xref: /openbsd-src/regress/lib/libcrypto/bn/bn_general.c (revision b2cabbc12a1e72cb4d2da0aba0e38395928f0709)
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