nettle-benchmark.c 18 KB
Newer Older
1
/* nettle-benchmark.c
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
   
   Tests the performance of the various algorithms.

   Copyright (C) 2001, 2010, 2014 Niels Möller

   This file is part of GNU Nettle.

   GNU Nettle is free software: you can redistribute it and/or
   modify it under the terms of either:

     * the GNU Lesser General Public License as published by the Free
       Software Foundation; either version 3 of the License, or (at your
       option) any later version.

   or

     * the GNU General Public License as published by the Free
       Software Foundation; either version 2 of the License, or (at your
       option) any later version.

   or both in parallel, as here.

   GNU Nettle 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
   General Public License for more details.

   You should have received copies of the GNU General Public License and
   the GNU Lesser General Public License along with this program.  If
   not, see http://www.gnu.org/licenses/.
*/
33

34
35
#if HAVE_CONFIG_H
# include "config.h"
36
37
38
39
#endif

#include <assert.h>
#include <errno.h>
40
#include <math.h>
Niels Möller's avatar
Niels Möller committed
41
#include <stdarg.h>
42
43
44
45
46
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <time.h>
47

48
49
#include "timing.h"

50
#include "aes.h"
Niels Möller's avatar
Niels Möller committed
51
52
53
#include "arcfour.h"
#include "blowfish.h"
#include "cast128.h"
Niels Möller's avatar
Niels Möller committed
54
#include "cbc.h"
Niels Möller's avatar
Niels Möller committed
55
#include "ctr.h"
Niels Möller's avatar
Niels Möller committed
56
#include "des.h"
57
#include "eax.h"
Niels Möller's avatar
Niels Möller committed
58
#include "gcm.h"
59
#include "memxor.h"
60
#include "salsa20.h"
Niels Möller's avatar
Niels Möller committed
61
#include "serpent.h"
62
63
#include "sha1.h"
#include "sha2.h"
Niels Möller's avatar
Niels Möller committed
64
#include "sha3.h"
Niels Möller's avatar
Niels Möller committed
65
#include "twofish.h"
Niels Möller's avatar
Niels Möller committed
66
#include "umac.h"
67
#include "poly1305.h"
Niels Möller's avatar
Niels Möller committed
68

69
70
71
#include "nettle-meta.h"
#include "nettle-internal.h"

Niels Möller's avatar
Niels Möller committed
72
#include "getopt.h"
73

74
static double frequency = 0.0;
Niels Möller's avatar
Niels Möller committed
75

76
/* Process BENCH_BLOCK bytes at a time, for BENCH_INTERVAL seconds. */
77
#define BENCH_BLOCK 10240
78
#define BENCH_INTERVAL 0.1
Niels Möller's avatar
Niels Möller committed
79

80
81
/* FIXME: Proper configure test for rdtsc? */
#ifndef WITH_CYCLE_COUNTER
82
# if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
83
84
85
86
87
88
89
#  define WITH_CYCLE_COUNTER 1
# else
#  define WITH_CYCLE_COUNTER 0
# endif
#endif

#if WITH_CYCLE_COUNTER
90
# if defined(__i386__)
91
92
93
94
95
96
97
98
99
#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")
100
101
102
103
104
105
106
107
108
109
110
# 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
111
112
113
#define BENCH_ITERATIONS 10
#endif

114
static void NORETURN PRINTF_STYLE(1,2)
Niels Möller's avatar
Niels Möller committed
115
116
117
118
119
120
121
122
123
124
die(const char *format, ...)
{
  va_list args;
  va_start(args, format);
  vfprintf(stderr, format, args);
  va_end(args);

  exit(EXIT_FAILURE);
}

125
126
static double overhead = 0.0; 

127
/* Returns second per function call */
128
129
130
static double
time_function(void (*f)(void *arg), void *arg)
{
131
  unsigned ncalls;
132
133
  double elapsed;

134
  for (ncalls = 10 ;;)
135
    {
136
      unsigned i;
137
138

      time_start();
139
140
      for (i = 0; i < ncalls; i++)
	f(arg);
141
      elapsed = time_end();
142
143
144
145
146
147
      if (elapsed > BENCH_INTERVAL)
	break;
      else if (elapsed < BENCH_INTERVAL / 10)
	ncalls *= 10;
      else
	ncalls *= 2;
148
    }
149
150
151
152
153
154
155
  return elapsed / ncalls - overhead;
}

