Пример #1
0
//This function will first generate EPIDSig Header according to sigrl_header
//After that, piece meal algorithm is used to
//   decode SigRl Entry in msg2 and update hash value 
//   generate EPIDSigEntry in msg3 and encrypt it
// The memory of msg2 for SigRl and  msg3 for EPIDSigEntry are all outside enclave
//     So that we need first copy each SigRl Entry into EPC memory, generate EPIDSigEntry inside EPC memory 
//            and copy it out after it is generated
//   The function assumes the size of SigRl has been verfied and it is not checked again here. 
// Finally it checks whether the hash value is valid according to ECDSA Sign in the end of SigRl to verify data is not modified
// A TLV Header for the EpidSignature should have been prepared in EPC memory signature_tlv_header
//It is assumed that the parm->sigrl_count>0 when the function is called and the size of sigrl has been checked
//EpidSignature TLV format: TLVHeader:EpidSignatureHeader:NrProof1:NrProof2:...:NrProofn
static pve_status_t gen_msg3_signature(const proc_prov_msg2_blob_input_t *msg2_blob_input,
                                       prov_msg3_parm_t *parm, 
                                       external_memory_byte_t *emp_signature,//pointer to external memory to write the EPID Signature
                                       uint32_t& signature_size) 
{
    pve_status_t ret = PVEC_SUCCESS;
    uint32_t cur_size = static_cast<uint32_t>(EPID_SIGNATURE_TLV_HEADER_SIZE+sizeof(EpidSignature)-sizeof(NrProof));
    //emp_proof_entry is pointer to external memory to each entry of the epid signature body in external memory
    external_memory_byte_t *emp_proof_entry = emp_signature + cur_size; 
    //emp_sigrl_entry is pointer to external memory to each entry of the sigrl_body in external memory
    const external_memory_byte_t *emp_sigrl_entry = parm->emp_sigrl_sig_entries;
    uint32_t i,entry_count = parm->sigrl_count;
    bool revoked = false;
    uint8_t sigrl_sign[2*ECDSA_SIGN_SIZE];//temp buffer in EPC to hold ECDSA signature
    //declare a buffer to hold encrypted data of TLV Header and EpidSignature Header
    uint8_t signature_header_to_encrypt[EPID_SIGNATURE_TLV_HEADER_SIZE + sizeof(EpidSignature)-sizeof(NrProof)];
    SigRlEntry temp1;
    NrProof temp3;
    uint32_t tlv_payload_size = 0;
    const SigRl *sigrl_header = NULL;
    BigNumStr rnd_bsn = { 0 };
    sgx_status_t sgx_status = SGX_SUCCESS;

    memset(sigrl_sign, 0, sizeof(sigrl_sign));
    memset(&temp1, 0, sizeof(temp1));
    memset(&temp3, 0, sizeof(temp3));
    memset(signature_header_to_encrypt, 0, sizeof(signature_header_to_encrypt));

    if(entry_count>0){
        sigrl_header = &parm->sigrl_header.sig_rl;//use the sigrl_header only when sigrl is available
        if(signature_size <  cur_size){//size of output buffer at least to hold currently generated data
            ret = PVEC_INSUFFICIENT_MEMORY_ERROR;
            goto ret_point;
        }
        if((signature_size-cur_size)/entry_count<sizeof(NrProof)){//safe way to check buffer overflow of output buffer to avoid integer overflow
            ret = PVEC_INSUFFICIENT_MEMORY_ERROR;
            goto ret_point;
        }
        tlv_payload_size = static_cast<uint32_t>(sizeof(EpidSignature)-sizeof(NrProof) + entry_count * sizeof(NrProof));
    }else{
        tlv_payload_size = static_cast<uint32_t>(sizeof(EpidSignature)-sizeof(NrProof)); //payload size for 0 entry, only basic signature with n2 and rl_ver to be 0
        if(signature_size <  cur_size){//size of output buffer at least to hold currently generated data
            ret = PVEC_INSUFFICIENT_MEMORY_ERROR;
            goto ret_point;
        }
    }

    memcpy(signature_header_to_encrypt, EPID_SIGNATURE_TLV_HEADER, EPID_SIGNATURE_TLV_HEADER_SIZE); //copy in the hard coded EPID Signature TLV Header
    tlv_payload_size = pve_htonl(tlv_payload_size);
    //overwritten the bigendian size in TLV Header. It is assumed that the size in TLV Header is always 4 bytes//Long format
    memcpy(signature_header_to_encrypt+EPID_SIGNATURE_TLV_SIZE_OFFSET, &tlv_payload_size, sizeof(tlv_payload_size));

    ret = gen_epid_signature_header(sigrl_header, parm->epid_member, msg2_blob_input->challenge_nonce, &parm->signature_header, &rnd_bsn);//Now generate EpidSignatureHeader 
    if( PVEC_SUCCESS != ret )
        goto ret_point;
    //Now encrypt the TLV Header and signature header including basic signature while the parm->signature_header is kept since piece-meal processing will use it
    memcpy(signature_header_to_encrypt+EPID_SIGNATURE_TLV_HEADER_SIZE, &parm->signature_header, cur_size-EPID_SIGNATURE_TLV_HEADER_SIZE);
    ret = sgx_error_to_pve_error(sgx_aes_gcm128_enc_inplace_update((sgx_aes_state_handle_t*)parm->p_msg3_state, signature_header_to_encrypt, cur_size));
    if( PVEC_SUCCESS != ret )
        goto ret_point;

    pve_memcpy_out(emp_signature, signature_header_to_encrypt, cur_size);//copy out tlv header, basic signature and other epid signature header info if required

    if(NULL==parm->emp_sigrl_sig_entries){//finish if no sigrl avaiable
        signature_size = cur_size;
        goto ret_point;
    }

    //copy the ECDSA Signature of the SigRl in ProvMsg2 into EPC memory in advance to defense in depth
    pve_memcpy_in(sigrl_sign, emp_sigrl_entry + entry_count *sizeof(SigRlEntry), 2*ECDSA_SIGN_SIZE);

    //piece-meal processing
    //The pointer calculation will never overflow as soon as size of sigrl and epid signature have been checked in advance
    //TO BE CLARIFY:We assume that the ecdsa signature follows entry array of SigRl directly 
    //  If later we change the format of sigrl to include extra data which should be ecdsa signed too,
    //       we need do the modification here: change the sigrl_sign and do more sha update
    signature_size = static_cast<uint32_t>(cur_size+entry_count *sizeof(NrProof));//recalculate output buffer
    //Start piece meal processing for each entry
    for(i=0;i<entry_count; i++){
        pve_memcpy_in(&temp1, emp_sigrl_entry, sizeof(temp1));//copy the data into trusted memory
        //update hash for the SigRl Entry
        sgx_status = sgx_sha256_update(reinterpret_cast<uint8_t *>(&temp1), sizeof(SigRlEntry), parm->sha_state);
        if(sgx_status != SGX_SUCCESS){
            ret = sgx_error_to_pve_error(sgx_status);
            goto ret_point;
        }
        //generate NrProof for the SigRl Entry in trusted memory
        EpidStatus epid_ret = EpidNrProve(parm->epid_member,
            const_cast<uint8_t *>(msg2_blob_input->challenge_nonce),//msg to sign
            CHALLENGE_NONCE_SIZE,
            &rnd_bsn,
            sizeof(rnd_bsn),
            &parm->signature_header.sigma0, //B and K in BasicSignature
            &temp1,  //B and K in sigrl entry
            &temp3); //output one NrProof
        if(kEpidNoErr != epid_ret){
            if(kEpidSigRevokedInSigRl == epid_ret){
                revoked = true;//if revoked, we could not return revoked status immediately until integrity checking passed
            }else{
                ret = epid_error_to_pve_error(epid_ret);
                goto ret_point;
            }
        }
        //encrypt the NrProof in EPC
        ret = sgx_error_to_pve_error(sgx_aes_gcm128_enc_inplace_update((sgx_aes_state_handle_t*)parm->p_msg3_state, reinterpret_cast<uint8_t *>(&temp3), sizeof(temp3)));
        if(ret != PVEC_SUCCESS){
            goto ret_point;
        }
        pve_memcpy_out(emp_proof_entry, &temp3, sizeof(temp3));//copy encrypted NrProof out of enclave
        emp_sigrl_entry += sizeof(SigRlEntry);//pointer to next SigRlEntry in external memory
        emp_proof_entry += sizeof(NrProof);//pointer to next NrProof in external memory
    }

    se_ae_ecdsa_hash_t out;
    //generate SHA256 hash value of the whole SigRl
    if((sgx_status=sgx_sha256_get_hash(parm->sha_state,
        reinterpret_cast<sgx_sha256_hash_t *>(&out))) !=
        SGX_SUCCESS){
            ret = sgx_error_to_pve_error(sgx_status);
            goto ret_point;
    }
    //Verify the signature is signed by EPIDSK 
    ret = verify_epid_ecdsa_signature(sigrl_sign, parm->local_xegb, &out);
    if(ret == PVEC_MSG_ERROR){
        ret = PVEC_SIGRL_INTEGRITY_CHECK_ERROR;//If sigrl signature checking failed, someone must has modified the message
    }

ret_point:
    //clear unsealed NrProof to defense in depth for potential attack to match attacker created sigrl entry with key 
    //While we need not clear BasicSignature
    (void)memset_s(&temp3, sizeof(temp3), 0, sizeof(temp3));
    if(ret == PVEC_SUCCESS &&revoked){
        ret = PVEC_REVOKED_ERROR;
    }
    return ret;
}
Пример #2
0
/*
 * An internal function used to sign the EPID signature on the quote body.
 * Prefix "emp_" means it is a pointer points memory outside enclave.
 *
 * For quote with SIG-RL
 * |--------------------------------------------------------------------|
 * |sgx_quote_t|wrap_key_t|iv|payload_size|basic_sig|rl_ver|n2|nrp..|mac|
 * |--------------------------------------------------------------------|
 * For quote without SIG-RL
 * |--------------------------------------------------------------|
 * |sgx_quote_t|wrap_key_t|iv|payload_size|basic_sig|rl_ver|n2|mac|
 * |--------------------------------------------------------------|
 *
 * @param p_epid_context[in] Pointer to the EPID context.
 * @param plaintext[in] Reference to the plain text part of EPID blob.
 * @param p_basename[in] The pointer to basename.
 * @param emp_sig_rl_entries[in] The pointer to SIG-RL entries.
 * @param p_sig_rl_header[in] The header of SIG-RL, within EPC.
 * @param p_sig_rl_signature[in] The ecdsa signature of SIG-RL, within EPC.
 * @param p_enclave_report[in] The input isv report.
 * @param p_nonce[in] The input nonce.
 * @param p_qe_report[out] The output buffer for qe_report.
 * @param emp_quote[out] The output buffer for quote.
 * @param p_quote_body[in] The quote body in EPC.
 * @param sign_size[in] size of the signature.
 * @return ae_error_t AE_SUCCESS for success, otherwise for errors.
 */
