1*b2cabbc1Sjsing /* $OpenBSD: bn_general.c,v 1.2 2023/04/11 05:53:53 jsing Exp $ */
2e79df2fbSjsing /*
3e79df2fbSjsing * Copyright (c) 2022, 2023 Joel Sing <jsing@openbsd.org>
4e79df2fbSjsing *
5e79df2fbSjsing * Permission to use, copy, modify, and distribute this software for any
6e79df2fbSjsing * purpose with or without fee is hereby granted, provided that the above
7e79df2fbSjsing * copyright notice and this permission notice appear in all copies.
8e79df2fbSjsing *
9e79df2fbSjsing * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10e79df2fbSjsing * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11e79df2fbSjsing * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12e79df2fbSjsing * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13e79df2fbSjsing * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14e79df2fbSjsing * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15e79df2fbSjsing * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16e79df2fbSjsing */
17e79df2fbSjsing
18e79df2fbSjsing #include <sys/resource.h>
19e79df2fbSjsing #include <sys/time.h>
20e79df2fbSjsing
21e79df2fbSjsing #include <err.h>
22e79df2fbSjsing #include <signal.h>
23e79df2fbSjsing #include <stdio.h>
24e79df2fbSjsing #include <string.h>
25e79df2fbSjsing #include <time.h>
26e79df2fbSjsing #include <unistd.h>
27e79df2fbSjsing
28e79df2fbSjsing #include <openssl/bn.h>
29e79df2fbSjsing
30e79df2fbSjsing static void
benchmark_bn_copy_setup(BIGNUM * dst,BIGNUM * src,int n)31e79df2fbSjsing benchmark_bn_copy_setup(BIGNUM *dst, BIGNUM *src, int n)
32e79df2fbSjsing {
33e79df2fbSjsing if (!BN_set_bit(dst, n - 1))
34e79df2fbSjsing errx(1, "BN_set_bit");
35e79df2fbSjsing if (!BN_set_bit(src, n - 1))
36e79df2fbSjsing errx(1, "BN_set_bit");
37e79df2fbSjsing }
38e79df2fbSjsing
39e79df2fbSjsing static void
benchmark_bn_copy_run_once(BIGNUM * dst,BIGNUM * src)40e79df2fbSjsing benchmark_bn_copy_run_once(BIGNUM *dst, BIGNUM *src)
41e79df2fbSjsing {
42e79df2fbSjsing if (BN_copy(dst, src) == NULL)
43e79df2fbSjsing errx(1, "BN_copy");
44e79df2fbSjsing }
45e79df2fbSjsing
46e79df2fbSjsing struct benchmark {
47e79df2fbSjsing const char *desc;
48e79df2fbSjsing void (*setup)(BIGNUM *, BIGNUM *, int);
49e79df2fbSjsing void (*run_once)(BIGNUM *, BIGNUM *);
50e79df2fbSjsing int bits;
51e79df2fbSjsing };
52e79df2fbSjsing
53e79df2fbSjsing struct benchmark benchmarks[] = {
54e79df2fbSjsing {
55e79df2fbSjsing .desc = "BN_copy() 32 bits",
56e79df2fbSjsing .setup = benchmark_bn_copy_setup,
57e79df2fbSjsing .run_once = benchmark_bn_copy_run_once,
58e79df2fbSjsing .bits = 32,
59e79df2fbSjsing },
60e79df2fbSjsing {
61e79df2fbSjsing .desc = "BN_copy() 256 bits",
62e79df2fbSjsing .setup = benchmark_bn_copy_setup,
63e79df2fbSjsing .run_once = benchmark_bn_copy_run_once,
64e79df2fbSjsing .bits = 256,
65e79df2fbSjsing },
66e79df2fbSjsing {
67e79df2fbSjsing .desc = "BN_copy() 320 bits",
68e79df2fbSjsing .setup = benchmark_bn_copy_setup,
69e79df2fbSjsing .run_once = benchmark_bn_copy_run_once,
70e79df2fbSjsing .bits = 320,
71e79df2fbSjsing },
72e79df2fbSjsing {
73e79df2fbSjsing .desc = "BN_copy() 512 bits",
74e79df2fbSjsing .setup = benchmark_bn_copy_setup,
75e79df2fbSjsing .run_once = benchmark_bn_copy_run_once,
76e79df2fbSjsing .bits = 512,
77e79df2fbSjsing },
78e79df2fbSjsing {
79e79df2fbSjsing .desc = "BN_copy() 1024 bits",
80e79df2fbSjsing .setup = benchmark_bn_copy_setup,
81e79df2fbSjsing .run_once = benchmark_bn_copy_run_once,
82e79df2fbSjsing .bits = 1024,
83e79df2fbSjsing },
84e79df2fbSjsing {
85e79df2fbSjsing .desc = "BN_copy() 2048 bits",
86e79df2fbSjsing .setup = benchmark_bn_copy_setup,
87e79df2fbSjsing .run_once = benchmark_bn_copy_run_once,
88e79df2fbSjsing .bits = 2048,
89e79df2fbSjsing },
90e79df2fbSjsing {
91e79df2fbSjsing .desc = "BN_copy() 4096 bits",
92e79df2fbSjsing .setup = benchmark_bn_copy_setup,
93e79df2fbSjsing .run_once = benchmark_bn_copy_run_once,
94e79df2fbSjsing .bits = 4096,
95e79df2fbSjsing },
96e79df2fbSjsing {
97e79df2fbSjsing .desc = "BN_copy() 16384 bits",
98e79df2fbSjsing .setup = benchmark_bn_copy_setup,
99e79df2fbSjsing .run_once = benchmark_bn_copy_run_once,
100e79df2fbSjsing .bits = 16384,
101e79df2fbSjsing },
102e79df2fbSjsing };
103e79df2fbSjsing
104e79df2fbSjsing #define N_BENCHMARKS (sizeof(benchmarks) / sizeof(benchmarks[0]))
105e79df2fbSjsing
106e79df2fbSjsing static int benchmark_stop;
107e79df2fbSjsing
108e79df2fbSjsing static void
benchmark_sig_alarm(int sig)109e79df2fbSjsing benchmark_sig_alarm(int sig)
110e79df2fbSjsing {
111e79df2fbSjsing benchmark_stop = 1;
112e79df2fbSjsing }
113e79df2fbSjsing
114e79df2fbSjsing static void
benchmark_run(const struct benchmark * bm,int seconds)115e79df2fbSjsing benchmark_run(const struct benchmark *bm, int seconds)
116e79df2fbSjsing {
117e79df2fbSjsing struct timespec start, end, duration;
118e79df2fbSjsing struct rusage rusage;
119e79df2fbSjsing BIGNUM *dst, *src;
120e79df2fbSjsing int i;
121e79df2fbSjsing
122e79df2fbSjsing signal(SIGALRM, benchmark_sig_alarm);
123e79df2fbSjsing
124e79df2fbSjsing if ((src = BN_new()) == NULL)
125e79df2fbSjsing errx(1, "BN_new");
126e79df2fbSjsing if ((dst = BN_new()) == NULL)
127e79df2fbSjsing errx(1, "BN_new");
128e79df2fbSjsing
129e79df2fbSjsing bm->setup(dst, src, bm->bits);
130e79df2fbSjsing
131e79df2fbSjsing benchmark_stop = 0;
132e79df2fbSjsing i = 0;
133e79df2fbSjsing alarm(seconds);
134e79df2fbSjsing
135e79df2fbSjsing if (getrusage(RUSAGE_SELF, &rusage) == -1)
136e79df2fbSjsing err(1, "getrusage failed");
137e79df2fbSjsing TIMEVAL_TO_TIMESPEC(&rusage.ru_utime, &start);
138e79df2fbSjsing
139e79df2fbSjsing fprintf(stderr, "Benchmarking %s for %ds: ", bm->desc, seconds);
140e79df2fbSjsing while (!benchmark_stop) {
141e79df2fbSjsing bm->run_once(dst, src);
142e79df2fbSjsing i++;
143e79df2fbSjsing }
144e79df2fbSjsing if (getrusage(RUSAGE_SELF, &rusage) == -1)
145e79df2fbSjsing err(1, "getrusage failed");
146e79df2fbSjsing TIMEVAL_TO_TIMESPEC(&rusage.ru_utime, &end);
147e79df2fbSjsing
148e79df2fbSjsing timespecsub(&end, &start, &duration);
149e79df2fbSjsing fprintf(stderr, "%d iterations in %f seconds - %llu op/s\n", i,
150e79df2fbSjsing duration.tv_sec + duration.tv_nsec / 1000000000.0,
151*b2cabbc1Sjsing (uint64_t)i * 1000000000 /
152e79df2fbSjsing (duration.tv_sec * 1000000000 + duration.tv_nsec));
153e79df2fbSjsing
154e79df2fbSjsing BN_free(src);
155e79df2fbSjsing BN_free(dst);
156e79df2fbSjsing }
157e79df2fbSjsing
158e79df2fbSjsing static void
benchmark_bn_general(void)159e79df2fbSjsing benchmark_bn_general(void)
160e79df2fbSjsing {
161e79df2fbSjsing const struct benchmark *bm;
162e79df2fbSjsing size_t i;
163e79df2fbSjsing
164e79df2fbSjsing for (i = 0; i < N_BENCHMARKS; i++) {
165e79df2fbSjsing bm = &benchmarks[i];
166e79df2fbSjsing benchmark_run(bm, 5);
167e79df2fbSjsing }
168e79df2fbSjsing }
169e79df2fbSjsing
170e79df2fbSjsing int
main(int argc,char ** argv)171e79df2fbSjsing main(int argc, char **argv)
172e79df2fbSjsing {
173e79df2fbSjsing int benchmark = 0, failed = 0;
174e79df2fbSjsing
175e79df2fbSjsing if (argc == 2 && strcmp(argv[1], "--benchmark") == 0)
176e79df2fbSjsing benchmark = 1;
177e79df2fbSjsing
178e79df2fbSjsing if (benchmark && !failed)
179e79df2fbSjsing benchmark_bn_general();
180e79df2fbSjsing
181e79df2fbSjsing return failed;
182e79df2fbSjsing }
183