static void
bench_nothing(void *arg UNUSED)
{
  return;
156
157
}

158
159
struct bench_memxor_info
{
160
161
162
  void *dst;
  const void *src;
  const void *other;
163
164
165
166
167
168
169
170
171
};

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

172
173
174
175
176
177
178
static void
bench_memxor3(void *arg)
{
  struct bench_memxor_info *info = arg;
  memxor3 (info->dst, info->src, info->other, BENCH_BLOCK);
}

179
180
181
struct bench_hash_info
{
  void *ctx;
182
  nettle_hash_update_func *update;
183
184
185
186
187
188
189
190
191
192
  const uint8_t *data;
};

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

193
194
195
struct bench_cipher_info
{
  void *ctx;
196
  nettle_cipher_func *crypt;
197
198
199
200
201
202
203
  uint8_t *data;
};

static void
bench_cipher(void *arg)
{
  struct bench_cipher_info *info = arg;
204
  info->crypt(info->ctx, BENCH_BLOCK, info->data, info->data);
205
206
207
208
209
}

struct bench_cbc_info
{
  void *ctx;
210
  nettle_cipher_func *crypt;
211
 
212
  uint8_t *data;
213
  
214
215
216
217
218
219
220
221
  unsigned block_size;
  uint8_t *iv;
};

static void
bench_cbc_encrypt(void *arg)
{
  struct bench_cbc_info *info = arg;
222
223
224
  cbc_encrypt(info->ctx, info->crypt,
	      info->block_size, info->iv,
	      BENCH_BLOCK, info->data, info->data);
225
226
227
228
229
230
}

static void
bench_cbc_decrypt(void *arg)
{
  struct bench_cbc_info *info = arg;
231
232
233
  cbc_decrypt(info->ctx, info->crypt,
	      info->block_size, info->iv,
	      BENCH_BLOCK, info->data, info->data);
234
235
}

Niels Möller's avatar
Niels Möller committed
236
237
238
239
240
241
242
243
244
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);
}

245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
struct bench_aead_info
{
  void *ctx;
  nettle_crypt_func *crypt;
  nettle_hash_update_func *update;
  uint8_t *data;
};

static void
bench_aead_crypt(void *arg)
{
  const struct bench_aead_info *info = arg;
  info->crypt (info->ctx, BENCH_BLOCK, info->data, info->data);
}

static void
bench_aead_update(void *arg)
{
  const struct bench_aead_info *info = arg;
  info->update (info->ctx, BENCH_BLOCK, info->data);
}

