u_instructions.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * Copyright (C) 2011-2017 Intel Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Intel Corporation nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. // u_instructions.cpp -- It simulates Enclave instructions.
  32. #include <string.h>
  33. #include <assert.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include "arch.h"
  37. #include "util.h"
  38. #include "se_memory.h"
  39. #include "se_memcpy.h"
  40. #include "se_trace.h"
  41. #include "enclave.h"
  42. #include "td_mngr.h"
  43. #include "lowlib.h"
  44. #include "sgxsim.h"
  45. #include "enclave_mngr.h"
  46. #include "u_instructions.h"
  47. #include "crypto_wrapper.h"
  48. static uintptr_t _EINIT(secs_t* secs, enclave_css_t* css, token_t* launch);
  49. static uintptr_t _ECREATE (page_info_t* pi);
  50. static uintptr_t _EADD (page_info_t* pi, void* epc_lin_addr);
  51. static uintptr_t _EREMOVE(const void* epc_lin_addr);
  52. ////////////////////////////////////////////////////////////////////////
  53. #define __GP__() exit(EXIT_FAILURE)
  54. #define GP() do { \
  55. SE_TRACE(SE_TRACE_DEBUG, "#GP on %s, line: %d\n", __FILE__, __LINE__); \
  56. __GP__(); \
  57. } while (0)
  58. #define GP_ON(cond) if (cond) GP()
  59. #define GP_ON_EENTER GP_ON
  60. #define mcp_same_size(dst_ptr, src_ptr, size) memcpy_s(dst_ptr, size, src_ptr, size)
  61. uintptr_t _EINIT(secs_t* secs, enclave_css_t *css, token_t *launch)
  62. {
  63. CEnclaveMngr *mngr = CEnclaveMngr::get_instance();
  64. assert(mngr != NULL);
  65. CEnclaveSim* ce = mngr->get_enclave(secs);
  66. GP_ON(ce == NULL);
  67. GP_ON((ce->get_secs()->attributes.flags & SGX_FLAGS_INITTED) != 0);
  68. // Fill MREnclave, MRSigner, ISVPRODID, ISVSVN
  69. secs_t* this_secs = ce->get_secs();
  70. if (css != NULL) {
  71. // Check signature
  72. if ((css->body.attribute_mask.xfrm & this_secs->attributes.xfrm)
  73. != (css->body.attribute_mask.xfrm & css->body.attributes.xfrm))
  74. {
  75. SE_TRACE(SE_TRACE_DEBUG,
  76. "SECS attributes.xfrm does NOT match signature attributes.xfrm\n");
  77. return SGX_ERROR_INVALID_ATTRIBUTE;
  78. }
  79. if ((css->body.attribute_mask.flags & this_secs->attributes.flags)
  80. != (css->body.attribute_mask.flags & css->body.attributes.flags))
  81. {
  82. SE_TRACE(SE_TRACE_DEBUG,
  83. "SECS attributes.flag does NOT match signature attributes.flag\n");
  84. return SGX_ERROR_INVALID_ATTRIBUTE;
  85. }
  86. mcp_same_size(&this_secs->mr_enclave, &css->body.enclave_hash, sizeof(sgx_measurement_t));
  87. this_secs->isv_prod_id = css->body.isv_prod_id;
  88. this_secs->isv_svn = css->body.isv_svn;
  89. uint8_t signer[SGX_HASH_SIZE] = {0};
  90. unsigned int signer_len = SGX_HASH_SIZE;
  91. sgx_status_t ret = sgx_EVP_Digest(EVP_sha256(), css->key.modulus, SE_KEY_SIZE, signer, &signer_len);
  92. if(ret != SGX_SUCCESS)
  93. {
  94. if(ret != SGX_ERROR_OUT_OF_MEMORY)
  95. ret = SGX_ERROR_UNEXPECTED;
  96. return ret;
  97. }
  98. assert(signer_len == SGX_HASH_SIZE);
  99. mcp_same_size(&this_secs->mr_signer, signer, SGX_HASH_SIZE);
  100. }
  101. // Check launch token
  102. if (launch != NULL && launch->body.valid) {
  103. if (memcmp(&launch->body.attributes, &this_secs->attributes, sizeof(sgx_attributes_t)))
  104. {
  105. SE_TRACE(SE_TRACE_DEBUG,
  106. "SECS attributes does NOT match launch token attribuets\n");
  107. return SGX_ERROR_INVALID_ATTRIBUTE;
  108. }
  109. }
  110. // Mark it initialized
  111. this_secs->attributes.flags |= SGX_FLAGS_INITTED;
  112. return SGX_SUCCESS;
  113. }
  114. static inline bool is_power_of_two(size_t n)
  115. {
  116. return (n != 0) && (!(n & (n - 1)));
  117. }
  118. // Returns the pointer to the Enclave instance on success.
  119. uintptr_t _ECREATE(page_info_t* pi)
  120. {
  121. secs_t* secs = reinterpret_cast<secs_t*>(pi->src_page);
  122. // Enclave size must be at least 2 pages and a power of 2.
  123. GP_ON(!is_power_of_two((size_t)secs->size));
  124. GP_ON(secs->size < (SE_PAGE_SIZE << 1));
  125. CEnclaveSim* ce = new CEnclaveSim(secs);
  126. void* addr;
  127. // `ce' is not checked against NULL, since it is not
  128. // allocated with new(std::no_throw).
  129. addr = se_virtual_alloc(NULL, (size_t)secs->size, MEM_COMMIT);
  130. if (addr == NULL) {
  131. delete ce;
  132. return 0;
  133. }
  134. // Mark all the memory inaccessible.
  135. se_virtual_protect(addr, (size_t)secs->size, SGX_PROT_NONE);
  136. ce->get_secs()->base = addr;
  137. CEnclaveMngr::get_instance()->add(ce);
  138. return reinterpret_cast<uintptr_t>(ce);
  139. }
  140. uintptr_t _EADD(page_info_t* pi, void *epc_lin_addr)
  141. {
  142. void *src_page = pi->src_page;
  143. CEnclaveMngr *mngr = CEnclaveMngr::get_instance();
  144. CEnclaveSim *ce = mngr->get_enclave(pi->lin_addr);
  145. if (ce == NULL) {
  146. SE_TRACE(SE_TRACE_DEBUG, "failed to get enclave instance\n");
  147. return SGX_ERROR_UNEXPECTED;
  148. }
  149. GP_ON(!IS_PAGE_ALIGNED(epc_lin_addr));
  150. GP_ON((ce->get_secs()->attributes.flags & SGX_FLAGS_INITTED) != 0);
  151. // Make the page writable before doing memcpy()
  152. se_virtual_protect(epc_lin_addr, SE_PAGE_SIZE, SI_FLAGS_RW);
  153. mcp_same_size(epc_lin_addr, src_page, SE_PAGE_SIZE);
  154. se_virtual_protect(epc_lin_addr, SE_PAGE_SIZE, (uint32_t)pi->sec_info->flags);
  155. GP_ON(!ce->add_page(pi->lin_addr, pi->sec_info->flags));
  156. return SGX_SUCCESS;
  157. }
  158. uintptr_t _EREMOVE(const void *epc_lin_addr)
  159. {
  160. CEnclaveMngr *mngr = CEnclaveMngr::get_instance();
  161. CEnclaveSim *ce = mngr->get_enclave(epc_lin_addr);
  162. GP_ON(!ce);
  163. GP_ON(!IS_PAGE_ALIGNED(epc_lin_addr));
  164. return ce->remove_page(epc_lin_addr) ? 0 : -1;
  165. }
  166. ////////////////////////////////////////////////////////////////////////
  167. // Master entry functions
  168. void _SE3(uintptr_t xax, uintptr_t xbx,
  169. uintptr_t xcx, uintptr_t xdx,
  170. uintptr_t xsi, uintptr_t xdi)
  171. {
  172. UNUSED(xdx);
  173. switch (xax)
  174. {
  175. case SE_EENTER:
  176. uintptr_t xip;
  177. void * enclave_base_addr;
  178. se_pt_regs_t* p_pt_regs;
  179. tcs_t* tcs;
  180. tcs_sim_t* tcs_sim;
  181. ssa_gpr_t* p_ssa_gpr;
  182. secs_t* secs;
  183. CEnclaveMngr* mngr;
  184. CEnclaveSim* ce;
  185. // xbx contains the address of a TCS
  186. tcs = reinterpret_cast<tcs_t*>(xbx);
  187. // Is TCS pointer page-aligned?
  188. GP_ON_EENTER(!IS_PAGE_ALIGNED(tcs));
  189. mngr = CEnclaveMngr::get_instance();
  190. assert(mngr != NULL);
  191. // Is it really a TCS?
  192. ce = mngr->get_enclave(tcs);
  193. GP_ON_EENTER(ce == NULL);
  194. GP_ON_EENTER(!ce->is_tcs_page(tcs));
  195. // Check the EntryReason
  196. tcs_sim = reinterpret_cast<tcs_sim_t *>(tcs->reserved);
  197. GP_ON_EENTER(tcs_sim->tcs_state != TCS_STATE_INACTIVE);
  198. GP_ON_EENTER(tcs->cssa >= tcs->nssa);
  199. secs = ce->get_secs();
  200. enclave_base_addr = secs->base;
  201. p_ssa_gpr = reinterpret_cast<ssa_gpr_t*>(reinterpret_cast<uintptr_t>(enclave_base_addr) + static_cast<size_t>(tcs->ossa)
  202. + secs->ssa_frame_size * SE_PAGE_SIZE
  203. - sizeof(ssa_gpr_t));
  204. tcs_sim->saved_aep = xcx;
  205. p_pt_regs = reinterpret_cast<se_pt_regs_t*>(get_bp());
  206. p_ssa_gpr->REG(bp_u) = p_pt_regs->xbp;
  207. p_ssa_gpr->REG(sp_u) = reinterpret_cast<uintptr_t>(p_pt_regs + 1);
  208. xcx = p_pt_regs->xip;
  209. xip = reinterpret_cast<uintptr_t>(enclave_base_addr);
  210. GP_ON_EENTER(xip == 0);
  211. //set the _tls_array to point to the self_addr of TLS section inside the enclave
  212. GP_ON_EENTER(td_mngr_set_td(enclave_base_addr, tcs) == false);
  213. // Destination depends on STATE
  214. xip += (uintptr_t)tcs->oentry;
  215. tcs_sim->tcs_state = TCS_STATE_ACTIVE;
  216. // Link the TCS to the thread
  217. GP_ON_EENTER((secs->attributes.flags & SGX_FLAGS_INITTED) == 0);
  218. // Replace the return address on the stack with the enclave entry,
  219. // so that when we return from this function, we'll enter the enclave.
  220. enclu_regs_t regs;
  221. regs.xax = tcs->cssa;
  222. regs.xbx = reinterpret_cast<uintptr_t>(tcs);
  223. regs.xcx = xcx;
  224. regs.xdx = 0;
  225. regs.xsi = xsi;
  226. regs.xdi = xdi;
  227. regs.xbp = p_ssa_gpr->REG(bp_u);
  228. regs.xsp = p_ssa_gpr->REG(sp_u);
  229. regs.xip = xip;
  230. load_regs(&regs);
  231. // Returning from this function enters the enclave
  232. return;
  233. default:
  234. // There's only 1 ring 3 instruction outside the enclave: EENTER.
  235. GP();
  236. }
  237. }
  238. uintptr_t _SE0(uintptr_t xax, uintptr_t xbx,
  239. uintptr_t xcx, uintptr_t xdx,
  240. uintptr_t xsi, uintptr_t xdi)
  241. {
  242. UNUSED(xsi), UNUSED(xdi);
  243. switch (xax)
  244. {
  245. case SE_ECREATE:
  246. return _ECREATE(reinterpret_cast<page_info_t*>(xbx));
  247. case SE_EADD:
  248. return _EADD(reinterpret_cast<page_info_t*>(xbx),
  249. reinterpret_cast<void*>(xcx));
  250. case SE_EINIT:
  251. return _EINIT(reinterpret_cast<secs_t*>(xbx),
  252. reinterpret_cast<enclave_css_t *>(xcx),
  253. reinterpret_cast<token_t *>(xdx));
  254. case SE_EREMOVE:
  255. return _EREMOVE(reinterpret_cast<void*>(xcx));
  256. default:
  257. GP();
  258. }
  259. return 0;
  260. }