pve_logic.cpp 16 KB

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