267
268
269
270
271
/* 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
272
  for (i = j = 0; i<BENCH_BLOCK;  i++)
273
274
275
276
277
278
279
280
    {
      if (j*j < i)
	j++;
      data[i] = j;
    }
}

static void
Niels Möller's avatar
Niels Möller committed
281
282
init_key(unsigned length,
         uint8_t *key)
283
{
Niels Möller's avatar
Niels Möller committed
284
285
286
  unsigned i;
  for (i = 0; i<length; i++)
    key[i] = i;
287
288
}

289
290
291
292
293
294
295
296
297
static void
init_nonce(unsigned length,
	   uint8_t *nonce)
{
  unsigned i;
  for (i = 0; i<length; i++)
    nonce[i] = 3*i;
}

298
299
300
301
302
static void
header(void)
{
  printf("%18s %11s Mbyte/s%s\n",
	 "Algorithm", "mode", 
Niels Möller's avatar
Niels Möller committed
303
	 frequency > 0.0 ? " cycles/byte cycles/block" : "");  
304
305
}

Niels Möller's avatar
Niels Möller committed
306
static void
Niels Möller's avatar
Niels Möller committed
307
display(const char *name, const char *mode, unsigned block_size,
308
	double time)
Niels Möller's avatar
Niels Möller committed
309
{
310
  printf("%18s %11s %7.2f",
Niels Möller's avatar
Niels Möller committed
311
	 name, mode,
312
	 BENCH_BLOCK / (time * 1048576.0));
313
  if (frequency > 0.0)
Niels Möller's avatar
Niels Möller committed
314
    {
315
      printf(" %11.2f", time * frequency / BENCH_BLOCK);
Niels Möller's avatar
Niels Möller committed
316
      if (block_size > 0)
317
	printf(" %12.2f", time * frequency * block_size / BENCH_BLOCK);
Niels Möller's avatar
Niels Möller committed
318
    }
319
  printf("\n");
Niels Möller's avatar
Niels Möller committed
320
321
}

322
323
324
325
326
static void *
xalloc(size_t size)
{
  void *p = malloc(size);
  if (!p)
327
    die("Virtual memory exhausted.\n");
328
329
330
331

  return p;
}

332
333
334
335
336
337
338
339
340
341
342
343
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");  
}



344
345
346
347
static void
time_memxor(void)
{
  struct bench_memxor_info info;
348
349
350
  unsigned long src[BENCH_BLOCK / sizeof(long) + 2];
  unsigned long other[BENCH_BLOCK / sizeof(long) + 2];
  unsigned long dst[BENCH_BLOCK / sizeof(long) + 1];
351
352
353
354

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

355
356
  display ("memxor", "aligned", sizeof(unsigned long),
	   time_function(bench_memxor, &info));
357
  info.src = (const char *) src + 1;
358
  display ("memxor", "unaligned", sizeof(unsigned long),
359
360
361
362
363
364
365
	   time_function(bench_memxor, &info));

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

366
  info.other = (const char *) other + 1;
367
368
  display ("memxor3", "unaligned01", sizeof(unsigned long),
	   time_function(bench_memxor3, &info));
369
  info.src = (const char *) src + 1;
370
371
  display ("memxor3", "unaligned11", sizeof(unsigned long),
	   time_function(bench_memxor3, &info));
372
  info.other = (const char *) other + 2;
373
374
  display ("memxor3", "unaligned12", sizeof(unsigned long),
	   time_function(bench_memxor3, &info));  
375
376
}

377
378
379
380
381
static void
time_hash(const struct nettle_hash *hash)
{
  static uint8_t data[BENCH_BLOCK];
  struct bench_hash_info info;
382

383
  info.ctx = xalloc(hash->context_size); 
384
385
386
387
388
389
  info.update = hash->update;
  info.data = data;

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

Niels Möller's avatar
Niels Möller committed
390
  display(hash->name, "update", hash->block_size,
391
	  time_function(bench_hash, &info));
392
393

  free(info.ctx);
394
395
}

Niels Möller's avatar
Niels Möller committed
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
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;

413
  display("umac32", "update", UMAC_BLOCK_SIZE,
Niels Möller's avatar
Niels Möller committed
414
415
416
417
418
419
420
	  time_function(bench_hash, &info));

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

421
  display("umac64", "update", UMAC_BLOCK_SIZE,
Niels Möller's avatar
Niels Möller committed
422
423
424
425
426
427
428
	  time_function(bench_hash, &info));

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

429
  display("umac96", "update", UMAC_BLOCK_SIZE,
Niels Möller's avatar
Niels Möller committed
430
431
432
433
434
435
436
	  time_function(bench_hash, &info));

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

437
  display("umac128", "update", UMAC_BLOCK_SIZE,
Niels Möller's avatar
Niels Möller committed
438
439
440
	  time_function(bench_hash, &info));
}

441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
static void
time_poly1305_aes(void)
{
  static uint8_t data[BENCH_BLOCK];
  struct bench_hash_info info;
  struct poly1305_aes_ctx ctx;
  uint8_t key[32];

  poly1305_aes_set_key (&ctx, key);
  info.ctx = &ctx;
  info.update = (nettle_hash_update_func *) poly1305_aes_update;
  info.data = data;

  display("poly1305-aes", "update", 1024,
	  time_function(bench_hash, &info));
}

458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
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
475
static void
476
time_cipher(const struct nettle_cipher *cipher)
Niels Möller's avatar
Niels Möller committed
477
{
478
479
  void *ctx = xalloc(cipher->context_size);
  uint8_t *key = xalloc(cipher->key_size);
Niels Möller's avatar
Niels Möller committed
480

481
  static uint8_t data[BENCH_BLOCK];
Niels Möller's avatar
Niels Möller committed
482
483
484
485

  printf("\n");
  
  init_data(data);
486
487

  {
Niels Möller's avatar
Niels Möller committed
488
489
490
491
492
    /* 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;
493
    
Niels Möller's avatar
Niels Möller committed
494
    init_key(cipher->key_size, key);
495
    cipher->set_encrypt_key(ctx, key);
Niels Möller's avatar
Niels Möller committed
496

Niels Möller's avatar
Niels Möller committed
497
    display(cipher->name, "ECB encrypt", cipher->block_size,
Niels Möller's avatar
Niels Möller committed
498
	    time_function(bench_cipher, &info));
499
  }
Niels Möller's avatar
Niels Möller committed
500
  
501
  {
Niels Möller's avatar
Niels Möller committed
502
503
504
505
    struct bench_cipher_info info;
    info.ctx = ctx;
    info.crypt = cipher->decrypt;
    info.data = data;
506
    
Niels Möller's avatar
Niels Möller committed
507
    init_key(cipher->key_size, key);
508
    cipher->set_decrypt_key(ctx, key);
Niels Möller's avatar
Niels Möller committed
509

Niels Möller's avatar
Niels Möller committed
510
    display(cipher->name, "ECB decrypt", cipher->block_size,
Niels Möller's avatar
Niels Möller committed
511
	    time_function(bench_cipher, &info));
512
513
  }

514
  if (block_cipher_p(cipher))
Niels Möller's avatar
Niels Möller committed
515
    {
516
      uint8_t *iv = xalloc(cipher->block_size);
Niels Möller's avatar
Niels Möller committed
517
518
519
      
      /* Do CBC mode */
      {
Niels Möller's avatar
Niels Möller committed
520
521
522
523
524
525
        struct bench_cbc_info info;
	info.ctx = ctx;
	info.crypt = cipher->encrypt;
	info.data = data;
	info.block_size = cipher->block_size;
	info.iv = iv;
526
    
527
        memset(iv, 0, cipher->block_size);
528
    
529
        cipher->set_encrypt_key(ctx, key);
530

Niels Möller's avatar
Niels Möller committed
531
	display(cipher->name, "CBC encrypt", cipher->block_size,
Niels Möller's avatar
Niels Möller committed
532
		time_function(bench_cbc_encrypt, &info));
Niels Möller's avatar
Niels Möller committed
533
      }
