Home | History | Annotate | Download | only in src
      1 /*############################################################################
      2   # Copyright 2016-2017 Intel Corporation
      3   #
      4   # Licensed under the Apache License, Version 2.0 (the "License");
      5   # you may not use this file except in compliance with the License.
      6   # You may obtain a copy of the License at
      7   #
      8   #     http://www.apache.org/licenses/LICENSE-2.0
      9   #
     10   # Unless required by applicable law or agreed to in writing, software
     11   # distributed under the License is distributed on an "AS IS" BASIS,
     12   # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13   # See the License for the specific language governing permissions and
     14   # limitations under the License.
     15   ############################################################################*/
     16 
     17 /*!
     18  * \file
     19  * \brief EcdsaSignBuffer implementation.
     20  */
     21 
     22 #include "epid/common/math/bignum.h"
     23 #include "epid/common/math/ecdsa.h"
     24 #include "epid/common/math/ecgroup.h"
     25 #include "epid/common/math/src/bignum-internal.h"
     26 #include "epid/common/src/memory.h"
     27 #include "ext/ipp/include/ippcp.h"
     28 
     29 /// The number of attempts to generate ephemeral key pair
     30 #define EPHKEYGEN_WATCHDOG (10)
     31 
     32 EpidStatus EcdsaSignBuffer(ConstOctStr buf, size_t buf_len,
     33                            EcdsaPrivateKey const* privkey, BitSupplier rnd_func,
     34                            void* rnd_param, EcdsaSignature* sig) {
     35   EpidStatus result = kEpidMathErr;
     36 
     37   IppsECCPState* ec_ctx = NULL;
     38   BigNum* bn_ec_order = NULL;
     39 
     40   BigNum* bn_hash = NULL;
     41 
     42   BigNum* bn_reg_private = NULL;
     43   BigNum* bn_eph_private = NULL;
     44   IppsECCPPointState* ecp_eph_public = NULL;
     45 
     46   BigNum* bn_sig_x = NULL;
     47   BigNum* bn_sig_y = NULL;
     48 
     49   do {
     50     EpidStatus epid_status = kEpidNoErr;
     51     IppStatus sts = ippStsNoErr;
     52     int ctxsize = 0;
     53     // order of EC secp256r1
     54     const uint8_t secp256r1_r[32] = {
     55         0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
     56         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17,
     57         0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51};
     58     Ipp8u hash[IPP_SHA256_DIGEST_BITSIZE / 8] = {0};
     59     unsigned int gen_loop_count = EPHKEYGEN_WATCHDOG;
     60     Ipp32u cmp0 = IS_ZERO;
     61     Ipp32u cmp_order = IS_ZERO;
     62 
     63     if ((0 != buf_len && !buf) || !privkey || !rnd_func || !sig) {
     64       result = kEpidBadArgErr;
     65       break;
     66     }
     67     if (buf_len > INT_MAX) {
     68       result = kEpidBadArgErr;
     69       break;
     70     }
     71 
     72     // Define standard elliptic curve secp256r1
     73     sts = ippsECCPGetSizeStd256r1(&ctxsize);
     74     if (ippStsNoErr != sts) break;
     75     ec_ctx = (IppsECCPState*)SAFE_ALLOC(ctxsize);
     76     if (!ec_ctx) {
     77       result = kEpidMemAllocErr;
     78       break;
     79     }
     80     sts = ippsECCPInitStd256r1(ec_ctx);
     81     if (ippStsNoErr != sts) break;
     82     sts = ippsECCPSetStd256r1(ec_ctx);
     83     if (ippStsNoErr != sts) break;
     84 
     85     // Create big number for order of elliptic curve secp256r1
     86     epid_status = NewBigNum(sizeof(secp256r1_r), &bn_ec_order);
     87     if (kEpidMemAllocErr == epid_status) {
     88       result = kEpidMemAllocErr;
     89       break;
     90     }
     91     if (kEpidNoErr != epid_status) break;
     92     epid_status = ReadBigNum(secp256r1_r, sizeof(secp256r1_r), bn_ec_order);
     93     if (kEpidNoErr != epid_status) break;
     94 
     95     // Calculate hash for input message
     96     sts = ippsSHA256MessageDigest(buf, (int)buf_len, hash);
     97     if (ippStsNoErr != sts) break;
     98 
     99     // Create big number for hash
    100     epid_status = NewBigNum(sizeof(hash), &bn_hash);
    101     if (kEpidMemAllocErr == epid_status) {
    102       result = kEpidMemAllocErr;
    103       break;
    104     }
    105     if (kEpidNoErr != epid_status) break;
    106     epid_status = ReadBigNum(hash, sizeof(hash), bn_hash);
    107     if (kEpidNoErr != epid_status) break;
    108     sts = ippsMod_BN(bn_hash->ipp_bn, bn_ec_order->ipp_bn, bn_hash->ipp_bn);
    109     if (ippStsNoErr != sts) break;
    110 
    111     // Create big number for regular private key
    112     epid_status = NewBigNum(sizeof(*privkey), &bn_reg_private);
    113     if (kEpidMemAllocErr == epid_status) {
    114       result = kEpidMemAllocErr;
    115       break;
    116     }
    117     if (kEpidNoErr != epid_status) break;
    118     epid_status = ReadBigNum(privkey, sizeof(*privkey), bn_reg_private);
    119     if (kEpidNoErr != epid_status) break;
    120 
    121     // Validate private key is in range [1, bn_ec_order-1]
    122     sts = ippsCmpZero_BN(bn_reg_private->ipp_bn, &cmp0);
    123     if (ippStsNoErr != sts) break;
    124     sts = ippsCmp_BN(bn_reg_private->ipp_bn, bn_ec_order->ipp_bn, &cmp_order);
    125     if (ippStsNoErr != sts) break;
    126     if (IS_ZERO == cmp0 || LESS_THAN_ZERO != cmp_order) {
    127       result = kEpidBadArgErr;
    128       break;
    129     }
    130 
    131     // Create big number for ephemeral private key
    132     epid_status = NewBigNum(sizeof(secp256r1_r), &bn_eph_private);
    133     if (kEpidMemAllocErr == epid_status) {
    134       result = kEpidMemAllocErr;
    135       break;
    136     }
    137     if (kEpidNoErr != epid_status) break;
    138 
    139     // Create EC point for ephemeral public key
    140     sts = ippsECCPPointGetSize(256, &ctxsize);
    141     if (ippStsNoErr != sts) break;
    142     ecp_eph_public = (IppsECCPPointState*)SAFE_ALLOC(ctxsize);
    143     if (!ecp_eph_public) {
    144       result = kEpidMemAllocErr;
    145       break;
    146     }
    147     sts = ippsECCPPointInit(256, ecp_eph_public);
    148     if (ippStsNoErr != sts) break;
    149 
    150     // Create big numbers for signature
    151     epid_status = NewBigNum(sizeof(secp256r1_r), &bn_sig_x);
    152     if (kEpidMemAllocErr == epid_status) {
    153       result = kEpidMemAllocErr;
    154       break;
    155     }
    156     if (kEpidNoErr != epid_status) break;
    157     epid_status = NewBigNum(sizeof(secp256r1_r), &bn_sig_y);
    158     if (kEpidMemAllocErr == epid_status) {
    159       result = kEpidMemAllocErr;
    160       break;
    161     }
    162     if (kEpidNoErr != epid_status) break;
    163 
    164     do {
    165       // Generate ephemeral key pair
    166       sts = ippsECCPGenKeyPair(bn_eph_private->ipp_bn, ecp_eph_public, ec_ctx,
    167                                (IppBitSupplier)rnd_func, rnd_param);
    168       if (ippStsNoErr != sts) break;
    169 
    170       // Set ephemeral key pair
    171       sts = ippsECCPSetKeyPair(bn_eph_private->ipp_bn, ecp_eph_public, ippFalse,
    172                                ec_ctx);
    173       if (ippStsNoErr != sts) break;
    174 
    175       // Compute signature
    176       sts = ippsECCPSignDSA(bn_hash->ipp_bn, bn_reg_private->ipp_bn,
    177                             bn_sig_x->ipp_bn, bn_sig_y->ipp_bn, ec_ctx);
    178       if (ippStsEphemeralKeyErr != sts) break;
    179     } while (--gen_loop_count);
    180     if (ippStsEphemeralKeyErr == sts) {
    181       result = kEpidRandMaxIterErr;
    182       break;
    183     }
    184     if (ippStsNoErr != sts) break;
    185 
    186     sts = ippsGetOctString_BN(sig->x.data, sizeof(sig->x), bn_sig_x->ipp_bn);
    187     if (ippStsNoErr != sts) break;
    188     sts = ippsGetOctString_BN(sig->y.data, sizeof(sig->y), bn_sig_y->ipp_bn);
    189     if (ippStsNoErr != sts) break;
    190 
    191     result = kEpidNoErr;
    192   } while (0);
    193 
    194   DeleteBigNum(&bn_ec_order);
    195   DeleteBigNum(&bn_hash);
    196   DeleteBigNum(&bn_reg_private);
    197   DeleteBigNum(&bn_eph_private);
    198   DeleteBigNum(&bn_sig_x);
    199   DeleteBigNum(&bn_sig_y);
    200 
    201   SAFE_FREE(ec_ctx);
    202   SAFE_FREE(ecp_eph_public);
    203 
    204   return result;
    205 }
    206