nettle-benchmark.c 16 KB
Newer Older
1 2 3 4 5 6 7 8
/* nettle-benchmark.c
 *
 * Tries the performance of the various algorithms.
 *
 */
 
/* nettle, low-level cryptographics library
 *
Niels Möller's avatar
Niels Möller committed
9
 * Copyright (C) 2001, 2010 Niels Möller
10 11 12 13 14 15 16 17 18 19 20 21 22
 *  
 * The nettle library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * The nettle library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with the nettle library; see the file COPYING.LIB.  If not, write to
23 24
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02111-1301, USA.
25 26
 */

27 28
#if HAVE_CONFIG_H
# include "config.h"
29 30 31 32
#endif

#include <assert.h>
#include <errno.h>
33
#include <math.h>
Niels Möller's avatar
Niels Möller committed
34
#include <stdarg.h>
35 36 37 38 39
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <time.h>
40

41
#include "aes.h"
Niels Möller's avatar
Niels Möller committed
42 43 44
#include "arcfour.h"
#include "blowfish.h"
#include "cast128.h"
Niels Möller's avatar
Niels Möller committed
45
#include "cbc.h"
Niels Möller's avatar
Niels Möller committed
46
#include "ctr.h"
Niels Möller's avatar
Niels Möller committed
47
#include "des.h"
Niels Möller's avatar
Niels Möller committed
48
#include "gcm.h"
49
#include "memxor.h"
50
#include "salsa20.h"
Niels Möller's avatar
Niels Möller committed
51
#include "serpent.h"
52 53
#include "sha1.h"
#include "sha2.h"
Niels Möller's avatar
Niels Möller committed
54
#include "sha3.h"
Niels Möller's avatar
Niels Möller committed
55 56
#include "twofish.h"

57 58 59
#include "nettle-meta.h"
#include "nettle-internal.h"

Niels Möller's avatar
Niels Möller committed
60
#include "getopt.h"
61

62
static double frequency = 0.0;
Niels Möller's avatar
Niels Möller committed
63

64
/* Process BENCH_BLOCK bytes at a time, for BENCH_INTERVAL seconds. */
65
#define BENCH_BLOCK 10240
66
#define BENCH_INTERVAL 0.1
Niels Möller's avatar
Niels Möller committed
67

68 69
/* FIXME: Proper configure test for rdtsc? */
#ifndef WITH_CYCLE_COUNTER
70
# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
71 72 73 74 75 76 77
#  define WITH_CYCLE_COUNTER 1
# else
#  define WITH_CYCLE_COUNTER 0
# endif
#endif

#if WITH_CYCLE_COUNTER
78
# if defined(__i386__)
79 80 81 82 83 84 85 86 87
#define GET_CYCLE_COUNTER(hi, lo)		\
  __asm__("xorl %%eax,%%eax\n"			\
	  "movl %%ebx, %%edi\n"			\
	  "cpuid\n"				\
	  "rdtsc\n"				\
	  "movl %%edi, %%ebx\n"			\
	  : "=a" (lo), "=d" (hi)		\
	  : /* No inputs. */			\
	  : "%edi", "%ecx", "cc")
88 89 90 91 92 93 94 95 96 97 98
# elif defined(__x86_64__)
#define GET_CYCLE_COUNTER(hi, lo)		\
  __asm__("xorl %%eax,%%eax\n"			\
	  "mov %%rbx, %%r10\n"			\
	  "cpuid\n"				\
	  "rdtsc\n"				\
	  "mov %%r10, %%rbx\n"			\
	  : "=a" (lo), "=d" (hi)		\
	  : /* No inputs. */			\
	  : "%r10", "%rcx", "cc")
# endif
99 100 101
#define BENCH_ITERATIONS 10
#endif

102
static void NORETURN PRINTF_STYLE(1,2)
Niels Möller's avatar
Niels Möller committed
103 104 105 106 107 108 109 110 111 112
die(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  vfprintf(stderr, format, args);
  va_end(args);

  exit(EXIT_FAILURE);
}

