summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2023-03-18 08:55:42 +0000
committertb <>2023-03-18 08:55:42 +0000
commitac5a70a7aa4b4c24f3172ba564f529b08b329434 (patch)
treea92c4a5f00d8cf39fcfdf43c50fb46d5fff375c2
parent84f3ea7b91c095ce2c1a6e4cf4d19aca2a480e3d (diff)
downloadopenbsd-ac5a70a7aa4b4c24f3172ba564f529b08b329434.tar.gz
openbsd-ac5a70a7aa4b4c24f3172ba564f529b08b329434.tar.bz2
openbsd-ac5a70a7aa4b4c24f3172ba564f529b08b329434.zip
Reimplement a variant of the bn_mod_exp tests from scratch
This exercises the same corner cases as bn_mod_exp and a few more. With input from jsing
-rw-r--r--src/regress/lib/libcrypto/bn/bn_mod_exp_zero.c204
1 files changed, 202 insertions, 2 deletions
diff --git a/src/regress/lib/libcrypto/bn/bn_mod_exp_zero.c b/src/regress/lib/libcrypto/bn/bn_mod_exp_zero.c
index 292983e86b..23cfffc5b6 100644
--- a/src/regress/lib/libcrypto/bn/bn_mod_exp_zero.c
+++ b/src/regress/lib/libcrypto/bn/bn_mod_exp_zero.c
@@ -1,7 +1,7 @@
1/* $OpenBSD: bn_mod_exp_zero.c,v 1.2 2023/03/15 00:41:04 tb Exp $ */ 1/* $OpenBSD: bn_mod_exp_zero.c,v 1.3 2023/03/18 08:55:42 tb Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2022,2023 Theo Buehler <tb@openbsd.org>
5 * 5 *
6 * Permission to use, copy, modify, and distribute this software for any 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 7 * purpose with or without fee is hereby granted, provided that the above
@@ -176,12 +176,212 @@ run_bn_mod_exp_zero_tests(void)
176 return failed; 176 return failed;
177} 177}
178 178
179#define N_MOD_EXP_TESTS 400
180
181static const struct mod_exp_test {
182 const char *name;
183 int (*mod_exp_fn)(BIGNUM *,const BIGNUM *, const BIGNUM *,
184 const BIGNUM *, BN_CTX *);
185 int (*mod_exp_mont_fn)(BIGNUM *,const BIGNUM *, const BIGNUM *,
186 const BIGNUM *, BN_CTX *, BN_MONT_CTX *);
187} mod_exp_fn[] = {
188 INIT_MOD_EXP_FN(BN_mod_exp),
189 INIT_MOD_EXP_FN(BN_mod_exp_ct),
190 INIT_MOD_EXP_FN(BN_mod_exp_nonct),
191 INIT_MOD_EXP_FN(BN_mod_exp_recp),
192 INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont),
193 INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont_ct),
194 INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont_consttime),
195 INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont_nonct),
196};
197
198#define N_MOD_EXP_FN (sizeof(mod_exp_fn) / sizeof(mod_exp_fn[0]))
199
200static int
201generate_bn(BIGNUM *bn, int avg_bits, int deviate, int force_odd)
202{
203 int bits;
204
205 if (avg_bits <= 0 || deviate <= 0 || deviate >= avg_bits)
206 return 0;
207
208 bits = avg_bits + arc4random_uniform(deviate) - deviate;
209
210 return BN_rand(bn, bits, 0, force_odd);
211}
212
213static int
214generate_test_triple(int reduce, BIGNUM *a, BIGNUM *p, BIGNUM *m, BN_CTX *ctx)
215{
216 BIGNUM *mmodified;
217 BN_ULONG multiple;
218 int avg = 2 * BN_BITS, deviate = BN_BITS / 2;
219 int ret = 0;
220
221 if (!generate_bn(a, avg, deviate, 0))
222 return 0;
223
224 if (!generate_bn(p, avg, deviate, 0))
225 return 0;
226
227 if (!generate_bn(m, avg, deviate, 1))
228 return 0;
229
230 if (reduce)
231 return BN_mod(a, a, m, ctx);
232
233 /*
234 * Add a random multiple of m to a to test unreduced exponentiation.
235 */
236
237 BN_CTX_start(ctx);
238
239 if ((mmodified = BN_CTX_get(ctx)) == NULL)
240 goto err;
241
242 if (BN_copy(mmodified, m) == NULL)
243 goto err;
244
245 multiple = arc4random_uniform(1023) + 2;
246
247 if (!BN_mul_word(mmodified, multiple))
248 goto err;
249
250 if (!BN_add(a, a, mmodified))
251 goto err;
252
253 ret = 1;
254 err:
255 BN_CTX_end(ctx);
256
257 return ret;
258}
259
260static void
261dump_results(const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
262 const BIGNUM *got, const BIGNUM *want, const char *name)
263{
264 printf("BN_mod_exp_simple() and %s() disagree", name);
265
266 printf("\nwant: ");
267 BN_print_fp(stdout, want);
268 printf("\ngot: ");
269 BN_print_fp(stdout, got);
270
271 printf("\na: ");
272 BN_print_fp(stdout, a);
273 printf("\nb: ");
274 BN_print_fp(stdout, p);
275 printf("\nm: ");
276 BN_print_fp(stdout, m);
277 printf("\n\n");
278}
279
280static int
281test_mod_exp(const BIGNUM *want, const BIGNUM *a, const BIGNUM *p,
282 const BIGNUM *m, BN_CTX *ctx, const struct mod_exp_test *test)
283{
284 BIGNUM *got;
285 int ret = 0;
286
287 BN_CTX_start(ctx);
288
289 if ((got = BN_CTX_get(ctx)) == NULL)
290 goto err;
291
292 if (test->mod_exp_fn != NULL)
293 ret = test->mod_exp_fn(got, a, p, m, ctx);
294 else
295 ret = test->mod_exp_mont_fn(got, a, p, m, ctx, NULL);
296
297 if (!ret)
298 errx(1, "%s() failed", test->name);
299
300 if (BN_cmp(want, got) != 0) {
301 dump_results(a, p, m, want, got, test->name);
302 goto err;
303 }
304
305 ret = 1;
306
307 err:
308 BN_CTX_end(ctx);
309
310 return ret;
311}
312
313static int
314bn_mod_exp_test(int reduce, BIGNUM *want, BIGNUM *a, BIGNUM *p, BIGNUM *m,
315 BN_CTX *ctx)
316{
317 size_t i, j;
318 int failed = 0;
319
320 if (!generate_test_triple(reduce, a, p, m, ctx))
321 errx(1, "generate_test_triple");
322
323 for (i = 0; i < 4; i++) {
324 BN_set_negative(a, i & 1);
325 BN_set_negative(p, (i >> 1) & 1);
326
327 if ((BN_mod_exp_simple(want, a, p, m, ctx)) <= 0)
328 errx(1, "BN_mod_exp_simple");
329
330 for (j = 0; j < N_MOD_EXP_FN; j++) {
331 const struct mod_exp_test *test = &mod_exp_fn[j];
332
333 if (!test_mod_exp(want, a, p, m, ctx, test))
334 failed |= 1;
335 }
336 }
337
338 return failed;
339}
340
341static int
342run_bn_mod_exp_tests(void)
343{
344 BIGNUM *a, *p, *m, *want;
345 BN_CTX *ctx;
346 int i;
347 int reduce;
348 int failed = 0;
349
350 if ((ctx = BN_CTX_new()) == NULL)
351 errx(1, "BN_CTX_new");
352
353 BN_CTX_start(ctx);
354
355 if ((a = BN_CTX_get(ctx)) == NULL)
356 errx(1, "a = BN_CTX_get()");
357 if ((p = BN_CTX_get(ctx)) == NULL)
358 errx(1, "p = BN_CTX_get()");
359 if ((m = BN_CTX_get(ctx)) == NULL)
360 errx(1, "m = BN_CTX_get()");
361 if ((want = BN_CTX_get(ctx)) == NULL)
362 errx(1, "want = BN_CTX_get()");
363
364 reduce = 0;
365 for (i = 0; i < N_MOD_EXP_TESTS; i++)
366 failed |= bn_mod_exp_test(reduce, want, a, p, m, ctx);
367
368 reduce = 1;
369 for (i = 0; i < N_MOD_EXP_TESTS; i++)
370 failed |= bn_mod_exp_test(reduce, want, a, p, m, ctx);
371
372 BN_CTX_end(ctx);
373 BN_CTX_free(ctx);
374
375 return failed;
376}
377
179int 378int
180main(void) 379main(void)
181{ 380{
182 int failed = 0; 381 int failed = 0;
183 382
184 failed |= run_bn_mod_exp_zero_tests(); 383 failed |= run_bn_mod_exp_zero_tests();
384 failed |= run_bn_mod_exp_tests();
185 385
186 return failed; 386 return failed;
187} 387}