Beispiel #1
0
ae_error_t CertificateProvisioningProtocol::get_random_value(uint32_t size, upse::Buffer& randomValue)
{
    ae_error_t status = AE_FAILURE;

    do
    {
        status = randomValue.Alloc(size);
        if (AE_FAILED(status))
            break;

        uint8_t* p;
        upse::BufferWriter bw(randomValue);
        status = bw.reserve(size, &p);
        if (AE_FAILED(status))
            break;

        status = aesm_read_rand(p, size);

    } while (0);

    return status;
}
 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;
}