static ae_error_t qe_epid_sign(
    MemberCtx *p_epid_context,
    const se_plaintext_epid_data_sdk_t& plaintext,
    const sgx_basename_t *p_basename,
    const SigRlEntry *emp_sig_rl_entries,
    se_sig_rl_t *p_sig_rl_header,
    sgx_ec256_signature_t *p_sig_rl_signature,
    const sgx_report_t *p_enclave_report,
    const sgx_quote_nonce_t *p_nonce,
    sgx_report_t *p_qe_report,
    uint8_t *emp_quote,
    const sgx_quote_t *p_quote_body,
    uint32_t sign_size)
{
    ae_error_t ret = AE_SUCCESS;
    sgx_status_t se_ret = SGX_SUCCESS;
    EpidStatus epid_ret = kEpidNoErr;

    se_wrap_key_t wrap_key;
    BasicSignature basic_sig;
    BasicSignature encrypted_basic_sig;
    uint8_t aes_iv[QUOTE_IV_SIZE] = {0};
    uint8_t aes_key[QE_AES_KEY_SIZE] = {0};
    uint8_t aes_tag[SGX_SEAL_TAG_SIZE] = {0};
    sgx_report_data_t qe_report_data = {{0}};
    sgx_target_info_t report_target;
    sgx_ec256_public_t ec_pub_key; // little endian
    se_ae_ecdsa_hash_t sig_rl_hash = {{0}};
    uint8_t ecc_result = SGX_EC_INVALID_SIGNATURE;

    sgx_sha_state_handle_t sha_context = NULL;
    sgx_sha_state_handle_t sha_quote_context = NULL;
    sgx_aes_state_handle_t aes_gcm_state = NULL;
    void *pub_key = NULL;
    size_t pub_key_size = 0;
    uint8_t* pub_key_buffer = NULL;
    sgx_ecc_state_handle_t ecc_handle = NULL;

    memset(&wrap_key, 0, sizeof(wrap_key));
    memset(&basic_sig, 0, sizeof(basic_sig));
    memset(&encrypted_basic_sig, 0, sizeof(encrypted_basic_sig));
    memset(&report_target, 0, sizeof(report_target));
    memset(&ec_pub_key, 0, sizeof(ec_pub_key));

    se_encrypted_sign_t *emp_p = (se_encrypted_sign_t *)
                                (((sgx_quote_t *)emp_quote)->signature);

    uint8_t* emp_nr = NULL;
    uint32_t match = FALSE;

    /* Sign the quote body and get the basic signature*/
    epid_ret = EpidSignBasic(p_epid_context,
               (uint8_t *)const_cast<sgx_quote_t *>(p_quote_body),
               (uint32_t)QE_QUOTE_BODY_SIZE,
               (uint8_t *)const_cast<sgx_basename_t *>(p_basename),
               sizeof(*p_basename),
               &basic_sig,
               NULL); //Random basename, can be NULL if basename is provided
    if(kEpidNoErr != epid_ret)
    {
        ret = QE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }

    /* Prepare the context for SHA256 of quote. */
    if(p_qe_report)
    {
        se_ret = sgx_sha256_init(&sha_quote_context);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }

        // Update hash for nonce.
        se_ret = sgx_sha256_update((uint8_t *)const_cast<sgx_quote_nonce_t *>(p_nonce),
                                   sizeof(*p_nonce),
                                   sha_quote_context);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }
        // Update hash for the first part of quote.
        se_ret = sgx_sha256_update((uint8_t *)const_cast<sgx_quote_t *>(p_quote_body),
                                   sizeof(*p_quote_body),
                                   sha_quote_context);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }
    }

    /* Prepare the context for SHA256 and start calculate the hash of header
     * of SIG-RL. */
    if(emp_sig_rl_entries)
    {
        se_ret = sgx_sha256_init(&sha_context);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }

        /* Calculate the hash of SIG-RL header. */
        se_ret = sgx_sha256_update((uint8_t *)p_sig_rl_header,
                                   (uint32_t)(sizeof(se_sig_rl_t) - sizeof(SigRlEntry)),
                                   sha_context);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }
    }

    // Start encrypt the signature.

    /* Get the random wrap key */
    se_ret = sgx_read_rand(aes_key, sizeof(aes_key));
    if(SGX_SUCCESS != se_ret)
    {
        ret = QE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }

    /* Copy the hash of wrap key into output buffer. */
    se_static_assert(sizeof(wrap_key.key_hash) == sizeof(sgx_sha256_hash_t));
    se_ret = sgx_sha256_msg(aes_key, sizeof(aes_key),
                            (sgx_sha256_hash_t *)wrap_key.key_hash);
    if(SGX_SUCCESS != se_ret)
    {
        ret = QE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }

    /* Start encrypt the wrap key by RSA algorithm. */
    se_ret = sgx_create_rsa_pub1_key(sizeof(g_qsdk_pub_key_n),
                                 sizeof(g_qsdk_pub_key_e),
                                 (const unsigned char *)g_qsdk_pub_key_n,
                                 (const unsigned char *)g_qsdk_pub_key_e,
                                 &pub_key);
    if(se_ret != SGX_SUCCESS)
    {
        ret = QE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }

    /* Get output buffer size */
    se_ret = sgx_rsa_pub_encrypt_sha256(pub_key, NULL, &pub_key_size, aes_key, sizeof(aes_key));
    if(SGX_SUCCESS != se_ret)
    {
        ret = QE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }

    se_ret = sgx_rsa_pub_encrypt_sha256(pub_key, wrap_key.encrypted_key, &pub_key_size, aes_key, sizeof(aes_key));
    if(SGX_SUCCESS != se_ret)
    {
        ret = QE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }

    /* Create the random AES IV. */
    se_ret = sgx_read_rand(aes_iv, sizeof(aes_iv));
    if(SGX_SUCCESS != se_ret)
    {
        ret = QE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }

    /* Copy the wrap_key_t into output buffer. */
    memcpy(&emp_p->wrap_key, &wrap_key, sizeof(wrap_key));
    /* Copy the AES IV into output buffer. */
    memcpy(&emp_p->iv, aes_iv, sizeof(aes_iv));
    /* Copy the AES Blob payload size into output buffer. */
    memcpy(&emp_p->payload_size, &sign_size, sizeof(sign_size));


    se_ret = sgx_aes_gcm128_enc_init(
        aes_key,
        aes_iv, //input initial vector. randomly generated value and encryption of different msg should use different iv
        sizeof(aes_iv),   //length of initial vector, usually IV_SIZE
        NULL,//AAD of AES-GCM, it could be NULL
        0,  //length of bytes of AAD
        &aes_gcm_state);
    if(SGX_SUCCESS != se_ret)
    {
        ret = QE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }
    memset_s(aes_key, sizeof(aes_key), 0, sizeof(aes_key));

    /* Encrypt the basic signature. */
    se_ret = sgx_aes_gcm128_enc_update(
        (uint8_t *)&basic_sig,   //start address to data before/after encryption
        sizeof(basic_sig),
        (uint8_t *)&encrypted_basic_sig, //length of data
        aes_gcm_state); //pointer to a state

    if(SGX_SUCCESS != se_ret)
    {
        ret = QE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }

    /* Copy the encrypted basic signature into output buffer. */
    memcpy(&emp_p->basic_sign, &encrypted_basic_sig,
           sizeof(encrypted_basic_sig));

    if(p_qe_report)
    {
        se_ret = sgx_sha256_update((uint8_t *)&wrap_key,
                                   sizeof(wrap_key),
                                   sha_quote_context);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }
        se_ret = sgx_sha256_update(aes_iv,
                                   sizeof(aes_iv),
                                   sha_quote_context);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }
        se_ret = sgx_sha256_update((uint8_t *)&sign_size,
                                   sizeof(sign_size),
                                   sha_quote_context);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }
        se_ret = sgx_sha256_update((uint8_t *)&encrypted_basic_sig,
                                   sizeof(encrypted_basic_sig),
                                   sha_quote_context);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }
    }

    /* Start process the SIG-RL. */
    if(emp_sig_rl_entries)
    {
        unsigned int entry_count = 0;
        unsigned int i = 0;
        RLver_t encrypted_rl_ver = {{0}};
        RLCount encrypted_n2 = {{0}};
        entry_count = lv_ntohl(p_sig_rl_header->sig_rl.n2);//entry count for big endian to little endian

        // Continue encrypt the output
        se_ret = sgx_aes_gcm128_enc_update(
            (uint8_t *)&(p_sig_rl_header->sig_rl.version),   //start address to data before/after encryption
            sizeof(p_sig_rl_header->sig_rl.version),
            (uint8_t *)&encrypted_rl_ver, //length of data
            aes_gcm_state); //pointer to a state
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }

        se_ret = sgx_aes_gcm128_enc_update(
            (uint8_t *)&(p_sig_rl_header->sig_rl.n2),   //start address to data before/after encryption
            sizeof(p_sig_rl_header->sig_rl.n2),
            (uint8_t *)&encrypted_n2, //length of data
            aes_gcm_state); //pointer to a state
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }

        memcpy(&(emp_p->rl_ver), &encrypted_rl_ver,
               sizeof(encrypted_rl_ver));
        memcpy(&(emp_p->rl_num), &encrypted_n2,
               sizeof(encrypted_n2));
        if(p_qe_report)
        {
            se_ret = sgx_sha256_update((uint8_t *)&encrypted_rl_ver,
                                       sizeof(encrypted_rl_ver),
                                       sha_quote_context);
            if(SGX_SUCCESS != se_ret)
            {
                ret = QE_UNEXPECTED_ERROR;
                goto CLEANUP;
            }
            se_ret = sgx_sha256_update((uint8_t *)&encrypted_n2,
                                       sizeof(encrypted_n2),
                                       sha_quote_context);
            if(SGX_SUCCESS != se_ret)
            {
                ret = QE_UNEXPECTED_ERROR;
                goto CLEANUP;
            }
        }

        /* Start process the SIG-RL entries one by one. */
        emp_nr = emp_p->nrp_mac;
        for (i = 0; i < entry_count; i++, emp_nr += sizeof(NrProof))
        {
            /* Generate non-revoke prove one by one. */
            SigRlEntry entry;
            NrProof temp_nr;
            NrProof encrypted_temp_nr;
            memcpy(&entry, emp_sig_rl_entries + i, sizeof(entry));
            memset_s(&temp_nr, sizeof(temp_nr), 0, sizeof(temp_nr));
            memset_s(&encrypted_temp_nr, sizeof(encrypted_temp_nr), 0, sizeof(encrypted_temp_nr));
            epid_ret = EpidNrProve(p_epid_context,
                (uint8_t *)const_cast<sgx_quote_t *>(p_quote_body),
                (uint32_t)QE_QUOTE_BODY_SIZE,
                (uint8_t *)const_cast<sgx_basename_t *>(p_basename), // basename is required, otherwise it will return kEpidBadArgErr
                sizeof(*p_basename),
                &basic_sig, // Basic signature with 'b' and 'k' in it
                &entry, //Single entry in SigRl composed of 'b' and 'k'
                &temp_nr); // The generated non-revoked proof
            if(kEpidNoErr != epid_ret)
            {
                if(kEpidSigRevokedInSigRl == epid_ret)
                    match = TRUE;
                else
                {
                    ret = QE_UNEXPECTED_ERROR;
                    goto CLEANUP;
                }
            }

            /* Update the hash of SIG-RL */
            se_ret = sgx_sha256_update((uint8_t *)&entry,
                                       sizeof(entry), sha_context);
            if(SGX_SUCCESS != se_ret)
            {
                ret = QE_UNEXPECTED_ERROR;
                goto CLEANUP;
            }

            se_ret = sgx_aes_gcm128_enc_update(
                (uint8_t *)&temp_nr,   //start address to data before/after encryption
                sizeof(encrypted_temp_nr),
                (uint8_t *)&encrypted_temp_nr, //length of data
                aes_gcm_state); //pointer to a state
            if(SGX_SUCCESS != se_ret)
            {
                ret = QE_UNEXPECTED_ERROR;
                goto CLEANUP;
            }

            memcpy(emp_nr, &encrypted_temp_nr, sizeof(encrypted_temp_nr));

            if(p_qe_report)
            {
                se_ret = sgx_sha256_update((uint8_t *)&encrypted_temp_nr,
                                           sizeof(encrypted_temp_nr),
                                           sha_quote_context);
                if(SGX_SUCCESS != se_ret)
                {
                    ret = QE_UNEXPECTED_ERROR;
                    goto CLEANUP;
                }
            }
        }

        /* Get the final hash of the whole SIG-RL. */
        se_ret =  sgx_sha256_get_hash(sha_context,
                                      (sgx_sha256_hash_t *)&sig_rl_hash.hash);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }

        /* Verify the integrity of SIG-RL by check ECDSA signature. */
        se_static_assert(sizeof(ec_pub_key) == sizeof(plaintext.epid_sk));
        // Both plaintext.epid_sk and ec_pub_key are little endian
        memcpy(&ec_pub_key, plaintext.epid_sk, sizeof(ec_pub_key));

        se_ret = sgx_ecc256_open_context(&ecc_handle);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }

        // sgx_ecdsa_verify_hash will take ec_pub_key as little endian
        se_ret = sgx_ecdsa_verify_hash((uint8_t*)&(sig_rl_hash.hash),
                            (const sgx_ec256_public_t *)&ec_pub_key,
                            p_sig_rl_signature,
                            &ecc_result,
                            ecc_handle);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }
        else if(SGX_EC_VALID != ecc_result)
        {
            ret = QE_SIGRL_ERROR;
            goto CLEANUP;
        }
        else if(match)
        {
            ret = QE_REVOKED_ERROR;
            goto CLEANUP;
        }
    }
    else
    {
        se_static_assert(sizeof(emp_p->rl_ver) == sizeof(RLver_t));
        se_static_assert(sizeof(emp_p->rl_num) == sizeof(RLCount));
        uint8_t temp_buf[sizeof(RLver_t) + sizeof(RLCount)] = {0};
        uint8_t encrypted_temp_buf[sizeof(temp_buf)] = {0};

        se_ret = sgx_aes_gcm128_enc_update(
            (uint8_t *)&temp_buf,   //start address to data before/after encryption
            sizeof(encrypted_temp_buf),
            (uint8_t *)&encrypted_temp_buf, //length of data
            aes_gcm_state); //pointer to a state
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }
        /* This will copy both encrypted rl_ver and encrypted rl_num into
           Output buffer. */
        memcpy(&emp_p->rl_ver, &encrypted_temp_buf,
               sizeof(encrypted_temp_buf));

        if(p_qe_report)
        {
            se_ret = sgx_sha256_update((uint8_t *)&encrypted_temp_buf,
                                       sizeof(encrypted_temp_buf),
                                       sha_quote_context);
            if(SGX_SUCCESS != se_ret)
            {
                ret = QE_UNEXPECTED_ERROR;
                goto CLEANUP;
            }
        }
    }

    se_ret = sgx_aes_gcm128_enc_get_mac(aes_tag, aes_gcm_state);
    if(SGX_SUCCESS != se_ret)
    {
        ret = QE_UNEXPECTED_ERROR;
        goto CLEANUP;
    }

    memcpy((uint8_t *)&(emp_p->basic_sign) + sign_size, &aes_tag,
           sizeof(aes_tag));

    if(p_qe_report)
    {
        se_ret = sgx_sha256_update(aes_tag, sizeof(aes_tag),
                                   sha_quote_context);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }
        se_ret =  sgx_sha256_get_hash(sha_quote_context,
                                      (sgx_sha256_hash_t *)&qe_report_data);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_UNEXPECTED_ERROR;
            goto CLEANUP;
        }
        memcpy(&(report_target.attributes),
               &(((const sgx_report_t *)p_enclave_report)->body.attributes),
               sizeof(report_target.attributes));
        memcpy(&(report_target.mr_enclave),
               &(((const sgx_report_t *)p_enclave_report)->body.mr_enclave),
               sizeof(report_target.mr_enclave));
        memcpy(&(report_target.misc_select),
            &(((const sgx_report_t *)p_enclave_report)->body.misc_select),
            sizeof(report_target.misc_select));
        se_ret = sgx_create_report(&report_target, &qe_report_data, p_qe_report);
        if(SGX_SUCCESS != se_ret)
        {
            ret = QE_PARAMETER_ERROR;
            goto CLEANUP;
        }
    }

