//*********************************************************************
// Call quoting enclave to convert report to name-based quote
//*********************************************************************
static ae_error_t do_get_quote
    (
    /*in */ upse::Buffer& reportBuffer,
    /*in */ upse::Buffer& sigRLBuffer,
    /*out*/ upse::Buffer& quoteBuffer
    )
{
    // Call QE to convert REPORT to a name-based QUOTE
    ae_error_t status = AE_FAILURE;
    ae_error_t tmp_status = AE_SUCCESS;

    do
    {
#ifndef FAKE_QUOTE
        uint32_t nQuote;                                 // in     - Quote buffer size

        sgx_report_t enclaveReport;                      // in
        sgx_quote_sign_type_t quote_type;                // in
        sgx_spid_t spid = {{0}};                           // in
        uint8_t* pSigRL = NULL;                          // in
        uint32_t nSigRL = 0;                               // in     - Sig RL buffer size

        memset(&enclaveReport, 0, sizeof(enclaveReport));

        nSigRL = sigRLBuffer.getSize();

        if (0 != nSigRL)
            pSigRL = const_cast<uint8_t*>(sigRLBuffer.getData());

        if (SGX_SUCCESS != sgx_calc_quote_size(pSigRL, nSigRL, &nQuote))
            break;

        tmp_status = quoteBuffer.Alloc(nQuote);
        if (AE_FAILED(tmp_status))
            break;
        upse::BufferWriter bwQuote(quoteBuffer);
        uint8_t* pQuote;
        tmp_status = bwQuote.reserve(nQuote, &pQuote);      // out
        if (AE_FAILED(tmp_status))
            break;

        quote_type = SGX_UNLINKABLE_SIGNATURE; // or SGX_LINKABLE_SIGNATURE

        // LSB16(SHA256("SGX PSE PROVISIONING SERVER"))
        // const char* SPID_VALUE = "SGX PSE PROVISIONING SERVER";
        // sgx_sha256_hash_t spid_hash;
        // sgx_sha256_msg((const uint8_t*)SPID_VALUE, strlen(SPID_VALUE), &spid_hash);
        // memcpy_s(spid.id, sizeof(spid.id), &spid_hash[0], 16);
        static uint8_t spid_hash[] = { 0x32, 0x81, 0xE5, 0x9E, 0xB1, 0x23, 0xFA, 0xCD,
            0x56, 0xDB, 0x62, 0x1E, 0x3B, 0x37, 0xFB, 0xE2 };
        memcpy_s(spid.id, sizeof(spid.id), spid_hash, sizeof(spid_hash));

        if (reportBuffer.getSize() != sizeof(enclaveReport))
            break;

        memcpy_s(&enclaveReport, reportBuffer.getSize(), reportBuffer.getData(), reportBuffer.getSize());
        aesm_error_t result;
        result = AESMLogic::get_quote(
            (uint8_t*)&enclaveReport, sizeof(enclaveReport),
            quote_type,
            (uint8_t*)&spid, sizeof(spid),
            NULL, 0,
            pSigRL, nSigRL,
            NULL, 0,
            (uint8_t*)pQuote, nQuote);
        if (result == AESM_BUSY)
        {
            //EPID_PROVISION triggered, make sure previous EPID provision has finished
            ae_error_t temp_ret = wait_pve_thread();
            BREAK_IF_TRUE(AE_SUCCESS != temp_ret , status, PSE_PR_PCH_EPID_UNKNOWN_ERROR);
            //redo get_quote
            result = AESMLogic::get_quote(
                (uint8_t*)&enclaveReport, sizeof(enclaveReport),
                quote_type,
                (uint8_t*)&spid, sizeof(spid),
                NULL, 0,
                pSigRL, nSigRL,
                NULL, 0,
                (uint8_t*)pQuote, nQuote);
        }
        BREAK_IF_TRUE(AESM_OUT_OF_EPC == result, status, AESM_AE_OUT_OF_EPC);
        BREAK_IF_TRUE(AESM_SUCCESS != result, status, AESM_PSE_PR_GET_QUOTE_ERROR);
#else
        const uint16_t SIGNATURE_LENGTH = 32;

        tmp_status = quoteBuffer.Alloc(sizeof(sgx_quote_t) + SIGNATURE_LENGTH);
        if (AE_FAILED(tmp_status))
            break;

        sgx_quote_t* pQuote;
        tmp_status = upse::BufferWriter(quoteBuffer).reserve(quoteBuffer.getSize(), (uint8_t**)&pQuote);
        if (AE_FAILED(tmp_status))
            break;

        uint16_t CPUSVN = 1;
        pQuote->version = 1;
        memcpy_s(pQuote->epid_group_id, sizeof(pQuote->epid_group_id), &GID_TO_USE, sizeof(GID_TO_USE));
        pQuote->report_body.isv_prod_id = 0x0002; //0x8086;
        pQuote->report_body.isv_svn = 1;
        memcpy_s(pQuote->report_body.cpu_svn, sizeof(pQuote->report_body.cpu_svn), &CPUSVN, sizeof(CPUSVN));

        const sgx_report_t* pReport = (sgx_report_t*)reportBuffer.getData();

        memcpy_s(pQuote->report_body.report_data, sizeof(pQuote->report_body.report_data), pReport->body.report_data, sizeof(pQuote->report_body.report_data));

        pQuote->signature_len = SIGNATURE_LENGTH;

        //NOTE: The signature is not valid when doing a FAKE_QUOTE
#endif

        status = AE_SUCCESS;

    } while (0);

    if ((AE_FAILURE == status) && AE_FAILED(tmp_status))
        status = tmp_status;

    SGX_DBGPRINT_PRINT_FUNCTION_AND_RETURNVAL(__FUNCTION__, status);

    return status;
}
Beispiel #2
0
sgx_status_t sgx_ra_proc_msg2(
    sgx_ra_context_t context,
    sgx_enclave_id_t eid,
    sgx_ecall_proc_msg2_trusted_t p_proc_msg2,
    sgx_ecall_get_msg3_trusted_t p_get_msg3,
    const sgx_ra_msg2_t *p_msg2,
    uint32_t msg2_size,
    sgx_ra_msg3_t **pp_msg3,
    uint32_t *p_msg3_size)
{
    if(!p_msg2 || !p_proc_msg2 || !p_get_msg3 || !p_msg3_size || !pp_msg3)
        return SGX_ERROR_INVALID_PARAMETER;
    if(msg2_size != sizeof(sgx_ra_msg2_t) + p_msg2->sig_rl_size)
        return SGX_ERROR_INVALID_PARAMETER;

    sgx_status_t ret = SGX_ERROR_UNEXPECTED;
    sgx_report_t report;
    sgx_ra_msg3_t *p_msg3 = NULL;
    sgx_att_key_id_t empty_att_key_id;

    memset(&report, 0, sizeof(report));
    memset(&empty_att_key_id, 0, sizeof(empty_att_key_id));

    {
        sgx_quote_nonce_t nonce;
        sgx_report_t qe_report;
        sgx_target_info_t qe_target_info;

        memset(&nonce, 0, sizeof(nonce));
        memset(&qe_report, 0, sizeof(qe_report));

        sgx_status_t status;
        g_ukey_spin_lock.lock();
        if(0 != memcmp(&g_att_key_id, &empty_att_key_id, sizeof(g_att_key_id)))
        {
            ret = SGX_ERROR_INVALID_STATE;
            g_ukey_spin_lock.unlock();
            goto CLEANUP;
        }
        if(memcpy_s(&qe_target_info, sizeof(qe_target_info),
                 &g_qe_target_info, sizeof(g_qe_target_info)) != 0)
        {
            ret = SGX_ERROR_UNEXPECTED;
            g_ukey_spin_lock.unlock();
            goto CLEANUP;
        }
        g_ukey_spin_lock.unlock();
        ret = p_proc_msg2(eid, &status, context, p_msg2, &qe_target_info,
                          &report, &nonce);
        if(SGX_SUCCESS!=ret)
        {
            goto CLEANUP;
        }
        if(SGX_SUCCESS!=status)
        {
            ret = status;
            goto CLEANUP;
        }

        uint32_t quote_size = 0;
        ret = sgx_calc_quote_size(p_msg2->sig_rl_size ?
                                    const_cast<uint8_t *>(p_msg2->sig_rl):NULL,
                                 p_msg2->sig_rl_size,
                                 &quote_size);
        if(SGX_SUCCESS!=ret)
        {
            goto CLEANUP;
        }

        //check integer overflow of quote_size
        if (UINT32_MAX - quote_size < sizeof(sgx_ra_msg3_t))
        {
            ret = SGX_ERROR_UNEXPECTED;
            goto CLEANUP;
        }
        uint32_t msg3_size = static_cast<uint32_t>(sizeof(sgx_ra_msg3_t)) + quote_size;
        p_msg3 = (sgx_ra_msg3_t *)malloc(msg3_size);
        if(!p_msg3)
        {
            ret = SGX_ERROR_OUT_OF_MEMORY;
            goto CLEANUP;
        }
        memset(p_msg3, 0, msg3_size);

        ret = sgx_get_quote(&report,
                           p_msg2->quote_type == SGX_UNLINKABLE_SIGNATURE ?
                               SGX_UNLINKABLE_SIGNATURE : SGX_LINKABLE_SIGNATURE,
                           const_cast<sgx_spid_t *>(&p_msg2->spid),
                           &nonce,
                           p_msg2->sig_rl_size ?
                               const_cast<uint8_t *>(p_msg2->sig_rl):NULL,
                           p_msg2->sig_rl_size,
                           &qe_report,
                           (sgx_quote_t *)p_msg3->quote,
                           quote_size);
        if(SGX_SUCCESS!=ret)
        {
            goto CLEANUP;
        }

        ret = p_get_msg3(eid, &status, context, quote_size, &qe_report,
                         p_msg3, msg3_size);
        if(SGX_SUCCESS!=ret)
        {
            goto CLEANUP;
        }
        if(SGX_SUCCESS!=status)
        {
            ret = status;
            goto CLEANUP;
        }
        *pp_msg3 = p_msg3;
        *p_msg3_size = msg3_size;
    }

CLEANUP:
    if(ret)
        SAFE_FREE(p_msg3);
    return ret;
}