Skip to content

Commit 734bb73

Browse files
author
tb
committed
Rewrite the tests that various modular exponentiation functions
compute a^0 = 0 (mod 1) for all a from scratch.
1 parent b62b5fd commit 734bb73

File tree

2 files changed

+189
-148
lines changed

2 files changed

+189
-148
lines changed

src/regress/lib/libcrypto/bn/bn_mod_exp.c

Lines changed: 2 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: bn_mod_exp.c,v 1.1 2022/12/01 21:21:51 tb Exp $ */
1+
/* $OpenBSD: bn_mod_exp.c,v 1.2 2022/12/02 17:33:38 tb Exp $ */
22
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
33
* All rights reserved.
44
*
@@ -64,153 +64,10 @@
6464
#include <openssl/bn.h>
6565
#include <openssl/err.h>
6666

67-
int BN_mod_exp_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
68-
const BIGNUM *m, BN_CTX *ctx);
69-
int BN_mod_exp_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
70-
const BIGNUM *m, BN_CTX *ctx);
71-
int BN_mod_exp_mont_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
72-
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
73-
int BN_mod_exp_mont_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
74-
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
67+
#include "bn_local.h"
7568

7669
#define NUM_BITS (BN_BITS*2)
7770

78-
/*
79-
* Test that r == 0 in test_exp_mod_zero(). Returns one on success,
80-
* returns zero and prints debug output otherwise.
81-
*/
82-
static int
83-
a_is_zero_mod_one(const char *method, const BIGNUM *r, const BIGNUM *a)
84-
{
85-
if (!BN_is_zero(r)) {
86-
fprintf(stderr, "%s failed:\n", method);
87-
fprintf(stderr, "a ** 0 mod 1 = r (should be 0)\n");
88-
fprintf(stderr, "a = ");
89-
BN_print_fp(stderr, a);
90-
fprintf(stderr, "\nr = ");
91-
BN_print_fp(stderr, r);
92-
fprintf(stderr, "\n");
93-
return 0;
94-
}
95-
return 1;
96-
}
97-
98-
/*
99-
* test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success.
100-
*/
101-
static int
102-
test_exp_mod_zero(void)
103-
{
104-
BIGNUM *a = NULL, *p = NULL, *m = NULL, *r = NULL;
105-
BN_ULONG one_word = 1;
106-
BN_CTX *ctx;
107-
int ret = 1, failed = 0;
108-
109-
if ((ctx = BN_CTX_new()) == NULL)
110-
goto err;
111-
if ((m = BN_new()) == NULL)
112-
goto err;
113-
if (!BN_one(m))
114-
goto err;
115-
116-
if ((a = BN_new()) == NULL)
117-
goto err;
118-
if (!BN_one(a))
119-
goto err;
120-
121-
if ((p = BN_new()) == NULL)
122-
goto err;
123-
BN_zero(p);
124-
125-
if ((r = BN_new()) == NULL)
126-
goto err;
127-
128-
if (!BN_rand(a, 1024, 0, 0))
129-
goto err;
130-
131-
if (!BN_mod_exp(r, a, p, m, ctx))
132-
goto err;
133-
134-
if (!a_is_zero_mod_one("BN_mod_exp", r, a))
135-
failed = 1;
136-
137-
if (!BN_mod_exp_ct(r, a, p, m, ctx))
138-
goto err;
139-
140-
if (!a_is_zero_mod_one("BN_mod_exp_ct", r, a))
141-
failed = 1;
142-
143-
if (!BN_mod_exp_nonct(r, a, p, m, ctx))
144-
goto err;
145-
146-
if (!a_is_zero_mod_one("BN_mod_exp_nonct", r, a))
147-
failed = 1;
148-
149-
if (!BN_mod_exp_recp(r, a, p, m, ctx))
150-
goto err;
151-
152-
if (!a_is_zero_mod_one("BN_mod_exp_recp", r, a))
153-
failed = 1;
154-
155-
if (!BN_mod_exp_simple(r, a, p, m, ctx))
156-
goto err;
157-
158-
if (!a_is_zero_mod_one("BN_mod_exp_simple", r, a))
159-
failed = 1;
160-
161-
if (!BN_mod_exp_mont(r, a, p, m, ctx, NULL))
162-
goto err;
163-
164-
if (!a_is_zero_mod_one("BN_mod_exp_mont", r, a))
165-
failed = 1;
166-
167-
if (!BN_mod_exp_mont_ct(r, a, p, m, ctx, NULL))
168-
goto err;
169-
170-
if (!a_is_zero_mod_one("BN_mod_exp_mont_ct", r, a))
171-
failed = 1;
172-
173-
if (!BN_mod_exp_mont_nonct(r, a, p, m, ctx, NULL))
174-
goto err;
175-
176-
if (!a_is_zero_mod_one("BN_mod_exp_mont_nonct", r, a))
177-
failed = 1;
178-
179-
if (!BN_mod_exp_mont_consttime(r, a, p, m, ctx, NULL)) {
180-
goto err;
181-
}
182-
183-
if (!a_is_zero_mod_one("BN_mod_exp_mont_consttime", r, a))
184-
failed = 1;
185-
186-
/*
187-
* A different codepath exists for single word multiplication
188-
* in non-constant-time only.
189-
*/
190-
if (!BN_mod_exp_mont_word(r, one_word, p, m, ctx, NULL))
191-
goto err;
192-
193-
if (!BN_is_zero(r)) {
194-
fprintf(stderr, "BN_mod_exp_mont_word failed:\n");
195-
fprintf(stderr, "1 ** 0 mod 1 = r (should be 0)\n");
196-
fprintf(stderr, "r = ");
197-
BN_print_fp(stderr, r);
198-
fprintf(stderr, "\n");
199-
return 0;
200-
}
201-
202-
ret = failed;
203-
204-
err:
205-
BN_free(r);
206-
BN_free(a);
207-
BN_free(p);
208-
BN_free(m);
209-
BN_CTX_free(ctx);
210-
211-
return ret;
212-
}
213-
21471
int
21572
main(int argc, char *argv[])
21673
{
@@ -346,9 +203,6 @@ main(int argc, char *argv[])
346203
CRYPTO_mem_leaks(out);
347204
BIO_free(out);
348205

349-
if (test_exp_mod_zero() != 0)
350-
goto err;
351-
352206
return (0);
353207

354208
err:
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/* $OpenBSD: bn_mod_exp_zero.c,v 1.1 2022/12/02 17:33:38 tb Exp $ */
2+
3+
/*
4+
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
5+
*
6+
* Permission to use, copy, modify, and distribute this software for any
7+
* purpose with or without fee is hereby granted, provided that the above
8+
* copyright notice and this permission notice appear in all copies.
9+
*
10+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17+
*/
18+
19+
#include <stdio.h>
20+
#include <err.h>
21+
22+
#include <openssl/bn.h>
23+
#include <openssl/err.h>
24+
25+
#include "bn_local.h"
26+
27+
#define INIT_MOD_EXP_FN(f) { .name = #f, .mod_exp_fn = (f), }
28+
#define INIT_MOD_EXP_MONT_FN(f) { .name = #f, .mod_exp_mont_fn = (f), }
29+
30+
static const struct mod_exp_zero_test {
31+
const char *name;
32+
int (*mod_exp_fn)(BIGNUM *,const BIGNUM *, const BIGNUM *,
33+
const BIGNUM *, BN_CTX *);
34+
int (*mod_exp_mont_fn)(BIGNUM *,const BIGNUM *, const BIGNUM *,
35+
const BIGNUM *, BN_CTX *, BN_MONT_CTX *);
36+
} mod_exp_zero_test_data[] = {
37+
INIT_MOD_EXP_FN(BN_mod_exp),
38+
INIT_MOD_EXP_FN(BN_mod_exp_ct),
39+
INIT_MOD_EXP_FN(BN_mod_exp_nonct),
40+
INIT_MOD_EXP_FN(BN_mod_exp_recp),
41+
INIT_MOD_EXP_FN(BN_mod_exp_simple),
42+
INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont),
43+
INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont_ct),
44+
INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont_consttime),
45+
INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont_nonct),
46+
};
47+
48+
#define N_MOD_EXP_ZERO_TESTS \
49+
(sizeof(mod_exp_zero_test_data) / sizeof(mod_exp_zero_test_data[0]))
50+
51+
static void
52+
print_failure(const BIGNUM *result, const BIGNUM *a, const char *name)
53+
{
54+
fprintf(stderr, "%s test failed for a = ", name);
55+
BN_print_fp(stderr, a);
56+
fprintf(stderr, "\nwant 0, got ");
57+
BN_print_fp(stderr, result);
58+
fprintf(stderr, "\n");
59+
}
60+
61+
static int
62+
bn_mod_exp_zero_test(const struct mod_exp_zero_test *test, BN_CTX *ctx,
63+
int use_random)
64+
{
65+
const BIGNUM *one;
66+
BIGNUM *a, *p, *result;
67+
int failed = 1;
68+
69+
BN_CTX_start(ctx);
70+
71+
if ((a = BN_CTX_get(ctx)) == NULL)
72+
errx(1, "BN_CTX_get");
73+
if ((p = BN_CTX_get(ctx)) == NULL)
74+
errx(1, "BN_CTX_get");
75+
if ((result = BN_CTX_get(ctx)) == NULL)
76+
errx(1, "BN_CTX_get");
77+
78+
one = BN_value_one();
79+
BN_zero(a);
80+
BN_zero(p);
81+
82+
if (use_random) {
83+
if (!BN_rand(a, 1024, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
84+
errx(1, "BN_rand");
85+
}
86+
87+
if (test->mod_exp_fn != NULL) {
88+
if (!test->mod_exp_fn(result, a, p, one, ctx)) {
89+
fprintf(stderr, "%s failed\n", test->name);
90+
ERR_print_errors_fp(stderr);
91+
goto err;
92+
}
93+
} else {
94+
if (!test->mod_exp_mont_fn(result, a, p, one, ctx, NULL)) {
95+
fprintf(stderr, "%s failed\n", test->name);
96+
ERR_print_errors_fp(stderr);
97+
goto err;
98+
}
99+
}
100+
101+
if (!BN_is_zero(result)) {
102+
print_failure(result, a, test->name);
103+
goto err;
104+
}
105+
106+
failed = 0;
107+
108+
err:
109+
BN_CTX_end(ctx);
110+
111+
return failed;
112+
}
113+
114+
static int
115+
bn_mod_exp_zero_word_test(BN_CTX *ctx)
116+
{
117+
const char *name = "BN_mod_exp_mont_word";
118+
const BIGNUM *one;
119+
BIGNUM *p, *result;
120+
int failed = 1;
121+
122+
BN_CTX_start(ctx);
123+
124+
if ((p = BN_CTX_get(ctx)) == NULL)
125+
errx(1, "BN_CTX_get");
126+
if ((result = BN_CTX_get(ctx)) == NULL)
127+
errx(1, "BN_CTX_get");
128+
129+
one = BN_value_one();
130+
BN_zero(p);
131+
132+
if (!BN_mod_exp_mont_word(result, 1, p, one, ctx, NULL)) {
133+
fprintf(stderr, "%s failed\n", name);
134+
ERR_print_errors_fp(stderr);
135+
goto err;
136+
}
137+
138+
if (!BN_is_zero(result)) {
139+
print_failure(result, one, name);
140+
goto err;
141+
}
142+
143+
failed = 0;
144+
145+
err:
146+
BN_CTX_end(ctx);
147+
148+
return failed;
149+
}
150+
151+
static int
152+
run_bn_mod_exp_zero_tests(void)
153+
{
154+
BN_CTX *ctx;
155+
size_t i;
156+
int use_random;
157+
int failed = 0;
158+
159+
if ((ctx = BN_CTX_new()) == NULL)
160+
errx(1, "BN_CTX_new");
161+
162+
use_random = 1;
163+
for (i = 0; i < N_MOD_EXP_ZERO_TESTS; i++)
164+
failed |= bn_mod_exp_zero_test(&mod_exp_zero_test_data[i], ctx,
165+
use_random);
166+
167+
use_random = 0;
168+
for (i = 0; i < N_MOD_EXP_ZERO_TESTS; i++)
169+
failed |= bn_mod_exp_zero_test(&mod_exp_zero_test_data[i], ctx,
170+
use_random);
171+
172+
failed |= bn_mod_exp_zero_word_test(ctx);
173+
174+
BN_CTX_free(ctx);
175+
176+
return failed;
177+
}
178+
179+
int
180+
main(void)
181+
{
182+
int failed = 0;
183+
184+
failed |= run_bn_mod_exp_zero_tests();
185+
186+
return failed;
187+
}

0 commit comments

Comments
 (0)