113 114
static double overhead = 0.0; 

115
#if HAVE_CLOCK_GETTIME && defined CLOCK_PROCESS_CPUTIME_ID
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
#define TRY_CLOCK_GETTIME 1
struct timespec cgt_start;

static int
cgt_works_p(void)
{
  struct timespec now;
  return clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &now) == 0;
}

static void
cgt_time_start(void)
{
  if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &cgt_start) < 0)
    die("clock_gettime failed: %s\n", strerror(errno));
}

static double
cgt_time_end(void)
{
    struct timespec end;
    if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end) < 0)
      die("clock_gettime failed: %s\n", strerror(errno));

    return end.tv_sec - cgt_start.tv_sec
      + 1e-9 * (end.tv_nsec - cgt_start.tv_nsec);
}

static void (*time_start)(void);
static double (*time_end)(void);

147
#else /* !HAVE_CLOCK_GETTIME */
148 149 150
#define TRY_CLOCK_GETTIME 0
#define time_start clock_time_start
#define time_end clock_time_end
151 152
#endif /* !HAVE_CLOCK_GETTIME */

153 154 155 156 157 158 159 160 161 162 163 164 165 166
static clock_t clock_start;

static void
clock_time_start(void)
{
  clock_start = clock();
}

static double
clock_time_end(void)
{
  return (double) (clock() - (clock_start)) / CLOCKS_PER_SEC;
}

167
/* Returns second per function call */
168 169 170
static double
time_function(void (*f)(void *arg), void *arg)
{
171
  unsigned ncalls;
172 173
  double elapsed;

174
  for (ncalls = 10 ;;)
175
    {
176
      unsigned i;
177 178

      time_start();
179 180
      for (i = 0; i < ncalls; i++)
	f(arg);
181
      elapsed = time_end();
182 183 184 185 186 187
      if (elapsed > BENCH_INTERVAL)
	break;
      else if (elapsed < BENCH_INTERVAL / 10)
	ncalls *= 10;
      else
	ncalls *= 2;
188
    }
189 190 191 192 193 194 195
  return elapsed / ncalls - overhead;
}

static void
bench_nothing(void *arg UNUSED)
{
  return;
196 197
}

198 199 200 201
struct bench_memxor_info
{
  uint8_t *dst;
  const uint8_t *src;
202
  const uint8_t *other;  
203 204 205 206 207 208 209 210 211
};

static void
bench_memxor(void *arg)
{
  struct bench_memxor_info *info = arg;
  memxor (info->dst, info->src, BENCH_BLOCK);
}

212 213 214 215 216 217 218
static void
bench_memxor3(void *arg)
{
  struct bench_memxor_info *info = arg;
  memxor3 (info->dst, info->src, info->other, BENCH_BLOCK);
}

219 220 221
struct bench_hash_info
{
  void *ctx;
222
  nettle_hash_update_func *update;
223 224 225 226 227 228 229 230 231 232
  const uint8_t *data;
};

static void
bench_hash(void *arg)
{
  struct bench_hash_info *info = arg;
  info->update(info->ctx, BENCH_BLOCK, info->data);
}

233 234 235
struct bench_cipher_info
{
  void *ctx;
236
  nettle_crypt_func *crypt;
237 238 239 240 241 242 243
  uint8_t *data;
};

static void
bench_cipher(void *arg)
{
  struct bench_cipher_info *info = arg;
244
  info->crypt(info->ctx, BENCH_BLOCK, info->data, info->data);
245 246 247 248 249
}

struct bench_cbc_info
{
  void *ctx;
250
  nettle_crypt_func *crypt;
251
 
252
  uint8_t *data;
253
  
254 255 256 257 258 259 260 261
  unsigned block_size;
  uint8_t *iv;
};

