static ae_error_t prov_es_gen_header(provision_request_header_t *es_header, const uint8_t *xid, uint32_t msg_buffer_size) { uint32_t total_size = 0; total_size = ES_SELECTOR_TLV_SIZE(); //initialize ES Msg1 Header es_header->protocol = ENDPOINT_SELECTION; es_header->type = TYPE_ES_MSG1; es_header->version = TLV_VERSION_1; if(0!=memcpy_s(es_header->xid, XID_SIZE, xid, XID_SIZE)){ AESM_DBG_FATAL("memcpy error"); return PVE_UNEXPECTED_ERROR; } uint32_t size_in; size_in = _htonl(total_size);//big endian size required in msg header if(0!=memcpy_s(&es_header->size,sizeof(es_header->size), &size_in, sizeof(size_in))){ AESM_DBG_FATAL("memcpy error"); return PVE_UNEXPECTED_ERROR; } if(total_size +sizeof(*es_header) >msg_buffer_size){//the input msg body buffer size is not large enough AESM_DBG_ERROR("input msg buffer is too small"); return PVE_INSUFFICIENT_MEMORY_ERROR; } return AE_SUCCESS; }
uint32_t CPVEClass::gen_es_msg1( uint8_t *msg, uint32_t msg_size, const gen_endpoint_selection_output_t& es_output) { ae_error_t ret; AESM_PROFILE_FUN; if(msg_size < PROVISION_REQUEST_HEADER_SIZE) return PVE_INSUFFICIENT_MEMORY_ERROR; provision_request_header_t *es_header = reinterpret_cast<provision_request_header_t *>(msg); ret = prov_es_gen_header(es_header, es_output.xid, msg_size); if(AE_SUCCESS != ret){ AESM_DBG_ERROR("Fail to generate Endpoint Selection Msg1 Header:%d",ret); return ret; } { TLVsMsg tlvs_msg; tlv_status_t tlv_status = tlvs_msg.add_es_selector(SE_EPID_PROVISIONING, es_output.selector_id); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS!=ret){ AESM_DBG_ERROR("fail to create ES Selector TLV:%d",ret); return ret; } assert(tlvs_msg.get_tlv_msg_size()<=msg_size - PROVISION_REQUEST_HEADER_SIZE); //The checking should have been done in prov_es_gen_header if(0!=memcpy_s(msg+PROVISION_REQUEST_HEADER_SIZE, msg_size-PROVISION_REQUEST_HEADER_SIZE, tlvs_msg.get_tlv_msg(), tlvs_msg.get_tlv_msg_size())){ AESM_DBG_FATAL("memcpy failed"); return PVE_UNEXPECTED_ERROR; } return AE_SUCCESS; } }
aesm_error_t AESMLogic::get_launch_token( const uint8_t * mrenclave, uint32_t mrenclave_size, const uint8_t *public_key, uint32_t public_key_size, const uint8_t *se_attributes, uint32_t se_attributes_size, uint8_t * lictoken, uint32_t lictoken_size) { AESM_DBG_INFO("enter function"); CHECK_SERVICE_STATUS; AESMLogicLock lock(_le_mutex); CHECK_SERVICE_STATUS; ae_error_t ret_le = AE_SUCCESS; if (NULL == mrenclave || NULL == public_key || NULL == se_attributes || NULL == lictoken) { //sizes are checked in CLEClass::get_launch_token() AESM_DBG_TRACE("Invalid parameter"); return AESM_PARAMETER_ERROR; } ae_error_t ae_ret = CLEClass::instance().load_enclave(); if(ae_ret == AE_SERVER_NOT_AVAILABLE) { AESM_LOG_ERROR("%s", g_event_string_table[SGX_EVENT_SERVICE_UNAVAILABLE]); AESM_DBG_FATAL("LE not loaded due to AE_SERVER_NOT_AVAILABLE, possible SGX Env Not Ready"); return AESM_NO_DEVICE_ERROR; } else if(AE_FAILED(ae_ret)) { AESM_DBG_ERROR("LE not loaded:%d", ae_ret); return AESM_UNEXPECTED_ERROR; } ret_le = static_cast<ae_error_t>(CLEClass::instance().get_launch_token( const_cast<uint8_t *>(mrenclave), mrenclave_size, const_cast<uint8_t *>(public_key), public_key_size, const_cast<uint8_t *>(se_attributes), se_attributes_size, lictoken, lictoken_size)); switch (ret_le) { case AE_SUCCESS: return AESM_SUCCESS; case LE_INVALID_PARAMETER: AESM_DBG_TRACE("Invalid parameter"); return AESM_PARAMETER_ERROR; case LE_INVALID_ATTRIBUTE: case LE_INVALID_PRIVILEGE_ERROR: AESM_DBG_TRACE("Launch token error"); return AESM_GET_LICENSETOKEN_ERROR; case LE_WHITELIST_UNINITIALIZED_ERROR: AESM_DBG_TRACE("LE whitelist uninitialized error"); return AESM_UNEXPECTED_ERROR; default: AESM_DBG_WARN("unexpeted error %d", ret_le); return AESM_UNEXPECTED_ERROR; } }
//Function to initialize request header for ProvMsg1 //msg1_header: request header for ProvMsg1 to fill in //use_flags: whether the flag tlv is included //xid: transaction ID //msg1_buffer_size: buffer size for ProvMsg1, in bytes static ae_error_t prov_msg1_gen_header(provision_request_header_t *msg1_header, bool use_flags, const uint8_t *xid, uint32_t msg1_buffer_size) { uint32_t total_size = 0; //platform info tlv size uint32_t field1_data_size = PLATFORM_INFO_TLV_SIZE(); field1_data_size += CIPHER_TEXT_TLV_SIZE(RSA_3072_KEY_BYTES); //add flag tlv if needed if(use_flags){ field1_data_size += FLAGS_TLV_SIZE(); } if(sizeof(*msg1_header)>msg1_buffer_size){ AESM_DBG_ERROR("Too small ProvMsg1 buffer size"); return PVE_INSUFFICIENT_MEMORY_ERROR; } total_size = CIPHER_TEXT_TLV_SIZE(RSA_3072_KEY_BYTES) + BLOCK_CIPHER_TEXT_TLV_SIZE(field1_data_size) +MAC_TLV_SIZE(MAC_SIZE); //initialize Msg1 Header msg1_header->protocol = SE_EPID_PROVISIONING; msg1_header->type = TYPE_PROV_MSG1; msg1_header->version = TLV_VERSION_2; if(0!=memcpy_s(msg1_header->xid, sizeof(msg1_header->xid), xid, XID_SIZE)){ AESM_DBG_FATAL("fail in memcpy_s"); return PVE_UNEXPECTED_ERROR; } uint32_t size_in; //use as a tmp size, big endian required in msg header size_in = _htonl(total_size); //copy big endian msg body size into header if(0!=memcpy_s(&msg1_header->size, sizeof(msg1_header->size),&size_in, sizeof(size_in))){ AESM_DBG_FATAL("fail in memcpy_s"); return PVE_UNEXPECTED_ERROR; } if(total_size +sizeof(*msg1_header) >msg1_buffer_size){ //the input msg body size is not large enough AESM_DBG_ERROR("Too small ProvMsg1 buffer size"); return PVE_INSUFFICIENT_MEMORY_ERROR; } return AE_SUCCESS; }
//Function to decode ProvMsg4 and generate epid data blob uint32_t CPVEClass::proc_prov_msg4( bool use_ek2_in_input, const uint8_t ek2[SK_SIZE], const uint8_t* msg4, uint32_t msg4_size, uint8_t* data_blob, uint32_t blob_size) { ae_error_t ret = AE_SUCCESS; uint8_t local_ek2[SK_SIZE]; uint8_t *decoded_msg4 = NULL; const provision_response_header_t *msg4_header = reinterpret_cast<const provision_response_header_t *>(msg4); if(msg4_size < PROVISION_RESPONSE_HEADER_SIZE){ AESM_DBG_ERROR("invalid msg4 size"); return PVE_MSG_ERROR; } if(blob_size != HARD_CODED_EPID_BLOB_SIZE){ AESM_DBG_FATAL("invalid input epid blob size"); return PVE_PARAMETER_ERROR; } ret = check_prov_msg4_header(msg4_header, msg4_size); if( AE_SUCCESS != ret){ AESM_DBG_ERROR("Invalid ProvMsg4 Header:%d",ret); return ret; } ret = check_epid_pve_pg_status_before_mac_verification(msg4_header); if( AE_SUCCESS != ret){ AESM_DBG_ERROR("Backend return failure in ProvMsg4 Header:%d",ret); return ret; } do{ TLVsMsg tlvs_msg4; tlv_status_t tlv_status; tlv_status = tlvs_msg4.init_from_buffer(msg4+static_cast<uint32_t>(PROVISION_RESPONSE_HEADER_SIZE), msg4_size - static_cast<uint32_t>(PROVISION_RESPONSE_HEADER_SIZE)); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS!=ret){ AESM_DBG_ERROR("fail to decode ProvMsg4:%d",tlv_status); break; } ret = msg4_integrity_checking(tlvs_msg4); if(AE_SUCCESS != ret){ AESM_DBG_ERROR("ProvMsg4 integrity checking error:%d",ret); break; } AESM_DBG_TRACE("ProvMsg4 decoded"); if(!use_ek2_in_input){ //we need generate ek2 prov_get_ek2_input_t ek2_input; if(memcpy_s(ek2_input.nonce, NONCE_SIZE, MSG4_TOP_FIELD_NONCE.payload, NONCE_SIZE)!=0){ AESM_DBG_ERROR("fail in memcpy"); ret = PVE_UNEXPECTED_ERROR; break; } if(memcpy_s(ek2_input.xid, XID_SIZE, msg4_header->xid, XID_SIZE)!=0){ AESM_DBG_ERROR("fail in memcpy"); ret = PVE_UNEXPECTED_ERROR; break; } //call PvE to get EK2 se_static_assert(SK_SIZE == sizeof(prov_get_ek2_output_t)); ret = (ae_error_t)get_ek2(&ek2_input, reinterpret_cast<prov_get_ek2_output_t *>(local_ek2)); if(AE_SUCCESS != ret){ AESM_DBG_ERROR("fail to get EK2:%d",ret); break; } }else{//reuse ek2 generated in processing ProvMsg2 if(0!=memcpy_s(local_ek2, sizeof(local_ek2), ek2, SK_SIZE)){ AESM_DBG_ERROR("fail in memcpy"); ret = PVE_UNEXPECTED_ERROR; break; } } se_static_assert(SK_SIZE==sizeof(sgx_aes_gcm_128bit_key_t)); tlv_msg_t field1 = block_cipher_tlv_get_encrypted_text(MSG4_TOP_FIELD_DATA); decoded_msg4 = reinterpret_cast<uint8_t *>(malloc(field1.msg_size)); if(NULL == decoded_msg4){ AESM_DBG_ERROR("malloc error"); ret = AE_OUT_OF_MEMORY_ERROR; break; } sgx_status_t sgx_status = sgx_rijndael128GCM_decrypt(reinterpret_cast<const sgx_aes_gcm_128bit_key_t *>(local_ek2), field1.msg_buf, field1.msg_size, decoded_msg4, reinterpret_cast<uint8_t *>(block_cipher_tlv_get_iv(MSG4_TOP_FIELD_DATA)), IV_SIZE, reinterpret_cast<const uint8_t *>(msg4_header), PROVISION_RESPONSE_HEADER_SIZE, reinterpret_cast<const sgx_aes_gcm_128bit_tag_t *>(MSG4_TOP_FIELD_MAC.payload)); if(SGX_ERROR_MAC_MISMATCH == sgx_status){ AESM_DBG_ERROR("fail to decrypt ProvMsg4 by EK2"); ret = PVE_INTEGRITY_CHECK_ERROR; break; } if( AE_SUCCESS != (ret = sgx_error_to_ae_error(sgx_status))){ AESM_DBG_ERROR("error in decrypting ProvMsg4:%d",sgx_status); break; } AESM_DBG_TRACE("ProvMsg4 decrypted by EK2 successfully"); ret = check_epid_pve_pg_status_after_mac_verification(msg4_header); if(AE_SUCCESS != ret){ AESM_DBG_ERROR("Backend reported error passed MAC verification:%d",ret); break; } TLVsMsg tlvs_field1; tlv_status = tlvs_field1.init_from_buffer(decoded_msg4, field1.msg_size); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS != ret){ AESM_DBG_ERROR("ProvMsg4 Field2.1 decoding failed:%d",tlv_status); break; } ret = msg4_field1_msg_checking(tlvs_field1); if( AE_SUCCESS != ret){ AESM_DBG_ERROR("ProvMsg4 Field2.1 invalid:%d",ret); break; } proc_prov_msg4_input_t msg4_input; if(sizeof(proc_prov_msg4_output_t)!=SGX_TRUSTED_EPID_BLOB_SIZE){ AESM_DBG_FATAL("Trusted ProvMsg4 output buffer size error"); ret = PVE_UNEXPECTED_ERROR; break; } tlv_msg_t tcb_data = block_cipher_tlv_get_encrypted_text(MSG4_FIELD1_ENC_TCB); tlv_msg_t Axf_data = block_cipher_tlv_get_encrypted_text(MSG4_FIELD1_ENC_Axf); if(0!=memcpy_s(&msg4_input.group_cert, sizeof(msg4_input.group_cert), MSG4_FIELD1_GROUP_CERT.payload, MSG4_FIELD1_GROUP_CERT.size)|| 0!=memcpy_s(&msg4_input.equivalent_psvn, sizeof(psvn_t), device_id_tlv_get_psvn(MSG4_FIELD1_DEVICE_ID), sizeof(psvn_t))|| 0!=memcpy_s(&msg4_input.fmsp, sizeof(fmsp_t), device_id_tlv_get_fmsp(MSG4_FIELD1_DEVICE_ID), sizeof(fmsp_t))|| 0!=memcpy_s(&msg4_input.tcb_iv, IV_SIZE, block_cipher_tlv_get_iv(MSG4_FIELD1_ENC_TCB), IV_SIZE)|| 0!=memcpy_s(&msg4_input.encrypted_tcb, SK_SIZE, tcb_data.msg_buf, tcb_data.msg_size)|| 0!=memcpy_s(&msg4_input.tcb_mac, MAC_SIZE, MSG4_FIELD1_MAC_TCB.payload, MSG4_FIELD1_MAC_TCB.size)|| 0!=memcpy_s(&msg4_input.member_credential_iv, IV_SIZE, block_cipher_tlv_get_iv(MSG4_FIELD1_ENC_Axf), IV_SIZE)|| 0!=memcpy_s(&msg4_input.encrypted_member_credential, HARD_CODED_EPID_MEMBER_WITH_ESCROW_TLV_SIZE, Axf_data.msg_buf, Axf_data.msg_size)|| 0!=memcpy_s(&msg4_input.member_credential_mac, MAC_SIZE, MSG4_FIELD1_MAC_Axf.payload, MSG4_FIELD1_MAC_Axf.size)){ AESM_DBG_ERROR("memcpy error"); ret = PVE_UNEXPECTED_ERROR; break; } ret = (ae_error_t)proc_prov_msg4_data(&msg4_input, reinterpret_cast<proc_prov_msg4_output_t *>(data_blob)); AESM_DBG_TRACE("PvE return %d in Process ProvMsg4",ret); }while(0); if(decoded_msg4)free(decoded_msg4); return ret; }
//Function to decode ProvMsg4 and generate epid data blob uint32_t CPVEClass::proc_prov_msg4( const pve_data_t &data, const uint8_t *msg4, uint32_t msg4_size, uint8_t *data_blob, uint32_t blob_size) { ae_error_t ret = AE_SUCCESS; uint8_t local_ek2[SK_SIZE]; uint8_t *decoded_msg4 = NULL; uint8_t temp[XID_SIZE+NONCE_SIZE]; sgx_status_t sgx_status; const provision_response_header_t *msg4_header = reinterpret_cast<const provision_response_header_t *>(msg4); if(msg4_size < PROVISION_RESPONSE_HEADER_SIZE) { AESM_DBG_ERROR("invalid msg4 size"); return PVE_MSG_ERROR; } if (blob_size != SGX_TRUSTED_EPID_BLOB_SIZE_PAK) { AESM_DBG_FATAL("invalid input epid blob size"); return PVE_PARAMETER_ERROR; } ret = check_prov_msg4_header(msg4_header, msg4_size); if( AE_SUCCESS != ret) { AESM_DBG_ERROR("Invalid ProvMsg4 Header:(ae%d)",ret); return ret; } if(0!=memcmp(msg4_header->xid, data.xid, XID_SIZE)) { AESM_DBG_ERROR("Invalid XID in msg4 header"); return PVE_MSG_ERROR; } ret = check_epid_pve_pg_status_before_mac_verification(msg4_header); if( AE_SUCCESS != ret) { AESM_DBG_ERROR("Backend return failure in ProvMsg4 Header:(ae%d)",ret); return ret; } do { TLVsMsg tlvs_msg4; uint8_t aad[PROVISION_RESPONSE_HEADER_SIZE+NONCE_SIZE]; tlv_status_t tlv_status; tlv_status = tlvs_msg4.init_from_buffer(msg4+static_cast<uint32_t>(PROVISION_RESPONSE_HEADER_SIZE), msg4_size - static_cast<uint32_t>(PROVISION_RESPONSE_HEADER_SIZE)); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS!=ret) { AESM_DBG_ERROR("fail to decode ProvMsg4:(ae%d)",ret); break; } ret = msg4_integrity_checking(tlvs_msg4); if(AE_SUCCESS != ret) { AESM_DBG_ERROR("ProvMsg4 integrity checking error:(ae%d)",ret); break; } AESM_DBG_TRACE("ProvMsg4 decoded"); se_static_assert(sizeof(sgx_cmac_128bit_key_t)==SK_SIZE); if(0!=memcpy_s(temp,sizeof(temp), data.xid, XID_SIZE)|| 0!=memcpy_s(temp+XID_SIZE, sizeof(temp)-XID_SIZE, MSG4_TOP_FIELD_NONCE.payload, NONCE_SIZE)) { AESM_DBG_ERROR("Fail in memcpy"); ret = AE_FAILURE; break; } if((sgx_status=sgx_rijndael128_cmac_msg(reinterpret_cast<const sgx_cmac_128bit_key_t *>(data.sk), temp, XID_SIZE+NONCE_SIZE, reinterpret_cast<sgx_cmac_128bit_tag_t *>(local_ek2)))!=SGX_SUCCESS) { AESM_DBG_ERROR("Fail to generate ek2:(sgx0x%x)",sgx_status); ret = AE_FAILURE; break; } se_static_assert(SK_SIZE==sizeof(sgx_aes_gcm_128bit_key_t)); tlv_msg_t field1 = block_cipher_tlv_get_encrypted_text(MSG4_TOP_FIELD_DATA); decoded_msg4 = reinterpret_cast<uint8_t *>(malloc(field1.msg_size)); if(NULL == decoded_msg4) { AESM_DBG_ERROR("malloc error"); ret = AE_OUT_OF_MEMORY_ERROR; break; } if (memcpy_s(aad, sizeof(aad), msg4_header, PROVISION_RESPONSE_HEADER_SIZE) != 0 || memcpy_s(aad + PROVISION_RESPONSE_HEADER_SIZE, sizeof(aad)-PROVISION_RESPONSE_HEADER_SIZE, MSG4_TOP_FIELD_NONCE.payload, MSG4_TOP_FIELD_NONCE.size) != 0) { AESM_DBG_ERROR("memcpy failure"); ret = AE_FAILURE; break; } sgx_status_t sgx_status = sgx_rijndael128GCM_decrypt(reinterpret_cast<const sgx_aes_gcm_128bit_key_t *>(local_ek2), field1.msg_buf, field1.msg_size, decoded_msg4, reinterpret_cast<uint8_t *>(block_cipher_tlv_get_iv(MSG4_TOP_FIELD_DATA)), IV_SIZE, aad, sizeof(aad), reinterpret_cast<const sgx_aes_gcm_128bit_tag_t *>(MSG4_TOP_FIELD_MAC.payload)); if(SGX_ERROR_MAC_MISMATCH == sgx_status) { AESM_DBG_ERROR("fail to decrypt ProvMsg4 by EK2 (sgx0x%x)",sgx_status); ret = PVE_INTEGRITY_CHECK_ERROR; break; } if( AE_SUCCESS != (ret = sgx_error_to_ae_error(sgx_status))) { AESM_DBG_ERROR("error in decrypting ProvMsg4:(sgx0x%x)",sgx_status); break; } AESM_DBG_TRACE("ProvMsg4 decrypted by EK2 successfully"); ret = check_epid_pve_pg_status_after_mac_verification(msg4_header); if(AE_SUCCESS != ret) { AESM_DBG_ERROR("Backend reported error passed MAC verification:(ae%d)",ret); break; } TLVsMsg tlvs_field1; tlv_status = tlvs_field1.init_from_buffer(decoded_msg4, field1.msg_size); ret = tlv_error_2_pve_error(tlv_status); if(AE_SUCCESS != ret) { AESM_DBG_ERROR("ProvMsg4 Field2.1 decoding failed:(ae%d)",ret); break; } ret = msg4_field1_msg_checking(tlvs_field1); if( AE_SUCCESS != ret) { AESM_DBG_ERROR("ProvMsg4 Field2.1 invalid:(ae%d)",ret); break; } proc_prov_msg4_input_t msg4_input; tlv_msg_t Axf_data = block_cipher_tlv_get_encrypted_text(MSG4_FIELD1_ENC_Axf); if(0!=memcpy_s(&msg4_input.group_cert, sizeof(msg4_input.group_cert), MSG4_FIELD1_GROUP_CERT.payload, MSG4_FIELD1_GROUP_CERT.size)|| 0!=memcpy_s(&msg4_input.n2, NONCE_2_SIZE, MSG4_FIELD1_Nonce2.payload, MSG4_FIELD1_Nonce2.size) || 0!=memcpy_s(&msg4_input.equivalent_psvn, sizeof(psvn_t), platform_info_tlv_get_psvn(MSG4_FIELD1_PLATFORM_INFO), sizeof(psvn_t))|| 0!=memcpy_s(&msg4_input.fmsp, sizeof(fmsp_t), platform_info_tlv_get_fmsp(MSG4_FIELD1_PLATFORM_INFO), sizeof(fmsp_t))|| 0!=memcpy_s(&msg4_input.member_credential_iv, IV_SIZE, block_cipher_tlv_get_iv(MSG4_FIELD1_ENC_Axf), IV_SIZE)|| 0!=memcpy_s(&msg4_input.encrypted_member_credential, HARD_CODED_EPID_MEMBER_WITH_ESCROW_TLV_SIZE, Axf_data.msg_buf, Axf_data.msg_size)|| 0!=memcpy_s(&msg4_input.member_credential_mac, MAC_SIZE, MSG4_FIELD1_MAC_Axf.payload, MSG4_FIELD1_MAC_Axf.size)) { AESM_DBG_ERROR("memcpy error"); ret = PVE_UNEXPECTED_ERROR; break; } if (AE_SUCCESS != (ret =XEGDBlob::instance().read(msg4_input.xegb))) { AESM_DBG_ERROR("Fail to read extend epid blob info (ae%d)",ret); return ret; } ret = CPVEClass::instance().load_enclave();//Load PvE enclave now if( ret != AE_SUCCESS) { AESM_DBG_ERROR("Fail to load PvE enclave:(ae%d)\n",ret); break; } ret = (ae_error_t)proc_prov_msg4_data(&msg4_input, reinterpret_cast<proc_prov_msg4_output_t *>(data_blob)); AESM_DBG_TRACE("PvE return (ae%d) in Process ProvMsg4",ret); } while(0); if(decoded_msg4)free(decoded_msg4); return ret; }
sgx_status_t AESMLogic::get_launch_token(const enclave_css_t* signature, const sgx_attributes_t* attribute, sgx_launch_token_t* launch_token) { AESM_DBG_INFO("enter function"); AESMLogicLock lock(_le_mutex); ae_error_t ret_le = AE_SUCCESS; // load LE to get launch token if((ret_le=CLEClass::instance().load_enclave()) != AE_SUCCESS) { if(ret_le == AE_SERVER_NOT_AVAILABLE) { AESM_DBG_FATAL("LE not loaded due to AE_SERVER_NOT_AVAILABLE, possible SGX Env Not Ready"); return SGX_ERROR_NO_DEVICE; } AESM_DBG_FATAL("fail to load LE:%d",ret_le); return SGX_ERROR_UNEXPECTED; } ret_le = static_cast<ae_error_t>(CLEClass::instance().get_launch_token( const_cast<uint8_t*>(reinterpret_cast<const uint8_t *>(&signature->body.enclave_hash)), sizeof(sgx_measurement_t), const_cast<uint8_t*>(reinterpret_cast<const uint8_t *>(&signature->key.modulus)), sizeof(signature->key.modulus), const_cast<uint8_t*>(reinterpret_cast<const uint8_t *>(attribute)), sizeof(sgx_attributes_t), reinterpret_cast<uint8_t*>(launch_token), sizeof(token_t))); switch (ret_le) { case AE_SUCCESS: break; case LE_INVALID_PARAMETER: AESM_DBG_TRACE("Invalid parameter"); return SGX_ERROR_INVALID_PARAMETER; case LE_INVALID_ATTRIBUTE: case LE_INVALID_PRIVILEGE_ERROR: AESM_DBG_TRACE("Launch token error"); return SGX_ERROR_SERVICE_INVALID_PRIVILEGE; case LE_WHITELIST_UNINITIALIZED_ERROR: AESM_DBG_TRACE("LE whitelist uninitialized error"); return SGX_ERROR_UNEXPECTED; default: AESM_DBG_WARN("unexpeted error %d", ret_le); return SGX_ERROR_UNEXPECTED; } token_t *lt = reinterpret_cast<token_t *>(launch_token); ret_le = set_psvn(signature->body.isv_prod_id, signature->body.isv_svn, lt->cpu_svn_le); if(AE_PSVN_UNMATCHED_ERROR == ret_le) { //QE or PSE has been changed, but AESM doesn't restart. Will not provide service. return SGX_ERROR_SERVICE_UNAVAILABLE; }else if(AE_SUCCESS != ret_le) { AESM_DBG_ERROR("fail to save psvn:%d", ret_le); return SGX_ERROR_UNEXPECTED; } return SGX_SUCCESS; }
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; }