blob: 1d08123badbf030fec435310c336d922f39d6d1b [file] [log] [blame]
Adam Langleyd9e397b2015-01-22 14:27:53 -08001/* ====================================================================
2 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * 3. All advertising materials mentioning features or use of this
17 * software must display the following acknowledgment:
18 * "This product includes software developed by the OpenSSL Project
19 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
20 *
21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22 * endorse or promote products derived from this software without
23 * prior written permission. For written permission, please contact
24 * openssl-core@OpenSSL.org.
25 *
26 * 5. Products derived from this software may not be called "OpenSSL"
27 * nor may "OpenSSL" appear in their names without prior written
28 * permission of the OpenSSL Project.
29 *
30 * 6. Redistributions of any form whatsoever must retain the following
31 * acknowledgment:
32 * "This product includes software developed by the OpenSSL Project
33 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46 * OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This product includes cryptographic software written by Eric Young
50 * (eay@cryptsoft.com). This product includes software written by Tim
51 * Hudson (tjh@cryptsoft.com). */
52
53#include <openssl/ecdsa.h>
54
Kenny Rootb8494592015-09-25 02:29:14 +000055#include <assert.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080056#include <string.h>
57
58#include <openssl/bn.h>
59#include <openssl/err.h>
60#include <openssl/mem.h>
Robert Sloan99319a12017-11-27 10:32:46 -080061#include <openssl/sha.h>
62#include <openssl/type_check.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080063
Robert Sloan69939df2017-01-09 10:53:07 -080064#include "../bn/internal.h"
Adam Langleyd9e397b2015-01-22 14:27:53 -080065#include "../ec/internal.h"
Robert Sloan8ff03552017-06-14 12:40:58 -070066#include "../../internal.h"
Adam Langleyd9e397b2015-01-22 14:27:53 -080067
68
Robert Sloancd79cde2017-12-11 09:06:12 -080069// EC_LOOSE_SCALAR is like |EC_SCALAR| but is bounded by 2^|BN_num_bits(order)|
70// rather than |order|.
71typedef union {
72 // bytes is the representation of the scalar in little-endian order.
73 uint8_t bytes[EC_MAX_SCALAR_BYTES];
74 BN_ULONG words[EC_MAX_SCALAR_WORDS];
75} EC_LOOSE_SCALAR;
76
77static void scalar_add_loose(const EC_GROUP *group, EC_LOOSE_SCALAR *r,
78 const EC_LOOSE_SCALAR *a, const EC_SCALAR *b) {
79 // Add and subtract one copy of |order| if necessary. We have:
80 // |a| + |b| < 2^BN_num_bits(order) + order
81 // so this leaves |r| < 2^BN_num_bits(order).
82 const BIGNUM *order = &group->order;
Robert Sloanab8b8882018-03-26 11:39:51 -070083 BN_ULONG carry = bn_add_words(r->words, a->words, b->words, order->width);
Robert Sloancd79cde2017-12-11 09:06:12 -080084 EC_LOOSE_SCALAR tmp;
Robert Sloanab8b8882018-03-26 11:39:51 -070085 BN_ULONG v =
86 bn_sub_words(tmp.words, r->words, order->d, order->width) - carry;
87 bn_select_words(r->words, 0u - v, r->words /* tmp < 0 */,
88 tmp.words /* tmp >= 0 */, order->width);
Robert Sloancd79cde2017-12-11 09:06:12 -080089}
90
91static int scalar_mod_mul_montgomery(const EC_GROUP *group, EC_SCALAR *r,
92 const EC_SCALAR *a, const EC_SCALAR *b) {
93 const BIGNUM *order = &group->order;
Robert Sloanab8b8882018-03-26 11:39:51 -070094 return bn_mod_mul_montgomery_small(r->words, order->width, a->words,
95 order->width, b->words, order->width,
96 group->order_mont);
Robert Sloancd79cde2017-12-11 09:06:12 -080097}
98
99static int scalar_mod_mul_montgomery_loose(const EC_GROUP *group, EC_SCALAR *r,
100 const EC_LOOSE_SCALAR *a,
101 const EC_SCALAR *b) {
102 // Although |a| is loose, |bn_mod_mul_montgomery_small| only requires the
103 // product not exceed R * |order|. |b| is fully reduced and |a| <
104 // 2^BN_num_bits(order) <= R, so this holds.
105 const BIGNUM *order = &group->order;
Robert Sloanab8b8882018-03-26 11:39:51 -0700106 return bn_mod_mul_montgomery_small(r->words, order->width, a->words,
107 order->width, b->words, order->width,
108 group->order_mont);
Robert Sloancd79cde2017-12-11 09:06:12 -0800109}
110
Robert Sloan99319a12017-11-27 10:32:46 -0800111// digest_to_scalar interprets |digest_len| bytes from |digest| as a scalar for
112// ECDSA. Note this value is not fully reduced modulo the order, only the
113// correct number of bits.
Robert Sloancd79cde2017-12-11 09:06:12 -0800114static void digest_to_scalar(const EC_GROUP *group, EC_LOOSE_SCALAR *out,
Robert Sloan99319a12017-11-27 10:32:46 -0800115 const uint8_t *digest, size_t digest_len) {
116 const BIGNUM *order = &group->order;
117 size_t num_bits = BN_num_bits(order);
118 // Need to truncate digest if it is too long: first truncate whole bytes.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800119 if (8 * digest_len > num_bits) {
120 digest_len = (num_bits + 7) / 8;
121 }
Robert Sloan99319a12017-11-27 10:32:46 -0800122 OPENSSL_memset(out, 0, sizeof(EC_SCALAR));
123 for (size_t i = 0; i < digest_len; i++) {
124 out->bytes[i] = digest[digest_len - 1 - i];
Adam Langleyd9e397b2015-01-22 14:27:53 -0800125 }
126
Robert Sloan8f860b12017-08-28 07:37:06 -0700127 // If still too long truncate remaining bits with a shift
Robert Sloan99319a12017-11-27 10:32:46 -0800128 if (8 * digest_len > num_bits) {
129 size_t shift = 8 - (num_bits & 0x7);
Robert Sloanab8b8882018-03-26 11:39:51 -0700130 for (int i = 0; i < order->width - 1; i++) {
Robert Sloan99319a12017-11-27 10:32:46 -0800131 out->words[i] =
132 (out->words[i] >> shift) | (out->words[i + 1] << (BN_BITS2 - shift));
133 }
Robert Sloanab8b8882018-03-26 11:39:51 -0700134 out->words[order->width - 1] >>= shift;
Robert Sloan99319a12017-11-27 10:32:46 -0800135 }
136}
137
138// field_element_to_scalar reduces |r| modulo |group->order|. |r| must
139// previously have been reduced modulo |group->field|.
140static int field_element_to_scalar(const EC_GROUP *group, BIGNUM *r) {
141 // We must have p < 2×order, assuming p is not tiny (p >= 17). Thus rather we
142 // can reduce by performing at most one subtraction.
143 //
144 // Proof: We only work with prime order curves, so the number of points on
145 // the curve is the order. Thus Hasse's theorem gives:
146 //
147 // |order - (p + 1)| <= 2×sqrt(p)
148 // p + 1 - order <= 2×sqrt(p)
149 // p + 1 - 2×sqrt(p) <= order
150 // p + 1 - 2×(p/4) < order (p/4 > sqrt(p) for p >= 17)
151 // p/2 < p/2 + 1 < order
152 // p < 2×order
153 //
154 // Additionally, one can manually check this property for built-in curves. It
155 // is enforced for legacy custom curves in |EC_GROUP_set_generator|.
156 //
157 // TODO(davidben): Introduce |EC_FIELD_ELEMENT|, make this a function from
158 // |EC_FIELD_ELEMENT| to |EC_SCALAR|, and cut out the |BIGNUM|. Does this need
159 // to be constant-time for signing? |r| is the x-coordinate for kG, which is
160 // public unless k was rerolled because |s| was zero.
161 assert(!BN_is_negative(r));
162 assert(BN_cmp(r, &group->field) < 0);
163 if (BN_cmp(r, &group->order) >= 0 &&
164 !BN_sub(r, r, &group->order)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800165 return 0;
166 }
Robert Sloan99319a12017-11-27 10:32:46 -0800167 assert(!BN_is_negative(r));
168 assert(BN_cmp(r, &group->order) < 0);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800169 return 1;
170}
171
Robert Sloan8ff03552017-06-14 12:40:58 -0700172ECDSA_SIG *ECDSA_SIG_new(void) {
173 ECDSA_SIG *sig = OPENSSL_malloc(sizeof(ECDSA_SIG));
174 if (sig == NULL) {
175 return NULL;
176 }
177 sig->r = BN_new();
178 sig->s = BN_new();
179 if (sig->r == NULL || sig->s == NULL) {
180 ECDSA_SIG_free(sig);
181 return NULL;
182 }
183 return sig;
184}
185
186void ECDSA_SIG_free(ECDSA_SIG *sig) {
187 if (sig == NULL) {
188 return;
189 }
190
191 BN_free(sig->r);
192 BN_free(sig->s);
193 OPENSSL_free(sig);
194}
195
Robert Sloan99319a12017-11-27 10:32:46 -0800196void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **out_r,
197 const BIGNUM **out_s) {
198 if (out_r != NULL) {
199 *out_r = sig->r;
200 }
201 if (out_s != NULL) {
202 *out_s = sig->s;
203 }
204}
205
206int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) {
207 if (r == NULL || s == NULL) {
208 return 0;
209 }
210 BN_free(sig->r);
211 BN_free(sig->s);
212 sig->r = r;
213 sig->s = s;
214 return 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800215}
216
217int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
Robert Sloana94fe052017-02-21 08:49:28 -0800218 const ECDSA_SIG *sig, const EC_KEY *eckey) {
Robert Sloan99319a12017-11-27 10:32:46 -0800219 const EC_GROUP *group = EC_KEY_get0_group(eckey);
220 const EC_POINT *pub_key = EC_KEY_get0_public_key(eckey);
221 if (group == NULL || pub_key == NULL || sig == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000222 OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_MISSING_PARAMETERS);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800223 return 0;
224 }
225
Robert Sloan99319a12017-11-27 10:32:46 -0800226 BN_CTX *ctx = BN_CTX_new();
Adam Langleyd9e397b2015-01-22 14:27:53 -0800227 if (!ctx) {
Kenny Rootb8494592015-09-25 02:29:14 +0000228 OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800229 return 0;
230 }
Robert Sloan99319a12017-11-27 10:32:46 -0800231 int ret = 0;
232 EC_POINT *point = NULL;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800233 BN_CTX_start(ctx);
Robert Sloan99319a12017-11-27 10:32:46 -0800234 BIGNUM *X = BN_CTX_get(ctx);
235 if (X == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000236 OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800237 goto err;
238 }
239
Robert Sloancd79cde2017-12-11 09:06:12 -0800240 EC_SCALAR r, s, u1, u2, s_inv_mont;
241 EC_LOOSE_SCALAR m;
Adam Langley4139edb2016-01-13 15:00:54 -0800242 const BIGNUM *order = EC_GROUP_get0_order(group);
Robert Sloan99319a12017-11-27 10:32:46 -0800243 if (BN_is_zero(sig->r) ||
Robert Sloan99319a12017-11-27 10:32:46 -0800244 !ec_bignum_to_scalar(group, &r, sig->r) ||
245 BN_is_zero(sig->s) ||
Robert Sloan99319a12017-11-27 10:32:46 -0800246 !ec_bignum_to_scalar(group, &s, sig->s)) {
Kenny Rootb8494592015-09-25 02:29:14 +0000247 OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800248 goto err;
249 }
Robert Sloan99319a12017-11-27 10:32:46 -0800250 // s_inv_mont = s^-1 mod order. We convert the result to Montgomery form for
251 // the products below.
David Benjaminc895d6b2016-08-11 13:26:41 -0400252 int no_inverse;
Robert Sloan99319a12017-11-27 10:32:46 -0800253 if (!BN_mod_inverse_odd(X, &no_inverse, sig->s, order, ctx) ||
Robert Sloancd79cde2017-12-11 09:06:12 -0800254 // TODO(davidben): Add a words version of |BN_mod_inverse_odd| and write
255 // into |s_inv_mont| directly.
256 !ec_bignum_to_scalar_unchecked(group, &s_inv_mont, X) ||
Robert Sloanab8b8882018-03-26 11:39:51 -0700257 !bn_to_montgomery_small(s_inv_mont.words, order->width, s_inv_mont.words,
258 order->width, group->order_mont)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800259 goto err;
260 }
Robert Sloancd79cde2017-12-11 09:06:12 -0800261 // u1 = m * s^-1 mod order
262 // u2 = r * s^-1 mod order
Robert Sloan99319a12017-11-27 10:32:46 -0800263 //
264 // |s_inv_mont| is in Montgomery form while |m| and |r| are not, so |u1| and
Robert Sloancd79cde2017-12-11 09:06:12 -0800265 // |u2| will be taken out of Montgomery form, as desired.
Robert Sloan99319a12017-11-27 10:32:46 -0800266 digest_to_scalar(group, &m, digest, digest_len);
Robert Sloancd79cde2017-12-11 09:06:12 -0800267 if (!scalar_mod_mul_montgomery_loose(group, &u1, &m, &s_inv_mont) ||
268 !scalar_mod_mul_montgomery(group, &u2, &r, &s_inv_mont)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800269 goto err;
270 }
271
272 point = EC_POINT_new(group);
273 if (point == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000274 OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800275 goto err;
276 }
Robert Sloan55818102017-12-18 11:26:17 -0800277 if (!ec_point_mul_scalar_public(group, point, &u1, pub_key, &u2, ctx)) {
Kenny Rootb8494592015-09-25 02:29:14 +0000278 OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800279 goto err;
280 }
281 if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) {
Kenny Rootb8494592015-09-25 02:29:14 +0000282 OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800283 goto err;
284 }
Robert Sloan99319a12017-11-27 10:32:46 -0800285 if (!field_element_to_scalar(group, X)) {
Kenny Rootb8494592015-09-25 02:29:14 +0000286 OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800287 goto err;
288 }
Robert Sloan99319a12017-11-27 10:32:46 -0800289 // The signature is correct iff |X| is equal to |sig->r|.
290 if (BN_ucmp(X, sig->r) != 0) {
Robert Sloan2424d842017-05-01 07:46:28 -0700291 OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
292 goto err;
293 }
294
295 ret = 1;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800296
297err:
David Benjamin4969cc92016-04-22 15:02:23 -0400298 BN_CTX_end(ctx);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800299 BN_CTX_free(ctx);
Adam Langleye9ada862015-05-11 17:20:37 -0700300 EC_POINT_free(point);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800301 return ret;
302}
303
Robert Sloan99319a12017-11-27 10:32:46 -0800304static int ecdsa_sign_setup(const EC_KEY *eckey, BN_CTX *ctx,
305 EC_SCALAR *out_kinv_mont, BIGNUM **rp,
306 const uint8_t *digest, size_t digest_len,
307 const EC_SCALAR *priv_key) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800308 EC_POINT *tmp_point = NULL;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800309 int ret = 0;
Robert Sloan99319a12017-11-27 10:32:46 -0800310 EC_SCALAR k;
311 BIGNUM *r = BN_new(); // this value is later returned in *rp
312 if (r == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000313 OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800314 goto err;
315 }
Robert Sloan99319a12017-11-27 10:32:46 -0800316 const EC_GROUP *group = EC_KEY_get0_group(eckey);
317 const BIGNUM *order = EC_GROUP_get0_order(group);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800318 tmp_point = EC_POINT_new(group);
319 if (tmp_point == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000320 OPENSSL_PUT_ERROR(ECDSA, ERR_R_EC_LIB);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800321 goto err;
322 }
Adam Langley4139edb2016-01-13 15:00:54 -0800323
Robert Sloan8f860b12017-08-28 07:37:06 -0700324 // Check that the size of the group order is FIPS compliant (FIPS 186-4
325 // B.5.2).
Robert Sloan572a4e22017-04-17 10:52:19 -0700326 if (BN_num_bits(order) < 160) {
327 OPENSSL_PUT_ERROR(ECDSA, EC_R_INVALID_GROUP_ORDER);
328 goto err;
329 }
330
Adam Langleyd9e397b2015-01-22 14:27:53 -0800331 do {
Robert Sloan99319a12017-11-27 10:32:46 -0800332 // Include the private key and message digest in the k generation.
Robert Sloan8ff03552017-06-14 12:40:58 -0700333 if (eckey->fixed_k != NULL) {
Robert Sloan99319a12017-11-27 10:32:46 -0800334 if (!ec_bignum_to_scalar(group, &k, eckey->fixed_k)) {
Robert Sloan8ff03552017-06-14 12:40:58 -0700335 goto err;
336 }
Robert Sloan99319a12017-11-27 10:32:46 -0800337 } else {
338 // Pass a SHA512 hash of the private key and digest as additional data
339 // into the RBG. This is a hardening measure against entropy failure.
340 OPENSSL_COMPILE_ASSERT(SHA512_DIGEST_LENGTH >= 32,
341 additional_data_is_too_large_for_sha512);
342 SHA512_CTX sha;
343 uint8_t additional_data[SHA512_DIGEST_LENGTH];
344 SHA512_Init(&sha);
Robert Sloanab8b8882018-03-26 11:39:51 -0700345 SHA512_Update(&sha, priv_key->words, order->width * sizeof(BN_ULONG));
Robert Sloan99319a12017-11-27 10:32:46 -0800346 SHA512_Update(&sha, digest, digest_len);
347 SHA512_Final(additional_data, &sha);
348 if (!ec_random_nonzero_scalar(group, &k, additional_data)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800349 goto err;
350 }
351 }
352
Robert Sloan99319a12017-11-27 10:32:46 -0800353 // Compute k^-1. We leave it in the Montgomery domain as an optimization for
354 // later operations.
Robert Sloanab8b8882018-03-26 11:39:51 -0700355 if (!bn_to_montgomery_small(out_kinv_mont->words, order->width, k.words,
356 order->width, group->order_mont) ||
357 !bn_mod_inverse_prime_mont_small(out_kinv_mont->words, order->width,
358 out_kinv_mont->words, order->width,
Robert Sloan99319a12017-11-27 10:32:46 -0800359 group->order_mont)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800360 goto err;
361 }
Robert Sloan99319a12017-11-27 10:32:46 -0800362
363 // Compute r, the x-coordinate of generator * k.
364 if (!ec_point_mul_scalar(group, tmp_point, &k, NULL, NULL, ctx) ||
365 !EC_POINT_get_affine_coordinates_GFp(group, tmp_point, r, NULL,
David Benjaminc895d6b2016-08-11 13:26:41 -0400366 ctx)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800367 goto err;
368 }
369
Robert Sloan99319a12017-11-27 10:32:46 -0800370 if (!field_element_to_scalar(group, r)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800371 goto err;
372 }
373 } while (BN_is_zero(r));
374
Adam Langleye9ada862015-05-11 17:20:37 -0700375 BN_clear_free(*rp);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800376 *rp = r;
Robert Sloan99319a12017-11-27 10:32:46 -0800377 r = NULL;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800378 ret = 1;
379
380err:
Robert Sloan99319a12017-11-27 10:32:46 -0800381 OPENSSL_cleanse(&k, sizeof(k));
382 BN_clear_free(r);
Adam Langleye9ada862015-05-11 17:20:37 -0700383 EC_POINT_free(tmp_point);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800384 return ret;
385}
386
Robert Sloan99319a12017-11-27 10:32:46 -0800387ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len,
388 const EC_KEY *eckey) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800389 if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
Kenny Rootb8494592015-09-25 02:29:14 +0000390 OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800391 return NULL;
392 }
393
Robert Sloan99319a12017-11-27 10:32:46 -0800394 const EC_GROUP *group = EC_KEY_get0_group(eckey);
Robert Sloanab8b8882018-03-26 11:39:51 -0700395 if (group == NULL || eckey->priv_key == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000396 OPENSSL_PUT_ERROR(ECDSA, ERR_R_PASSED_NULL_PARAMETER);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800397 return NULL;
398 }
Robert Sloan99319a12017-11-27 10:32:46 -0800399 const BIGNUM *order = EC_GROUP_get0_order(group);
Robert Sloanab8b8882018-03-26 11:39:51 -0700400 const EC_SCALAR *priv_key = &eckey->priv_key->scalar;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800401
Robert Sloan99319a12017-11-27 10:32:46 -0800402 int ok = 0;
403 ECDSA_SIG *ret = ECDSA_SIG_new();
404 BN_CTX *ctx = BN_CTX_new();
Robert Sloanab8b8882018-03-26 11:39:51 -0700405 EC_SCALAR kinv_mont, r_mont, s;
Robert Sloancd79cde2017-12-11 09:06:12 -0800406 EC_LOOSE_SCALAR m, tmp;
Robert Sloan99319a12017-11-27 10:32:46 -0800407 if (ret == NULL || ctx == NULL) {
Kenny Rootb8494592015-09-25 02:29:14 +0000408 OPENSSL_PUT_ERROR(ECDSA, ERR_R_MALLOC_FAILURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800409 return NULL;
410 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800411
Robert Sloan99319a12017-11-27 10:32:46 -0800412 digest_to_scalar(group, &m, digest, digest_len);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800413 for (;;) {
Robert Sloan99319a12017-11-27 10:32:46 -0800414 if (!ecdsa_sign_setup(eckey, ctx, &kinv_mont, &ret->r, digest, digest_len,
Robert Sloanab8b8882018-03-26 11:39:51 -0700415 priv_key)) {
Robert Sloan99319a12017-11-27 10:32:46 -0800416 goto err;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800417 }
418
Robert Sloan99319a12017-11-27 10:32:46 -0800419 // Compute priv_key * r (mod order). Note if only one parameter is in the
Robert Sloancd79cde2017-12-11 09:06:12 -0800420 // Montgomery domain, |scalar_mod_mul_montgomery| will compute the answer in
421 // the normal domain.
Robert Sloan99319a12017-11-27 10:32:46 -0800422 if (!ec_bignum_to_scalar(group, &r_mont, ret->r) ||
Robert Sloanab8b8882018-03-26 11:39:51 -0700423 !bn_to_montgomery_small(r_mont.words, order->width, r_mont.words,
424 order->width, group->order_mont) ||
425 !scalar_mod_mul_montgomery(group, &s, priv_key, &r_mont)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800426 goto err;
427 }
Robert Sloan99319a12017-11-27 10:32:46 -0800428
Robert Sloancd79cde2017-12-11 09:06:12 -0800429 // Compute tmp = m + priv_key * r.
430 scalar_add_loose(group, &tmp, &m, &s);
Robert Sloan99319a12017-11-27 10:32:46 -0800431
432 // Finally, multiply s by k^-1. That was retained in Montgomery form, so the
Robert Sloancd79cde2017-12-11 09:06:12 -0800433 // same technique as the previous multiplication works.
434 if (!scalar_mod_mul_montgomery_loose(group, &s, &tmp, &kinv_mont) ||
Robert Sloanab8b8882018-03-26 11:39:51 -0700435 !bn_set_words(ret->s, s.words, order->width)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800436 goto err;
437 }
Robert Sloan99319a12017-11-27 10:32:46 -0800438 if (!BN_is_zero(ret->s)) {
Robert Sloan8f860b12017-08-28 07:37:06 -0700439 // s != 0 => we have a valid signature
Adam Langleyd9e397b2015-01-22 14:27:53 -0800440 break;
441 }
442 }
443
444 ok = 1;
445
446err:
447 if (!ok) {
448 ECDSA_SIG_free(ret);
449 ret = NULL;
450 }
Adam Langleye9ada862015-05-11 17:20:37 -0700451 BN_CTX_free(ctx);
Robert Sloan99319a12017-11-27 10:32:46 -0800452 OPENSSL_cleanse(&kinv_mont, sizeof(kinv_mont));
Robert Sloan99319a12017-11-27 10:32:46 -0800453 OPENSSL_cleanse(&r_mont, sizeof(r_mont));
454 OPENSSL_cleanse(&s, sizeof(s));
455 OPENSSL_cleanse(&tmp, sizeof(tmp));
456 OPENSSL_cleanse(&m, sizeof(m));
Adam Langleyd9e397b2015-01-22 14:27:53 -0800457 return ret;
458}