pve_logic.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  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 "pve_logic.h"
  32. #include "aesm_logic.h"
  33. #include "PVEClass.h"
  34. #include "QEClass.h"
  35. #include "PCEClass.h"
  36. #include "oal/oal.h"
  37. #include "aesm_epid_blob.h"
  38. #include "se_wrapper.h"
  39. #include "prov_msg_size.h"
  40. #include "network_encoding_wrapper.h"
  41. #include "prof_fun.h"
  42. #include "aesm_long_lived_thread.h"
  43. #include "endpoint_select_info.h"
  44. #include <assert.h>
  45. #define SAFE_FREE(ptr) {if (NULL != (ptr)) {free(ptr); (ptr)=NULL;}}
  46. //Function to continue process Provisioning logic when the response of ProvMsg1 is ProvMsg2
  47. ae_error_t PvEAESMLogic::process_pve_msg2(pve_data_t& data, const uint8_t* msg2, uint32_t msg2_size, const endpoint_selection_infos_t& es_info)
  48. {
  49. uint32_t msg_size = 0;
  50. uint8_t *msg = NULL;
  51. uint8_t *resp_msg = NULL;
  52. uint32_t resp_size = 0;
  53. epid_blob_with_cur_psvn_t epid_data;
  54. ae_error_t ret = AE_SUCCESS;
  55. AESM_PROFILE_FUN;
  56. AESM_DBG_DEBUG("enter fun");
  57. AESM_DBG_TRACE("processing msg2 whose length is %d",msg2_size);
  58. memset(&epid_data, 0, sizeof(epid_data));
  59. if(EPIDBlob::instance().read(epid_data)!=AE_SUCCESS){
  60. //First try to read existing EPID Blob to get old epid blob
  61. //error code of reading epid blob will be ignored since old epid blob is optional
  62. AESM_DBG_TRACE("read old epid blob fail");
  63. }else{
  64. AESM_DBG_TRACE("succ read old epid blob");
  65. }
  66. msg_size = estimate_msg3_size_by_msg2_size(msg2_size); //estimate an upbound for msg3 size
  67. AESM_DBG_TRACE("estimate msg3 size: %d",msg_size);
  68. assert(msg_size > 0);
  69. msg = static_cast<uint8_t *>(malloc(msg_size));
  70. if(msg == NULL){
  71. AESM_DBG_ERROR("malloc failed");
  72. ret = AE_OUT_OF_MEMORY_ERROR;
  73. goto CLEANUP;
  74. }
  75. memset(msg, 0, msg_size);
  76. AESM_DBG_TRACE("start processing msg2 and gen msg3");
  77. ret = static_cast<ae_error_t>(CPVEClass::instance().proc_prov_msg2(data, msg2, msg2_size,
  78. epid_data.trusted_epid_blob, SGX_TRUSTED_EPID_BLOB_SIZE_SDK,//discard curpsvn in epid blob
  79. msg, msg_size));//with help of PvE, process ProvMsg2 and generate ProvMsg3
  80. if(ret == AE_SUCCESS){
  81. if(GET_SIZE_FROM_PROVISION_REQUEST(msg)>msg_size){
  82. AESM_DBG_ERROR("prov msg2 size %d is larger than buffer size %d", GET_SIZE_FROM_PROVISION_REQUEST(msg), msg_size);
  83. ret = PVE_UNEXPECTED_ERROR;
  84. goto CLEANUP;
  85. }
  86. AESM_DBG_TRACE("Start send msg3 and recv msg4");
  87. msg_size = static_cast<uint32_t>(GET_SIZE_FROM_PROVISION_REQUEST(msg));//get the real size of ProvMsg3
  88. ret = AESMNetworkEncoding::aesm_send_recv_msg_encoding(es_info.provision_url,
  89. msg, msg_size, resp_msg, resp_size); //Encoding ProvMsg3, send to server, receive ProvMsg4 and decode
  90. if(ret != AE_SUCCESS){
  91. AESM_LOG_ERROR("%s",g_event_string_table[SGX_EVENT_EPID_PROV_FAILURE]);
  92. AESM_DBG_WARN("send prov msg3 via network failed:(ae%d)",ret);
  93. goto CLEANUP;
  94. }
  95. assert(resp_msg!=NULL);
  96. AESM_DBG_TRACE("Start to proc msg4");
  97. ret = process_pve_msg4(data, resp_msg, resp_size);//The response msg must be ProvMsg4, process it to generate EPIDBlob
  98. if(ret != AE_SUCCESS){
  99. AESM_DBG_TRACE("processing msg4 failed:(ae%d)",ret);
  100. goto CLEANUP;
  101. }
  102. ret = AE_SUCCESS;
  103. AESM_DBG_TRACE("processing msg4 succ");
  104. }else{
  105. AESM_DBG_WARN("fail to process prov msg2:(ae%d)",ret);
  106. }
  107. CLEANUP:
  108. SAFE_FREE(msg);
  109. if(resp_msg!=NULL)
  110. AESMNetworkEncoding::aesm_free_response_msg(resp_msg);
  111. return ret;
  112. }
  113. //Function to finish the Provisioning Logic when a ProvMsg4 is expected or encountered
  114. ae_error_t PvEAESMLogic::process_pve_msg4(const pve_data_t& data, const uint8_t* msg4, uint32_t msg4_size)
  115. {
  116. AESM_PROFILE_FUN;
  117. epid_blob_with_cur_psvn_t epid_data;
  118. ae_error_t ret = AE_SUCCESS;
  119. AESM_DBG_DEBUG("enter fun");
  120. AESM_DBG_TRACE("processing msg4 with size %d",msg4_size);
  121. memset(&epid_data, 0, sizeof(epid_data));
  122. //with the help of PvE to process ProvMsg4 and generate EPIDDataBlob
  123. if((ret = static_cast<ae_error_t>(CPVEClass::instance().proc_prov_msg4(data, msg4, msg4_size,
  124. epid_data.trusted_epid_blob, SGX_TRUSTED_EPID_BLOB_SIZE_SDK)))!=AE_SUCCESS){
  125. AESM_DBG_WARN("proc prov msg4 fail:(ae%d)",ret);
  126. goto fini;
  127. }
  128. if(0!=memcpy_s(&epid_data.cur_pi, sizeof(epid_data.cur_pi),
  129. &data.bpi, sizeof(data.bpi))){
  130. AESM_DBG_ERROR("memcpy failed");
  131. ret = PVE_UNEXPECTED_ERROR;
  132. goto fini;
  133. }
  134. #ifdef DBG_LOG
  135. char dbg_str[256];
  136. aesm_dbg_format_hex(reinterpret_cast<const uint8_t *>(&epid_data), sizeof(epid_data), dbg_str, 256);
  137. AESM_DBG_TRACE("write epid_data=%s",dbg_str);
  138. #endif
  139. ret=EPIDBlob::instance().write(epid_data);//save the data into persistent data storage
  140. if(AE_SUCCESS!=ret){
  141. AESM_DBG_WARN("fail to write epid_data:(ae%d)",ret);
  142. }
  143. fini:
  144. return (ae_error_t)ret;
  145. }
  146. //Function to process the Provisioning Logic for backup retrieval of old epid data blob
  147. //The function assumes that the PvE state has been IDLE
  148. ae_error_t PvEAESMLogic::update_old_blob(pve_data_t& data, const endpoint_selection_infos_t& es_info)
  149. {
  150. uint32_t msg_size = 0;
  151. uint8_t *msg = NULL;
  152. uint32_t ae_ret = AE_SUCCESS;
  153. uint8_t *resp_msg = NULL;
  154. uint32_t resp_size = 0;
  155. AESM_PROFILE_FUN;
  156. AESM_DBG_DEBUG("enter fun");
  157. msg_size = estimate_msg1_size(false);
  158. assert(msg_size > 0);
  159. msg = static_cast<uint8_t *>(malloc(msg_size));
  160. if(msg == NULL){
  161. AESM_DBG_ERROR("malloc fail");
  162. ae_ret = AE_OUT_OF_MEMORY_ERROR;
  163. goto ret_point;
  164. }
  165. memset(msg, 0, msg_size);
  166. AESM_DBG_TRACE("start to gen prov msg1, estimate size %d", msg_size);
  167. data.is_backup_retrieval = true;
  168. data.is_performance_rekey = false;
  169. ae_ret = CPVEClass::instance().gen_prov_msg1(data, msg, msg_size);//generate ProvMsg1
  170. if (ae_ret != AE_SUCCESS)
  171. {
  172. AESM_DBG_WARN("gen prov msg1 failed:(ae%d)",ae_ret);
  173. goto ret_point;
  174. }
  175. msg_size = static_cast<uint32_t>(GET_SIZE_FROM_PROVISION_REQUEST(msg));
  176. AESM_DBG_TRACE("start to send msg1 to server and recv msg4");
  177. ae_ret = AESMNetworkEncoding::aesm_send_recv_msg_encoding(es_info.provision_url,
  178. msg, msg_size, resp_msg,resp_size);//encoding/send/receive/decoding
  179. if(ae_ret != AE_SUCCESS){
  180. AESM_LOG_ERROR("%s",g_event_string_table[SGX_EVENT_EPID_PROV_FAILURE]);
  181. AESM_DBG_WARN("send prov msg1 via network failed:%d",ae_ret);
  182. goto ret_point;
  183. }
  184. assert(resp_msg != NULL);
  185. if (resp_size < PROVISION_RESPONSE_HEADER_SIZE) {
  186. AESM_DBG_WARN("response message %d too small",resp_size);
  187. ae_ret = PVE_UNEXPECTED_ERROR;
  188. goto ret_point;
  189. }
  190. AESM_DBG_TRACE("start to send msg4 to server");
  191. if(GET_TYPE_FROM_PROVISION_RESPONSE(resp_msg) == TYPE_PROV_MSG4){
  192. ae_ret = process_pve_msg4(data, resp_msg, resp_size);//process ProvMsg4 and generated/save EPID Data Blob
  193. AESM_DBG_TRACE("msg4 processing finished, status (ae%d)",ae_ret);
  194. }else{
  195. AESM_DBG_WARN("response message is not prov msg4");
  196. ae_ret = PVE_UNEXPECTED_ERROR;
  197. }
  198. ret_point:
  199. if(msg)free(msg);
  200. if(resp_msg!=NULL){
  201. AESMNetworkEncoding::aesm_free_response_msg(resp_msg);
  202. }
  203. return (ae_error_t)ae_ret;
  204. }
  205. aesm_error_t PvEAESMLogic::pve_error_postprocess(ae_error_t ae_error)
  206. {
  207. switch(ae_error){
  208. case AE_SUCCESS:
  209. return AESM_SUCCESS;
  210. case OAL_NETWORK_UNAVAILABLE_ERROR:
  211. {
  212. AESM_LOG_FATAL("%s", g_event_string_table[SGX_EVENT_EPID_PROV_FAILURE]);
  213. return AESM_NETWORK_ERROR;
  214. }
  215. case OAL_THREAD_TIMEOUT_ERROR:
  216. return AESM_BUSY;
  217. case OAL_NETWORK_BUSY:
  218. return AESM_NETWORK_BUSY_ERROR;
  219. case OAL_PROXY_SETTING_ASSIST:
  220. return AESM_PROXY_SETTING_ASSIST;
  221. case OAL_FILE_ACCESS_ERROR:
  222. case OAL_CONFIG_FILE_ERROR:
  223. return AESM_FILE_ACCESS_ERROR;
  224. case PVE_PARAMETER_ERROR:
  225. case AE_INVALID_PARAMETER:
  226. case OAL_PARAMETER_ERROR:
  227. return AESM_PARAMETER_ERROR;
  228. case PVE_EPIDBLOB_ERROR:
  229. return AESM_EPIDBLOB_ERROR;
  230. case AE_ENCLAVE_LOST:
  231. return AESM_NO_DEVICE_ERROR;
  232. case AE_SERVER_NOT_AVAILABLE:
  233. return AESM_SERVICE_UNAVAILABLE;
  234. case PVE_INTEGRITY_CHECK_ERROR:
  235. {
  236. AESM_LOG_FATAL("%s", g_event_string_table[SGX_EVENT_EPID_PROV_INTEGRITY_ERROR]);
  237. return AESM_SGX_PROVISION_FAILED;
  238. }
  239. case PVE_SIGRL_INTEGRITY_CHECK_ERROR:
  240. {
  241. AESM_LOG_FATAL("%s", g_event_string_table[SGX_EVENT_EPID20_SIGRL_INTEGRITY_ERROR]);
  242. return AESM_SGX_PROVISION_FAILED;
  243. }
  244. case PVE_SERVER_REPORTED_ERROR:
  245. case PVE_MSG_ERROR:
  246. return AESM_SGX_PROVISION_FAILED;
  247. case PVE_REVOKED_ERROR:
  248. return AESM_EPID_REVOKED_ERROR;
  249. case PVE_SERVER_BUSY_ERROR:
  250. return AESM_BACKEND_SERVER_BUSY;
  251. case PVE_PROV_ATTEST_KEY_NOT_FOUND:
  252. return AESM_UNRECOGNIZED_PLATFORM;
  253. case AE_OUT_OF_MEMORY_ERROR:
  254. return AESM_OUT_OF_MEMORY_ERROR;
  255. case PSW_UPDATE_REQUIRED:
  256. return AESM_UPDATE_AVAILABLE;
  257. case AESM_AE_OUT_OF_EPC:
  258. return AESM_OUT_OF_EPC;
  259. default:
  260. return AESM_UNEXPECTED_ERROR;
  261. }
  262. }
  263. aesm_error_t PvEAESMLogic::provision(bool performance_rekey_used, uint32_t timeout_usec)
  264. {
  265. ae_error_t ae_ret = AE_SUCCESS;
  266. AESM_PROFILE_FUN;
  267. AESM_DBG_DEBUG("enter fun");
  268. AESM_DBG_TRACE("start end point selection");
  269. ae_ret = start_epid_provision_thread(performance_rekey_used, timeout_usec);
  270. return pve_error_postprocess(ae_ret);
  271. }
  272. static void log_provision_result(ae_error_t ae_ret)
  273. {
  274. // Log provisioning results to the Admin Log
  275. switch (ae_ret) {
  276. case AE_SUCCESS:
  277. AESM_LOG_INFO_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_EPID_PROV_SUCCESS]);
  278. break;
  279. case OAL_NETWORK_UNAVAILABLE_ERROR:
  280. AESM_LOG_ERROR_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_EPID_PROV_FAIL_NW]);
  281. break;
  282. case PSW_UPDATE_REQUIRED:
  283. AESM_LOG_ERROR_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_EPID_PROV_FAIL_PSWVER]);
  284. break;
  285. case PVE_REVOKED_ERROR:
  286. AESM_LOG_ERROR_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_EPID_PROV_FAIL_REVOKED]);
  287. break;
  288. case OAL_PROXY_SETTING_ASSIST://do not log for proxy assist and thread time out error
  289. case OAL_THREAD_TIMEOUT_ERROR:
  290. break;
  291. default:
  292. AESM_LOG_ERROR_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_EPID_PROV_FAIL]);
  293. break;
  294. }
  295. }
  296. ae_error_t PvEAESMLogic::epid_provision_thread_func(bool performance_rekey_used)
  297. {
  298. uint32_t msg_size = 0;
  299. uint8_t *msg = NULL;
  300. uint8_t *resp_msg = NULL;
  301. uint32_t resp_size = 0;
  302. ae_error_t ae_ret = AE_SUCCESS;
  303. uint32_t repeat = 0;
  304. endpoint_selection_infos_t es_info;
  305. pve_data_t pve_data;
  306. AESM_LOG_INFO_ADMIN("%s", g_admin_event_string_table[SGX_ADMIN_EVENT_EPID_PROV_START]);
  307. memset(&pve_data, 0, sizeof(pve_data));
  308. if(AE_SUCCESS!=(ae_ret=aesm_start_request_wake_execution())){
  309. AESM_DBG_ERROR("fail to request wake execution:(ae%d)", ae_ret);
  310. log_provision_result(ae_ret);
  311. return ae_ret;
  312. }
  313. AESM_DBG_TRACE("start end point selection");
  314. if((ae_ret = EndpointSelectionInfo::instance().start_protocol(es_info))!=AE_SUCCESS){//EndPoint Selection Protocol to setup Provisioning URL
  315. (void)aesm_stop_request_wake_execution();
  316. AESM_DBG_WARN("end point selection failed:(ae%d)",ae_ret);
  317. log_provision_result(ae_ret);
  318. return ae_ret;
  319. }
  320. //If enclave_lost encountered(such as S3/S4 reached, the retry will be increased by 1, for other kinds of exception like network error, repeat is increased by 1)
  321. while(repeat < AESM_RETRY_COUNT){
  322. //estimate upbound of ProvMsg1 and alloc memory for it
  323. msg_size = estimate_msg1_size(performance_rekey_used);
  324. AESM_DBG_TRACE("estimate msg1 size :%d",msg_size);
  325. assert(msg_size > 0);
  326. if(msg!=NULL)free(msg);
  327. msg = (uint8_t *)malloc(msg_size);
  328. if(msg == NULL){
  329. AESM_DBG_TRACE("malloc failed");
  330. ae_ret = AE_OUT_OF_MEMORY_ERROR;
  331. break;
  332. }
  333. memset(msg, 0, msg_size);
  334. //Generate ProvMsg1
  335. pve_data.is_backup_retrieval = false;
  336. pve_data.is_performance_rekey = performance_rekey_used;
  337. if(0!=memcpy_s(&pve_data.pek, sizeof(pve_data.pek), &es_info.pek, sizeof(es_info.pek))){
  338. AESM_DBG_ERROR("memcpy error");
  339. ae_ret = AE_FAILURE;
  340. break;
  341. }
  342. ae_ret = static_cast<ae_error_t>(CPVEClass::instance().gen_prov_msg1(pve_data, msg, msg_size));//Generate ProvMsg1
  343. if (ae_ret != AE_SUCCESS)
  344. {
  345. AESM_DBG_WARN("fail to generate prov msg1:(ae%d)",ae_ret);
  346. break;
  347. }
  348. assert( msg != NULL && GET_SIZE_FROM_PROVISION_REQUEST(msg) >= PROVISION_REQUEST_HEADER_SIZE);
  349. msg_size = static_cast<uint32_t>(GET_SIZE_FROM_PROVISION_REQUEST(msg));
  350. AESM_DBG_TRACE("msg1 generated with size %d",msg_size);
  351. if(resp_msg!=NULL){
  352. AESMNetworkEncoding::aesm_free_response_msg(resp_msg);
  353. resp_msg=NULL;
  354. }
  355. AESM_DBG_TRACE("start to send prov msg1 and recv response");
  356. ae_ret = AESMNetworkEncoding::aesm_send_recv_msg_encoding(es_info.provision_url,
  357. msg,msg_size, resp_msg, resp_size);//encoding/send ProvMsg1, receiving and decoding resp message
  358. if(ae_ret != AE_SUCCESS){
  359. AESM_DBG_WARN("send msg1 via network fail:(ae%d)",ae_ret);
  360. break;//aesm_send_recv_se_msg will not return AE_ENCLAVE_LOST
  361. }
  362. assert (resp_msg != NULL && resp_size >= PROVISION_RESPONSE_HEADER_SIZE);
  363. if(GET_TYPE_FROM_PROVISION_RESPONSE(resp_msg) == TYPE_PROV_MSG2){//If responsed msg is ProvMsg2
  364. AESM_DBG_TRACE("start to process prov msg2, size %d", resp_size);
  365. ae_ret = process_pve_msg2(pve_data, resp_msg, resp_size, es_info);//processing following flow if response message is ProvMsg2
  366. if(ae_ret != AE_SUCCESS){
  367. if(ae_ret == PVE_EPIDBLOB_ERROR){//If it reports old EPID Blob Error
  368. AESM_DBG_TRACE("retrieve old epid blob");
  369. if((ae_ret = update_old_blob(pve_data, es_info))!=AE_SUCCESS){//try to retrieve old EPID blob from backend server
  370. AESM_DBG_WARN("fail to retrieve old epid blob:(ae%d)",ae_ret);
  371. break;
  372. }else{
  373. AESM_DBG_TRACE("retrieve old epid blob successfully");
  374. ae_ret = AE_FAILURE;//set to failure
  375. repeat++;//only retry after update old epid blob
  376. continue;
  377. }
  378. }else{
  379. AESM_DBG_WARN("processing prov msg2 failed:(ae%d)",ae_ret);
  380. break;
  381. }
  382. }
  383. }else if(GET_TYPE_FROM_PROVISION_RESPONSE(resp_msg) == TYPE_PROV_MSG4){
  384. AESM_DBG_TRACE("start to process prov msg4 for current psvn");
  385. if((ae_ret = process_pve_msg4(pve_data, resp_msg,resp_size))!=AE_SUCCESS){//process ProvMsg4 to generate EPID blob if resp is Msg4
  386. AESM_DBG_WARN("fail to process prov msg4:(ae%d)",ae_ret);
  387. break;
  388. }
  389. }else{
  390. AESM_DBG_ERROR("Invalid resp msg type from backend server:%d",(int)GET_TYPE_FROM_PROVISION_RESPONSE(resp_msg));
  391. ae_ret = AE_FAILURE;
  392. break;
  393. }
  394. AESM_DBG_TRACE("provisioning succ");
  395. ae_ret = AE_SUCCESS;
  396. break;
  397. }
  398. SAFE_FREE(msg);
  399. if(resp_msg!=NULL){
  400. AESMNetworkEncoding::aesm_free_response_msg(resp_msg);
  401. }
  402. (void)aesm_stop_request_wake_execution();
  403. log_provision_result(ae_ret);
  404. return ae_ret;
  405. }