diff options
author | tb <> | 2018-06-15 19:24:13 +0000 |
---|---|---|
committer | tb <> | 2018-06-15 19:24:13 +0000 |
commit | a3ae248d6e35515f29a8a97a956d678a5cf9bb30 (patch) | |
tree | 9ca0ee6a1212018a6da9597acbb46e91aee4e22c | |
parent | 2c25c4b4c61884af3b090e7db459cc826945c359 (diff) | |
download | openbsd-a3ae248d6e35515f29a8a97a956d678a5cf9bb30.tar.gz openbsd-a3ae248d6e35515f29a8a97a956d678a5cf9bb30.tar.bz2 openbsd-a3ae248d6e35515f29a8a97a956d678a5cf9bb30.zip |
Basic cleanup. Handle the possibly NULL ctx_in in ecdsa_sign_setup() with
the usual idiom. All the allocations are now handled inside conditionals as
is usually done in this part of the tree. Turn a few comments into actual
sentences and remove a few self-evident ones. Change outdated or cryptic
comments into more helpful annotations. In ecdsa_do_verify(), start
calculating only after properly truncating the message digest. More
consistent variable names: prefer 'order_bits' and 'point' over 'i' and
'tmp_point'.
ok jsing
-rw-r--r-- | src/lib/libcrypto/ecdsa/ecs_ossl.c | 129 |
1 files changed, 62 insertions, 67 deletions
diff --git a/src/lib/libcrypto/ecdsa/ecs_ossl.c b/src/lib/libcrypto/ecdsa/ecs_ossl.c index be279b34b6..eff2a5022d 100644 --- a/src/lib/libcrypto/ecdsa/ecs_ossl.c +++ b/src/lib/libcrypto/ecdsa/ecs_ossl.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ecs_ossl.c,v 1.13 2018/06/15 05:00:41 tb Exp $ */ | 1 | /* $OpenBSD: ecs_ossl.c,v 1.14 2018/06/15 19:24:13 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Written by Nils Larsch for the OpenSSL project | 3 | * Written by Nils Larsch for the OpenSSL project |
4 | */ | 4 | */ |
@@ -88,9 +88,9 @@ ECDSA_OpenSSL(void) | |||
88 | static int | 88 | static int |
89 | ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) | 89 | ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) |
90 | { | 90 | { |
91 | BN_CTX *ctx = NULL; | 91 | BN_CTX *ctx = ctx_in; |
92 | BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; | 92 | BIGNUM *k = NULL, *r = NULL, *order = NULL, *X = NULL; |
93 | EC_POINT *tmp_point = NULL; | 93 | EC_POINT *point = NULL; |
94 | const EC_GROUP *group; | 94 | const EC_GROUP *group; |
95 | int order_bits, ret = 0; | 95 | int order_bits, ret = 0; |
96 | 96 | ||
@@ -99,23 +99,19 @@ ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) | |||
99 | return 0; | 99 | return 0; |
100 | } | 100 | } |
101 | 101 | ||
102 | if (ctx_in == NULL) { | 102 | if (ctx == NULL) { |
103 | if ((ctx = BN_CTX_new()) == NULL) { | 103 | if ((ctx = BN_CTX_new()) == NULL) { |
104 | ECDSAerror(ERR_R_MALLOC_FAILURE); | 104 | ECDSAerror(ERR_R_MALLOC_FAILURE); |
105 | return 0; | 105 | return 0; |
106 | } | 106 | } |
107 | } else | 107 | } |
108 | ctx = ctx_in; | 108 | |
109 | 109 | if ((k = BN_new()) == NULL || (r = BN_new()) == NULL || | |
110 | k = BN_new(); /* this value is later returned in *kinvp */ | 110 | (order = BN_new()) == NULL || (X = BN_new()) == NULL) { |
111 | r = BN_new(); /* this value is later returned in *rp */ | ||
112 | order = BN_new(); | ||
113 | X = BN_new(); | ||
114 | if (!k || !r || !order || !X) { | ||
115 | ECDSAerror(ERR_R_MALLOC_FAILURE); | 111 | ECDSAerror(ERR_R_MALLOC_FAILURE); |
116 | goto err; | 112 | goto err; |
117 | } | 113 | } |
118 | if ((tmp_point = EC_POINT_new(group)) == NULL) { | 114 | if ((point = EC_POINT_new(group)) == NULL) { |
119 | ECDSAerror(ERR_R_EC_LIB); | 115 | ECDSAerror(ERR_R_EC_LIB); |
120 | goto err; | 116 | goto err; |
121 | } | 117 | } |
@@ -132,14 +128,13 @@ ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) | |||
132 | goto err; | 128 | goto err; |
133 | 129 | ||
134 | do { | 130 | do { |
135 | /* get random k */ | 131 | do { |
136 | do | ||
137 | if (!BN_rand_range(k, order)) { | 132 | if (!BN_rand_range(k, order)) { |
138 | ECDSAerror( | 133 | ECDSAerror( |
139 | ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); | 134 | ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED); |
140 | goto err; | 135 | goto err; |
141 | } | 136 | } |
142 | while (BN_is_zero(k)); | 137 | } while (BN_is_zero(k)); |
143 | 138 | ||
144 | /* | 139 | /* |
145 | * We do not want timing information to leak the length of k, | 140 | * We do not want timing information to leak the length of k, |
@@ -162,23 +157,23 @@ ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) | |||
162 | 157 | ||
163 | BN_set_flags(k, BN_FLG_CONSTTIME); | 158 | BN_set_flags(k, BN_FLG_CONSTTIME); |
164 | 159 | ||
165 | /* compute r the x-coordinate of generator * k */ | 160 | /* Compute r, the x-coordinate of G * k. */ |
166 | if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { | 161 | if (!EC_POINT_mul(group, point, k, NULL, NULL, ctx)) { |
167 | ECDSAerror(ERR_R_EC_LIB); | 162 | ECDSAerror(ERR_R_EC_LIB); |
168 | goto err; | 163 | goto err; |
169 | } | 164 | } |
170 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == | 165 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == |
171 | NID_X9_62_prime_field) { | 166 | NID_X9_62_prime_field) { |
172 | if (!EC_POINT_get_affine_coordinates_GFp(group, | 167 | if (!EC_POINT_get_affine_coordinates_GFp(group, point, |
173 | tmp_point, X, NULL, ctx)) { | 168 | X, NULL, ctx)) { |
174 | ECDSAerror(ERR_R_EC_LIB); | 169 | ECDSAerror(ERR_R_EC_LIB); |
175 | goto err; | 170 | goto err; |
176 | } | 171 | } |
177 | } | 172 | } |
178 | #ifndef OPENSSL_NO_EC2M | 173 | #ifndef OPENSSL_NO_EC2M |
179 | else { /* NID_X9_62_characteristic_two_field */ | 174 | else { /* NID_X9_62_characteristic_two_field */ |
180 | if (!EC_POINT_get_affine_coordinates_GF2m(group, | 175 | if (!EC_POINT_get_affine_coordinates_GF2m(group, point, |
181 | tmp_point, X, NULL, ctx)) { | 176 | X, NULL, ctx)) { |
182 | ECDSAerror(ERR_R_EC_LIB); | 177 | ECDSAerror(ERR_R_EC_LIB); |
183 | goto err; | 178 | goto err; |
184 | } | 179 | } |
@@ -190,15 +185,12 @@ ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) | |||
190 | } | 185 | } |
191 | } while (BN_is_zero(r)); | 186 | } while (BN_is_zero(r)); |
192 | 187 | ||
193 | /* compute the inverse of k */ | ||
194 | if (!BN_mod_inverse_ct(k, k, order, ctx)) { | 188 | if (!BN_mod_inverse_ct(k, k, order, ctx)) { |
195 | ECDSAerror(ERR_R_BN_LIB); | 189 | ECDSAerror(ERR_R_BN_LIB); |
196 | goto err; | 190 | goto err; |
197 | } | 191 | } |
198 | /* clear old values if necessary */ | ||
199 | BN_clear_free(*rp); | 192 | BN_clear_free(*rp); |
200 | BN_clear_free(*kinvp); | 193 | BN_clear_free(*kinvp); |
201 | /* save the pre-computed values */ | ||
202 | *rp = r; | 194 | *rp = r; |
203 | *kinvp = k; | 195 | *kinvp = k; |
204 | ret = 1; | 196 | ret = 1; |
@@ -211,7 +203,7 @@ ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) | |||
211 | if (ctx_in == NULL) | 203 | if (ctx_in == NULL) |
212 | BN_CTX_free(ctx); | 204 | BN_CTX_free(ctx); |
213 | BN_free(order); | 205 | BN_free(order); |
214 | EC_POINT_free(tmp_point); | 206 | EC_POINT_free(point); |
215 | BN_clear_free(X); | 207 | BN_clear_free(X); |
216 | return (ret); | 208 | return (ret); |
217 | } | 209 | } |
@@ -228,7 +220,7 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, | |||
228 | const EC_GROUP *group; | 220 | const EC_GROUP *group; |
229 | ECDSA_SIG *ret; | 221 | ECDSA_SIG *ret; |
230 | ECDSA_DATA *ecdsa; | 222 | ECDSA_DATA *ecdsa; |
231 | int ok = 0, i; | 223 | int ok = 0, order_bits; |
232 | 224 | ||
233 | ecdsa = ecdsa_check(eckey); | 225 | ecdsa = ecdsa_check(eckey); |
234 | group = EC_KEY_get0_group(eckey); | 226 | group = EC_KEY_get0_group(eckey); |
@@ -239,8 +231,7 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, | |||
239 | return NULL; | 231 | return NULL; |
240 | } | 232 | } |
241 | 233 | ||
242 | ret = ECDSA_SIG_new(); | 234 | if ((ret = ECDSA_SIG_new()) == NULL) { |
243 | if (!ret) { | ||
244 | ECDSAerror(ERR_R_MALLOC_FAILURE); | 235 | ECDSAerror(ERR_R_MALLOC_FAILURE); |
245 | return NULL; | 236 | return NULL; |
246 | } | 237 | } |
@@ -258,18 +249,21 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, | |||
258 | ECDSAerror(ERR_R_EC_LIB); | 249 | ECDSAerror(ERR_R_EC_LIB); |
259 | goto err; | 250 | goto err; |
260 | } | 251 | } |
261 | i = BN_num_bits(order); | 252 | |
262 | /* Truncate digest if it is too long: first truncate whole bytes. */ | 253 | /* Truncate digest if it is too long: first truncate whole bytes. */ |
263 | if (8 * dgst_len > i) | 254 | order_bits = BN_num_bits(order); |
264 | dgst_len = (i + 7)/8; | 255 | if (8 * dgst_len > order_bits) |
256 | dgst_len = (order_bits + 7) / 8; | ||
265 | if (!BN_bin2bn(dgst, dgst_len, m)) { | 257 | if (!BN_bin2bn(dgst, dgst_len, m)) { |
266 | ECDSAerror(ERR_R_BN_LIB); | 258 | ECDSAerror(ERR_R_BN_LIB); |
267 | goto err; | 259 | goto err; |
268 | } | 260 | } |
269 | /* If it is still too long, truncate the remaining bits with a shift. */ | 261 | /* If it is still too long, truncate the remaining bits with a shift. */ |
270 | if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { | 262 | if (8 * dgst_len > order_bits) { |
271 | ECDSAerror(ERR_R_BN_LIB); | 263 | if (!BN_rshift(m, m, 8 - (order_bits & 0x7))) { |
272 | goto err; | 264 | ECDSAerror(ERR_R_BN_LIB); |
265 | goto err; | ||
266 | } | ||
273 | } | 267 | } |
274 | 268 | ||
275 | do { | 269 | do { |
@@ -359,7 +353,7 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, | |||
359 | ok = 1; | 353 | ok = 1; |
360 | 354 | ||
361 | err: | 355 | err: |
362 | if (!ok) { | 356 | if (ok == 0) { |
363 | ECDSA_SIG_free(ret); | 357 | ECDSA_SIG_free(ret); |
364 | ret = NULL; | 358 | ret = NULL; |
365 | } | 359 | } |
@@ -379,22 +373,20 @@ static int | |||
379 | ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, | 373 | ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, |
380 | EC_KEY *eckey) | 374 | EC_KEY *eckey) |
381 | { | 375 | { |
382 | int ret = -1, i; | 376 | BN_CTX *ctx; |
383 | BN_CTX *ctx; | 377 | BIGNUM *order, *u1, *u2, *m, *X; |
384 | BIGNUM *order, *u1, *u2, *m, *X; | ||
385 | EC_POINT *point = NULL; | 378 | EC_POINT *point = NULL; |
386 | const EC_GROUP *group; | 379 | const EC_GROUP *group; |
387 | const EC_POINT *pub_key; | 380 | const EC_POINT *pub_key; |
381 | int order_bits, ret = -1; | ||
388 | 382 | ||
389 | /* check input values */ | ||
390 | if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || | 383 | if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || |
391 | (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { | 384 | (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { |
392 | ECDSAerror(ECDSA_R_MISSING_PARAMETERS); | 385 | ECDSAerror(ECDSA_R_MISSING_PARAMETERS); |
393 | return -1; | 386 | return -1; |
394 | } | 387 | } |
395 | 388 | ||
396 | ctx = BN_CTX_new(); | 389 | if ((ctx = BN_CTX_new()) == NULL) { |
397 | if (!ctx) { | ||
398 | ECDSAerror(ERR_R_MALLOC_FAILURE); | 390 | ECDSAerror(ERR_R_MALLOC_FAILURE); |
399 | return -1; | 391 | return -1; |
400 | } | 392 | } |
@@ -404,7 +396,7 @@ ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, | |||
404 | u2 = BN_CTX_get(ctx); | 396 | u2 = BN_CTX_get(ctx); |
405 | m = BN_CTX_get(ctx); | 397 | m = BN_CTX_get(ctx); |
406 | X = BN_CTX_get(ctx); | 398 | X = BN_CTX_get(ctx); |
407 | if (!X) { | 399 | if (X == NULL) { |
408 | ECDSAerror(ERR_R_BN_LIB); | 400 | ECDSAerror(ERR_R_BN_LIB); |
409 | goto err; | 401 | goto err; |
410 | } | 402 | } |
@@ -414,43 +406,46 @@ ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, | |||
414 | goto err; | 406 | goto err; |
415 | } | 407 | } |
416 | 408 | ||
417 | if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || | 409 | /* Verify that r and s are in the range [1, order-1]. */ |
418 | BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || | 410 | if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || |
419 | BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { | 411 | BN_ucmp(sig->r, order) >= 0 || |
412 | BN_is_zero(sig->s) || BN_is_negative(sig->s) || | ||
413 | BN_ucmp(sig->s, order) >= 0) { | ||
420 | ECDSAerror(ECDSA_R_BAD_SIGNATURE); | 414 | ECDSAerror(ECDSA_R_BAD_SIGNATURE); |
421 | ret = 0; /* signature is invalid */ | 415 | ret = 0; |
422 | goto err; | ||
423 | } | ||
424 | /* calculate tmp1 = inv(S) mod order */ | ||
425 | if (!BN_mod_inverse_ct(u2, sig->s, order, ctx)) { | ||
426 | ECDSAerror(ERR_R_BN_LIB); | ||
427 | goto err; | 416 | goto err; |
428 | } | 417 | } |
429 | /* digest -> m */ | 418 | |
430 | i = BN_num_bits(order); | ||
431 | /* Truncate digest if it is too long: first truncate whole bytes. */ | 419 | /* Truncate digest if it is too long: first truncate whole bytes. */ |
432 | if (8 * dgst_len > i) | 420 | order_bits = BN_num_bits(order); |
433 | dgst_len = (i + 7)/8; | 421 | if (8 * dgst_len > order_bits) |
422 | dgst_len = (order_bits + 7) / 8; | ||
434 | if (!BN_bin2bn(dgst, dgst_len, m)) { | 423 | if (!BN_bin2bn(dgst, dgst_len, m)) { |
435 | ECDSAerror(ERR_R_BN_LIB); | 424 | ECDSAerror(ERR_R_BN_LIB); |
436 | goto err; | 425 | goto err; |
437 | } | 426 | } |
438 | /* If it is still too long, truncate the remaining bits with a shift. */ | 427 | /* If it is still too long, truncate the remaining bits with a shift. */ |
439 | if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { | 428 | if (8 * dgst_len > order_bits) { |
429 | if (!BN_rshift(m, m, 8 - (order_bits & 0x7))) { | ||
430 | ECDSAerror(ERR_R_BN_LIB); | ||
431 | goto err; | ||
432 | } | ||
433 | } | ||
434 | |||
435 | if (!BN_mod_inverse_ct(u2, sig->s, order, ctx)) { /* w = inv(s) */ | ||
440 | ECDSAerror(ERR_R_BN_LIB); | 436 | ECDSAerror(ERR_R_BN_LIB); |
441 | goto err; | 437 | goto err; |
442 | } | 438 | } |
443 | /* u1 = m * tmp mod order */ | 439 | if (!BN_mod_mul(u1, m, u2, order, ctx)) { /* u1 = mw */ |
444 | if (!BN_mod_mul(u1, m, u2, order, ctx)) { | ||
445 | ECDSAerror(ERR_R_BN_LIB); | 440 | ECDSAerror(ERR_R_BN_LIB); |
446 | goto err; | 441 | goto err; |
447 | } | 442 | } |
448 | /* u2 = r * w mod q */ | 443 | if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { /* u2 = rw */ |
449 | if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { | ||
450 | ECDSAerror(ERR_R_BN_LIB); | 444 | ECDSAerror(ERR_R_BN_LIB); |
451 | goto err; | 445 | goto err; |
452 | } | 446 | } |
453 | 447 | ||
448 | /* Compute the x-coordinate of G * u1 + pub_key * u2. */ | ||
454 | if ((point = EC_POINT_new(group)) == NULL) { | 449 | if ((point = EC_POINT_new(group)) == NULL) { |
455 | ECDSAerror(ERR_R_MALLOC_FAILURE); | 450 | ECDSAerror(ERR_R_MALLOC_FAILURE); |
456 | goto err; | 451 | goto err; |
@@ -461,16 +456,16 @@ ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, | |||
461 | } | 456 | } |
462 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == | 457 | if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == |
463 | NID_X9_62_prime_field) { | 458 | NID_X9_62_prime_field) { |
464 | if (!EC_POINT_get_affine_coordinates_GFp(group, | 459 | if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, |
465 | point, X, NULL, ctx)) { | 460 | ctx)) { |
466 | ECDSAerror(ERR_R_EC_LIB); | 461 | ECDSAerror(ERR_R_EC_LIB); |
467 | goto err; | 462 | goto err; |
468 | } | 463 | } |
469 | } | 464 | } |
470 | #ifndef OPENSSL_NO_EC2M | 465 | #ifndef OPENSSL_NO_EC2M |
471 | else { /* NID_X9_62_characteristic_two_field */ | 466 | else { /* NID_X9_62_characteristic_two_field */ |
472 | if (!EC_POINT_get_affine_coordinates_GF2m(group, | 467 | if (!EC_POINT_get_affine_coordinates_GF2m(group, point, X, NULL, |
473 | point, X, NULL, ctx)) { | 468 | ctx)) { |
474 | ECDSAerror(ERR_R_EC_LIB); | 469 | ECDSAerror(ERR_R_EC_LIB); |
475 | goto err; | 470 | goto err; |
476 | } | 471 | } |
@@ -481,7 +476,7 @@ ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, | |||
481 | goto err; | 476 | goto err; |
482 | } | 477 | } |
483 | 478 | ||
484 | /* If the signature is correct, then u1 is equal to sig->r. */ | 479 | /* If the signature is correct, the x-coordinate is equal to sig->r. */ |
485 | ret = (BN_ucmp(u1, sig->r) == 0); | 480 | ret = (BN_ucmp(u1, sig->r) == 0); |
486 | 481 | ||
487 | err: | 482 | err: |