bool protected_fs_file::update_meta_data_node() { sgx_status_t status; // randomize a new key, saves the key _id_ in the meta data plain part if (generate_random_meta_data_key() != true) { // last error already set return false; } // encrypt meta data encrypted part, also updates the gmac in the meta data plain part status = sgx_rijndael128GCM_encrypt(&cur_key, (const uint8_t*)&encrypted_part_plain, sizeof(meta_data_encrypted_t), (uint8_t*)&file_meta_data.encrypted_part, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &file_meta_data.plain_part.meta_data_gmac); if (status != SGX_SUCCESS) { last_error = status; return false; } return true; }
uint32_t aes128gcm_encrypt(const sgx_aes_gcm_128bit_key_t *key, const uint8_t *bufin, const size_t bufinlen, uint8_t *bufout, size_t bufoutlen) { // check buffer bounds if(bufoutlen < aes128gcm_ciphertext_size(bufinlen)) { return 0Xffffffff; } // source random IV from rdrand if(sgx_read_rand(bufout, SGX_AESGCM_IV_SIZE) != SGX_SUCCESS) { return 0Xffffffff; } // encrypt if(SGX_SUCCESS != sgx_rijndael128GCM_encrypt(key, bufin, bufinlen, // plaintext bufout + SGX_AESGCM_IV_SIZE + SGX_AESGCM_MAC_SIZE, // ciphertext bufout, SGX_AESGCM_IV_SIZE, // iv NULL, 0, // aad (sgx_aes_gcm_128bit_tag_t*) (bufout + SGX_AESGCM_IV_SIZE) // mac )) { return 0Xffffffff; } return 0; }
ae_error_t CertificateProvisioningProtocol::aesGCMEncrypt(const upse::Buffer& iv, const upse::Buffer& key, const upse::Buffer& plainText, const upse::Buffer& aad, upse::Buffer& encryptedText, upse::Buffer& mac) { ae_error_t status = AE_FAILURE; do { if (key.getSize() != sizeof(sgx_aes_gcm_128bit_key_t)) break; status = encryptedText.Alloc(plainText.getSize()); if (AE_FAILED(status)) break; uint8_t* pEncryptedText; status = upse::BufferWriter(encryptedText).reserve(encryptedText.getSize(), &pEncryptedText); if (AE_FAILED(status)) break; status = mac.Alloc(sizeof(sgx_aes_gcm_128bit_tag_t)); if (AE_FAILED(status)) break; uint8_t* pMAC; status = upse::BufferWriter(mac).reserve(mac.getSize(), &pMAC); if (AE_FAILED(status)) break; sgx_status_t sgx_status; sgx_status = sgx_rijndael128GCM_encrypt(reinterpret_cast<const sgx_aes_gcm_128bit_key_t *>(key.getData()), plainText.getData(), plainText.getSize(), pEncryptedText, iv.getData(), IV_SIZE, aad.getData(), aad.getSize(), reinterpret_cast<sgx_aes_gcm_128bit_tag_t *>(pMAC)); if (SGX_SUCCESS != sgx_status) { status = AE_FAILURE; break; } status = AE_SUCCESS; } while (0); return status; }
//Function to create data for ProvMsg3 generation // The sigrl of ProvMsg2 will processed in this function in piece-meal method //@msg2_blob_input: structure to hold decoded data of ProvMsg2 //@performance_rekey_used[in]: 1 if performance rekey used or 0 if not //@msg3_parm: structure to hold most information to generate ProvMsg3 //@msg3_output: structure to hold output data to create ProvMsg3 //@emp_epid_sig: output buffer to external memory for variable length EpidSignature //@epid_sig_buffer_size: size in bytes of buffer emp_epid_sig //@return PVEC_SUCCESS on success and error code if failed pve_status_t gen_prov_msg3_data(const proc_prov_msg2_blob_input_t *msg2_blob_input, prov_msg3_parm_t& msg3_parm, uint8_t performance_rekey_used, gen_prov_msg3_output_t *msg3_output, external_memory_byte_t *emp_epid_sig, uint32_t epid_sig_buffer_size) { pve_status_t ret = PVEC_SUCCESS; sgx_status_t sgx_status = SGX_ERROR_UNEXPECTED; uint8_t temp_buf[JOIN_PROOF_TLV_TOTAL_SIZE]; uint8_t *data_to_encrypt = NULL; uint8_t size_to_encrypt = 0; uint8_t pwk2_tlv_buffer[PWK2_TLV_TOTAL_SIZE]; sgx_key_128bit_t *pwk2=reinterpret_cast<sgx_key_128bit_t *>(pwk2_tlv_buffer+PWK2_TLV_HEADER_SIZE); uint8_t report_data_payload[MAC_SIZE + HARD_CODED_JOIN_PROOF_WITH_ESCROW_TLV_SIZE + NONCE_2_SIZE + PEK_MOD_SIZE]; uint8_t* pdata = &report_data_payload[0]; sgx_report_data_t report_data = { 0 }; uint8_t aad[sizeof(GroupId)+sizeof(device_id_t)+CHALLENGE_NONCE_SIZE]; void *pub_key = NULL; const signed_pek_t& pek = msg2_blob_input->pek; uint32_t le_e; int i; size_t output_len = 0; uint8_t le_n[sizeof(pek.n)]; static_assert(sizeof(pek.n)==384, "pek.n should be 384 bytes"); device_id_t *device_id_in_aad= (device_id_t *)(aad+sizeof(GroupId)); join_proof_with_escrow_t* join_proof_with_escrow=reinterpret_cast<join_proof_with_escrow_t *>(temp_buf+JOIN_PROOF_TLV_HEADER_SIZE); se_static_assert(sizeof(join_proof_with_escrow_t)+JOIN_PROOF_TLV_HEADER_SIZE==JOIN_PROOF_TLV_TOTAL_SIZE); /*unmatched hardcoded size*/ se_static_assert(sizeof(sgx_key_128bit_t)==PWK2_TLV_TOTAL_SIZE-PWK2_TLV_HEADER_SIZE); /*unmatched PWK2 size*/ memset(temp_buf, 0 ,sizeof(temp_buf)); memset(aad, 0, sizeof(aad)); memset(pwk2, 0, sizeof(sgx_key_128bit_t)); memcpy(pwk2_tlv_buffer, PWK2_TLV_HEADER, PWK2_TLV_HEADER_SIZE); msg3_output->is_join_proof_generated=false; msg3_output->is_epid_sig_generated=false; if ((msg2_blob_input->pce_target_info.attributes.flags & SGX_FLAGS_PROVISION_KEY) != SGX_FLAGS_PROVISION_KEY || (msg2_blob_input->pce_target_info.attributes.flags & SGX_FLAGS_DEBUG) != 0){ //PCE must have access to provisioning key //Can't be debug PCE ret = PVEC_PARAMETER_ERROR; goto ret_point; } if(!performance_rekey_used){ //the temp_buf used for join_proof_with_escrow tlv memcpy(temp_buf, JOIN_PROOF_TLV_HEADER, JOIN_PROOF_TLV_HEADER_SIZE);//first copy in tlv header ret = random_stack_advance(gen_msg3_join_proof_escrow_data, msg2_blob_input, *join_proof_with_escrow);//generate the tlv payload if( PVEC_SUCCESS != ret ) goto ret_point; msg3_output->is_join_proof_generated = true; data_to_encrypt = temp_buf; size_to_encrypt = JOIN_PROOF_TLV_TOTAL_SIZE; } //now encrypt field1 ret = se_read_rand_error_to_pve_error(sgx_read_rand(msg3_output->field1_iv, IV_SIZE));//randomly generate IV if( PVEC_SUCCESS != ret) goto ret_point; memcpy(aad, &msg2_blob_input->group_cert.key.gid,sizeof(GroupId));//start to prepare AAD memcpy(&device_id_in_aad->fmsp, &msg2_blob_input->equiv_pi.fmsp, sizeof(fmsp_t)); memcpy(&device_id_in_aad->psvn.cpu_svn, &msg2_blob_input->equiv_pi.cpu_svn, sizeof(sgx_cpu_svn_t)); memcpy(&device_id_in_aad->psvn.isv_svn, &msg2_blob_input->equiv_pi.pve_svn, sizeof(sgx_isv_svn_t)); memset(&device_id_in_aad->ppid, 0, sizeof(device_id_in_aad->ppid)); ret = pve_rng_generate(NONCE_2_SIZE*8, msg3_output->n2); if(PVEC_SUCCESS !=ret){ goto ret_point; } ret = random_stack_advance(get_pwk2, &device_id_in_aad->psvn, msg3_output->n2, pwk2); if( PVEC_SUCCESS != ret ) goto ret_point; memcpy(aad+sizeof(GroupId)+sizeof(device_id_t), msg2_blob_input->challenge_nonce, CHALLENGE_NONCE_SIZE); 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*/ 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*/ sgx_status = sgx_rijndael128GCM_encrypt(reinterpret_cast<const sgx_aes_gcm_128bit_key_t *>(pwk2), data_to_encrypt, size_to_encrypt, msg3_output->field1_data, msg3_output->field1_iv, IV_SIZE, aad, static_cast<uint32_t>(sizeof(GroupId)+sizeof(device_id_t)+CHALLENGE_NONCE_SIZE), reinterpret_cast<sgx_aes_gcm_128bit_tag_t *>(msg3_output->field1_mac));//encrypt field1 if(SGX_SUCCESS != sgx_status){ ret = sgx_error_to_pve_error(sgx_status); goto ret_point; } if( msg2_blob_input->is_previous_pi_provided ){ //preparing the encryption state of ProvMsg3 and encrypt inplace of msg3_inside enclave (field1_0 and field1_1) //The function will randomly set the iv value too ret = proc_msg3_state_init(&msg3_parm, pwk2); if( PVEC_SUCCESS!=ret ) goto ret_point; //Now start piece-meal generation of EPIDsign ret = gen_msg3_signature(msg2_blob_input, &msg3_parm, emp_epid_sig, epid_sig_buffer_size); if( PVEC_SUCCESS!=ret ) goto ret_point; msg3_output->is_epid_sig_generated = true; msg3_output->epid_sig_output_size = epid_sig_buffer_size; memcpy(msg3_output->epid_sig_iv, msg3_parm.iv, IV_SIZE); //generate MAC in EPC ret = sgx_error_to_pve_error(sgx_aes_gcm128_enc_get_mac(msg3_output->epid_sig_mac, (sgx_aes_state_handle_t*)msg3_parm.p_msg3_state)); if (PVEC_SUCCESS != ret) goto ret_point; } le_e = lv_ntohl(pek.e); se_static_assert(sizeof(pek.n)==sizeof(le_n)); /*unmatched size of pek.n*/ //endian swap for(i=0;i<(int)(sizeof(pek.n)/sizeof(pek.n[0]));i++){ le_n[i]=pek.n[sizeof(pek.n)/sizeof(pek.n[0])-i-1]; } sgx_status = sgx_create_rsa_pub_key(sizeof(pek.n), sizeof(pek.e), reinterpret_cast<const unsigned char *>(le_n), reinterpret_cast<const unsigned char *>(&le_e), &pub_key); if (SGX_SUCCESS != sgx_status) { ret = sgx_error_to_pve_error(sgx_status); goto ret_point; } sgx_status = sgx_rsa_pub_encrypt_sha256(pub_key, NULL, &output_len, reinterpret_cast<const unsigned char*>(pwk2_tlv_buffer), PWK2_TLV_TOTAL_SIZE); if (SGX_SUCCESS != sgx_status) { ret = sgx_error_to_pve_error(sgx_status); goto ret_point; } sgx_status = sgx_rsa_pub_encrypt_sha256(pub_key, msg3_output->encrypted_pwk2, &output_len, reinterpret_cast<const unsigned char*>(pwk2_tlv_buffer), PWK2_TLV_TOTAL_SIZE); if (SGX_SUCCESS != sgx_status) { ret = sgx_error_to_pve_error(sgx_status); goto ret_point; } // X = (NT)MAC_PWK2(... (NT)E_PWK2((T)(JoinP, f)) ...) | (NT)E_PWK2((T)(JoinP, f)) | (NT)PWK2N | (NT)E_PEK((T)PWK2) // REPORT.ReportData == SHA256[X] memcpy(pdata, msg3_output->field1_mac, MAC_SIZE); pdata += MAC_SIZE; if (!performance_rekey_used){ memcpy(pdata, msg3_output->field1_data, HARD_CODED_JOIN_PROOF_WITH_ESCROW_TLV_SIZE); pdata += HARD_CODED_JOIN_PROOF_WITH_ESCROW_TLV_SIZE; } memcpy(pdata, msg3_output->n2, NONCE_2_SIZE); pdata += NONCE_2_SIZE; memcpy(pdata, msg3_output->encrypted_pwk2, PEK_MOD_SIZE); pdata += PEK_MOD_SIZE; se_static_assert(sizeof(report_data) >= sizeof(sgx_sha256_hash_t)); /*report data is no large enough*/ sgx_status = sgx_sha256_msg(report_data_payload, (uint32_t)(pdata - &report_data_payload[0]), reinterpret_cast<sgx_sha256_hash_t *>(&report_data)); if (SGX_SUCCESS != sgx_status){ ret = sgx_error_to_pve_error(sgx_status); goto ret_point; } sgx_status = sgx_create_report(&msg2_blob_input->pce_target_info, &report_data, &msg3_output->pwk2_report); if (SGX_SUCCESS != sgx_status){ ret = sgx_error_to_pve_error(sgx_status); goto ret_point; } ret_point: (void)memset_s(aad, sizeof(aad), 0, sizeof(aad)); (void)memset_s(temp_buf, sizeof(temp_buf), 0, sizeof(temp_buf)); (void)memset_s(pwk2_tlv_buffer, sizeof(pwk2_tlv_buffer),0,sizeof(pwk2_tlv_buffer)); if(pub_key){ sgx_free_rsa_key(pub_key, SGX_RSA_PUBLIC_KEY, sizeof(pek.n), sizeof(pek.e)); } return ret; }
//Function to generate Field1_0 of ProvMsg3 //@msg2_blob_input, input decoded ProvMsg2 info //@join_proof, output the join proof and the escrow data which is encrypted f of Private Key //@return PVEC_SUCCESS on success and error code on failure //The function assume all required inputs have been prepared in msg2_blob_input static pve_status_t gen_msg3_join_proof_escrow_data(const proc_prov_msg2_blob_input_t *msg2_blob_input, join_proof_with_escrow_t& join_proof) { pve_status_t ret = PVEC_SUCCESS; BitSupplier epid_prng = (BitSupplier) epid_random_func; FpElemStr temp_f; //first generate private key f randomly before sealing it by PSK FpElemStr *f = &temp_f; sgx_status_t sgx_status = SGX_SUCCESS; JoinRequest *join_r = &join_proof.jr; EpidStatus epid_ret = kEpidNoErr; psvn_t psvn; MemberCtx* ctx = NULL; memset(&temp_f, 0, sizeof(temp_f)); //randomly generate the private EPID key f, host to network transformation not required since server will not decode it ret=sgx_error_to_pve_error(sgx_gen_epid_priv_f((void*)f)); if(PVEC_SUCCESS != ret){ goto ret_point; } //generate JoinP using f before encryption by calling EPID library memset(join_r, 0, sizeof(JoinRequest));//first clear to 0 //generate JoinP to fill it in field1_0_0 by EPID library epid_ret = epid_member_create(epid_prng, NULL, f, &ctx); if(kEpidNoErr!=epid_ret){ ret = epid_error_to_pve_error(epid_ret); goto ret_point; } epid_ret = EpidCreateJoinRequest(ctx, &msg2_blob_input->group_cert.key, //EPID Group Cert from ProvMsgs2 used reinterpret_cast<const IssuerNonce *>(msg2_blob_input->challenge_nonce), join_r); if(kEpidNoErr != epid_ret){ ret = epid_error_to_pve_error(epid_ret); goto ret_point; } //get PSK sgx_key_128bit_t psk; memcpy(&psvn.cpu_svn, &msg2_blob_input->equiv_pi.cpu_svn, sizeof(psvn.cpu_svn)); memcpy(&psvn.isv_svn, &msg2_blob_input->equiv_pi.pve_svn, sizeof(psvn.isv_svn)); ret = get_pve_psk(&psvn, &psk); if(PVEC_SUCCESS != ret){ goto ret_point; } join_proof.escrow.version = 0;//version 0 used for escrow data //now we could seal f by PSK ret = se_read_rand_error_to_pve_error(sgx_read_rand(join_proof.escrow.iv, IV_SIZE)); if(PVEC_SUCCESS != ret){ goto ret_point; } 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*/ 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*/ sgx_status = sgx_rijndael128GCM_encrypt(reinterpret_cast<const sgx_aes_gcm_128bit_key_t *>(&psk), reinterpret_cast<uint8_t *>(f), sizeof(*f), reinterpret_cast<uint8_t *>(&join_proof.escrow.f), join_proof.escrow.iv, IV_SIZE, NULL, 0, reinterpret_cast<sgx_aes_gcm_128bit_tag_t *>(join_proof.escrow.mac)); if(SGX_SUCCESS != sgx_status){ ret = sgx_error_to_pve_error(sgx_status); } ret_point: (void)memset_s(&psk, sizeof(psk), 0, sizeof(psk));//clear the key (void)memset_s(&temp_f, sizeof(temp_f), 0, sizeof(temp_f));//clear temp f in stack if(PVEC_SUCCESS != ret){ (void)memset_s(&join_proof, sizeof(join_proof), 0, sizeof(join_proof)); } epid_member_delete(&ctx); return ret; }
uint32_t CPVEClass::gen_prov_msg1( pve_data_t &pve_data, uint8_t *msg1, uint32_t msg1_size) { uint32_t ret = AE_SUCCESS; uint16_t pce_id = 0; uint16_t pce_isv_svn = 0; sgx_report_t pek_report; uint8_t *field2 = NULL; uint8_t field2_iv[IV_SIZE]; uint8_t field2_mac[MAC_SIZE]; uint8_t encrypted_ppid[RSA_3072_KEY_BYTES]; //msg1 header will be in the beginning part of the output msg provision_request_header_t *msg1_header = reinterpret_cast<provision_request_header_t *>(msg1); memset(&pek_report, 0, sizeof(pek_report)); sgx_target_info_t pce_target_info; sgx_status_t sgx_status; //Load PCE Enclave required ret = CPCEClass::instance().load_enclave(); if(ret != AE_SUCCESS){ AESM_DBG_ERROR("Fail to load PCE enclave:( ae%d)\n",ret); return ret; } ret = CPCEClass::instance().get_pce_target(&pce_target_info); if(ret != AE_SUCCESS){ AESM_DBG_ERROR("Fail to get PCE target info:( ae %d)\n",ret); return ret; } //Load PvE enclave now ret = CPVEClass::instance().load_enclave(); if( ret != AE_SUCCESS){ AESM_DBG_ERROR("Fail to load PvE enclave:(ae%d)\n",ret); return ret; } //The code will generate a report on PEK by PvE ret = gen_prov_msg1_data(&pve_data.pek, &pce_target_info, &pek_report); if(AE_SUCCESS != ret ){ AESM_DBG_ERROR("Gen ProvMsg1 in trusted code failed:( ae %d)",ret); return ret; } se_static_assert(sizeof(encrypted_ppid)==PEK_MOD_SIZE); //Load PCE Enclave required ret = CPCEClass::instance().load_enclave(); if(ret != AE_SUCCESS){ AESM_DBG_ERROR("Fail to load PCE enclave:( ae %d)\n",ret); return ret; } ret = CPCEClass::instance().get_pce_info(pek_report, pve_data.pek, pce_id, pce_isv_svn, encrypted_ppid); if(AE_SUCCESS != ret){ AESM_DBG_ERROR("Fail to generate pc_info:(ae%d)",ret); return ret; } //randomly generate XID ret = aesm_read_rand(pve_data.xid, XID_SIZE); if(AE_SUCCESS != ret ){ AESM_DBG_ERROR("Fail to generate random XID (ae%d)",ret); return ret; } //randomly generate SK ret = aesm_read_rand(pve_data.sk, SK_SIZE); if(AE_SUCCESS != ret ){ AESM_DBG_ERROR("Fail to generate random SK (ae%d)",ret); return ret; } CPCEClass::instance().unload_enclave(); ret = prov_msg1_gen_header(msg1_header, pve_data.is_performance_rekey, pve_data.xid, msg1_size); if(AE_SUCCESS != ret){ AESM_DBG_ERROR("fail to generate ProvMsg1 Header:(ae %d)",ret); return ret; } { TLVsMsg tlvs_msg1_sub; tlv_status_t tlv_status; sgx_sha256_hash_t psid; tlv_status = tlvs_msg1_sub.add_block_cipher_info(pve_data.sk); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS!=ret){ AESM_DBG_ERROR("Fail to generate SK TLV of ProvMsg1 (ae %d)",ret); return ret; } sgx_status = sgx_sha256_msg(reinterpret_cast<const uint8_t *>(&pve_data.pek.n), static_cast<uint32_t>(sizeof(pve_data.pek.n) + sizeof(pve_data.pek.e)), &psid); if(SGX_SUCCESS != sgx_status){ AESM_DBG_ERROR("Fail to generate PSID, (sgx0x%x)",sgx_status); return AE_FAILURE; } se_static_assert(sizeof(sgx_sha256_hash_t)==sizeof(psid_t)); tlv_status = tlvs_msg1_sub.add_psid(reinterpret_cast<const psid_t *>(&psid)); ret = tlv_error_2_pve_error(tlv_status); if(SGX_SUCCESS != ret){ AESM_DBG_ERROR("Fail to add PSID TLV ae(%d)",ret); return ret; } //transform rsa format PEK public key of Provision Server void *rsa_pub_key = NULL; signed_pek_t le_pek{}; // Change the endian for the PEK public key for(uint32_t i = 0; i< sizeof(le_pek.n); i++) { le_pek.n[i] = pve_data.pek.n[sizeof(le_pek.n) - i - 1]; } for(uint32_t i= 0; i < sizeof(le_pek.e); i++) { le_pek.e[i] = pve_data.pek.e[sizeof(le_pek.e) - i - 1]; } sgx_status = get_provision_server_rsa_pub_key(le_pek, &rsa_pub_key); if( SGX_SUCCESS != sgx_status){ AESM_DBG_ERROR("Fail to decode PEK:%d",sgx_status); return AE_FAILURE; } uint8_t field0[RSA_3072_KEY_BYTES]; ret = aesm_rsa_oaep_encrypt(tlvs_msg1_sub.get_tlv_msg(), tlvs_msg1_sub.get_tlv_msg_size(), rsa_pub_key, field0); sgx_free_rsa_key(rsa_pub_key, SGX_RSA_PUBLIC_KEY, RSA_3072_KEY_BYTES, sizeof(le_pek.e)); if(AE_SUCCESS!=ret){ AESM_DBG_ERROR("Fail to in RSA_OAEP for ProvMsg1:(ae%d)",ret); return ret; } TLVsMsg tlvs_msg1; tlv_status= tlvs_msg1.add_cipher_text(field0, RSA_3072_KEY_BYTES, PEK_3072_PUB); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS!=ret){ AESM_DBG_ERROR("Fail to generate field0 TLV of ProvMsg1( ae%d)",ret); return ret; } TLVsMsg tlvs_msg2_sub; tlv_status = tlvs_msg2_sub.add_cipher_text(encrypted_ppid, RSA_3072_KEY_BYTES, PEK_3072_PUB); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS!=ret){ return ret; } if(!pve_data.is_backup_retrieval){ if(0!=memcpy_s(&pve_data.bpi.cpu_svn, sizeof(pve_data.bpi.cpu_svn), &pek_report.body.cpu_svn, sizeof(pek_report.body.cpu_svn))){ AESM_DBG_FATAL("fail in memcpy_s"); return PVE_UNEXPECTED_ERROR; } if(0!=memcpy_s(&pve_data.bpi.pve_svn, sizeof(pve_data.bpi.pve_svn), &pek_report.body.isv_svn, sizeof(pek_report.body.isv_svn))){ AESM_DBG_FATAL("fail in memcpy_s"); return PVE_UNEXPECTED_ERROR; } if(0!=memcpy_s(&pve_data.bpi.pce_svn, sizeof(pve_data.bpi.pce_svn), &pce_isv_svn, sizeof(pce_isv_svn))){ AESM_DBG_FATAL("fail in memcpy_s"); return PVE_UNEXPECTED_ERROR; } } //always use pce_id from PCE enclave pve_data.bpi.pce_id = pce_id; memset(&pve_data.bpi.fmsp, 0, sizeof(pve_data.bpi.fmsp)); tlv_status = tlvs_msg2_sub.add_platform_info(pve_data.bpi); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS != ret){ AESM_DBG_ERROR("Fail to generate Platform Info TLV of ProvMsg1 (ae%d)",ret); return ret; } if(pve_data.is_performance_rekey){ flags_t flags; memset(&flags,0,sizeof(flags)); //set performance rekey flags flags.flags[FLAGS_SIZE-1]=1; tlv_status = tlvs_msg2_sub.add_flags(&flags); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS != ret){ AESM_DBG_ERROR("Fail to generate FLAGS TLV of ProvMsg1, (ae %d)",ret); return ret; } } ret = aesm_read_rand(field2_iv, IV_SIZE); if(AE_SUCCESS != ret){ AESM_DBG_ERROR("Fail to read rand:(ae%d)",ret); return ret; } sgx_cmac_128bit_tag_t ek1; se_static_assert(SK_SIZE==sizeof(sgx_cmac_128bit_key_t)); if((sgx_status = sgx_rijndael128_cmac_msg(reinterpret_cast<const sgx_cmac_128bit_key_t *>(pve_data.sk), pve_data.xid, XID_SIZE, &ek1))!=SGX_SUCCESS){ AESM_DBG_ERROR("Fail to generate ek1:(sgx%d)",sgx_status); return AE_FAILURE; } field2 = (uint8_t *)malloc(tlvs_msg2_sub.get_tlv_msg_size()); if(NULL == field2){ AESM_DBG_ERROR("Out of memory"); return AE_OUT_OF_MEMORY_ERROR; } sgx_status = sgx_rijndael128GCM_encrypt(&ek1, tlvs_msg2_sub.get_tlv_msg(), tlvs_msg2_sub.get_tlv_msg_size(), field2,field2_iv, IV_SIZE, (const uint8_t *)msg1_header, sizeof(provision_request_header_t), (sgx_aes_gcm_128bit_tag_t *)field2_mac); if(SGX_SUCCESS != sgx_status){ ret = sgx_error_to_ae_error(sgx_status); AESM_DBG_ERROR("Fail to do AES encrypt (sgx %d)", sgx_status); free(field2); return ret; } tlv_status = tlvs_msg1.add_block_cipher_text(field2_iv, field2, tlvs_msg2_sub.get_tlv_msg_size()); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS!=ret){ free(field2); AESM_DBG_ERROR("Fail to generate field1 TLV of ProvMsg1(ae%d)",ret); return ret; } free(field2); tlv_status = tlvs_msg1.add_mac(field2_mac); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS!=ret){ AESM_DBG_ERROR("Fail to create field2 TLV of ProvMsg1:(ae %d)",ret); return ret; } uint32_t size = tlvs_msg1.get_tlv_msg_size(); if(memcpy_s(msg1+PROVISION_REQUEST_HEADER_SIZE, msg1_size - PROVISION_REQUEST_HEADER_SIZE, tlvs_msg1.get_tlv_msg(), size)!=0){ //The size overflow has been checked in header generation AESM_DBG_FATAL("fail in memcpy_s"); return PVE_UNEXPECTED_ERROR; } } return AE_SUCCESS; }
bool protected_fs_file::update_all_data_and_mht_nodes() { std::list<file_mht_node_t*> mht_list; std::list<file_mht_node_t*>::iterator mht_list_it; file_mht_node_t* file_mht_node; sgx_status_t status; void* data = cache.get_first(); // 1. encrypt the changed data // 2. set the IV+GMAC in the parent MHT // [3. set the need_writing flag for all the parents] while (data != NULL) { if (((file_data_node_t*)data)->type == FILE_DATA_NODE_TYPE) // type is in the same offset in both node types { file_data_node_t* data_node = (file_data_node_t*)data; if (data_node->need_writing == true) { if (derive_random_node_key(data_node->physical_node_number) == false) return false; gcm_crypto_data_t* gcm_crypto_data = &data_node->parent->plain.data_nodes_crypto[data_node->data_node_number % ATTACHED_DATA_NODES_COUNT]; // encrypt the data, this also saves the gmac of the operation in the mht crypto node status = sgx_rijndael128GCM_encrypt(&cur_key, data_node->plain.data, NODE_SIZE, data_node->encrypted.cipher, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac); if (status != SGX_SUCCESS) { last_error = status; return false; } memcpy(gcm_crypto_data->key, cur_key, sizeof(sgx_aes_gcm_128bit_key_t)); // save the key used for this encryption file_mht_node = data_node->parent; // this loop should do nothing, add it here just to be safe while (file_mht_node->mht_node_number != 0) { assert(file_mht_node->need_writing == true); file_mht_node->need_writing = true; // just in case, for release file_mht_node = file_mht_node->parent; } } } data = cache.get_next(); } // add all the mht nodes that needs writing to a list data = cache.get_first(); while (data != NULL) { if (((file_mht_node_t*)data)->type == FILE_MHT_NODE_TYPE) // type is in the same offset in both node types { file_mht_node = (file_mht_node_t*)data; if (file_mht_node->need_writing == true) mht_list.push_front(file_mht_node); } data = cache.get_next(); } // sort the list from the last node to the first (bottom layers first) mht_list.sort(mht_order); // update the gmacs in the parents while ((mht_list_it = mht_list.begin()) != mht_list.end()) { file_mht_node = *mht_list_it; gcm_crypto_data_t* gcm_crypto_data = &file_mht_node->parent->plain.mht_nodes_crypto[(file_mht_node->mht_node_number - 1) % CHILD_MHT_NODES_COUNT]; if (derive_random_node_key(file_mht_node->physical_node_number) == false) { mht_list.clear(); return false; } status = sgx_rijndael128GCM_encrypt(&cur_key, (const uint8_t*)&file_mht_node->plain, NODE_SIZE, file_mht_node->encrypted.cipher, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac); if (status != SGX_SUCCESS) { mht_list.clear(); last_error = status; return false; } memcpy(gcm_crypto_data->key, cur_key, sizeof(sgx_aes_gcm_128bit_key_t)); // save the key used for this gmac mht_list.pop_front(); } // update mht root gmac in the meta data node if (derive_random_node_key(root_mht.physical_node_number) == false) return false; status = sgx_rijndael128GCM_encrypt(&cur_key, (const uint8_t*)&root_mht.plain, NODE_SIZE, root_mht.encrypted.cipher, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &encrypted_part_plain.mht_gmac); if (status != SGX_SUCCESS) { last_error = status; return false; } memcpy(&encrypted_part_plain.mht_key, cur_key, sizeof(sgx_aes_gcm_128bit_key_t)); // save the key used for this gmac return true; }