CLEANUP:
    memset_s(aes_key, sizeof(aes_key), 0, sizeof(aes_key));
    sgx_sha256_close(sha_context);
    sgx_sha256_close(sha_quote_context);
    if (aes_gcm_state)
        sgx_aes_gcm_close(aes_gcm_state);
    if (pub_key)
        sgx_free_rsa_key(pub_key, SGX_RSA_PUBLIC_KEY, sizeof(plaintext.qsdk_mod), sizeof(plaintext.qsdk_exp));
    if (pub_key_buffer)
        free(pub_key_buffer);
    if (ecc_handle)
        sgx_ecc256_close_context(ecc_handle);

    return ret;
}
Пример #3
0
EpidStatus EpidSign(MemberCtx const* ctx, void const* msg, size_t msg_len,
                    void const* basename, size_t basename_len,
                    SigRl const* sig_rl, size_t sig_rl_size, EpidSignature* sig,
                    size_t sig_len) {
  EpidStatus result = kEpidErr;
  uint32_t num_sig_rl = 0;
  OctStr32 octstr32_0 = {{0x00, 0x00, 0x00, 0x00}};
  if (!ctx || !sig) {
    return kEpidBadArgErr;
  }
  if (!ctx->pub_key) {
    return kEpidBadArgErr;
  }
  if (!msg && (0 != msg_len)) {
    // if message is non-empty it must have both length and content
    return kEpidBadArgErr;
  }
  if (!basename && (0 != basename_len)) {
    // if basename is non-empty it must have both length and content
    return kEpidBadArgErr;
  }
  if (sig_rl && (sig_rl_size < sizeof(SigRl) - sizeof(SigRlEntry))) {
    return kEpidBadArgErr;
  }
  if (sig_rl && EpidGetSigSize(sig_rl) > sig_len) {
    return kEpidBadArgErr;
  }

  // 11. The member sets sigma0 = (B, K, T, c, sx, sf, sa, sb).
  result =
      EpidSignBasic(ctx, msg, msg_len, basename, basename_len, &sig->sigma0);
  if (kEpidNoErr != result) {
    return result;
  }

  if (!sig_rl) {
    // 12. If SigRL is not provided as input,
    //   a. The member sets RLver = 0 and n2 = 0.
    //   b. The member outputs (sigma0, RLver, n2) and returns "succeeded".
    sig->rl_ver = octstr32_0;
    sig->n2 = octstr32_0;
    return kEpidNoErr;
  } else {
    uint32_t i = 0;
    EpidStatus nr_prove_status = kEpidNoErr;
    // 13. If SigRL is provided as input, the member proceeds with
    //     the following steps:
    //   a. The member verifies that gid in public key and in SigRL
    //      match.
    if (!IsSigRlValid(&ctx->pub_key->gid, sig_rl, sig_rl_size)) {
      return kEpidBadArgErr;
    }
    //   b. The member copies RLver and n2 values in SigRL to the
    //      signature.
    if (0 != memcpy_S(&sig->rl_ver, sizeof(sig->rl_ver), &sig_rl->version,
                      sizeof(sig_rl->version)))
      return kEpidBadArgErr;
    if (0 !=
        memcpy_S(&sig->n2, sizeof(sig->n2), &sig_rl->n2, sizeof(sig_rl->n2)))
      return kEpidBadArgErr;
    //   c. For i = 0, ..., n2-1, the member computes sigma[i] =
    //      nrProve(f, B, K, B[i], K[i]). The details of nrProve()
    //      will be given in the next subsection.
    num_sig_rl = ntohl(sig_rl->n2);
    for (i = 0; i < num_sig_rl; i++) {
      result = EpidNrProve(ctx, msg, msg_len, &sig->sigma0, &sig_rl->bk[i],
                           &sig->sigma[i]);
      if (kEpidNoErr != result) {
        nr_prove_status = result;
      }
    }
    if (kEpidNoErr != nr_prove_status) {
      memset(&sig->sigma[0], 0, num_sig_rl * sizeof(sig->sigma[0]));
      return nr_prove_status;
    }
  }
  //   d. The member outputs (sigma0, RLver, n2, sigma[0], ...,
  //      sigma[n2-1]).
  //   e. If any of the nrProve() functions outputs "failed", the
  //      member returns "revoked", otherwise returns "succeeded".
  return kEpidNoErr;
}