static void
bench_cbc_encrypt(void *arg)
{
  struct bench_cbc_info *info = arg;
262 263 264
  cbc_encrypt(info->ctx, info->crypt,
	      info->block_size, info->iv,
	      BENCH_BLOCK, info->data, info->data);
265 266 267 268 269 270
}

static void
bench_cbc_decrypt(void *arg)
{
  struct bench_cbc_info *info = arg;
271 272 273
  cbc_decrypt(info->ctx, info->crypt,
	      info->block_size, info->iv,
	      BENCH_BLOCK, info->data, info->data);
274 275
}

Niels Möller's avatar
Niels Möller committed
276 277 278 279 280 281 282 283 284
static void
bench_ctr(void *arg)
{
  struct bench_cbc_info *info = arg;
  ctr_crypt(info->ctx, info->crypt,
	    info->block_size, info->iv,
	    BENCH_BLOCK, info->data, info->data);
}

285 286 287 288 289
/* Set data[i] = floor(sqrt(i)) */
static void
init_data(uint8_t *data)
{
  unsigned i,j;
Niels Möller's avatar
Niels Möller committed
290
  for (i = j = 0; i<BENCH_BLOCK;  i++)
291 292 293 294 295 296 297 298
    {
      if (j*j < i)
	j++;
      data[i] = j;
    }
}

static void
Niels Möller's avatar
Niels Möller committed
299 300
init_key(unsigned length,
         uint8_t *key)
301
{
Niels Möller's avatar
Niels Möller committed
302 303 304
  unsigned i;
  for (i = 0; i<length; i++)
    key[i] = i;
305 306
}

307 308 309 310 311
static void
header(void)
{
  printf("%18s %11s Mbyte/s%s\n",
	 "Algorithm", "mode", 
Niels Möller's avatar
Niels Möller committed
312
	 frequency > 0.0 ? " cycles/byte cycles/block" : "");  
313 314
}

Niels Möller's avatar
Niels Möller committed
315
static void
Niels Möller's avatar
Niels Möller committed
316
display(const char *name, const char *mode, unsigned block_size,
317
	double time)
Niels Möller's avatar
Niels Möller committed
318
{
319
  printf("%18s %11s %7.2f",
Niels Möller's avatar
Niels Möller committed
320
	 name, mode,
321
	 BENCH_BLOCK / (time * 1048576.0));
322
  if (frequency > 0.0)
Niels Möller's avatar
Niels Möller committed
323
    {
324
      printf(" %11.2f", time * frequency / BENCH_BLOCK);
Niels Möller's avatar
Niels Möller committed
325
      if (block_size > 0)
326
	printf(" %12.2f", time * frequency * block_size / BENCH_BLOCK);
Niels Möller's avatar
Niels Möller committed
327
    }
328
  printf("\n");
Niels Möller's avatar
Niels Möller committed
329 330
}

331 332 333 334 335
static void *
xalloc(size_t size)
{
  void *p = malloc(size);
  if (!p)
336
    die("Virtual memory exhausted.\n");
337 338 339 340

  return p;
}

341 342 343 344 345 346 347 348 349 350 351 352
static void
time_overhead(void)
{
  overhead = time_function(bench_nothing, NULL);
  printf("benchmark call overhead: %7f us", overhead * 1e6);
  if (frequency > 0.0)
    printf("%7.2f cycles\n", overhead * frequency);
  printf("\n");  
}