534

Niels Möller's avatar
Niels Möller committed
535
      {
Niels Möller's avatar
Niels Möller committed
536
537
538
539
540
541
        struct bench_cbc_info info;
	info.ctx = ctx;
	info.crypt = cipher->decrypt;
	info.data = data;
	info.block_size = cipher->block_size;
	info.iv = iv;
542
    
543
        memset(iv, 0, cipher->block_size);
544

545
        cipher->set_decrypt_key(ctx, key);
546

Niels Möller's avatar
Niels Möller committed
547
	display(cipher->name, "CBC decrypt", cipher->block_size,
Niels Möller's avatar
Niels Möller committed
548
		time_function(bench_cbc_decrypt, &info));
Niels Möller's avatar
Niels Möller committed
549
      }
Niels Möller's avatar
Niels Möller committed
550
551
552
553
554
555
556
557
558
559

      /* 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;
    
560
        memset(iv, 0, cipher->block_size);
Niels Möller's avatar
Niels Möller committed
561
    
562
        cipher->set_encrypt_key(ctx, key);
Niels Möller's avatar
Niels Möller committed
563
564
565
566
567

	display(cipher->name, "CTR", cipher->block_size,
		time_function(bench_ctr, &info));	
      }
      
568
      free(iv);
Niels Möller's avatar
Niels Möller committed
569
    }
570
571
  free(ctx);
  free(key);
Niels Möller's avatar
Niels Möller committed
572
573
}

574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
static void
time_aead(const struct nettle_aead *aead)
{
  void *ctx = xalloc(aead->context_size);
  uint8_t *key = xalloc(aead->key_size);
  uint8_t *nonce = xalloc(aead->nonce_size);
  static uint8_t data[BENCH_BLOCK];

  printf("\n");
  
  init_data(data);
  if (aead->set_nonce)
    init_nonce (aead->nonce_size, nonce);

  {
    /* Decent initializers are a GNU extension, so don't use it here. */
    struct bench_aead_info info;
    info.ctx = ctx;
    info.crypt = aead->encrypt;
    info.data = data;
    
    init_key(aead->key_size, key);
    aead->set_encrypt_key(ctx, key);
    if (aead->set_nonce)
      aead->set_nonce (ctx, nonce);

    display(aead->name, "encrypt", aead->block_size,
	    time_function(bench_aead_crypt, &info));
  }
  
  {
    struct bench_aead_info info;
    info.ctx = ctx;
    info.crypt = aead->decrypt;
    info.data = data;
    
    init_key(aead->key_size, key);
    aead->set_decrypt_key(ctx, key);
    if (aead->set_nonce)
      aead->set_nonce (ctx, nonce);

    display(aead->name, "decrypt", aead->block_size,
	    time_function(bench_aead_crypt, &info));
  }

  if (aead->update)
    {
      struct bench_aead_info info;
      info.ctx = ctx;
      info.update = aead->update;
      info.data = data;

      aead->set_encrypt_key(ctx, key);

      if (aead->set_nonce)
	aead->set_nonce (ctx, nonce);
    
      display(aead->name, "update", aead->block_size,
	      time_function(bench_aead_update, &info));
    }
  free(ctx);
  free(key);
  free(nonce);
}

