diff options
Diffstat (limited to 'src/regress/lib')
| -rw-r--r-- | src/regress/lib/libcrypto/bn/bn_mod_exp_zero.c | 204 |
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 | |||
| 181 | static 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 | |||
| 200 | static int | ||
| 201 | generate_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 | |||
| 213 | static int | ||
| 214 | generate_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 | |||
| 260 | static void | ||
| 261 | dump_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 | |||
| 280 | static int | ||
| 281 | test_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 | |||
| 313 | static int | ||
| 314 | bn_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 | |||
| 341 | static int | ||
| 342 | run_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 | |||
| 179 | int | 378 | int |
| 180 | main(void) | 379 | main(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 | } |
