nettle-benchmark.c 15.8 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 42
#include "timing.h"

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

60 61 62
#include "nettle-meta.h"
#include "nettle-internal.h"

Niels Möller's avatar
Niels Möller committed
63
#include "getopt.h"
64

65
static double frequency = 0.0;
Niels Möller's avatar
Niels Möller committed
66

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

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

#if WITH_CYCLE_COUNTER
81
# if defined(__i386__)
82 83 84 85 86 87 88 89 90
#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")
91 92 93 94 95 96 97 98 99 100 101
# 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
102 103 104
#define BENCH_ITERATIONS 10
#endif

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

  exit(EXIT_FAILURE);
}

116 117
static double overhead = 0.0; 

118
/* Returns second per function call */
119 120 121
static double
time_function(void (*f)(void *arg), void *arg)
{
122
  unsigned ncalls;
123 124
  double elapsed;

125
  for (ncalls = 10 ;;)
126
    {
127
      unsigned i;
128 129

      time_start();
130 131
      for (i = 0; i < ncalls; i++)
	f(arg);
132
      elapsed = time_end();
133 134 135 136 137 138
      if (elapsed > BENCH_INTERVAL)
	break;
      else if (elapsed < BENCH_INTERVAL / 10)
	ncalls *= 10;
      else
	ncalls *= 2;
139
    }
140 141 142 143 144 145 146
  return elapsed / ncalls - overhead;
}

static void
bench_nothing(void *arg UNUSED)
{
  return;
147 148
}

149 150 151 152
struct bench_memxor_info
{
  uint8_t *dst;
  const uint8_t *src;
153
  const uint8_t *other;  
154 155 156 157 158 159 160 161 162
};

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

163 164 165 166 167 168 169
static void
bench_memxor3(void *arg)
{
  struct bench_memxor_info *info = arg;
  memxor3 (info->dst, info->src, info->other, BENCH_BLOCK);
}

170 171 172
struct bench_hash_info
{
  void *ctx;
173
  nettle_hash_update_func *update;
174 175 176 177 178 179 180 181 182 183
  const uint8_t *data;
};

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

184 185 186
struct bench_cipher_info
{
  void *ctx;
187
  nettle_crypt_func *crypt;
188 189 190 191 192 193 194
  uint8_t *data;
};

static void
bench_cipher(void *arg)
{
  struct bench_cipher_info *info = arg;
195
  info->crypt(info->ctx, BENCH_BLOCK, info->data, info->data);
196 197 198 199 200
}

struct bench_cbc_info
{
  void *ctx;
201
  nettle_crypt_func *crypt;
202
 
203
  uint8_t *data;
204
  
205 206 207 208 209 210 211 212
  unsigned block_size;
  uint8_t *iv;
};

static void
bench_cbc_encrypt(void *arg)
{
  struct bench_cbc_info *info = arg;
213 214 215
  cbc_encrypt(info->ctx, info->crypt,
	      info->block_size, info->iv,
	      BENCH_BLOCK, info->data, info->data);
216 217 218 219 220 221
}

static void
bench_cbc_decrypt(void *arg)
{
  struct bench_cbc_info *info = arg;
222 223 224
  cbc_decrypt(info->ctx, info->crypt,
	      info->block_size, info->iv,
	      BENCH_BLOCK, info->data, info->data);
225 226
}

Niels Möller's avatar
Niels Möller committed
227 228 229 230 231 232 233 234 235
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);
}

