forked from openenclave/openenclave
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathecall_ids.c
206 lines (173 loc) · 5.71 KB
/
ecall_ids.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
// Copyright (c) Open Enclave SDK contributors.
// Licensed under the MIT License.
#include "ecall_ids.h"
#include <openenclave/internal/raise.h>
#include <stdlib.h>
#include "hostthread.h"
// Initial size of ecall table mapping ecall names to global id.
// Most enclaves in OE SDK repo have fewer than 16 ecalls.
#define OE_ECALL_TABLE_INITIAL_SIZE 16
/* The maximum numer of different ecalls that an application can make is
* bounded. */
static const char** _ecall_table;
static uint32_t _ecall_table_capacity;
static uint32_t _ecall_table_size;
/* Mutex for assigning/looking up global ids in a thread-safe manner. */
static oe_mutex _lock = OE_H_MUTEX_INITIALIZER;
/* Cleanup memory during program terminaton */
static void _free_ecall_table(void)
{
oe_free((void*)_ecall_table);
}
/* Get the global ecall id from the _ecall_table. Locking must be done by
* caller. */
static oe_result_t _get_global_id(const char* name, uint64_t* global_id)
{
oe_result_t result = OE_NOT_FOUND;
if (!name || !global_id)
OE_RAISE(OE_INVALID_PARAMETER);
/* Search for id assigned for given name. */
for (uint64_t i = 0; i < _ecall_table_size; i++)
{
if (strcmp(_ecall_table[i], name) == 0)
{
*global_id = i;
break;
}
}
/* If the name is not found, adding it to the table. */
if (*global_id == OE_GLOBAL_ECALL_ID_NULL)
{
// Resize table if needed.
if (_ecall_table_size == _ecall_table_capacity)
{
if (!_ecall_table)
{
_ecall_table_capacity = OE_ECALL_TABLE_INITIAL_SIZE;
atexit(_free_ecall_table);
}
else
{
_ecall_table_capacity *= 2;
}
_ecall_table = oe_realloc(
(void*)_ecall_table, _ecall_table_capacity * sizeof(char*));
if (!_ecall_table)
OE_RAISE(OE_OUT_OF_MEMORY);
}
_ecall_table[_ecall_table_size] = name;
*global_id = _ecall_table_size;
_ecall_table_size++;
}
result = OE_OK;
done:
return result;
}
oe_result_t oe_get_global_id(const char* name, uint64_t* global_id)
{
oe_result_t result = OE_UNEXPECTED;
bool locked = false;
if (oe_mutex_lock(&_lock) != 0)
OE_RAISE(OE_FAILURE);
locked = true;
result = _get_global_id(name, global_id);
done:
if (locked)
oe_mutex_unlock(&_lock);
return result;
}
oe_result_t oe_get_ecall_ids(
oe_enclave_t* enclave,
const char* name,
uint64_t* global_id,
uint64_t* id)
{
oe_result_t result = OE_FAILURE;
oe_ecall_id_t* ecall_id_table = NULL;
uint64_t ecall_id_table_size = 0;
/* Validate parameters */
if (!enclave || !global_id || !name || !id)
{
result = OE_INVALID_PARAMETER;
goto done;
}
/* Initialize output parameter to NULL id */
*id = OE_ECALL_ID_NULL;
/* Fetch ecall_id_table using platform agnostic API */
OE_CHECK(
oe_get_ecall_id_table(enclave, &ecall_id_table, &ecall_id_table_size));
/* Lookup/assign global id */
if (*global_id == OE_GLOBAL_ECALL_ID_NULL)
{
/* The global_id variable is generated by edger8r, one global id
* variable per ecall. The same variable will be reused every time that
* ecall is made. Therefore, for an ecall, the following code will be
* executed only once.
*/
OE_CHECK(oe_get_global_id(name, global_id));
}
/* Look up function id based on global id. */
if (*global_id >= ecall_id_table_size)
OE_RAISE(OE_NOT_FOUND);
/* Look-up the ecall id from the per-enclave table.
* The ecall_id_table is expected to be set up during enclave creation
*/
*id = ecall_id_table[*global_id].id;
if (*id == OE_ECALL_ID_NULL)
OE_RAISE(OE_NOT_FOUND);
result = OE_OK;
done:
return result;
}
oe_result_t oe_register_ecalls(
oe_enclave_t* enclave,
const oe_ecall_info_t* ecall_info_table,
uint32_t num_ecalls)
{
oe_result_t result = OE_UNEXPECTED;
oe_ecall_id_t* ecall_id_table = NULL;
uint64_t max_global_id = 0;
uint64_t ecall_id_table_size = 0;
bool locked = false;
/* Validate parameters */
if (!enclave || !ecall_info_table || !num_ecalls)
OE_RAISE(OE_INVALID_PARAMETER);
if (oe_mutex_lock(&_lock) != 0)
OE_RAISE(OE_FAILURE);
locked = true;
/* Iterate through the ecalls and assign global ids.
* Also find out the maximum global id for the enclave. */
for (uint32_t i = 0; i < num_ecalls; i++)
{
uint64_t global_id = OE_GLOBAL_ECALL_ID_NULL;
const char* name = ecall_info_table[i].name;
/* Assign a proper global id based on the global __ecall_table. */
OE_CHECK(_get_global_id(name, &global_id));
if (global_id > max_global_id)
max_global_id = global_id;
}
/* Allocate ecall id table for the enclave */
ecall_id_table_size = max_global_id + 1;
ecall_id_table =
(oe_ecall_id_t*)oe_malloc(sizeof(uint64_t) * ecall_id_table_size);
if (!ecall_id_table)
OE_RAISE(OE_OUT_OF_MEMORY);
for (uint64_t i = 0; i < ecall_id_table_size; ++i)
ecall_id_table[i].id = OE_ECALL_ID_NULL;
/* Fill the ecall id table */
for (uint32_t i = 0; i < num_ecalls; i++)
{
uint64_t global_id = OE_GLOBAL_ECALL_ID_NULL;
const char* name = ecall_info_table[i].name;
uint64_t local_id = i;
OE_CHECK(_get_global_id(name, &global_id));
ecall_id_table[global_id].id = local_id;
}
OE_CHECK(
oe_set_ecall_id_table(enclave, ecall_id_table, ecall_id_table_size));
result = OE_OK;
done:
if (locked)
oe_mutex_unlock(&_lock);
return result;
}