LEClass.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Copyright (C) 2011-2016 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. 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);
  38. #include "launch_enclave_u.h"
  39. #include "launch_enclave_u.c"
  40. int CLEClass::white_list_register(
  41. const uint8_t *white_list_cert,
  42. uint32_t white_list_cert_size,
  43. bool save_to_persistent_storage)
  44. {
  45. sgx_status_t ret = SGX_SUCCESS;
  46. int retry = 0;
  47. uint32_t status = 0;
  48. assert(m_enclave_id);
  49. ret = le_init_white_list_wrapper(m_enclave_id, &status,
  50. const_cast<uint8_t*>(white_list_cert),
  51. white_list_cert_size);
  52. for(; ret == SGX_ERROR_ENCLAVE_LOST && retry < AESM_RETRY_COUNT; retry++)
  53. {
  54. unload_enclave();
  55. if(AE_SUCCESS != load_enclave_only())
  56. return AE_FAILURE;
  57. ret = le_init_white_list_wrapper(m_enclave_id, &status,
  58. const_cast<uint8_t*>(white_list_cert),
  59. white_list_cert_size);
  60. }
  61. if(SGX_SUCCESS!=ret)
  62. return sgx_error_to_ae_error(ret);
  63. AESM_DBG_TRACE("le_init_white_list_wrapper return %d",status);
  64. if(AE_SUCCESS == status&&save_to_persistent_storage){//successfully register the white list cert
  65. 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
  66. AESM_DBG_WARN("Fail to save white list cert in persistent storage");
  67. }
  68. }
  69. return status;
  70. }
  71. void CLEClass::load_white_cert_list()
  72. {
  73. load_verified_white_cert_list();
  74. load_white_cert_list_to_be_verify();//If this version is older than previous one, it will not be loaded
  75. }
  76. ae_error_t CLEClass::load_verified_white_cert_list()
  77. {
  78. ae_error_t ae_err;
  79. uint32_t white_cert_size=0;
  80. ae_err = aesm_query_data_size(FT_PERSISTENT_STORAGE, AESM_WHITE_LIST_CERT_FID, &white_cert_size);
  81. if(AE_SUCCESS == ae_err && white_cert_size ==0){//file not existing or 0 size
  82. AESM_DBG_TRACE("no white cert list available in persistent storage");
  83. return AE_SUCCESS;
  84. }
  85. if(AE_SUCCESS != ae_err)
  86. return ae_err;
  87. uint8_t *p = (uint8_t *)malloc(white_cert_size);
  88. if(NULL == p){
  89. AESM_DBG_ERROR("out of memory");
  90. return AE_OUT_OF_MEMORY_ERROR;
  91. }
  92. ae_err = aesm_read_data(FT_PERSISTENT_STORAGE, AESM_WHITE_LIST_CERT_FID, p, &white_cert_size);
  93. if(AE_SUCCESS != ae_err){
  94. AESM_DBG_WARN("Fail to read white cert list file");
  95. free(p);
  96. return ae_err;
  97. }
  98. ae_err = (ae_error_t)white_list_register(p, white_cert_size,false);//Need not save the data to file again
  99. if(AE_SUCCESS!=ae_err){
  100. AESM_DBG_WARN("fail to register white cert list file in persistent storage");
  101. }
  102. free(p);
  103. return ae_err;
  104. }
  105. //This function must be called after white list cert has been verified and the file may overwrite the original one
  106. ae_error_t CLEClass::load_white_cert_list_to_be_verify()
  107. {
  108. ae_error_t ae_err;
  109. uint32_t white_cert_size=0;
  110. ae_err = aesm_query_data_size(FT_PERSISTENT_STORAGE, AESM_WHITE_LIST_CERT_TO_BE_VERIFY_FID, &white_cert_size);
  111. if(AE_SUCCESS != ae_err || white_cert_size ==0){//file not existing or 0 size
  112. AESM_DBG_TRACE("no white cert list to be verify in persistent storage");
  113. return AE_SUCCESS;
  114. }
  115. uint8_t *p = (uint8_t *)malloc(white_cert_size);
  116. if(NULL == p){
  117. AESM_DBG_ERROR("out of memory");
  118. return AE_OUT_OF_MEMORY_ERROR;
  119. }
  120. ae_err = aesm_read_data(FT_PERSISTENT_STORAGE, AESM_WHITE_LIST_CERT_TO_BE_VERIFY_FID, p, &white_cert_size);
  121. if(AE_SUCCESS != ae_err){
  122. AESM_DBG_WARN("Fail to read white cert list file");
  123. free(p);
  124. return ae_err;
  125. }
  126. 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
  127. if(AE_SUCCESS!=ae_err){
  128. AESM_DBG_WARN("fail to register white cert list file in persistent storage");
  129. }
  130. {//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
  131. char white_list_to_be_verify_path_name[MAX_PATH];
  132. 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);
  133. if(AE_SUCCESS == ae_err){
  134. se_delete_tfile(white_list_to_be_verify_path_name);
  135. }
  136. }
  137. free(p);
  138. return ae_err;
  139. }
  140. ae_error_t CLEClass::load_enclave_only()
  141. {
  142. before_enclave_load();
  143. assert(m_enclave_id==0);
  144. sgx_status_t ret;
  145. ae_error_t ae_err;
  146. char prod_css_path[MAX_PATH]={0};
  147. char enclave_path[MAX_PATH]= {0};
  148. char *p_prod_css_path = prod_css_path;
  149. int production_le_loaded = 0;
  150. if((ae_err = aesm_get_pathname(FT_PERSISTENT_STORAGE, LE_PROD_SIG_STRUCT_FID, prod_css_path, MAX_PATH))!=AE_SUCCESS){
  151. AESM_DBG_WARN("fail to get production sig struction of LE");
  152. p_prod_css_path = NULL;
  153. }
  154. if((ae_err = aesm_get_pathname(FT_ENCLAVE_NAME, get_enclave_fid(), enclave_path,//get non-production signed LE pathname
  155. MAX_PATH))
  156. !=AE_SUCCESS){
  157. AESM_DBG_ERROR("fail to get LE pathname");
  158. return ae_err;
  159. }
  160. int launch_token_update;
  161. #ifdef AESM_SIM
  162. UNUSED(p_prod_css_path);
  163. UNUSED(production_le_loaded);
  164. ret = sgx_create_enclave(enclave_path, get_debug_flag(), &m_launch_token,
  165. &launch_token_update, &m_enclave_id,
  166. &m_attributes);//simulation mode has no sgx_create_le function. Use sgx_create_enclave
  167. if(ret != SGX_SUCCESS){
  168. AESM_DBG_ERROR("Fail to load LE");
  169. return AE_FAILURE;
  170. }
  171. return AE_SUCCESS;
  172. #else
  173. ret = sgx_create_le(enclave_path, p_prod_css_path, get_debug_flag(), &m_launch_token,
  174. &launch_token_update, &m_enclave_id,
  175. &m_attributes, &production_le_loaded);
  176. if (ret == SGX_ERROR_NO_DEVICE){
  177. AESM_DBG_ERROR("AE SERVER NOT AVAILABLE in load non-production signed LE: %s",enclave_path);
  178. return AE_SERVER_NOT_AVAILABLE;
  179. }
  180. if (ret != SGX_SUCCESS){
  181. AESM_DBG_ERROR("Loading LE failed:%d",ret);
  182. return AE_FAILURE;
  183. }else if(production_le_loaded!=0){//production signed LE loaded
  184. AESM_DBG_INFO("Production signed LE loaded, try loading white list now");
  185. }else{
  186. AESM_DBG_INFO("Debug signed LE loaded");
  187. }
  188. return AE_SUCCESS;
  189. #endif
  190. }
  191. ae_error_t CLEClass::load_enclave()
  192. {
  193. if(m_enclave_id){//LE has been loaded before
  194. return AE_SUCCESS;
  195. }
  196. ae_error_t ae_err = load_enclave_only();
  197. if( AE_SUCCESS == ae_err){
  198. load_white_cert_list();
  199. }
  200. return ae_err;
  201. }
  202. int CLEClass::get_launch_token(
  203. uint8_t * mrenclave, uint32_t mrenclave_size,
  204. uint8_t *public_key, uint32_t public_key_size,
  205. uint8_t *se_attributes, uint32_t se_attributes_size,
  206. uint8_t * lictoken, uint32_t lictoken_size
  207. )
  208. {
  209. sgx_status_t ret = SGX_SUCCESS;
  210. int retry = 0;
  211. int status = 0;
  212. assert(m_enclave_id);
  213. sgx_measurement_t mrsigner;
  214. if(mrenclave_size !=sizeof(sgx_measurement_t) ||
  215. SE_KEY_SIZE != public_key_size ||
  216. se_attributes_size != sizeof(sgx_attributes_t) ||
  217. lictoken_size < sizeof(token_t) )
  218. return LE_INVALID_PARAMETER;
  219. //set mrsigner based on the hash of isv pub key from enclave signature
  220. IppStatus ipperrorCode = ippStsNoErr;
  221. ipperrorCode = ippsHashMessage(reinterpret_cast<const Ipp8u *>(public_key), public_key_size, reinterpret_cast<Ipp8u *>(&mrsigner), IPP_ALG_HASH_SHA256);
  222. if( ipperrorCode != ippStsNoErr){
  223. return AE_FAILURE;
  224. }
  225. #ifdef DBG_LOG
  226. char mrsigner_info[256];
  227. aesm_dbg_format_hex((uint8_t *)&mrsigner, sizeof(mrsigner), mrsigner_info, 256);
  228. AESM_DBG_INFO("try to load Enclave with mrsigner:%s",mrsigner_info);
  229. #endif
  230. //get launch token by ecall into LE
  231. ret = le_get_launch_token_wrapper(m_enclave_id, &status,
  232. reinterpret_cast<sgx_measurement_t*>(mrenclave),
  233. &mrsigner,
  234. reinterpret_cast<sgx_attributes_t*>(se_attributes),
  235. reinterpret_cast<token_t*>(lictoken));
  236. for(; ret == SGX_ERROR_ENCLAVE_LOST && retry < AESM_RETRY_COUNT; retry++)
  237. {
  238. unload_enclave();
  239. if(AE_SUCCESS != load_enclave())
  240. return AE_FAILURE;
  241. ret = le_get_launch_token_wrapper(m_enclave_id, &status,
  242. reinterpret_cast<sgx_measurement_t*>(mrenclave),
  243. &mrsigner,
  244. reinterpret_cast<sgx_attributes_t*>(se_attributes),
  245. reinterpret_cast<token_t*>(lictoken));
  246. }
  247. if(SGX_SUCCESS!=ret)
  248. return sgx_error_to_ae_error(ret);
  249. return status;
  250. }