• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EcdsaSignBuffer(ConstOctStr buf,size_t buf_len,EcdsaPrivateKey const * privkey,BitSupplier rnd_func,void * rnd_param,EcdsaSignature * sig)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