353 354 355 356
static void
time_memxor(void)
{
  struct bench_memxor_info info;
357
  uint8_t src[BENCH_BLOCK + sizeof(long)];
358
  uint8_t other[BENCH_BLOCK + sizeof(long)];
359
  uint8_t dst[BENCH_BLOCK];
360 361 362 363

  info.src = src;
  info.dst = dst;

364 365
  display ("memxor", "aligned", sizeof(unsigned long),
	   time_function(bench_memxor, &info));
366
  info.src = src + 1;
367
  display ("memxor", "unaligned", sizeof(unsigned long),
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
	   time_function(bench_memxor, &info));

  info.src = src;
  info.other = other;
  display ("memxor3", "aligned", sizeof(unsigned long),
	   time_function(bench_memxor3, &info));

  info.other = other + 1;
  display ("memxor3", "unaligned01", sizeof(unsigned long),
	   time_function(bench_memxor3, &info));
  info.src = src + 1;
  display ("memxor3", "unaligned11", sizeof(unsigned long),
	   time_function(bench_memxor3, &info));
  info.other = other + 2;
  display ("memxor3", "unaligned12", sizeof(unsigned long),
	   time_function(bench_memxor3, &info));  
384 385
}

386 387 388 389 390
static void
time_hash(const struct nettle_hash *hash)
{
  static uint8_t data[BENCH_BLOCK];
  struct bench_hash_info info;
391

392
  info.ctx = xalloc(hash->context_size); 
393 394 395 396 397 398
  info.update = hash->update;
  info.data = data;

  init_data(data);
  hash->init(info.ctx);

Niels Möller's avatar
Niels Möller committed
399
  display(hash->name, "update", hash->block_size,
400
	  time_function(bench_hash, &info));
401 402

  free(info.ctx);
403 404
}

Niels Möller's avatar
Niels Möller committed
405
static void
406
time_gcm(void)
Niels Möller's avatar
Niels Möller committed
407 408
{
  static uint8_t data[BENCH_BLOCK];
409 410
  struct bench_hash_info hinfo;
  struct bench_cipher_info cinfo;
411
  struct gcm_aes_ctx ctx;
412

Niels Möller's avatar
Niels Möller committed
413 414 415
  uint8_t key[16];
  uint8_t iv[GCM_IV_SIZE];

416 417
  gcm_aes_set_key(&ctx, sizeof(key), key);
  gcm_aes_set_iv(&ctx, sizeof(iv), iv);
Niels Möller's avatar
Niels Möller committed
418

419 420 421 422 423 424 425 426 427 428
  hinfo.ctx = &ctx;
  hinfo.update = (nettle_hash_update_func *) gcm_aes_update;
  hinfo.data = data;
  
  display("gcm-aes", "update", GCM_BLOCK_SIZE,
	  time_function(bench_hash, &hinfo));
  
  cinfo.ctx = &ctx;
  cinfo.crypt = (nettle_crypt_func *) gcm_aes_encrypt;
  cinfo.data = data;
Niels Möller's avatar
Niels Möller committed
429

430 431 432 433 434 435 436
  display("gcm-aes", "encrypt", GCM_BLOCK_SIZE,
	  time_function(bench_cipher, &cinfo));

  cinfo.crypt = (nettle_crypt_func *) gcm_aes_decrypt;

  display("gcm-aes", "decrypt", GCM_BLOCK_SIZE,
	  time_function(bench_cipher, &cinfo));
Niels Möller's avatar
Niels Möller committed
437 438
}

439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
static int
prefix_p(const char *prefix, const char *s)
{
  size_t i;
  for (i = 0; prefix[i]; i++)
    if (prefix[i] != s[i])
      return 0;
  return 1;
}

static int
block_cipher_p(const struct nettle_cipher *cipher)
{
  /* Don't use nettle cbc and ctr for openssl ciphers. */
  return cipher->block_size > 0 && !prefix_p("openssl", cipher->name);
}

