From 14d0cc1888207c1aa262c00a85aa02113d7f8d90 Mon Sep 17 00:00:00 2001 From: jsing Date: Sat, 21 Jan 2023 13:24:39 +0000 Subject: [PATCH] Provide basic benchmarks for BN_mul() and BN_sqr(). --- regress/lib/libcrypto/bn/Makefile | 6 +- regress/lib/libcrypto/bn/bn_mul.c | 271 ++++++++++++++++++++++++++++++ 2 files changed, 275 insertions(+), 2 deletions(-) create mode 100644 regress/lib/libcrypto/bn/bn_mul.c diff --git a/regress/lib/libcrypto/bn/Makefile b/regress/lib/libcrypto/bn/Makefile index 6e89e026b25..ad15acfac4f 100644 --- a/regress/lib/libcrypto/bn/Makefile +++ b/regress/lib/libcrypto/bn/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.18 2022/12/17 22:31:10 tb Exp $ +# $OpenBSD: Makefile,v 1.19 2023/01/21 13:24:39 jsing Exp $ PROGS += bn_add_sub PROGS += bn_cmp @@ -8,6 +8,7 @@ PROGS += bn_mod_exp2_mont PROGS += bn_mod_exp_zero PROGS += bn_mod_sqrt PROGS += bn_mont +PROGS += bn_mul PROGS += bn_primes PROGS += bn_rand_interval PROGS += bn_shift @@ -60,7 +61,8 @@ run-bc: bn_test.out CLEANFILES += bn_test.out bc.out -benchmark: bn_shift +benchmark: bn_mul bn_shift + ./bn_mul --benchmark ./bn_shift --benchmark .PHONY: benchmark diff --git a/regress/lib/libcrypto/bn/bn_mul.c b/regress/lib/libcrypto/bn/bn_mul.c new file mode 100644 index 00000000000..de1f5c6b76f --- /dev/null +++ b/regress/lib/libcrypto/bn/bn_mul.c @@ -0,0 +1,271 @@ +/* $OpenBSD: bn_mul.c,v 1.1 2023/01/21 13:24:39 jsing Exp $ */ +/* + * Copyright (c) 2023 Joel Sing + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +static int +benchmark_bn_mul_setup(BIGNUM *a, size_t a_bits, BIGNUM *b, size_t b_bits, + BIGNUM *r) +{ + if (!BN_rand(a, a_bits - 1, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + return 0; + if (!BN_rand(b, b_bits - 1, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + return 0; + if (!BN_set_bit(r, (a_bits + b_bits) - 1)) + return 0; + + return 1; +} + +static void +benchmark_bn_mul_run_once(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *bn_ctx) +{ + if (!BN_mul(r, a, b, bn_ctx)) + errx(1, "BN_mul"); +} + +static int +benchmark_bn_sqr_setup(BIGNUM *a, size_t a_bits, BIGNUM *b, size_t b_bits, + BIGNUM *r) +{ + if (!BN_rand(a, a_bits - 1, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) + return 0; + if (!BN_set_bit(r, (a_bits + a_bits) - 1)) + return 0; + + return 1; +} + +static void +benchmark_bn_sqr_run_once(BIGNUM *r, BIGNUM *a, BIGNUM *b, BN_CTX *bn_ctx) +{ + if (!BN_sqr(r, a, bn_ctx)) + errx(1, "BN_sqr"); +} + +struct benchmark { + const char *desc; + int (*setup)(BIGNUM *, size_t, BIGNUM *, size_t, BIGNUM *); + void (*run_once)(BIGNUM *, BIGNUM *, BIGNUM *, BN_CTX *); + size_t a_bits; + size_t b_bits; +}; + +struct benchmark benchmarks[] = { + { + .desc = "BN_mul (128 bit x 128 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 128, + .b_bits = 128, + }, + { + .desc = "BN_mul (128 bit x 256 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 128, + .b_bits = 256, + }, + { + .desc = "BN_mul (256 bit x 256 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 256, + .b_bits = 256, + }, + { + .desc = "BN_mul (512 bit x 512 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 512, + .b_bits = 512, + }, + { + .desc = "BN_mul (1024 bit x 1024 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 1024, + .b_bits = 1024, + }, + { + .desc = "BN_mul (1024 bit x 2048 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 1024, + .b_bits = 2048, + }, + { + .desc = "BN_mul (2048 bit x 2048 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 2048, + .b_bits = 2048, + }, + { + .desc = "BN_mul (4096 bit x 4096 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 4096, + .b_bits = 4096, + }, + { + .desc = "BN_mul (4096 bit x 8192 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 4096, + .b_bits = 8192, + }, + { + .desc = "BN_mul (8192 bit x 8192 bit)", + .setup = benchmark_bn_mul_setup, + .run_once = benchmark_bn_mul_run_once, + .a_bits = 8192, + .b_bits = 8192, + }, + { + .desc = "BN_sqr (128 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 128, + }, + { + .desc = "BN_sqr (256 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 256, + }, + { + .desc = "BN_sqr (512 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 512, + }, + { + .desc = "BN_sqr (1024 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 1024, + }, + { + .desc = "BN_sqr (2048 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 2048, + }, + { + .desc = "BN_sqr (4096 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 4096, + }, + { + .desc = "BN_sqr (8192 bit)", + .setup = benchmark_bn_sqr_setup, + .run_once = benchmark_bn_sqr_run_once, + .a_bits = 8192, + }, +}; + +#define N_BENCHMARKS (sizeof(benchmarks) / sizeof(benchmarks[0])) + +static volatile sig_atomic_t benchmark_stop; + +static void +benchmark_sig_alarm(int sig) +{ + benchmark_stop = 1; +} + +static void +benchmark_run(const struct benchmark *bm, int seconds) +{ + struct timespec start, end, duration; + BIGNUM *a, *b, *r; + BN_CTX *bn_ctx; + int i; + + signal(SIGALRM, benchmark_sig_alarm); + + if ((bn_ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + BN_CTX_start(bn_ctx); + + if ((a = BN_CTX_get(bn_ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((b = BN_CTX_get(bn_ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((r = BN_CTX_get(bn_ctx)) == NULL) + errx(1, "BN_CTX_get"); + + if (!bm->setup(a, bm->a_bits, b, bm->b_bits, r)) + errx(1, "benchmark setup failed"); + + benchmark_stop = 0; + i = 0; + alarm(seconds); + + clock_gettime(CLOCK_MONOTONIC, &start); + + fprintf(stderr, "Benchmarking %s for %ds: ", bm->desc, seconds); + while (!benchmark_stop) { + bm->run_once(r, a, b, bn_ctx); + i++; + } + clock_gettime(CLOCK_MONOTONIC, &end); + timespecsub(&end, &start, &duration); + fprintf(stderr, "%d iterations in %f seconds\n", i, + duration.tv_sec + duration.tv_nsec / 1000000000.0); + + BN_CTX_end(bn_ctx); + BN_CTX_free(bn_ctx); +} + +static void +benchmark_bn_mul_sqr(void) +{ + const struct benchmark *bm; + size_t i; + + for (i = 0; i < N_BENCHMARKS; i++) { + bm = &benchmarks[i]; + benchmark_run(bm, 5); + } +} + +int +main(int argc, char **argv) +{ + int benchmark = 0, failed = 0; + + if (argc == 2 && strcmp(argv[1], "--benchmark") == 0) + benchmark = 1; + + if (benchmark && !failed) + benchmark_bn_mul_sqr(); + + return failed; +} -- 2.20.1