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