Niels Möller's avatar
Niels Möller committed
639
640
/* Try to get accurate cycle times for assembler functions. */
#if WITH_CYCLE_COUNTER
641
642
643
644
645
646
647
648
649
650
651
652
653
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
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
#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)

676
677
678
679
static void
bench_sha1_compress(void)
{
  uint32_t state[_SHA1_DIGEST_LENGTH];
680
  uint8_t data[SHA1_BLOCK_SIZE];
Niels Möller's avatar
Niels Möller committed
681
  double t;
682

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

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

688
689
690
691
static void
bench_salsa20_core(void)
{
  uint32_t state[_SALSA20_INPUT_LENGTH];
Niels Möller's avatar
Niels Möller committed
692
  double t;
693

Niels Möller's avatar
Niels Möller committed
694
695
696
  TIME_CYCLES (t, _nettle_salsa20_core(state, state, 20));
  printf("salsa20_core: %.2f cycles\n", t);  
}
697

Niels Möller's avatar
Niels Möller committed
698
699
700
701
702
static void
bench_sha3_permute(void)
{
  struct sha3_state state;
  double t;
703

Niels Möller's avatar
Niels Möller committed
704
705
  TIME_CYCLES (t, sha3_permute (&state));
  printf("sha3_permute: %.2f cycles (%.2f / round)\n", t, t / 24.0);
706
707
708
709
}
#else
#define bench_sha1_compress()
#define bench_salsa20_core()
Niels Möller's avatar
Niels Möller committed
710
#define bench_sha3_permute()
711
712
#endif

Niels Möller's avatar
Niels Möller committed
713
#if WITH_OPENSSL
714
715
716
717
# define OPENSSL(x) x,
#else
# define OPENSSL(x)
#endif
Niels Möller's avatar
Niels Möller committed
718
719

int
720
main(int argc, char **argv)
Niels Möller's avatar
Niels Möller committed
721
722
{
  unsigned i;
723
  int c;
724
  const char *alg;
725
726
727
728

  const struct nettle_hash *hashes[] =
    {
      &nettle_md2, &nettle_md4, &nettle_md5,
729
      OPENSSL(&nettle_openssl_md5)
730
      &nettle_sha1, OPENSSL(&nettle_openssl_sha1)
Niels Möller's avatar
Niels Möller committed
731
732
      &nettle_sha224, &nettle_sha256,
      &nettle_sha384, &nettle_sha512,
733
      &nettle_sha512_224, &nettle_sha512_256,
734
735
      &nettle_sha3_224, &nettle_sha3_256,
      &nettle_sha3_384, &nettle_sha3_512,
736
      &nettle_ripemd160, &nettle_gosthash94,
737
738
739
      NULL
    };

740
  const struct nettle_cipher *ciphers[] =
Niels Möller's avatar
Niels Möller committed
741
    {
742
      &nettle_aes128, &nettle_aes192, &nettle_aes256,
Niels Möller's avatar
Niels Möller committed
743
744
745
746
      OPENSSL(&nettle_openssl_aes128)
      OPENSSL(&nettle_openssl_aes192)
      OPENSSL(&nettle_openssl_aes256)
      &nettle_blowfish128, OPENSSL(&nettle_openssl_blowfish128)
Niels Möller's avatar
Niels Möller committed
747
      &nettle_camellia128, &nettle_camellia192, &nettle_camellia256,
748
749
750
      &nettle_cast128, OPENSSL(&nettle_openssl_cast128)
      &nettle_des, OPENSSL(&nettle_openssl_des)
      &nettle_des3,
751
752
      &nettle_serpent256,
      &nettle_twofish128, &nettle_twofish192, &nettle_twofish256,
753
754
755
756
757
      NULL
    };

  const struct nettle_aead *aeads[] =
    {
758
759
760
761
      /* Stream ciphers */
      &nettle_arcfour128, OPENSSL(&nettle_openssl_arcfour128)
      &nettle_salsa20, &nettle_salsa20r12, &nettle_chacha,
      /* Proper AEAD algorithme. */
762
763
764
765
766
767
768
      &nettle_gcm_aes128,
      &nettle_gcm_aes192,
      &nettle_gcm_aes256,
      &nettle_gcm_camellia128,
      &nettle_gcm_camellia256,
      &nettle_eax_aes128,
      &nettle_chacha_poly1305,
769
      NULL
Niels Möller's avatar
Niels Möller committed
770
    };
771

772
773
774
775
776
777
778
779
780
781
  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)
782
783
784
785
786
787
788
    switch (c)
      {
      case 'f':
	frequency = atof(optarg);
	if (frequency > 0.0)
	  break;

789
790
791
792
793
      case OPT_HELP:
	printf("Usage: nettle-benchmark [-f clock frequency] [alg]\n");
	return EXIT_SUCCESS;

      case '?':
794
795
796
797
798
799
	return EXIT_FAILURE;

      default:
	abort();
    }

800
  alg = argv[optind];
801

802
  time_init();
803
  bench_sha1_compress();
804
  bench_salsa20_core();
Niels Möller's avatar
Niels Möller committed
805
806
  bench_sha3_permute();
  printf("\n");
807
808
  time_overhead();

809
810
  header();

811
812
813
814
815
  if (!alg || strstr ("memxor", alg))
    {
      time_memxor();
      printf("\n");
    }
816
  
817
  for (i = 0; hashes[i]; i++)
818
819
    if (!alg || strstr(hashes[i]->name, alg))
      time_hash(hashes[i]);
Niels Möller's avatar
Niels Möller committed
820

Niels Möller's avatar
Niels Möller committed
821
822
823
  if (!alg || strstr ("umac", alg))
    time_umac();

824
825
826
  if (!alg || strstr ("poly1305-aes", alg))
    time_poly1305_aes();

827
  for (i = 0; ciphers[i]; i++)
828
829
830
    if (!alg || strstr(ciphers[i]->name, alg))
      time_cipher(ciphers[i]);

831
832
833
  for (i = 0; aeads[i]; i++)
    if (!alg || strstr(aeads[i]->name, alg))
      time_aead(aeads[i]);
Niels Möller's avatar
Niels Möller committed
834

835
836
  return 0;
}