Niels Möller's avatar
Niels Möller committed
456
static void
457
time_cipher(const struct nettle_cipher *cipher)
Niels Möller's avatar
Niels Möller committed
458
{
459 460
  void *ctx = xalloc(cipher->context_size);
  uint8_t *key = xalloc(cipher->key_size);
Niels Möller's avatar
Niels Möller committed
461

462
  static uint8_t data[BENCH_BLOCK];
Niels Möller's avatar
Niels Möller committed
463 464 465 466

  printf("\n");
  
  init_data(data);
467 468

  {
Niels Möller's avatar
Niels Möller committed
469 470 471 472 473
    /* Decent initializers are a GNU extension, so don't use it here. */
    struct bench_cipher_info info;
    info.ctx = ctx;
    info.crypt = cipher->encrypt;
    info.data = data;
474
    
Niels Möller's avatar
Niels Möller committed
475
    init_key(cipher->key_size, key);
476
    cipher->set_encrypt_key(ctx, cipher->key_size, key);
Niels Möller's avatar
Niels Möller committed
477

Niels Möller's avatar
Niels Möller committed
478
    display(cipher->name, "ECB encrypt", cipher->block_size,
Niels Möller's avatar
Niels Möller committed
479
	    time_function(bench_cipher, &info));
480
  }
Niels Möller's avatar
Niels Möller committed
481
  
482
  {
Niels Möller's avatar
Niels Möller committed
483 484 485 486
    struct bench_cipher_info info;
    info.ctx = ctx;
    info.crypt = cipher->decrypt;
    info.data = data;
487
    
Niels Möller's avatar
Niels Möller committed
488
    init_key(cipher->key_size, key);
489
    cipher->set_decrypt_key(ctx, cipher->key_size, key);
Niels Möller's avatar
Niels Möller committed
490

Niels Möller's avatar
Niels Möller committed
491
    display(cipher->name, "ECB decrypt", cipher->block_size,
Niels Möller's avatar
Niels Möller committed
492
	    time_function(bench_cipher, &info));
493 494
  }

495
  if (block_cipher_p(cipher))
Niels Möller's avatar
Niels Möller committed
496
    {
497
      uint8_t *iv = xalloc(cipher->block_size);
Niels Möller's avatar
Niels Möller committed
498 499 500
      
      /* Do CBC mode */
      {
Niels Möller's avatar
Niels Möller committed
501 502 503 504 505 506
        struct bench_cbc_info info;
	info.ctx = ctx;
	info.crypt = cipher->encrypt;
	info.data = data;
	info.block_size = cipher->block_size;
	info.iv = iv;
507
    
Niels Möller's avatar
Niels Möller committed
508
        memset(iv, 0, sizeof(iv));
509
    
510
        cipher->set_encrypt_key(ctx, cipher->key_size, key);
511

Niels Möller's avatar
Niels Möller committed
512
	display(cipher->name, "CBC encrypt", cipher->block_size,
Niels Möller's avatar
Niels Möller committed
513
		time_function(bench_cbc_encrypt, &info));
Niels Möller's avatar
Niels Möller committed
514
      }
515

Niels Möller's avatar
Niels Möller committed
516
      {
Niels Möller's avatar
Niels Möller committed
517 518 519 520 521 522
        struct bench_cbc_info info;
	info.ctx = ctx;
	info.crypt = cipher->decrypt;
	info.data = data;
	info.block_size = cipher->block_size;
	info.iv = iv;
523
    
Niels Möller's avatar
Niels Möller committed
524
        memset(iv, 0, sizeof(iv));
525

526
        cipher->set_decrypt_key(ctx, cipher->key_size, key);
527

Niels Möller's avatar
Niels Möller committed
528
	display(cipher->name, "CBC decrypt", cipher->block_size,
Niels Möller's avatar
Niels Möller committed
529
		time_function(bench_cbc_decrypt, &info));
Niels Möller's avatar
Niels Möller committed
530
      }
Niels Möller's avatar
Niels Möller committed
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548

      /* Do CTR mode */
      {
        struct bench_cbc_info info;
	info.ctx = ctx;
	info.crypt = cipher->encrypt;
	info.data = data;
	info.block_size = cipher->block_size;
	info.iv = iv;
    
        memset(iv, 0, sizeof(iv));
    
        cipher->set_encrypt_key(ctx, cipher->key_size, key);

	display(cipher->name, "CTR", cipher->block_size,
		time_function(bench_ctr, &info));	
      }
      
549
      free(iv);
Niels Möller's avatar
Niels Möller committed
550
    }
551 552
  free(ctx);
  free(key);
Niels Möller's avatar
Niels Möller committed
553 554
}

