LEClass.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. /*
  2. * Copyright (C) 2011-2018 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 <assert.h>
  32. #include "LEClass.h"
  33. #include "aeerror.h"
  34. #include "arch.h"
  35. #include "ae_ipp.h"
  36. #include "util.h"
  37. #include "service_enclave_mrsigner.hh"
  38. #include "aesm_long_lived_thread.h"
  39. #ifdef REF_LE
  40. #include "ref_le_u.h"
  41. #include "ref_le_u.c"
  42. #else
  43. #include "launch_enclave_u.h"
  44. #include "launch_enclave_u.c"
  45. extern "C" sgx_status_t sgx_create_le(const char *file_name, const char *prd_css_file_name, const int debug, sgx_launch_token_t *launch_token, int *launch_token_updated, sgx_enclave_id_t *enclave_id, sgx_misc_attribute_t *misc_attr, int *production_loaded);
  46. extern "C" bool is_in_kernel_driver();
  47. #endif
  48. int CLEClass::white_list_register(
  49. const uint8_t *white_list_cert,
  50. uint32_t white_list_cert_size,
  51. bool save_to_persistent_storage)
  52. {
  53. sgx_status_t ret = SGX_SUCCESS;
  54. int retry = 0;
  55. uint32_t status = 0;
  56. AESMLogicLock locker(AESMLogic::_le_mutex);
  57. assert(m_enclave_id);
  58. #ifdef REF_LE
  59. if (white_list_cert_size < sizeof(ref_le_white_list_t))
  60. {
  61. AESM_DBG_WARN("white list size is smaller than the expected minimum");
  62. return AE_INVALID_PARAMETER;
  63. }
  64. ref_le_white_list_t *p_white_list = (ref_le_white_list_t*)white_list_cert;
  65. uint32_t entries_count = _ntohs(p_white_list->entries_count);
  66. uint32_t white_list_size = REF_LE_WL_SIZE(entries_count);
  67. if ((white_list_size + sizeof(sgx_rsa3072_signature_t)) > white_list_cert_size)
  68. {
  69. AESM_DBG_WARN("white list size for %d recornds - expected: %d + %d = %d, actual: %d", entries_count,
  70. white_list_size, sizeof(sgx_rsa3072_signature_t), white_list_size + sizeof(sgx_rsa3072_signature_t), white_list_cert_size);
  71. return AE_INVALID_PARAMETER;
  72. }
  73. sgx_rsa3072_signature_t* p_white_list_sig = (sgx_rsa3072_signature_t*)((uint64_t)white_list_cert + white_list_size);
  74. ret = ref_le_init_white_list(m_enclave_id, (int*)&status, p_white_list, white_list_size, p_white_list_sig);
  75. #else
  76. if (white_list_cert_size < sizeof(wl_cert_chain_t)) {
  77. return LE_INVALID_PARAMETER;
  78. }
  79. ret = le_init_white_list_wrapper(m_enclave_id, &status,
  80. const_cast<uint8_t*>(white_list_cert),
  81. white_list_cert_size);
  82. #endif // REF_LE
  83. for(; ret == SGX_ERROR_ENCLAVE_LOST && retry < AESM_RETRY_COUNT; retry++)
  84. {
  85. unload_enclave();
  86. if(AE_SUCCESS != load_enclave_only())
  87. return AE_FAILURE;
  88. #ifdef REF_LE
  89. ret = ref_le_init_white_list(m_enclave_id, (int*)&status, p_white_list, white_list_size, p_white_list_sig);
  90. #else
  91. ret = le_init_white_list_wrapper(m_enclave_id, &status,
  92. const_cast<uint8_t*>(white_list_cert),
  93. white_list_cert_size);
  94. #endif // REF_LE
  95. }
  96. if(SGX_SUCCESS!=ret)
  97. return sgx_error_to_ae_error(ret);
  98. AESM_DBG_TRACE("le_init_white_list_wrapper return %d",status);
  99. if(AE_SUCCESS == status&&save_to_persistent_storage){//successfully register the white list cert
  100. if(AE_SUCCESS != aesm_write_data(FT_PERSISTENT_STORAGE,AESM_WHITE_LIST_CERT_FID,white_list_cert, white_list_cert_size)){//ignore error if failed to save in persistent storage
  101. AESM_DBG_WARN("Fail to save white list cert in persistent storage");
  102. }
  103. }
  104. if (LE_WHITE_LIST_ALREADY_UPDATED == status) {
  105. status = AE_SUCCESS;
  106. }
  107. return status;
  108. }
  109. void CLEClass::load_white_cert_list()
  110. {
  111. load_verified_white_cert_list();
  112. load_white_cert_list_to_be_verify();//If this version is older than previous one, it will not be loaded
  113. }
  114. #include <time.h>
  115. #include "endpoint_select_info.h"
  116. #include "stdint.h"
  117. #define UPDATE_DURATION (24*3600)
  118. ae_error_t CLEClass::update_white_list_by_url()
  119. {
  120. // on reference LE we don't support equiring white list from URL
  121. #ifndef REF_LE
  122. static time_t last_updated_time = 0;
  123. int i = 0;
  124. ae_error_t ret = AE_FAILURE;
  125. time_t cur_time = time(NULL);
  126. if (last_updated_time + UPDATE_DURATION > cur_time){
  127. return LE_WHITE_LIST_QUERY_BUSY;
  128. }
  129. if (is_in_kernel_driver())
  130. {
  131. AESM_DBG_INFO("InKernel LE loaded");
  132. return AE_SUCCESS;
  133. }
  134. AESM_LOG_INFO_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_WL_UPDATE_START]);
  135. for (i = 0; i < 2; i++){//at most retry once if network error
  136. uint8_t *resp_buf = NULL;
  137. uint32_t resp_size = 0;
  138. const char *url = EndpointSelectionInfo::instance().get_server_url(SGX_WHITE_LIST_FILE);
  139. if (NULL == url){
  140. return OAL_CONFIG_FILE_ERROR;
  141. }
  142. ret = aesm_network_send_receive(url,
  143. NULL, 0, &resp_buf, &resp_size,GET, false);
  144. if (ret == OAL_NETWORK_UNAVAILABLE_ERROR){
  145. AESM_DBG_WARN("Network failure in getting white list...");
  146. continue;
  147. }
  148. if (ret == AE_SUCCESS){
  149. if (resp_buf != NULL && resp_size > 0){
  150. ret = (ae_error_t)instance().white_list_register(resp_buf, resp_size, true);
  151. if (AE_SUCCESS == ret&&resp_size >= sizeof(wl_cert_chain_t)){
  152. const wl_cert_chain_t* wl = reinterpret_cast<const wl_cert_chain_t*>(resp_buf);
  153. AESM_LOG_INFO_ADMIN("%s for Version: %d", g_admin_event_string_table[SGX_ADMIN_EVENT_WL_UPDATE_SUCCESS],
  154. _ntohl(wl->wl_cert.wl_version));
  155. }
  156. else if (LE_INVALID_PARAMETER == ret || LE_INVALID_PRIVILEGE_ERROR ==ret){
  157. AESM_LOG_WARN_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_WL_UPDATE_FAIL]);
  158. }else{
  159. ret = AE_FAILURE;//Internal error, maybe LE not consistent with AESM?
  160. }
  161. }
  162. last_updated_time = cur_time;
  163. aesm_free_network_response_buffer(resp_buf);
  164. }
  165. break;
  166. }
  167. if (OAL_NETWORK_UNAVAILABLE_ERROR == ret){
  168. AESM_LOG_WARN_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_WL_UPDATE_NETWORK_FAIL]);
  169. }
  170. return ret;
  171. #else
  172. return AE_SUCCESS;
  173. #endif
  174. }
  175. ae_error_t CLEClass::load_verified_white_cert_list()
  176. {
  177. ae_error_t ae_err;
  178. uint32_t white_cert_size=0;
  179. ae_err = aesm_query_data_size(FT_PERSISTENT_STORAGE, AESM_WHITE_LIST_CERT_FID, &white_cert_size);
  180. if(AE_SUCCESS == ae_err && white_cert_size ==0){//file not existing or 0 size
  181. AESM_DBG_TRACE("no white cert list available in persistent storage");
  182. return AE_SUCCESS;
  183. }
  184. if(AE_SUCCESS != ae_err)
  185. return ae_err;
  186. uint8_t *p = (uint8_t *)malloc(white_cert_size);
  187. if(NULL == p){
  188. AESM_DBG_ERROR("out of memory");
  189. return AE_OUT_OF_MEMORY_ERROR;
  190. }
  191. ae_err = aesm_read_data(FT_PERSISTENT_STORAGE, AESM_WHITE_LIST_CERT_FID, p, &white_cert_size);
  192. if(AE_SUCCESS != ae_err){
  193. AESM_DBG_WARN("Fail to read white cert list file");
  194. free(p);
  195. return ae_err;
  196. }
  197. ae_err = (ae_error_t)white_list_register(p, white_cert_size,false);//Need not save the data to file again
  198. if(AE_SUCCESS!=ae_err){
  199. AESM_DBG_WARN("fail to register white cert list file in persistent storage");
  200. }
  201. free(p);
  202. return ae_err;
  203. }
  204. //This function must be called after white list cert has been verified and the file may overwrite the original one
  205. ae_error_t CLEClass::load_white_cert_list_to_be_verify()
  206. {
  207. ae_error_t ae_err;
  208. uint32_t white_cert_size=0;
  209. ae_err = aesm_query_data_size(FT_PERSISTENT_STORAGE, AESM_WHITE_LIST_CERT_TO_BE_VERIFY_FID, &white_cert_size);
  210. if(AE_SUCCESS != ae_err || white_cert_size ==0){//file not existing or 0 size
  211. AESM_DBG_TRACE("no white cert list to be verify in persistent storage");
  212. return AE_SUCCESS;
  213. }
  214. uint8_t *p = (uint8_t *)malloc(white_cert_size);
  215. if(NULL == p){
  216. AESM_DBG_ERROR("out of memory");
  217. return AE_OUT_OF_MEMORY_ERROR;
  218. }
  219. ae_err = aesm_read_data(FT_PERSISTENT_STORAGE, AESM_WHITE_LIST_CERT_TO_BE_VERIFY_FID, p, &white_cert_size);
  220. if(AE_SUCCESS != ae_err){
  221. AESM_DBG_WARN("Fail to read white cert list file");
  222. free(p);
  223. return ae_err;
  224. }
  225. ae_err = (ae_error_t)white_list_register(p, white_cert_size,true);//We need to overwrite the original white list file if the file is passed
  226. if(AE_SUCCESS!=ae_err){
  227. AESM_DBG_WARN("fail to register white cert list file in persistent storage");
  228. }
  229. {//Always remove the file now. If it is not verified, the file has problem and remove it; otherwise, it has been saved as the AESM_WHITE_LIST_CERT_FID
  230. char white_list_to_be_verify_path_name[MAX_PATH];
  231. ae_err = aesm_get_pathname(FT_PERSISTENT_STORAGE, AESM_WHITE_LIST_CERT_TO_BE_VERIFY_FID, white_list_to_be_verify_path_name, MAX_PATH);
  232. if(AE_SUCCESS == ae_err){
  233. se_delete_tfile(white_list_to_be_verify_path_name);
  234. }
  235. }
  236. free(p);
  237. return ae_err;
  238. }
  239. ae_error_t CLEClass::load_enclave_only()
  240. {
  241. before_enclave_load();
  242. assert(m_enclave_id==0);
  243. sgx_status_t ret;
  244. ae_error_t ae_err;
  245. char prod_css_path[MAX_PATH]={0};
  246. char enclave_path[MAX_PATH]= {0};
  247. char *p_prod_css_path = prod_css_path;
  248. int production_le_loaded = 0;
  249. if((ae_err = aesm_get_pathname(FT_PERSISTENT_STORAGE, LE_PROD_SIG_STRUCT_FID, prod_css_path, MAX_PATH))!=AE_SUCCESS){
  250. AESM_DBG_WARN("fail to get production sig struction of LE");
  251. p_prod_css_path = NULL;
  252. }
  253. if((ae_err = aesm_get_pathname(FT_ENCLAVE_NAME, get_enclave_fid(), enclave_path,//get non-production signed LE pathname
  254. MAX_PATH))
  255. !=AE_SUCCESS){
  256. AESM_DBG_ERROR("fail to get LE pathname");
  257. return ae_err;
  258. }
  259. int launch_token_update;
  260. // in the ref LE we do not support loading non-production signed LE, as it should used with LCP a developer may
  261. // load a non-production launch enclave by setting the non-production provider to the IA32_SGXLEPUBKEYHASH0..3 MSRs.
  262. #if defined(AESM_SIM) || defined(REF_LE)
  263. UNUSED(p_prod_css_path);
  264. UNUSED(production_le_loaded);
  265. ret = sgx_create_enclave(enclave_path, get_debug_flag(), &m_launch_token,
  266. &launch_token_update, &m_enclave_id,
  267. &m_attributes);//simulation or ref_le mode has no sgx_create_le function. Use sgx_create_enclave
  268. if(ret != SGX_SUCCESS){
  269. AESM_DBG_ERROR("Fail to load LE");
  270. return AE_FAILURE;
  271. }
  272. #ifdef REF_LE
  273. AESM_DBG_DEBUG("ref_le loaded succesfully");
  274. #endif
  275. m_ufd = false;
  276. #else
  277. ret = sgx_create_le(enclave_path, p_prod_css_path, get_debug_flag(), &m_launch_token,
  278. &launch_token_update, &m_enclave_id,
  279. &m_attributes, &production_le_loaded);
  280. if (ret == SGX_ERROR_NO_DEVICE){
  281. AESM_DBG_ERROR("AE SERVER NOT AVAILABLE in load non-production signed LE: %s",enclave_path);
  282. return AESM_AE_NO_DEVICE;
  283. }
  284. if(ret == SGX_ERROR_OUT_OF_EPC)
  285. {
  286. AESM_DBG_ERROR("Loading LE failed due to out of epc");
  287. return AESM_AE_OUT_OF_EPC;
  288. }
  289. if (ret != SGX_SUCCESS){
  290. AESM_DBG_ERROR("Loading LE failed:%d",ret);
  291. return AE_SERVER_NOT_AVAILABLE;
  292. }else if(production_le_loaded!=0){//production signed LE loaded
  293. m_ufd = false;
  294. AESM_DBG_INFO("Production signed LE loaded, try loading white list now");
  295. }else{
  296. m_ufd = true;
  297. AESM_DBG_INFO("Debug signed LE loaded");
  298. }
  299. #endif
  300. return AE_SUCCESS;
  301. }
  302. ae_error_t CLEClass::load_enclave()
  303. {
  304. if(m_enclave_id){//LE has been loaded before
  305. return AE_SUCCESS;
  306. }
  307. #ifndef REF_LE
  308. if (is_in_kernel_driver())
  309. {
  310. AESM_DBG_INFO("InKernel LE loaded");
  311. return AE_SUCCESS;
  312. }
  313. #endif
  314. ae_error_t ae_err = load_enclave_only();
  315. if( AE_SUCCESS == ae_err){
  316. load_white_cert_list();
  317. }
  318. return ae_err;
  319. }
  320. int CLEClass::get_launch_token(
  321. uint8_t * mrenclave, uint32_t mrenclave_size,
  322. uint8_t *public_key, uint32_t public_key_size,
  323. uint8_t *se_attributes, uint32_t se_attributes_size,
  324. uint8_t * lictoken, uint32_t lictoken_size,
  325. uint32_t *ae_mrsigner_index
  326. )
  327. {
  328. sgx_status_t ret = SGX_SUCCESS;
  329. int retry = 0;
  330. int status = 0;
  331. assert(m_enclave_id);
  332. sgx_measurement_t mrsigner;
  333. if(mrenclave_size !=sizeof(sgx_measurement_t) ||
  334. SE_KEY_SIZE != public_key_size ||
  335. se_attributes_size != sizeof(sgx_attributes_t) ||
  336. lictoken_size < sizeof(token_t) ||
  337. lictoken == NULL)
  338. return LE_INVALID_PARAMETER;
  339. //set mrsigner based on the hash of isv pub key from enclave signature
  340. IppStatus ipperrorCode = ippStsNoErr;
  341. ipperrorCode = ippsHashMessage_rmf(reinterpret_cast<const Ipp8u *>(public_key), public_key_size, reinterpret_cast<Ipp8u *>(&mrsigner), ippsHashMethod_SHA256_TT());
  342. if( ipperrorCode != ippStsNoErr){
  343. return AE_FAILURE;
  344. }
  345. if(ae_mrsigner_index!=NULL){
  346. *ae_mrsigner_index = UINT32_MAX;
  347. for(uint32_t i=0;i<sizeof(G_SERVICE_ENCLAVE_MRSIGNER)/sizeof(G_SERVICE_ENCLAVE_MRSIGNER[0]);i++){
  348. if(memcmp(&G_SERVICE_ENCLAVE_MRSIGNER[i], &mrsigner, sizeof(mrsigner))==0){
  349. *ae_mrsigner_index=i;
  350. break;
  351. }
  352. }
  353. }
  354. #ifdef DBG_LOG
  355. char mrsigner_info[256];
  356. sgx_attributes_t *attr = (sgx_attributes_t *)se_attributes;
  357. aesm_dbg_format_hex((uint8_t *)&mrsigner, sizeof(mrsigner), mrsigner_info, 256);
  358. AESM_DBG_INFO("try to load Enclave with mrsigner:%s , attr %llx, xfrm %llx", mrsigner_info, attr->flags, attr->xfrm);
  359. #endif
  360. // the interface of the get token API is identical, only the name is different
  361. #ifdef REF_LE
  362. #define le_get_launch_token_wrapper ref_le_get_launch_token
  363. #endif // REF_LE
  364. //get launch token by ecall into LE
  365. ret = le_get_launch_token_wrapper(m_enclave_id, &status,
  366. reinterpret_cast<sgx_measurement_t*>(mrenclave),
  367. &mrsigner,
  368. reinterpret_cast<sgx_attributes_t*>(se_attributes),
  369. reinterpret_cast<token_t*>(lictoken));
  370. for(; ret == SGX_ERROR_ENCLAVE_LOST && retry < AESM_RETRY_COUNT; retry++)
  371. {
  372. unload_enclave();
  373. if(AE_SUCCESS != load_enclave())
  374. return AE_FAILURE;
  375. ret = le_get_launch_token_wrapper(m_enclave_id, &status,
  376. reinterpret_cast<sgx_measurement_t*>(mrenclave),
  377. &mrsigner,
  378. reinterpret_cast<sgx_attributes_t*>(se_attributes),
  379. reinterpret_cast<token_t*>(lictoken));
  380. }
  381. AESM_DBG_INFO("token request returned with ret = %d, status = %d", ret, status);
  382. if(SGX_SUCCESS!=ret)
  383. return sgx_error_to_ae_error(ret);
  384. if (status == LE_WHITELIST_UNINITIALIZED_ERROR || status == LE_INVALID_PRIVILEGE_ERROR){
  385. start_white_list_thread(0);//try to query white list unblocking
  386. }
  387. if(is_ufd()){
  388. reinterpret_cast<token_t*>(lictoken)->body.valid = 0;
  389. }
  390. return status;
  391. }