Line data Source code
1 : /* bench-slope.c - for libgcrypt
2 : * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
3 : *
4 : * This file is part of Libgcrypt.
5 : *
6 : * Libgcrypt is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser general Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * Libgcrypt is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #ifdef HAVE_CONFIG_H
21 : #include <config.h>
22 : #endif
23 : #include <stdio.h>
24 : #include <stdlib.h>
25 : #include <stdarg.h>
26 : #include <assert.h>
27 : #include <time.h>
28 :
29 : #ifdef _GCRYPT_IN_LIBGCRYPT
30 : # include "../src/gcrypt-int.h"
31 : # include "../compat/libcompat.h"
32 : #else
33 : # include <gcrypt.h>
34 : #endif
35 :
36 : #ifndef STR
37 : #define STR(v) #v
38 : #define STR2(v) STR(v)
39 : #endif
40 :
41 : #define PGM "bench-slope"
42 : #include "t-common.h"
43 :
44 : static int verbose;
45 : static int csv_mode;
46 : static int unaligned_mode;
47 : static int num_measurement_repetitions;
48 :
49 : /* CPU Ghz value provided by user, allows constructing cycles/byte and other
50 : results. */
51 : static double cpu_ghz = -1;
52 :
53 : /* Whether we are running as part of the regression test suite. */
54 : static int in_regression_test;
55 :
56 : /* The name of the currently printed section. */
57 : static char *current_section_name;
58 : /* The name of the currently printed algorithm. */
59 : static char *current_algo_name;
60 : /* The name of the currently printed mode. */
61 : static char *current_mode_name;
62 :
63 :
64 : /*************************************** Default parameters for measurements. */
65 :
66 : /* Start at small buffer size, to get reasonable timer calibration for fast
67 : * implementations (AES-NI etc). Sixteen selected to support the largest block
68 : * size of current set cipher blocks. */
69 : #define BUF_START_SIZE 16
70 :
71 : /* From ~0 to ~4kbytes give comparable results with results from academia
72 : * (SUPERCOP). */
73 : #define BUF_END_SIZE (BUF_START_SIZE + 4096)
74 :
75 : /* With 128 byte steps, we get (4096)/64 = 64 data points. */
76 : #define BUF_STEP_SIZE 64
77 :
78 : /* Number of repeated measurements at each data point. The median of these
79 : * measurements is selected as data point further analysis. */
80 : #define NUM_MEASUREMENT_REPETITIONS 64
81 :
82 : /**************************************************** High-resolution timers. */
83 :
84 : /* This benchmarking module needs needs high resolution timer. */
85 : #undef NO_GET_NSEC_TIME
86 : #if defined(_WIN32)
87 : struct nsec_time
88 : {
89 : LARGE_INTEGER perf_count;
90 : };
91 :
92 : static void
93 : get_nsec_time (struct nsec_time *t)
94 : {
95 : BOOL ok;
96 :
97 : ok = QueryPerformanceCounter (&t->perf_count);
98 : assert (ok);
99 : }
100 :
101 : static double
102 : get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end)
103 : {
104 : static double nsecs_per_count = 0.0;
105 : double nsecs;
106 :
107 : if (nsecs_per_count == 0.0)
108 : {
109 : LARGE_INTEGER perf_freq;
110 : BOOL ok;
111 :
112 : /* Get counts per second. */
113 : ok = QueryPerformanceFrequency (&perf_freq);
114 : assert (ok);
115 :
116 : nsecs_per_count = 1.0 / perf_freq.QuadPart;
117 : nsecs_per_count *= 1000000.0 * 1000.0; /* sec => nsec */
118 :
119 : assert (nsecs_per_count > 0.0);
120 : }
121 :
122 : nsecs = end->perf_count.QuadPart - start->perf_count.QuadPart; /* counts */
123 : nsecs *= nsecs_per_count; /* counts * (nsecs / count) => nsecs */
124 :
125 : return nsecs;
126 : }
127 : #elif defined(HAVE_CLOCK_GETTIME)
128 : struct nsec_time
129 : {
130 : struct timespec ts;
131 : };
132 :
133 : static void
134 28204686 : get_nsec_time (struct nsec_time *t)
135 : {
136 : int err;
137 :
138 28204686 : err = clock_gettime (CLOCK_REALTIME, &t->ts);
139 28204686 : assert (err == 0);
140 28204686 : }
141 :
142 : static double
143 28143903 : get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end)
144 : {
145 : double nsecs;
146 :
147 28143903 : nsecs = end->ts.tv_sec - start->ts.tv_sec;
148 28143903 : nsecs *= 1000000.0 * 1000.0; /* sec => nsec */
149 :
150 : /* This way we don't have to care if tv_nsec unsigned or signed. */
151 28143903 : if (end->ts.tv_nsec >= start->ts.tv_nsec)
152 2142909 : nsecs += end->ts.tv_nsec - start->ts.tv_nsec;
153 : else
154 26000994 : nsecs -= start->ts.tv_nsec - end->ts.tv_nsec;
155 :
156 28143903 : return nsecs;
157 : }
158 : #elif defined(HAVE_GETTIMEOFDAY)
159 : struct nsec_time
160 : {
161 : struct timeval tv;
162 : };
163 :
164 : static void
165 : get_nsec_time (struct nsec_time *t)
166 : {
167 : int err;
168 :
169 : err = gettimeofday (&t->tv, NULL);
170 : assert (err == 0);
171 : }
172 :
173 : static double
174 : get_time_nsec_diff (struct nsec_time *start, struct nsec_time *end)
175 : {
176 : double nsecs;
177 :
178 : nsecs = end->tv.tv_sec - start->tv.tv_sec;
179 : nsecs *= 1000000; /* sec => µsec */
180 :
181 : /* This way we don't have to care if tv_usec unsigned or signed. */
182 : if (end->tv.tv_usec >= start->tv.tv_usec)
183 : nsecs += end->tv.tv_usec - start->tv.tv_usec;
184 : else
185 : nsecs -= start->tv.tv_usec - end->tv.tv_usec;
186 :
187 : nsecs *= 1000; /* µsec => nsec */
188 :
189 : return nsecs;
190 : }
191 : #else
192 : #define NO_GET_NSEC_TIME 1
193 : #endif
194 :
195 :
196 : /* If no high resolution timer found, provide dummy bench-slope. */
197 : #ifdef NO_GET_NSEC_TIME
198 :
199 :
200 : int
201 : main (void)
202 : {
203 : /* No nsec timer => SKIP test. */
204 : return 77;
205 : }
206 :
207 :
208 : #else /* !NO_GET_NSEC_TIME */
209 :
210 :
211 : /********************************************** Slope benchmarking framework. */
212 :
213 : struct bench_obj
214 : {
215 : const struct bench_ops *ops;
216 :
217 : unsigned int num_measure_repetitions;
218 : unsigned int min_bufsize;
219 : unsigned int max_bufsize;
220 : unsigned int step_size;
221 :
222 : void *priv;
223 : };
224 :
225 : typedef int (*const bench_initialize_t) (struct bench_obj * obj);
226 : typedef void (*const bench_finalize_t) (struct bench_obj * obj);
227 : typedef void (*const bench_do_run_t) (struct bench_obj * obj, void *buffer,
228 : size_t buflen);
229 :
230 : struct bench_ops
231 : {
232 : bench_initialize_t initialize;
233 : bench_finalize_t finalize;
234 : bench_do_run_t do_run;
235 : };
236 :
237 :
238 : double
239 442 : get_slope (double (*const get_x) (unsigned int idx, void *priv),
240 : void *get_x_priv, double y_points[], unsigned int npoints,
241 : double *overhead)
242 : {
243 : double sumx, sumy, sumx2, sumy2, sumxy;
244 : unsigned int i;
245 : double b, a;
246 :
247 442 : sumx = sumy = sumx2 = sumy2 = sumxy = 0;
248 :
249 27105 : for (i = 0; i < npoints; i++)
250 : {
251 : double x, y;
252 :
253 26663 : x = get_x (i, get_x_priv); /* bytes */
254 26663 : y = y_points[i]; /* nsecs */
255 :
256 26663 : sumx += x;
257 26663 : sumy += y;
258 26663 : sumx2 += x * x;
259 : /*sumy2 += y * y;*/
260 26663 : sumxy += x * y;
261 : }
262 :
263 442 : b = (npoints * sumxy - sumx * sumy) / (npoints * sumx2 - sumx * sumx);
264 442 : a = (sumy - b * sumx) / npoints;
265 :
266 442 : if (overhead)
267 442 : *overhead = a; /* nsecs */
268 :
269 442 : return b; /* nsecs per byte */
270 : }
271 :
272 :
273 : double
274 26663 : get_bench_obj_point_x (unsigned int idx, void *priv)
275 : {
276 26663 : struct bench_obj *obj = priv;
277 26663 : return (double) (obj->min_bufsize + (idx * obj->step_size));
278 : }
279 :
280 :
281 : unsigned int
282 442 : get_num_measurements (struct bench_obj *obj)
283 : {
284 442 : unsigned int buf_range = obj->max_bufsize - obj->min_bufsize;
285 442 : unsigned int num = buf_range / obj->step_size + 1;
286 :
287 1326 : while (obj->min_bufsize + (num * obj->step_size) > obj->max_bufsize)
288 442 : num--;
289 :
290 442 : return num + 1;
291 : }
292 :
293 :
294 : static int
295 30391 : double_cmp (const void *_a, const void *_b)
296 : {
297 : const double *a, *b;
298 :
299 30391 : a = _a;
300 30391 : b = _b;
301 :
302 30391 : if (*a > *b)
303 17836 : return 1;
304 12555 : if (*a < *b)
305 12468 : return -1;
306 87 : return 0;
307 : }
308 :
309 :
310 : double
311 30391 : do_bench_obj_measurement (struct bench_obj *obj, void *buffer, size_t buflen,
312 : double *measurement_raw,
313 : unsigned int loop_iterations)
314 : {
315 30391 : const unsigned int num_repetitions = obj->num_measure_repetitions;
316 30391 : const bench_do_run_t do_run = obj->ops->do_run;
317 : struct nsec_time start, end;
318 : unsigned int rep, loop;
319 : double res;
320 :
321 30391 : if (num_repetitions < 1 || loop_iterations < 1)
322 0 : return 0.0;
323 :
324 91173 : for (rep = 0; rep < num_repetitions; rep++)
325 : {
326 60782 : get_nsec_time (&start);
327 :
328 582760 : for (loop = 0; loop < loop_iterations; loop++)
329 521978 : do_run (obj, buffer, buflen);
330 :
331 60782 : get_nsec_time (&end);
332 :
333 60782 : measurement_raw[rep] = get_time_nsec_diff (&start, &end);
334 : }
335 :
336 : /* Return median of repeated measurements. */
337 30391 : qsort (measurement_raw, num_repetitions, sizeof (measurement_raw[0]),
338 : double_cmp);
339 :
340 30391 : if (num_repetitions % 2 == 1)
341 0 : return measurement_raw[num_repetitions / 2];
342 :
343 60782 : res = measurement_raw[num_repetitions / 2]
344 30391 : + measurement_raw[num_repetitions / 2 - 1];
345 30391 : return res / 2;
346 : }
347 :
348 :
349 : unsigned int
350 442 : adjust_loop_iterations_to_timer_accuracy (struct bench_obj *obj, void *buffer,
351 : double *measurement_raw)
352 : {
353 442 : const double increase_thres = 3.0;
354 : double tmp, nsecs;
355 : unsigned int loop_iterations;
356 : unsigned int test_bufsize;
357 :
358 442 : test_bufsize = obj->min_bufsize;
359 442 : if (test_bufsize == 0)
360 0 : test_bufsize += obj->step_size;
361 :
362 442 : loop_iterations = 0;
363 : do
364 : {
365 : /* Increase loop iterations until we get other results than zero. */
366 884 : nsecs =
367 442 : do_bench_obj_measurement (obj, buffer, test_bufsize,
368 : measurement_raw, ++loop_iterations);
369 : }
370 442 : while (nsecs < 1.0 - 0.1);
371 : do
372 : {
373 : /* Increase loop iterations until we get reasonable increase for elapsed time. */
374 6572 : tmp =
375 3286 : do_bench_obj_measurement (obj, buffer, test_bufsize,
376 : measurement_raw, ++loop_iterations);
377 : }
378 3286 : while (tmp < nsecs * (increase_thres - 0.1));
379 :
380 442 : return loop_iterations;
381 : }
382 :
383 :
384 : /* Benchmark and return linear regression slope in nanoseconds per byte. */
385 : double
386 442 : do_slope_benchmark (struct bench_obj *obj)
387 : {
388 : unsigned int num_measurements;
389 442 : double *measurements = NULL;
390 442 : double *measurement_raw = NULL;
391 : double slope, overhead;
392 : unsigned int loop_iterations, midx, i;
393 442 : unsigned char *real_buffer = NULL;
394 : unsigned char *buffer;
395 : size_t cur_bufsize;
396 : int err;
397 :
398 442 : err = obj->ops->initialize (obj);
399 442 : if (err < 0)
400 0 : return -1;
401 :
402 442 : num_measurements = get_num_measurements (obj);
403 442 : measurements = calloc (num_measurements, sizeof (*measurements));
404 442 : if (!measurements)
405 0 : goto err_free;
406 :
407 442 : measurement_raw =
408 442 : calloc (obj->num_measure_repetitions, sizeof (*measurement_raw));
409 442 : if (!measurement_raw)
410 0 : goto err_free;
411 :
412 884 : if (num_measurements < 1 || obj->num_measure_repetitions < 1 ||
413 884 : obj->max_bufsize < 1 || obj->min_bufsize > obj->max_bufsize)
414 : goto err_free;
415 :
416 442 : real_buffer = malloc (obj->max_bufsize + 128 + unaligned_mode);
417 442 : if (!real_buffer)
418 0 : goto err_free;
419 : /* Get aligned buffer */
420 442 : buffer = real_buffer;
421 442 : buffer += 128 - ((real_buffer - (unsigned char *) 0) & (128 - 1));
422 442 : if (unaligned_mode)
423 0 : buffer += unaligned_mode; /* Make buffer unaligned */
424 :
425 1806570 : for (i = 0; i < obj->max_bufsize; i++)
426 1806128 : buffer[i] = 0x55 ^ (-i);
427 :
428 : /* Adjust number of loop iterations up to timer accuracy. */
429 442 : loop_iterations = adjust_loop_iterations_to_timer_accuracy (obj, buffer,
430 : measurement_raw);
431 :
432 : /* Perform measurements */
433 27547 : for (midx = 0, cur_bufsize = obj->min_bufsize;
434 26663 : cur_bufsize <= obj->max_bufsize; cur_bufsize += obj->step_size, midx++)
435 : {
436 53326 : measurements[midx] =
437 26663 : do_bench_obj_measurement (obj, buffer, cur_bufsize, measurement_raw,
438 : loop_iterations);
439 26663 : measurements[midx] /= loop_iterations;
440 : }
441 :
442 442 : assert (midx == num_measurements);
443 :
444 442 : slope =
445 : get_slope (&get_bench_obj_point_x, obj, measurements, num_measurements,
446 : &overhead);
447 :
448 442 : free (measurement_raw);
449 442 : free (measurements);
450 442 : free (real_buffer);
451 442 : obj->ops->finalize (obj);
452 :
453 442 : return slope;
454 :
455 : err_free:
456 0 : if (measurement_raw)
457 0 : free (measurement_raw);
458 0 : if (measurements)
459 0 : free (measurements);
460 0 : if (real_buffer)
461 0 : free (real_buffer);
462 0 : obj->ops->finalize (obj);
463 :
464 0 : return -1;
465 : }
466 :
467 :
468 : /********************************************************** Printing results. */
469 :
470 : static void
471 857 : double_to_str (char *out, size_t outlen, double value)
472 : {
473 : const char *fmt;
474 :
475 857 : if (value < 1.0)
476 52 : fmt = "%.3f";
477 805 : else if (value < 100.0)
478 531 : fmt = "%.2f";
479 : else
480 274 : fmt = "%.1f";
481 :
482 857 : snprintf (out, outlen, fmt, value);
483 857 : }
484 :
485 : static void
486 0 : bench_print_result_csv (double nsecs_per_byte)
487 : {
488 : double cycles_per_byte, mbytes_per_sec;
489 : char nsecpbyte_buf[16];
490 : char mbpsec_buf[16];
491 : char cpbyte_buf[16];
492 :
493 0 : *cpbyte_buf = 0;
494 :
495 0 : double_to_str (nsecpbyte_buf, sizeof (nsecpbyte_buf), nsecs_per_byte);
496 :
497 : /* If user didn't provide CPU speed, we cannot show cycles/byte results. */
498 0 : if (cpu_ghz > 0.0)
499 : {
500 0 : cycles_per_byte = nsecs_per_byte * cpu_ghz;
501 0 : double_to_str (cpbyte_buf, sizeof (cpbyte_buf), cycles_per_byte);
502 : }
503 :
504 0 : mbytes_per_sec =
505 0 : (1000.0 * 1000.0 * 1000.0) / (nsecs_per_byte * 1024 * 1024);
506 0 : double_to_str (mbpsec_buf, sizeof (mbpsec_buf), mbytes_per_sec);
507 :
508 : /* We print two empty fields to allow for future enhancements. */
509 0 : printf ("%s,%s,%s,,,%s,ns/B,%s,MiB/s,%s,c/B\n",
510 : current_section_name,
511 0 : current_algo_name? current_algo_name : "",
512 0 : current_mode_name? current_mode_name : "",
513 : nsecpbyte_buf,
514 : mbpsec_buf,
515 : cpbyte_buf);
516 :
517 0 : }
518 :
519 : static void
520 415 : bench_print_result_std (double nsecs_per_byte)
521 : {
522 : double cycles_per_byte, mbytes_per_sec;
523 : char nsecpbyte_buf[16];
524 : char mbpsec_buf[16];
525 : char cpbyte_buf[16];
526 :
527 415 : double_to_str (nsecpbyte_buf, sizeof (nsecpbyte_buf), nsecs_per_byte);
528 :
529 : /* If user didn't provide CPU speed, we cannot show cycles/byte results. */
530 415 : if (cpu_ghz > 0.0)
531 : {
532 0 : cycles_per_byte = nsecs_per_byte * cpu_ghz;
533 0 : double_to_str (cpbyte_buf, sizeof (cpbyte_buf), cycles_per_byte);
534 : }
535 : else
536 415 : strcpy (cpbyte_buf, "-");
537 :
538 415 : mbytes_per_sec =
539 415 : (1000.0 * 1000.0 * 1000.0) / (nsecs_per_byte * 1024 * 1024);
540 415 : double_to_str (mbpsec_buf, sizeof (mbpsec_buf), mbytes_per_sec);
541 :
542 415 : printf ("%9s ns/B %9s MiB/s %9s c/B\n",
543 : nsecpbyte_buf, mbpsec_buf, cpbyte_buf);
544 415 : }
545 :
546 : static void
547 415 : bench_print_result (double nsecs_per_byte)
548 : {
549 415 : if (csv_mode)
550 0 : bench_print_result_csv (nsecs_per_byte);
551 : else
552 415 : bench_print_result_std (nsecs_per_byte);
553 415 : }
554 :
555 : static void
556 4 : bench_print_section (const char *section_name, const char *print_name)
557 : {
558 4 : if (csv_mode)
559 : {
560 0 : gcry_free (current_section_name);
561 0 : current_section_name = gcry_xstrdup (section_name);
562 : }
563 : else
564 4 : printf ("%s:\n", print_name);
565 4 : }
566 :
567 : static void
568 26 : bench_print_header (int algo_width, const char *algo_name)
569 : {
570 26 : if (csv_mode)
571 : {
572 0 : gcry_free (current_algo_name);
573 0 : current_algo_name = gcry_xstrdup (algo_name);
574 : }
575 : else
576 : {
577 26 : if (algo_width < 0)
578 0 : printf (" %-*s | ", -algo_width, algo_name);
579 : else
580 26 : printf (" %-*s | ", algo_width, algo_name);
581 26 : printf ("%14s %15s %13s\n", "nanosecs/byte", "mebibytes/sec",
582 : "cycles/byte");
583 : }
584 26 : }
585 :
586 : static void
587 99 : bench_print_algo (int algo_width, const char *algo_name)
588 : {
589 99 : if (csv_mode)
590 : {
591 0 : gcry_free (current_algo_name);
592 0 : current_algo_name = gcry_xstrdup (algo_name);
593 : }
594 : else
595 : {
596 99 : if (algo_width < 0)
597 99 : printf (" %-*s | ", -algo_width, algo_name);
598 : else
599 0 : printf (" %-*s | ", algo_width, algo_name);
600 : }
601 99 : }
602 :
603 : static void
604 343 : bench_print_mode (int width, const char *mode_name)
605 : {
606 343 : if (csv_mode)
607 : {
608 0 : gcry_free (current_mode_name);
609 0 : current_mode_name = gcry_xstrdup (mode_name);
610 : }
611 : else
612 : {
613 343 : if (width < 0)
614 0 : printf (" %-*s | ", -width, mode_name);
615 : else
616 343 : printf (" %*s | ", width, mode_name);
617 343 : fflush (stdout);
618 : }
619 343 : }
620 :
621 : static void
622 27 : bench_print_footer (int algo_width)
623 : {
624 27 : if (!csv_mode)
625 27 : printf (" %-*s =\n", algo_width, "");
626 27 : }
627 :
628 :
629 : /********************************************************* Cipher benchmarks. */
630 :
631 : struct bench_cipher_mode
632 : {
633 : int mode;
634 : const char *name;
635 : struct bench_ops *ops;
636 :
637 : int algo;
638 : };
639 :
640 :
641 : static int
642 319 : bench_encrypt_init (struct bench_obj *obj)
643 : {
644 319 : struct bench_cipher_mode *mode = obj->priv;
645 : gcry_cipher_hd_t hd;
646 : int err, keylen;
647 :
648 319 : obj->min_bufsize = BUF_START_SIZE;
649 319 : obj->max_bufsize = BUF_END_SIZE;
650 319 : obj->step_size = BUF_STEP_SIZE;
651 319 : obj->num_measure_repetitions = num_measurement_repetitions;
652 :
653 319 : err = gcry_cipher_open (&hd, mode->algo, mode->mode, 0);
654 319 : if (err)
655 : {
656 0 : fprintf (stderr, PGM ": error opening cipher `%s'\n",
657 : gcry_cipher_algo_name (mode->algo));
658 0 : exit (1);
659 : }
660 :
661 319 : keylen = gcry_cipher_get_algo_keylen (mode->algo);
662 319 : if (keylen)
663 319 : {
664 319 : char key[keylen];
665 : int i;
666 :
667 7289 : for (i = 0; i < keylen; i++)
668 6970 : key[i] = 0x33 ^ (11 - i);
669 :
670 319 : err = gcry_cipher_setkey (hd, key, keylen);
671 319 : if (err)
672 : {
673 0 : fprintf (stderr, PGM ": gcry_cipher_setkey failed: %s\n",
674 : gpg_strerror (err));
675 0 : gcry_cipher_close (hd);
676 0 : exit (1);
677 : }
678 : }
679 : else
680 : {
681 0 : fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n",
682 : gcry_cipher_algo_name (mode->algo));
683 0 : gcry_cipher_close (hd);
684 0 : exit (1);
685 : }
686 :
687 319 : obj->priv = hd;
688 :
689 319 : return 0;
690 : }
691 :
692 : static void
693 343 : bench_encrypt_free (struct bench_obj *obj)
694 : {
695 343 : gcry_cipher_hd_t hd = obj->priv;
696 :
697 343 : gcry_cipher_close (hd);
698 343 : }
699 :
700 : static void
701 182560 : bench_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
702 : {
703 182560 : gcry_cipher_hd_t hd = obj->priv;
704 : int err;
705 :
706 182560 : err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen);
707 182560 : if (err)
708 : {
709 0 : fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
710 : gpg_strerror (err));
711 0 : gcry_cipher_close (hd);
712 0 : exit (1);
713 : }
714 182560 : }
715 :
716 : static void
717 150532 : bench_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
718 : {
719 150532 : gcry_cipher_hd_t hd = obj->priv;
720 : int err;
721 :
722 150532 : err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen);
723 150532 : if (err)
724 : {
725 0 : fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
726 : gpg_strerror (err));
727 0 : gcry_cipher_close (hd);
728 0 : exit (1);
729 : }
730 150532 : }
731 :
732 : static struct bench_ops encrypt_ops = {
733 : &bench_encrypt_init,
734 : &bench_encrypt_free,
735 : &bench_encrypt_do_bench
736 : };
737 :
738 : static struct bench_ops decrypt_ops = {
739 : &bench_encrypt_init,
740 : &bench_encrypt_free,
741 : &bench_decrypt_do_bench
742 : };
743 :
744 :
745 : static int
746 24 : bench_xts_encrypt_init (struct bench_obj *obj)
747 : {
748 24 : struct bench_cipher_mode *mode = obj->priv;
749 : gcry_cipher_hd_t hd;
750 : int err, keylen;
751 :
752 : /* For XTS, benchmark with typical data-unit size (512 byte sectors). */
753 24 : obj->min_bufsize = 512;
754 24 : obj->max_bufsize = 16 * obj->min_bufsize;
755 24 : obj->step_size = obj->min_bufsize;
756 24 : obj->num_measure_repetitions = num_measurement_repetitions;
757 :
758 24 : err = gcry_cipher_open (&hd, mode->algo, mode->mode, 0);
759 24 : if (err)
760 : {
761 0 : fprintf (stderr, PGM ": error opening cipher `%s'\n",
762 : gcry_cipher_algo_name (mode->algo));
763 0 : exit (1);
764 : }
765 :
766 : /* Double key-length for XTS. */
767 24 : keylen = gcry_cipher_get_algo_keylen (mode->algo) * 2;
768 24 : if (keylen)
769 24 : {
770 24 : char key[keylen];
771 : int i;
772 :
773 1144 : for (i = 0; i < keylen; i++)
774 1120 : key[i] = 0x33 ^ (11 - i);
775 :
776 24 : err = gcry_cipher_setkey (hd, key, keylen);
777 24 : if (err)
778 : {
779 0 : fprintf (stderr, PGM ": gcry_cipher_setkey failed: %s\n",
780 : gpg_strerror (err));
781 0 : gcry_cipher_close (hd);
782 0 : exit (1);
783 : }
784 : }
785 : else
786 : {
787 0 : fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n",
788 : gcry_cipher_algo_name (mode->algo));
789 0 : gcry_cipher_close (hd);
790 0 : exit (1);
791 : }
792 :
793 24 : obj->priv = hd;
794 :
795 24 : return 0;
796 : }
797 :
798 : static void
799 1788 : bench_xts_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
800 : {
801 1788 : gcry_cipher_hd_t hd = obj->priv;
802 : unsigned int pos;
803 : static const char tweak[16] = { 0xff, 0xff, 0xfe, };
804 1788 : size_t sectorlen = obj->step_size;
805 1788 : char *cbuf = buf;
806 : int err;
807 :
808 1788 : gcry_cipher_setiv (hd, tweak, sizeof (tweak));
809 :
810 : /* Process each sector separately. */
811 :
812 15096 : for (pos = 0; pos < buflen; pos += sectorlen, cbuf += sectorlen)
813 : {
814 13308 : err = gcry_cipher_encrypt (hd, cbuf, sectorlen, cbuf, sectorlen);
815 13308 : if (err)
816 : {
817 0 : fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
818 : gpg_strerror (err));
819 0 : gcry_cipher_close (hd);
820 0 : exit (1);
821 : }
822 : }
823 1788 : }
824 :
825 : static void
826 1738 : bench_xts_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
827 : {
828 1738 : gcry_cipher_hd_t hd = obj->priv;
829 : unsigned int pos;
830 : static const char tweak[16] = { 0xff, 0xff, 0xfe, };
831 1738 : size_t sectorlen = obj->step_size;
832 1738 : char *cbuf = buf;
833 : int err;
834 :
835 1738 : gcry_cipher_setiv (hd, tweak, sizeof (tweak));
836 :
837 : /* Process each sector separately. */
838 :
839 14756 : for (pos = 0; pos < buflen; pos += sectorlen, cbuf += sectorlen)
840 : {
841 13018 : err = gcry_cipher_decrypt (hd, cbuf, sectorlen, cbuf, sectorlen);
842 13018 : if (err)
843 : {
844 0 : fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
845 : gpg_strerror (err));
846 0 : gcry_cipher_close (hd);
847 0 : exit (1);
848 : }
849 : }
850 1738 : }
851 :
852 : static struct bench_ops xts_encrypt_ops = {
853 : &bench_xts_encrypt_init,
854 : &bench_encrypt_free,
855 : &bench_xts_encrypt_do_bench
856 : };
857 :
858 : static struct bench_ops xts_decrypt_ops = {
859 : &bench_xts_encrypt_init,
860 : &bench_encrypt_free,
861 : &bench_xts_decrypt_do_bench
862 : };
863 :
864 :
865 : static void
866 17574 : bench_ccm_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
867 : {
868 17574 : gcry_cipher_hd_t hd = obj->priv;
869 : int err;
870 : char tag[8];
871 17574 : char nonce[11] = { 0x80, 0x01, };
872 : u64 params[3];
873 :
874 17574 : gcry_cipher_setiv (hd, nonce, sizeof (nonce));
875 :
876 : /* Set CCM lengths */
877 17574 : params[0] = buflen;
878 17574 : params[1] = 0; /*aadlen */
879 17574 : params[2] = sizeof (tag);
880 17574 : err =
881 17574 : gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof (params));
882 17574 : if (err)
883 : {
884 0 : fprintf (stderr, PGM ": gcry_cipher_ctl failed: %s\n",
885 : gpg_strerror (err));
886 0 : gcry_cipher_close (hd);
887 0 : exit (1);
888 : }
889 :
890 17574 : err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen);
891 17574 : if (err)
892 : {
893 0 : fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
894 : gpg_strerror (err));
895 0 : gcry_cipher_close (hd);
896 0 : exit (1);
897 : }
898 :
899 17574 : err = gcry_cipher_gettag (hd, tag, sizeof (tag));
900 17574 : if (err)
901 : {
902 0 : fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
903 : gpg_strerror (err));
904 0 : gcry_cipher_close (hd);
905 0 : exit (1);
906 : }
907 17574 : }
908 :
909 : static void
910 11346 : bench_ccm_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
911 : {
912 11346 : gcry_cipher_hd_t hd = obj->priv;
913 : int err;
914 11346 : char tag[8] = { 0, };
915 11346 : char nonce[11] = { 0x80, 0x01, };
916 : u64 params[3];
917 :
918 11346 : gcry_cipher_setiv (hd, nonce, sizeof (nonce));
919 :
920 : /* Set CCM lengths */
921 11346 : params[0] = buflen;
922 11346 : params[1] = 0; /*aadlen */
923 11346 : params[2] = sizeof (tag);
924 11346 : err =
925 11346 : gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof (params));
926 11346 : if (err)
927 : {
928 0 : fprintf (stderr, PGM ": gcry_cipher_ctl failed: %s\n",
929 : gpg_strerror (err));
930 0 : gcry_cipher_close (hd);
931 0 : exit (1);
932 : }
933 :
934 11346 : err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen);
935 11346 : if (err)
936 : {
937 0 : fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
938 : gpg_strerror (err));
939 0 : gcry_cipher_close (hd);
940 0 : exit (1);
941 : }
942 :
943 11346 : err = gcry_cipher_checktag (hd, tag, sizeof (tag));
944 11346 : if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
945 11346 : err = gpg_error (GPG_ERR_NO_ERROR);
946 11346 : if (err)
947 : {
948 0 : fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
949 : gpg_strerror (err));
950 0 : gcry_cipher_close (hd);
951 0 : exit (1);
952 : }
953 11346 : }
954 :
955 : static void
956 15700 : bench_ccm_authenticate_do_bench (struct bench_obj *obj, void *buf,
957 : size_t buflen)
958 : {
959 15700 : gcry_cipher_hd_t hd = obj->priv;
960 : int err;
961 15700 : char tag[8] = { 0, };
962 15700 : char nonce[11] = { 0x80, 0x01, };
963 : u64 params[3];
964 15700 : char data = 0xff;
965 :
966 15700 : gcry_cipher_setiv (hd, nonce, sizeof (nonce));
967 :
968 : /* Set CCM lengths */
969 15700 : params[0] = sizeof (data); /*datalen */
970 15700 : params[1] = buflen; /*aadlen */
971 15700 : params[2] = sizeof (tag);
972 15700 : err =
973 15700 : gcry_cipher_ctl (hd, GCRYCTL_SET_CCM_LENGTHS, params, sizeof (params));
974 15700 : if (err)
975 : {
976 0 : fprintf (stderr, PGM ": gcry_cipher_ctl failed: %s\n",
977 : gpg_strerror (err));
978 0 : gcry_cipher_close (hd);
979 0 : exit (1);
980 : }
981 :
982 15700 : err = gcry_cipher_authenticate (hd, buf, buflen);
983 15700 : if (err)
984 : {
985 0 : fprintf (stderr, PGM ": gcry_cipher_authenticate failed: %s\n",
986 : gpg_strerror (err));
987 0 : gcry_cipher_close (hd);
988 0 : exit (1);
989 : }
990 :
991 15700 : err = gcry_cipher_encrypt (hd, &data, sizeof (data), &data, sizeof (data));
992 15700 : if (err)
993 : {
994 0 : fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
995 : gpg_strerror (err));
996 0 : gcry_cipher_close (hd);
997 0 : exit (1);
998 : }
999 :
1000 15700 : err = gcry_cipher_gettag (hd, tag, sizeof (tag));
1001 15700 : if (err)
1002 : {
1003 0 : fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
1004 : gpg_strerror (err));
1005 0 : gcry_cipher_close (hd);
1006 0 : exit (1);
1007 : }
1008 15700 : }
1009 :
1010 : static struct bench_ops ccm_encrypt_ops = {
1011 : &bench_encrypt_init,
1012 : &bench_encrypt_free,
1013 : &bench_ccm_encrypt_do_bench
1014 : };
1015 :
1016 : static struct bench_ops ccm_decrypt_ops = {
1017 : &bench_encrypt_init,
1018 : &bench_encrypt_free,
1019 : &bench_ccm_decrypt_do_bench
1020 : };
1021 :
1022 : static struct bench_ops ccm_authenticate_ops = {
1023 : &bench_encrypt_init,
1024 : &bench_encrypt_free,
1025 : &bench_ccm_authenticate_do_bench
1026 : };
1027 :
1028 :
1029 : static void
1030 29550 : bench_aead_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen,
1031 : const char *nonce, size_t noncelen)
1032 : {
1033 29550 : gcry_cipher_hd_t hd = obj->priv;
1034 : int err;
1035 : char tag[16];
1036 :
1037 29550 : gcry_cipher_setiv (hd, nonce, noncelen);
1038 :
1039 29550 : gcry_cipher_final (hd);
1040 29550 : err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen);
1041 29550 : if (err)
1042 : {
1043 0 : fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
1044 : gpg_strerror (err));
1045 0 : gcry_cipher_close (hd);
1046 0 : exit (1);
1047 : }
1048 :
1049 29550 : err = gcry_cipher_gettag (hd, tag, sizeof (tag));
1050 29550 : if (err)
1051 : {
1052 0 : fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
1053 : gpg_strerror (err));
1054 0 : gcry_cipher_close (hd);
1055 0 : exit (1);
1056 : }
1057 29550 : }
1058 :
1059 : static void
1060 19790 : bench_aead_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen,
1061 : const char *nonce, size_t noncelen)
1062 : {
1063 19790 : gcry_cipher_hd_t hd = obj->priv;
1064 : int err;
1065 19790 : char tag[16] = { 0, };
1066 :
1067 19790 : gcry_cipher_setiv (hd, nonce, noncelen);
1068 :
1069 19790 : gcry_cipher_final (hd);
1070 19790 : err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen);
1071 19790 : if (err)
1072 : {
1073 0 : fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
1074 : gpg_strerror (err));
1075 0 : gcry_cipher_close (hd);
1076 0 : exit (1);
1077 : }
1078 :
1079 19790 : err = gcry_cipher_checktag (hd, tag, sizeof (tag));
1080 19790 : if (gpg_err_code (err) == GPG_ERR_CHECKSUM)
1081 19790 : err = gpg_error (GPG_ERR_NO_ERROR);
1082 19790 : if (err)
1083 : {
1084 0 : fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
1085 : gpg_strerror (err));
1086 0 : gcry_cipher_close (hd);
1087 0 : exit (1);
1088 : }
1089 19790 : }
1090 :
1091 : static void
1092 20376 : bench_aead_authenticate_do_bench (struct bench_obj *obj, void *buf,
1093 : size_t buflen, const char *nonce,
1094 : size_t noncelen)
1095 : {
1096 20376 : gcry_cipher_hd_t hd = obj->priv;
1097 : int err;
1098 20376 : char tag[16] = { 0, };
1099 20376 : char data = 0xff;
1100 :
1101 20376 : err = gcry_cipher_setiv (hd, nonce, noncelen);
1102 20376 : if (err)
1103 : {
1104 0 : fprintf (stderr, PGM ": gcry_cipher_setiv failed: %s\n",
1105 : gpg_strerror (err));
1106 0 : gcry_cipher_close (hd);
1107 0 : exit (1);
1108 : }
1109 :
1110 20376 : err = gcry_cipher_authenticate (hd, buf, buflen);
1111 20376 : if (err)
1112 : {
1113 0 : fprintf (stderr, PGM ": gcry_cipher_authenticate failed: %s\n",
1114 : gpg_strerror (err));
1115 0 : gcry_cipher_close (hd);
1116 0 : exit (1);
1117 : }
1118 :
1119 20376 : gcry_cipher_final (hd);
1120 20376 : err = gcry_cipher_encrypt (hd, &data, sizeof (data), &data, sizeof (data));
1121 20376 : if (err)
1122 : {
1123 0 : fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n",
1124 : gpg_strerror (err));
1125 0 : gcry_cipher_close (hd);
1126 0 : exit (1);
1127 : }
1128 :
1129 20376 : err = gcry_cipher_gettag (hd, tag, sizeof (tag));
1130 20376 : if (err)
1131 : {
1132 0 : fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n",
1133 : gpg_strerror (err));
1134 0 : gcry_cipher_close (hd);
1135 0 : exit (1);
1136 : }
1137 20376 : }
1138 :
1139 :
1140 : static void
1141 16922 : bench_gcm_encrypt_do_bench (struct bench_obj *obj, void *buf,
1142 : size_t buflen)
1143 : {
1144 16922 : char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
1145 : 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 };
1146 16922 : bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
1147 16922 : }
1148 :
1149 : static void
1150 10372 : bench_gcm_decrypt_do_bench (struct bench_obj *obj, void *buf,
1151 : size_t buflen)
1152 : {
1153 10372 : char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
1154 : 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 };
1155 10372 : bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
1156 10372 : }
1157 :
1158 : static void
1159 11234 : bench_gcm_authenticate_do_bench (struct bench_obj *obj, void *buf,
1160 : size_t buflen)
1161 : {
1162 11234 : char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
1163 : 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88 };
1164 11234 : bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
1165 11234 : }
1166 :
1167 : static struct bench_ops gcm_encrypt_ops = {
1168 : &bench_encrypt_init,
1169 : &bench_encrypt_free,
1170 : &bench_gcm_encrypt_do_bench
1171 : };
1172 :
1173 : static struct bench_ops gcm_decrypt_ops = {
1174 : &bench_encrypt_init,
1175 : &bench_encrypt_free,
1176 : &bench_gcm_decrypt_do_bench
1177 : };
1178 :
1179 : static struct bench_ops gcm_authenticate_ops = {
1180 : &bench_encrypt_init,
1181 : &bench_encrypt_free,
1182 : &bench_gcm_authenticate_do_bench
1183 : };
1184 :
1185 :
1186 : static void
1187 11218 : bench_ocb_encrypt_do_bench (struct bench_obj *obj, void *buf,
1188 : size_t buflen)
1189 : {
1190 11218 : char nonce[15] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
1191 : 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
1192 : 0x00, 0x00, 0x01 };
1193 11218 : bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
1194 11218 : }
1195 :
1196 : static void
1197 8596 : bench_ocb_decrypt_do_bench (struct bench_obj *obj, void *buf,
1198 : size_t buflen)
1199 : {
1200 8596 : char nonce[15] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
1201 : 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
1202 : 0x00, 0x00, 0x01 };
1203 8596 : bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
1204 8596 : }
1205 :
1206 : static void
1207 8462 : bench_ocb_authenticate_do_bench (struct bench_obj *obj, void *buf,
1208 : size_t buflen)
1209 : {
1210 8462 : char nonce[15] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce,
1211 : 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
1212 : 0x00, 0x00, 0x01 };
1213 8462 : bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
1214 8462 : }
1215 :
1216 : static struct bench_ops ocb_encrypt_ops = {
1217 : &bench_encrypt_init,
1218 : &bench_encrypt_free,
1219 : &bench_ocb_encrypt_do_bench
1220 : };
1221 :
1222 : static struct bench_ops ocb_decrypt_ops = {
1223 : &bench_encrypt_init,
1224 : &bench_encrypt_free,
1225 : &bench_ocb_decrypt_do_bench
1226 : };
1227 :
1228 : static struct bench_ops ocb_authenticate_ops = {
1229 : &bench_encrypt_init,
1230 : &bench_encrypt_free,
1231 : &bench_ocb_authenticate_do_bench
1232 : };
1233 :
1234 :
1235 : static void
1236 1410 : bench_poly1305_encrypt_do_bench (struct bench_obj *obj, void *buf,
1237 : size_t buflen)
1238 : {
1239 1410 : char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad };
1240 1410 : bench_aead_encrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
1241 1410 : }
1242 :
1243 : static void
1244 822 : bench_poly1305_decrypt_do_bench (struct bench_obj *obj, void *buf,
1245 : size_t buflen)
1246 : {
1247 822 : char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad };
1248 822 : bench_aead_decrypt_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
1249 822 : }
1250 :
1251 : static void
1252 680 : bench_poly1305_authenticate_do_bench (struct bench_obj *obj, void *buf,
1253 : size_t buflen)
1254 : {
1255 680 : char nonce[8] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad };
1256 680 : bench_aead_authenticate_do_bench (obj, buf, buflen, nonce, sizeof(nonce));
1257 680 : }
1258 :
1259 : static struct bench_ops poly1305_encrypt_ops = {
1260 : &bench_encrypt_init,
1261 : &bench_encrypt_free,
1262 : &bench_poly1305_encrypt_do_bench
1263 : };
1264 :
1265 : static struct bench_ops poly1305_decrypt_ops = {
1266 : &bench_encrypt_init,
1267 : &bench_encrypt_free,
1268 : &bench_poly1305_decrypt_do_bench
1269 : };
1270 :
1271 : static struct bench_ops poly1305_authenticate_ops = {
1272 : &bench_encrypt_init,
1273 : &bench_encrypt_free,
1274 : &bench_poly1305_authenticate_do_bench
1275 : };
1276 :
1277 :
1278 : static struct bench_cipher_mode cipher_modes[] = {
1279 : {GCRY_CIPHER_MODE_ECB, "ECB enc", &encrypt_ops},
1280 : {GCRY_CIPHER_MODE_ECB, "ECB dec", &decrypt_ops},
1281 : {GCRY_CIPHER_MODE_CBC, "CBC enc", &encrypt_ops},
1282 : {GCRY_CIPHER_MODE_CBC, "CBC dec", &decrypt_ops},
1283 : {GCRY_CIPHER_MODE_CFB, "CFB enc", &encrypt_ops},
1284 : {GCRY_CIPHER_MODE_CFB, "CFB dec", &decrypt_ops},
1285 : {GCRY_CIPHER_MODE_OFB, "OFB enc", &encrypt_ops},
1286 : {GCRY_CIPHER_MODE_OFB, "OFB dec", &decrypt_ops},
1287 : {GCRY_CIPHER_MODE_CTR, "CTR enc", &encrypt_ops},
1288 : {GCRY_CIPHER_MODE_CTR, "CTR dec", &decrypt_ops},
1289 : {GCRY_CIPHER_MODE_XTS, "XTS enc", &xts_encrypt_ops},
1290 : {GCRY_CIPHER_MODE_XTS, "XTS dec", &xts_decrypt_ops},
1291 : {GCRY_CIPHER_MODE_CCM, "CCM enc", &ccm_encrypt_ops},
1292 : {GCRY_CIPHER_MODE_CCM, "CCM dec", &ccm_decrypt_ops},
1293 : {GCRY_CIPHER_MODE_CCM, "CCM auth", &ccm_authenticate_ops},
1294 : {GCRY_CIPHER_MODE_GCM, "GCM enc", &gcm_encrypt_ops},
1295 : {GCRY_CIPHER_MODE_GCM, "GCM dec", &gcm_decrypt_ops},
1296 : {GCRY_CIPHER_MODE_GCM, "GCM auth", &gcm_authenticate_ops},
1297 : {GCRY_CIPHER_MODE_OCB, "OCB enc", &ocb_encrypt_ops},
1298 : {GCRY_CIPHER_MODE_OCB, "OCB dec", &ocb_decrypt_ops},
1299 : {GCRY_CIPHER_MODE_OCB, "OCB auth", &ocb_authenticate_ops},
1300 : {GCRY_CIPHER_MODE_POLY1305, "POLY1305 enc", &poly1305_encrypt_ops},
1301 : {GCRY_CIPHER_MODE_POLY1305, "POLY1305 dec", &poly1305_decrypt_ops},
1302 : {GCRY_CIPHER_MODE_POLY1305, "POLY1305 auth", &poly1305_authenticate_ops},
1303 : {0},
1304 : };
1305 :
1306 :
1307 : static void
1308 576 : cipher_bench_one (int algo, struct bench_cipher_mode *pmode)
1309 : {
1310 576 : struct bench_cipher_mode mode = *pmode;
1311 576 : struct bench_obj obj = { 0 };
1312 : double result;
1313 : unsigned int blklen;
1314 :
1315 576 : mode.algo = algo;
1316 :
1317 : /* Check if this mode is ok */
1318 576 : blklen = gcry_cipher_get_algo_blklen (algo);
1319 576 : if (!blklen)
1320 233 : return;
1321 :
1322 : /* Stream cipher? Only test with "ECB" and POLY1305. */
1323 664 : if (blklen == 1 && (mode.mode != GCRY_CIPHER_MODE_ECB &&
1324 88 : mode.mode != GCRY_CIPHER_MODE_POLY1305))
1325 76 : return;
1326 500 : if (blklen == 1 && mode.mode == GCRY_CIPHER_MODE_ECB)
1327 : {
1328 8 : mode.mode = GCRY_CIPHER_MODE_STREAM;
1329 8 : mode.name = mode.ops == &encrypt_ops ? "STREAM enc" : "STREAM dec";
1330 : }
1331 :
1332 : /* Poly1305 has restriction for cipher algorithm */
1333 500 : if (mode.mode == GCRY_CIPHER_MODE_POLY1305 && algo != GCRY_CIPHER_CHACHA20)
1334 69 : return;
1335 :
1336 : /* CCM has restrictions for block-size */
1337 431 : if (mode.mode == GCRY_CIPHER_MODE_CCM && blklen != GCRY_CCM_BLOCK_LEN)
1338 24 : return;
1339 :
1340 : /* GCM has restrictions for block-size */
1341 407 : if (mode.mode == GCRY_CIPHER_MODE_GCM && blklen != GCRY_GCM_BLOCK_LEN)
1342 24 : return;
1343 :
1344 : /* XTS has restrictions for block-size */
1345 383 : if (mode.mode == GCRY_CIPHER_MODE_XTS && blklen != GCRY_XTS_BLOCK_LEN)
1346 16 : return;
1347 :
1348 : /* Our OCB implementaion has restrictions for block-size. */
1349 367 : if (mode.mode == GCRY_CIPHER_MODE_OCB && blklen != GCRY_OCB_BLOCK_LEN)
1350 24 : return;
1351 :
1352 343 : bench_print_mode (14, mode.name);
1353 :
1354 343 : obj.ops = mode.ops;
1355 343 : obj.priv = &mode;
1356 :
1357 343 : result = do_slope_benchmark (&obj);
1358 :
1359 343 : bench_print_result (result);
1360 : }
1361 :
1362 :
1363 : static void
1364 24 : _cipher_bench (int algo)
1365 : {
1366 : const char *algoname;
1367 : int i;
1368 :
1369 24 : algoname = gcry_cipher_algo_name (algo);
1370 :
1371 24 : bench_print_header (14, algoname);
1372 :
1373 600 : for (i = 0; cipher_modes[i].mode; i++)
1374 576 : cipher_bench_one (algo, &cipher_modes[i]);
1375 :
1376 24 : bench_print_footer (14);
1377 24 : }
1378 :
1379 :
1380 : void
1381 1 : cipher_bench (char **argv, int argc)
1382 : {
1383 : int i, algo;
1384 :
1385 1 : bench_print_section ("cipher", "Cipher");
1386 :
1387 1 : if (argv && argc)
1388 : {
1389 0 : for (i = 0; i < argc; i++)
1390 : {
1391 0 : algo = gcry_cipher_map_name (argv[i]);
1392 0 : if (algo)
1393 0 : _cipher_bench (algo);
1394 : }
1395 : }
1396 : else
1397 : {
1398 400 : for (i = 1; i < 400; i++)
1399 399 : if (!gcry_cipher_test_algo (i))
1400 24 : _cipher_bench (i);
1401 : }
1402 1 : }
1403 :
1404 :
1405 : /*********************************************************** Hash benchmarks. */
1406 :
1407 : struct bench_hash_mode
1408 : {
1409 : const char *name;
1410 : struct bench_ops *ops;
1411 :
1412 : int algo;
1413 : };
1414 :
1415 :
1416 : static int
1417 33 : bench_hash_init (struct bench_obj *obj)
1418 : {
1419 33 : struct bench_hash_mode *mode = obj->priv;
1420 : gcry_md_hd_t hd;
1421 : int err;
1422 :
1423 33 : obj->min_bufsize = BUF_START_SIZE;
1424 33 : obj->max_bufsize = BUF_END_SIZE;
1425 33 : obj->step_size = BUF_STEP_SIZE;
1426 33 : obj->num_measure_repetitions = num_measurement_repetitions;
1427 :
1428 33 : err = gcry_md_open (&hd, mode->algo, 0);
1429 33 : if (err)
1430 : {
1431 0 : fprintf (stderr, PGM ": error opening hash `%s'\n",
1432 : gcry_md_algo_name (mode->algo));
1433 0 : exit (1);
1434 : }
1435 :
1436 33 : obj->priv = hd;
1437 :
1438 33 : return 0;
1439 : }
1440 :
1441 : static void
1442 33 : bench_hash_free (struct bench_obj *obj)
1443 : {
1444 33 : gcry_md_hd_t hd = obj->priv;
1445 :
1446 33 : gcry_md_close (hd);
1447 33 : }
1448 :
1449 : static void
1450 33168 : bench_hash_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
1451 : {
1452 33168 : gcry_md_hd_t hd = obj->priv;
1453 :
1454 33168 : gcry_md_reset (hd);
1455 33168 : gcry_md_write (hd, buf, buflen);
1456 33168 : gcry_md_final (hd);
1457 33168 : }
1458 :
1459 : static struct bench_ops hash_ops = {
1460 : &bench_hash_init,
1461 : &bench_hash_free,
1462 : &bench_hash_do_bench
1463 : };
1464 :
1465 :
1466 : static struct bench_hash_mode hash_modes[] = {
1467 : {"", &hash_ops},
1468 : {0},
1469 : };
1470 :
1471 :
1472 : static void
1473 33 : hash_bench_one (int algo, struct bench_hash_mode *pmode)
1474 : {
1475 33 : struct bench_hash_mode mode = *pmode;
1476 33 : struct bench_obj obj = { 0 };
1477 : double result;
1478 :
1479 33 : mode.algo = algo;
1480 :
1481 33 : if (mode.name[0] == '\0')
1482 33 : bench_print_algo (-14, gcry_md_algo_name (algo));
1483 : else
1484 0 : bench_print_algo (14, mode.name);
1485 :
1486 33 : obj.ops = mode.ops;
1487 33 : obj.priv = &mode;
1488 :
1489 33 : result = do_slope_benchmark (&obj);
1490 :
1491 33 : bench_print_result (result);
1492 33 : }
1493 :
1494 : static void
1495 33 : _hash_bench (int algo)
1496 : {
1497 : int i;
1498 :
1499 66 : for (i = 0; hash_modes[i].name; i++)
1500 33 : hash_bench_one (algo, &hash_modes[i]);
1501 33 : }
1502 :
1503 : void
1504 1 : hash_bench (char **argv, int argc)
1505 : {
1506 : int i, algo;
1507 :
1508 1 : bench_print_section ("hash", "Hash");
1509 1 : bench_print_header (14, "");
1510 :
1511 1 : if (argv && argc)
1512 : {
1513 0 : for (i = 0; i < argc; i++)
1514 : {
1515 0 : algo = gcry_md_map_name (argv[i]);
1516 0 : if (algo)
1517 0 : _hash_bench (algo);
1518 : }
1519 : }
1520 : else
1521 : {
1522 400 : for (i = 1; i < 400; i++)
1523 399 : if (!gcry_md_test_algo (i))
1524 33 : _hash_bench (i);
1525 : }
1526 :
1527 1 : bench_print_footer (14);
1528 1 : }
1529 :
1530 :
1531 : /************************************************************ MAC benchmarks. */
1532 :
1533 : struct bench_mac_mode
1534 : {
1535 : const char *name;
1536 : struct bench_ops *ops;
1537 :
1538 : int algo;
1539 : };
1540 :
1541 :
1542 : static int
1543 39 : bench_mac_init (struct bench_obj *obj)
1544 : {
1545 39 : struct bench_mac_mode *mode = obj->priv;
1546 : gcry_mac_hd_t hd;
1547 : int err;
1548 : unsigned int keylen;
1549 : void *key;
1550 :
1551 39 : obj->min_bufsize = BUF_START_SIZE;
1552 39 : obj->max_bufsize = BUF_END_SIZE;
1553 39 : obj->step_size = BUF_STEP_SIZE;
1554 39 : obj->num_measure_repetitions = num_measurement_repetitions;
1555 :
1556 39 : keylen = gcry_mac_get_algo_keylen (mode->algo);
1557 39 : if (keylen == 0)
1558 0 : keylen = 32;
1559 39 : key = malloc (keylen);
1560 39 : if (!key)
1561 : {
1562 0 : fprintf (stderr, PGM ": couldn't allocate %d bytes\n", keylen);
1563 0 : exit (1);
1564 : }
1565 39 : memset(key, 42, keylen);
1566 :
1567 39 : err = gcry_mac_open (&hd, mode->algo, 0, NULL);
1568 39 : if (err)
1569 : {
1570 0 : fprintf (stderr, PGM ": error opening mac `%s'\n",
1571 : gcry_mac_algo_name (mode->algo));
1572 0 : free (key);
1573 0 : exit (1);
1574 : }
1575 :
1576 39 : err = gcry_mac_setkey (hd, key, keylen);
1577 39 : if (err)
1578 : {
1579 0 : fprintf (stderr, PGM ": error setting key for mac `%s'\n",
1580 : gcry_mac_algo_name (mode->algo));
1581 0 : free (key);
1582 0 : exit (1);
1583 : }
1584 :
1585 39 : switch (mode->algo)
1586 : {
1587 : default:
1588 34 : break;
1589 : case GCRY_MAC_POLY1305_AES:
1590 : case GCRY_MAC_POLY1305_CAMELLIA:
1591 : case GCRY_MAC_POLY1305_TWOFISH:
1592 : case GCRY_MAC_POLY1305_SERPENT:
1593 : case GCRY_MAC_POLY1305_SEED:
1594 5 : gcry_mac_setiv (hd, key, 16);
1595 5 : break;
1596 : }
1597 :
1598 39 : obj->priv = hd;
1599 :
1600 39 : free (key);
1601 39 : return 0;
1602 : }
1603 :
1604 : static void
1605 39 : bench_mac_free (struct bench_obj *obj)
1606 : {
1607 39 : gcry_mac_hd_t hd = obj->priv;
1608 :
1609 39 : gcry_mac_close (hd);
1610 39 : }
1611 :
1612 : static void
1613 30468 : bench_mac_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
1614 : {
1615 30468 : gcry_mac_hd_t hd = obj->priv;
1616 : size_t bs;
1617 : char b;
1618 :
1619 30468 : gcry_mac_reset (hd);
1620 30468 : gcry_mac_write (hd, buf, buflen);
1621 30468 : bs = sizeof(b);
1622 30468 : gcry_mac_read (hd, &b, &bs);
1623 30468 : }
1624 :
1625 : static struct bench_ops mac_ops = {
1626 : &bench_mac_init,
1627 : &bench_mac_free,
1628 : &bench_mac_do_bench
1629 : };
1630 :
1631 :
1632 : static struct bench_mac_mode mac_modes[] = {
1633 : {"", &mac_ops},
1634 : {0},
1635 : };
1636 :
1637 :
1638 : static void
1639 39 : mac_bench_one (int algo, struct bench_mac_mode *pmode)
1640 : {
1641 39 : struct bench_mac_mode mode = *pmode;
1642 39 : struct bench_obj obj = { 0 };
1643 : double result;
1644 :
1645 39 : mode.algo = algo;
1646 :
1647 39 : if (mode.name[0] == '\0')
1648 39 : bench_print_algo (-18, gcry_mac_algo_name (algo));
1649 : else
1650 0 : bench_print_algo (18, mode.name);
1651 :
1652 39 : obj.ops = mode.ops;
1653 39 : obj.priv = &mode;
1654 :
1655 39 : result = do_slope_benchmark (&obj);
1656 :
1657 39 : bench_print_result (result);
1658 39 : }
1659 :
1660 : static void
1661 39 : _mac_bench (int algo)
1662 : {
1663 : int i;
1664 :
1665 78 : for (i = 0; mac_modes[i].name; i++)
1666 39 : mac_bench_one (algo, &mac_modes[i]);
1667 39 : }
1668 :
1669 : void
1670 1 : mac_bench (char **argv, int argc)
1671 : {
1672 : int i, algo;
1673 :
1674 1 : bench_print_section ("mac", "MAC");
1675 1 : bench_print_header (18, "");
1676 :
1677 1 : if (argv && argc)
1678 : {
1679 0 : for (i = 0; i < argc; i++)
1680 : {
1681 0 : algo = gcry_mac_map_name (argv[i]);
1682 0 : if (algo)
1683 0 : _mac_bench (algo);
1684 : }
1685 : }
1686 : else
1687 : {
1688 600 : for (i = 1; i < 600; i++)
1689 599 : if (!gcry_mac_test_algo (i))
1690 39 : _mac_bench (i);
1691 : }
1692 :
1693 1 : bench_print_footer (18);
1694 1 : }
1695 :
1696 :
1697 : /************************************************************ KDF benchmarks. */
1698 :
1699 : struct bench_kdf_mode
1700 : {
1701 : struct bench_ops *ops;
1702 :
1703 : int algo;
1704 : int subalgo;
1705 : };
1706 :
1707 :
1708 : static int
1709 27 : bench_kdf_init (struct bench_obj *obj)
1710 : {
1711 27 : struct bench_kdf_mode *mode = obj->priv;
1712 :
1713 27 : if (mode->algo == GCRY_KDF_PBKDF2)
1714 : {
1715 27 : obj->min_bufsize = 2;
1716 27 : obj->max_bufsize = 2 * 32;
1717 27 : obj->step_size = 2;
1718 : }
1719 :
1720 27 : obj->num_measure_repetitions = num_measurement_repetitions;
1721 :
1722 27 : return 0;
1723 : }
1724 :
1725 : static void
1726 27 : bench_kdf_free (struct bench_obj *obj)
1727 : {
1728 : (void)obj;
1729 27 : }
1730 :
1731 : static void
1732 7388 : bench_kdf_do_bench (struct bench_obj *obj, void *buf, size_t buflen)
1733 : {
1734 7388 : struct bench_kdf_mode *mode = obj->priv;
1735 : char keybuf[16];
1736 :
1737 : (void)buf;
1738 :
1739 7388 : if (mode->algo == GCRY_KDF_PBKDF2)
1740 : {
1741 7388 : gcry_kdf_derive("qwerty", 6, mode->algo, mode->subalgo, "01234567", 8,
1742 : buflen, sizeof(keybuf), keybuf);
1743 : }
1744 7388 : }
1745 :
1746 : static struct bench_ops kdf_ops = {
1747 : &bench_kdf_init,
1748 : &bench_kdf_free,
1749 : &bench_kdf_do_bench
1750 : };
1751 :
1752 :
1753 : static void
1754 33 : kdf_bench_one (int algo, int subalgo)
1755 : {
1756 33 : struct bench_kdf_mode mode = { &kdf_ops };
1757 33 : struct bench_obj obj = { 0 };
1758 : double nsecs_per_iteration;
1759 : double cycles_per_iteration;
1760 : char algo_name[32];
1761 : char nsecpiter_buf[16];
1762 : char cpiter_buf[16];
1763 :
1764 33 : mode.algo = algo;
1765 33 : mode.subalgo = subalgo;
1766 :
1767 33 : switch (subalgo)
1768 : {
1769 : case GCRY_MD_CRC32:
1770 : case GCRY_MD_CRC32_RFC1510:
1771 : case GCRY_MD_CRC24_RFC2440:
1772 : case GCRY_MD_MD4:
1773 : /* Skip CRC32s. */
1774 10 : return;
1775 : }
1776 :
1777 29 : if (gcry_md_get_algo_dlen (subalgo) == 0)
1778 : {
1779 : /* Skip XOFs */
1780 2 : return;
1781 : }
1782 :
1783 27 : *algo_name = 0;
1784 :
1785 27 : if (algo == GCRY_KDF_PBKDF2)
1786 : {
1787 27 : snprintf (algo_name, sizeof(algo_name), "PBKDF2-HMAC-%s",
1788 : gcry_md_algo_name (subalgo));
1789 : }
1790 :
1791 27 : bench_print_algo (-24, algo_name);
1792 :
1793 27 : obj.ops = mode.ops;
1794 27 : obj.priv = &mode;
1795 :
1796 27 : nsecs_per_iteration = do_slope_benchmark (&obj);
1797 :
1798 27 : strcpy(cpiter_buf, csv_mode ? "" : "-");
1799 :
1800 27 : double_to_str (nsecpiter_buf, sizeof (nsecpiter_buf), nsecs_per_iteration);
1801 :
1802 : /* If user didn't provide CPU speed, we cannot show cycles/iter results. */
1803 27 : if (cpu_ghz > 0.0)
1804 : {
1805 0 : cycles_per_iteration = nsecs_per_iteration * cpu_ghz;
1806 0 : double_to_str (cpiter_buf, sizeof (cpiter_buf), cycles_per_iteration);
1807 : }
1808 :
1809 27 : if (csv_mode)
1810 : {
1811 0 : printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter\n",
1812 : current_section_name,
1813 0 : current_algo_name ? current_algo_name : "",
1814 0 : current_mode_name ? current_mode_name : "",
1815 : nsecpiter_buf,
1816 : cpiter_buf);
1817 : }
1818 : else
1819 : {
1820 27 : printf ("%14s %13s\n", nsecpiter_buf, cpiter_buf);
1821 : }
1822 : }
1823 :
1824 : void
1825 1 : kdf_bench (char **argv, int argc)
1826 : {
1827 : char algo_name[32];
1828 : int i, j;
1829 :
1830 1 : bench_print_section ("kdf", "KDF");
1831 :
1832 1 : if (!csv_mode)
1833 : {
1834 1 : printf (" %-*s | ", 24, "");
1835 1 : printf ("%14s %13s\n", "nanosecs/iter", "cycles/iter");
1836 : }
1837 :
1838 1 : if (argv && argc)
1839 : {
1840 0 : for (i = 0; i < argc; i++)
1841 : {
1842 0 : for (j = 1; j < 400; j++)
1843 : {
1844 0 : if (gcry_md_test_algo (j))
1845 0 : continue;
1846 :
1847 0 : snprintf (algo_name, sizeof(algo_name), "PBKDF2-HMAC-%s",
1848 : gcry_md_algo_name (j));
1849 :
1850 0 : if (!strcmp(argv[i], algo_name))
1851 0 : kdf_bench_one (GCRY_KDF_PBKDF2, j);
1852 : }
1853 : }
1854 : }
1855 : else
1856 : {
1857 400 : for (i = 1; i < 400; i++)
1858 399 : if (!gcry_md_test_algo (i))
1859 33 : kdf_bench_one (GCRY_KDF_PBKDF2, i);
1860 : }
1861 :
1862 1 : bench_print_footer (24);
1863 1 : }
1864 :
1865 :
1866 : /************************************************************** Main program. */
1867 :
1868 : void
1869 0 : print_help (void)
1870 : {
1871 : static const char *help_lines[] = {
1872 : "usage: bench-slope [options] [hash|mac|cipher|kdf [algonames]]",
1873 : "",
1874 : " options:",
1875 : " --cpu-mhz <mhz> Set CPU speed for calculating cycles",
1876 : " per bytes results.",
1877 : " --disable-hwf <features> Disable hardware acceleration feature(s)",
1878 : " for benchmarking.",
1879 : " --repetitions <n> Use N repetitions (default "
1880 : STR2(NUM_MEASUREMENT_REPETITIONS) ")",
1881 : " --unaligned Use unaligned input buffers.",
1882 : " --csv Use CSV output format",
1883 : NULL
1884 : };
1885 : const char **line;
1886 :
1887 0 : for (line = help_lines; *line; line++)
1888 0 : fprintf (stdout, "%s\n", *line);
1889 0 : }
1890 :
1891 :
1892 : /* Warm up CPU. */
1893 : static void
1894 1 : warm_up_cpu (void)
1895 : {
1896 : struct nsec_time start, end;
1897 :
1898 1 : get_nsec_time (&start);
1899 : do
1900 : {
1901 28083121 : get_nsec_time (&end);
1902 : }
1903 28083121 : while (get_time_nsec_diff (&start, &end) < 1000.0 * 1000.0 * 1000.0);
1904 1 : }
1905 :
1906 :
1907 : int
1908 1 : main (int argc, char **argv)
1909 : {
1910 1 : int last_argc = -1;
1911 :
1912 1 : if (argc)
1913 : {
1914 1 : argc--;
1915 1 : argv++;
1916 : }
1917 :
1918 : /* We skip this test if we are running under the test suite (no args
1919 : and srcdir defined) and GCRYPT_NO_BENCHMARKS is set. */
1920 1 : if (!argc && getenv ("srcdir") && getenv ("GCRYPT_NO_BENCHMARKS"))
1921 0 : exit (77);
1922 :
1923 1 : if (getenv ("GCRYPT_IN_REGRESSION_TEST"))
1924 : {
1925 1 : in_regression_test = 1;
1926 1 : num_measurement_repetitions = 2;
1927 : }
1928 : else
1929 0 : num_measurement_repetitions = NUM_MEASUREMENT_REPETITIONS;
1930 :
1931 2 : while (argc && last_argc != argc)
1932 : {
1933 0 : last_argc = argc;
1934 :
1935 0 : if (!strcmp (*argv, "--"))
1936 : {
1937 0 : argc--;
1938 0 : argv++;
1939 0 : break;
1940 : }
1941 0 : else if (!strcmp (*argv, "--help"))
1942 : {
1943 0 : print_help ();
1944 0 : exit (0);
1945 : }
1946 0 : else if (!strcmp (*argv, "--verbose"))
1947 : {
1948 0 : verbose++;
1949 0 : argc--;
1950 0 : argv++;
1951 : }
1952 0 : else if (!strcmp (*argv, "--debug"))
1953 : {
1954 0 : verbose += 2;
1955 0 : debug++;
1956 0 : argc--;
1957 0 : argv++;
1958 : }
1959 0 : else if (!strcmp (*argv, "--csv"))
1960 : {
1961 0 : csv_mode = 1;
1962 0 : argc--;
1963 0 : argv++;
1964 : }
1965 0 : else if (!strcmp (*argv, "--unaligned"))
1966 : {
1967 0 : unaligned_mode = 1;
1968 0 : argc--;
1969 0 : argv++;
1970 : }
1971 0 : else if (!strcmp (*argv, "--disable-hwf"))
1972 : {
1973 0 : argc--;
1974 0 : argv++;
1975 0 : if (argc)
1976 : {
1977 0 : if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL))
1978 0 : fprintf (stderr,
1979 : PGM
1980 : ": unknown hardware feature `%s' - option ignored\n",
1981 : *argv);
1982 0 : argc--;
1983 0 : argv++;
1984 : }
1985 : }
1986 0 : else if (!strcmp (*argv, "--cpu-mhz"))
1987 : {
1988 0 : argc--;
1989 0 : argv++;
1990 0 : if (argc)
1991 : {
1992 0 : cpu_ghz = atof (*argv);
1993 0 : cpu_ghz /= 1000; /* Mhz => Ghz */
1994 :
1995 0 : argc--;
1996 0 : argv++;
1997 : }
1998 : }
1999 0 : else if (!strcmp (*argv, "--repetitions"))
2000 : {
2001 0 : argc--;
2002 0 : argv++;
2003 0 : if (argc)
2004 : {
2005 0 : num_measurement_repetitions = atof (*argv);
2006 0 : if (num_measurement_repetitions < 2)
2007 : {
2008 0 : fprintf (stderr,
2009 : PGM
2010 : ": value for --repetitions too small - using %d\n",
2011 : NUM_MEASUREMENT_REPETITIONS);
2012 0 : num_measurement_repetitions = NUM_MEASUREMENT_REPETITIONS;
2013 : }
2014 0 : argc--;
2015 0 : argv++;
2016 : }
2017 : }
2018 : }
2019 :
2020 1 : xgcry_control (GCRYCTL_SET_VERBOSITY, (int) verbose);
2021 :
2022 1 : if (!gcry_check_version (GCRYPT_VERSION))
2023 : {
2024 0 : fprintf (stderr, PGM ": version mismatch; pgm=%s, library=%s\n",
2025 : GCRYPT_VERSION, gcry_check_version (NULL));
2026 0 : exit (1);
2027 : }
2028 :
2029 1 : if (debug)
2030 0 : xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
2031 :
2032 1 : xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
2033 1 : xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
2034 1 : xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
2035 :
2036 1 : if (in_regression_test)
2037 1 : fputs ("Note: " PGM " running in quick regression test mode.\n", stdout);
2038 :
2039 1 : if (!argc)
2040 : {
2041 1 : warm_up_cpu ();
2042 1 : hash_bench (NULL, 0);
2043 1 : mac_bench (NULL, 0);
2044 1 : cipher_bench (NULL, 0);
2045 1 : kdf_bench (NULL, 0);
2046 : }
2047 0 : else if (!strcmp (*argv, "hash"))
2048 : {
2049 0 : argc--;
2050 0 : argv++;
2051 :
2052 0 : warm_up_cpu ();
2053 0 : hash_bench ((argc == 0) ? NULL : argv, argc);
2054 : }
2055 0 : else if (!strcmp (*argv, "mac"))
2056 : {
2057 0 : argc--;
2058 0 : argv++;
2059 :
2060 0 : warm_up_cpu ();
2061 0 : mac_bench ((argc == 0) ? NULL : argv, argc);
2062 : }
2063 0 : else if (!strcmp (*argv, "cipher"))
2064 : {
2065 0 : argc--;
2066 0 : argv++;
2067 :
2068 0 : warm_up_cpu ();
2069 0 : cipher_bench ((argc == 0) ? NULL : argv, argc);
2070 : }
2071 0 : else if (!strcmp (*argv, "kdf"))
2072 : {
2073 0 : argc--;
2074 0 : argv++;
2075 :
2076 0 : warm_up_cpu ();
2077 0 : kdf_bench ((argc == 0) ? NULL : argv, argc);
2078 : }
2079 : else
2080 : {
2081 0 : fprintf (stderr, PGM ": unknown argument: %s\n", *argv);
2082 0 : print_help ();
2083 : }
2084 :
2085 1 : return 0;
2086 : }
2087 :
2088 : #endif /* !NO_GET_NSEC_TIME */
|