コード例 #1
0
ae_error_t pib_verify_signature(platform_info_blob_wrapper_t& piBlobWrapper)
{
    ae_error_t ae_err = AE_FAILURE;
    sgx_ecc_state_handle_t ecc_handle = NULL;

    uint8_t result = SGX_EC_INVALID_SIGNATURE;

    const uint32_t data_size = static_cast<uint32_t>(sizeof(piBlobWrapper.platform_info_blob) - sizeof(piBlobWrapper.platform_info_blob.signature));


    piBlobWrapper.valid_info_blob = false;
    do
    {
        sgx_ec256_public_t publicKey;
        sgx_ec256_signature_t signature;
        sgx_status_t sgx_status;

        //BREAK_IF_TRUE((sizeof(publicKey) != sizeof(s_pib_pub_key_big_endian)), ae_err, AE_FAILURE);
        //BREAK_IF_TRUE((sizeof(signature) != sizeof(piBlobWrapper.platform_info_blob.signature)), ae_err, AE_FAILURE);

        if(0!=memcpy_s(&publicKey, sizeof(publicKey), s_pib_pub_key_big_endian, sizeof(s_pib_pub_key_big_endian))){
            ae_err = AE_FAILURE;
            break;
        }

        if(0!=memcpy_s(&signature, sizeof(signature), &piBlobWrapper.platform_info_blob.signature, sizeof(piBlobWrapper.platform_info_blob.signature))){
            ae_err = AE_FAILURE;
            break;
        }

        sgx_status = sgx_ecc256_open_context(&ecc_handle);
        BREAK_IF_TRUE((SGX_SUCCESS != sgx_status), ae_err, AE_FAILURE);

        sgx_status = sgx_ecdsa_verify((uint8_t*)&piBlobWrapper.platform_info_blob, data_size, &publicKey, &signature, &result, ecc_handle);
        BREAK_IF_TRUE((SGX_SUCCESS != sgx_status), ae_err, AE_FAILURE);

        if (SGX_EC_VALID != result)
        {
            AESM_LOG_WARN(g_event_string_table[SGX_EVENT_PID_SIGNATURE_FAILURE]);
            break;
        }

        piBlobWrapper.valid_info_blob = true;

        ae_err = AE_SUCCESS;

    } while (0);
    if (ecc_handle != NULL) {
        sgx_ecc256_close_context(ecc_handle);
    }

    return ae_err;
}
コード例 #2
0
ファイル: pse_pr.cpp プロジェクト: hyjiang/linux-sgx
ae_error_t ecall_tVerifyM8
(
    /*in */ const SIGMA_S3_MESSAGE*      pS3,
    /*in */ uint32_t  nLen_S3,
    /*in */ const EPID_PRIV_RL*        pPrivRL,
    /*in */ uint32_t  nTotalLen_PrivRL,
    /*out*/       pairing_blob_t* pPairingBlob,
    /*out*/ uint8_t*  puNewPairing
)
{
    ae_error_t status = AE_FAILURE;

    do
    {
        BREAK_IF_TRUE((NULL == s_pVerifier), status, PSE_PR_CALL_ORDER_ERROR);

        status = s_pVerifier->VerifyM8(
            pS3, nLen_S3, 
            pPrivRL, 
            nTotalLen_PrivRL,
            pPairingBlob,
            (bool*)puNewPairing);
        BREAK_IF_FAILED(status);

    } while (0);

    PSE_PR_SAFE_DELETE(s_pVerifier);

    return status;
}
コード例 #3
0
ファイル: pse_pr.cpp プロジェクト: hyjiang/linux-sgx
ae_error_t ecall_tGenM7
(
    /*in */ const SIGMA_S1_MESSAGE*      pS1,
    /*in */ const EPID_SIG_RL*           pSigRL,
    /*in */ uint32_t  nTotalLen_SigRL,
    /*in */ const uint8_t*               pOcspResp, 
    /*in */ uint32_t  nLen_OcspResp,
    /*in */ const uint8_t*               pVerifierCert,
    /*in */ uint32_t  nLen_VerifierCert,
    /*in */ const pairing_blob_t* pPairingBlob,
    /*in */ uint32_t  nMax_S2,
    /*out*/       SIGMA_S2_MESSAGE*      pS2,
    /*out*/ uint32_t* pnLen_S2
)
{
    ae_error_t status = AE_FAILURE;

    PSE_PR_SAFE_DELETE(s_pVerifier);

    do
    {
        s_pVerifier = new (std::nothrow) TEpidSigmaVerifier;
        BREAK_IF_TRUE((NULL == s_pVerifier), status, PSE_PR_INSUFFICIENT_MEMORY_ERROR);

        status = s_pVerifier->GenM7(
            pS1, 
            pSigRL, 
            nTotalLen_SigRL,
            pOcspResp, nLen_OcspResp, 
            pVerifierCert, nLen_VerifierCert,
            pPairingBlob,
            nMax_S2, pS2, pnLen_S2);
        BREAK_IF_FAILED(status);

    } while (0);

    if (AE_FAILED(status))
        PSE_PR_SAFE_DELETE(s_pVerifier);

    return status;
}
コード例 #4
0
//*********************************************************************
// 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;
}
コード例 #5
0
//*********************************************************************
// Call quoting enclave to get target info
//*********************************************************************
static ae_error_t do_quote_initialization
    (
    /*out */ upse::Buffer& targetInfo,
    /*out */ GroupId* pGID
    )
{
    ae_error_t status = AE_FAILURE;


    do
    {
        BREAK_IF_TRUE( (NULL == pGID), status, PSE_PR_BAD_POINTER_ERROR);

#ifndef FAKE_QUOTE
        if (AE_FAILED(targetInfo.Alloc(sizeof(sgx_target_info_t))))
            break;
        upse::BufferWriter bwTargetInfo(targetInfo);
        uint8_t* p;
        status = bwTargetInfo.reserve(sizeof(sgx_target_info_t), &p);
        if (AE_FAILED(status))
            break;
        sgx_target_info_t* pTargetInfo = (sgx_target_info_t*)p;

        aesm_error_t result;
        SGX_DBGPRINT_PRINT_ANSI_STRING("aesmLogic.init_quote?");

        result = AESMLogic::init_quote(
            (uint8_t*)pTargetInfo, sizeof(sgx_target_info_t),
            (uint8_t*)pGID, sizeof(*pGID));
        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 init_quote
            result = AESMLogic::init_quote(
                (uint8_t*)pTargetInfo, sizeof(sgx_target_info_t),
                (uint8_t*)pGID, sizeof(*pGID));
        }
        BREAK_IF_TRUE(AESM_UPDATE_AVAILABLE == result, status, PSW_UPDATE_REQUIRED);
        BREAK_IF_TRUE(AESM_OUT_OF_EPC == result, status, AESM_AE_OUT_OF_EPC);
        BREAK_IF_TRUE(AESM_SUCCESS != result, status, AESM_PSE_PR_INIT_QUOTE_ERROR);
#else

        //NRG: m_tmpGID = 0;
        upse::Buffer m_tmpGID;
        if (AE_FAILED(m_tmpGID.Alloc(GID_TO_USE, sizeof(GID_TO_USE))))
            break;

        //      m_tmpGID = 1244;
        //      upse::BufferWriter(m_tmpGID).writeRaw(GID_TO_USE, sizeof(GID_TO_USE));
        SigmaData::SetGID(m_tmpGID);
        memcpy_s(pGID, sizeof(GroupId), m_tmpGID.getData(), sizeof(GroupId));
        if (AE_FAILED(targetInfo.Alloc(sizeof(sgx_target_info_t))))
            break;
#endif

        SGX_DBGPRINT_PRINT_ANSI_STRING("aesmLogic.init_quote success");
        status = AE_SUCCESS;

    } while (0);

    SGX_DBGPRINT_PRINT_FUNCTION_AND_RETURNVAL(__FUNCTION__, status);

    return status;
}
コード例 #6
0
//*********************************************************************
// Do the certificate chain provisioning logic
//*********************************************************************
static ae_error_t do_certificate_chain_provisioning
    (
    /*in */ const endpoint_selection_infos_t& es_info,
    /*out*/ platform_info_blob_wrapper_t* pib_wrapper
    )
{
    if (NULL == pib_wrapper)
        return AESM_PSE_PR_BAD_POINTER_ERROR;

    ae_error_t status = AE_FAILURE;
    upse::Buffer target_info;

    uint32_t gid = 0;
    //    GroupId gid = {0};                  // Send to Server in M1

    upse::Buffer nonce;                 // Receive from Server in M2
    upse::Buffer sig_rl;                // Receive from Server in M2
    upse::Buffer csr_pse;               // Send to Server in M3
    upse::Buffer quote;                 // Send to Server in M3
    std::list<upse::Buffer> certChain;  // Receive from Server in M4

    upse::Buffer report;                // Received from PSE_pr
    upse::Buffer pairing_blob;          // Received from PSE_pr
    upse::Buffer ocsp_req;              // Created here from cert chain

    const char *szURL = EndpointSelectionInfo::instance().get_pse_provisioning_url(es_info);

    memset(pib_wrapper, 0, sizeof(platform_info_blob_wrapper_t));   // Receive from Server in M4

    CertificateProvisioningProtocol cpp;

    SGX_DBGPRINT_PRINT_ANSI_STRING("Begin Certificate (PSE) Provisioning");
    do
    {
        Helper::RemoveCertificateChain();
        Helper::delete_ocsp_response_vlr();

#if defined(NO_PROVISIONING_SERVER)

        {
            //*********************************************************************
            // Use hardcoded Cert.
            //*********************************************************************
            SGX_DBGPRINT_PRINT_ANSI_STRING("Using Hard Coded Cert");
            status = tPrepareForCertificateProvisioning_hardcoded_privatekey(pairing_blob);
            BREAK_IF_FAILED(status);

            /* Use the hardcoded "Public" Cert */
            upse::Buffer Cert;
            Cert.Alloc(PUBLIC_PSE_CERT_LEN);
            upse::BufferWriter bwCert(Cert);
            uint8_t* pCert;
            status = bwCert.reserve(PUBLIC_PSE_CERT_LEN, &pCert);
            BREAK_IF_FAILED(status);
            memcpy_s(pCert, PUBLIC_PSE_CERT_LEN, PUBLIC_PSE_CERT, PUBLIC_PSE_CERT_LEN);
            certChain.push_back(Cert);

        }

#else

        {

            status = cpp.init(szURL, es_info.pek);
            BREAK_IF_FAILED(status);

            //=====================================================================
            // Start: CERTIFICATE CHAIN PROVISIONING  (3.6.7.1.1.2.1)
            //=====================================================================

            //*********************************************************************
            // Retrieve GID_SE from the QE
            SGX_DBGPRINT_PRINT_ANSI_STRING("quote init?");
            //*********************************************************************
            status = do_quote_initialization(target_info, (GroupId*)&gid);
            BREAK_IF_FAILED(status);//keep reason for quoting failure including UPDATE required
            SGX_DBGPRINT_PRINT_ANSI_STRING("quote init success");

            //*********************************************************************
            // Retrieve SIG_RL and Nonce from Intel Server.
            //*********************************************************************
            status = cpp.SendM1_ReceiveM2(*(uint32_t*)&gid, nonce, sig_rl);
            BREAK_IF_FAILED(status);
            SGX_DBGPRINT_PRINT_ANSI_STRING("send m1, receive m2 success");

            Helper::read_ltp_blob(pairing_blob);
            // Note: failure during read_ltp_blob is okay, pairing_blob will be empty and get filled in by enclave

            //*********************************************************************
            // Generate ECDSA key pair, CSR_pse, and REPORT in enclave (PSE_Pr).
            //*********************************************************************
            status = tPrepareForCertificateProvisioning(nonce, target_info, csr_pse,
                report, pairing_blob);
            BREAK_IF_FAILED(status);
            SGX_DBGPRINT_PRINT_ANSI_STRING("prepare for cert pv success");

            //*********************************************************************
            // Call QE to convert REPORT to name-based QUOTE using SIG_RL
            //*********************************************************************
            status = do_get_quote(report, sig_rl, quote);
            BREAK_IF_TRUE((AESM_AE_OUT_OF_EPC == status), status, AESM_AE_OUT_OF_EPC);
            BREAK_IF_FAILED_ERR(status, AESM_CP_ATTESTATION_FAILURE);
            SGX_DBGPRINT_PRINT_ANSI_STRING("get quote success");

            //*********************************************************************
            // Retrieve the Certificate Chain from Intel Server.
            //*********************************************************************
            status = cpp.SendM3_ReceiveM4(csr_pse, quote, certChain, *pib_wrapper);
            BREAK_IF_TRUE((PSE_PRS_OK != cpp.GetProtocolResponseStatus()), status, AESM_CP_ATTESTATION_FAILURE);
            BREAK_IF_FAILED(status);
            SGX_DBGPRINT_PRINT_ANSI_STRING("send m3, receive m4 success");
        }

#endif

        //*********************************************************************
        // Save the Certificate Chain to persistent storage.
        //*********************************************************************
        status = Helper::SaveCertificateChain(certChain);
        BREAK_IF_FAILED(status);
        SGX_DBGPRINT_PRINT_ANSI_STRING("save cert success");

        //*********************************************************************
        // Save the sealed pairing blob to persistent storage.
        //*********************************************************************
        status = Helper::write_ltp_blob(pairing_blob);
        BREAK_IF_FAILED(status);
        SGX_DBGPRINT_PRINT_ANSI_STRING("write blob success");

        status = AE_SUCCESS;

        SGX_DBGPRINT_PRINT_ANSI_STRING("End of Certificate (PSE) Provisioning");
    } while (0);

    status = ConvertBackendStatus(cpp, status);
    return status;
}
コード例 #7
0
ファイル: quoting_enclave.cpp プロジェクト: 01org/linux-sgx
/*
 * An internal function used to verify EPID Blob, get EPID Group Cert
 * and get EPID context, at the same time, you can check whether EPID blob has
 * been resealed.
 *
 * @param p_blob[in, out] Pointer to EPID Blob.
 * @param p_is_resealed[out] Whether the EPID Blob has been resealed.
 * @param create_context[in] Flag indicates create EPID context or not.
 * @param plaintext_epid_data[out] Used to get the plaintext part of epid blob
 * @param pp_epid_context[out] Used to get the pointer of the EPID context.
 * @param p_cpusvn[out] Return the raw CPUSVN.
 * @return ae_error_t AE_SUCCESS or other error cases.
 */
