diff options
author | tb <> | 2023-06-02 17:15:30 +0000 |
---|---|---|
committer | tb <> | 2023-06-02 17:15:30 +0000 |
commit | 74b7c36772c9b29f9523bafec5ccaf81245d37ba (patch) | |
tree | f043b7261800ea529ad2ae4a8fdf8af2a680e927 | |
parent | 2b97cf7e3d42610c403a60d91ae66bfa39bedd26 (diff) | |
download | openbsd-74b7c36772c9b29f9523bafec5ccaf81245d37ba.tar.gz openbsd-74b7c36772c9b29f9523bafec5ccaf81245d37ba.tar.bz2 openbsd-74b7c36772c9b29f9523bafec5ccaf81245d37ba.zip |
Fix variable reuse in BN_mod_inverse()
The somewhat strange calculation m = a^{-1} (mod m) can return 0. This
breaks because of BN_nnmod() having delicate semantics of which variable
can be reused. BN_nnmod(a, a, m, ctx) works and the library relies on that.
Here, the code ends up doing BN_nnmod(m, a, m, ctx) and this doesn't work.
If the result of the initial BN_mod() is negative, then BN_nnmod() will
return 0.
Problem reported by Guido Vranken in
https://github.com/openssl/openssl/issues/21110
This code is well covered by regress, but it does not currently have
explicit test coverage. Such will be added soon.
ok beck jsing
-rw-r--r-- | src/lib/libcrypto/bn/bn_gcd.c | 36 |
1 files changed, 15 insertions, 21 deletions
diff --git a/src/lib/libcrypto/bn/bn_gcd.c b/src/lib/libcrypto/bn/bn_gcd.c index c44b933260..6b3d8a3cb9 100644 --- a/src/lib/libcrypto/bn/bn_gcd.c +++ b/src/lib/libcrypto/bn/bn_gcd.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bn_gcd.c,v 1.27 2023/04/09 18:38:59 tb Exp $ */ | 1 | /* $OpenBSD: bn_gcd.c,v 1.28 2023/06/02 17:15:30 tb Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -497,19 +497,16 @@ BN_mod_inverse_no_branch(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, | |||
497 | } | 497 | } |
498 | /* Now Y*a == A (mod |n|). */ | 498 | /* Now Y*a == A (mod |n|). */ |
499 | 499 | ||
500 | if (BN_is_one(A)) { | 500 | if (!BN_is_one(A)) { |
501 | /* Y*a == 1 (mod |n|) */ | ||
502 | if (!Y->neg && BN_ucmp(Y, n) < 0) { | ||
503 | if (!bn_copy(R, Y)) | ||
504 | goto err; | ||
505 | } else { | ||
506 | if (!BN_nnmod(R, Y, n, ctx)) | ||
507 | goto err; | ||
508 | } | ||
509 | } else { | ||
510 | BNerror(BN_R_NO_INVERSE); | 501 | BNerror(BN_R_NO_INVERSE); |
511 | goto err; | 502 | goto err; |
512 | } | 503 | } |
504 | |||
505 | if (!BN_nnmod(Y, Y, n, ctx)) | ||
506 | goto err; | ||
507 | if (!bn_copy(R, Y)) | ||
508 | goto err; | ||
509 | |||
513 | ret = R; | 510 | ret = R; |
514 | 511 | ||
515 | err: | 512 | err: |
@@ -785,19 +782,16 @@ BN_mod_inverse_internal(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ct | |||
785 | } | 782 | } |
786 | /* Now Y*a == A (mod |n|). */ | 783 | /* Now Y*a == A (mod |n|). */ |
787 | 784 | ||
788 | if (BN_is_one(A)) { | 785 | if (!BN_is_one(A)) { |
789 | /* Y*a == 1 (mod |n|) */ | ||
790 | if (!Y->neg && BN_ucmp(Y, n) < 0) { | ||
791 | if (!bn_copy(R, Y)) | ||
792 | goto err; | ||
793 | } else { | ||
794 | if (!BN_nnmod(R, Y,n, ctx)) | ||
795 | goto err; | ||
796 | } | ||
797 | } else { | ||
798 | BNerror(BN_R_NO_INVERSE); | 786 | BNerror(BN_R_NO_INVERSE); |
799 | goto err; | 787 | goto err; |
800 | } | 788 | } |
789 | |||
790 | if (!BN_nnmod(Y, Y, n, ctx)) | ||
791 | goto err; | ||
792 | if (!bn_copy(R, Y)) | ||
793 | goto err; | ||
794 | |||
801 | ret = R; | 795 | ret = R; |
802 | 796 | ||
803 | err: | 797 | err: |