launch_enclave.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  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. #include <stdlib.h>
  32. #include "launch_enclave.h"
  33. #include "byte_order.h"
  34. #include "sgx_utils.h"
  35. #include "launch_enclave_t.c"
  36. #include "wl_pub.hh"
  37. #include "launch_enclave_mrsigner.hh"
  38. #include "service_enclave_mrsigner.hh"
  39. #if !defined(SWAP_ENDIAN_DW)
  40. #define SWAP_ENDIAN_DW(dw) ((((dw) & 0x000000ff) << 24) \
  41. | (((dw) & 0x0000ff00) << 8) \
  42. | (((dw) & 0x00ff0000) >> 8) \
  43. | (((dw) & 0xff000000) >> 24))
  44. #endif
  45. #if !defined(SWAP_ENDIAN_32B)
  46. #define SWAP_ENDIAN_8X32B(ptr) \
  47. { \
  48. uint32_t temp = 0; \
  49. temp = SWAP_ENDIAN_DW(((uint32_t*)(ptr))[0]); \
  50. ((uint32_t*)(ptr))[0] = SWAP_ENDIAN_DW(((uint32_t*)(ptr))[7]); \
  51. ((uint32_t*)(ptr))[7] = temp; \
  52. temp = SWAP_ENDIAN_DW(((uint32_t*)(ptr))[1]); \
  53. ((uint32_t*)(ptr))[1] = SWAP_ENDIAN_DW(((uint32_t*)(ptr))[6]); \
  54. ((uint32_t*)(ptr))[6] = temp; \
  55. temp = SWAP_ENDIAN_DW(((uint32_t*)(ptr))[2]); \
  56. ((uint32_t*)(ptr))[2] = SWAP_ENDIAN_DW(((uint32_t*)(ptr))[5]); \
  57. ((uint32_t*)(ptr))[5] = temp; \
  58. temp = SWAP_ENDIAN_DW(((uint32_t*)(ptr))[3]); \
  59. ((uint32_t*)(ptr))[3] = SWAP_ENDIAN_DW(((uint32_t*)(ptr))[4]); \
  60. ((uint32_t*)(ptr))[4] = temp; \
  61. }
  62. #endif
  63. #define LE_MAX_MRSIGNER_NUMBER 2048
  64. // Macro used to get mac wl cert size, signature is not included
  65. #define LE_MAX_WL_CERT_SIZE (sizeof(wl_cert_t) + LE_MAX_MRSIGNER_NUMBER \
  66. * sizeof(sgx_measurement_t))
  67. #define WL_CERT_VERSION 0x0100
  68. #define WL_CERT_TYPE 0x0100
  69. #define WL_CERT_PROVIDER_ID 0
  70. #define WL_PROVIDER_CERT_VERSION 0x0100
  71. #define WL_PROVIDER_CERT_TYPE 0
  72. #define WL_PROVIDER_CERT_PROVIDER_ID 0
  73. #define WL_PROVIDER_CERT_ROOT_ID 0
  74. static uint8_t g_wl_cert_buf[LE_MAX_WL_CERT_SIZE] = {0};
  75. static void reverse_byte_array(uint8_t *array, size_t size)
  76. {
  77. size_t i = 0;
  78. for(i = 0; i < size / 2; i++)
  79. {
  80. uint8_t temp = array[i];
  81. array[i] = array[size - i - 1];
  82. array[size - i - 1] = temp;
  83. }
  84. }
  85. //calculate launch token. key_id, attributes_le and then mac is updated.
  86. //return AE_SUCCESS on success
  87. static ae_error_t le_calc_lic_token(token_t* lictoken)
  88. {
  89. //calculate launch token
  90. sgx_key_request_t key_request;
  91. sgx_key_128bit_t launch_key;
  92. if(SGX_SUCCESS != sgx_read_rand((uint8_t*)&lictoken->key_id,
  93. sizeof(sgx_key_id_t)))
  94. {
  95. return LE_UNEXPECTED_ERROR;
  96. }
  97. // Create Key Request
  98. memset(&key_request, 0, sizeof(key_request));
  99. //setup key_request parameters to derive launch key
  100. key_request.key_name = SGX_KEYSELECT_EINITTOKEN;
  101. memcpy(&key_request.key_id, &lictoken->key_id,
  102. sizeof(key_request.key_id));
  103. memcpy(&key_request.cpu_svn, &(lictoken->cpu_svn_le),
  104. sizeof(key_request.cpu_svn));
  105. memcpy(&key_request.isv_svn, &(lictoken->isv_svn_le),
  106. sizeof(key_request.isv_svn));
  107. key_request.attribute_mask.xfrm = 0;
  108. //0xFFFFFFFFFFFFFFFB: ~SGX_FLAGS_MODE64BIT
  109. key_request.attribute_mask.flags = ~SGX_FLAGS_MODE64BIT;
  110. key_request.misc_mask = 0xFFFFFFFF;
  111. lictoken->masked_misc_select_le &= key_request.misc_mask;
  112. lictoken->attributes_le.flags = (lictoken->attributes_le.flags)
  113. & (key_request.attribute_mask.flags);
  114. lictoken->attributes_le.xfrm = (lictoken->attributes_le.xfrm)
  115. & (key_request.attribute_mask.xfrm);
  116. // EGETKEY
  117. sgx_status_t sgx_ret = sgx_get_key(&key_request,&launch_key);
  118. if(SGX_SUCCESS != sgx_ret)
  119. {
  120. return LE_GET_EINITTOKEN_KEY_ERROR;
  121. }
  122. sgx_cmac_state_handle_t p_cmac_handle = NULL;
  123. do{
  124. sgx_ret = sgx_cmac128_init(&launch_key, &p_cmac_handle);
  125. if(SGX_SUCCESS != sgx_ret)
  126. {
  127. break;
  128. }
  129. sgx_ret = sgx_cmac128_update((uint8_t*)&lictoken->body,
  130. sizeof(lictoken->body),
  131. p_cmac_handle);
  132. if(SGX_SUCCESS != sgx_ret)
  133. {
  134. break;
  135. }
  136. sgx_ret = sgx_cmac128_final(p_cmac_handle,
  137. (sgx_cmac_128bit_tag_t*)&lictoken->mac);
  138. }while(0);
  139. if (p_cmac_handle != NULL)
  140. {
  141. sgx_cmac128_close(p_cmac_handle);
  142. }
  143. //clear launch_key after being used
  144. memset_s(launch_key,sizeof(launch_key), 0, sizeof(launch_key));
  145. if (SGX_SUCCESS != sgx_ret)
  146. {
  147. return AE_FAILURE;
  148. }
  149. return AE_SUCCESS;
  150. }
  151. ae_error_t le_generate_launch_token(
  152. const sgx_measurement_t* mrenclave,
  153. const sgx_measurement_t* mrsigner,
  154. const sgx_attributes_t* se_attributes,
  155. token_t* lictoken)
  156. {
  157. uint32_t i = 0;
  158. bool is_production = false;
  159. sgx_status_t sgx_ret = SGX_ERROR_UNEXPECTED;
  160. ae_error_t ae_ret = AE_FAILURE;
  161. wl_cert_t *p_wl_cert_cache = (wl_cert_t *)g_wl_cert_buf;
  162. sgx_measurement_t empty_mrsigner;
  163. sgx_report_t report;
  164. // se_attributes must have no reserved bit set.
  165. // urts(finally EINIT instruction)rejects EINIT Token with SGX_FLAGS_INITTED
  166. // set. So LE doesn't need to check it here.
  167. if((se_attributes->flags) & SGX_FLAGS_RESERVED)
  168. {
  169. return LE_INVALID_ATTRIBUTE;
  170. }
  171. memset(&report, 0, sizeof(report));
  172. // Create report to get current cpu_svn and isv_svn.
  173. sgx_ret = sgx_create_report(NULL, NULL, &report);
  174. if(SGX_SUCCESS != sgx_ret)
  175. {
  176. return LE_UNEXPECTED_ERROR;
  177. }
  178. for(i = 0; i < (sizeof(g_le_mrsigner) / sizeof(g_le_mrsigner[0])); i++)
  179. {
  180. if(0 == memcmp(&(g_le_mrsigner[i]), &(report.body.mr_signer),
  181. sizeof(g_le_mrsigner[0])))
  182. {
  183. is_production = true;
  184. break;
  185. }
  186. }
  187. if(true == is_production)
  188. {
  189. // Only Provision Enclave is allowed to be EINITed with the privilege
  190. // to access the PROVISIONKEY, which is signed with fixed signing key
  191. if((se_attributes->flags & SGX_FLAGS_PROVISION_KEY))
  192. {
  193. for(i = 0; i < (sizeof(G_SERVICE_ENCLAVE_MRSIGNER) / sizeof(G_SERVICE_ENCLAVE_MRSIGNER[0]));
  194. i++)
  195. {
  196. if(0 == memcmp(&G_SERVICE_ENCLAVE_MRSIGNER[i], mrsigner,
  197. sizeof(G_SERVICE_ENCLAVE_MRSIGNER[0])))
  198. {
  199. break;
  200. }
  201. }
  202. if(i == sizeof(G_SERVICE_ENCLAVE_MRSIGNER) / sizeof(G_SERVICE_ENCLAVE_MRSIGNER[0]))
  203. {
  204. return LE_INVALID_ATTRIBUTE;
  205. }
  206. }
  207. }
  208. // on "production" system, enclaves to be launched in "non-enclave-debug"
  209. // mode are subjected to Enclave Signing Key White Listing control.
  210. if(((se_attributes->flags & SGX_FLAGS_DEBUG) == 0)
  211. && (true == is_production))
  212. {
  213. // Check whether the wl is initialized
  214. if(p_wl_cert_cache->version == 0)
  215. {
  216. return LE_WHITELIST_UNINITIALIZED_ERROR;
  217. }
  218. // Create an empty mrsigner
  219. memset(&empty_mrsigner, 0, sizeof(empty_mrsigner));
  220. // Check if p_wl_cert_cache->mr_signer_list[0] is empty.
  221. // If mr_signer_list[0] = 0, a "wild card" white list cert is in-use,
  222. // meant to allow any enclave to launch.
  223. if(0 != memcmp(&(p_wl_cert_cache->mr_signer_list[0]), &empty_mrsigner,
  224. sizeof(p_wl_cert_cache->mr_signer_list[0])))
  225. {
  226. for(i = 0; i < p_wl_cert_cache->entry_number; i++)
  227. {
  228. if(0 == memcmp(&(p_wl_cert_cache->mr_signer_list[i]),
  229. mrsigner,
  230. sizeof(p_wl_cert_cache->mr_signer_list[i])))
  231. {
  232. break;
  233. }
  234. }
  235. if(i == p_wl_cert_cache->entry_number)
  236. {
  237. return LE_INVALID_PRIVILEGE_ERROR;
  238. }
  239. }
  240. }
  241. //initial EINIT Token and set 0 for all reserved area
  242. memset(lictoken, 0, sizeof(*lictoken));
  243. //set the EINIT Token valid
  244. lictoken->body.valid = 1;
  245. //set EINIT Token mrenclave
  246. memcpy(&lictoken->body.mr_enclave, mrenclave,
  247. sizeof(lictoken->body.mr_enclave));
  248. //set EINIT Token mrsigner
  249. memcpy(&lictoken->body.mr_signer, mrsigner,
  250. sizeof(lictoken->body.mr_signer));
  251. //set EINIT Token attributes
  252. memcpy(&lictoken->body.attributes, se_attributes,
  253. sizeof(lictoken->body.attributes));
  254. //set EINIT Token with platform information from ereport of LE
  255. memcpy(&lictoken->cpu_svn_le, &report.body.cpu_svn, sizeof(sgx_cpu_svn_t));
  256. lictoken->isv_svn_le = report.body.isv_svn;
  257. lictoken->isv_prod_id_le = report.body.isv_prod_id;
  258. //will mask attributes in le_calc_lic_token
  259. memcpy(&lictoken->attributes_le, &report.body.attributes,
  260. sizeof(lictoken->attributes_le));
  261. //will mask misc_select_le in le_calc_lic_token
  262. lictoken->masked_misc_select_le = report.body.misc_select;
  263. //calculate EINIT Token
  264. ae_ret = le_calc_lic_token(lictoken);
  265. //if failure, clear EINIT Token
  266. if (ae_ret != AE_SUCCESS)
  267. {
  268. memset_s(lictoken,sizeof(*lictoken), 0, sizeof(*lictoken));
  269. }
  270. return ae_ret;
  271. }
  272. int le_get_launch_token_wrapper(
  273. const sgx_measurement_t* mrenclave,
  274. const sgx_measurement_t* mrsigner,
  275. const sgx_attributes_t* se_attributes,
  276. token_t* lictoken)
  277. {
  278. // Security assumption is that the edgr8r generated trusted bridge code
  279. // makes sure mrenclave, mrsigner, se_attributes, lictoken buffers are all
  280. // inside enclave. check all input and output pointers, defense in depth
  281. if (NULL == mrenclave ||
  282. NULL == mrsigner ||
  283. NULL == se_attributes ||
  284. NULL == lictoken)
  285. {
  286. return LE_INVALID_PARAMETER;
  287. }
  288. return le_generate_launch_token(mrenclave, mrsigner, se_attributes,
  289. lictoken);
  290. }
  291. /*
  292. * Internal function used to init white list. It will check the content of the
  293. * cert chain, and verify the signature of input cert chains. If no problem,
  294. * it will cache the input white list into EPC.
  295. *
  296. * @param p_wl_cert_chain[in] Pointer to the white list cert chain.
  297. * @param entry_number[in] The entry number within the white list.
  298. * @param wl_cert_chain_size[in] The size of white list cert chain, in bytes.
  299. * @return uint32_t AE_SUCCESS for success, otherwise for errors.
  300. */
  301. uint32_t le_init_white_list(
  302. const wl_cert_chain_t *p_wl_cert_chain,
  303. uint32_t entry_number,
  304. uint32_t wl_cert_chain_size)
  305. {
  306. sgx_status_t sgx_ret = SGX_SUCCESS;
  307. uint32_t ret = AE_SUCCESS;
  308. uint32_t new_wl_version = 0;
  309. uint8_t verify_result = 0;
  310. int valid = 0;
  311. const uint8_t *buf = NULL;
  312. uint32_t buf_size = 0;
  313. sgx_prod_id_t wl_prod_id = 0;
  314. sgx_ecc_state_handle_t ecc_handle = NULL;
  315. wl_cert_t *p_wl_cert_cache = (wl_cert_t *)g_wl_cert_buf;
  316. sgx_report_t report;
  317. sgx_ec256_signature_t wl_signature;
  318. sgx_ec256_public_t wl_pubkey;
  319. // Check fields of provider cert
  320. // Format version should be 1 (big endian)
  321. if(p_wl_cert_chain->wl_provider_cert.version != WL_PROVIDER_CERT_VERSION)
  322. {
  323. ret = LE_INVALID_PARAMETER;
  324. goto CLEANUP;
  325. }
  326. // For Enclave Signing Key White List Cert, must be 0
  327. if(p_wl_cert_chain->wl_provider_cert.cert_type != WL_PROVIDER_CERT_TYPE)
  328. {
  329. ret = LE_INVALID_PARAMETER;
  330. goto CLEANUP;
  331. }
  332. // only one White List Provider is approved:
  333. // WLProviderID: ISecG = 0
  334. if(p_wl_cert_chain->wl_provider_cert.provider_id != WL_PROVIDER_CERT_PROVIDER_ID)
  335. {
  336. ret = LE_INVALID_PARAMETER;
  337. goto CLEANUP;
  338. }
  339. // only one WLRootID is valid: WLRootID-iKGF-Key-0 = 0
  340. if(p_wl_cert_chain->wl_provider_cert.root_id != WL_PROVIDER_CERT_ROOT_ID)
  341. {
  342. ret = LE_INVALID_PARAMETER;
  343. goto CLEANUP;
  344. }
  345. // Check fields of wl cert
  346. // only valid version is 1
  347. if(p_wl_cert_chain->wl_cert.version != WL_CERT_VERSION)
  348. {
  349. ret = LE_INVALID_PARAMETER;
  350. goto CLEANUP;
  351. }
  352. // For Enclave Signing Key White List Cert, must be 1
  353. if(p_wl_cert_chain->wl_cert.cert_type != WL_CERT_TYPE)
  354. {
  355. ret = LE_INVALID_PARAMETER;
  356. goto CLEANUP;
  357. }
  358. // only one White List Provider is approved:
  359. // WLProviderID: ISecG = 0
  360. if(p_wl_cert_chain->wl_cert.provider_id != WL_CERT_PROVIDER_ID)
  361. {
  362. ret = LE_INVALID_PARAMETER;
  363. goto CLEANUP;
  364. }
  365. // If cache exists
  366. new_wl_version = p_wl_cert_chain->wl_cert.wl_version;
  367. new_wl_version = _ntohl(new_wl_version);
  368. if(p_wl_cert_cache->version != 0)
  369. {
  370. // the logic will be needed to support more than
  371. // one providers in the future.
  372. //if(p_wl_cert_chain->wl_cert.provider_id
  373. // != p_wl_cert_cache->provider_id)
  374. //{
  375. // ret = LE_INVALID_PARAMETER;
  376. // goto CLEANUP;
  377. //}
  378. if(new_wl_version <= p_wl_cert_cache->wl_version)
  379. {
  380. ret = LE_WHITE_LIST_ALREADY_UPDATED;
  381. goto CLEANUP;
  382. }
  383. }
  384. sgx_ret = sgx_ecc256_open_context(&ecc_handle);
  385. if (SGX_SUCCESS != sgx_ret)
  386. {
  387. ret = LE_UNEXPECTED_ERROR;
  388. goto CLEANUP;
  389. }
  390. memset(&wl_signature, 0, sizeof(wl_signature));
  391. // Convert the signature of provider cert into little endian
  392. memcpy(&wl_signature,
  393. &(p_wl_cert_chain->wl_provider_cert.signature),
  394. sizeof(wl_signature));
  395. SWAP_ENDIAN_8X32B(wl_signature.x);
  396. SWAP_ENDIAN_8X32B(wl_signature.y);
  397. // Verify the wl provider cert
  398. buf = (const uint8_t *)&(p_wl_cert_chain->wl_provider_cert);
  399. buf_size = static_cast<uint32_t>(sizeof(p_wl_cert_chain->wl_provider_cert)
  400. - sizeof(p_wl_cert_chain->wl_provider_cert.signature));
  401. sgx_ret = sgx_ecdsa_verify(buf, buf_size,
  402. &g_wl_root_pubkey,
  403. &wl_signature,
  404. &verify_result,
  405. ecc_handle);
  406. if (SGX_SUCCESS != sgx_ret)
  407. {
  408. ret = LE_UNEXPECTED_ERROR;
  409. goto CLEANUP;
  410. }
  411. if(SGX_EC_VALID != verify_result)
  412. {
  413. ret = LE_INVALID_PARAMETER;
  414. goto CLEANUP;
  415. }
  416. // Convert the signature of wl cert into little endian
  417. buf = (const uint8_t *)p_wl_cert_chain + wl_cert_chain_size
  418. - sizeof(wl_signature);
  419. memcpy(&wl_signature, buf, sizeof(wl_signature));
  420. SWAP_ENDIAN_8X32B(wl_signature.x);
  421. SWAP_ENDIAN_8X32B(wl_signature.y);
  422. // Convert the pubkey into little endian
  423. memset(&wl_pubkey, 0, sizeof(wl_pubkey));
  424. memcpy(&wl_pubkey,
  425. &(p_wl_cert_chain->wl_provider_cert.pub_key),
  426. sizeof(wl_pubkey));
  427. reverse_byte_array(wl_pubkey.gx, sizeof(wl_pubkey.gx));
  428. reverse_byte_array(wl_pubkey.gy, sizeof(wl_pubkey.gy));
  429. // Check whether the pubkey is valid first.
  430. sgx_ret = sgx_ecc256_check_point(&wl_pubkey, ecc_handle, &valid);
  431. if(SGX_SUCCESS != sgx_ret)
  432. {
  433. ret = LE_UNEXPECTED_ERROR;
  434. goto CLEANUP;
  435. }
  436. if(!valid)
  437. {
  438. ret = LE_INVALID_PARAMETER;
  439. goto CLEANUP;
  440. }
  441. // Verify the wl_cert
  442. buf = (const uint8_t *)&(p_wl_cert_chain->wl_cert);
  443. buf_size = wl_cert_chain_size - static_cast<uint32_t>(sizeof(wl_provider_cert_t) + sizeof(sgx_ec256_signature_t));
  444. sgx_ret = sgx_ecdsa_verify(buf, buf_size,
  445. &wl_pubkey,
  446. &wl_signature,
  447. &verify_result,
  448. ecc_handle);
  449. if (SGX_SUCCESS != sgx_ret)
  450. {
  451. ret = LE_UNEXPECTED_ERROR;
  452. goto CLEANUP;
  453. }
  454. if(SGX_EC_VALID != verify_result)
  455. {
  456. ret = LE_INVALID_PARAMETER;
  457. goto CLEANUP;
  458. }
  459. memset(&report, 0, sizeof(report));
  460. // Create report to get current mrsigner.
  461. sgx_ret = sgx_create_report(NULL, NULL, &report);
  462. if(SGX_SUCCESS != sgx_ret)
  463. {
  464. ret = LE_UNEXPECTED_ERROR;
  465. goto CLEANUP;
  466. }
  467. // Convert the big endian prod id to little endian.
  468. wl_prod_id = p_wl_cert_chain->wl_cert.le_prod_id;
  469. wl_prod_id = _ntohs(wl_prod_id);
  470. if(report.body.isv_prod_id != wl_prod_id)
  471. {
  472. ret = LE_INVALID_PARAMETER;
  473. goto CLEANUP;
  474. }
  475. // Cache the wl cert
  476. memset(g_wl_cert_buf, 0, sizeof(g_wl_cert_buf));
  477. memcpy(g_wl_cert_buf, &(p_wl_cert_chain->wl_cert), buf_size);
  478. // Change entry_number and wl_version to little endian, so we don't need to
  479. // convert them next time.
  480. p_wl_cert_cache->entry_number = entry_number;
  481. p_wl_cert_cache->wl_version = new_wl_version;
  482. CLEANUP:
  483. if(ecc_handle != NULL)
  484. {
  485. sgx_ecc256_close_context(ecc_handle);
  486. }
  487. return ret;
  488. }
  489. /*
  490. * External function used to init white list. It will check whether the input
  491. * buffer is correctly copied into EPC, and check the size of the buffer.
  492. *
  493. * @param wl_cert_chain[in] Pointer to the white list cert chain.
  494. * @param wl_cert_chain_size[in] The size of white list cert chain, in bytes.
  495. * @return uint32_t AE_SUCCESS for success, otherwise for errors.
  496. */
  497. uint32_t le_init_white_list_wrapper(
  498. const uint8_t *wl_cert_chain,
  499. uint32_t wl_cert_chain_size)
  500. {
  501. const wl_cert_chain_t *p_wl_cert_chain = NULL;
  502. uint32_t entry_number = 0;
  503. uint32_t temp_size = 0;
  504. if(wl_cert_chain == NULL)
  505. {
  506. return LE_INVALID_PARAMETER;
  507. }
  508. if(!sgx_is_within_enclave(wl_cert_chain, wl_cert_chain_size))
  509. return LE_INVALID_PARAMETER;
  510. p_wl_cert_chain = (const wl_cert_chain_t *)wl_cert_chain;
  511. // First compare wl_cert_chain_size with the minimal size of cert chain.
  512. // It should have at least one entry of mrsigner.
  513. if(wl_cert_chain_size < sizeof(wl_cert_chain_t)
  514. + sizeof(sgx_measurement_t)
  515. + sizeof(sgx_ec256_signature_t))
  516. {
  517. return LE_INVALID_PARAMETER;
  518. }
  519. entry_number = p_wl_cert_chain->wl_cert.entry_number;
  520. entry_number = _ntohl(entry_number);
  521. // limits max MRSIGNER entry number in
  522. // WL Cert to be <= 2048
  523. if(entry_number > LE_MAX_MRSIGNER_NUMBER)
  524. {
  525. return LE_INVALID_PARAMETER;
  526. }
  527. temp_size = static_cast<uint32_t>(sizeof(wl_cert_chain_t)
  528. + sizeof(sgx_ec256_signature_t)
  529. + (sizeof(sgx_measurement_t) * entry_number));
  530. if(wl_cert_chain_size != temp_size)
  531. {
  532. return LE_INVALID_PARAMETER;
  533. }
  534. return le_init_white_list(p_wl_cert_chain, entry_number, wl_cert_chain_size);
  535. }