236 237 238 239 240
/* 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
241
  for (i = j = 0; i<BENCH_BLOCK;  i++)
242 243 244 245 246 247 248 249
    {
      if (j*j < i)
	j++;
      data[i] = j;
    }
}

static void
Niels Möller's avatar
Niels Möller committed
250 251
init_key(unsigned length,
         uint8_t *key)
252
{
Niels Möller's avatar
Niels Möller committed
253 254 255
  unsigned i;
  for (i = 0; i<length; i++)
    key[i] = i;
256 257
}

258 259 260 261 262
static void
header(void)
{
  printf("%18s %11s Mbyte/s%s\n",
	 "Algorithm", "mode", 
Niels Möller's avatar
Niels Möller committed
263
	 frequency > 0.0 ? " cycles/byte cycles/block" : "");  
264 265
}

Niels Möller's avatar
Niels Möller committed
266
static void
Niels Möller's avatar
Niels Möller committed
267
display(const char *name, const char *mode, unsigned block_size,
268
	double time)
Niels Möller's avatar
Niels Möller committed
269
{
270
  printf("%18s %11s %7.2f",
Niels Möller's avatar
Niels Möller committed
271
	 name, mode,
272
	 BENCH_BLOCK / (time * 1048576.0));
273
  if (frequency > 0.0)
Niels Möller's avatar
Niels Möller committed
274
    {
275
      printf(" %11.2f", time * frequency / BENCH_BLOCK);
Niels Möller's avatar
Niels Möller committed
276
      if (block_size > 0)
277
	printf(" %12.2f", time * frequency * block_size / BENCH_BLOCK);
Niels Möller's avatar
Niels Möller committed
278
    }
279
  printf("\n");
Niels Möller's avatar
Niels Möller committed
280 281
}

282 283 284 285 286
static void *
xalloc(size_t size)
{
  void *p = malloc(size);
  if (!p)
287
    die("Virtual memory exhausted.\n");
288 289 290 291

  return p;
}

292 293 294 295 296 297 298 299 300 301 302 303
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");  
}



304 305 306 307
static void
time_memxor(void)
{
  struct bench_memxor_info info;
308
  uint8_t src[BENCH_BLOCK + sizeof(long)];
309
  uint8_t other[BENCH_BLOCK + sizeof(long)];
310
  uint8_t dst[BENCH_BLOCK];
311 312 313 314

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

315 316
  display ("memxor", "aligned", sizeof(unsigned long),
	   time_function(bench_memxor, &info));
317
  info.src = src + 1;
318
  display ("memxor", "unaligned", sizeof(unsigned long),
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
	   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));  
335 336
}

337 338 339 340 341
static void
time_hash(const struct nettle_hash *hash)
{
  static uint8_t data[BENCH_BLOCK];
  struct bench_hash_info info;
342

343
  info.ctx = xalloc(hash->context_size); 
344 345 346 347 348 349
  info.update = hash->update;
  info.data = data;

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

Niels Möller's avatar
Niels Möller committed
350
  display(hash->name, "update", hash->block_size,
351
	  time_function(bench_hash, &info));
352 353

  free(info.ctx);
354 355
}

Niels Möller's avatar
Niels Möller committed
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
static void
time_umac(void)
{
  static uint8_t data[BENCH_BLOCK];
  struct bench_hash_info info;
  struct umac32_ctx ctx32;
  struct umac64_ctx ctx64;
  struct umac96_ctx ctx96;
  struct umac128_ctx ctx128;
  
  uint8_t key[16];

  umac32_set_key (&ctx32, key);
  info.ctx = &ctx32;
  info.update = (nettle_hash_update_func *) umac32_update;
  info.data = data;

  display("umac32", "update", UMAC_BLOCK_SIZE,
	  time_function(bench_hash, &info));

  umac64_set_key (&ctx64, key);
  info.ctx = &ctx64;
  info.update = (nettle_hash_update_func *) umac64_update;
  info.data = data;

  display("umac64", "update", UMAC_BLOCK_SIZE,
	  time_function(bench_hash, &info));

  umac96_set_key (&ctx96, key);
  info.ctx = &ctx96;
  info.update = (nettle_hash_update_func *) umac96_update;
  info.data = data;

  display("umac96", "update", UMAC_BLOCK_SIZE,
	  time_function(bench_hash, &info));

  umac128_set_key (&ctx128, key);
  info.ctx = &ctx128;
  info.update = (nettle_hash_update_func *) umac128_update;
  info.data = data;

  display("umac128", "update", UMAC_BLOCK_SIZE,
	  time_function(bench_hash, &info));
}

Niels Möller's avatar
Niels Möller committed
401
static void
402
time_gcm(void)
Niels Möller's avatar
Niels Möller committed
403 404
{
  static uint8_t data[BENCH_BLOCK];
405 406
  struct bench_hash_info hinfo;
  struct bench_cipher_info cinfo;
407
  struct gcm_aes_ctx ctx;
408

Niels Möller's avatar
Niels Möller committed
409 410 411
  uint8_t key[16];
  uint8_t iv[GCM_IV_SIZE];

412 413
  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
414

415 416 417 418 419 420 421 422 423 424
  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
425

426 427 428 429 430 431 432
  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
433 434
}

435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
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
452
static void
453
time_cipher(const struct nettle_cipher *cipher)
Niels Möller's avatar
Niels Möller committed
454
{
455 456
  void *ctx = xalloc(cipher->context_size);
  uint8_t *key = xalloc(cipher->key_size);
Niels Möller's avatar
Niels Möller committed
457

458
  static uint8_t data[BENCH_BLOCK];
Niels Möller's avatar
Niels Möller committed
459 460 461 462

  printf("\n");
  
  init_data(data);
463 464

  {
Niels Möller's avatar
Niels Möller committed
465 466 467 468 469
    /* 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;
470
    
Niels Möller's avatar
Niels Möller committed
471
    init_key(cipher->key_size, key);
472
    cipher->set_encrypt_key(ctx, cipher->key_size, key);
Niels Möller's avatar
Niels Möller committed
473

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

Niels Möller's avatar
Niels Möller committed
487
    display(cipher->name, "ECB decrypt", cipher->block_size,
Niels Möller's avatar
Niels Möller committed
488
	    time_function(bench_cipher, &info));
489 490
  }

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

Niels Möller's avatar
Niels Möller committed
508
	display(cipher->name, "CBC encrypt", cipher->block_size,
Niels Möller's avatar
Niels Möller committed
509
		time_function(bench_cbc_encrypt, &info));
Niels Möller's avatar
Niels Möller committed
510
      }
511

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

522
        cipher->set_decrypt_key(ctx, cipher->key_size, key);
523

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

      /* 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));	
      }
      
545
      free(iv);
Niels Möller's avatar
Niels Möller committed
546
    }
547 548
  free(ctx);
  free(key);
Niels Möller's avatar
Niels Möller committed
549 550
}

Niels Möller's avatar
Niels Möller committed
551 552
/* Try to get accurate cycle times for assembler functions. */
#if WITH_CYCLE_COUNTER
553 554 555 556 557 558 559 560 561 562 563 564 565
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
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
#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)

