epid_provision_msg1.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  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 "type_length_value.h"
  32. #include "epid_utility.h"
  33. #include "oal/oal.h"
  34. #include "aeerror.h"
  35. #include "PVEClass.h"
  36. #include "PCEClass.h"
  37. #include "aesm_rand.h"
  38. #include "epid_pve_type.h"
  39. #include "ipp_wrapper.h"
  40. /**
  41. * File: epid_provision_msg1.cpp
  42. * Description: Provide the untrusted implementation of code to generate ProvMsg1
  43. */
  44. //For each ProvMsg,the first field is msg header (which including XID)
  45. //But in the code here, XID is not counted as a TLV field(since it is part of msg header)
  46. //and the index of TLV field is started from 0.
  47. //Msg1 Top TLVs: TLV_CIPHER_TEXT(rsa_oaep_result),E+MAC(encrypted_and_mac_data)
  48. //#define MSG1_TOP_FIELDS_COUNT 3
  49. //#define MSG1_TOP_FIELD_RSA_OAEP_DATA msg1_fields[0]
  50. //#define MSG1_TOP_FIELD_GCM_DATA msg1_fields[1]
  51. //#define MSG1_TOP_FIELD_GCM_MAC msg1_fields[2]
  52. //Function to transform the RSA public key(big endian) into ipp format, the function is defined in pve_pub_key.cpp
  53. //the key is received in endpoint selection from Provision Server which is used for rsa-oaep in ProvMsg1
  54. //secure_free_rsa_pub_key should be called to release the memory on successfully returned rsa_pub_key
  55. //return PVEC_SUCCESS on success
  56. IppStatus get_provision_server_rsa_pub_key_in_ipp_format(const signed_pek_t& pek, IppsRSAPublicKeyState **rsa_pub_key);
  57. //Function to initialize request header for ProvMsg1
  58. //msg1_header: request header for ProvMsg1 to fill in
  59. //use_flags: whether the flag tlv is included
  60. //xid: transaction ID
  61. //msg1_buffer_size: buffer size for ProvMsg1, in bytes
  62. static ae_error_t prov_msg1_gen_header(provision_request_header_t *msg1_header,
  63. bool use_flags,
  64. const uint8_t *xid,
  65. uint32_t msg1_buffer_size)
  66. {
  67. uint32_t total_size = 0;
  68. //platform info tlv size
  69. uint32_t field1_data_size = PLATFORM_INFO_TLV_SIZE();
  70. field1_data_size += CIPHER_TEXT_TLV_SIZE(RSA_3072_KEY_BYTES);
  71. //add flag tlv if needed
  72. if(use_flags){
  73. field1_data_size += FLAGS_TLV_SIZE();
  74. }
  75. if(sizeof(*msg1_header)>msg1_buffer_size){
  76. AESM_DBG_ERROR("Too small ProvMsg1 buffer size");
  77. return PVE_INSUFFICIENT_MEMORY_ERROR;
  78. }
  79. total_size = CIPHER_TEXT_TLV_SIZE(RSA_3072_KEY_BYTES) + BLOCK_CIPHER_TEXT_TLV_SIZE(field1_data_size) +MAC_TLV_SIZE(MAC_SIZE);
  80. //initialize Msg1 Header
  81. msg1_header->protocol = SE_EPID_PROVISIONING;
  82. msg1_header->type = TYPE_PROV_MSG1;
  83. msg1_header->version = TLV_VERSION_2;
  84. if(0!=memcpy_s(msg1_header->xid, sizeof(msg1_header->xid), xid, XID_SIZE)){
  85. AESM_DBG_FATAL("fail in memcpy_s");
  86. return PVE_UNEXPECTED_ERROR;
  87. }
  88. uint32_t size_in;
  89. //use as a tmp size, big endian required in msg header
  90. size_in = _htonl(total_size);
  91. //copy big endian msg body size into header
  92. if(0!=memcpy_s(&msg1_header->size, sizeof(msg1_header->size),&size_in, sizeof(size_in))){
  93. AESM_DBG_FATAL("fail in memcpy_s");
  94. return PVE_UNEXPECTED_ERROR;
  95. }
  96. if(total_size +sizeof(*msg1_header) >msg1_buffer_size){
  97. //the input msg body size is not large enough
  98. AESM_DBG_ERROR("Too small ProvMsg1 buffer size");
  99. return PVE_INSUFFICIENT_MEMORY_ERROR;
  100. }
  101. return AE_SUCCESS;
  102. }
  103. //This function will do the rsa oaep encryption with input src[0:src_len] and put the output to buffer dst
  104. //The function will assume that buffer src_len is no more than PVE_RSAOAEP_ENCRYPT_MAXLEN and the buffer size of dst is at least RSA_3072_KEY_BITS
  105. static ae_error_t aesm_rsa_oaep_encrypt(const uint8_t *src, uint32_t src_len, const IppsRSAPublicKeyState *rsa, uint8_t dst[RSA_3072_KEY_BYTES])
  106. {
  107. const int hashsize = SHA_SIZE_BIT;
  108. Ipp8u seeds[hashsize];
  109. IppStatus status = ippStsNoErr;
  110. ae_error_t ret = AE_SUCCESS;
  111. uint8_t* pub_key_buffer = NULL;
  112. int pub_key_size;
  113. ret = aesm_read_rand(seeds, hashsize);
  114. if(AE_SUCCESS!=ret){
  115. goto ret_point;
  116. }
  117. if((status = ippsRSA_GetBufferSizePublicKey(&pub_key_size, rsa)) != ippStsNoErr)
  118. {
  119. ret = AE_FAILURE;
  120. goto ret_point;
  121. }
  122. //allocate temporary buffer
  123. pub_key_buffer = (uint8_t*)malloc(pub_key_size);
  124. if(pub_key_buffer == NULL)
  125. {
  126. ret = AE_OUT_OF_MEMORY_ERROR;
  127. goto ret_point;
  128. }
  129. if((status = ippsRSAEncrypt_OAEP(src, src_len,
  130. NULL, 0, seeds,
  131. dst, rsa, IPP_ALG_HASH_SHA256, pub_key_buffer)) != ippStsNoErr)
  132. {
  133. ret = AE_FAILURE;
  134. goto ret_point;
  135. }
  136. ret_point:
  137. if(pub_key_buffer)
  138. free(pub_key_buffer);
  139. return ret;
  140. }
  141. //generate ProvMsg1
  142. //The function will generate a random transaction id which is used by msg header of msg1 and saved in pve_data
  143. //The function return AE_SUCCESS on success and other to indicate error
  144. //@pve_data: global structure used to store pve relative data
  145. //@msg1: buffer to receive ProvMsg1 (including both header and body)
  146. //@msg1_size: size of buffer msg1
  147. //@return AE_SUCCESS on success
  148. uint32_t CPVEClass::gen_prov_msg1(
  149. pve_data_t &pve_data,
  150. uint8_t *msg1,
  151. uint32_t msg1_size)
  152. {
  153. uint32_t ret = AE_SUCCESS;
  154. uint16_t pce_id = 0;
  155. uint16_t pce_isv_svn = 0;
  156. sgx_report_t pek_report;
  157. uint8_t *field2 = NULL;
  158. uint8_t field2_iv[IV_SIZE];
  159. uint8_t field2_mac[MAC_SIZE];
  160. uint8_t encrypted_ppid[RSA_3072_KEY_BYTES];
  161. //msg1 header will be in the beginning part of the output msg
  162. provision_request_header_t *msg1_header = reinterpret_cast<provision_request_header_t *>(msg1);
  163. memset(&pek_report, 0, sizeof(pek_report));
  164. sgx_target_info_t pce_target_info;
  165. sgx_status_t sgx_status;
  166. //Load PCE Enclave required
  167. ret = CPCEClass::instance().load_enclave();
  168. if(ret != AE_SUCCESS){
  169. AESM_DBG_ERROR("Fail to load PCE enclave:( ae%d)\n",ret);
  170. return ret;
  171. }
  172. ret = CPCEClass::instance().get_pce_target(&pce_target_info);
  173. if(ret != AE_SUCCESS){
  174. AESM_DBG_ERROR("Fail to get PCE target info:( ae %d)\n",ret);
  175. return ret;
  176. }
  177. //Load PvE enclave now
  178. ret = CPVEClass::instance().load_enclave();
  179. if( ret != AE_SUCCESS){
  180. AESM_DBG_ERROR("Fail to load PvE enclave:(ae%d)\n",ret);
  181. return ret;
  182. }
  183. //The code will generate a report on PEK by PvE
  184. ret = gen_prov_msg1_data(&pve_data.pek, &pce_target_info, &pek_report);
  185. if(AE_SUCCESS != ret ){
  186. AESM_DBG_ERROR("Gen ProvMsg1 in trusted code failed:( ae %d)",ret);
  187. return ret;
  188. }
  189. se_static_assert(sizeof(encrypted_ppid)==PEK_MOD_SIZE);
  190. //Load PCE Enclave required
  191. ret = CPCEClass::instance().load_enclave();
  192. if(ret != AE_SUCCESS){
  193. AESM_DBG_ERROR("Fail to load PCE enclave:( ae %d)\n",ret);
  194. return ret;
  195. }
  196. ret = CPCEClass::instance().get_pce_info(pek_report, pve_data.pek, pce_id,
  197. pce_isv_svn, encrypted_ppid);
  198. if(AE_SUCCESS != ret){
  199. AESM_DBG_ERROR("Fail to generate pc_info:(ae%d)",ret);
  200. return ret;
  201. }
  202. //randomly generate XID
  203. ret = aesm_read_rand(pve_data.xid, XID_SIZE);
  204. if(AE_SUCCESS != ret ){
  205. AESM_DBG_ERROR("Fail to generate random XID (ae%d)",ret);
  206. return ret;
  207. }
  208. //randomly generate SK
  209. ret = aesm_read_rand(pve_data.sk, SK_SIZE);
  210. if(AE_SUCCESS != ret ){
  211. AESM_DBG_ERROR("Fail to generate random SK (ae%d)",ret);
  212. return ret;
  213. }
  214. CPCEClass::instance().unload_enclave();
  215. ret = prov_msg1_gen_header(msg1_header, pve_data.is_performance_rekey, pve_data.xid, msg1_size);
  216. if(AE_SUCCESS != ret){
  217. AESM_DBG_ERROR("fail to generate ProvMsg1 Header:(ae %d)",ret);
  218. return ret;
  219. }
  220. {
  221. TLVsMsg tlvs_msg1_sub;
  222. tlv_status_t tlv_status;
  223. sgx_sha256_hash_t psid;
  224. tlv_status = tlvs_msg1_sub.add_block_cipher_info(pve_data.sk);
  225. ret = tlv_error_2_pve_error(tlv_status);
  226. if(AE_SUCCESS!=ret){
  227. AESM_DBG_ERROR("Fail to generate SK TLV of ProvMsg1 (ae %d)",ret);
  228. return ret;
  229. }
  230. sgx_status = sgx_sha256_msg(reinterpret_cast<const uint8_t *>(&pve_data.pek.n),
  231. static_cast<uint32_t>(sizeof(pve_data.pek.n) + sizeof(pve_data.pek.e)), &psid);
  232. if(SGX_SUCCESS != sgx_status){
  233. AESM_DBG_ERROR("Fail to generate PSID, (sgx0x%x)",sgx_status);
  234. return AE_FAILURE;
  235. }
  236. se_static_assert(sizeof(sgx_sha256_hash_t)==sizeof(psid_t));
  237. tlv_status = tlvs_msg1_sub.add_psid(reinterpret_cast<const psid_t *>(&psid));
  238. ret = tlv_error_2_pve_error(tlv_status);
  239. if(SGX_SUCCESS != ret){
  240. AESM_DBG_ERROR("Fail to add PSID TLV ae(%d)",ret);
  241. return ret;
  242. }
  243. //transform rsa format PEK public key of Provision Server into IPP library format
  244. IppsRSAPublicKeyState *rsa_pub_key = NULL;
  245. IppStatus ippStatus = get_provision_server_rsa_pub_key_in_ipp_format(pve_data.pek, &rsa_pub_key);
  246. if( ippStsNoErr != ippStatus){
  247. AESM_DBG_ERROR("Fail to decode PEK:%d",ippStatus);
  248. return AE_FAILURE;
  249. }
  250. uint8_t field0[RSA_3072_KEY_BYTES];
  251. ret = aesm_rsa_oaep_encrypt(tlvs_msg1_sub.get_tlv_msg(), tlvs_msg1_sub.get_tlv_msg_size(), rsa_pub_key, field0);
  252. secure_free_rsa_pub_key(RSA_3072_KEY_BYTES, sizeof(uint32_t), rsa_pub_key);
  253. if(AE_SUCCESS!=ret){
  254. AESM_DBG_ERROR("Fail to in RSA_OAEP for ProvMsg1:(ae%d)",ret);
  255. return ret;
  256. }
  257. TLVsMsg tlvs_msg1;
  258. tlv_status= tlvs_msg1.add_cipher_text(field0, RSA_3072_KEY_BYTES, PEK_3072_PUB);
  259. ret = tlv_error_2_pve_error(tlv_status);
  260. if(AE_SUCCESS!=ret){
  261. AESM_DBG_ERROR("Fail to generate field0 TLV of ProvMsg1( ae%d)",ret);
  262. return ret;
  263. }
  264. TLVsMsg tlvs_msg2_sub;
  265. tlv_status = tlvs_msg2_sub.add_cipher_text(encrypted_ppid, RSA_3072_KEY_BYTES, PEK_3072_PUB);
  266. ret = tlv_error_2_pve_error(tlv_status);
  267. if(AE_SUCCESS!=ret){
  268. return ret;
  269. }
  270. if(!pve_data.is_backup_retrieval){
  271. if(0!=memcpy_s(&pve_data.bpi.cpu_svn, sizeof(pve_data.bpi.cpu_svn),
  272. &pek_report.body.cpu_svn, sizeof(pek_report.body.cpu_svn))){
  273. AESM_DBG_FATAL("fail in memcpy_s");
  274. return PVE_UNEXPECTED_ERROR;
  275. }
  276. if(0!=memcpy_s(&pve_data.bpi.pve_svn, sizeof(pve_data.bpi.pve_svn),
  277. &pek_report.body.isv_svn, sizeof(pek_report.body.isv_svn))){
  278. AESM_DBG_FATAL("fail in memcpy_s");
  279. return PVE_UNEXPECTED_ERROR;
  280. }
  281. if(0!=memcpy_s(&pve_data.bpi.pce_svn, sizeof(pve_data.bpi.pce_svn),
  282. &pce_isv_svn, sizeof(pce_isv_svn))){
  283. AESM_DBG_FATAL("fail in memcpy_s");
  284. return PVE_UNEXPECTED_ERROR;
  285. }
  286. }
  287. //always use pce_id from PCE enclave
  288. pve_data.bpi.pce_id = pce_id;
  289. memset(&pve_data.bpi.fmsp, 0, sizeof(pve_data.bpi.fmsp));
  290. tlv_status = tlvs_msg2_sub.add_platform_info(pve_data.bpi);
  291. ret = tlv_error_2_pve_error(tlv_status);
  292. if(AE_SUCCESS != ret){
  293. AESM_DBG_ERROR("Fail to generate Platform Info TLV of ProvMsg1 (ae%d)",ret);
  294. return ret;
  295. }
  296. if(pve_data.is_performance_rekey){
  297. flags_t flags;
  298. memset(&flags,0,sizeof(flags));
  299. //set performance rekey flags
  300. flags.flags[FLAGS_SIZE-1]=1;
  301. tlv_status = tlvs_msg2_sub.add_flags(&flags);
  302. ret = tlv_error_2_pve_error(tlv_status);
  303. if(AE_SUCCESS != ret){
  304. AESM_DBG_ERROR("Fail to generate FLAGS TLV of ProvMsg1, (ae %d)",ret);
  305. return ret;
  306. }
  307. }
  308. ret = aesm_read_rand(field2_iv, IV_SIZE);
  309. if(AE_SUCCESS != ret){
  310. AESM_DBG_ERROR("Fail to read rand:(ae%d)",ret);
  311. return ret;
  312. }
  313. sgx_cmac_128bit_tag_t ek1;
  314. se_static_assert(SK_SIZE==sizeof(sgx_cmac_128bit_key_t));
  315. if((sgx_status = sgx_rijndael128_cmac_msg(reinterpret_cast<const sgx_cmac_128bit_key_t *>(pve_data.sk),
  316. pve_data.xid, XID_SIZE, &ek1))!=SGX_SUCCESS){
  317. AESM_DBG_ERROR("Fail to generate ek1:(sgx%d)",sgx_status);
  318. return AE_FAILURE;
  319. }
  320. field2 = (uint8_t *)malloc(tlvs_msg2_sub.get_tlv_msg_size());
  321. if(NULL == field2){
  322. AESM_DBG_ERROR("Out of memory");
  323. return AE_OUT_OF_MEMORY_ERROR;
  324. }
  325. sgx_status = sgx_rijndael128GCM_encrypt(&ek1,
  326. tlvs_msg2_sub.get_tlv_msg(), tlvs_msg2_sub.get_tlv_msg_size(),
  327. field2,field2_iv, IV_SIZE, (const uint8_t *)msg1_header, sizeof(provision_request_header_t),
  328. (sgx_aes_gcm_128bit_tag_t *)field2_mac);
  329. if(SGX_SUCCESS != sgx_status){
  330. ret = sgx_error_to_ae_error(sgx_status);
  331. AESM_DBG_ERROR("Fail to do AES encrypt (sgx %d)", sgx_status);
  332. free(field2);
  333. return ret;
  334. }
  335. tlv_status = tlvs_msg1.add_block_cipher_text(field2_iv, field2, tlvs_msg2_sub.get_tlv_msg_size());
  336. ret = tlv_error_2_pve_error(tlv_status);
  337. if(AE_SUCCESS!=ret){
  338. free(field2);
  339. AESM_DBG_ERROR("Fail to generate field1 TLV of ProvMsg1(ae%d)",ret);
  340. return ret;
  341. }
  342. free(field2);
  343. tlv_status = tlvs_msg1.add_mac(field2_mac);
  344. ret = tlv_error_2_pve_error(tlv_status);
  345. if(AE_SUCCESS!=ret){
  346. AESM_DBG_ERROR("Fail to create field2 TLV of ProvMsg1:(ae %d)",ret);
  347. return ret;
  348. }
  349. uint32_t size = tlvs_msg1.get_tlv_msg_size();
  350. if(memcpy_s(msg1+PROVISION_REQUEST_HEADER_SIZE, msg1_size - PROVISION_REQUEST_HEADER_SIZE,
  351. tlvs_msg1.get_tlv_msg(), size)!=0){
  352. //The size overflow has been checked in header generation
  353. AESM_DBG_FATAL("fail in memcpy_s");
  354. return PVE_UNEXPECTED_ERROR;
  355. }
  356. }
  357. return AE_SUCCESS;
  358. }