예제 #1
0
EpidStatus EcdsaSignBuffer(void const* buf, size_t buf_len,
                           EcdsaPrivateKey const* privkey, BitSupplier rnd_func,
                           void* rnd_param, EcdsaSignature* sig) {
  EpidStatus result = kEpidMathErr;

  IppsECCPState* ec_ctx = NULL;
  BigNum* bn_ec_order = NULL;

  BigNum* bn_hash = NULL;

  BigNum* bn_reg_private = NULL;
  BigNum* bn_eph_private = NULL;
  IppsECCPPointState* ecp_eph_public = NULL;

  BigNum* bn_sig_x = NULL;
  BigNum* bn_sig_y = NULL;

  do {
    EpidStatus epid_status = kEpidNoErr;
    IppStatus sts = ippStsNoErr;
    int ctxsize = 0;
    // order of EC secp256r1
    const uint8_t secp256r1_r[32] = {
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17,
        0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51};
    Ipp8u hash[IPP_SHA256_DIGEST_BITSIZE / 8] = {0};
    unsigned int gen_loop_count = EPHKEYGEN_WATCHDOG;
    Ipp32u cmp0 = IS_ZERO;
    Ipp32u cmp_order = IS_ZERO;

    if ((0 != buf_len && !buf) || !privkey || !rnd_func || !sig) {
      result = kEpidBadArgErr;
      break;
    }
    if (buf_len > INT_MAX) {
      result = kEpidBadArgErr;
      break;
    }

    // Define standard elliptic curve secp256r1
    sts = ippsECCPGetSizeStd256r1(&ctxsize);
    if (ippStsNoErr != sts) break;
    ec_ctx = (IppsECCPState*)SAFE_ALLOC(ctxsize);
    if (!ec_ctx) {
      result = kEpidMemAllocErr;
      break;
    }
    sts = ippsECCPInitStd256r1(ec_ctx);
    if (ippStsNoErr != sts) break;
    sts = ippsECCPSetStd256r1(ec_ctx);
    if (ippStsNoErr != sts) break;

    // Create big number for order of elliptic curve secp256r1
    epid_status = NewBigNum(sizeof(secp256r1_r), &bn_ec_order);
    if (kEpidMemAllocErr == epid_status) {
      result = kEpidMemAllocErr;
      break;
    }
    if (kEpidNoErr != epid_status) break;
    epid_status = ReadBigNum(secp256r1_r, sizeof(secp256r1_r), bn_ec_order);
    if (kEpidNoErr != epid_status) break;

    // Calculate hash for input message
    sts = ippsSHA256MessageDigest(buf, (int)buf_len, hash);
    if (ippStsNoErr != sts) break;

    // Create big number for hash
    epid_status = NewBigNum(sizeof(hash), &bn_hash);
    if (kEpidMemAllocErr == epid_status) {
      result = kEpidMemAllocErr;
      break;
    }
    if (kEpidNoErr != epid_status) break;
    epid_status = ReadBigNum(hash, sizeof(hash), bn_hash);
    if (kEpidNoErr != epid_status) break;
    sts = ippsMod_BN(bn_hash->ipp_bn, bn_ec_order->ipp_bn, bn_hash->ipp_bn);
    if (ippStsNoErr != sts) break;

    // Create big number for regular private key
    epid_status = NewBigNum(sizeof(*privkey), &bn_reg_private);
    if (kEpidMemAllocErr == epid_status) {
      result = kEpidMemAllocErr;
      break;
    }
    if (kEpidNoErr != epid_status) break;
    epid_status = ReadBigNum(privkey, sizeof(*privkey), bn_reg_private);
    if (kEpidNoErr != epid_status) break;

    // Validate private key is in range [1, bn_ec_order-1]
    sts = ippsCmpZero_BN(bn_reg_private->ipp_bn, &cmp0);
    if (ippStsNoErr != sts) break;
    sts = ippsCmp_BN(bn_reg_private->ipp_bn, bn_ec_order->ipp_bn, &cmp_order);
    if (ippStsNoErr != sts) break;
    if (IS_ZERO == cmp0 || LESS_THAN_ZERO != cmp_order) {
      result = kEpidBadArgErr;
      break;
    }

    // Create big number for ephemeral private key
    epid_status = NewBigNum(sizeof(secp256r1_r), &bn_eph_private);
    if (kEpidMemAllocErr == epid_status) {
      result = kEpidMemAllocErr;
      break;
    }
    if (kEpidNoErr != epid_status) break;

    // Create EC point for ephemeral public key
    sts = ippsECCPPointGetSize(256, &ctxsize);
    if (ippStsNoErr != sts) break;
    ecp_eph_public = (IppsECCPPointState*)SAFE_ALLOC(ctxsize);
    if (!ecp_eph_public) {
      result = kEpidMemAllocErr;
      break;
    }
    sts = ippsECCPPointInit(256, ecp_eph_public);
    if (ippStsNoErr != sts) break;

    // Create big numbers for signature
    epid_status = NewBigNum(sizeof(secp256r1_r), &bn_sig_x);
    if (kEpidMemAllocErr == epid_status) {
      result = kEpidMemAllocErr;
      break;
    }
    if (kEpidNoErr != epid_status) break;
    epid_status = NewBigNum(sizeof(secp256r1_r), &bn_sig_y);
    if (kEpidMemAllocErr == epid_status) {
      result = kEpidMemAllocErr;
      break;
    }
    if (kEpidNoErr != epid_status) break;

    do {
      // Generate ephemeral key pair
      sts = ippsECCPGenKeyPair(bn_eph_private->ipp_bn, ecp_eph_public, ec_ctx,
                               (IppBitSupplier)rnd_func, rnd_param);
      if (ippStsNoErr != sts) break;

      // Set ephemeral key pair
      sts = ippsECCPSetKeyPair(bn_eph_private->ipp_bn, ecp_eph_public, ippFalse,
                               ec_ctx);
      if (ippStsNoErr != sts) break;

      // Compute signature
      sts = ippsECCPSignDSA(bn_hash->ipp_bn, bn_reg_private->ipp_bn,
                            bn_sig_x->ipp_bn, bn_sig_y->ipp_bn, ec_ctx);
      if (ippStsEphemeralKeyErr != sts) break;
    } while (--gen_loop_count);
    if (ippStsEphemeralKeyErr == sts) {
      result = kEpidRandMaxIterErr;
      break;
    }
    if (ippStsNoErr != sts) break;

    sts = ippsGetOctString_BN(sig->x.data, sizeof(sig->x), bn_sig_x->ipp_bn);
    if (ippStsNoErr != sts) break;
    sts = ippsGetOctString_BN(sig->y.data, sizeof(sig->y), bn_sig_y->ipp_bn);
    if (ippStsNoErr != sts) break;

    result = kEpidNoErr;
  } while (0);

  DeleteBigNum(&bn_ec_order);
  DeleteBigNum(&bn_hash);
  DeleteBigNum(&bn_reg_private);
  DeleteBigNum(&bn_eph_private);
  DeleteBigNum(&bn_sig_x);
  DeleteBigNum(&bn_sig_y);

  SAFE_FREE(ec_ctx);
  SAFE_FREE(ecp_eph_public);

  return result;
}
예제 #2
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;
    }
}