588 589 590 591
static void
bench_sha1_compress(void)
{
  uint32_t state[_SHA1_DIGEST_LENGTH];
Niels Möller's avatar
Niels Möller committed
592 593
  uint8_t data[SHA1_DATA_SIZE];
  double t;
594

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

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

600 601 602 603
static void
bench_salsa20_core(void)
{
  uint32_t state[_SALSA20_INPUT_LENGTH];
Niels Möller's avatar
Niels Möller committed
604
  double t;
605

Niels Möller's avatar
Niels Möller committed
606 607 608
  TIME_CYCLES (t, _nettle_salsa20_core(state, state, 20));
  printf("salsa20_core: %.2f cycles\n", t);  
}
609

Niels Möller's avatar
Niels Möller committed
610 611 612 613 614
static void
bench_sha3_permute(void)
{
  struct sha3_state state;
  double t;
615

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

Niels Möller's avatar
Niels Möller committed
625
#if WITH_OPENSSL
626 627 628 629
# define OPENSSL(x) x,
#else
# define OPENSSL(x)
#endif
Niels Möller's avatar
Niels Möller committed
630 631

int
632
main(int argc, char **argv)
Niels Möller's avatar
Niels Möller committed
633 634
{
  unsigned i;
635
  int c;
636
  const char *alg;
637 638 639 640

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

651
  const struct nettle_cipher *ciphers[] =
Niels Möller's avatar
Niels Möller committed
652
    {
653
      &nettle_aes128, &nettle_aes192, &nettle_aes256,
Niels Möller's avatar
Niels Möller committed
654 655 656 657 658
      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
659
      &nettle_camellia128, &nettle_camellia192, &nettle_camellia256,
660 661 662
      &nettle_cast128, OPENSSL(&nettle_openssl_cast128)
      &nettle_des, OPENSSL(&nettle_openssl_des)
      &nettle_des3,
663 664
      &nettle_serpent256,
      &nettle_twofish128, &nettle_twofish192, &nettle_twofish256,
Niels Möller's avatar
Niels Möller committed
665
      &nettle_salsa20, &nettle_salsa20r12,
666
      NULL
Niels Möller's avatar
Niels Möller committed
667
    };
668

669 670 671 672 673 674 675 676 677 678
  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)
679 680 681 682 683 684 685
    switch (c)
      {
      case 'f':
	frequency = atof(optarg);
	if (frequency > 0.0)
	  break;

686 687 688 689 690
      case OPT_HELP:
	printf("Usage: nettle-benchmark [-f clock frequency] [alg]\n");
	return EXIT_SUCCESS;

      case '?':
691 692 693 694 695 696
	return EXIT_FAILURE;

      default:
	abort();
    }

697
  alg = argv[optind];
698

699
  time_init();
700
  bench_sha1_compress();
701
  bench_salsa20_core();
Niels Möller's avatar
Niels Möller committed
702 703
  bench_sha3_permute();
  printf("\n");
704 705
  time_overhead();

706 707
  header();

708 709 710 711 712
  if (!alg || strstr ("memxor", alg))
    {
      time_memxor();
      printf("\n");
    }
713
  
714
  for (i = 0; hashes[i]; i++)
715 716
    if (!alg || strstr(hashes[i]->name, alg))
      time_hash(hashes[i]);
Niels Möller's avatar
Niels Möller committed
717

Niels Möller's avatar
Niels Möller committed
718 719 720
  if (!alg || strstr ("umac", alg))
    time_umac();

721
  for (i = 0; ciphers[i]; i++)
722 723 724
    if (!alg || strstr(ciphers[i]->name, alg))
      time_cipher(ciphers[i]);

725 726 727 728 729 730
  if (!alg || strstr ("gcm", alg))
    {
      printf("\n");
      time_gcm();
    }

731 732
  return 0;
}