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