Example #1
0
//Function to verify that ECDSA signature of XEGB is correct
sgx_status_t verify_xegb(const extended_epid_group_blob_t& xegb, uint8_t *result){
    if (lv_htons(xegb.data_length) != EXTENDED_EPID_GROUP_BLOB_DATA_LEN
        || xegb.format_id != XEGB_FORMAT_ID){
        return SGX_ERROR_INVALID_PARAMETER;
    }

    sgx_status_t status = SGX_SUCCESS;
    sgx_ecc_state_handle_t handle= 0;
    sgx_ec256_signature_t ec_signature;
    status = sgx_ecc256_open_context(&handle);
    if(SGX_SUCCESS!=status){
        return status;
    }
    se_static_assert(sizeof(ec_signature)==sizeof(xegb.signature));
    memcpy(&ec_signature, xegb.signature, sizeof(xegb.signature));
    SWAP_ENDIAN_32B(ec_signature.x);
    SWAP_ENDIAN_32B(ec_signature.y);
    status = sgx_ecdsa_verify(reinterpret_cast<const uint8_t *>(&xegb),
        static_cast<uint32_t>(sizeof(xegb)-sizeof(xegb.signature)),
        const_cast<sgx_ec256_public_t *>(&g_sdsk_pub_key_little_endian),
        &ec_signature,
        result,
        handle);
    (void)sgx_ecc256_close_context(handle);
    if(SGX_SUCCESS!=status){
        return status;
    }
    return SGX_SUCCESS;
}
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;
}
Example #3
0
//Function to verify the ECDSA signature of a PEK
//SHA1 value for integrity checking is not verified since the ECDSA verification could make sure the integrity at the same time.
sgx_status_t check_pek_signature(const signed_pek_t& signed_pek, const sgx_ec256_public_t* pek_sk, uint8_t *result)
{
    sgx_status_t status = SGX_SUCCESS;
    sgx_ecc_state_handle_t handle= 0;
    sgx_ec256_signature_t ec_signature;
    status = sgx_ecc256_open_context(&handle);
    if(SGX_SUCCESS!=status){
        return status;
    }
    se_static_assert(sizeof(ec_signature)==sizeof(signed_pek.pek_signature));
    memcpy(&ec_signature, signed_pek.pek_signature, sizeof(signed_pek.pek_signature));
    SWAP_ENDIAN_32B(ec_signature.x);
    SWAP_ENDIAN_32B(ec_signature.y);
    status = sgx_ecdsa_verify(reinterpret_cast<const uint8_t *>(&signed_pek),
        static_cast<uint32_t>(sizeof(signed_pek.n)+sizeof(signed_pek.e)),
        pek_sk,
        &ec_signature,
        result,
        handle);
    (void)sgx_ecc256_close_context(handle);
    return status;
}
Example #4
0
extern "C" sgx_status_t sgx_ra_proc_msg2_trusted(
    sgx_ra_context_t context,
    const sgx_ra_msg2_t *p_msg2,            //(g_b||spid||quote_type|| KDF_ID ||sign_gb_ga||cmac||sig_rl_size||sig_rl)
    const sgx_target_info_t *p_qe_target,
    sgx_report_t *p_report,
    sgx_quote_nonce_t* p_nonce)
{
    sgx_status_t se_ret = SGX_ERROR_UNEXPECTED;
    //p_msg2[in] p_qe_target[in] p_report[out] p_nonce[out] in EDL file
    if(vector_size(&g_ra_db) <= context
       || !p_msg2
       || !p_qe_target
       || !p_report
       || !p_nonce)
        return SGX_ERROR_INVALID_PARAMETER;

    ra_db_item_t* item = NULL;
    if(0 != vector_get(&g_ra_db, context, reinterpret_cast<void**>(&item)) || item == NULL )
        return SGX_ERROR_INVALID_PARAMETER;

    sgx_ec256_private_t a;
    memset(&a, 0, sizeof(a));
    // Create gb_ga
    sgx_ec256_public_t gb_ga[2];
    sgx_ec256_public_t sp_pubkey;
    sgx_ec_key_128bit_t smkey = {0};
    sgx_ec_key_128bit_t skey = {0};
    sgx_ec_key_128bit_t mkey = {0};
    sgx_ec_key_128bit_t vkey = {0};
    sgx_ra_derive_secret_keys_t ra_key_cb = NULL;

    memset(&gb_ga[0], 0, sizeof(gb_ga));
    sgx_spin_lock(&item->item_lock);
    //sgx_ra_get_ga must have been called
    if (item->state != ra_get_gaed)
    {
        sgx_spin_unlock(&item->item_lock);
        return SGX_ERROR_INVALID_STATE;
    }
    memcpy(&a, &item->a, sizeof(a));
    memcpy(&gb_ga[1], &item->g_a, sizeof(gb_ga[1]));
    memcpy(&sp_pubkey, &item->sp_pubkey, sizeof(sp_pubkey));
    ra_key_cb = DEC_KDF_POINTER(item->derive_key_cb);
    sgx_spin_unlock(&item->item_lock);
    memcpy(&gb_ga[0], &p_msg2->g_b, sizeof(gb_ga[0]));

    sgx_ecc_state_handle_t ecc_state = NULL;

    // ecc_state need to be freed when exit.
    se_ret = sgx_ecc256_open_context(&ecc_state);
    if (SGX_SUCCESS != se_ret)
    {
        if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
            se_ret = SGX_ERROR_UNEXPECTED;
        return se_ret;
    }

    sgx_ec256_dh_shared_t dh_key;
    memset(&dh_key, 0, sizeof(dh_key));
    sgx_ec256_public_t* p_msg2_g_b = const_cast<sgx_ec256_public_t*>(&p_msg2->g_b);
    se_ret = sgx_ecc256_compute_shared_dhkey(&a,
        (sgx_ec256_public_t*)p_msg2_g_b,
        &dh_key, ecc_state);
    if(SGX_SUCCESS != se_ret)
    {
        if (SGX_ERROR_OUT_OF_MEMORY != se_ret)
            se_ret = SGX_ERROR_UNEXPECTED;
        sgx_ecc256_close_context(ecc_state);
        return se_ret;
    }
    // Verify signature of gb_ga
    uint8_t result;
    sgx_ec256_signature_t* p_msg2_sign_gb_ga = const_cast<sgx_ec256_signature_t*>(&p_msg2->sign_gb_ga);
    se_ret = sgx_ecdsa_verify((uint8_t *)&gb_ga, sizeof(gb_ga),
        &sp_pubkey,
        p_msg2_sign_gb_ga,
        &result, ecc_state);
    if(SGX_SUCCESS != se_ret)
    {
        if (SGX_ERROR_OUT_OF_MEMORY != se_ret)
            se_ret = SGX_ERROR_UNEXPECTED;
        sgx_ecc256_close_context(ecc_state);
        return se_ret;
    }
    if(SGX_EC_VALID != result)
    {
        sgx_ecc256_close_context(ecc_state);
        return SGX_ERROR_INVALID_SIGNATURE;
    }

    do
    {
        if(NULL != ra_key_cb)
        {
            se_ret = ra_key_cb(&dh_key,
                               p_msg2->kdf_id,
                               &smkey,
                               &skey,
                               &mkey,
                               &vkey);
            if (SGX_SUCCESS != se_ret)
            {
                if(SGX_ERROR_OUT_OF_MEMORY != se_ret &&
                    SGX_ERROR_INVALID_PARAMETER != se_ret &&
                    SGX_ERROR_KDF_MISMATCH != se_ret)
                    se_ret = SGX_ERROR_UNEXPECTED;
                break;
            }
        }
        else if (p_msg2->kdf_id == 0x0001)
        {
            se_ret = derive_key(&dh_key, "SMK", (uint32_t)(sizeof("SMK") -1), &smkey);
            if (SGX_SUCCESS != se_ret)
            {
                if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                    se_ret = SGX_ERROR_UNEXPECTED;
                break;
            }
            se_ret = derive_key(&dh_key, "SK", (uint32_t)(sizeof("SK") -1), &skey);
            if (SGX_SUCCESS != se_ret)
            {
                if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                    se_ret = SGX_ERROR_UNEXPECTED;
                break;
            }

            se_ret = derive_key(&dh_key, "MK", (uint32_t)(sizeof("MK") -1), &mkey);
            if (SGX_SUCCESS != se_ret)
            {
                if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                    se_ret = SGX_ERROR_UNEXPECTED;
                break;
            }

            se_ret = derive_key(&dh_key, "VK", (uint32_t)(sizeof("VK") -1), &vkey);
            if (SGX_SUCCESS != se_ret)
            {
                if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                    se_ret = SGX_ERROR_UNEXPECTED;
                break;
            }
        }
        else
        {
            se_ret = SGX_ERROR_KDF_MISMATCH;
            break;
        }

        sgx_cmac_128bit_tag_t mac;
        uint32_t maced_size = offsetof(sgx_ra_msg2_t, mac);

        se_ret = sgx_rijndael128_cmac_msg(&smkey, (const uint8_t *)p_msg2, maced_size, &mac);
        if (SGX_SUCCESS != se_ret)
        {
            if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                se_ret = SGX_ERROR_UNEXPECTED;
            break;
        }
        //Check mac
        if(0 == consttime_memequal(mac, p_msg2->mac, sizeof(mac)))
        {
            se_ret = SGX_ERROR_MAC_MISMATCH;
            break;
        }

        //create a nonce
        se_ret =sgx_read_rand((uint8_t*)p_nonce, sizeof(sgx_quote_nonce_t));
        if (SGX_SUCCESS != se_ret)
        {
            if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                se_ret = SGX_ERROR_UNEXPECTED;
            break;
        }

        sgx_spin_lock(&item->item_lock);
        //sgx_ra_get_ga must have been called
        if (item->state != ra_get_gaed)
        {
            se_ret = SGX_ERROR_INVALID_STATE;
            sgx_spin_unlock(&item->item_lock);
            break;
        }
        memcpy(&item->g_b, &p_msg2->g_b, sizeof(item->g_b));
        memcpy(&item->smk_key, smkey, sizeof(item->smk_key));
        memcpy(&item->sk_key, skey, sizeof(item->sk_key));
        memcpy(&item->mk_key, mkey, sizeof(item->mk_key));
        memcpy(&item->vk_key, vkey, sizeof(item->vk_key));
        memcpy(&item->qe_target, p_qe_target, sizeof(sgx_target_info_t));
        memcpy(&item->quote_nonce, p_nonce, sizeof(sgx_quote_nonce_t));
        sgx_report_data_t report_data = {{0}};
        se_static_assert(sizeof(sgx_report_data_t)>=sizeof(sgx_sha256_hash_t));
        // H = SHA256(ga || gb || VK_CMAC)
        uint32_t sha256ed_size = offsetof(ra_db_item_t, sp_pubkey);
        //report_data is 512bits, H is 256bits. The H is in the lower 256 bits of report data while the higher 256 bits are all zeros.
        se_ret = sgx_sha256_msg((uint8_t *)&item->g_a, sha256ed_size,
                                (sgx_sha256_hash_t *)&report_data);
        if(SGX_SUCCESS != se_ret)
        {
            if (SGX_ERROR_OUT_OF_MEMORY != se_ret)
                se_ret = SGX_ERROR_UNEXPECTED;
            sgx_spin_unlock(&item->item_lock);
            break;
        }
        //REPORTDATA = H
        se_ret = sgx_create_report(p_qe_target, &report_data, p_report);
        if (SGX_SUCCESS != se_ret)
        {
            if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                se_ret = SGX_ERROR_UNEXPECTED;
            sgx_spin_unlock(&item->item_lock);
            break;
        }
        item->state = ra_proc_msg2ed;
        sgx_spin_unlock(&item->item_lock);
    }while(0);
    memset_s(&dh_key, sizeof(dh_key), 0, sizeof(dh_key));
    sgx_ecc256_close_context(ecc_state);
    memset_s(&a, sizeof(sgx_ec256_private_t),0, sizeof(sgx_ec256_private_t));
    memset_s(smkey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t));
    memset_s(skey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t));
    memset_s(mkey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t));
    memset_s(vkey, sizeof(sgx_ec_key_128bit_t),0, sizeof(sgx_ec_key_128bit_t));
    return se_ret;
}
Example #5
0
/*
 * Internal function used to init white list. It will check the content of the
 * cert chain, and verify the signature of input cert chains. If no problem,
 * it will cache the input white list into EPC.
 *
 * @param p_wl_cert_chain[in] Pointer to the white list cert chain.
 * @param entry_number[in] The entry number within the white list.
 * @param wl_cert_chain_size[in] The size of white list cert chain, in bytes.
 * @return uint32_t AE_SUCCESS for success, otherwise for errors.
 */
