LCOV - code coverage report
Current view: top level - tests - bench-slope.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 524 749 70.0 %
Date: 2015-11-05 17:08:00 Functions: 58 60 96.7 %

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

Generated by: LCOV version 1.11