enclave_entry.S 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. #include "sgx_arch.h"
  2. #include "sgx_tls.h"
  3. .extern ecall_table
  4. .extern enclave_ecall_pal_main
  5. .global enclave_entry
  6. .type enclave_entry, @function
  7. enclave_entry:
  8. # On EENTER/ERESUME, RAX is the current SSA, RBX is the address of TCS,
  9. # RCX is the address of AEP. Other registers are not trusted.
  10. # current SSA is in RAX (Trusted)
  11. cmp $0, %rax
  12. jne .Lhandle_resume
  13. # TCS is in RBX (Trusted)
  14. # AEP address in RCX (Trusted)
  15. mov %rcx, %gs:SGX_AEP
  16. # The following code is hardened to defend attacks from untrusted host.
  17. # Any states given by the host instead of the ISA must be assumed
  18. # potentially malicious.
  19. #
  20. # For instance, Jo Van Bulck contributed a detailed vulnerability report
  21. # in https://github.com/oscarlab/graphene/issues/28. (Fixed)
  22. # Brief description of the vulnerabilities:
  23. # The previous implementation does not check the index of entry
  24. # functions (RDI at enclave entry) given by the untrusted PAL.
  25. # An attacker can cause overflow/underflow to jump to random
  26. # locaion in enclaves. Moreover, we used a specific index
  27. # (RETURN_FROM_OCALL) to tell if the control flow is returned
  28. # from a OCALL in the untrusted PAL. Attackers can manipulate RDI
  29. # to deceive the trusted PAL.
  30. # A safe design: check if %gs:SGX_EXIT_TARGET is ever assigned
  31. mov %gs:SGX_EXIT_TARGET, %rcx
  32. cmp $0, %rcx
  33. jne .Lreturn_from_ocall
  34. # PAL convention:
  35. # RDI - index in ecall_table
  36. # RSI - prointer to ecall arguments
  37. # RDX - exit target
  38. # RCX (former RSP) - The unstrusted stack
  39. # R8 - enclave base
  40. # calculate enclave base = RBX (trusted) - %gs:SGX_TCS_OFFSET
  41. sub %gs:SGX_TCS_OFFSET, %rbx
  42. mov %rbx, %r8
  43. # push untructed stack address to RCX
  44. mov %rsp, %rcx
  45. # switch to enclve stack: enclave base + %gs:SGX_INITIAL_STACK_OFFSET
  46. add %gs:SGX_INITIAL_STACK_OFFSET, %rbx
  47. mov %rbx, %rsp
  48. # clear the rest of register states
  49. xor %rax, %rax
  50. xor %rbx, %rbx
  51. xor %r9, %r9
  52. xor %r10, %r10
  53. xor %r11, %r11
  54. xor %r12, %r12
  55. xor %r13, %r13
  56. xor %r14, %r14
  57. xor %r15, %r15
  58. # register states need to be carefully checked, so we move the handling
  59. # to handle_ecall() in enclave_ecalls.c
  60. call handle_ecall
  61. # never return to this point (should die)
  62. xor %rdi, %rdi
  63. xor %rsi, %rsi
  64. jmp .Leexit
  65. .Lhandle_resume:
  66. # PAL convention:
  67. # RDI - external event
  68. # get some information from GPR
  69. mov %gs:SGX_GPR, %rbx
  70. mov %rdi, %rsi
  71. xor %rdi, %rdi
  72. mov SGX_GPR_EXITINFO(%rbx), %edi
  73. test $0x80000000, %edi
  74. jnz .Lhandle_exception
  75. mov %esi, %edi
  76. # use external event - only the first 8 bits count
  77. and $0xff, %edi
  78. cmp $0, %edi
  79. jne .Lhandle_exception
  80. #if SGX_HAS_FSGSBASE == 0
  81. mov %gs:SGX_FSBASE, %rdi
  82. cmp $0, %rdi
  83. je .Ljust_resume
  84. mov SGX_GPR_RSP(%rbx), %rsi
  85. sub $16, %rsi
  86. mov %rsi, SGX_GPR_RSP(%rbx)
  87. # try to push rip and fsbase onto the stack
  88. mov %rdi, (%rsi)
  89. mov SGX_GPR_RIP(%rbx), %rdi
  90. mov %rdi, 8(%rsi)
  91. # new RIP is the resume point
  92. lea .Lafter_resume(%rip), %rdi
  93. mov %rdi, SGX_GPR_RIP(%rbx)
  94. .Ljust_resume:
  95. #endif
  96. # clear the registers
  97. xor %rdi, %rdi
  98. xor %rsi, %rsi
  99. # exit address in RDX, mov it to RBX
  100. mov %rdx, %rbx
  101. mov $EEXIT, %rax
  102. ENCLU
  103. #if SGX_HAS_FSGSBASE == 0
  104. .Lafter_resume:
  105. mov %rbx, -8(%rsp)
  106. pop %rbx
  107. .byte 0xf3, 0x48, 0x0f, 0xae, 0xd3 /* WRFSBASE %RBX */
  108. mov -16(%rsp), %rbx
  109. ret
  110. #endif
  111. .Lhandle_exception:
  112. mov SGX_GPR_RSP(%rbx), %rsi
  113. sub $0x90, %rsi
  114. # we have exitinfo in RDI, swap with the one on GPR
  115. # and dump into the context
  116. xchg %rdi, SGX_GPR_RDI(%rbx)
  117. mov %rdi, 0x38(%rsi)
  118. # dump the rest of context
  119. mov SGX_GPR_RAX(%rbx), %rdi
  120. mov %rdi, 0x00(%rsi)
  121. mov SGX_GPR_RCX(%rbx), %rdi
  122. mov %rdi, 0x08(%rsi)
  123. mov SGX_GPR_RDX(%rbx), %rdi
  124. mov %rdi, 0x10(%rsi)
  125. mov SGX_GPR_RBX(%rbx), %rdi
  126. mov %rdi, 0x18(%rsi)
  127. mov SGX_GPR_RSP(%rbx), %rdi
  128. mov %rdi, 0x20(%rsi)
  129. mov SGX_GPR_RBP(%rbx), %rdi
  130. mov %rdi, 0x28(%rsi)
  131. mov SGX_GPR_RSI(%rbx), %rdi
  132. mov %rdi, 0x30(%rsi)
  133. mov SGX_GPR_R8(%rbx), %rdi
  134. mov %rdi, 0x40(%rsi)
  135. mov SGX_GPR_R9(%rbx), %rdi
  136. mov %rdi, 0x48(%rsi)
  137. mov SGX_GPR_R10(%rbx), %rdi
  138. mov %rdi, 0x50(%rsi)
  139. mov SGX_GPR_R11(%rbx), %rdi
  140. mov %rdi, 0x58(%rsi)
  141. mov SGX_GPR_R12(%rbx), %rdi
  142. mov %rdi, 0x60(%rsi)
  143. mov SGX_GPR_R13(%rbx), %rdi
  144. mov %rdi, 0x68(%rsi)
  145. mov SGX_GPR_R14(%rbx), %rdi
  146. mov %rdi, 0x70(%rsi)
  147. mov SGX_GPR_R15(%rbx), %rdi
  148. mov %rdi, 0x78(%rsi)
  149. mov SGX_GPR_RFLAGS(%rbx), %rdi
  150. mov %rdi, 0x80(%rsi)
  151. mov SGX_GPR_RIP(%rbx), %rdi
  152. mov %rdi, 0x88(%rsi)
  153. mov %rsi, SGX_GPR_RSP(%rbx)
  154. mov %rsi, SGX_GPR_RSI(%rbx)
  155. # new RIP is the exception handler
  156. lea _DkExceptionHandler(%rip), %rdi
  157. mov %rdi, SGX_GPR_RIP(%rbx)
  158. # clear the registers
  159. xor %rdi, %rdi
  160. xor %rsi, %rsi
  161. # exit address in RDX, mov it to RBX
  162. mov %rdx, %rbx
  163. mov $EEXIT, %rax
  164. ENCLU
  165. .global sgx_ocall
  166. .type sgx_ocall, @function
  167. sgx_ocall:
  168. push %rbp
  169. mov %rsp, %rbp
  170. mov 8(%rbp), %rax
  171. push %rax # previous RIP
  172. pushfq
  173. push %r15
  174. push %r14
  175. push %r13
  176. push %r12
  177. push %r11
  178. push %r10
  179. push %r9
  180. push %r8
  181. push %rdi
  182. push %rsi
  183. mov (%rbp), %rax
  184. push %rax # previous RBP
  185. lea 16(%rbp), %rax
  186. push %rax # previous RSP
  187. push %rbx
  188. push %rdx
  189. push %rcx
  190. # no RAX
  191. mov %rsp, %rbp
  192. sub $XSAVE_SIZE, %rsp
  193. and $XSAVE_ALIGN, %rsp
  194. fxsave (%rsp)
  195. push %rbp
  196. mov %rsp, %gs:SGX_STACK
  197. jmp .Leexit
  198. .Lexception_handler:
  199. .Leexit:
  200. xor %rdx, %rdx
  201. xor %r8, %r8
  202. xor %r9, %r9
  203. xor %r10, %r10
  204. xor %r11, %r11
  205. xor %r12, %r12
  206. xor %r13, %r13
  207. xor %r14, %r14
  208. xor %r15, %r15
  209. xor %rbp, %rbp
  210. mov %gs:SGX_USTACK, %rsp
  211. and $STACK_ALIGN, %rsp
  212. mov %gs:SGX_EXIT_TARGET, %rbx
  213. mov %gs:SGX_AEP, %rcx
  214. mov $EEXIT, %rax
  215. ENCLU
  216. .Lreturn_from_ocall:
  217. # PAL convention:
  218. # RDI - return value
  219. # RSI - external event (if there is any)
  220. mov %rdi, %rax
  221. # restore FSBASE if necessary
  222. mov %gs:SGX_FSBASE, %rbx
  223. cmp $0, %rbx
  224. je .Lno_fsbase
  225. .byte 0xf3, 0x48, 0x0f, 0xae, 0xd3 /* WRFSBASE %RBX */
  226. .Lno_fsbase:
  227. # restore the stack
  228. mov %gs:SGX_STACK, %rsp
  229. pop %rbp
  230. fxrstor (%rsp)
  231. mov %rbp, %rsp
  232. cmp $0, %rsi
  233. je .Lno_external_event
  234. push %rax
  235. mov %rsi, %rdi
  236. mov %rsp, %rsi
  237. call _DkHandleExternelEvent
  238. pop %rax
  239. .Lno_external_event:
  240. pop %rcx
  241. pop %rdx
  242. pop %rbx
  243. add $16, %rsp # skip RSP and RBP
  244. pop %rsi
  245. pop %rdi
  246. pop %r8
  247. pop %r9
  248. pop %r10
  249. pop %r11
  250. pop %r12
  251. pop %r13
  252. pop %r14
  253. pop %r15
  254. popfq
  255. add $8, %rsp # skip RIP
  256. pop %rbp
  257. ret
  258. /*
  259. * sgx_report:
  260. * Generate SGX hardware signed report.
  261. */
  262. .global sgx_report
  263. .type sgx_report, @function
  264. sgx_report:
  265. .cfi_startproc
  266. push %rbx
  267. push %rcx
  268. mov %rdi, %rbx
  269. mov %rsi, %rcx
  270. mov $EREPORT, %rax
  271. ENCLU
  272. pop %rcx
  273. pop %rbx
  274. ret
  275. .cfi_endproc
  276. .size sgx_report, .-sgx_report
  277. /*
  278. * sgx_getkey:
  279. * Retreive SGX hardware enclave cryptography key.
  280. */
  281. .global sgx_getkey
  282. .type sgx_getkey, @function
  283. sgx_getkey:
  284. .cfi_startproc
  285. push %rbx
  286. push %rcx
  287. mov %rdi, %rbx
  288. mov %rsi, %rcx
  289. mov $EGETKEY, %rax
  290. ENCLU
  291. pop %rcx
  292. pop %rbx
  293. ret
  294. .cfi_endproc
  295. .size sgx_getkey, .-sgx_getkey
  296. /*
  297. * rdrand:
  298. * Get hardware generated random value.
  299. */
  300. .global rdrand
  301. .type rdrand, @function
  302. rdrand:
  303. .cfi_startproc
  304. .Lretry_rdrand:
  305. .byte 0x0f, 0xc7, 0xf0 /* RDRAND %EAX */
  306. jnc .Lretry_rdrand
  307. ret
  308. .cfi_endproc
  309. .size rdrand, .-rdrand
  310. /*
  311. * rdfsbase:
  312. * read FS register (allowed in enclaves).
  313. */
  314. .global rdfsbase
  315. .type rdfsbase, @function
  316. rdfsbase:
  317. .cfi_startproc
  318. .byte 0xf3, 0x48, 0x0f, 0xae, 0xc0 /* RDFSBASE %RAX */
  319. ret
  320. .cfi_endproc
  321. .size rdfsbase, .-rdfsbase
  322. /*
  323. * wrfsbase:
  324. * modify FS register (allowed in enclaves).
  325. */
  326. .global wrfsbase
  327. .type wrfsbase, @function
  328. wrfsbase:
  329. .cfi_startproc
  330. .byte 0xf3, 0x48, 0x0f, 0xae, 0xd7 /* WRFSBASE %RDI */
  331. ret
  332. .cfi_endproc
  333. .size wrfsbase, .-wrfsbase