provision_msg3.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  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 "msg3_parm.h"
  32. #include "se_sig_rl.h"
  33. #include "cipher.h"
  34. #include "helper.h"
  35. #include "sgx_trts.h"
  36. #include "pve_qe_common.h"
  37. #include "pve_hardcoded_tlv_data.h"
  38. #include "sgx_utils.h"
  39. #include "byte_order.h"
  40. #include "ipp_wrapper.h"
  41. #include <string.h>
  42. #include <stdlib.h>
  43. #include "pek_pub_key.h"
  44. #include "util.h"
  45. #ifdef __cplusplus
  46. extern "C" {
  47. #endif
  48. #include "epid/common/src/memory.h"
  49. #include "epid/member/software_member.h"
  50. #include "epid/member/src/signbasic.h"
  51. #include "epid/member/src/nrprove.h"
  52. #ifdef __cplusplus
  53. }
  54. #endif
  55. /**
  56. * File: provision_msg3.cpp
  57. * Description: Provide the implementation of code to generate ProvMsg3
  58. *
  59. * Core Code for Provision Enclave
  60. * Piece-meal processing used to process SigRl of ProvMsg2 and generate EpidSignature of ProvMsg3
  61. */
  62. //initialize the epid signature header according to sigrl_header
  63. static pve_status_t gen_epid_signature_header(const SigRl *sigrl_header,
  64. EPIDMember *epid_member,
  65. const uint8_t *nonce_challenge,
  66. EpidSignature *epid_header,
  67. BigNumStr *rnd_bsn)
  68. {
  69. if(NULL!=sigrl_header){
  70. memcpy(&epid_header->n2, &sigrl_header->n2, sizeof(sigrl_header->n2));//copy size into header in BigEndian
  71. memcpy(&epid_header->rl_ver, &sigrl_header->version, sizeof(sigrl_header->version)); //Copy rl_ver in BigEndian
  72. }else{
  73. memset(&epid_header->n2, 0, sizeof(epid_header->n2)); //set n2 and rl_ver to 0 if no sigrl provided
  74. memset(&epid_header->rl_ver, 0, sizeof(epid_header->rl_ver));
  75. }
  76. //challenge nonce value is used as sign message
  77. uint32_t msg_len = CHALLENGE_NONCE_SIZE;
  78. EpidStatus epid_ret = EpidSignBasic(epid_member,
  79. const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(nonce_challenge)),
  80. msg_len, NULL, 0, &epid_header->sigma0, rnd_bsn);//generate EpidSignature Header inside EPC memory
  81. if(kEpidNoErr != epid_ret){
  82. return epid_error_to_pve_error(epid_ret);
  83. }
  84. return PVEC_SUCCESS;
  85. }
  86. static uint32_t pve_htonl(uint32_t x)
  87. {
  88. uint32_t l0=x&0xFF;
  89. uint32_t l1=(x>>8)&0xFF;
  90. uint32_t l2=(x>>16)&0xFF;
  91. uint32_t l3=(x>>24)&0xFF;
  92. return l3|(l2<<8)|(l1<<16)|(l0<<24);
  93. }
  94. //This function will first generate EPIDSig Header according to sigrl_header
  95. //After that, piece meal algorithm is used to
  96. // decode SigRl Entry in msg2 and update hash value
  97. // generate EPIDSigEntry in msg3 and encrypt it
  98. // The memory of msg2 for SigRl and msg3 for EPIDSigEntry are all outside enclave
  99. // So that we need first copy each SigRl Entry into EPC memory, generate EPIDSigEntry inside EPC memory
  100. // and copy it out after it is generated
  101. // The function assumes the size of SigRl has been verfied and it is not checked again here.
  102. // Finally it checks whether the hash value is valid according to ECDSA Sign in the end of SigRl to verify data is not modified
  103. // A TLV Header for the EpidSignature should have been prepared in EPC memory signature_tlv_header
  104. //It is assumed that the parm->sigrl_count>0 when the function is called and the size of sigrl has been checked
  105. //EpidSignature TLV format: TLVHeader:EpidSignatureHeader:NrProof1:NrProof2:...:NrProofn
  106. static pve_status_t gen_msg3_signature(const proc_prov_msg2_blob_input_t *msg2_blob_input,
  107. prov_msg3_parm_t *parm,
  108. external_memory_byte_t *emp_signature,//pointer to external memory to write the EPID Signature
  109. uint32_t& signature_size)
  110. {
  111. pve_status_t ret = PVEC_SUCCESS;
  112. uint32_t cur_size = static_cast<uint32_t>(EPID_SIGNATURE_TLV_HEADER_SIZE+sizeof(EpidSignature)-sizeof(NrProof));
  113. //emp_proof_entry is pointer to external memory to each entry of the epid signature body in external memory
  114. external_memory_byte_t *emp_proof_entry = emp_signature + cur_size;
  115. //emp_sigrl_entry is pointer to external memory to each entry of the sigrl_body in external memory
  116. const external_memory_byte_t *emp_sigrl_entry = parm->emp_sigrl_sig_entries;
  117. uint32_t i,entry_count = parm->sigrl_count;
  118. bool revoked = false;
  119. uint8_t sigrl_sign[2*ECDSA_SIGN_SIZE];//temp buffer in EPC to hold ECDSA signature
  120. //declare a buffer to hold encrypted data of TLV Header and EpidSignature Header
  121. uint8_t signature_header_to_encrypt[EPID_SIGNATURE_TLV_HEADER_SIZE + sizeof(EpidSignature)-sizeof(NrProof)];
  122. SigRlEntry temp1;
  123. NrProof temp3;
  124. uint32_t tlv_payload_size = 0;
  125. const SigRl *sigrl_header = NULL;
  126. BigNumStr rnd_bsn = { 0 };
  127. sgx_status_t sgx_status = SGX_SUCCESS;
  128. memset(sigrl_sign, 0, sizeof(sigrl_sign));
  129. memset(&temp1, 0, sizeof(temp1));
  130. memset(&temp3, 0, sizeof(temp3));
  131. memset(signature_header_to_encrypt, 0, sizeof(signature_header_to_encrypt));
  132. if(entry_count>0){
  133. sigrl_header = &parm->sigrl_header.sig_rl;//use the sigrl_header only when sigrl is available
  134. if(signature_size < cur_size){//size of output buffer at least to hold currently generated data
  135. ret = PVEC_INSUFFICIENT_MEMORY_ERROR;
  136. goto ret_point;
  137. }
  138. if((signature_size-cur_size)/entry_count<sizeof(NrProof)){//safe way to check buffer overflow of output buffer to avoid integer overflow
  139. ret = PVEC_INSUFFICIENT_MEMORY_ERROR;
  140. goto ret_point;
  141. }
  142. tlv_payload_size = static_cast<uint32_t>(sizeof(EpidSignature)-sizeof(NrProof) + entry_count * sizeof(NrProof));
  143. }else{
  144. tlv_payload_size = static_cast<uint32_t>(sizeof(EpidSignature)-sizeof(NrProof)); //payload size for 0 entry, only basic signature with n2 and rl_ver to be 0
  145. if(signature_size < cur_size){//size of output buffer at least to hold currently generated data
  146. ret = PVEC_INSUFFICIENT_MEMORY_ERROR;
  147. goto ret_point;
  148. }
  149. }
  150. memcpy(signature_header_to_encrypt, EPID_SIGNATURE_TLV_HEADER, EPID_SIGNATURE_TLV_HEADER_SIZE); //copy in the hard coded EPID Signature TLV Header
  151. tlv_payload_size = pve_htonl(tlv_payload_size);
  152. //overwritten the bigendian size in TLV Header. It is assumed that the size in TLV Header is always 4 bytes//Long format
  153. memcpy(signature_header_to_encrypt+EPID_SIGNATURE_TLV_SIZE_OFFSET, &tlv_payload_size, sizeof(tlv_payload_size));
  154. ret = gen_epid_signature_header(sigrl_header, parm->epid_member, msg2_blob_input->challenge_nonce, &parm->signature_header, &rnd_bsn);//Now generate EpidSignatureHeader
  155. if( PVEC_SUCCESS != ret )
  156. goto ret_point;
  157. //Now encrypt the TLV Header and signature header including basic signature while the parm->signature_header is kept since piece-meal processing will use it
  158. memcpy(signature_header_to_encrypt+EPID_SIGNATURE_TLV_HEADER_SIZE, &parm->signature_header, cur_size-EPID_SIGNATURE_TLV_HEADER_SIZE);
  159. ret =pve_aes_gcm_encrypt_inplace_update(parm->p_msg3_state, signature_header_to_encrypt, cur_size);
  160. if( PVEC_SUCCESS != ret )
  161. goto ret_point;
  162. pve_memcpy_out(emp_signature, signature_header_to_encrypt, cur_size);//copy out tlv header, basic signature and other epid signature header info if required
  163. if(NULL==parm->emp_sigrl_sig_entries){//finish if no sigrl avaiable
  164. signature_size = cur_size;
  165. goto ret_point;
  166. }
  167. //copy the ECDSA Signature of the SigRl in ProvMsg2 into EPC memory in advance to defense in depth
  168. pve_memcpy_in(sigrl_sign, emp_sigrl_entry + entry_count *sizeof(SigRlEntry), 2*ECDSA_SIGN_SIZE);
  169. //piece-meal processing
  170. //The pointer calculation will never overflow as soon as size of sigrl and epid signature have been checked in advance
  171. //TO BE CLARIFY:We assume that the ecdsa signature follows entry array of SigRl directly
  172. // If later we change the format of sigrl to include extra data which should be ecdsa signed too,
  173. // we need do the modification here: change the sigrl_sign and do more sha update
  174. signature_size = static_cast<uint32_t>(cur_size+entry_count *sizeof(NrProof));//recalculate output buffer
  175. //Start piece meal processing for each entry
  176. for(i=0;i<entry_count; i++){
  177. pve_memcpy_in(&temp1, emp_sigrl_entry, sizeof(temp1));//copy the data into trusted memory
  178. //update hash for the SigRl Entry
  179. sgx_status = sgx_sha256_update(reinterpret_cast<uint8_t *>(&temp1), sizeof(SigRlEntry), parm->sha_state);
  180. if(sgx_status != SGX_SUCCESS){
  181. ret = sgx_error_to_pve_error(sgx_status);
  182. goto ret_point;
  183. }
  184. //generate NrProof for the SigRl Entry in trusted memory
  185. EpidStatus epid_ret = EpidNrProve(parm->epid_member,
  186. const_cast<uint8_t *>(msg2_blob_input->challenge_nonce),//msg to sign
  187. CHALLENGE_NONCE_SIZE,
  188. &rnd_bsn,
  189. sizeof(rnd_bsn),
  190. &parm->signature_header.sigma0, //B and K in BasicSignature
  191. &temp1, //B and K in sigrl entry
  192. &temp3); //output one NrProof
  193. if(kEpidNoErr != epid_ret){
  194. if(kEpidSigRevokedInSigRl == epid_ret){
  195. revoked = true;//if revoked, we could not return revoked status immediately until integrity checking passed
  196. }else{
  197. ret = epid_error_to_pve_error(epid_ret);
  198. goto ret_point;
  199. }
  200. }
  201. //encrypt the NrProof in EPC
  202. ret = pve_aes_gcm_encrypt_inplace_update(parm->p_msg3_state, reinterpret_cast<uint8_t *>(&temp3), sizeof(temp3));
  203. if(ret != PVEC_SUCCESS){
  204. goto ret_point;
  205. }
  206. pve_memcpy_out(emp_proof_entry, &temp3, sizeof(temp3));//copy encrypted NrProof out of enclave
  207. emp_sigrl_entry += sizeof(SigRlEntry);//pointer to next SigRlEntry in external memory
  208. emp_proof_entry += sizeof(NrProof);//pointer to next NrProof in external memory
  209. }
  210. se_ae_ecdsa_hash_t out;
  211. //generate SHA256 hash value of the whole SigRl
  212. if((sgx_status=sgx_sha256_get_hash(parm->sha_state,
  213. reinterpret_cast<sgx_sha256_hash_t *>(&out))) !=
  214. SGX_SUCCESS){
  215. ret = sgx_error_to_pve_error(sgx_status);
  216. goto ret_point;
  217. }
  218. //Verify the signature is signed by EPIDSK
  219. ret = verify_epid_ecdsa_signature(sigrl_sign, parm->local_xegb, &out);
  220. if(ret == PVEC_MSG_ERROR){
  221. ret = PVEC_SIGRL_INTEGRITY_CHECK_ERROR;//If sigrl signature checking failed, someone must has modified the message
  222. }
  223. ret_point:
  224. //clear unsealed NrProof to defense in depth for potential attack to match attacker created sigrl entry with key
  225. //While we need not clear BasicSignature
  226. (void)memset_s(&temp3, sizeof(temp3), 0, sizeof(temp3));
  227. if(ret == PVEC_SUCCESS &&revoked){
  228. ret = PVEC_REVOKED_ERROR;
  229. }
  230. return ret;
  231. }
  232. //The function will try to do some preparation for piece meal encryption of field1 in ProvMsg3
  233. // It prepares the encryption state in msg3
  234. //@parm: structure to provide some input data to generate ProvMsg3 and also some states for piece meal processing
  235. //@return PVEC_SUCCESS on success and error code if failed
  236. static pve_status_t proc_msg3_state_init(prov_msg3_parm_t *parm, const sgx_key_128bit_t *pwk2)
  237. {
  238. pve_status_t ret = PVEC_SUCCESS;
  239. sgx_status_t se_ret = SGX_SUCCESS;
  240. if((se_ret=sgx_read_rand(parm->iv, IV_SIZE))!=SGX_SUCCESS){//randomly generate the IV
  241. ret = se_read_rand_error_to_pve_error(se_ret);
  242. goto ret_point;
  243. }
  244. se_static_assert(SK_SIZE==sizeof(sgx_cmac_128bit_tag_t)); /*size of sgx_cmac_128bit_tag_t should same as value of SK_SIZE*/
  245. //initialize state for piece-meal encryption of field of ProvMsg3
  246. ret = pve_aes_gcm_encrypt_init((const uint8_t *)pwk2, parm->iv, IV_SIZE,//pwk2 as the key
  247. NULL, 0,//no AAD used for the encryption of EpidSignature
  248. &parm->p_msg3_state, &parm->msg3_state_size);
  249. ret_point:
  250. return ret;
  251. }
  252. //Function to generate Field1_0 of ProvMsg3
  253. //@msg2_blob_input, input decoded ProvMsg2 info
  254. //@join_proof, output the join proof and the escrow data which is encrypted f of Private Key
  255. //@return PVEC_SUCCESS on success and error code on failure
  256. //The function assume all required inputs have been prepared in msg2_blob_input
  257. static pve_status_t gen_msg3_join_proof_escrow_data(const proc_prov_msg2_blob_input_t *msg2_blob_input,
  258. join_proof_with_escrow_t& join_proof)
  259. {
  260. pve_status_t ret = PVEC_SUCCESS;
  261. BitSupplier epid_prng = (BitSupplier) epid_random_func;
  262. FpElemStr temp_f;
  263. //first generate private key f randomly before sealing it by PSK
  264. FpElemStr *f = &temp_f;
  265. sgx_status_t sgx_status = SGX_SUCCESS;
  266. JoinRequest *join_r = &join_proof.jr;
  267. EpidStatus epid_ret = kEpidNoErr;
  268. psvn_t psvn;
  269. MemberCtx* ctx = NULL;
  270. memset(&temp_f, 0, sizeof(temp_f));
  271. //randomly generate the private EPID key f, host to network transformation not required since server will not decode it
  272. if(PVEC_SUCCESS != (ret=gen_epid_priv_f(f))){
  273. goto ret_point;
  274. }
  275. //generate JoinP using f before encryption by calling EPID library
  276. memset(join_r, 0, sizeof(JoinRequest));//first clear to 0
  277. //generate JoinP to fill it in field1_0_0 by EPID library
  278. epid_ret = epid_member_create(epid_prng, NULL, f, &ctx);
  279. if(kEpidNoErr!=epid_ret){
  280. ret = epid_error_to_pve_error(epid_ret);
  281. goto ret_point;
  282. }
  283. epid_ret = EpidCreateJoinRequest(ctx,
  284. &msg2_blob_input->group_cert.key, //EPID Group Cert from ProvMsgs2 used
  285. reinterpret_cast<const IssuerNonce *>(msg2_blob_input->challenge_nonce),
  286. join_r);
  287. if(kEpidNoErr != epid_ret){
  288. ret = epid_error_to_pve_error(epid_ret);
  289. goto ret_point;
  290. }
  291. //get PSK
  292. sgx_key_128bit_t psk;
  293. memcpy(&psvn.cpu_svn, &msg2_blob_input->equiv_pi.cpu_svn, sizeof(psvn.cpu_svn));
  294. memcpy(&psvn.isv_svn, &msg2_blob_input->equiv_pi.pve_svn, sizeof(psvn.isv_svn));
  295. ret = get_pve_psk(&psvn, &psk);
  296. if(PVEC_SUCCESS != ret){
  297. goto ret_point;
  298. }
  299. join_proof.escrow.version = 0;//version 0 used for escrow data
  300. //now we could seal f by PSK
  301. ret = se_read_rand_error_to_pve_error(sgx_read_rand(join_proof.escrow.iv, IV_SIZE));
  302. if(PVEC_SUCCESS != ret){
  303. goto ret_point;
  304. }
  305. se_static_assert(sizeof(psk)==sizeof(sgx_aes_gcm_128bit_key_t)); /*sizeof sgx_aes_gcm_128bit_key_t tshould be same as size of psk*/
  306. se_static_assert(sizeof(sgx_aes_gcm_128bit_tag_t)==sizeof(join_proof.escrow.mac)); /*sizeof sgx_aes_gcm_128bit_tag_t should be same as MAC_SIZE*/
  307. sgx_status = sgx_rijndael128GCM_encrypt(reinterpret_cast<const sgx_aes_gcm_128bit_key_t *>(&psk),
  308. reinterpret_cast<uint8_t *>(f), sizeof(*f), reinterpret_cast<uint8_t *>(&join_proof.escrow.f),
  309. join_proof.escrow.iv, IV_SIZE, NULL, 0,
  310. reinterpret_cast<sgx_aes_gcm_128bit_tag_t *>(join_proof.escrow.mac));
  311. if(SGX_SUCCESS != sgx_status){
  312. ret = sgx_error_to_pve_error(sgx_status);
  313. }
  314. ret_point:
  315. (void)memset_s(&psk, sizeof(psk), 0, sizeof(psk));//clear the key
  316. (void)memset_s(&temp_f, sizeof(temp_f), 0, sizeof(temp_f));//clear temp f in stack
  317. if(PVEC_SUCCESS != ret){
  318. (void)memset_s(&join_proof, sizeof(join_proof), 0, sizeof(join_proof));
  319. }
  320. epid_member_delete(&ctx);
  321. return ret;
  322. }
  323. //Function to create data for ProvMsg3 generation
  324. // The sigrl of ProvMsg2 will processed in this function in piece-meal method
  325. //@msg2_blob_input: structure to hold decoded data of ProvMsg2
  326. //@performance_rekey_used[in]: 1 if performance rekey used or 0 if not
  327. //@msg3_parm: structure to hold most information to generate ProvMsg3
  328. //@msg3_output: structure to hold output data to create ProvMsg3
  329. //@emp_epid_sig: output buffer to external memory for variable length EpidSignature
  330. //@epid_sig_buffer_size: size in bytes of buffer emp_epid_sig
  331. //@return PVEC_SUCCESS on success and error code if failed
  332. pve_status_t gen_prov_msg3_data(const proc_prov_msg2_blob_input_t *msg2_blob_input,
  333. prov_msg3_parm_t& msg3_parm,
  334. uint8_t performance_rekey_used,
  335. gen_prov_msg3_output_t *msg3_output,
  336. external_memory_byte_t *emp_epid_sig,
  337. uint32_t epid_sig_buffer_size)
  338. {
  339. pve_status_t ret = PVEC_SUCCESS;
  340. sgx_status_t sgx_status = SGX_SUCCESS;
  341. uint8_t temp_buf[JOIN_PROOF_TLV_TOTAL_SIZE];
  342. uint8_t *data_to_encrypt = NULL;
  343. uint8_t size_to_encrypt = 0;
  344. uint8_t pwk2_tlv_buffer[PWK2_TLV_TOTAL_SIZE];
  345. sgx_key_128bit_t *pwk2=reinterpret_cast<sgx_key_128bit_t *>(pwk2_tlv_buffer+PWK2_TLV_HEADER_SIZE);
  346. uint8_t report_data_payload[MAC_SIZE + HARD_CODED_JOIN_PROOF_WITH_ESCROW_TLV_SIZE + NONCE_2_SIZE + PEK_MOD_SIZE];
  347. uint8_t* pdata = &report_data_payload[0];
  348. sgx_report_data_t report_data = { 0 };
  349. uint8_t aad[sizeof(GroupId)+sizeof(device_id_t)+CHALLENGE_NONCE_SIZE];
  350. IppsRSAPublicKeyState *pub_key = NULL;
  351. uint8_t *pub_key_buffer = NULL;
  352. IppStatus ipp_status;
  353. int pub_key_size;
  354. Ipp8u seeds[PVE_RSA_SEED_SIZE]={0};
  355. const signed_pek_t& pek = msg2_blob_input->pek;
  356. uint32_t le_e;
  357. int i;
  358. uint8_t le_n[sizeof(pek.n)];
  359. static_assert(sizeof(pek.n)==384, "pek.n should be 384 bytes");
  360. device_id_t *device_id_in_aad= (device_id_t *)(aad+sizeof(GroupId));
  361. join_proof_with_escrow_t* join_proof_with_escrow=reinterpret_cast<join_proof_with_escrow_t *>(temp_buf+JOIN_PROOF_TLV_HEADER_SIZE);
  362. se_static_assert(sizeof(join_proof_with_escrow_t)+JOIN_PROOF_TLV_HEADER_SIZE==JOIN_PROOF_TLV_TOTAL_SIZE); /*unmatched hardcoded size*/
  363. se_static_assert(sizeof(sgx_key_128bit_t)==PWK2_TLV_TOTAL_SIZE-PWK2_TLV_HEADER_SIZE); /*unmatched PWK2 size*/
  364. memset(temp_buf, 0 ,sizeof(temp_buf));
  365. memset(aad, 0, sizeof(aad));
  366. memset(pwk2, 0, sizeof(sgx_key_128bit_t));
  367. memcpy(pwk2_tlv_buffer, PWK2_TLV_HEADER, PWK2_TLV_HEADER_SIZE);
  368. msg3_output->is_join_proof_generated=false;
  369. msg3_output->is_epid_sig_generated=false;
  370. if ((msg2_blob_input->pce_target_info.attributes.flags & SGX_FLAGS_PROVISION_KEY) != SGX_FLAGS_PROVISION_KEY ||
  371. (msg2_blob_input->pce_target_info.attributes.flags & SGX_FLAGS_DEBUG) != 0){
  372. //PCE must have access to provisioning key
  373. //Can't be debug PCE
  374. ret = PVEC_PARAMETER_ERROR;
  375. goto ret_point;
  376. }
  377. if(!performance_rekey_used){
  378. //the temp_buf used for join_proof_with_escrow tlv
  379. memcpy(temp_buf, JOIN_PROOF_TLV_HEADER, JOIN_PROOF_TLV_HEADER_SIZE);//first copy in tlv header
  380. ret = gen_msg3_join_proof_escrow_data(msg2_blob_input, *join_proof_with_escrow);//generate the tlv payload
  381. if( PVEC_SUCCESS != ret )
  382. goto ret_point;
  383. msg3_output->is_join_proof_generated = true;
  384. data_to_encrypt = temp_buf;
  385. size_to_encrypt = JOIN_PROOF_TLV_TOTAL_SIZE;
  386. }
  387. //now encrypt field1
  388. ret = se_read_rand_error_to_pve_error(sgx_read_rand(msg3_output->field1_iv, IV_SIZE));//randomly generate IV
  389. if( PVEC_SUCCESS != ret)
  390. goto ret_point;
  391. memcpy(aad, &msg2_blob_input->group_cert.key.gid,sizeof(GroupId));//start to prepare AAD
  392. memcpy(&device_id_in_aad->fmsp, &msg2_blob_input->equiv_pi.fmsp, sizeof(fmsp_t));
  393. memcpy(&device_id_in_aad->psvn.cpu_svn, &msg2_blob_input->equiv_pi.cpu_svn, sizeof(sgx_cpu_svn_t));
  394. memcpy(&device_id_in_aad->psvn.isv_svn, &msg2_blob_input->equiv_pi.pve_svn, sizeof(sgx_isv_svn_t));
  395. memset(&device_id_in_aad->ppid, 0, sizeof(device_id_in_aad->ppid));
  396. ret = pve_rng_generate(NONCE_2_SIZE*8, msg3_output->n2);
  397. if(PVEC_SUCCESS !=ret){
  398. goto ret_point;
  399. }
  400. ret = get_pwk2(&device_id_in_aad->psvn, msg3_output->n2, pwk2);
  401. if( PVEC_SUCCESS != ret )
  402. goto ret_point;
  403. memcpy(aad+sizeof(GroupId)+sizeof(device_id_t), msg2_blob_input->challenge_nonce, CHALLENGE_NONCE_SIZE);
  404. se_static_assert(sizeof(sgx_aes_gcm_128bit_key_t)==SK_SIZE); /*sizeof sgx_aes_gcm_128bit_key_t should be same as TCB size*/
  405. se_static_assert(sizeof(sgx_aes_gcm_128bit_tag_t)==MAC_SIZE); /*sizeof sgx_aes_gcm_128bit_tag_t should be same as MAC_SIZE*/
  406. sgx_status = sgx_rijndael128GCM_encrypt(reinterpret_cast<const sgx_aes_gcm_128bit_key_t *>(pwk2),
  407. data_to_encrypt, size_to_encrypt, msg3_output->field1_data,
  408. msg3_output->field1_iv, IV_SIZE, aad, static_cast<uint32_t>(sizeof(GroupId)+sizeof(device_id_t)+CHALLENGE_NONCE_SIZE),
  409. reinterpret_cast<sgx_aes_gcm_128bit_tag_t *>(msg3_output->field1_mac));//encrypt field1
  410. if(SGX_SUCCESS != sgx_status){
  411. ret = sgx_error_to_pve_error(sgx_status);
  412. goto ret_point;
  413. }
  414. if( msg2_blob_input->is_previous_pi_provided ){
  415. //preparing the encryption state of ProvMsg3 and encrypt inplace of msg3_inside enclave (field1_0 and field1_1)
  416. //The function will randomly set the iv value too
  417. ret = proc_msg3_state_init(&msg3_parm, pwk2);
  418. if( PVEC_SUCCESS!=ret )
  419. goto ret_point;
  420. //Now start piece-meal generation of EPIDsign
  421. ret = gen_msg3_signature(msg2_blob_input, &msg3_parm, emp_epid_sig, epid_sig_buffer_size);
  422. if( PVEC_SUCCESS!=ret )
  423. goto ret_point;
  424. msg3_output->is_epid_sig_generated = true;
  425. msg3_output->epid_sig_output_size = epid_sig_buffer_size;
  426. memcpy(msg3_output->epid_sig_iv, msg3_parm.iv, IV_SIZE);
  427. //generate MAC in EPC
  428. ret = pve_aes_gcm_get_mac(msg3_parm.p_msg3_state, msg3_output->epid_sig_mac);
  429. if (PVEC_SUCCESS != ret)
  430. goto ret_point;
  431. }
  432. le_e = lv_ntohl(pek.e);
  433. se_static_assert(sizeof(pek.n)==sizeof(le_n)); /*unmatched size of pek.n*/
  434. //endian swap
  435. for(i=0;i<(int)(sizeof(pek.n)/sizeof(pek.n[0]));i++){
  436. le_n[i]=pek.n[sizeof(pek.n)/sizeof(pek.n[0])-i-1];
  437. }
  438. ipp_status = create_rsa_pub_key(sizeof(pek.n), sizeof(pek.e),
  439. reinterpret_cast<const Ipp32u *>(le_n), &le_e, &pub_key);
  440. if(ippStsNoErr != ipp_status){
  441. ret = ipp_error_to_pve_error(ipp_status);
  442. goto ret_point;
  443. }
  444. ipp_status = ippsRSA_GetBufferSizePublicKey(&pub_key_size, pub_key);
  445. if(ippStsNoErr != ipp_status){
  446. ret = ipp_error_to_pve_error(ipp_status);
  447. goto ret_point;
  448. }
  449. if(SGX_SUCCESS != (sgx_status =sgx_read_rand(seeds, PVE_RSA_SEED_SIZE))){
  450. ret = se_read_rand_error_to_pve_error(sgx_status);
  451. goto ret_point;
  452. }
  453. pub_key_buffer = (uint8_t *)malloc(pub_key_size);
  454. if(NULL ==pub_key_buffer){
  455. ret = PVEC_INSUFFICIENT_MEMORY_ERROR;
  456. goto ret_point;
  457. }
  458. ipp_status = ippsRSAEncrypt_OAEP(reinterpret_cast<const Ipp8u *>(pwk2_tlv_buffer), PWK2_TLV_TOTAL_SIZE, NULL, 0, seeds,
  459. msg3_output->encrypted_pwk2, pub_key, IPP_ALG_HASH_SHA256, pub_key_buffer);
  460. if(ippStsNoErr != ipp_status){
  461. ret = ipp_error_to_pve_error(ipp_status);
  462. goto ret_point;
  463. }
  464. // X = (NT)MAC_PWK2(... (NT)E_PWK2((T)(JoinP, f)) ...) | (NT)E_PWK2((T)(JoinP, f)) | (NT)PWK2N | (NT)E_PEK((T)PWK2)
  465. // REPORT.ReportData == SHA256[X]
  466. memcpy(pdata, msg3_output->field1_mac, MAC_SIZE);
  467. pdata += MAC_SIZE;
  468. if (!performance_rekey_used){
  469. memcpy(pdata, msg3_output->field1_data, HARD_CODED_JOIN_PROOF_WITH_ESCROW_TLV_SIZE);
  470. pdata += HARD_CODED_JOIN_PROOF_WITH_ESCROW_TLV_SIZE;
  471. }
  472. memcpy(pdata, msg3_output->n2, NONCE_2_SIZE);
  473. pdata += NONCE_2_SIZE;
  474. memcpy(pdata, msg3_output->encrypted_pwk2, PEK_MOD_SIZE);
  475. pdata += PEK_MOD_SIZE;
  476. se_static_assert(sizeof(report_data) >= sizeof(sgx_sha256_hash_t)); /*report data is no large enough*/
  477. sgx_status = sgx_sha256_msg(report_data_payload, (uint32_t)(pdata - &report_data_payload[0]), reinterpret_cast<sgx_sha256_hash_t *>(&report_data));
  478. if (SGX_SUCCESS != sgx_status){
  479. ret = sgx_error_to_pve_error(sgx_status);
  480. goto ret_point;
  481. }
  482. sgx_status = sgx_create_report(&msg2_blob_input->pce_target_info, &report_data, &msg3_output->pwk2_report);
  483. if (SGX_SUCCESS != sgx_status){
  484. ret = sgx_error_to_pve_error(sgx_status);
  485. goto ret_point;
  486. }
  487. ret_point:
  488. (void)memset_s(aad, sizeof(aad), 0, sizeof(aad));
  489. (void)memset_s(temp_buf, sizeof(temp_buf), 0, sizeof(temp_buf));
  490. (void)memset_s(pwk2_tlv_buffer, sizeof(pwk2_tlv_buffer),0,sizeof(pwk2_tlv_buffer));
  491. if(pub_key){
  492. secure_free_rsa_pub_key(sizeof(pek.n), sizeof(pek.e), pub_key);
  493. }
  494. if(pub_key_buffer){
  495. free(pub_key_buffer);
  496. }
  497. return ret;
  498. }