Niels Möller's avatar
Niels Möller committed
555 556
/* Try to get accurate cycle times for assembler functions. */
#if WITH_CYCLE_COUNTER
557 558 559 560 561 562 563 564 565 566 567 568 569
static int
compare_double(const void *ap, const void *bp)
{
  double a = *(const double *) ap;
  double b = *(const double *) bp;
  if (a < b)
    return -1;
  else if (a > b)
    return 1;
  else
    return 0;
}

Niels Möller's avatar
Niels Möller committed
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
#define TIME_CYCLES(t, code) do {				\
  double tc_count[5];						\
  uint32_t tc_start_lo, tc_start_hi, tc_end_lo, tc_end_hi;	\
  unsigned tc_i, tc_j;						\
  for (tc_j = 0; tc_j < 5; tc_j++)				\
    {								\
      tc_i = 0;							\
      GET_CYCLE_COUNTER(tc_start_hi, tc_start_lo);		\
      for (; tc_i < BENCH_ITERATIONS; tc_i++)			\
	{ code; }						\
								\
      GET_CYCLE_COUNTER(tc_end_hi, tc_end_lo);			\
								\
      tc_end_hi -= (tc_start_hi + (tc_start_lo > tc_end_lo));	\
      tc_end_lo -= tc_start_lo;					\
								\
      tc_count[tc_j] = ldexp(tc_end_hi, 32) + tc_end_lo;	\
    }								\
  qsort(tc_count, 5, sizeof(double), compare_double);		\
  (t) = tc_count[2] / BENCH_ITERATIONS;				\
} while (0)

592 593 594 595
static void
bench_sha1_compress(void)
{
  uint32_t state[_SHA1_DIGEST_LENGTH];
Niels Möller's avatar
Niels Möller committed
596 597
  uint8_t data[SHA1_DATA_SIZE];
  double t;
598

Niels Möller's avatar
Niels Möller committed
599
  TIME_CYCLES (t, _nettle_sha1_compress(state, data));
600

Niels Möller's avatar
Niels Möller committed
601
  printf("sha1_compress: %.2f cycles\n", t);  
602 603
}

604 605 606 607
static void
bench_salsa20_core(void)
{
  uint32_t state[_SALSA20_INPUT_LENGTH];
Niels Möller's avatar
Niels Möller committed
608
  double t;
609

Niels Möller's avatar
Niels Möller committed
610 611 612
  TIME_CYCLES (t, _nettle_salsa20_core(state, state, 20));
  printf("salsa20_core: %.2f cycles\n", t);  
}
613

Niels Möller's avatar
Niels Möller committed
614 615 616 617 618
static void
bench_sha3_permute(void)
{
  struct sha3_state state;
  double t;
619

Niels Möller's avatar
Niels Möller committed
620 621
  TIME_CYCLES (t, sha3_permute (&state));
  printf("sha3_permute: %.2f cycles (%.2f / round)\n", t, t / 24.0);
622 623 624 625
}
#else
#define bench_sha1_compress()
#define bench_salsa20_core()
Niels Möller's avatar
Niels Möller committed
626
#define bench_sha3_permute()
627 628
#endif

Niels Möller's avatar
Niels Möller committed
629
#if WITH_OPENSSL
630 631 632 633
# define OPENSSL(x) x,
#else
# define OPENSSL(x)
#endif
Niels Möller's avatar
Niels Möller committed
634 635

