summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2022-12-17 17:18:46 +0000
committerjsing <>2022-12-17 17:18:46 +0000
commit3badb2f37b0b6599d1adea20cfe176f262924ddc (patch)
tree584200d07b15a79d4fe9b0e386517da7c173569c
parentdf2ca82e06a75275e3bc983f48d1bb6f80cefdc5 (diff)
downloadopenbsd-3badb2f37b0b6599d1adea20cfe176f262924ddc.tar.gz
openbsd-3badb2f37b0b6599d1adea20cfe176f262924ddc.tar.bz2
openbsd-3badb2f37b0b6599d1adea20cfe176f262924ddc.zip
Provide regress coverage for BN shift functions.
Provide regress coverage for BN_lshift1(), BN_rshift1(), BN_lshift() and BN_rshift(), along with basic benchmarking functionality (run via 'make benchmark').
-rw-r--r--src/regress/lib/libcrypto/bn/Makefile6
-rw-r--r--src/regress/lib/libcrypto/bn/bn_shift.c538
2 files changed, 543 insertions, 1 deletions
diff --git a/src/regress/lib/libcrypto/bn/Makefile b/src/regress/lib/libcrypto/bn/Makefile
index e95091aeb5..8a51a2ccad 100644
--- a/src/regress/lib/libcrypto/bn/Makefile
+++ b/src/regress/lib/libcrypto/bn/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.16 2022/12/09 09:56:41 tb Exp $ 1# $OpenBSD: Makefile,v 1.17 2022/12/17 17:18:46 jsing Exp $
2 2
3PROGS += bn_add_sub 3PROGS += bn_add_sub
4PROGS += bn_cmp 4PROGS += bn_cmp
@@ -10,6 +10,7 @@ PROGS += bn_mod_sqrt
10PROGS += bn_mont 10PROGS += bn_mont
11PROGS += bn_primes 11PROGS += bn_primes
12PROGS += bn_rand_interval 12PROGS += bn_rand_interval
13PROGS += bn_shift
13PROGS += bn_test 14PROGS += bn_test
14PROGS += bn_to_string 15PROGS += bn_to_string
15PROGS += bn_unit 16PROGS += bn_unit
@@ -63,4 +64,7 @@ CLEANFILES += bn_test.out bc.out
63LDADD_$p += ${CRYPTO_INT} 64LDADD_$p += ${CRYPTO_INT}
64.endfor 65.endfor
65 66
67benchmark: bn_shift
68 ./bn_shift --benchmark
69
66.include <bsd.regress.mk> 70.include <bsd.regress.mk>
diff --git a/src/regress/lib/libcrypto/bn/bn_shift.c b/src/regress/lib/libcrypto/bn/bn_shift.c
new file mode 100644
index 0000000000..c8f9d3ad1c
--- /dev/null
+++ b/src/regress/lib/libcrypto/bn/bn_shift.c
@@ -0,0 +1,538 @@
1/* $OpenBSD: bn_shift.c,v 1.1 2022/12/17 17:18:46 jsing Exp $ */
2/*
3 * Copyright (c) 2022 Joel Sing <jsing@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/time.h>
19
20#include <err.h>
21#include <signal.h>
22#include <stdio.h>
23#include <string.h>
24#include <time.h>
25#include <unistd.h>
26
27#include <openssl/bn.h>
28
29static const char *bn_shift_want_hex = \
30 "02AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \
31 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8";
32
33static int
34check_shift_result(BIGNUM *bn1)
35{
36 BIGNUM *bn2 = NULL;
37 char *s = NULL;
38 int ret = 0;
39
40 if (!BN_hex2bn(&bn2, bn_shift_want_hex)) {
41 fprintf(stderr, "FAIL: BN_hex2bn() failed\n");
42 goto failure;
43 }
44 if (BN_cmp(bn1, bn2) != 0) {
45 fprintf(stderr, "FAIL: shifted result differs\n");
46 if ((s = BN_bn2hex(bn1)) == NULL) {
47 fprintf(stderr, "FAIL: BN_bn2hex()\n");
48 goto failure;
49 }
50 fprintf(stderr, "Got: %s\n", s);
51 free(s);
52 if ((s = BN_bn2hex(bn2)) == NULL) {
53 fprintf(stderr, "FAIL: BN_bn2hex()\n");
54 goto failure;
55 }
56 fprintf(stderr, "Want: %s\n", s);
57 }
58
59 ret = 1;
60
61 failure:
62 BN_free(bn2);
63 free(s);
64
65 return ret;
66}
67
68static int
69test_bn_shift1(void)
70{
71 BIGNUM *bn1 = NULL, *bn2 = NULL;
72 int i;
73 int failed = 1;
74
75 if ((bn1 = BN_new()) == NULL) {
76 fprintf(stderr, "FAIL: failed to create BN\n");
77 goto failure;
78 }
79 if ((bn2 = BN_new()) == NULL) {
80 fprintf(stderr, "FAIL: failed to create BN\n");
81 goto failure;
82 }
83
84 for (i = 1; i <= 256; i++) {
85 if (!BN_set_bit(bn1, 1)) {
86 fprintf(stderr, "FAIL: failed to set bit\n");
87 goto failure;
88 }
89 if (!BN_lshift1(bn1, bn1)) {
90 fprintf(stderr, "FAIL: failed to BN_lshift1()\n");
91 goto failure;
92 }
93 if (!BN_lshift1(bn1, bn1)) {
94 fprintf(stderr, "FAIL: failed to BN_lshift1()\n");
95 goto failure;
96 }
97 if (!BN_rshift1(bn1, bn1)) {
98 fprintf(stderr, "FAIL: failed to BN_rshift1()\n");
99 goto failure;
100 }
101 if (!BN_lshift1(bn1, bn1)) {
102 fprintf(stderr, "FAIL: failed to BN_lshift1()\n");
103 goto failure;
104 }
105 }
106
107 if (!check_shift_result(bn1))
108 goto failure;
109
110 /*
111 * Shift result into a different BN.
112 */
113 if (!BN_lshift1(bn1, bn1)) {
114 fprintf(stderr, "FAIL: failed to BN_lshift1()\n");
115 goto failure;
116 }
117 if (!BN_rshift1(bn2, bn1)) {
118 fprintf(stderr, "FAIL: failed to BN_rshift1()\n");
119 goto failure;
120 }
121
122 if (!check_shift_result(bn2))
123 goto failure;
124
125 if (!BN_rshift1(bn2, bn2)) {
126 fprintf(stderr, "FAIL: failed to BN_rshift1()\n");
127 goto failure;
128 }
129 if (!BN_lshift1(bn1, bn2)) {
130 fprintf(stderr, "FAIL: failed to BN_lshift1()\n");
131 goto failure;
132 }
133
134 if (!check_shift_result(bn1))
135 goto failure;
136
137 failed = 0;
138
139 failure:
140 BN_free(bn1);
141 BN_free(bn2);
142
143 return failed;
144}
145
146static int
147test_bn_shift(void)
148{
149 BIGNUM *bn1 = NULL, *bn2 = NULL;
150 int i;
151 int failed = 1;
152
153 if ((bn1 = BN_new()) == NULL) {
154 fprintf(stderr, "FAIL: failed to create BN 1\n");
155 goto failure;
156 }
157 if ((bn2 = BN_new()) == NULL) {
158 fprintf(stderr, "FAIL: failed to create BN 2\n");
159 goto failure;
160 }
161
162 for (i = 1; i <= 256; i++) {
163 if (!BN_set_bit(bn1, 1)) {
164 fprintf(stderr, "FAIL: failed to set bit\n");
165 goto failure;
166 }
167 if (!BN_lshift(bn1, bn1, i + 1)) {
168 fprintf(stderr, "FAIL: failed to BN_lshift()\n");
169 goto failure;
170 }
171 if (!BN_rshift(bn1, bn1, i - 1)) {
172 fprintf(stderr, "FAIL: failed to BN_rshift()\n");
173 goto failure;
174 }
175 }
176
177 if (!check_shift_result(bn1))
178 goto failure;
179
180 for (i = 0; i <= 256; i++) {
181 if (!BN_lshift(bn1, bn1, i)) {
182 fprintf(stderr, "FAIL: failed to BN_lshift()\n");
183 goto failure;
184 }
185 if (i > 1) {
186 if (!BN_set_bit(bn1, 1)) {
187 fprintf(stderr, "FAIL: failed to set bit\n");
188 goto failure;
189 }
190 }
191 }
192
193 if (BN_num_bytes(bn1) != 4177) {
194 fprintf(stderr, "FAIL: BN has %d bytes, want 4177\n",
195 BN_num_bytes(bn1));
196 goto failure;
197 }
198
199 for (i = 0; i <= 256; i++) {
200 if (!BN_rshift(bn1, bn1, i)) {
201 fprintf(stderr, "FAIL: failed to BN_rshift()\n");
202 goto failure;
203 }
204 }
205
206 if (!check_shift_result(bn1))
207 goto failure;
208
209 /*
210 * Shift result into a different BN.
211 */
212 if (!BN_lshift(bn1, bn1, BN_BITS2 + 1)) {
213 fprintf(stderr, "FAIL: failed to BN_lshift()\n");
214 goto failure;
215 }
216 if (!BN_rshift(bn2, bn1, BN_BITS2 + 1)) {
217 fprintf(stderr, "FAIL: failed to BN_rshift()\n");
218 goto failure;
219 }
220
221 if (!check_shift_result(bn2))
222 goto failure;
223
224 if (!BN_rshift(bn2, bn2, 3)) {
225 fprintf(stderr, "FAIL: failed to BN_rshift()\n");
226 goto failure;
227 }
228 if (!BN_lshift(bn1, bn2, 3)) {
229 fprintf(stderr, "FAIL: failed to BN_lshift()\n");
230 goto failure;
231 }
232
233 if (!check_shift_result(bn1))
234 goto failure;
235
236 failed = 0;
237
238 failure:
239 BN_free(bn1);
240 BN_free(bn2);
241
242 return failed;
243}
244
245static int
246test_bn_rshift_to_zero(void)
247{
248 BIGNUM *bn1 = NULL, *bn2 = NULL;
249 int failed = 1;
250
251 if (!BN_hex2bn(&bn1, "ffff")) {
252 fprintf(stderr, "FAIL: BN_hex2bn() failed\n");
253 goto failure;
254 }
255 if (!BN_lshift(bn1, bn1, BN_BITS2)) {
256 fprintf(stderr, "FAIL: BN_lshift() failed\n");
257 goto failure;
258 }
259
260 if ((bn2 = BN_new()) == NULL) {
261 fprintf(stderr, "FAIL: BN_new() failed\n");
262 goto failure;
263 }
264
265 /* Shift all words. */
266 if (!BN_rshift(bn2, bn1, BN_BITS2 * 2)) {
267 fprintf(stderr, "FAIL: BN_rshift() failed\n");
268 goto failure;
269 }
270 if (BN_is_zero(bn1)) {
271 fprintf(stderr, "FAIL: BN is zero\n");
272 goto failure;
273 }
274 if (!BN_is_zero(bn2)) {
275 fprintf(stderr, "FAIL: BN is not zero\n");
276 goto failure;
277 }
278
279 /* Shift to zero, with partial shift for top most word. */
280 if (!BN_rshift(bn2, bn1, BN_BITS2 + 16)) {
281 fprintf(stderr, "FAIL: BN_rshift() failed\n");
282 goto failure;
283 }
284 if (BN_is_zero(bn1)) {
285 fprintf(stderr, "FAIL: BN is zero\n");
286 goto failure;
287 }
288 if (!BN_is_zero(bn2)) {
289 fprintf(stderr, "FAIL: BN is not zero\n");
290 goto failure;
291 }
292
293 /* Shift to zero of negative value. */
294 if (!BN_one(bn1)) {
295 fprintf(stderr, "FAIL: BN_one() failed\n");
296 goto failure;
297 }
298 BN_set_negative(bn1, 1);
299 if (!BN_rshift(bn1, bn1, 1)) {
300 fprintf(stderr, "FAIL: BN_rshift() failed\n");
301 goto failure;
302 }
303 if (!BN_is_zero(bn1)) {
304 fprintf(stderr, "FAIL: BN is not zero\n");
305 goto failure;
306 }
307
308 failed = 0;
309
310 failure:
311 BN_free(bn1);
312 BN_free(bn2);
313
314 return failed;
315}
316
317static void
318benchmark_bn_lshift1(BIGNUM *bn)
319{
320 int i;
321
322 if (!BN_one(bn))
323 errx(1, "BN_one");
324
325 for (i = 0; i < 8192; i++) {
326 if (!BN_lshift1(bn, bn))
327 errx(1, "BN_lshift1");
328 }
329}
330
331static void
332benchmark_bn_lshift(BIGNUM *bn, int n)
333{
334 int i;
335
336 if (!BN_one(bn))
337 errx(1, "BN_one");
338
339 for (i = 0; i < 8192; i++) {
340 if (!BN_lshift(bn, bn, n))
341 errx(1, "BN_lshift");
342 }
343}
344
345static void
346benchmark_bn_lshift_1(BIGNUM *bn)
347{
348 benchmark_bn_lshift(bn, 1);
349}
350
351static void
352benchmark_bn_lshift_32(BIGNUM *bn)
353{
354 benchmark_bn_lshift(bn, 32);
355}
356
357static void
358benchmark_bn_lshift_64(BIGNUM *bn)
359{
360 benchmark_bn_lshift(bn, 64);
361}
362
363static void
364benchmark_bn_lshift_127(BIGNUM *bn)
365{
366 benchmark_bn_lshift(bn, 127);
367}
368
369static void
370benchmark_bn_rshift1(BIGNUM *bn)
371{
372 int i;
373
374 if (!BN_set_bit(bn, 8192))
375 errx(1, "BN_set_bit");
376
377 for (i = 0; i < 8192; i++) {
378 if (!BN_rshift1(bn, bn))
379 errx(1, "BN_rshift1");
380 }
381}
382
383static void
384benchmark_bn_rshift(BIGNUM *bn, int n)
385{
386 int i;
387
388 if (!BN_set_bit(bn, 8192 * n))
389 errx(1, "BN_set_bit");
390
391 for (i = 0; i < 8192; i++) {
392 if (!BN_rshift(bn, bn, n))
393 errx(1, "BN_rshift");
394 }
395}
396
397static void
398benchmark_bn_rshift_1(BIGNUM *bn)
399{
400 benchmark_bn_rshift(bn, 1);
401}
402
403static void
404benchmark_bn_rshift_32(BIGNUM *bn)
405{
406 benchmark_bn_rshift(bn, 32);
407}
408
409static void
410benchmark_bn_rshift_64(BIGNUM *bn)
411{
412 benchmark_bn_rshift(bn, 64);
413}
414
415static void
416benchmark_bn_rshift_127(BIGNUM *bn)
417{
418 benchmark_bn_rshift(bn, 127);
419}
420
421struct benchmark {
422 const char *desc;
423 void (*func)(BIGNUM *);
424};
425
426struct benchmark benchmarks[] = {
427 {
428 .desc = "BN_lshift1()",
429 .func = benchmark_bn_lshift1,
430 },
431 {
432 .desc = "BN_lshift(_, _, 1)",
433 .func = benchmark_bn_lshift_1,
434 },
435 {
436 .desc = "BN_lshift(_, _, 32)",
437 .func = benchmark_bn_lshift_32,
438 },
439 {
440 .desc = "BN_lshift(_, _, 64)",
441 .func = benchmark_bn_lshift_64,
442 },
443 {
444 .desc = "BN_lshift(_, _, 127)",
445 .func = benchmark_bn_lshift_127,
446 },
447 {
448 .desc = "BN_rshift1()",
449 .func = benchmark_bn_rshift1,
450 },
451 {
452 .desc = "BN_rshift(_, _, 1)",
453 .func = benchmark_bn_rshift_1,
454 },
455 {
456 .desc = "BN_rshift(_, _, 32)",
457 .func = benchmark_bn_rshift_32,
458 },
459 {
460 .desc = "BN_rshift(_, _, 64)",
461 .func = benchmark_bn_rshift_64,
462 },
463 {
464 .desc = "BN_rshift(_, _, 127)",
465 .func = benchmark_bn_rshift_127,
466 },
467};
468
469#define N_BENCHMARKS (sizeof(benchmarks) / sizeof(benchmarks[0]))
470
471static int benchmark_stop;
472
473static void
474benchmark_sig_alarm(int sig)
475{
476 benchmark_stop = 1;
477}
478
479static void
480benchmark_run(const struct benchmark *bm, int seconds)
481{
482 struct timespec start, end, duration;
483 BIGNUM *bn;
484 int i;
485
486 signal(SIGALRM, benchmark_sig_alarm);
487
488 if ((bn = BN_new()) == NULL)
489 errx(1, "BN_new");
490
491 benchmark_stop = 0;
492 i = 0;
493 alarm(seconds);
494
495 clock_gettime(CLOCK_MONOTONIC, &start);
496
497 fprintf(stderr, "Benchmarking %s for %ds: ", bm->desc, seconds);
498 while (!benchmark_stop) {
499 bm->func(bn);
500 i++;
501 }
502 clock_gettime(CLOCK_MONOTONIC, &end);
503 timespecsub(&end, &start, &duration);
504 fprintf(stderr, "%d iterations in %f seconds\n", i,
505 duration.tv_sec + duration.tv_nsec / 1000000000.0);
506
507 BN_free(bn);
508}
509
510static void
511benchmark_bn_shift(void)
512{
513 const struct benchmark *bm;
514 size_t i;
515
516 for (i = 0; i < N_BENCHMARKS; i++) {
517 bm = &benchmarks[i];
518 benchmark_run(bm, 5);
519 }
520}
521
522int
523main(int argc, char **argv)
524{
525 int benchmark = 0, failed = 0;
526
527 if (argc == 2 && strcmp(argv[1], "--benchmark") == 0)
528 benchmark = 1;
529
530 failed |= test_bn_shift1();
531 failed |= test_bn_shift();
532 failed |= test_bn_rshift_to_zero();
533
534 if (benchmark && !failed)
535 benchmark_bn_shift();
536
537 return failed;
538}