forked from sslab-gatech/opensgx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsgx-user.c
375 lines (307 loc) · 10.8 KB
/
sgx-user.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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
/*
* Copyright (C) 2015, OpenSGX team, Georgia Tech & KAIST, All Rights Reserved
*
* This file is part of OpenSGX (https://github.com/sslab-gatech/opensgx).
*
* OpenSGX is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenSGX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenSGX. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <sgx-kern.h>
#include <sgx-user.h>
#include <sgx-utils.h>
#include <sgx-crypto.h>
#include <sgx-trampoline.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <sgx-malloc.h>
#include <stdarg.h>
#include <malloc.h>
static uint64_t _tcs_app;
// (ref. r2:5.2)
// out_regs store the output value returned from qemu */
void enclu(enclu_cmd_t leaf, uint64_t rbx, uint64_t rcx, uint64_t rdx,
out_regs_t *out_regs)
{
out_regs_t tmp;
asm volatile(".byte 0x0F\n\t"
".byte 0x01\n\t"
".byte 0xd7\n\t"
:"=a"(tmp.oeax),
"=b"(tmp.orbx),
"=c"(tmp.orcx),
"=d"(tmp.ordx)
:"a"((uint32_t)leaf),
"b"(rbx),
"c"(rcx),
"d"(rdx)
:"memory");
// Check whether function requires out_regs
if (out_regs != NULL) {
asm volatile ("" : : : "memory"); // Compile time Barrier
asm volatile ("movl %%eax, %0\n\t"
"movq %%rbx, %1\n\t"
"movq %%rcx, %2\n\t"
"movq %%rdx, %3\n\t"
:"=a"(out_regs->oeax),
"=b"(out_regs->orbx),
"=c"(out_regs->orcx),
"=d"(out_regs->ordx));
}
}
void sgx_enter(tcs_t *tcs, void (*aep)())
{
// RBX: TCS (In, EA)
// RCX: AEP (In, EA)
enclu(ENCLU_EENTER, (uint64_t)tcs, (uint64_t)aep, 0, NULL);
}
void sgx_resume(tcs_t *tcs, void (*aep)()) {
// RBX: TCS (In, EA)
// RCX: AEP (In, EA)
enclu(ENCLU_ERESUME, (uint64_t)tcs, (uint64_t)aep, 0, NULL);
}
void exception_handler(void)
{
sgx_msg(trace, "Asy_Call\n");
uint64_t aep = 0x00;
uint64_t rdx = 0x00;
asm("movl %0, %%eax\n\t"
"movq %1, %%rbx\n\t"
"movq %2, %%rcx\n\t"
"movq %3, %%rdx\n\t"
".byte 0x0F\n\t"
".byte 0x01\n\t"
".byte 0xd7\n\t"
:
:"a"((uint32_t)ENCLU_ERESUME),
"b"((uint64_t)_tcs_app),
"c"((uint64_t)aep),
"d"((uint64_t)rdx));
}
// (ref re:2.13, EINIT/p88)
// Set up sigstruct fields require to be signed.
static
sigstruct_t *alloc_sigstruct(void)
{
sigstruct_t *s = memalign(PAGE_SIZE, sizeof(sigstruct_t));
if (!s)
return NULL;
// Initializate with 0s
memset(s, 0, sizeof(sigstruct_t));
// HEADER(16 bytes)
uint8_t header[16] = SIG_HEADER1;
memcpy(s->header, swap_endian(header, 16), 16);
// VENDOR(4 bytes)
// Non-Intel Enclave;
s->vendor = 0x00000000;
// DATE(4 bytes)
s->date = 0x20150101;
// HEADER2(16 bytes)
uint8_t header2[16] = SIG_HEADER2;
memcpy(s->header2, swap_endian(header2, 16), 16);
// SWDEFINTO(4 bytes)
s->swdefined = 0x00000000;
// MISCSELECT(4 bytes)
//s->miscselect = 0x0;
// MISCMASK(4 bytes)
//s->miscmask = 0x0;
// ATTRIBUTES(16 bytes)
memset(&s->attributes, 0, sizeof(attributes_t));
s->attributes.mode64bit = true;
s->attributes.provisionkey = true;
s->attributes.einittokenkey = false;
s->attributes.xfrm = 0x03;
// ATTRIBUTEMAST(16 bytes)
memset(&s->attributeMask, 0 ,sizeof(attributes_t));
s->attributeMask.mode64bit = true;
s->attributeMask.provisionkey = true;
s->attributeMask.einittokenkey = false;
s->attributeMask.xfrm = 0x03;
// ISVPRODID(2 bytes)
s->isvProdID = 0x0001;
// ISVSVN(2 bytes)
s->isvSvn = 0x0001;
return s;
}
// Set up einittoken fields require to be signed.
static
einittoken_t *alloc_einittoken(rsa_key_t pubkey, sigstruct_t *sigstruct)
{
einittoken_t *t = memalign(EINITTOKEN_ALIGN_SIZE, sizeof(einittoken_t));
if (!t)
return NULL;
// Initializate with 0s
memset(t, 0, sizeof(einittoken_t));
// VALID(4 bytes)
t->valid = 0x00000001;
// ATTRIBUTES(16 bytes)
memset(&t->attributes, 0, sizeof(attributes_t));
t->attributes.mode64bit = true;
t->attributes.provisionkey = true;
t->attributes.einittokenkey = false;
t->attributes.xfrm = 0x03;
// MRENCLAVE(32 bytes)
memcpy(&t->mrEnclave, &sigstruct->enclaveHash, sizeof(t->mrEnclave));
// MRSIGNER(32 bytes)
sha256(pubkey, KEY_LENGTH, (unsigned char *)&t->mrSigner, 0);
return t;
}
// (ref re:2.13)
// Fill the fields not required for signature after signing.
static
void update_sigstruct(sigstruct_t *sigstruct, rsa_key_t pubkey, rsa_sig_t sig)
{
// MODULUS (384 bytes)
memcpy(sigstruct->modulus, pubkey, sizeof(rsa_key_t));
// EXPONENT (4 bytes)
sigstruct->exponent = SGX_RSA_EXPONENT;
// SIGNATURE (384 bytes)
memcpy(sigstruct->signature, sig, sizeof(rsa_sig_t));
// TODO: sig->q1 = floor(signature^2 / modulus)
// sig->q2 = floor((signature^3 / modulus) / modulus)
}
static
void update_einittoken(einittoken_t *token)
{
/*
memcpy(token.cpuSvnLE, keyreq.cpusvn, sizeof(token.cpuSvnLE));
memcpy(&token.isvsvnLE, &keyreq.isvsvn, sizeof(token.isvsvnLE));
memcpy(token.keyid, keyreq.keyid, sizeof(token.keyid));
memcpy(&token.isvprodIDLE, &sig.isvProdID, sizeof(token.isvprodIDLE));
*/
// TODO: Mask einittoken attribute field with keyreq.attributeMask for maskedattributele
// TODO : Set KEYID field
}
static
void print_eid_stat(keid_t stat) {
printf("--------------------------------------------\n");
printf("kern in count\t: %d\n",stat.kin_n);
printf("kern out count\t: %d\n",stat.kout_n);
printf("--------------------------------------------\n");
printf("encls count\t: %d\n",stat.qstat.encls_n);
printf("ecreate count\t: %d\n",stat.qstat.ecreate_n);
printf("eadd count\t: %d\n",stat.qstat.eadd_n);
printf("eextend count\t: %d\n",stat.qstat.eextend_n);
printf("einit count\t: %d\n",stat.qstat.einit_n);
printf("eaug count\t: %d\n",stat.qstat.eaug_n);
printf("--------------------------------------------\n");
printf("enclu count\t: %d\n",stat.qstat.enclu_n);
printf("eenter count\t: %d\n",stat.qstat.eenter_n);
printf("eresume count\t: %d\n",stat.qstat.eresume_n);
printf("eexit count\t: %d\n",stat.qstat.eexit_n);
printf("egetkey count\t: %d\n",stat.qstat.egetkey_n);
printf("ereport count\t: %d\n",stat.qstat.ereport_n);
printf("eaccept count\t: %d\n",stat.qstat.eaccept_n);
printf("--------------------------------------------\n");
printf("mode switch count : %d\n",stat.qstat.mode_switch);
printf("tlb flush count\t: %d\n",stat.qstat.tlbflush_n);
printf("--------------------------------------------\n");
printf("TCS address\t: %lx\n", stat.tcs);
printf("Pre-allocated EPC SSA region\t: 0x%lx\n",stat.prealloc_ssa);
printf("Pre-allocated EPC Heap region\t: 0x%lx\n",stat.prealloc_heap);
printf("Later-Augmented EPC Heap region\t: 0x%lx\n",stat.augged_heap);
long total_epc_heap = stat.prealloc_heap + stat.augged_heap;
printf("Total EPC Heap region\t: 0x%lx\n",total_epc_heap);
}
tcs_t *init_enclave(void *base, unsigned int offset, unsigned int n_of_pages, char *conf)
{
assert(sizeof(tcs_t) == PAGE_SIZE);
sigstruct_t *sigstruct;
einittoken_t *token;
// allocate TCS
tcs_t *tcs = (tcs_t *)memalign(PAGE_SIZE, sizeof(tcs_t));
if (!tcs)
err(1, "failed to allocate tcs");
memset(tcs, 0, sizeof(tcs_t));
// XXX. tcs structure is freed at the end! maintain as part of
// keid structure
_tcs_app = (uint64_t)tcs;
// Calculate the offset for setting oentry of tcs
set_tcs_fields(tcs, offset);
// XXX. exception handler is app specific? then pass it through
// argument.
void (*aep)() = exception_handler;
if (conf != NULL) {
// load sigstruct from file
sigstruct = load_sigstruct(conf);
// load einittoken from file
token = load_einittoken(conf);
} else {
// Configuration file is not provided, generate a fake
// configuration for testing purpose.
// generate RSA key pair
rsa_key_t pubkey;
rsa_key_t seckey;
// load rsa key from conf
rsa_context *ctx = load_rsa_keys("conf/test.key", pubkey, seckey,
KEY_LENGTH_BITS);
{
char *pubkey_str = fmt_bytes(pubkey, sizeof(pubkey));
char *seckey_str = fmt_bytes(seckey, sizeof(pubkey));
sgx_dbg(info, "pubkey: %.40s..", pubkey_str);
sgx_dbg(info, "seckey: %.40s..", seckey_str);
free(pubkey_str);
free(seckey_str);
}
// set sigstruct which will be used for signing
sigstruct = alloc_sigstruct();
if (!sigstruct)
err(1, "failed to allocate sigstruct");
// for testing, all zero = bypass
memset(sigstruct->enclaveHash, 0, sizeof(sigstruct->enclaveHash));
// signing with private key
rsa_sig_t sig;
rsa_sign(ctx, sig, (unsigned char *)sigstruct, sizeof(sigstruct_t));
// set sigstruct after signing
update_sigstruct(sigstruct, pubkey, sig);
// set einittoken which will be used for MAC
token = alloc_einittoken(pubkey, sigstruct);
if (!token)
err(1, "failed to allocate einittoken");
}
int keid = sys_create_enclave(base, n_of_pages, tcs, sigstruct, token, false);
if (keid < 0)
err(1, "failed to create enclave");
keid_t stat;
if (sys_stat_enclave(keid, &stat) < 0)
err(1, "failed to stat enclave");
// stats report
print_eid_stat(stat);
// please check STUB_ADDR is mmaped in the main before enable below
sgx_stub_info *stub = (sgx_stub_info *)STUB_ADDR;
stub->tcs = stat.tcs;
free(tcs);
return stat.tcs;
}
int sgx_host_read(void *buf, int len)
{
sgx_stub_info *stub = (sgx_stub_info *)STUB_ADDR;
if (len <= 0) {
return -1;
}
memcpy(buf, stub->out_shm, len);
memset(stub->out_shm, 0, SGXLIB_MAX_ARG);
return len;
}
int sgx_host_write(void *buf, int len)
{
sgx_stub_info *stub = (sgx_stub_info *)STUB_ADDR;
if (len <= 0) {
return -1;
}
memset(stub->in_shm, 0, SGXLIB_MAX_ARG);
memcpy(stub->in_shm, buf, len);
return len;
}