endpoint_select_info.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  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 "endpoint_select_info.h"
  32. #include "PVEClass.h"
  33. #include "prov_msg_size.h"
  34. #include "network_encoding_wrapper.h"
  35. #include "ipp_wrapper.h"
  36. #include "sgx_tcrypto.h"
  37. #include "ippcp.h"
  38. #include "ippcore.h"
  39. #include "sgx_read_rand.h"
  40. #include "se_wrapper.h"
  41. #include <time.h>
  42. //Function to do basic checking of the endpoint selection blob. Esp to avoid no zero-ending in the input string url
  43. static bool is_valid_endpoint_selection_info(const endpoint_selection_infos_t& es_info)
  44. {
  45. if(es_info.aesm_data_type != AESM_DATA_ENDPOINT_SELECTION_INFOS)
  46. return false;
  47. if(es_info.aesm_data_version != AESM_DATA_ENDPOINT_SELECTION_VERSION)
  48. return false;
  49. if(strnlen(es_info.provision_url,MAX_PATH)>=MAX_PATH)
  50. return false;
  51. return true;
  52. }
  53. ae_error_t EndpointSelectionInfo::read_pek(endpoint_selection_infos_t& es_info)
  54. {
  55. ae_error_t ae_err=AE_SUCCESS;
  56. uint32_t es_info_size = sizeof(es_info);
  57. ae_err = aesm_read_data(FT_PERSISTENT_STORAGE, PROVISION_PEK_BLOB_FID, reinterpret_cast<uint8_t *>(&es_info), &es_info_size);
  58. if(AE_SUCCESS == ae_err && (es_info_size != sizeof(es_info)||!is_valid_endpoint_selection_info(es_info))){
  59. AESM_DBG_ERROR("Invalid ES result in persistent storage:size %d, expected size %d", es_info_size, sizeof(es_info));
  60. ae_err = OAL_FILE_ACCESS_ERROR;
  61. }
  62. if(AE_SUCCESS == ae_err){
  63. AESM_DBG_INFO("Read ES result from persistent storage successfully");
  64. }else{
  65. AESM_DBG_WARN("ES result in persistent storage failed to load:%d", ae_err);
  66. }
  67. return ae_err;
  68. }
  69. ae_error_t EndpointSelectionInfo::write_pek(const endpoint_selection_infos_t& es_info)
  70. {
  71. return aesm_write_data(FT_PERSISTENT_STORAGE, PROVISION_PEK_BLOB_FID, reinterpret_cast<const uint8_t *>(&es_info), sizeof(es_info));
  72. }
  73. static ae_error_t ipp_error_to_ae_error(IppStatus ipp_status)
  74. {
  75. if(ipp_status == ippStsNoErr) return AE_SUCCESS;
  76. else if(ipp_status == ippStsMemAllocErr||
  77. ipp_status == ippStsNoMemErr) return AE_OUT_OF_MEMORY_ERROR;
  78. else return AE_FAILURE;//unknown or unexpected ipp error
  79. }
  80. ae_error_t aesm_check_pek_signature(const signed_pek_t& signed_pek);
  81. IppStatus get_provision_server_rsa_pub_key_in_ipp_format(const signed_pek_t& pek, IppsRSAPublicKeyState **rsa_pub_key);
  82. //The function is to verify the PEK ECDSA Signature and RSA Signature for ES Msg2
  83. // When PvE uses PEK, it will re-check the ECDSA Signature
  84. //The function will only be called after ES protocol is completed. But it will not be called when reading data back from persitent storage
  85. //@param provision_ttl: The TTL field from ES Msg2 in little endian format
  86. //@param rsa_signature: The RSA Signature in ES Msg2, it is RSA Signature to XID:TTL:provision_url
  87. //@param xid: The transaction id (XID) of the ES Protocol
  88. //@return AE_SUCCESS if signature verification success and passed
  89. //@return PVE_MSG_ERROR if signature verification failed or message error
  90. //other kinds of error code could be returned too due to corresponding error situation
  91. ae_error_t EndpointSelectionInfo::verify_signature(const endpoint_selection_infos_t& es_info, uint8_t xid[XID_SIZE], uint8_t rsa_signature[PVE_RSA_KEY_BYTES], uint16_t provision_ttl)
  92. {
  93. //Do signature verification here
  94. ae_error_t ae_err = AE_SUCCESS;
  95. IppsRSAPublicKeyState *rsa_pub_key = NULL;
  96. Ipp8u *buffer = NULL;
  97. int public_key_buffer_size = 0;
  98. int vr = 0;
  99. uint16_t ttl=_htons(provision_ttl);
  100. IppStatus ipp_status = ippStsNoErr;
  101. uint8_t msg_buf[XID_SIZE + sizeof(ttl) + MAX_PATH];
  102. uint32_t buf_size = 0;
  103. ae_err = aesm_check_pek_signature(es_info.pek);
  104. if(AE_SUCCESS != ae_err){
  105. AESM_DBG_ERROR("PEK Signature verifcation not passed:%d",ae_err);
  106. goto ret_point;
  107. }
  108. AESM_DBG_INFO("PEK signature verified successfully");
  109. buf_size = XID_SIZE +static_cast<uint32_t>(sizeof(ttl) + strnlen_s(es_info.provision_url, MAX_PATH));
  110. if(0!=memcpy_s(msg_buf,sizeof(msg_buf), xid, XID_SIZE)||
  111. 0!=memcpy_s(msg_buf+XID_SIZE, sizeof(ttl) + MAX_PATH, &ttl, sizeof(ttl))||
  112. 0!=memcpy_s(msg_buf+XID_SIZE+sizeof(ttl), MAX_PATH, es_info.provision_url, buf_size-XID_SIZE-sizeof(ttl))){
  113. ae_err = AE_FAILURE;
  114. AESM_DBG_ERROR("memcpy error");
  115. goto ret_point;
  116. }
  117. ipp_status = get_provision_server_rsa_pub_key_in_ipp_format(es_info.pek, &rsa_pub_key);
  118. if(ippStsNoErr != ipp_status){
  119. AESM_DBG_ERROR("Fail to load rsa public key from PEK:%d", ipp_status);
  120. ae_err = ipp_error_to_ae_error(ipp_status);
  121. goto ret_point;
  122. }
  123. ipp_status = ippsRSA_GetBufferSizePublicKey(&public_key_buffer_size, rsa_pub_key);
  124. if(ippStsNoErr != ipp_status){
  125. AESM_DBG_ERROR("Fail to get rsa public key size:%s", ipp_status);
  126. ae_err = ipp_error_to_ae_error(ipp_status);
  127. goto ret_point;
  128. }
  129. buffer = (Ipp8u *)malloc(public_key_buffer_size);
  130. if(NULL == buffer){
  131. AESM_DBG_ERROR("malloc error");
  132. ae_err = AE_OUT_OF_MEMORY_ERROR;
  133. goto ret_point;
  134. }
  135. ipp_status = ippsRSAVerify_PKCS1v15(msg_buf, buf_size, rsa_signature, &vr, rsa_pub_key, ippHashAlg_SHA256, buffer);
  136. if(ippStsNoErr != ipp_status){
  137. AESM_DBG_ERROR("Fail to verify rsa signature:%d", ipp_status);
  138. ae_err = ipp_error_to_ae_error(ipp_status);
  139. goto ret_point;
  140. }
  141. if(vr == 0){
  142. AESM_DBG_TRACE("rsa signature verification failed");
  143. ae_err = PVE_MSG_ERROR;
  144. goto ret_point;
  145. }else{
  146. AESM_DBG_TRACE("rsa signature verification passed");
  147. ae_err = AE_SUCCESS;
  148. }
  149. ret_point:
  150. if(NULL != rsa_pub_key){
  151. secure_free_rsa_pub_key(PVE_RSA_KEY_BYTES, sizeof(uint32_t), rsa_pub_key);
  152. }
  153. if(NULL != buffer){
  154. free(buffer);
  155. }
  156. return ae_err;
  157. }
  158. #define MAX_ENCLAVE_LOST_RETRY_TIME 1
  159. bool read_aesm_config(aesm_config_infos_t& infos);
  160. //Function to implement the end point selection protocol
  161. ae_error_t EndpointSelectionInfo::start_protocol(endpoint_selection_infos_t& es_info)
  162. {
  163. AESMLogicLock lock(_es_lock);
  164. uint32_t msg_size = 0;
  165. uint8_t *resp = NULL;
  166. uint32_t resp_size = 0;
  167. uint16_t provision_ttl = 0;
  168. uint8_t *msg = NULL;
  169. uint8_t rsa_signature[PVE_RSA_KEY_BYTES];
  170. gen_endpoint_selection_output_t enclave_output;
  171. ae_error_t ae_ret = AE_SUCCESS;
  172. uint32_t enclave_lost_count = 0;
  173. AESM_DBG_DEBUG("enter fun");
  174. memset(&es_info, 0, sizeof(es_info));
  175. memset(&enclave_output, 0, sizeof(enclave_output));
  176. if(!_is_server_url_loaded){
  177. (void) read_aesm_config(_server_urls);
  178. _is_server_url_loaded = true;
  179. }
  180. do{
  181. if((ae_ret = CPVEClass::instance().load_enclave())!=AE_SUCCESS){
  182. AESM_DBG_ERROR("Fail to load PVE enclave:%d", ae_ret);
  183. goto final_point;
  184. }
  185. //call PvE to generate the partition and xid
  186. ae_ret = static_cast<ae_error_t>(CPVEClass::instance().gen_es_msg1_data(&enclave_output));
  187. if(ae_ret == AE_ENCLAVE_LOST&& (++enclave_lost_count)<=MAX_ENCLAVE_LOST_RETRY_TIME ){
  188. CPVEClass::instance().unload_enclave();//unload and reload PvE when enclave lost encountered
  189. continue;
  190. }else if(ae_ret == AE_SUCCESS){
  191. break;
  192. }else{
  193. AESM_DBG_ERROR("fail to generate parition by PvE");
  194. goto final_point;
  195. }
  196. }while(1);
  197. AESM_DBG_TRACE("use parition %d from PvE", (int)enclave_output.selector_id);
  198. AESM_DBG_INFO("Connect to server url \"%s\" for endpoint selection", _server_urls.endpoint_url);
  199. msg_size = estimate_es_msg1_size();
  200. assert(msg_size>0);
  201. msg = reinterpret_cast<uint8_t *>(malloc(msg_size));
  202. if(msg == NULL){
  203. AESM_DBG_ERROR("malloc error");
  204. ae_ret = AE_OUT_OF_MEMORY_ERROR;
  205. goto final_point;
  206. }
  207. memset(msg, 0, msg_size);
  208. ae_ret = static_cast<ae_error_t>(CPVEClass::instance().gen_es_msg1(msg, msg_size, enclave_output));//Generate EndPoint Selection Msg1
  209. if(ae_ret != AE_SUCCESS){
  210. AESM_DBG_ERROR("ES msg1 generation failed:%d",ae_ret);
  211. goto final_point;
  212. }
  213. AESM_DBG_TRACE("ES msg1 generated");
  214. ae_ret = AESMNetworkEncoding::aesm_send_recv_msg_encoding(_server_urls.endpoint_url, msg, msg_size, resp, resp_size);//Encoding/send/receive/Decoding
  215. if(ae_ret != AE_SUCCESS){
  216. AESM_DBG_ERROR("fail to send ES msg1 to backend server:%d",ae_ret);
  217. if(OAL_PROXY_SETTING_ASSIST == ae_ret){//when proxy setting assistant required, return directly
  218. goto final_point;
  219. }
  220. if(read_pek(es_info)==AE_SUCCESS){
  221. ae_ret = AE_SUCCESS;//use es_info inside persistent storage and ignore network error
  222. }
  223. goto final_point;
  224. }
  225. assert(resp != NULL);
  226. AESM_DBG_TRACE("start to process ES msg2");
  227. ae_ret = static_cast<ae_error_t>(CPVEClass::instance().proc_es_msg2(resp, resp_size, es_info.provision_url, provision_ttl, enclave_output.xid, rsa_signature , es_info.pek));
  228. if(AE_SUCCESS != ae_ret){
  229. AESM_DBG_WARN("Fail to process ES msg2 from backend server:%d",ae_ret);
  230. goto final_point;
  231. }
  232. AESM_DBG_TRACE("ES Msg2 decoded successfully, ttl %ds",provision_ttl);
  233. ae_ret = verify_signature(es_info, enclave_output.xid, rsa_signature, provision_ttl);
  234. if(AE_SUCCESS != ae_ret){
  235. AESM_DBG_WARN("Signature verification in ES Msg2 failed");
  236. goto final_point;
  237. }
  238. AESM_DBG_TRACE("Signature in ES Msg2 verified");
  239. es_info.aesm_data_type = AESM_DATA_ENDPOINT_SELECTION_INFOS;
  240. es_info.aesm_data_version = AESM_DATA_ENDPOINT_SELECTION_VERSION;
  241. (void)write_pek(es_info);//ignore file writing error
  242. AESM_DBG_TRACE("end point selection succ, provisioning url: %s",es_info.provision_url);
  243. final_point:
  244. if(msg!=NULL)free(msg);
  245. if(resp!=NULL){
  246. AESMNetworkEncoding::aesm_free_response_msg(resp);
  247. }
  248. return ae_ret;
  249. }
  250. void EndpointSelectionInfo::get_proxy(uint32_t& proxy_type, char proxy_url[MAX_PATH])
  251. {
  252. AESMLogicLock lock(_es_lock);
  253. if(!_is_server_url_loaded){
  254. (void)read_aesm_config(_server_urls);
  255. _is_server_url_loaded=true;
  256. }
  257. proxy_type = _server_urls.proxy_type;
  258. strcpy(proxy_url, _server_urls.aesm_proxy);
  259. }