summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2023-06-02 17:15:30 +0000
committertb <>2023-06-02 17:15:30 +0000
commit74b7c36772c9b29f9523bafec5ccaf81245d37ba (patch)
treef043b7261800ea529ad2ae4a8fdf8af2a680e927
parent2b97cf7e3d42610c403a60d91ae66bfa39bedd26 (diff)
downloadopenbsd-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.c36
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: