pve_logic.cpp 17 KB

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