Skip to content

Commit

Permalink
Make BN_mod_inverse() deal with repeated arguments
Browse files Browse the repository at this point in the history
BN_nnmod() can deal with the situation that the first and the second
arguments are the same, but it cannot deal with the first and the
second argument being equal. In that situation, if BN_mod(x, y, x, ctx)
results in a negative x, then the result of BN_nnmod() is zero. This
breaks the strange BN_mod_inverse(m, a, m, ctx).

Reported by Guido Vranken in
openssl/openssl#21110

Change-Id: I8584720660f214f172b3b33716a5e3b29e8f2fd8
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60365
Reviewed-by: Bob Beck <bbe@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
  • Loading branch information
botovq authored and Boringssl LUCI CQ committed Jun 2, 2023
1 parent e106b53 commit b034104
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 6 deletions.
8 changes: 8 additions & 0 deletions crypto/fipsmodule/bn/bn_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,14 @@ static void TestModInv(BIGNUMFileTest *t, BN_CTX *ctx) {
bn_mod_inverse_consttime(ret.get(), &no_inverse, a.get(), m.get(), ctx));
EXPECT_BIGNUMS_EQUAL("inv(A) (mod M) (constant-time)", mod_inv.get(),
ret.get());

ASSERT_TRUE(BN_copy(ret.get(), m.get()));
ASSERT_TRUE(BN_mod_inverse(ret.get(), a.get(), ret.get(), ctx));
EXPECT_BIGNUMS_EQUAL("inv(A) (mod M) (ret == m)", mod_inv.get(), ret.get());

ASSERT_TRUE(BN_copy(ret.get(), a.get()));
ASSERT_TRUE(BN_mod_inverse(ret.get(), ret.get(), m.get(), ctx));
EXPECT_BIGNUMS_EQUAL("inv(A) (mod M) (ret == a)", mod_inv.get(), ret.get());
}

static void TestGCD(BIGNUMFileTest *t, BN_CTX *ctx) {
Expand Down
11 changes: 5 additions & 6 deletions crypto/fipsmodule/bn/gcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,15 +263,14 @@ int BN_mod_inverse_odd(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
// Now Y*a == A (mod |n|).

// Y*a == 1 (mod |n|)
if (!Y->neg && BN_ucmp(Y, n) < 0) {
if (!BN_copy(R, Y)) {
goto err;
}
} else {
if (!BN_nnmod(R, Y, n, ctx)) {
if (Y->neg || BN_ucmp(Y, n) >= 0) {
if (!BN_nnmod(Y, Y, n, ctx)) {
goto err;
}
}
if (!BN_copy(R, Y)) {
goto err;
}

ret = 1;

Expand Down

0 comments on commit b034104

Please sign in to comment.