Ejemplo n.º 1
0
extern "C" IppStatus create_rsa_pub_key(int n_byte_size, int e_byte_size, const Ipp32u *n, const Ipp32u *e, IppsRSAPublicKeyState **new_pub_key)
{
    IppsRSAPublicKeyState *p_pub_key = NULL;
    IppsBigNumState *p_n = NULL, *p_e = NULL;
    int rsa_size = 0;
    if(n_byte_size <= 0 || e_byte_size <= 0 || n == NULL || e == NULL || new_pub_key == NULL)
    {
        return ippStsBadArgErr;
    }

    IppStatus error_code = ippStsNoErr;
    do{
        error_code = newBN(n, n_byte_size, &p_n);
        ERROR_BREAK(error_code);
        error_code = newBN(e, e_byte_size, &p_e);
        ERROR_BREAK(error_code);

        error_code = ippsRSA_GetSizePublicKey(n_byte_size * 8, e_byte_size * 8, &rsa_size);
        ERROR_BREAK(error_code);
        p_pub_key = (IppsRSAPublicKeyState *)malloc(rsa_size);
        NULL_BREAK(p_pub_key);
        error_code = ippsRSA_InitPublicKey(n_byte_size * 8, e_byte_size * 8, p_pub_key, rsa_size);
        ERROR_BREAK(error_code);
        error_code = ippsRSA_SetPublicKey(p_n, p_e, p_pub_key);
        ERROR_BREAK(error_code);
    }while(0);
    secure_free_BN(p_n, n_byte_size);
    secure_free_BN(p_e, e_byte_size);
    if(error_code != ippStsNoErr || p_pub_key == NULL)
    {
        if(error_code == ippStsNoErr )
            error_code = ippStsMemAllocErr;

        secure_free_rsa_pub_key(n_byte_size, e_byte_size, p_pub_key);
        return error_code;
    }

    *new_pub_key = p_pub_key;
    return error_code;

}
Ejemplo n.º 2
0
/* the caller is supposed to fill the quote field in emp_msg3 before calling
 * this function.*/
extern "C" sgx_status_t sgx_ra_get_msg3_trusted(
    sgx_ra_context_t context,
    uint32_t quote_size,
    sgx_report_t* qe_report,
    sgx_ra_msg3_t *emp_msg3,    //(mac||g_a||ps_sec_prop||quote)
    uint32_t msg3_size)
{
    if(vector_size(&g_ra_db) <= context ||!quote_size || !qe_report || !emp_msg3)
        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;

    //check integer overflow of msg3_size and quote_size
    if (UINTPTR_MAX - reinterpret_cast<uintptr_t>(emp_msg3) < msg3_size ||
        UINT32_MAX - quote_size < sizeof(sgx_ra_msg3_t) ||
        sizeof(sgx_ra_msg3_t) + quote_size != msg3_size)
        return SGX_ERROR_INVALID_PARAMETER;

    if (!sgx_is_outside_enclave(emp_msg3, msg3_size))
        return SGX_ERROR_INVALID_PARAMETER;
    //
    // fence after boundary check 
    // this also stops speculation in case of 
    // branch associated 
    // with sizeof(sgx_ra_msg3_t) + quote_size != msg3_size
    // mispredicting
    //
    sgx_lfence();

    sgx_status_t se_ret = SGX_ERROR_UNEXPECTED;

    //verify qe report
    se_ret = sgx_verify_report(qe_report);
    if(se_ret != SGX_SUCCESS)
    {
        if (SGX_ERROR_MAC_MISMATCH != se_ret &&
            SGX_ERROR_OUT_OF_MEMORY != se_ret)
            se_ret = SGX_ERROR_UNEXPECTED;
        return se_ret;
    }

    sgx_spin_lock(&item->item_lock);
    //sgx_ra_proc_msg2_trusted must have been called
    if (item->state != ra_proc_msg2ed)
    {
        sgx_spin_unlock(&item->item_lock);
        return SGX_ERROR_INVALID_STATE;
    }
    //verify qe_report attributes and mr_enclave same as quoting enclave
    if( memcmp( &qe_report->body.attributes, &item->qe_target.attributes, sizeof(sgx_attributes_t)) ||
        memcmp( &qe_report->body.mr_enclave, &item->qe_target.mr_enclave, sizeof(sgx_measurement_t)) )
    {
        sgx_spin_unlock(&item->item_lock);
        return SGX_ERROR_INVALID_PARAMETER;
    }

    sgx_ra_msg3_t msg3_except_quote_in;
    sgx_cmac_128bit_key_t smk_key;
    memcpy(&msg3_except_quote_in.g_a, &item->g_a, sizeof(msg3_except_quote_in.g_a));
    memcpy(&msg3_except_quote_in.ps_sec_prop, &item->ps_sec_prop,
        sizeof(msg3_except_quote_in.ps_sec_prop));
    memcpy(&smk_key, &item->smk_key, sizeof(smk_key));
    sgx_spin_unlock(&item->item_lock);

    sgx_sha_state_handle_t sha_handle = NULL;
    sgx_cmac_state_handle_t cmac_handle = NULL;


    //SHA256(NONCE || emp_quote)
    sgx_sha256_hash_t hash = {0};
    se_ret = sgx_sha256_init(&sha_handle);
    if (SGX_SUCCESS != se_ret)
    {
        if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
            se_ret = SGX_ERROR_UNEXPECTED;
        return se_ret;
    }
    if (NULL == sha_handle)
        {
            return SGX_ERROR_UNEXPECTED;
        }
    do
    {
        se_ret = sgx_sha256_update((uint8_t *)&item->quote_nonce,
            sizeof(item->quote_nonce),
            sha_handle);
        if (SGX_SUCCESS != se_ret)
        {
            if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                se_ret = SGX_ERROR_UNEXPECTED;
            break;
        }

         //cmac   M := ga || PS_SEC_PROP_DESC(all zero if unused) ||emp_quote
        sgx_cmac_128bit_tag_t mac;
        se_ret = sgx_cmac128_init(&smk_key, &cmac_handle);
        if (SGX_SUCCESS != se_ret)
        {
            if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                se_ret = SGX_ERROR_UNEXPECTED;
            break;
        }
        if (NULL == cmac_handle)
        {
            se_ret = SGX_ERROR_UNEXPECTED;
            break;
        }
        se_ret = sgx_cmac128_update((uint8_t*)&msg3_except_quote_in.g_a,
            sizeof(msg3_except_quote_in.g_a), cmac_handle);
        if (SGX_SUCCESS != se_ret)
        {
            if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                se_ret = SGX_ERROR_UNEXPECTED;
            break;
        }
        se_ret = sgx_cmac128_update((uint8_t*)&msg3_except_quote_in.ps_sec_prop,
            sizeof(msg3_except_quote_in.ps_sec_prop), cmac_handle);
        if (SGX_SUCCESS != se_ret)
        {
            if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                se_ret = SGX_ERROR_UNEXPECTED;
            break;
        }

        // sha256 and cmac quote
        uint8_t quote_piece[32];
        const uint8_t* emp_quote_piecemeal = emp_msg3->quote;
        uint32_t quote_piece_size = static_cast<uint32_t>(sizeof(quote_piece));

        while (emp_quote_piecemeal < emp_msg3->quote + quote_size)
        {
            //calculate size of one piece, the size of them are sizeof(quote_piece) except for the last one.
            if (static_cast<uint32_t>(emp_msg3->quote + quote_size - emp_quote_piecemeal) < quote_piece_size)
                quote_piece_size = static_cast<uint32_t>(emp_msg3->quote - emp_quote_piecemeal) + quote_size ;
            memcpy(quote_piece, emp_quote_piecemeal, quote_piece_size);
            se_ret = sgx_sha256_update(quote_piece,
                                    quote_piece_size,
                                    sha_handle);
           if (SGX_SUCCESS != se_ret)
           {
               if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                   se_ret = SGX_ERROR_UNEXPECTED;
              break;
           }
           se_ret = sgx_cmac128_update(quote_piece,
                                    quote_piece_size,
                                    cmac_handle);
           if (SGX_SUCCESS != se_ret)
          {
              if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                  se_ret = SGX_ERROR_UNEXPECTED;
              break;
          }
           emp_quote_piecemeal += sizeof(quote_piece);
        }
        ERROR_BREAK(se_ret);

        //get sha256 hash value
        se_ret = sgx_sha256_get_hash(sha_handle, &hash);
        if (SGX_SUCCESS != se_ret)
        {
            if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                se_ret = SGX_ERROR_UNEXPECTED;
            break;
        }

        //get cmac value
        se_ret = sgx_cmac128_final(cmac_handle, &mac);
        if (SGX_SUCCESS != se_ret)
        {
            if(SGX_ERROR_OUT_OF_MEMORY != se_ret)
                se_ret = SGX_ERROR_UNEXPECTED;
            break;
        }

        //verify qe_report->body.report_data == SHA256(NONCE || emp_quote)
        if(0 != memcmp(&qe_report->body.report_data, &hash, sizeof(hash)))
        {
            se_ret = SGX_ERROR_MAC_MISMATCH;
            break;
        }

        memcpy(&msg3_except_quote_in.mac, mac, sizeof(mac));
        memcpy(emp_msg3, &msg3_except_quote_in, offsetof(sgx_ra_msg3_t, quote));
        se_ret = SGX_SUCCESS;
    }while(0);
    memset_s(&smk_key, sizeof(smk_key), 0, sizeof(smk_key));
    (void)sgx_sha256_close(sha_handle);
    if(cmac_handle != NULL)
        sgx_cmac128_close(cmac_handle);
    return se_ret;
}
Ejemplo n.º 3
0
/* Computes DH shared key based on private B key (local) and remote public Ga Key
* Parameters:
*   Return: sgx_status_t - SGX_SUCCESS or failure as defined sgx_error.h
*   Inputs: sgx_ecc_state_handle_t ecc_handle - Handle to ECC crypto system
*           sgx_ec256_private_t *p_private_b - Pointer to the local private key - LITTLE ENDIAN
*           sgx_ec256_public_t *p_public_ga - Pointer to the remote public key - LITTLE ENDIAN
*   Output: sgx_ec256_dh_shared_t *p_shared_key - Pointer to the shared DH key - LITTLE ENDIAN
x-coordinate of (privKeyB - pubKeyA) */
sgx_status_t sgx_ecc256_compute_shared_dhkey(sgx_ec256_private_t *p_private_b,
                                             sgx_ec256_public_t *p_public_ga,
                                             sgx_ec256_dh_shared_t *p_shared_key,
                                             sgx_ecc_state_handle_t ecc_handle)
{
    if ((ecc_handle == NULL) || (p_private_b == NULL) || (p_public_ga == NULL) || (p_shared_key == NULL))
    {
        return SGX_ERROR_INVALID_PARAMETER;
    }

    IppsBigNumState*    BN_dh_privB = NULL;
    IppsBigNumState*    BN_dh_share = NULL;
    IppsBigNumState*    pubA_gx = NULL;
    IppsBigNumState*    pubA_gy = NULL;
    IppsECCPPointState* point_pubA = NULL;
    IppStatus           ipp_ret = ippStsNoErr;
    int                 ecPointSize = 0;
    IppsECCPState* p_ecc_state = (IppsECCPState*)ecc_handle;
    IppECResult ipp_result = ippECValid;

    do
    {
        ipp_ret = sgx_ipp_newBN((Ipp32u*)p_private_b->r, sizeof(sgx_ec256_private_t), &BN_dh_privB);
        ERROR_BREAK(ipp_ret);
        ipp_ret = sgx_ipp_newBN((uint32_t*)p_public_ga->gx, sizeof(p_public_ga->gx), &pubA_gx);
        ERROR_BREAK(ipp_ret);
        ipp_ret = sgx_ipp_newBN((uint32_t*)p_public_ga->gy, sizeof(p_public_ga->gy), &pubA_gy);
        ERROR_BREAK(ipp_ret);
        ipp_ret = ippsECCPPointGetSize(256, &ecPointSize);
        ERROR_BREAK(ipp_ret);
        point_pubA = (IppsECCPPointState*)(malloc(ecPointSize));
        if (!point_pubA)
        {
            ipp_ret = ippStsNoMemErr;
            break;
        }
        ipp_ret = ippsECCPPointInit(256, point_pubA);
        ERROR_BREAK(ipp_ret);
        ipp_ret = ippsECCPSetPoint(pubA_gx, pubA_gy, point_pubA, p_ecc_state);
        ERROR_BREAK(ipp_ret);

        // Check to see if the point is a valid point on the Elliptic curve and is not infinity
        ipp_ret = ippsECCPCheckPoint(point_pubA, &ipp_result, p_ecc_state);
        if (ipp_result != ippECValid)
        {
            break;
        }
        ERROR_BREAK(ipp_ret);

        ipp_ret = sgx_ipp_newBN(NULL, sizeof(sgx_ec256_dh_shared_t), &BN_dh_share);
        ERROR_BREAK(ipp_ret);
        /* This API generates shareA = x-coordinate of (privKeyB*pubKeyA) */
        ipp_ret = ippsECCPSharedSecretDH(BN_dh_privB, point_pubA, BN_dh_share, p_ecc_state);
        ERROR_BREAK(ipp_ret);
        IppsBigNumSGN sgn = IppsBigNumPOS;
        int length = 0;
        Ipp32u * pdata = NULL;
        ipp_ret = ippsRef_BN(&sgn, &length, &pdata, BN_dh_share);
        ERROR_BREAK(ipp_ret);
        memset(p_shared_key->s, 0, sizeof(p_shared_key->s));
        ipp_ret = check_copy_size(sizeof(p_shared_key->s), ROUND_TO(length, 8) / 8);
        ERROR_BREAK(ipp_ret);
        memcpy(p_shared_key->s, pdata, ROUND_TO(length, 8) / 8);
    } while (0);

    // Clear temp buffer before free.
    if (point_pubA) memset_s(point_pubA, ecPointSize, 0, ecPointSize);
    SAFE_FREE(point_pubA);
    sgx_ipp_secure_free_BN(pubA_gx, sizeof(p_public_ga->gx));
    sgx_ipp_secure_free_BN(pubA_gy, sizeof(p_public_ga->gy));
    sgx_ipp_secure_free_BN(BN_dh_privB, sizeof(sgx_ec256_private_t));
    sgx_ipp_secure_free_BN(BN_dh_share, sizeof(sgx_ec256_dh_shared_t));


    if (ipp_result != ippECValid)
    {
        return SGX_ERROR_INVALID_PARAMETER;
    }
    switch (ipp_ret)
    {
    case ippStsNoErr: return SGX_SUCCESS;
    case ippStsNoMemErr:
    case ippStsMemAllocErr: return SGX_ERROR_OUT_OF_MEMORY;
    case ippStsNullPtrErr:
    case ippStsLengthErr:
    case ippStsOutOfRangeErr:
    case ippStsSizeErr:
    case ippStsBadArgErr: return SGX_ERROR_INVALID_PARAMETER;
    default: return SGX_ERROR_UNEXPECTED;
    }
}
Ejemplo n.º 4
0
/* Checks whether the input point is a valid point on the given elliptic curve
* Parameters:
*   Return: sgx_status_t - SGX_SUCCESS or failure as defined sgx_error.h
*   Inputs: sgx_ecc_state_handle_t ecc_handle - Handle to ECC crypto system
*           sgx_ec256_public_t *p_point - Pointer to perform validity check on - LITTLE ENDIAN
*   Output: int *p_valid - Return 0 if the point is an invalid point on ECC curve */
sgx_status_t sgx_ecc256_check_point(const sgx_ec256_public_t *p_point,
                                    const sgx_ecc_state_handle_t ecc_handle,
                                    int *p_valid)
{
    if ((ecc_handle == NULL) || (p_point == NULL) || (p_valid == NULL))
    {
        return SGX_ERROR_INVALID_PARAMETER;
    }

    IppsECCPPointState* point2check = NULL;
    IppStatus           ipp_ret = ippStsNoErr;
    IppsECCPState* p_ecc_state = (IppsECCPState*)ecc_handle;
    IppECResult ipp_result = ippECValid;
    int                 ecPointSize = 0;
    IppsBigNumState*    BN_gx = NULL;
    IppsBigNumState*    BN_gy = NULL;

    // Intialize return to false
    *p_valid = 0;

    do
    {
        ipp_ret = ippsECCPPointGetSize(256, &ecPointSize);
        ERROR_BREAK(ipp_ret);
        point2check = (IppsECCPPointState*)malloc(ecPointSize);
        if (!point2check)
        {
            ipp_ret = ippStsNoMemErr;
            break;
        }
        ipp_ret = ippsECCPPointInit(256, point2check);
        ERROR_BREAK(ipp_ret);

        ipp_ret = sgx_ipp_newBN((const Ipp32u *)p_point->gx, sizeof(p_point->gx), &BN_gx);
        ERROR_BREAK(ipp_ret);
        ipp_ret = sgx_ipp_newBN((const Ipp32u *)p_point->gy, sizeof(p_point->gy), &BN_gy);
        ERROR_BREAK(ipp_ret);

        ipp_ret = ippsECCPSetPoint(BN_gx, BN_gy, point2check, p_ecc_state);
        ERROR_BREAK(ipp_ret);

        // Check to see if the point is a valid point on the Elliptic curve and is not infinity
        ipp_ret = ippsECCPCheckPoint(point2check, &ipp_result, p_ecc_state);
        ERROR_BREAK(ipp_ret);
        if (ipp_result == ippECValid)
        {
            *p_valid = 1;
        }
    } while (0);

    // Clear temp buffer before free.
    if (point2check)
        memset_s(point2check, ecPointSize, 0, ecPointSize);
    SAFE_FREE(point2check);

    sgx_ipp_secure_free_BN(BN_gx, sizeof(p_point->gx));
    sgx_ipp_secure_free_BN(BN_gy, sizeof(p_point->gy));

    switch (ipp_ret)
    {
    case ippStsNoErr: return SGX_SUCCESS;
    case ippStsNoMemErr:
    case ippStsMemAllocErr: return SGX_ERROR_OUT_OF_MEMORY;
    case ippStsNullPtrErr:
    case ippStsLengthErr:
    case ippStsOutOfRangeErr:
    case ippStsSizeErr:
    case ippStsBadArgErr: return SGX_ERROR_INVALID_PARAMETER;
    default: return SGX_ERROR_UNEXPECTED;
    }
}
Ejemplo n.º 5
0
/* Populates private/public key pair - caller code allocates memory
* Parameters:
*   Return: sgx_status_t  - SGX_SUCCESS or failure as defined sgx_error.h
*   Inputs: sgx_ecc_state_handle_t ecc_handle - Handle to ECC crypto system
*   Outputs: sgx_ec256_private_t *p_private - Pointer to the private key
*            sgx_ec256_public_t *p_public - Pointer to the public key  */
sgx_status_t sgx_ecc256_create_key_pair(sgx_ec256_private_t *p_private,
    sgx_ec256_public_t *p_public,
    sgx_ecc_state_handle_t ecc_handle)
{
    if ((ecc_handle == NULL) || (p_private == NULL) || (p_public == NULL))
    {
        return SGX_ERROR_INVALID_PARAMETER;
    }

    IppsBigNumState*    dh_priv_BN = NULL;
    IppsECCPPointState* point_pub = NULL;
    IppsBigNumState*    pub_gx = NULL;
    IppsBigNumState*    pub_gy = NULL;
    IppStatus           ipp_ret = ippStsNoErr;
    int                 ecPointSize = 0;
    IppsECCPState* p_ecc_state = (IppsECCPState*)ecc_handle;

    do
    {
        //init eccp point
        ipp_ret = ippsECCPPointGetSize(256, &ecPointSize);
        ERROR_BREAK(ipp_ret);
        point_pub = (IppsECCPPointState*)(malloc(ecPointSize));
        if (!point_pub)
        {
            ipp_ret = ippStsNoMemErr;
            break;
        }
        ipp_ret = ippsECCPPointInit(256, point_pub);
        ERROR_BREAK(ipp_ret);

        ipp_ret = sgx_ipp_newBN(NULL, SGX_ECP256_KEY_SIZE, &dh_priv_BN);
        ERROR_BREAK(ipp_ret);
        // Use the true random number (DRNG)
        // Notice that IPP ensures the private key generated is non-zero
        ipp_ret = ippsECCPGenKeyPair(dh_priv_BN, point_pub, p_ecc_state, (IppBitSupplier)sgx_ipp_DRNGen, NULL);
        ERROR_BREAK(ipp_ret);

        //convert point_result to oct string
        ipp_ret = sgx_ipp_newBN(NULL, SGX_ECP256_KEY_SIZE, &pub_gx);
        ERROR_BREAK(ipp_ret);
        ipp_ret = sgx_ipp_newBN(NULL, SGX_ECP256_KEY_SIZE, &pub_gy);
        ERROR_BREAK(ipp_ret);
        ipp_ret = ippsECCPGetPoint(pub_gx, pub_gy, point_pub, p_ecc_state);
        ERROR_BREAK(ipp_ret);

        IppsBigNumSGN sgn = IppsBigNumPOS;
        Ipp32u *pdata = NULL;
        // ippsRef_BN is in bits not bytes (versus old ippsGet_BN)
        int length = 0;
        ipp_ret = ippsRef_BN(&sgn, &length, &pdata, pub_gx);
        ERROR_BREAK(ipp_ret);
        memset(p_public->gx, 0, sizeof(p_public->gx));
        ipp_ret = check_copy_size(sizeof(p_public->gx), ROUND_TO(length, 8) / 8);
        ERROR_BREAK(ipp_ret);
        memcpy(p_public->gx, pdata, ROUND_TO(length, 8) / 8);
        ipp_ret = ippsRef_BN(&sgn, &length, &pdata, pub_gy);
        ERROR_BREAK(ipp_ret);
        memset(p_public->gy, 0, sizeof(p_public->gy));
        ipp_ret = check_copy_size(sizeof(p_public->gy), ROUND_TO(length, 8) / 8);
        ERROR_BREAK(ipp_ret);
        memcpy(p_public->gy, pdata, ROUND_TO(length, 8) / 8);
        ipp_ret = ippsRef_BN(&sgn, &length, &pdata, dh_priv_BN);
        ERROR_BREAK(ipp_ret);
        memset(p_private->r, 0, sizeof(p_private->r));
        ipp_ret = check_copy_size(sizeof(p_private->r), ROUND_TO(length, 8) / 8);
        ERROR_BREAK(ipp_ret);
        memcpy(p_private->r, pdata, ROUND_TO(length, 8) / 8);
    } while (0);

    //Clear temp buffer before free.
    if (point_pub) memset_s(point_pub, ecPointSize, 0, ecPointSize);
    SAFE_FREE(point_pub);
    sgx_ipp_secure_free_BN(pub_gx, SGX_ECP256_KEY_SIZE);
    sgx_ipp_secure_free_BN(pub_gy, SGX_ECP256_KEY_SIZE);
    sgx_ipp_secure_free_BN(dh_priv_BN, SGX_ECP256_KEY_SIZE);

    switch (ipp_ret)
    {
    case ippStsNoErr: return SGX_SUCCESS;
    case ippStsNoMemErr:
    case ippStsMemAllocErr: return SGX_ERROR_OUT_OF_MEMORY;
    case ippStsNullPtrErr:
    case ippStsLengthErr:
    case ippStsOutOfRangeErr:
    case ippStsSizeErr:
    case ippStsBadArgErr: return SGX_ERROR_INVALID_PARAMETER;
    default: return SGX_ERROR_UNEXPECTED;
    }
}
Ejemplo n.º 6
0
/* Computes signature for data based on private key
* Parameters:
*   Return: sample_status_t - SAMPLE_SUCCESS, SAMPLE_SUCCESS on success, error code otherwise.
*   Inputs: sample_ecc_state_handle_t ecc_handle - Handle to ECC crypto system
*           sample_ec256_private_t *p_private - Pointer to the private key - LITTLE ENDIAN
*           sample_uint8_t *p_data - Pointer to the data to be signed
*           uint32_t data_size - Size of the data to be signed
*   Output: sample_ec256_signature_t *p_signature - Pointer to the signature - LITTLE ENDIAN  */
sample_status_t sample_ecdsa_sign(const uint8_t *p_data,
                            uint32_t data_size,
                            sample_ec256_private_t *p_private,
                            sample_ec256_signature_t *p_signature,
                            sample_ecc_state_handle_t ecc_handle)
{
    if ((ecc_handle == NULL) || (p_private == NULL) || (p_signature == NULL) || (p_data == NULL) || (data_size < 1))
    {
        return SAMPLE_ERROR_INVALID_PARAMETER;
    }

    IppStatus ipp_ret = ippStsNoErr;
    IppsECCPState* p_ecc_state = (IppsECCPState*)ecc_handle;
    IppsBigNumState* p_ecp_order = NULL;
    IppsBigNumState* p_hash_bn = NULL;
    IppsBigNumState* p_msg_bn = NULL;
    IppsBigNumState* p_eph_priv_bn = NULL;
    IppsECCPPointState* p_eph_pub = NULL;
    IppsBigNumState* p_reg_priv_bn = NULL;
    IppsBigNumState* p_signx_bn = NULL;
    IppsBigNumState* p_signy_bn = NULL;
    Ipp32u *p_sigx = NULL;
    Ipp32u *p_sigy = NULL;
    int ecp_size = 0;
    const int order_size = sizeof(sample_nistp256_r);
    uint32_t hash[8] = {0};

    do
    {

        ipp_ret = sgx_ipp_newBN(sample_nistp256_r, order_size, &p_ecp_order);
        ERROR_BREAK(ipp_ret);

        // Prepare the message used to sign.
        ipp_ret = ippsHashMessage(p_data, data_size, (Ipp8u*)hash, IPP_ALG_HASH_SHA256);
        ERROR_BREAK(ipp_ret);
        /* Byte swap in creation of Big Number from SHA256 hash output */
        ipp_ret = sgx_ipp_newBN(NULL, sizeof(hash), &p_hash_bn);
        ERROR_BREAK(ipp_ret);
        ipp_ret = ippsSetOctString_BN((Ipp8u*)hash, sizeof(hash), p_hash_bn);
        ERROR_BREAK(ipp_ret);

        ipp_ret = sgx_ipp_newBN(NULL, order_size, &p_msg_bn);
        ERROR_BREAK(ipp_ret);
        ipp_ret = ippsMod_BN(p_hash_bn, p_ecp_order, p_msg_bn);
        ERROR_BREAK(ipp_ret);

        // Get ephemeral key pair.
        ipp_ret = sgx_ipp_newBN(NULL, order_size, &p_eph_priv_bn);
        ERROR_BREAK(ipp_ret);
        //init eccp point
        ipp_ret = ippsECCPPointGetSize(256, &ecp_size);
        ERROR_BREAK(ipp_ret);
        p_eph_pub = (IppsECCPPointState*)(malloc(ecp_size));
        if(!p_eph_pub)
        {
            ipp_ret = ippStsNoMemErr;
            break;
        }
        ipp_ret = ippsECCPPointInit(256, p_eph_pub);
        ERROR_BREAK(ipp_ret);
        // generate ephemeral key pair for signing operation
        ipp_ret = ippsECCPGenKeyPair(p_eph_priv_bn, p_eph_pub, p_ecc_state,
            (IppBitSupplier)sample_ipp_DRNGen, NULL);
        ERROR_BREAK(ipp_ret);
        ipp_ret = ippsECCPSetKeyPair(p_eph_priv_bn, p_eph_pub, ippFalse, p_ecc_state);
        ERROR_BREAK(ipp_ret);

        // Set the regular private key.
        ipp_ret = sgx_ipp_newBN((uint32_t *)p_private->r, sizeof(p_private->r),
            &p_reg_priv_bn);
        ERROR_BREAK(ipp_ret);
        ipp_ret = sgx_ipp_newBN(NULL, order_size, &p_signx_bn);
        ERROR_BREAK(ipp_ret);
        ipp_ret = sgx_ipp_newBN(NULL, order_size, &p_signy_bn);
        ERROR_BREAK(ipp_ret);

        // Sign the message.
        ipp_ret = ippsECCPSignDSA(p_msg_bn, p_reg_priv_bn, p_signx_bn, p_signy_bn,
            p_ecc_state);
        ERROR_BREAK(ipp_ret);

        IppsBigNumSGN sign;
        int length;
        ipp_ret = ippsRef_BN(&sign, &length,(Ipp32u**) &p_sigx, p_signx_bn);
        ERROR_BREAK(ipp_ret);
        memset(p_signature->x, 0, sizeof(p_signature->x));
        ipp_ret = check_copy_size(sizeof(p_signature->x), ROUND_TO(length, 8)/8);
        ERROR_BREAK(ipp_ret);
        memcpy(p_signature->x, p_sigx, ROUND_TO(length, 8)/8);
        memset_s(p_sigx, sizeof(p_signature->x), 0, ROUND_TO(length, 8)/8);
        ipp_ret = ippsRef_BN(&sign, &length,(Ipp32u**) &p_sigy, p_signy_bn);
        ERROR_BREAK(ipp_ret);
        memset(p_signature->y, 0, sizeof(p_signature->y));
        ipp_ret = check_copy_size(sizeof(p_signature->y), ROUND_TO(length, 8)/8);
        ERROR_BREAK(ipp_ret);
        memcpy(p_signature->y, p_sigy, ROUND_TO(length, 8)/8);
        memset_s(p_sigy, sizeof(p_signature->y), 0, ROUND_TO(length, 8)/8);        

    }while(0);

    // Clear buffer before free.
    if(p_eph_pub)
        memset_s(p_eph_pub, ecp_size, 0, ecp_size);
    SAFE_FREE(p_eph_pub);
    sample_ipp_secure_free_BN(p_ecp_order, order_size);
    sample_ipp_secure_free_BN(p_hash_bn, sizeof(hash));
    sample_ipp_secure_free_BN(p_msg_bn, order_size);
    sample_ipp_secure_free_BN(p_eph_priv_bn, order_size);
    sample_ipp_secure_free_BN(p_reg_priv_bn, sizeof(p_private->r));
    sample_ipp_secure_free_BN(p_signx_bn, order_size);
    sample_ipp_secure_free_BN(p_signy_bn, order_size);

    switch (ipp_ret)
    {
    case ippStsNoErr: return SAMPLE_SUCCESS;
    case ippStsNoMemErr:
    case ippStsMemAllocErr: return SAMPLE_ERROR_OUT_OF_MEMORY;
    case ippStsNullPtrErr:
    case ippStsLengthErr:
    case ippStsOutOfRangeErr:
    case ippStsSizeErr:
    case ippStsBadArgErr: return SAMPLE_ERROR_INVALID_PARAMETER;
    default: return SAMPLE_ERROR_UNEXPECTED;
    }
}