uint32_t le_init_white_list(
    const wl_cert_chain_t *p_wl_cert_chain,
    uint32_t entry_number,
    uint32_t wl_cert_chain_size)
{
    sgx_status_t sgx_ret = SGX_SUCCESS;
    uint32_t ret = AE_SUCCESS;
    uint32_t new_wl_version = 0;
    uint8_t verify_result = 0;
    int valid = 0;
    const uint8_t *buf = NULL;
    uint32_t buf_size = 0;
    sgx_prod_id_t wl_prod_id = 0;
    sgx_ecc_state_handle_t ecc_handle = NULL;
    wl_cert_t *p_wl_cert_cache = (wl_cert_t *)g_wl_cert_buf;
    sgx_report_t report;
    sgx_ec256_signature_t wl_signature;
    sgx_ec256_public_t wl_pubkey;


    // Check fields of provider cert
    // Format version should be 1 (big endian)
    if(p_wl_cert_chain->wl_provider_cert.version != WL_PROVIDER_CERT_VERSION)
    {
        ret = LE_INVALID_PARAMETER;
        goto CLEANUP;
    }
    // For Enclave Signing Key White List Cert, must be 0
    if(p_wl_cert_chain->wl_provider_cert.cert_type != WL_PROVIDER_CERT_TYPE)
    {
        ret = LE_INVALID_PARAMETER;
        goto CLEANUP;
    }
    // only one White List Provider is approved:
    // WLProviderID: ISecG = 0
    if(p_wl_cert_chain->wl_provider_cert.provider_id != WL_PROVIDER_CERT_PROVIDER_ID)
    {
        ret = LE_INVALID_PARAMETER;
        goto CLEANUP;
    }
    // only one WLRootID is valid: WLRootID-iKGF-Key-0 = 0
    if(p_wl_cert_chain->wl_provider_cert.root_id != WL_PROVIDER_CERT_ROOT_ID)
    {
        ret = LE_INVALID_PARAMETER;
        goto CLEANUP;
    }

    // Check fields of wl cert
    // only valid version is 1
    if(p_wl_cert_chain->wl_cert.version != WL_CERT_VERSION)
    {
        ret = LE_INVALID_PARAMETER;
        goto CLEANUP;
    }
    // For Enclave Signing Key White List Cert, must be 1
    if(p_wl_cert_chain->wl_cert.cert_type != WL_CERT_TYPE)
    {
        ret = LE_INVALID_PARAMETER;
        goto CLEANUP;
    }
    // only one White List Provider is approved:
    // WLProviderID: ISecG = 0
    if(p_wl_cert_chain->wl_cert.provider_id != WL_CERT_PROVIDER_ID)
    {
        ret = LE_INVALID_PARAMETER;
        goto CLEANUP;
    }

    // If cache exists
    new_wl_version = p_wl_cert_chain->wl_cert.wl_version;
    new_wl_version = _ntohl(new_wl_version);
    if(p_wl_cert_cache->version != 0)
    {
        // the logic will be needed to support more than
        // one providers in the future.
        //if(p_wl_cert_chain->wl_cert.provider_id
        //   != p_wl_cert_cache->provider_id)
        //{
        //    ret = LE_INVALID_PARAMETER;
        //    goto CLEANUP;
        //}
        if(new_wl_version < p_wl_cert_cache->wl_version)
        {
            ret = LE_INVALID_PARAMETER;
            goto CLEANUP;
        }
    }

    sgx_ret = sgx_ecc256_open_context(&ecc_handle);
    if (SGX_SUCCESS != sgx_ret)
    {
        ret = LE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }

    memset(&wl_signature, 0, sizeof(wl_signature));
    // Convert the signature of provider cert into little endian
    memcpy(&wl_signature,
           &(p_wl_cert_chain->wl_provider_cert.signature),
           sizeof(wl_signature));
    SWAP_ENDIAN_8X32B(wl_signature.x);
    SWAP_ENDIAN_8X32B(wl_signature.y);

    // Verify the wl provider cert
    buf = (const uint8_t *)&(p_wl_cert_chain->wl_provider_cert);
    buf_size = static_cast<uint32_t>(sizeof(p_wl_cert_chain->wl_provider_cert)
               - sizeof(p_wl_cert_chain->wl_provider_cert.signature));
    sgx_ret = sgx_ecdsa_verify(buf, buf_size,
                               &g_wl_root_pubkey,
                               &wl_signature,
                               &verify_result,
                               ecc_handle);
    if (SGX_SUCCESS != sgx_ret)
    {
        ret = LE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }
    if(SGX_EC_VALID != verify_result)
    {
        ret = LE_INVALID_PARAMETER;
        goto CLEANUP;
    }

    // Convert the signature of wl cert into little endian
    buf = (const uint8_t *)p_wl_cert_chain + wl_cert_chain_size
          - sizeof(wl_signature);
    memcpy(&wl_signature, buf, sizeof(wl_signature));
    SWAP_ENDIAN_8X32B(wl_signature.x);
    SWAP_ENDIAN_8X32B(wl_signature.y);

    // Convert the pubkey into little endian
    memset(&wl_pubkey, 0, sizeof(wl_pubkey));
    memcpy(&wl_pubkey,
           &(p_wl_cert_chain->wl_provider_cert.pub_key),
           sizeof(wl_pubkey));
    reverse_byte_array(wl_pubkey.gx, sizeof(wl_pubkey.gx));
    reverse_byte_array(wl_pubkey.gy, sizeof(wl_pubkey.gy));

    // Check whether the pubkey is valid first.
    sgx_ret = sgx_ecc256_check_point(&wl_pubkey, ecc_handle, &valid);
    if(SGX_SUCCESS != sgx_ret)
    {
        ret = LE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }
    if(!valid)
    {
        ret = LE_INVALID_PARAMETER;
        goto CLEANUP;
    }

    // Verify the wl_cert
    buf = (const uint8_t *)&(p_wl_cert_chain->wl_cert);
    buf_size = wl_cert_chain_size - static_cast<uint32_t>(sizeof(wl_provider_cert_t) + sizeof(sgx_ec256_signature_t));
    sgx_ret = sgx_ecdsa_verify(buf, buf_size,
                               &wl_pubkey,
                               &wl_signature,
                               &verify_result,
                               ecc_handle);
    if (SGX_SUCCESS != sgx_ret)
    {
        ret = LE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }
    if(SGX_EC_VALID != verify_result)
    {
        ret = LE_INVALID_PARAMETER;
        goto CLEANUP;
    }

    memset(&report, 0, sizeof(report));
    // Create report to get current mrsigner.
    sgx_ret = sgx_create_report(NULL, NULL, &report);
    if(SGX_SUCCESS != sgx_ret)
    {
        ret = LE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }

    // Convert the big endian prod id to little endian.
    wl_prod_id = p_wl_cert_chain->wl_cert.le_prod_id;
    wl_prod_id = _ntohs(wl_prod_id);
    if(report.body.isv_prod_id != wl_prod_id)
    {
        ret = LE_INVALID_PARAMETER;
        goto CLEANUP;
    }

    // Cache the wl cert
    memset(g_wl_cert_buf, 0, sizeof(g_wl_cert_buf));
    memcpy(g_wl_cert_buf, &(p_wl_cert_chain->wl_cert), buf_size);
    // Change entry_number and wl_version to little endian, so we don't need to
    // convert them next time.
    p_wl_cert_cache->entry_number = entry_number;
    p_wl_cert_cache->wl_version = new_wl_version;

CLEANUP:
    if(ecc_handle != NULL)
    {
        sgx_ecc256_close_context(ecc_handle);
    }
    return ret;

}