1*d1ac4eb2Sjsing /* $OpenBSD: bn_mul_div.c,v 1.7 2023/06/21 07:18:10 jsing Exp $ */
22900a9c1Sjsing /*
32900a9c1Sjsing * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
42900a9c1Sjsing *
52900a9c1Sjsing * Permission to use, copy, modify, and distribute this software for any
62900a9c1Sjsing * purpose with or without fee is hereby granted, provided that the above
72900a9c1Sjsing * copyright notice and this permission notice appear in all copies.
82900a9c1Sjsing *
92900a9c1Sjsing * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
102900a9c1Sjsing * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
112900a9c1Sjsing * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
122900a9c1Sjsing * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
132900a9c1Sjsing * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
142900a9c1Sjsing * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
152900a9c1Sjsing * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
162900a9c1Sjsing */
172900a9c1Sjsing
188d9f23acSjsing #include <sys/resource.h>
192900a9c1Sjsing #include <sys/time.h>
202900a9c1Sjsing
212900a9c1Sjsing #include <err.h>
222900a9c1Sjsing #include <signal.h>
232900a9c1Sjsing #include <stdio.h>
242900a9c1Sjsing #include <string.h>
252900a9c1Sjsing #include <time.h>
262900a9c1Sjsing #include <unistd.h>
272900a9c1Sjsing
282900a9c1Sjsing #include <openssl/bn.h>
292900a9c1Sjsing
302900a9c1Sjsing static int
benchmark_bn_div_setup(BIGNUM * a,size_t a_bits,BIGNUM * b,size_t b_bits,BIGNUM * r,BIGNUM * q)3172c289bdSjsing benchmark_bn_div_setup(BIGNUM *a, size_t a_bits, BIGNUM *b, size_t b_bits,
3272c289bdSjsing BIGNUM *r, BIGNUM *q)
3372c289bdSjsing {
3472c289bdSjsing if (!BN_rand(a, a_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
3572c289bdSjsing return 0;
3672c289bdSjsing if (!BN_rand(b, b_bits - 1, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
3772c289bdSjsing return 0;
3872c289bdSjsing if (!BN_set_bit(r, a_bits))
3972c289bdSjsing return 0;
4072c289bdSjsing if (!BN_set_bit(q, b_bits))
4172c289bdSjsing return 0;
4272c289bdSjsing
4372c289bdSjsing return 1;
4472c289bdSjsing }
4572c289bdSjsing
4672c289bdSjsing static void
benchmark_bn_div_run_once(BIGNUM * r,BIGNUM * q,BIGNUM * a,BIGNUM * b,BN_CTX * bn_ctx)4772c289bdSjsing benchmark_bn_div_run_once(BIGNUM *r, BIGNUM *q, BIGNUM *a, BIGNUM *b, BN_CTX *bn_ctx)
4872c289bdSjsing {
4972c289bdSjsing if (!BN_div(r, q, a, b, bn_ctx))
5072c289bdSjsing errx(1, "BN_div");
5172c289bdSjsing }
5272c289bdSjsing
5372c289bdSjsing static int
benchmark_bn_mul_setup(BIGNUM * a,size_t a_bits,BIGNUM * b,size_t b_bits,BIGNUM * r,BIGNUM * q)542900a9c1Sjsing benchmark_bn_mul_setup(BIGNUM *a, size_t a_bits, BIGNUM *b, size_t b_bits,
5572c289bdSjsing BIGNUM *r, BIGNUM *q)
562900a9c1Sjsing {
57a3f05336Sjsing if (!BN_rand(a, a_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
582900a9c1Sjsing return 0;
59a3f05336Sjsing if (!BN_rand(b, b_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
602900a9c1Sjsing return 0;
612900a9c1Sjsing if (!BN_set_bit(r, (a_bits + b_bits) - 1))
622900a9c1Sjsing return 0;
632900a9c1Sjsing
642900a9c1Sjsing return 1;
652900a9c1Sjsing }
662900a9c1Sjsing
672900a9c1Sjsing static void
benchmark_bn_mul_run_once(BIGNUM * r,BIGNUM * q,BIGNUM * a,BIGNUM * b,BN_CTX * bn_ctx)6872c289bdSjsing benchmark_bn_mul_run_once(BIGNUM *r, BIGNUM *q, BIGNUM *a, BIGNUM *b, BN_CTX *bn_ctx)
692900a9c1Sjsing {
702900a9c1Sjsing if (!BN_mul(r, a, b, bn_ctx))
712900a9c1Sjsing errx(1, "BN_mul");
722900a9c1Sjsing }
732900a9c1Sjsing
742900a9c1Sjsing static int
benchmark_bn_sqr_setup(BIGNUM * a,size_t a_bits,BIGNUM * b,size_t b_bits,BIGNUM * r,BIGNUM * q)752900a9c1Sjsing benchmark_bn_sqr_setup(BIGNUM *a, size_t a_bits, BIGNUM *b, size_t b_bits,
7672c289bdSjsing BIGNUM *r, BIGNUM *q)
772900a9c1Sjsing {
78a3f05336Sjsing if (!BN_rand(a, a_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
792900a9c1Sjsing return 0;
802900a9c1Sjsing if (!BN_set_bit(r, (a_bits + a_bits) - 1))
812900a9c1Sjsing return 0;
822900a9c1Sjsing
832900a9c1Sjsing return 1;
842900a9c1Sjsing }
852900a9c1Sjsing
862900a9c1Sjsing static void
benchmark_bn_sqr_run_once(BIGNUM * r,BIGNUM * q,BIGNUM * a,BIGNUM * b,BN_CTX * bn_ctx)8772c289bdSjsing benchmark_bn_sqr_run_once(BIGNUM *r, BIGNUM *q, BIGNUM *a, BIGNUM *b, BN_CTX *bn_ctx)
882900a9c1Sjsing {
892900a9c1Sjsing if (!BN_sqr(r, a, bn_ctx))
902900a9c1Sjsing errx(1, "BN_sqr");
912900a9c1Sjsing }
922900a9c1Sjsing
932900a9c1Sjsing struct benchmark {
942900a9c1Sjsing const char *desc;
9572c289bdSjsing int (*setup)(BIGNUM *, size_t, BIGNUM *, size_t, BIGNUM *, BIGNUM *);
9672c289bdSjsing void (*run_once)(BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BN_CTX *);
972900a9c1Sjsing size_t a_bits;
982900a9c1Sjsing size_t b_bits;
992900a9c1Sjsing };
1002900a9c1Sjsing
1012900a9c1Sjsing struct benchmark benchmarks[] = {
1022900a9c1Sjsing {
10372c289bdSjsing .desc = "BN_div (64 bit / 64 bit)",
10472c289bdSjsing .setup = benchmark_bn_div_setup,
10572c289bdSjsing .run_once = benchmark_bn_div_run_once,
10672c289bdSjsing .a_bits = 64,
10772c289bdSjsing .b_bits = 64,
10872c289bdSjsing },
10972c289bdSjsing {
11072c289bdSjsing .desc = "BN_div (128 bit / 128 bit)",
11172c289bdSjsing .setup = benchmark_bn_div_setup,
11272c289bdSjsing .run_once = benchmark_bn_div_run_once,
11372c289bdSjsing .a_bits = 128,
11472c289bdSjsing .b_bits = 128,
11572c289bdSjsing },
11672c289bdSjsing {
11772c289bdSjsing .desc = "BN_div (196 bit / 196 bit)",
11872c289bdSjsing .setup = benchmark_bn_div_setup,
11972c289bdSjsing .run_once = benchmark_bn_div_run_once,
12072c289bdSjsing .a_bits = 196,
12172c289bdSjsing .b_bits = 196,
12272c289bdSjsing },
12372c289bdSjsing {
12472c289bdSjsing .desc = "BN_div (256 bit / 256 bit)",
12572c289bdSjsing .setup = benchmark_bn_div_setup,
12672c289bdSjsing .run_once = benchmark_bn_div_run_once,
12772c289bdSjsing .a_bits = 256,
12872c289bdSjsing .b_bits = 256,
12972c289bdSjsing },
13072c289bdSjsing {
13172c289bdSjsing .desc = "BN_div (320 bit / 320 bit)",
13272c289bdSjsing .setup = benchmark_bn_div_setup,
13372c289bdSjsing .run_once = benchmark_bn_div_run_once,
13472c289bdSjsing .a_bits = 320,
13572c289bdSjsing .b_bits = 320,
13672c289bdSjsing },
13772c289bdSjsing {
13872c289bdSjsing .desc = "BN_div (384 bit / 384 bit)",
13972c289bdSjsing .setup = benchmark_bn_div_setup,
14072c289bdSjsing .run_once = benchmark_bn_div_run_once,
14172c289bdSjsing .a_bits = 384,
14272c289bdSjsing .b_bits = 384,
14372c289bdSjsing },
14472c289bdSjsing {
14572c289bdSjsing .desc = "BN_div (384 bit / 128 bit)",
14672c289bdSjsing .setup = benchmark_bn_div_setup,
14772c289bdSjsing .run_once = benchmark_bn_div_run_once,
14872c289bdSjsing .a_bits = 384,
14972c289bdSjsing .b_bits = 128,
15072c289bdSjsing },
15172c289bdSjsing {
15272c289bdSjsing .desc = "BN_div (448 bit / 256 bit)",
15372c289bdSjsing .setup = benchmark_bn_div_setup,
15472c289bdSjsing .run_once = benchmark_bn_div_run_once,
15572c289bdSjsing .a_bits = 448,
15672c289bdSjsing .b_bits = 256,
15772c289bdSjsing },
15872c289bdSjsing {
15972c289bdSjsing .desc = "BN_div (512 bit / 512 bit)",
16072c289bdSjsing .setup = benchmark_bn_div_setup,
16172c289bdSjsing .run_once = benchmark_bn_div_run_once,
16272c289bdSjsing .a_bits = 512,
16372c289bdSjsing .b_bits = 512,
16472c289bdSjsing },
16572c289bdSjsing {
16672c289bdSjsing .desc = "BN_div (768 bit / 256 bit)",
16772c289bdSjsing .setup = benchmark_bn_div_setup,
16872c289bdSjsing .run_once = benchmark_bn_div_run_once,
16972c289bdSjsing .a_bits = 768,
17072c289bdSjsing .b_bits = 256,
17172c289bdSjsing },
17272c289bdSjsing {
17372c289bdSjsing .desc = "BN_div (1024 bit / 128 bit)",
17472c289bdSjsing .setup = benchmark_bn_div_setup,
17572c289bdSjsing .run_once = benchmark_bn_div_run_once,
17672c289bdSjsing .a_bits = 1024,
17772c289bdSjsing .b_bits = 128,
17872c289bdSjsing },
17972c289bdSjsing {
18072c289bdSjsing .desc = "BN_div (2048 bit / 512 bit)",
18172c289bdSjsing .setup = benchmark_bn_div_setup,
18272c289bdSjsing .run_once = benchmark_bn_div_run_once,
18372c289bdSjsing .a_bits = 2048,
18472c289bdSjsing .b_bits = 128,
18572c289bdSjsing },
18672c289bdSjsing {
18772c289bdSjsing .desc = "BN_div (3072 bit / 1024 bit)",
18872c289bdSjsing .setup = benchmark_bn_div_setup,
18972c289bdSjsing .run_once = benchmark_bn_div_run_once,
19072c289bdSjsing .a_bits = 2048,
19172c289bdSjsing .b_bits = 1024,
19272c289bdSjsing },
19372c289bdSjsing {
19472c289bdSjsing .desc = "BN_div (4288 bit / 2176 bit)",
19572c289bdSjsing .setup = benchmark_bn_div_setup,
19672c289bdSjsing .run_once = benchmark_bn_div_run_once,
19772c289bdSjsing .a_bits = 2048,
19872c289bdSjsing .b_bits = 1024,
19972c289bdSjsing },
20072c289bdSjsing {
20172c289bdSjsing .desc = "BN_div (6144 bit / 2048 bit)",
20272c289bdSjsing .setup = benchmark_bn_div_setup,
20372c289bdSjsing .run_once = benchmark_bn_div_run_once,
20472c289bdSjsing .a_bits = 2048,
20572c289bdSjsing .b_bits = 1024,
20672c289bdSjsing },
20772c289bdSjsing {
20872c289bdSjsing .desc = "BN_div (16384 bit / 8192 bit)",
20972c289bdSjsing .setup = benchmark_bn_div_setup,
21072c289bdSjsing .run_once = benchmark_bn_div_run_once,
21172c289bdSjsing .a_bits = 16384,
21272c289bdSjsing .b_bits = 8192,
21372c289bdSjsing },
21472c289bdSjsing {
2152900a9c1Sjsing .desc = "BN_mul (128 bit x 128 bit)",
2162900a9c1Sjsing .setup = benchmark_bn_mul_setup,
2172900a9c1Sjsing .run_once = benchmark_bn_mul_run_once,
2182900a9c1Sjsing .a_bits = 128,
2192900a9c1Sjsing .b_bits = 128,
2202900a9c1Sjsing },
2212900a9c1Sjsing {
2222900a9c1Sjsing .desc = "BN_mul (128 bit x 256 bit)",
2232900a9c1Sjsing .setup = benchmark_bn_mul_setup,
2242900a9c1Sjsing .run_once = benchmark_bn_mul_run_once,
2252900a9c1Sjsing .a_bits = 128,
2262900a9c1Sjsing .b_bits = 256,
2272900a9c1Sjsing },
2282900a9c1Sjsing {
2292900a9c1Sjsing .desc = "BN_mul (256 bit x 256 bit)",
2302900a9c1Sjsing .setup = benchmark_bn_mul_setup,
2312900a9c1Sjsing .run_once = benchmark_bn_mul_run_once,
2322900a9c1Sjsing .a_bits = 256,
2332900a9c1Sjsing .b_bits = 256,
2342900a9c1Sjsing },
2352900a9c1Sjsing {
2362900a9c1Sjsing .desc = "BN_mul (512 bit x 512 bit)",
2372900a9c1Sjsing .setup = benchmark_bn_mul_setup,
2382900a9c1Sjsing .run_once = benchmark_bn_mul_run_once,
2392900a9c1Sjsing .a_bits = 512,
2402900a9c1Sjsing .b_bits = 512,
2412900a9c1Sjsing },
2422900a9c1Sjsing {
2432900a9c1Sjsing .desc = "BN_mul (1024 bit x 1024 bit)",
2442900a9c1Sjsing .setup = benchmark_bn_mul_setup,
2452900a9c1Sjsing .run_once = benchmark_bn_mul_run_once,
2462900a9c1Sjsing .a_bits = 1024,
2472900a9c1Sjsing .b_bits = 1024,
2482900a9c1Sjsing },
2492900a9c1Sjsing {
2502900a9c1Sjsing .desc = "BN_mul (1024 bit x 2048 bit)",
2512900a9c1Sjsing .setup = benchmark_bn_mul_setup,
2522900a9c1Sjsing .run_once = benchmark_bn_mul_run_once,
2532900a9c1Sjsing .a_bits = 1024,
2542900a9c1Sjsing .b_bits = 2048,
2552900a9c1Sjsing },
2562900a9c1Sjsing {
2572900a9c1Sjsing .desc = "BN_mul (2048 bit x 2048 bit)",
2582900a9c1Sjsing .setup = benchmark_bn_mul_setup,
2592900a9c1Sjsing .run_once = benchmark_bn_mul_run_once,
2602900a9c1Sjsing .a_bits = 2048,
2612900a9c1Sjsing .b_bits = 2048,
2622900a9c1Sjsing },
2632900a9c1Sjsing {
2642900a9c1Sjsing .desc = "BN_mul (4096 bit x 4096 bit)",
2652900a9c1Sjsing .setup = benchmark_bn_mul_setup,
2662900a9c1Sjsing .run_once = benchmark_bn_mul_run_once,
2672900a9c1Sjsing .a_bits = 4096,
2682900a9c1Sjsing .b_bits = 4096,
2692900a9c1Sjsing },
2702900a9c1Sjsing {
2712900a9c1Sjsing .desc = "BN_mul (4096 bit x 8192 bit)",
2722900a9c1Sjsing .setup = benchmark_bn_mul_setup,
2732900a9c1Sjsing .run_once = benchmark_bn_mul_run_once,
2742900a9c1Sjsing .a_bits = 4096,
2752900a9c1Sjsing .b_bits = 8192,
2762900a9c1Sjsing },
2772900a9c1Sjsing {
2782900a9c1Sjsing .desc = "BN_mul (8192 bit x 8192 bit)",
2792900a9c1Sjsing .setup = benchmark_bn_mul_setup,
2802900a9c1Sjsing .run_once = benchmark_bn_mul_run_once,
2812900a9c1Sjsing .a_bits = 8192,
2822900a9c1Sjsing .b_bits = 8192,
2832900a9c1Sjsing },
2842900a9c1Sjsing {
2852900a9c1Sjsing .desc = "BN_sqr (128 bit)",
2862900a9c1Sjsing .setup = benchmark_bn_sqr_setup,
2872900a9c1Sjsing .run_once = benchmark_bn_sqr_run_once,
2882900a9c1Sjsing .a_bits = 128,
2892900a9c1Sjsing },
2902900a9c1Sjsing {
2912900a9c1Sjsing .desc = "BN_sqr (256 bit)",
2922900a9c1Sjsing .setup = benchmark_bn_sqr_setup,
2932900a9c1Sjsing .run_once = benchmark_bn_sqr_run_once,
2942900a9c1Sjsing .a_bits = 256,
2952900a9c1Sjsing },
2962900a9c1Sjsing {
2972900a9c1Sjsing .desc = "BN_sqr (512 bit)",
2982900a9c1Sjsing .setup = benchmark_bn_sqr_setup,
2992900a9c1Sjsing .run_once = benchmark_bn_sqr_run_once,
3002900a9c1Sjsing .a_bits = 512,
3012900a9c1Sjsing },
3022900a9c1Sjsing {
3032900a9c1Sjsing .desc = "BN_sqr (1024 bit)",
3042900a9c1Sjsing .setup = benchmark_bn_sqr_setup,
3052900a9c1Sjsing .run_once = benchmark_bn_sqr_run_once,
3062900a9c1Sjsing .a_bits = 1024,
3072900a9c1Sjsing },
3082900a9c1Sjsing {
3092900a9c1Sjsing .desc = "BN_sqr (2048 bit)",
3102900a9c1Sjsing .setup = benchmark_bn_sqr_setup,
3112900a9c1Sjsing .run_once = benchmark_bn_sqr_run_once,
3122900a9c1Sjsing .a_bits = 2048,
3132900a9c1Sjsing },
3142900a9c1Sjsing {
3152900a9c1Sjsing .desc = "BN_sqr (4096 bit)",
3162900a9c1Sjsing .setup = benchmark_bn_sqr_setup,
3172900a9c1Sjsing .run_once = benchmark_bn_sqr_run_once,
3182900a9c1Sjsing .a_bits = 4096,
3192900a9c1Sjsing },
3202900a9c1Sjsing {
3212900a9c1Sjsing .desc = "BN_sqr (8192 bit)",
3222900a9c1Sjsing .setup = benchmark_bn_sqr_setup,
3232900a9c1Sjsing .run_once = benchmark_bn_sqr_run_once,
3242900a9c1Sjsing .a_bits = 8192,
3252900a9c1Sjsing },
3262900a9c1Sjsing };
3272900a9c1Sjsing
3282900a9c1Sjsing #define N_BENCHMARKS (sizeof(benchmarks) / sizeof(benchmarks[0]))
3292900a9c1Sjsing
3302900a9c1Sjsing static volatile sig_atomic_t benchmark_stop;
3312900a9c1Sjsing
3322900a9c1Sjsing static void
benchmark_sig_alarm(int sig)3332900a9c1Sjsing benchmark_sig_alarm(int sig)
3342900a9c1Sjsing {
3352900a9c1Sjsing benchmark_stop = 1;
3362900a9c1Sjsing }
3372900a9c1Sjsing
3382900a9c1Sjsing static void
benchmark_run(const struct benchmark * bm,int seconds)3392900a9c1Sjsing benchmark_run(const struct benchmark *bm, int seconds)
3402900a9c1Sjsing {
3412900a9c1Sjsing struct timespec start, end, duration;
3428d9f23acSjsing struct rusage rusage;
34372c289bdSjsing BIGNUM *a, *b, *r, *q;
3442900a9c1Sjsing BN_CTX *bn_ctx;
3452900a9c1Sjsing int i;
3462900a9c1Sjsing
3472900a9c1Sjsing signal(SIGALRM, benchmark_sig_alarm);
3482900a9c1Sjsing
3492900a9c1Sjsing if ((bn_ctx = BN_CTX_new()) == NULL)
3502900a9c1Sjsing errx(1, "BN_CTX_new");
3512900a9c1Sjsing
3522900a9c1Sjsing BN_CTX_start(bn_ctx);
3532900a9c1Sjsing
3542900a9c1Sjsing if ((a = BN_CTX_get(bn_ctx)) == NULL)
3552900a9c1Sjsing errx(1, "BN_CTX_get");
3562900a9c1Sjsing if ((b = BN_CTX_get(bn_ctx)) == NULL)
3572900a9c1Sjsing errx(1, "BN_CTX_get");
3582900a9c1Sjsing if ((r = BN_CTX_get(bn_ctx)) == NULL)
3592900a9c1Sjsing errx(1, "BN_CTX_get");
36072c289bdSjsing if ((q = BN_CTX_get(bn_ctx)) == NULL)
36172c289bdSjsing errx(1, "BN_CTX_get");
3622900a9c1Sjsing
363964a7cf0Sjsing BN_set_flags(a, BN_FLG_CONSTTIME);
364964a7cf0Sjsing BN_set_flags(b, BN_FLG_CONSTTIME);
365964a7cf0Sjsing
36672c289bdSjsing if (!bm->setup(a, bm->a_bits, b, bm->b_bits, r, q))
3672900a9c1Sjsing errx(1, "benchmark setup failed");
3682900a9c1Sjsing
3692900a9c1Sjsing benchmark_stop = 0;
3702900a9c1Sjsing i = 0;
3712900a9c1Sjsing alarm(seconds);
3722900a9c1Sjsing
3738d9f23acSjsing if (getrusage(RUSAGE_SELF, &rusage) == -1)
3748d9f23acSjsing err(1, "getrusage failed");
3758d9f23acSjsing TIMEVAL_TO_TIMESPEC(&rusage.ru_utime, &start);
3762900a9c1Sjsing
3772900a9c1Sjsing fprintf(stderr, "Benchmarking %s for %ds: ", bm->desc, seconds);
3782900a9c1Sjsing while (!benchmark_stop) {
37972c289bdSjsing bm->run_once(r, q, a, b, bn_ctx);
3802900a9c1Sjsing i++;
3812900a9c1Sjsing }
3828d9f23acSjsing if (getrusage(RUSAGE_SELF, &rusage) == -1)
3838d9f23acSjsing err(1, "getrusage failed");
3848d9f23acSjsing TIMEVAL_TO_TIMESPEC(&rusage.ru_utime, &end);
3858d9f23acSjsing
3862900a9c1Sjsing timespecsub(&end, &start, &duration);
3878d9f23acSjsing fprintf(stderr, "%d iterations in %f seconds - %llu op/s\n", i,
3888d9f23acSjsing duration.tv_sec + duration.tv_nsec / 1000000000.0,
389b2cabbc1Sjsing (uint64_t)i * 1000000000 /
3908d9f23acSjsing (duration.tv_sec * 1000000000 + duration.tv_nsec));
3912900a9c1Sjsing
3922900a9c1Sjsing BN_CTX_end(bn_ctx);
3932900a9c1Sjsing BN_CTX_free(bn_ctx);
3942900a9c1Sjsing }
3952900a9c1Sjsing
3962900a9c1Sjsing static void
benchmark_bn_mul_sqr(void)3972900a9c1Sjsing benchmark_bn_mul_sqr(void)
3982900a9c1Sjsing {
3992900a9c1Sjsing const struct benchmark *bm;
4002900a9c1Sjsing size_t i;
4012900a9c1Sjsing
4022900a9c1Sjsing for (i = 0; i < N_BENCHMARKS; i++) {
4032900a9c1Sjsing bm = &benchmarks[i];
4042900a9c1Sjsing benchmark_run(bm, 5);
4052900a9c1Sjsing }
4062900a9c1Sjsing }
4072900a9c1Sjsing
408*d1ac4eb2Sjsing static int
test_bn_sqr(void)409*d1ac4eb2Sjsing test_bn_sqr(void)
410*d1ac4eb2Sjsing {
411*d1ac4eb2Sjsing BN_CTX *bn_ctx = NULL;
412*d1ac4eb2Sjsing BIGNUM *a, *r;
413*d1ac4eb2Sjsing int failed = 1;
414*d1ac4eb2Sjsing
415*d1ac4eb2Sjsing if ((bn_ctx = BN_CTX_new()) == NULL)
416*d1ac4eb2Sjsing errx(1, "BN_CTX_new");
417*d1ac4eb2Sjsing
418*d1ac4eb2Sjsing BN_CTX_start(bn_ctx);
419*d1ac4eb2Sjsing
420*d1ac4eb2Sjsing if ((a = BN_CTX_get(bn_ctx)) == NULL)
421*d1ac4eb2Sjsing errx(1, "BN_new");
422*d1ac4eb2Sjsing if ((r = BN_CTX_get(bn_ctx)) == NULL)
423*d1ac4eb2Sjsing errx(1, "BN_new");
424*d1ac4eb2Sjsing
425*d1ac4eb2Sjsing /* Square of a new BN. */
426*d1ac4eb2Sjsing if (!BN_sqr(r, a, bn_ctx)) {
427*d1ac4eb2Sjsing fprintf(stderr, "FAIL: BN_sqr() on new BN failed\n");
428*d1ac4eb2Sjsing goto failure;
429*d1ac4eb2Sjsing }
430*d1ac4eb2Sjsing if (!BN_is_zero(r)) {
431*d1ac4eb2Sjsing fprintf(stderr, "FAIL: BN_sqr() on new BN is not zero\n");
432*d1ac4eb2Sjsing goto failure;
433*d1ac4eb2Sjsing }
434*d1ac4eb2Sjsing
435*d1ac4eb2Sjsing /* Square of BN that is explicitly set to zero. */
436*d1ac4eb2Sjsing if (!BN_set_word(a, 0)) {
437*d1ac4eb2Sjsing fprintf(stderr, "FAIL: BN_set_word(0) failed\n");
438*d1ac4eb2Sjsing goto failure;
439*d1ac4eb2Sjsing }
440*d1ac4eb2Sjsing if (!BN_sqr(r, a, bn_ctx)) {
441*d1ac4eb2Sjsing fprintf(stderr, "FAIL: BN_sqr(0) failed\n");
442*d1ac4eb2Sjsing goto failure;
443*d1ac4eb2Sjsing }
444*d1ac4eb2Sjsing if (!BN_is_zero(r)) {
445*d1ac4eb2Sjsing fprintf(stderr, "FAIL: BN_sqr(0) != 0\n");
446*d1ac4eb2Sjsing goto failure;
447*d1ac4eb2Sjsing }
448*d1ac4eb2Sjsing
449*d1ac4eb2Sjsing /* Square of BN with value one. */
450*d1ac4eb2Sjsing if (!BN_set_word(a, 1)) {
451*d1ac4eb2Sjsing fprintf(stderr, "FAIL: BN_set_word(1) failed\n");
452*d1ac4eb2Sjsing goto failure;
453*d1ac4eb2Sjsing }
454*d1ac4eb2Sjsing if (!BN_sqr(r, a, bn_ctx)) {
455*d1ac4eb2Sjsing fprintf(stderr, "FAIL: BN_sqr(1) failed\n");
456*d1ac4eb2Sjsing goto failure;
457*d1ac4eb2Sjsing }
458*d1ac4eb2Sjsing if (BN_get_word(r) != 1) {
459*d1ac4eb2Sjsing fprintf(stderr, "FAIL: BN_sqr(1) != 1\n");
460*d1ac4eb2Sjsing goto failure;
461*d1ac4eb2Sjsing }
462*d1ac4eb2Sjsing
463*d1ac4eb2Sjsing /* Square of BN with value two. */
464*d1ac4eb2Sjsing if (!BN_set_word(a, 2)) {
465*d1ac4eb2Sjsing fprintf(stderr, "FAIL: BN_set_word(2) failed\n");
466*d1ac4eb2Sjsing goto failure;
467*d1ac4eb2Sjsing }
468*d1ac4eb2Sjsing if (!BN_sqr(r, a, bn_ctx)) {
469*d1ac4eb2Sjsing fprintf(stderr, "FAIL: BN_sqr(2) failed\n");
470*d1ac4eb2Sjsing goto failure;
471*d1ac4eb2Sjsing }
472*d1ac4eb2Sjsing if (BN_get_word(r) != 4) {
473*d1ac4eb2Sjsing fprintf(stderr, "FAIL: BN_sqr(2) != 4\n");
474*d1ac4eb2Sjsing goto failure;
475*d1ac4eb2Sjsing }
476*d1ac4eb2Sjsing
477*d1ac4eb2Sjsing failed = 0;
478*d1ac4eb2Sjsing
479*d1ac4eb2Sjsing failure:
480*d1ac4eb2Sjsing BN_CTX_end(bn_ctx);
481*d1ac4eb2Sjsing BN_CTX_free(bn_ctx);
482*d1ac4eb2Sjsing
483*d1ac4eb2Sjsing return failed;
484*d1ac4eb2Sjsing }
485*d1ac4eb2Sjsing
4862900a9c1Sjsing int
main(int argc,char ** argv)4872900a9c1Sjsing main(int argc, char **argv)
4882900a9c1Sjsing {
4892900a9c1Sjsing int benchmark = 0, failed = 0;
4902900a9c1Sjsing
4912900a9c1Sjsing if (argc == 2 && strcmp(argv[1], "--benchmark") == 0)
4922900a9c1Sjsing benchmark = 1;
4932900a9c1Sjsing
494*d1ac4eb2Sjsing failed |= test_bn_sqr();
495*d1ac4eb2Sjsing
4962900a9c1Sjsing if (benchmark && !failed)
4972900a9c1Sjsing benchmark_bn_mul_sqr();
4982900a9c1Sjsing
4992900a9c1Sjsing return failed;
5002900a9c1Sjsing }
501