forked from gramineproject/graphene
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathenclave_entry.S
More file actions
497 lines (407 loc) · 9.03 KB
/
enclave_entry.S
File metadata and controls
497 lines (407 loc) · 9.03 KB
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
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
#include "sgx_arch.h"
#include "sgx_tls.h"
.extern ecall_table
.extern enclave_ecall_pal_main
.global enclave_entry
.type enclave_entry, @function
enclave_entry:
# On EENTER/ERESUME, RAX is the current SSA, RBX is the address of TCS,
# RCX is the address of AEP. Other registers are not trusted.
# current SSA is in RAX (Trusted)
cmp $0, %rax
je .Lnormal_enter
# Exception for growing stacks
cmp $2, %rdi
je .Lnormal_enter
# Not OCALL made in Exception context
cmp $1, %gs:SGX_OCALL_PENDING
jne .Lhandle_resume
# TCS is in RBX (Trusted)
.Lnormal_enter:
# AEP address in RCX (Trusted)
mov %rcx, %gs:SGX_AEP
# The following code is hardened to defend attacks from untrusted host.
# Any states given by the host instead of the ISA must be assumed
# potentially malicious.
#
# For instance, Jo Van Bulck contributed a detailed vulnerability report
# in https://github.com/oscarlab/graphene/issues/28. (Fixed)
# Brief description of the vulnerabilities:
# The previous implementation does not check the index of entry
# functions (RDI at enclave entry) given by the untrusted PAL.
# An attacker can cause overflow/underflow to jump to random
# locaion in enclaves. Moreover, we used a specific index
# (RETURN_FROM_OCALL) to tell if the control flow is returned
# from a OCALL in the untrusted PAL. Attackers can manipulate RDI
# to deceive the trusted PAL.
cmp $0, %gs:SGX_OCALL_PENDING
jne .Lreturn_from_ocall
# PAL convention:
# RDI - index in ecall_table
# RSI - prointer to ecall arguments
# RDX - exit target
# RCX (former RSP) - The unstrusted stack
# R8 - enclave base
# calculate enclave base = RBX (trusted) - %gs:SGX_TCS_OFFSET
sub %gs:SGX_TCS_OFFSET, %rbx
mov %rbx, %r8
# push untructed stack address to RCX
mov %rsp, %rcx
# handle stack grow, using auxiliary stack
cmp $2, %rdi
je .Lhandle_aux_stack
# setup thread context, using auxiliary stack
cmp $3, %rdi
je .Lhandle_aux_stack
cmp $4, %rdi
je .Lhandle_aux_stack
# switch to enclve stack: enclave base + %gs:SGX_INITIAL_STACK_OFFSET
add %gs:SGX_INITIAL_STACK_OFFSET, %rbx
mov %rbx, %rsp
.Ldo_handle_ecall:
# clear the rest of register states
xor %rax, %rax
xor %rbx, %rbx
xor %r9, %r9
xor %r10, %r10
xor %r11, %r11
xor %r12, %r12
xor %r13, %r13
xor %r14, %r14
xor %r15, %r15
# register states need to be carefully checked, so we move the handling
# to handle_ecall() in enclave_ecalls.c
call handle_ecall
# ecall_enclave_start/ecall_thread_start never return to this point
# other ecalls return here
xor %rdi, %rdi
xor %rsi, %rsi
jmp .Leexit
.Lhandle_aux_stack:
add %gs:SGX_AUX_STACK_OFFSET, %rbx
mov %rbx, %rsp
# In exception handler, ecall returns to the next
# RCX contains the return address, however occupied
# Using SGX_AEP instead
mov %gs:SGX_AEP, %r9
mov %r9, %gs:SGX_ECALL_RET_TARGET
jmp .Ldo_handle_ecall
.Lhandle_resume:
# PAL convention:
# RDI - external event
# get some information from GPR
mov %gs:SGX_GPR, %rbx
mov %rdi, %rsi
xor %rdi, %rdi
mov SGX_GPR_EXITINFO(%rbx), %edi
test $0x80000000, %edi
jnz .Lhandle_exception
mov %esi, %edi
# use external event - only the first 8 bits count
and $0xff, %edi
cmp $0, %edi
jne .Lhandle_exception
#if SGX_HAS_FSGSBASE == 0
mov %gs:SGX_FSBASE, %rdi
cmp $0, %rdi
je .Ljust_resume
mov SGX_GPR_RSP(%rbx), %rsi
sub $16, %rsi
mov %rsi, SGX_GPR_RSP(%rbx)
# try to push rip and fsbase onto the stack
mov %rdi, (%rsi)
mov SGX_GPR_RIP(%rbx), %rdi
mov %rdi, 8(%rsi)
# new RIP is the resume point
lea .Lafter_resume(%rip), %rdi
mov %rdi, SGX_GPR_RIP(%rbx)
.Ljust_resume:
#endif
# clear the registers
xor %rdi, %rdi
xor %rsi, %rsi
# exit address in RDX, mov it to RBX
mov %rdx, %rbx
mov $EEXIT, %rax
ENCLU
#if SGX_HAS_FSGSBASE == 0
.Lafter_resume:
mov %rbx, -8(%rsp)
pop %rbx
.byte 0xf3, 0x48, 0x0f, 0xae, 0xd3 /* WRFSBASE %RBX */
mov -16(%rsp), %rbx
ret
#endif
.Lhandle_exception:
mov SGX_GPR_RSP(%rbx), %rsi
sub $0x90, %rsi
# we have exitinfo in RDI, swap with the one on GPR
# and dump into the context
xchg %rdi, SGX_GPR_RDI(%rbx)
mov %rdi, 0x38(%rsi)
# dump the rest of context
mov SGX_GPR_RAX(%rbx), %rdi
mov %rdi, 0x00(%rsi)
mov SGX_GPR_RCX(%rbx), %rdi
mov %rdi, 0x08(%rsi)
mov SGX_GPR_RDX(%rbx), %rdi
mov %rdi, 0x10(%rsi)
mov SGX_GPR_RBX(%rbx), %rdi
mov %rdi, 0x18(%rsi)
mov SGX_GPR_RSP(%rbx), %rdi
mov %rdi, 0x20(%rsi)
mov SGX_GPR_RBP(%rbx), %rdi
mov %rdi, 0x28(%rsi)
mov SGX_GPR_RSI(%rbx), %rdi
mov %rdi, 0x30(%rsi)
mov SGX_GPR_R8(%rbx), %rdi
mov %rdi, 0x40(%rsi)
mov SGX_GPR_R9(%rbx), %rdi
mov %rdi, 0x48(%rsi)
mov SGX_GPR_R10(%rbx), %rdi
mov %rdi, 0x50(%rsi)
mov SGX_GPR_R11(%rbx), %rdi
mov %rdi, 0x58(%rsi)
mov SGX_GPR_R12(%rbx), %rdi
mov %rdi, 0x60(%rsi)
mov SGX_GPR_R13(%rbx), %rdi
mov %rdi, 0x68(%rsi)
mov SGX_GPR_R14(%rbx), %rdi
mov %rdi, 0x70(%rsi)
mov SGX_GPR_R15(%rbx), %rdi
mov %rdi, 0x78(%rsi)
mov SGX_GPR_RFLAGS(%rbx), %rdi
mov %rdi, 0x80(%rsi)
mov SGX_GPR_RIP(%rbx), %rdi
mov %rdi, 0x88(%rsi)
mov %rsi, SGX_GPR_RSP(%rbx)
mov %rsi, SGX_GPR_RSI(%rbx)
# new RIP is the exception handler
lea _DkExceptionHandler(%rip), %rdi
mov %rdi, SGX_GPR_RIP(%rbx)
# clear the registers
xor %rdi, %rdi
xor %rsi, %rsi
# exit address in RDX, mov it to RBX
mov %rdx, %rbx
mov $EEXIT, %rax
ENCLU
.global sgx_ocall
.type sgx_ocall, @function
sgx_ocall:
push %rbp
mov %rsp, %rbp
mov 8(%rbp), %rax
push %rax # previous RIP
pushfq
push %r15
push %r14
push %r13
push %r12
push %r11
push %r10
push %r9
push %r8
push %rdi
push %rsi
mov (%rbp), %rax
push %rax # previous RBP
lea 16(%rbp), %rax
push %rax # previous RSP
push %rbx
push %rdx
push %rcx
# no RAX
mov %rsp, %rbp
sub $XSAVE_SIZE, %rsp
and $XSAVE_ALIGN, %rsp
fxsave (%rsp)
push %rbp
mov %rsp, %gs:SGX_STACK
# ocall sets ocall_pending before exit
movq $1, %gs:SGX_OCALL_PENDING
jmp .Leexit
.Lexception_handler:
.Leexit:
xor %rdx, %rdx
xor %r8, %r8
xor %r9, %r9
xor %r10, %r10
xor %r11, %r11
xor %r12, %r12
xor %r13, %r13
xor %r14, %r14
xor %r15, %r15
xor %rbp, %rbp
mov %gs:SGX_USTACK, %rsp
# If it's an ecall return using
# ecall_ret_target as exit target
cmp $1, %gs:SGX_OCALL_PENDING
jne .Lecall_return_setup
mov %gs:SGX_EXIT_TARGET, %rbx
mov %gs:SGX_AEP, %rcx
.Lexecute_exit:
mov $EEXIT, %rax
ENCLU
.Lecall_return_setup:
mov %gs:SGX_ECALL_RET_TARGET, %rbx
mov %gs:SGX_AEP, %rcx
jmp .Lexecute_exit
.Lreturn_from_ocall:
# PAL convention:
# RDI - return value
# RSI - external event (if there is any)
mov %rdi, %rax
# clear ocall_pending
movq $0, %gs:SGX_OCALL_PENDING
# restore FSBASE if necessary
mov %gs:SGX_FSBASE, %rbx
cmp $0, %rbx
je .Lno_fsbase
.byte 0xf3, 0x48, 0x0f, 0xae, 0xd3 /* WRFSBASE %RBX */
.Lno_fsbase:
# restore the stack
mov %gs:SGX_STACK, %rsp
pop %rbp
fxrstor (%rsp)
mov %rbp, %rsp
cmp $0, %rsi
je .Lno_external_event
push %rax
mov %rsi, %rdi
mov %rsp, %rsi
call _DkHandleExternelEvent
pop %rax
.Lno_external_event:
pop %rcx
pop %rdx
pop %rbx
add $16, %rsp # skip RSP and RBP
pop %rsi
pop %rdi
pop %r8
pop %r9
pop %r10
pop %r11
pop %r12
pop %r13
pop %r14
pop %r15
popfq
add $8, %rsp # skip RIP
pop %rbp
ret
/*
* sgx_report:
* Generate SGX hardware signed report.
*/
.global sgx_report
.type sgx_report, @function
sgx_report:
.cfi_startproc
push %rbx
push %rcx
mov %rdi, %rbx
mov %rsi, %rcx
mov $EREPORT, %rax
ENCLU
pop %rcx
pop %rbx
ret
.cfi_endproc
.size sgx_report, .-sgx_report
/*
* sgx_getkey:
* Retreive SGX hardware enclave cryptography key.
*/
.global sgx_getkey
.type sgx_getkey, @function
sgx_getkey:
.cfi_startproc
push %rbx
push %rcx
mov %rdi, %rbx
mov %rsi, %rcx
mov $EGETKEY, %rax
ENCLU
pop %rcx
pop %rbx
ret
.cfi_endproc
.size sgx_getkey, .-sgx_getkey
/*
* sgx_accept:
* EACCEPT pages for dynamic memory management
*/
.global sgx_accept
.type sgx_accept, @function
sgx_accept:
.cfi_startproc
push %rbx
push %rcx
mov %rdi, %rbx
mov %rsi, %rcx
mov $EACCEPT, %rax
ENCLU
pop %rcx
pop %rbx
ret
.cfi_endproc
.size sgx_accept, .-sgx_accept
/*
* sgx_modpe:
* EMODPE pages for dynamic memory management
*/
.global sgx_modpe
.type sgx_modpe, @function
sgx_modpe:
.cfi_startproc
push %rbx
push %rcx
mov %rdi, %rbx
mov %rsi, %rcx
mov $EMODPE, %rax
ENCLU
pop %rcx
pop %rbx
ret
.cfi_endproc
.size sgx_modpe, .-sgx_modpe
/*
* rdrand:
* Get hardware generated random value.
*/
.global rdrand
.type rdrand, @function
rdrand:
.cfi_startproc
.Lretry_rdrand:
.byte 0x0f, 0xc7, 0xf0 /* RDRAND %EAX */
jnc .Lretry_rdrand
ret
.cfi_endproc
.size rdrand, .-rdrand
/*
* rdfsbase:
* read FS register (allowed in enclaves).
*/
.global rdfsbase
.type rdfsbase, @function
rdfsbase:
.cfi_startproc
.byte 0xf3, 0x48, 0x0f, 0xae, 0xc0 /* RDFSBASE %RAX */
ret
.cfi_endproc
.size rdfsbase, .-rdfsbase
/*
* wrfsbase:
* modify FS register (allowed in enclaves).
*/
.global wrfsbase
.type wrfsbase, @function
wrfsbase:
.cfi_startproc
.byte 0xf3, 0x48, 0x0f, 0xae, 0xd7 /* WRFSBASE %RDI */
ret
.cfi_endproc
.size wrfsbase, .-wrfsbase