int
636
main(int argc, char **argv)
Niels Möller's avatar
Niels Möller committed
637 638
{
  unsigned i;
639
  int c;
640
  const char *alg;
641 642 643 644

  const struct nettle_hash *hashes[] =
    {
      &nettle_md2, &nettle_md4, &nettle_md5,
645
      OPENSSL(&nettle_openssl_md5)
646
      &nettle_sha1, OPENSSL(&nettle_openssl_sha1)
Niels Möller's avatar
Niels Möller committed
647 648
      &nettle_sha224, &nettle_sha256,
      &nettle_sha384, &nettle_sha512,
649 650
      &nettle_sha3_224, &nettle_sha3_256,
      &nettle_sha3_384, &nettle_sha3_512,
651
      &nettle_ripemd160, &nettle_gosthash94,
652 653 654
      NULL
    };

655
  const struct nettle_cipher *ciphers[] =
Niels Möller's avatar
Niels Möller committed
656
    {
657
      &nettle_aes128, &nettle_aes192, &nettle_aes256,
Niels Möller's avatar
Niels Möller committed
658 659 660 661 662
      OPENSSL(&nettle_openssl_aes128)
      OPENSSL(&nettle_openssl_aes192)
      OPENSSL(&nettle_openssl_aes256)
      &nettle_arcfour128, OPENSSL(&nettle_openssl_arcfour128)
      &nettle_blowfish128, OPENSSL(&nettle_openssl_blowfish128)
Niels Möller's avatar
Niels Möller committed
663
      &nettle_camellia128, &nettle_camellia192, &nettle_camellia256,
664 665 666
      &nettle_cast128, OPENSSL(&nettle_openssl_cast128)
      &nettle_des, OPENSSL(&nettle_openssl_des)
      &nettle_des3,
667 668
      &nettle_serpent256,
      &nettle_twofish128, &nettle_twofish192, &nettle_twofish256,
669
      &nettle_salsa20,
670
      NULL
Niels Möller's avatar
Niels Möller committed
671
    };
672

673 674 675 676 677 678 679 680 681 682
  enum { OPT_HELP = 300 };
  static const struct option options[] =
    {
      /* Name, args, flag, val */
      { "help", no_argument, NULL, OPT_HELP },
      { "clock-frequency", required_argument, NULL, 'f' },
      { NULL, 0, NULL, 0 }
    };
  
  while ( (c = getopt_long(argc, argv, "f:", options, NULL)) != -1)
683 684 685 686 687 688 689
    switch (c)
      {
      case 'f':
	frequency = atof(optarg);
	if (frequency > 0.0)
	  break;

690 691 692 693 694
      case OPT_HELP:
	printf("Usage: nettle-benchmark [-f clock frequency] [alg]\n");
	return EXIT_SUCCESS;

      case '?':
695 696 697 698 699 700
	return EXIT_FAILURE;

      default:
	abort();
    }

701
  alg = argv[optind];
702

703 704 705 706 707 708 709 710 711 712 713 714 715 716
  /* Choose timing function */
#if TRY_CLOCK_GETTIME
  if (cgt_works_p())
    {
      time_start = cgt_time_start;
      time_end = cgt_time_end;
    }
  else
    {
      fprintf(stderr, "clock_gettime not working, falling back to clock\n");
      time_start = clock_time_start;
      time_end = clock_time_end;
    }
#endif
717
  bench_sha1_compress();
718
  bench_salsa20_core();
Niels Möller's avatar
Niels Möller committed
719 720
  bench_sha3_permute();
  printf("\n");
721 722
  time_overhead();

723 724
  header();

725 726 727 728 729
  if (!alg || strstr ("memxor", alg))
    {
      time_memxor();
      printf("\n");
    }
730
  
731
  for (i = 0; hashes[i]; i++)
732 733
    if (!alg || strstr(hashes[i]->name, alg))
      time_hash(hashes[i]);
Niels Möller's avatar
Niels Möller committed
734

735
  for (i = 0; ciphers[i]; i++)
736 737 738
    if (!alg || strstr(ciphers[i]->name, alg))
      time_cipher(ciphers[i]);

739 740 741 742 743 744
  if (!alg || strstr ("gcm", alg))
    {
      printf("\n");
      time_gcm();
    }

745 746
  return 0;
}