static ae_error_t verify_blob_internal(
    uint8_t *p_blob,
    uint32_t blob_size,
    uint8_t *p_is_resealed,
    uint32_t create_context,
    se_plaintext_epid_data_sdk_t& plaintext_epid_data,
    MemberCtx **pp_epid_context,
    sgx_cpu_svn_t *p_cpusvn)
{
    ae_error_t ret = QE_UNEXPECTED_ERROR;
    sgx_status_t se_ret = SGX_SUCCESS;
    uint8_t resealed = FALSE;
    se_secret_epid_data_sdk_t secret_epid_data;
    se_plaintext_epid_data_sik_t plaintext_old_format;
    uint32_t plaintext_length;
    int is_old_format = 0;
    uint32_t decryptedtext_length = sizeof(secret_epid_data);
    sgx_sealed_data_t *p_epid_blob = (sgx_sealed_data_t *)p_blob;
    uint8_t local_epid_blob[sizeof(*p_epid_blob)
                            + sizeof(secret_epid_data)
                            + sizeof(plaintext_epid_data)]
                            = {0};
    MemberCtx *p_ctx = NULL;

    do {
        // We will use plaintext_old_format as buffer to hold the output of sgx_unseal_data.
        // It can be se_plaintext_epid_data_sik_t or se_plaintext_epid_data_sdk_t.
        // We use the static assert to reassure plaintext_old_format is big enough.
        // If someone changed the definition of these 2 structures and break current assumption,
        // it will report error in compile time.
        se_static_assert(sizeof(plaintext_old_format) >= sizeof(plaintext_epid_data));

        if (sgx_get_encrypt_txt_len(p_epid_blob) != sizeof(se_secret_epid_data_sdk_t) &&
            sgx_get_encrypt_txt_len(p_epid_blob) != sizeof(se_secret_epid_data_sik_t)) {
            return QE_EPIDBLOB_ERROR;
        }
        plaintext_length = sgx_get_add_mac_txt_len(p_epid_blob);
        if (plaintext_length != sizeof(se_plaintext_epid_data_sik_t) &&
            plaintext_length != sizeof(se_plaintext_epid_data_sdk_t))
        {
            return QE_EPIDBLOB_ERROR;
        }

        memset(&secret_epid_data, 0, sizeof(secret_epid_data));
        memset(&plaintext_epid_data, 0, sizeof(plaintext_epid_data));
        memset(&plaintext_old_format, 0, sizeof(plaintext_old_format));

        se_ret = sgx_unseal_data(p_epid_blob,
            (uint8_t *)&plaintext_old_format, // The unsealed plaintext can be old or new format, the buffer is defined as old format because it is bigger
            &plaintext_length,
            (uint8_t *)&secret_epid_data,
            &decryptedtext_length);
        BREAK_IF_TRUE(SGX_SUCCESS != se_ret, ret, QE_EPIDBLOB_ERROR);

        //QE will support both epid blob with/without member precomputation
        //If the epid blob without member precomputation is used, QE will generate member precomputation and reseal epid blob
        //blob_type and key_version are always first two fields of plaintext in both format
        BREAK_IF_TRUE((plaintext_old_format.seal_blob_type != PVE_SEAL_EPID_KEY_BLOB)
            || (plaintext_old_format.epid_key_version != EPID_KEY_BLOB_VERSION_SDK&&
                plaintext_old_format.epid_key_version != EPID_KEY_BLOB_VERSION_SIK),
            ret, QE_EPIDBLOB_ERROR);

        // Only 2 combinations are legitimate for the tuple epid_key_version|decryptedtext_length|plaintext_length:
        // EPID_KEY_BLOB_VERSION_SIK|sizeof(se_secret_epid_data_sik_t)|sizeof(se_plaintext_epid_data_sik_t)
        // EPID_KEY_BLOB_VERSION_SDK|sizeof(se_secret_epid_data_sdk_t)|sizeof(se_plaintext_epid_data_sdk_t)
        BREAK_IF_TRUE((plaintext_old_format.epid_key_version == EPID_KEY_BLOB_VERSION_SIK &&
            (decryptedtext_length != sizeof(se_secret_epid_data_sik_t) || plaintext_length != sizeof(se_plaintext_epid_data_sik_t))) ||
            (plaintext_old_format.epid_key_version == EPID_KEY_BLOB_VERSION_SDK &&
            (decryptedtext_length != sizeof(se_secret_epid_data_sdk_t) || plaintext_length != sizeof(se_plaintext_epid_data_sdk_t))),
            ret, QE_EPIDBLOB_ERROR);

        // If the input epid blob is in sik format, we will upgrade it to sdk version
        if (plaintext_old_format.epid_key_version == EPID_KEY_BLOB_VERSION_SIK) {
            plaintext_epid_data.seal_blob_type = PVE_SEAL_EPID_KEY_BLOB;
            plaintext_epid_data.epid_key_version = EPID_KEY_BLOB_VERSION_SDK;
            memcpy(&plaintext_epid_data.equiv_cpu_svn, &plaintext_old_format.equiv_cpu_svn, sizeof(plaintext_old_format.equiv_cpu_svn));
            memcpy(&plaintext_epid_data.equiv_pve_isv_svn, &plaintext_old_format.equiv_pve_isv_svn, sizeof(plaintext_old_format.equiv_pve_isv_svn));
            memcpy(&plaintext_epid_data.epid_group_cert, &plaintext_old_format.epid_group_cert, sizeof(plaintext_old_format.epid_group_cert));
            memcpy(&plaintext_epid_data.qsdk_exp, &plaintext_old_format.qsdk_exp, sizeof(plaintext_old_format.qsdk_exp));
            memcpy(&plaintext_epid_data.qsdk_mod, &plaintext_old_format.qsdk_mod, sizeof(plaintext_old_format.qsdk_mod));
            memcpy(&plaintext_epid_data.epid_sk, &plaintext_old_format.epid_sk, sizeof(plaintext_old_format.epid_sk));
            plaintext_epid_data.xeid = plaintext_old_format.xeid;
            memset(&secret_epid_data.member_precomp_data, 0, sizeof(secret_epid_data.member_precomp_data));
            is_old_format = 1;
            //PrivKey of secret_epid_data are both in offset 0 so that we need not move it
        }
        else {//SDK version format
            memcpy(&plaintext_epid_data, &plaintext_old_format, sizeof(plaintext_epid_data));
        }

        /* Create report to get current cpu_svn and isv_svn. */
        sgx_report_t report;
        memset(&report, 0, sizeof(report));
        se_ret = sgx_create_report(NULL, NULL, &report);
        BREAK_IF_TRUE(SGX_SUCCESS != se_ret, ret, QE_UNEXPECTED_ERROR);

        /* Get the random function pointer. */
        BitSupplier rand_func = epid_random_func;

        /* Create EPID member context if required. PvE is responsible for verifying
        the Cert signature before storing them in the EPID blob. */
        if (create_context || is_old_format)
        {
            EpidStatus epid_ret = kEpidNoErr;
            epid_ret = epid_member_create(rand_func, NULL, NULL, &p_ctx);
            BREAK_IF_TRUE(kEpidNoErr != epid_ret, ret, QE_UNEXPECTED_ERROR);

            epid_ret = EpidProvisionKey(p_ctx,
                &(plaintext_epid_data.epid_group_cert),
                (PrivKey*)&(secret_epid_data.epid_private_key),
                is_old_format ? NULL : &secret_epid_data.member_precomp_data);
            BREAK_IF_TRUE(kEpidNoErr != epid_ret, ret, QE_UNEXPECTED_ERROR);

            // start member
            epid_ret = EpidMemberStartup(p_ctx);
            BREAK_IF_TRUE(kEpidNoErr != epid_ret, ret, QE_UNEXPECTED_ERROR);

            if (is_old_format)
            {
                epid_ret = EpidMemberWritePrecomp(p_ctx, &secret_epid_data.member_precomp_data);
                BREAK_IF_TRUE(kEpidNoErr != epid_ret, ret, QE_UNEXPECTED_ERROR);
            }
        }

        /* Update the Key Blob using the SEAL Key for the current TCB if the TCB is
           upgraded after the Key Blob is generated. Here memcmp cpu_svns might be
           different even though they're actually same, but for defense in depth we
           will keep this comparison here. And we will also upgrade old format EPID
           blob to new format here. */
        if ((memcmp(&report.body.cpu_svn, &p_epid_blob->key_request.cpu_svn,
            sizeof(report.body.cpu_svn)))
            || (report.body.isv_svn != p_epid_blob->key_request.isv_svn)
            || plaintext_old_format.epid_key_version == EPID_KEY_BLOB_VERSION_SIK)
        {
            se_ret = sgx_seal_data(sizeof(plaintext_epid_data),
                (uint8_t *)&plaintext_epid_data,
                sizeof(secret_epid_data),
                (uint8_t *)&secret_epid_data,
                SGX_TRUSTED_EPID_BLOB_SIZE_SDK,
                (sgx_sealed_data_t *)local_epid_blob);
            BREAK_IF_TRUE(SGX_SUCCESS != se_ret, ret, QE_UNEXPECTED_ERROR);

            memcpy(p_epid_blob, local_epid_blob, blob_size);
            resealed = TRUE;
        }
        *p_is_resealed = resealed;
        memcpy(p_cpusvn, &report.body.cpu_svn, sizeof(*p_cpusvn));
        ret = AE_SUCCESS;
    }
    while (false);

    // Clear the output buffer to make sure nothing leaks.
    memset_s(&secret_epid_data, sizeof(secret_epid_data), 0,
        sizeof(secret_epid_data));
    if (AE_SUCCESS != ret) {
        if (p_ctx)
            epid_member_delete(&p_ctx);
    }
    else if (!create_context) {
        if (p_ctx)
            epid_member_delete(&p_ctx);
    }
    else {
        *pp_epid_context = p_ctx;
    }

    return ret;
}
コード例 #8
0
ae_error_t prepare_for_certificate_provisioning
(
    /*in */ UINT64  nonce64,
    /*in */ const sgx_target_info_t*     pTargetInfo,
    /*in */ UINT16  nMax_CSR_pse,
    /*out*/ UINT8*  pCSR_pse,
    /*out*/ UINT16* pnLen_CSR_pse,
    /*out*/ sgx_report_t*          pREPORT,
    /*i/o*/ pairing_blob_t* pPairingBlob
)
{
    // Flow:  1) Check pointers for buffer data sizes
    //        2) If buffers are too small, return and tell caller size required
    //        3) Validate pointers and ensure buffers are within the enclave
    //        4) Generate a new private/public ECDSA key pair
    //        5) Request signed CSR template
    //        6) Calculate HASH_pse of (CSR_pse || nonce64)
    //        7) Generate REPORT with HASH_pse as the REPORTDATA, targeting QE
    //        8) Copy private key and public key into unsealed_pairing buffer
    //        9) Seal pairing blob
    //       10) Return Sealed pairing blob, generated CSR, REPORT, and status

    ae_error_t status = AE_FAILURE;

    pairing_data_t pairingData;
    EcDsaPrivKey privateKey;
    EcDsaPubKey publicKey;
    uint8_t     temp_instance_id[16];

    SignCSR CSR;

    size_t nMaxSizeCSR = CSR.GetMaxSize();
    sgx_ecc_state_handle_t csr_ecc_handle = NULL;

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

    /////////////////////////////////////////////////////////////////

    do
    {
        //*********************************************************************
        // Validate pointers and sizes
        //*********************************************************************
        BREAK_IF_TRUE((NULL == pPairingBlob),
            status, PSE_PR_BAD_POINTER_ERROR);

        // save SW_INSTANCE_ID
        memcpy(temp_instance_id, pPairingBlob->plaintext.pse_instance_id, sizeof(temp_instance_id));

        {

            BREAK_IF_TRUE((NULL == pTargetInfo),
                status, PSE_PR_BAD_POINTER_ERROR);

            BREAK_IF_TRUE((NULL == pREPORT),
                status, PSE_PR_BAD_POINTER_ERROR);

            BREAK_IF_TRUE((NULL == pCSR_pse || NULL == pnLen_CSR_pse),
                status, PSE_PR_BAD_POINTER_ERROR);

            BREAK_IF_TRUE((nMax_CSR_pse < nMaxSizeCSR),
                status, PSE_PR_PARAMETER_ERROR);

            BREAK_IF_FALSE(sgx_is_within_enclave(pCSR_pse, nMaxSizeCSR), status, PSE_PR_BAD_POINTER_ERROR);

            //*********************************************************************
            // Generate a new ECDSA Key Pair
            //*********************************************************************
            
            sgx_status_t sgx_status = sgx_ecc256_open_context(&csr_ecc_handle);
            BREAK_IF_TRUE((SGX_ERROR_OUT_OF_MEMORY == sgx_status), status, PSE_PR_INSUFFICIENT_MEMORY_ERROR);
            BREAK_IF_TRUE((SGX_SUCCESS != sgx_status), status, PSE_PR_KEY_PAIR_GENERATION_ERROR);

            sgx_status = sgx_ecc256_create_key_pair((sgx_ec256_private_t *)privateKey, (sgx_ec256_public_t*)publicKey, csr_ecc_handle);
            BREAK_IF_TRUE((SGX_SUCCESS != sgx_status), status, PSE_PR_KEY_PAIR_GENERATION_ERROR);

            *pnLen_CSR_pse = (uint16_t)nMaxSizeCSR;

            //*********************************************************************
            // Get a signed Certificate Signing Request from the template
            //*********************************************************************
            status = CSR.GetSignedTemplate(&privateKey, &publicKey, csr_ecc_handle,  pCSR_pse, pnLen_CSR_pse);
            BREAK_IF_FAILED(status);

            //*********************************************************************
            // Calculate HASH_pse of (CSR_pse || nonce64)
            //*********************************************************************
            PrepareHashSHA256 hash;
            SHA256_HASH computedHash;
            status = hash.Update(pCSR_pse, *pnLen_CSR_pse);
            BREAK_IF_FAILED(status);
            status = hash.Update(&nonce64, sizeof(nonce64));
            BREAK_IF_FAILED(status);
            status = hash.Finalize(&computedHash);
            BREAK_IF_FAILED(status);

            //*********************************************************************
            // Generate a REPORT with HASH_pse
            //*********************************************************************
            sgx_report_data_t report_data = {{0}};
            memcpy(&report_data, &computedHash, sizeof(computedHash));
            if (SGX_SUCCESS != sgx_create_report(const_cast<sgx_target_info_t*>(pTargetInfo), 
                &report_data, (sgx_report_t*)pREPORT))
            {
                status = PSE_PR_CREATE_REPORT_ERROR;
                break;
            }

            //*********************************************************************
            // Try to unseal the pairing data
            //*********************************************************************
            status = UnsealPairingBlob(pPairingBlob, &pairingData);
            if (AE_FAILED(status))
                memset_s(&pairingData, sizeof(pairingData), 0, sizeof(pairingData));

            //*********************************************************************
            // Seal ECDSA Verifier Private Key into blob
            //*********************************************************************

            memcpy(pairingData.secret_data.VerifierPrivateKey, &privateKey, sizeof(EcDsaPrivKey));
        
        } // "Public" PSE Cert

        // Set pairingData.plaintext.pse_instance_id using saved temp_instance_id
        memcpy(pairingData.plaintext.pse_instance_id, temp_instance_id, sizeof(pairingData.plaintext.pse_instance_id));

        status = SealPairingBlob(&pairingData, pPairingBlob);
        BREAK_IF_FAILED(status);

        //*********************************************************************
        // WE PASSED ALL BARRIERS TO SUCCESS
        //*********************************************************************

        status = AE_SUCCESS;

//        OutputOctets("::tPrepareForCertificateProvisioning:: New CSR generated", NULL, 0);

    } while (false);

    // Defense-in-depth: clear the data on stack that contains enclave secret.
    memset_s(&pairingData, sizeof(pairingData), 0, sizeof(pairingData));
    memset_s(&privateKey, sizeof(privateKey), 0, sizeof(privateKey));

    if (csr_ecc_handle != NULL) sgx_ecc256_close_context(csr_ecc_handle);

    return map_error_for_return(status);

}