Skip to content

Commit

Permalink
bn: Properly error out if aliasing return value with modulus
Browse files Browse the repository at this point in the history
Test case amended from code initially written by Bernd Edlinger.

Fixes #21110

Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
(Merged from #22421)

(cherry picked from commit af0025f)
  • Loading branch information
t8m authored and hlandau committed Oct 26, 2023
1 parent f0d88b4 commit 5cf554e
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 1 deletion.
21 changes: 21 additions & 0 deletions crypto/bn/bn_exp.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,14 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
wstart = bits - 1; /* The top bit of the window */
wend = 0; /* The bottom bit of the window */

if (r == p) {
BIGNUM *p_dup = BN_CTX_get(ctx);

if (p_dup == NULL || BN_copy(p_dup, p) == NULL)
goto err;
p = p_dup;
}

if (!BN_one(r))
goto err;

Expand Down Expand Up @@ -1317,6 +1325,11 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
return 0;
}

if (r == m) {
ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}

bits = BN_num_bits(p);
if (bits == 0) {
/* x**0 mod 1, or x**0 mod -1 is still zero. */
Expand Down Expand Up @@ -1362,6 +1375,14 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
wstart = bits - 1; /* The top bit of the window */
wend = 0; /* The bottom bit of the window */

if (r == p) {
BIGNUM *p_dup = BN_CTX_get(ctx);

if (p_dup == NULL || BN_copy(p_dup, p) == NULL)
goto err;
p = p_dup;
}

if (!BN_one(r))
goto err;

Expand Down
10 changes: 10 additions & 0 deletions crypto/bn/bn_mod.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
* always holds)
*/

if (r == d) {
ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}

if (!(BN_mod(r, m, d, ctx)))
return 0;
if (!r->neg)
Expand Down Expand Up @@ -186,6 +191,11 @@ int bn_mod_sub_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *m)
{
if (r == m) {
ERR_raise(ERR_LIB_BN, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}

if (!BN_sub(r, a, b))
return 0;
if (r->neg)
Expand Down
5 changes: 5 additions & 0 deletions doc/man3/BN_add.pod
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ temporary variables; see L<BN_CTX_new(3)>.
Unless noted otherwise, the result B<BIGNUM> must be different from
the arguments.

=head1 NOTES

For modular operations such as BN_nnmod() or BN_mod_exp() it is an error
to use the same B<BIGNUM> object for the modulus as for the output.

=head1 RETURN VALUES

The BN_mod_sqrt() returns the result (possibly incorrect if I<p> is
Expand Down
6 changes: 5 additions & 1 deletion doc/man3/BN_mod_inverse.pod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ places the result in B<r> (C<(a*r)%n==1>). If B<r> is NULL,
a new B<BIGNUM> is created.

B<ctx> is a previously allocated B<BN_CTX> used for temporary
variables. B<r> may be the same B<BIGNUM> as B<a> or B<n>.
variables. B<r> may be the same B<BIGNUM> as B<a>.

=head1 NOTES

It is an error to use the same B<BIGNUM> as B<n>.

=head1 RETURN VALUES

Expand Down
104 changes: 104 additions & 0 deletions test/bntest.c
Original file line number Diff line number Diff line change
Expand Up @@ -2927,6 +2927,108 @@ static int test_mod_exp2_mont(void)
return res;
}

static int test_mod_inverse(void)
{
int res = 0;
char *str = NULL;
BIGNUM *a = NULL;
BIGNUM *b = NULL;
BIGNUM *r = NULL;

if (!TEST_true(BN_dec2bn(&a, "5193817943")))
goto err;
if (!TEST_true(BN_dec2bn(&b, "3259122431")))
goto err;
if (!TEST_ptr(r = BN_new()))
goto err;
if (!TEST_ptr_eq(BN_mod_inverse(r, a, b, ctx), r))
goto err;
if (!TEST_ptr_ne(str = BN_bn2dec(r), NULL))
goto err;
if (!TEST_int_eq(strcmp(str, "2609653924"), 0))
goto err;

/* Note that this aliases the result with the modulus. */
if (!TEST_ptr_null(BN_mod_inverse(b, a, b, ctx)))
goto err;

res = 1;

err:
BN_free(a);
BN_free(b);
BN_free(r);
OPENSSL_free(str);
return res;
}

static int test_mod_exp_alias(int idx)
{
int res = 0;
char *str = NULL;
BIGNUM *a = NULL;
BIGNUM *b = NULL;
BIGNUM *c = NULL;
BIGNUM *r = NULL;

if (!TEST_true(BN_dec2bn(&a, "15")))
goto err;
if (!TEST_true(BN_dec2bn(&b, "10")))
goto err;
if (!TEST_true(BN_dec2bn(&c, "39")))
goto err;
if (!TEST_ptr(r = BN_new()))
goto err;

if (!TEST_int_eq((idx == 0 ? BN_mod_exp_simple
: BN_mod_exp_recp)(r, a, b, c, ctx), 1))
goto err;
if (!TEST_ptr_ne(str = BN_bn2dec(r), NULL))
goto err;
if (!TEST_str_eq(str, "36"))
goto err;

OPENSSL_free(str);
str = NULL;

BN_copy(r, b);

/* Aliasing with exponent must work. */
if (!TEST_int_eq((idx == 0 ? BN_mod_exp_simple
: BN_mod_exp_recp)(r, a, r, c, ctx), 1))
goto err;
if (!TEST_ptr_ne(str = BN_bn2dec(r), NULL))
goto err;
if (!TEST_str_eq(str, "36"))
goto err;

OPENSSL_free(str);
str = NULL;

/* Aliasing with modulus should return failure for the simple call. */
if (idx == 0) {
if (!TEST_int_eq(BN_mod_exp_simple(c, a, b, c, ctx), 0))
goto err;
} else {
if (!TEST_int_eq(BN_mod_exp_recp(c, a, b, c, ctx), 1))
goto err;
if (!TEST_ptr_ne(str = BN_bn2dec(c), NULL))
goto err;
if (!TEST_str_eq(str, "36"))
goto err;
}

res = 1;

err:
BN_free(a);
BN_free(b);
BN_free(c);
BN_free(r);
OPENSSL_free(str);
return res;
}

static int file_test_run(STANZA *s)
{
static const FILETEST filetests[] = {
Expand Down Expand Up @@ -3036,6 +3138,8 @@ int setup_tests(void)
ADD_ALL_TESTS(test_signed_mod_replace_ab, OSSL_NELEM(signed_mod_tests));
ADD_ALL_TESTS(test_signed_mod_replace_ba, OSSL_NELEM(signed_mod_tests));
ADD_TEST(test_mod);
ADD_TEST(test_mod_inverse);
ADD_ALL_TESTS(test_mod_exp_alias, 2);
ADD_TEST(test_modexp_mont5);
ADD_TEST(test_kronecker);
ADD_TEST(test_rand);
Expand Down

0 comments on commit 5cf554e

Please sign in to comment.