Пример #1
0
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;
    }
}
Пример #2
0
ae_error_t CertificateProvisioningProtocol::msg3_seq3_2_create_quote_signature_tlv(const upse::Buffer& quote, TLVsMsg& seq3_2_tlv_quote_signature)
{
    ae_error_t status = AESM_PSE_PR_INTERNAL_ERROR;
    tlv_status_t tlv_status;

    do
    {
	    if (sizeof(sgx_quote_t) > quote.getSize())
            break;

	    const sgx_quote_t* pQuote = (const sgx_quote_t*)quote.getData();

	    /* the QUOTE SIGNATURE TLV doesn't include Quote.signature_len */
        uint32_t SigLen = pQuote->signature_len;
  
        if (sizeof(sgx_quote_t) + SigLen > quote.getSize())
            break;

        const uint8_t *pSig = pQuote->signature;

        tlv_status = seq3_2_tlv_quote_signature.add_quote_signature(pSig, SigLen);
		status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        status = AE_SUCCESS;

    } while (0);

    return status;
}
Пример #3
0
ae_error_t CertificateProvisioningProtocol::msg1_create_seq3_0(const TLVsMsg& seq3_1_tlv_epid_gid, const provision_request_header_t& serializedHeader,
                               const upse::Buffer& ek1, TLVsMsg& seq3_0_tlv_block_cipher_text, upse::Buffer& mac)
{
    //* 3.0 Block Cipher Text TLV (TLV Type, Type, Version, Size, [IV, EncryptedPayload is 3.1])
    ae_error_t status = AE_FAILURE;
    tlv_status_t tlv_status;

    do
    {
        status = get_random_value(IV_SIZE, M1IV);
        if (AE_FAILED(status))
            break;

        upse::Buffer aad;
        status = aad.Alloc(sizeof(serializedHeader));
        if (AE_FAILED(status))
            break;

        upse::BufferWriter aadWriter(aad);
        status = aadWriter.writeRaw((const uint8_t*)&serializedHeader, sizeof(serializedHeader));
        if (AE_FAILED(status))
            break;

        upse::Buffer epidGid;
        status = epidGid.Alloc(seq3_1_tlv_epid_gid.get_tlv_msg(), seq3_1_tlv_epid_gid.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        upse::Buffer encryptedPayload;
        status = aesGCMEncrypt(M1IV, ek1, epidGid, aad, encryptedPayload, mac);
        if (AE_FAILED(status))
            break;

        tlv_status = seq3_0_tlv_block_cipher_text.add_block_cipher_text(M1IV.getData(), encryptedPayload.getData(), encryptedPayload.getSize());
        status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        status = AE_SUCCESS;

    } while (0);

    return status;
}
Пример #4
0
ae_error_t CertificateProvisioningProtocol::msg3_seq3_1_create_quote_tlv(const upse::Buffer& quoteBuffer, TLVsMsg& quoteTLV)
{
    ae_error_t status = AESM_PSE_PR_INTERNAL_ERROR;
    tlv_status_t tlv_status;

    do
    {
        if (sizeof(sgx_quote_t) > quoteBuffer.getSize())
            break;

        const sgx_quote_t* pQuote = (const sgx_quote_t*)quoteBuffer.getData();

        tlv_status = quoteTLV.add_quote((uint8_t*)pQuote, static_cast<uint32_t>(sizeof(sgx_quote_t)-sizeof(pQuote->signature_len)));
		status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

    } while (0);

    return status;
}
Пример #5
0
ae_error_t CertificateProvisioningProtocol::msg1_create_seq2_1(TLVsMsg& seq2_1_tlv_block_cipher_info)
{
    //* 2.1 Block Cipher Info TLV (TLV Type, Type, Version, Size, [SK])
    ae_error_t status = AE_FAILURE;
    tlv_status_t tlv_status;

    do
    {
        status = get_random_value(SK_SIZE, M1SK);
        if (AE_FAILED(status))
            break;

        tlv_status = seq2_1_tlv_block_cipher_info.add_block_cipher_info(M1SK.getData());
        status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        status = AE_SUCCESS;
    } while (0);

    return status;
}
Пример #6
0
ae_error_t CertificateProvisioningProtocol::msg1_create_seq2_0(const TLVsMsg& seq2_1_tlv_block_cipher_info, TLVsMsg& seq2_0_tlv_cipher_text)
{
    //* 2.0 Cipher Text TLV (TLV Type, Type, Version, Size, [KeyID, EncryptedPayload is 2.1])
    ae_error_t status = AE_FAILURE;
    tlv_status_t tlv_status;

    do
    {
        upse::Buffer seq2_1_encrypted_tlv;
        upse::Buffer encryptedBlockCipherInfo;

        const public_key_t& public_key = get_intel_pek();

        // Encrypt TLV 2.1
        upse::Buffer blockCipherInfo;
        status = blockCipherInfo.Alloc(seq2_1_tlv_block_cipher_info.get_tlv_msg(), seq2_1_tlv_block_cipher_info.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        upse::BufferReader blockCipherInfoReader(blockCipherInfo);

        status = encryptRSA_OAEP_SHA256(public_key, blockCipherInfoReader, encryptedBlockCipherInfo);
        if (AE_FAILED(status))
            break;

        tlv_status = seq2_0_tlv_cipher_text.add_cipher_text(encryptedBlockCipherInfo.getData(), encryptedBlockCipherInfo.getSize(), PEK_3072_PUB);
        status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        status = AE_SUCCESS;
    } while (0);


    return status;
}
Пример #7
0
//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;
}
Пример #8
0
ae_error_t CertificateProvisioningProtocol::msg3_generate(const upse::Buffer& csrBuffer, const upse::Buffer& quoteBuffer, upse::Buffer& serializedMsg3)
{
    ae_error_t status = AE_FAILURE;
    tlv_status_t tlv_status = TLV_UNKNOWN_ERROR;

    provision_request_header_t serializedHeader;
    memset(&serializedHeader, 0, sizeof(serializedHeader));

    TLVsMsg seq2_0_tlv_nonce;
    TLVsMsg seq3_0_tlv_block_cipher_text;
    TLVsMsg seq3_1_tlv_quote;
    TLVsMsg seq3_2_tlv_quote_signature;
    TLVsMsg seq3_3_tlv_x509_csr;
    TLVsMsg seq4_0_tlv_mac;

    do
    {
        tlv_status = seq2_0_tlv_nonce.add_nonce(Nonce.getData(), Nonce.getSize());
		status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        status = msg3_seq3_1_create_quote_tlv(quoteBuffer, seq3_1_tlv_quote);
        if (AE_FAILED(status))
            break;

        status = msg3_seq3_2_create_quote_signature_tlv(quoteBuffer, seq3_2_tlv_quote_signature);
        if (AE_FAILED(status))
            break;

        tlv_status = seq3_3_tlv_x509_csr.add_x509_csr(csrBuffer.getData(), csrBuffer.getSize());
		status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        status = msg3_create_header(TransactionID, seq2_0_tlv_nonce.get_tlv_msg_size(), seq3_1_tlv_quote.get_tlv_msg_size(),
            seq3_2_tlv_quote_signature.get_tlv_msg_size(), seq3_3_tlv_x509_csr.get_tlv_msg_size(), serializedHeader);
        if (AE_FAILED(status))
            break;

        upse::Buffer mac;
        status = msg3_seq3_0_create_block_cipher_text_tlv(seq3_1_tlv_quote, seq3_2_tlv_quote_signature, seq3_3_tlv_x509_csr, seq2_0_tlv_nonce, serializedHeader, 
            EK2, seq3_0_tlv_block_cipher_text, mac);
        if (AE_FAILED(status))
            break;

        tlv_status = seq4_0_tlv_mac.add_mac(mac.getData());
		status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        //*********************************************************************
        // Prepare serialized message buffer
        //*********************************************************************
        uint32_t size_msg3 = static_cast<uint32_t>(PROVISION_REQUEST_HEADER_SIZE + seq2_0_tlv_nonce.get_tlv_msg_size() +
                                seq3_0_tlv_block_cipher_text.get_tlv_msg_size() + seq4_0_tlv_mac.get_tlv_msg_size());

        status = serializedMsg3.Alloc(size_msg3);
        if (AE_FAILED(status))
            break;

        serializedMsg3.zeroMemory();
        upse::BufferWriter bwMsg3(serializedMsg3);

        // Write serialized request header to serialized message
        status = bwMsg3.writeRaw((uint8_t*)&serializedHeader, sizeof(serializedHeader));
        if (AE_FAILED(status))
            break;

        // Write sequence 2.0 - Nonce TLV
        status = bwMsg3.writeRaw(const_cast<uint8_t*>(seq2_0_tlv_nonce.get_tlv_msg()), seq2_0_tlv_nonce.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        // Write sequence 3.0 - Block Cipher Text TLV (contains 3.1, 3.2, and 3.3 as encrypted payload)
        status = bwMsg3.writeRaw(const_cast<uint8_t*>(seq3_0_tlv_block_cipher_text.get_tlv_msg()), seq3_0_tlv_block_cipher_text.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        // Write sequence 4.0 - MAC TLV
        status = bwMsg3.writeRaw(const_cast<uint8_t*>(seq4_0_tlv_mac.get_tlv_msg()), seq4_0_tlv_mac.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        status = AE_SUCCESS;

    } while (0);

    return status;
}
Пример #9
0
ae_error_t CertificateProvisioningProtocol::msg3_seq3_0_create_block_cipher_text_tlv(const TLVsMsg& quote, const TLVsMsg& epidSigTLV, const TLVsMsg& csrTLV, const TLVsMsg& nonceTLV, 
                                                      const provision_request_header_t& requestHeader, const upse::Buffer& ek2,
                                                      TLVsMsg& blockCipherTextTLV, upse::Buffer& mac)
{
    ae_error_t status = AE_FAILURE;
    tlv_status_t tlv_status;

    upse::Buffer plainText;
    upse::Buffer encryptedPayload;

    do
    {
        status = get_random_value(IV_SIZE, M3IV);
        if (AE_FAILED(status))
            break;

        status = plainText.Alloc(quote.get_tlv_msg_size() + epidSigTLV.get_tlv_msg_size() + csrTLV.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        upse::BufferWriter plainTextWriter(plainText);
        status = plainTextWriter.writeRaw(quote.get_tlv_msg(), quote.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;
        status = plainTextWriter.writeRaw(epidSigTLV.get_tlv_msg(), epidSigTLV.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;
        status = plainTextWriter.writeRaw(csrTLV.get_tlv_msg(), csrTLV.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        uint32_t payloadSize = BLOCK_CIPHER_TEXT_TLV_PAYLOAD_SIZE(plainText.getSize());
        uint32_t blockCipherTextHeaderSize = get_tlv_total_size(payloadSize) - payloadSize;

        // Calculate AAD (concatenation of Request header, Nonce, Block Cipher Text TLV header and IV from Block Cipher Text TLV)
        upse::Buffer aad;
        status = aad.Alloc(static_cast<uint32_t>(sizeof(requestHeader) + nonceTLV.get_tlv_msg_size() +  blockCipherTextHeaderSize + M3IV.getSize()));
        if (AE_FAILED(status))
            break;

        TLVsMsg tmpBlockCipherTextTLV;
        tlv_status = tmpBlockCipherTextTLV.add_block_cipher_text(M3IV.getData(), NULL, plainText.getSize());
		status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        upse::BufferWriter aadWriter(aad);
        status = aadWriter.writeRaw((const uint8_t*)&requestHeader, sizeof(requestHeader));
        if (AE_FAILED(status))
            break;
        status = aadWriter.writeRaw(nonceTLV.get_tlv_msg(), nonceTLV.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;
        status = aadWriter.writeRaw(tmpBlockCipherTextTLV.get_tlv_msg(), blockCipherTextHeaderSize);
        if (AE_FAILED(status))
            break;
        status = aadWriter.writeRaw(M3IV.getData(), M3IV.getSize());
        if (AE_FAILED(status))
            break;

        status = aesGCMEncrypt(M3IV, ek2, plainText, aad, encryptedPayload, mac);
        if (AE_FAILED(status))
            break;

        tlv_status = blockCipherTextTLV.add_block_cipher_text(M3IV.getData(), encryptedPayload.getData(), encryptedPayload.getSize());
		status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        status = AE_SUCCESS;

    } while (0);

    return status;
}
Пример #10
0
//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;
}
Пример #11
0
ae_error_t CertificateProvisioningProtocol::msg1_generate(const GroupId gid, upse::Buffer& serializedMsg1)
{
    ae_error_t status = AE_FAILURE;
    tlv_status_t tlv_status = TLV_UNKNOWN_ERROR;
    GroupId be_gid; //gid from init_quote is little endian, change to bigendian for backend server here
    be_gid.data[0]=gid.data[3];
    be_gid.data[1]=gid.data[2];
    be_gid.data[2]=gid.data[1];
    be_gid.data[3]=gid.data[0];

    provision_request_header_t header;
    memset(&header, 0, sizeof(header));

    TLVsMsg seq2_0_tlv_cipher_text;
    TLVsMsg seq2_1_tlv_block_cipher_info;
    TLVsMsg seq3_0_tlv_block_cipher_text;
    TLVsMsg seq3_1_tlv_epid_gid;
    TLVsMsg seq4_0_tlv_mac;

    do
    {
        status = get_random_value(XID_SIZE, TransactionID);
        if (AE_FAILED(status))
            break;

        // Prepare sequence 2.1 -- Block Cipher Text TLV with SK
        status = msg1_create_seq2_1(seq2_1_tlv_block_cipher_info);
        if (AE_FAILED(status))
            break;

        // Prepare sequence 2.0 -- Cipher Text TLV with KeyID and encrypted 2.1
        status = msg1_create_seq2_0(seq2_1_tlv_block_cipher_info, seq2_0_tlv_cipher_text);
        if (AE_FAILED(status))
            break;

        // Prepare sequence 3.1 -- EPID GID TLV
        tlv_status = seq3_1_tlv_epid_gid.add_epid_gid(be_gid);
        status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        // Derive EK1
        upse::Buffer EK1;
        status = aesCMAC(M1SK, TransactionID, EK1);
        if (AE_FAILED(status))
            break;

        // Create Request Header (we need to calculate size before AES-GCM CMAC)
        status = msg1_create_header(seq2_0_tlv_cipher_text.get_tlv_msg_size(), seq3_1_tlv_epid_gid.get_tlv_msg_size(), TransactionID, header);
        if (AE_FAILED(status))
            break;

        // Prepare sequence 3.0 -- Block Cipher Text TLV with IV and encrypted 3.1
        upse::Buffer mac;
        status = msg1_create_seq3_0(seq3_1_tlv_epid_gid, header, EK1, seq3_0_tlv_block_cipher_text, mac);
        if (AE_FAILED(status))
            break;

        // Prepare sequence 4.0 -- MAC TLV
        tlv_status = seq4_0_tlv_mac.add_mac(mac.getData());
        status = tlv_error_2_pve_error(tlv_status);
        if (AE_FAILED(status))
            break;

        //*********************************************************************
        // Prepare serialized message buffer
        //*********************************************************************
        uint32_t size_msg1 = static_cast<uint32_t>(PROVISION_REQUEST_HEADER_SIZE) + seq2_0_tlv_cipher_text.get_tlv_msg_size() +
                                seq3_0_tlv_block_cipher_text.get_tlv_msg_size() + seq4_0_tlv_mac.get_tlv_msg_size();

        status = serializedMsg1.Alloc(size_msg1);
        if (AE_FAILED(status))
            break;

        serializedMsg1.zeroMemory();
        upse::BufferWriter bwMsg1(serializedMsg1);

        // Write serialized request header to serialized message
        status = bwMsg1.writeRaw((uint8_t*)&header, sizeof(header));
        if (AE_FAILED(status))
            break;

        // Write sequence 2.0 - Cipher Text TLV (contains 2.1 as encrypted payload)
        status = bwMsg1.writeRaw(const_cast<uint8_t*>(seq2_0_tlv_cipher_text.get_tlv_msg()), seq2_0_tlv_cipher_text.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        // Write sequence 3.0 - Block Cipher Text TLV (contains 3.1 as encrypted payload)
        status = bwMsg1.writeRaw(const_cast<uint8_t*>(seq3_0_tlv_block_cipher_text.get_tlv_msg()), seq3_0_tlv_block_cipher_text.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        // Write sequence 4.0 - MAC TLV
        status = bwMsg1.writeRaw(const_cast<uint8_t*>(seq4_0_tlv_mac.get_tlv_msg()), seq4_0_tlv_mac.get_tlv_msg_size());
        if (AE_FAILED(status))
            break;

        status = AE_SUCCESS;

    } while (0);

    return status;
}
Пример #12
0
 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;
}
Пример #13
0
uint32_t CPVEClass::proc_es_msg2(
    const uint8_t *msg,
    uint32_t msg_size,
    char server_url[MAX_PATH],
    uint16_t& ttl,
    const uint8_t xid[XID_SIZE],
    uint8_t rsa_signature[PVE_RSA_KEY_BYTES],
    signed_pek_t& pek)
{
    uint32_t ae_ret = PVE_MSG_ERROR;
    TLVsMsg tlvs_msg;
    AESM_PROFILE_FUN;
    tlv_status_t tlv_status;
    uint16_t time_in_net;
    const provision_response_header_t *resp_header = (const provision_response_header_t *)msg;
    const uint8_t *resp_body = msg + PROVISION_RESPONSE_HEADER_SIZE;
    if(msg_size<PROVISION_RESPONSE_HEADER_SIZE){//at least response header is available
        AESM_DBG_ERROR("Endpoint selection Msg2 buffer size too small");
        goto final_point;
    }
    //first checking resp header for protocol, version and type
    if(resp_header->protocol != ENDPOINT_SELECTION || resp_header->version!=TLV_VERSION_1 || resp_header->type != TYPE_ES_MSG2){
        AESM_DBG_ERROR("ES Msg2 header error");
        goto final_point;
    }
    ae_ret = check_endpoint_pg_stauts(resp_header);
    if(AE_SUCCESS != ae_ret){
        AESM_DBG_ERROR("Backend report error in ES Msg2 Header:%d",ae_ret);
        goto final_point;
    }
    if(0!=memcmp(xid, resp_header->xid, XID_SIZE)){
        AESM_DBG_ERROR("XID in ES Msg2 header doesn't match the one in ES Msg1");
        ae_ret = PVE_MSG_ERROR;
        goto final_point;
    }
    uint32_t size; size = GET_BODY_SIZE_FROM_PROVISION_RESPONSE(msg);
    if(size + PROVISION_RESPONSE_HEADER_SIZE != msg_size){ //size information inconsistent
        AESM_DBG_ERROR("message size inconsistent in ES Msg2");
        ae_ret = PVE_MSG_ERROR;
        goto final_point;
    }
    tlv_status = tlvs_msg.init_from_buffer(resp_body, msg_size - static_cast<uint32_t>(PROVISION_RESPONSE_HEADER_SIZE));
    ae_ret = tlv_error_2_pve_error(tlv_status);
    if(AE_SUCCESS!=ae_ret){
        AESM_DBG_ERROR("Fail to decode ES Msg2:%d",ae_ret);
        goto final_point;
    }
    if(tlvs_msg.get_tlv_count() != ES_MSG2_FIELD_COUNT){//three TLVs
        AESM_DBG_ERROR("Invaid number of TLV in ES Msg2");
        ae_ret = PVE_MSG_ERROR;
        goto final_point;
    }
    if(tlvs_msg[0].type != TLV_ES_INFORMATION || tlvs_msg[0].version != TLV_VERSION_1 || tlvs_msg[0].header_size != SMALL_TLV_HEADER_SIZE){//TLV header checking
        AESM_DBG_ERROR("Invalid TLV in ES Msg2");
        ae_ret = PVE_MSG_ERROR;
        goto final_point;
    }

    if(tlvs_msg[0].size<ES_FIELD0_MIN_SIZE||tlvs_msg[0].size>ES_FIELD0_MAX_SIZE){//size checking
        AESM_DBG_ERROR("Invalid TLV in ES Msg2");
        ae_ret = PVE_MSG_ERROR;
        goto final_point;
    }
    if(tlvs_msg[1].type != TLV_SIGNATURE || tlvs_msg[1].version != TLV_VERSION_1 ||
        tlvs_msg[1].header_size!=SMALL_TLV_HEADER_SIZE||tlvs_msg[1].size != PVE_RSA_KEY_BYTES+1 ||
        tlvs_msg[1].payload[0] != PEK_PRIV){
        ae_ret = PVE_MSG_ERROR;
        AESM_DBG_ERROR("Invalid Signature TLV: type %d, version %d, size %d while expected value is %d, %d, %d", 
            tlvs_msg[1].type, tlvs_msg[1].version, tlvs_msg[1].size,
            TLV_SIGNATURE, TLV_VERSION_1, PVE_RSA_KEY_BYTES);
        goto final_point;
    }
    if(tlvs_msg[2].type != TLV_PEK || tlvs_msg[2].version != TLV_VERSION_1 ||
        tlvs_msg[2].header_size!=SMALL_TLV_HEADER_SIZE||tlvs_msg[2].size != sizeof(signed_pek_t)){
            ae_ret = PVE_MSG_ERROR;
        AESM_DBG_ERROR("Invalid PEK TLV: type %d, version %d, size %d while expected value is %d, %d, %d", 
            tlvs_msg[2].type, tlvs_msg[2].version, tlvs_msg[2].size,
            TLV_PEK, TLV_VERSION_1, sizeof(signed_pek_t));
        goto final_point;
    }
    //skip the byte for KEY_ID
    if(memcpy_s(rsa_signature, PVE_RSA_KEY_BYTES, tlvs_msg[1].payload+1, tlvs_msg[1].size-1)!=0){
        ae_ret = AE_FAILURE;
        AESM_DBG_ERROR("memcpy failed");
        goto final_point;
    }
    if(memcpy_s(&pek, sizeof(pek), tlvs_msg[2].payload, tlvs_msg[2].size)!=0){
        ae_ret = AE_FAILURE;
        AESM_DBG_ERROR("memcpy failed");
        goto final_point;
    }

    time_in_net = *(uint16_t *)tlvs_msg[0].payload;//TTL in ES
    ttl = lv_ntohs(time_in_net);//First two bytes in payload for TTL (maximal seconds that the URL to be valid)
    if(memcpy_s(server_url, MAX_PATH, tlvs_msg[0].payload+2, tlvs_msg[0].size-2)!=0){//other bytes for URL
        ae_ret = AE_FAILURE;
        AESM_DBG_ERROR("memcpy failed");
        goto final_point;
    }
    server_url[tlvs_msg[0].size-2]='\0';
    ae_ret = AE_SUCCESS;
final_point:
    return ae_ret;
}