Coverage Report

Created: 2024-02-29 06:05

/src/strongswan/src/libstrongswan/crypto/crypto_tester.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2009-2010 Martin Willi
3
 * Copyright (C) 2016-2019 Andreas Steffen
4
 *
5
 * Copyright (C) secunet Security Networks AG
6
 *
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms of the GNU General Public License as published by the
9
 * Free Software Foundation; either version 2 of the License, or (at your
10
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
 * for more details.
16
 */
17
18
#ifdef HAVE_DLADDR
19
# define _GNU_SOURCE
20
# include <dlfcn.h>
21
#endif
22
#include <time.h>
23
24
#include "crypto_tester.h"
25
26
#include <utils/debug.h>
27
#include <collections/linked_list.h>
28
#include <crypto/rngs/rng_tester.h>
29
30
typedef struct private_crypto_tester_t private_crypto_tester_t;
31
32
/**
33
 * Private data of an crypto_tester_t object.
34
 */
35
struct private_crypto_tester_t {
36
37
  /**
38
   * Public crypto_tester_t interface.
39
   */
40
  crypto_tester_t public;
41
42
  /**
43
   * List of crypter test vectors
44
   */
45
  linked_list_t *crypter;
46
47
  /**
48
   * List of aead test vectors
49
   */
50
  linked_list_t *aead;
51
52
  /**
53
   * List of signer test vectors
54
   */
55
  linked_list_t *signer;
56
57
  /**
58
   * List of hasher test vectors
59
   */
60
  linked_list_t *hasher;
61
62
  /**
63
   * List of PRF test vectors
64
   */
65
  linked_list_t *prf;
66
67
  /**
68
   * List of XOF test vectors
69
   */
70
  linked_list_t *xof;
71
72
  /**
73
   * List of KDF test vectors
74
   */
75
  linked_list_t *kdf;
76
77
  /**
78
   * List of DRBG test vectors
79
   */
80
  linked_list_t *drbg;
81
82
  /**
83
   * List of RNG test vectors
84
   */
85
  linked_list_t *rng;
86
87
  /**
88
   * List of key exchange method test vectors
89
   */
90
  linked_list_t *ke;
91
92
  /**
93
   * Is a test vector required to pass a test?
94
   */
95
  bool required;
96
97
  /**
98
   * should we run RNG_TRUE tests? Enough entropy?
99
   */
100
  bool rng_true;
101
102
  /**
103
   * time we test each algorithm
104
   */
105
  int bench_time;
106
107
  /**
108
   * size of buffer we use for benchmarking
109
   */
110
  int bench_size;
111
};
112
113
#if DEBUG_LEVEL >= 1
114
/**
115
 * Get the name of a test vector, if available
116
 */
117
static const char* get_name(void *sym)
118
0
{
119
0
#ifdef HAVE_DLADDR
120
0
  Dl_info dli;
121
122
0
  if (dladdr(sym, &dli))
123
0
  {
124
0
    return dli.dli_sname;
125
0
  }
126
0
#endif
127
0
  return "unknown";
128
0
}
129
#endif
130
131
#if defined(CLOCK_THREAD_CPUTIME_ID) && defined(HAVE_CLOCK_GETTIME)
132
133
/**
134
 * Start a benchmark timer
135
 */
136
static void start_timing(struct timespec *start)
137
0
{
138
0
  clock_gettime(CLOCK_THREAD_CPUTIME_ID, start);
139
0
}
140
141
/**
142
 * End a benchmark timer, return ms
143
 */
144
static u_int end_timing(struct timespec *start)
145
0
{
146
0
  struct timespec end;
147
148
0
  clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end);
149
0
  return (end.tv_nsec - start->tv_nsec) / 1000000 +
150
0
      (end.tv_sec - start->tv_sec) * 1000;
151
0
}
152
153
#else /* CLOCK_THREAD_CPUTIME_ID */
154
155
/* Make benchmarking a no-op if CLOCK_THREAD_CPUTIME_ID is not available */
156
#define start_timing(start) ((start)->tv_sec = 0, (start)->tv_nsec = 0)
157
#define end_timing(...) (this->bench_time)
158
159
#endif /* CLOCK_THREAD_CPUTIME_ID */
160
161
/**
162
 * Benchmark a crypter
163
 */
164
static u_int bench_crypter(private_crypto_tester_t *this,
165
  encryption_algorithm_t alg, crypter_constructor_t create, size_t key_size)
166
0
{
167
0
  crypter_t *crypter;
168
169
0
  crypter = create(alg, key_size);
170
0
  if (crypter)
171
0
  {
172
0
    char iv[crypter->get_iv_size(crypter)];
173
0
    char key[crypter->get_key_size(crypter)];
174
0
    chunk_t buf;
175
0
    struct timespec start;
176
0
    u_int runs;
177
178
0
    memset(iv, 0x56, sizeof(iv));
179
0
    memset(key, 0x12, sizeof(key));
180
0
    if (!crypter->set_key(crypter, chunk_from_thing(key)))
181
0
    {
182
0
      return 0;
183
0
    }
184
185
0
    buf = chunk_alloc(this->bench_size);
186
0
    memset(buf.ptr, 0x34, buf.len);
187
188
0
    runs = 0;
189
0
    start_timing(&start);
190
0
    while (end_timing(&start) < this->bench_time)
191
0
    {
192
0
      if (crypter->encrypt(crypter, buf, chunk_from_thing(iv), NULL))
193
0
      {
194
0
        runs++;
195
0
      }
196
0
      if (crypter->decrypt(crypter, buf, chunk_from_thing(iv), NULL))
197
0
      {
198
0
        runs++;
199
0
      }
200
0
    }
201
0
    free(buf.ptr);
202
0
    crypter->destroy(crypter);
203
204
0
    return runs;
205
0
  }
206
0
  return 0;
207
0
}
208
209
METHOD(crypto_tester_t, test_crypter, bool,
210
  private_crypto_tester_t *this, encryption_algorithm_t alg, size_t key_size,
211
  crypter_constructor_t create, u_int *speed, const char *plugin_name)
212
0
{
213
0
  enumerator_t *enumerator;
214
0
  crypter_test_vector_t *vector;
215
0
  bool failed = FALSE;
216
0
  u_int tested = 0;
217
218
0
  enumerator = this->crypter->create_enumerator(this->crypter);
219
0
  while (enumerator->enumerate(enumerator, &vector))
220
0
  {
221
0
    crypter_t *crypter;
222
0
    chunk_t key, iv, plain = chunk_empty, cipher = chunk_empty;
223
224
0
    if (vector->alg != alg)
225
0
    {
226
0
      continue;
227
0
    }
228
0
    if (key_size && key_size != vector->key_size)
229
0
    { /* test only vectors with a specific key size, if key size given */
230
0
      continue;
231
0
    }
232
233
0
    crypter = create(alg, vector->key_size);
234
0
    if (!crypter)
235
0
    { /* key size not supported */
236
0
      continue;
237
0
    }
238
0
    tested++;
239
0
    failed = TRUE;
240
241
0
    key = chunk_create(vector->key, crypter->get_key_size(crypter));
242
0
    if (!crypter->set_key(crypter, key))
243
0
    {
244
0
      goto failure;
245
0
    }
246
0
    iv = chunk_create(vector->iv, crypter->get_iv_size(crypter));
247
248
    /* allocated encryption */
249
0
    plain = chunk_create(vector->plain, vector->len);
250
0
    if (!crypter->encrypt(crypter, plain, iv, &cipher))
251
0
    {
252
0
      goto failure;
253
0
    }
254
0
    if (!memeq(vector->cipher, cipher.ptr, cipher.len))
255
0
    {
256
0
      goto failure;
257
0
    }
258
    /* inline decryption */
259
0
    if (!crypter->decrypt(crypter, cipher, iv, NULL))
260
0
    {
261
0
      goto failure;
262
0
    }
263
0
    if (!memeq(vector->plain, cipher.ptr, cipher.len))
264
0
    {
265
0
      goto failure;
266
0
    }
267
    /* allocated decryption */
268
0
    if (!crypter->decrypt(crypter,
269
0
            chunk_create(vector->cipher, vector->len), iv, &plain))
270
0
    {
271
0
      goto failure;
272
0
    }
273
0
    if (!memeq(vector->plain, plain.ptr, plain.len))
274
0
    {
275
0
      goto failure;
276
0
    }
277
    /* inline encryption */
278
0
    if (!crypter->encrypt(crypter, plain, iv, NULL))
279
0
    {
280
0
      goto failure;
281
0
    }
282
0
    if (!memeq(vector->cipher, plain.ptr, plain.len))
283
0
    {
284
0
      goto failure;
285
0
    }
286
287
0
    failed = FALSE;
288
0
failure:
289
0
    crypter->destroy(crypter);
290
0
    chunk_free(&cipher);
291
0
    if (plain.ptr != vector->plain)
292
0
    {
293
0
      chunk_free(&plain);
294
0
    }
295
0
    if (failed)
296
0
    {
297
0
      DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
298
0
         encryption_algorithm_names, alg, plugin_name, get_name(vector));
299
0
      break;
300
0
    }
301
0
  }
302
0
  enumerator->destroy(enumerator);
303
0
  if (!tested)
304
0
  {
305
0
    if (failed)
306
0
    {
307
0
      DBG1(DBG_LIB,"disable %N[%s]: %zd byte key size not supported",
308
0
         encryption_algorithm_names, alg, plugin_name, key_size);
309
0
      return FALSE;
310
0
    }
311
0
    else
312
0
    {
313
0
      DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
314
0
         this->required ? "disabled" : "enabled ",
315
0
         encryption_algorithm_names, alg, plugin_name);
316
0
      return !this->required;
317
0
    }
318
0
  }
319
0
  if (!failed)
320
0
  {
321
0
    if (speed)
322
0
    {
323
0
      *speed = bench_crypter(this, alg, create, key_size);
324
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points "
325
0
         "(%zd bit key)", encryption_algorithm_names, alg,
326
0
         plugin_name, tested, *speed, key_size * 8);
327
0
    }
328
0
    else
329
0
    {
330
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
331
0
         encryption_algorithm_names, alg, plugin_name, tested);
332
0
    }
333
0
  }
334
0
  return !failed;
335
0
}
336
337
/**
338
 * Benchmark an aead transform
339
 */
340
static u_int bench_aead(private_crypto_tester_t *this,
341
  encryption_algorithm_t alg, aead_constructor_t create, size_t key_size)
342
0
{
343
0
  aead_t *aead;
344
345
0
  aead = create(alg, key_size, 0);
346
0
  if (aead)
347
0
  {
348
0
    char iv[aead->get_iv_size(aead)];
349
0
    char key[aead->get_key_size(aead)];
350
0
    char assoc[4];
351
0
    chunk_t buf;
352
0
    struct timespec start;
353
0
    u_int runs;
354
0
    size_t icv;
355
356
0
    memset(iv, 0x56, sizeof(iv));
357
0
    memset(key, 0x12, sizeof(key));
358
0
    memset(assoc, 0x78, sizeof(assoc));
359
0
    if (!aead->set_key(aead, chunk_from_thing(key)))
360
0
    {
361
0
      return 0;
362
0
    }
363
0
    icv = aead->get_icv_size(aead);
364
365
0
    buf = chunk_alloc(this->bench_size + icv);
366
0
    memset(buf.ptr, 0x34, buf.len);
367
0
    buf.len -= icv;
368
369
0
    runs = 0;
370
0
    start_timing(&start);
371
0
    while (end_timing(&start) < this->bench_time)
372
0
    {
373
0
      if (aead->encrypt(aead, buf, chunk_from_thing(assoc),
374
0
            chunk_from_thing(iv), NULL))
375
0
      {
376
0
        runs += 2;
377
0
      }
378
0
      if (aead->decrypt(aead, chunk_create(buf.ptr, buf.len + icv),
379
0
            chunk_from_thing(assoc), chunk_from_thing(iv), NULL))
380
0
      {
381
0
        runs += 2;
382
0
      }
383
0
    }
384
0
    free(buf.ptr);
385
0
    aead->destroy(aead);
386
387
0
    return runs;
388
0
  }
389
0
  return 0;
390
0
}
391
392
METHOD(crypto_tester_t, test_aead, bool,
393
  private_crypto_tester_t *this, encryption_algorithm_t alg, size_t key_size,
394
  size_t salt_size, aead_constructor_t create,
395
  u_int *speed, const char *plugin_name)
396
0
{
397
0
  enumerator_t *enumerator;
398
0
  aead_test_vector_t *vector;
399
0
  bool failed = FALSE;
400
0
  u_int tested = 0;
401
402
0
  enumerator = this->aead->create_enumerator(this->aead);
403
0
  while (enumerator->enumerate(enumerator, &vector))
404
0
  {
405
0
    aead_t *aead;
406
0
    chunk_t key, iv, assoc, plain = chunk_empty, cipher = chunk_empty;
407
0
    size_t icv;
408
409
0
    if (vector->alg != alg)
410
0
    {
411
0
      continue;
412
0
    }
413
0
    if (key_size && key_size != vector->key_size)
414
0
    { /* test only vectors with a specific key size, if key size given */
415
0
      continue;
416
0
    }
417
0
    if (salt_size && salt_size != vector->salt_size)
418
0
    {
419
0
      continue;
420
0
    }
421
422
0
    tested++;
423
0
    failed = TRUE;
424
0
    aead = create(alg, vector->key_size, vector->salt_size);
425
0
    if (!aead)
426
0
    {
427
0
      DBG1(DBG_LIB, "%N[%s]: %u bit key size not supported",
428
0
         encryption_algorithm_names, alg, plugin_name,
429
0
         BITS_PER_BYTE * vector->key_size);
430
0
      continue;
431
0
    }
432
433
0
    key = chunk_create(vector->key, aead->get_key_size(aead));
434
0
    if (!aead->set_key(aead, key))
435
0
    {
436
0
      goto failure;
437
0
    }
438
0
    iv = chunk_create(vector->iv, aead->get_iv_size(aead));
439
0
    assoc = chunk_create(vector->adata, vector->alen);
440
0
    icv = aead->get_icv_size(aead);
441
442
    /* allocated encryption */
443
0
    plain = chunk_create(vector->plain, vector->len);
444
0
    if (!aead->encrypt(aead, plain, assoc, iv, &cipher))
445
0
    {
446
0
      goto failure;
447
0
    }
448
0
    if (!memeq(vector->cipher, cipher.ptr, cipher.len))
449
0
    {
450
0
      goto failure;
451
0
    }
452
    /* inline decryption */
453
0
    if (!aead->decrypt(aead, cipher, assoc, iv, NULL))
454
0
    {
455
0
      goto failure;
456
0
    }
457
0
    if (!memeq(vector->plain, cipher.ptr, cipher.len - icv))
458
0
    {
459
0
      goto failure;
460
0
    }
461
    /* allocated decryption */
462
0
    if (!aead->decrypt(aead, chunk_create(vector->cipher, vector->len + icv),
463
0
               assoc, iv, &plain))
464
0
    {
465
0
      goto failure;
466
0
    }
467
0
    if (!memeq(vector->plain, plain.ptr, plain.len))
468
0
    {
469
0
      goto failure;
470
0
    }
471
0
    plain.ptr = realloc(plain.ptr, plain.len + icv);
472
    /* inline encryption */
473
0
    if (!aead->encrypt(aead, plain, assoc, iv, NULL))
474
0
    {
475
0
      goto failure;
476
0
    }
477
0
    if (!memeq(vector->cipher, plain.ptr, plain.len + icv))
478
0
    {
479
0
      goto failure;
480
0
    }
481
482
0
    failed = FALSE;
483
0
failure:
484
0
    aead->destroy(aead);
485
0
    chunk_free(&cipher);
486
0
    if (plain.ptr != vector->plain)
487
0
    {
488
0
      chunk_free(&plain);
489
0
    }
490
0
    if (failed)
491
0
    {
492
0
      DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
493
0
         encryption_algorithm_names, alg, plugin_name, get_name(vector));
494
0
      break;
495
0
    }
496
0
  }
497
0
  enumerator->destroy(enumerator);
498
0
  if (!tested)
499
0
  {
500
0
    if (failed)
501
0
    {
502
0
      DBG1(DBG_LIB,"disable %N[%s]: %zd byte key size not supported",
503
0
         encryption_algorithm_names, alg, plugin_name, key_size);
504
0
      return FALSE;
505
0
    }
506
0
    else
507
0
    {
508
0
      DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
509
0
         this->required ? "disabled" : "enabled ",
510
0
         encryption_algorithm_names, alg, plugin_name);
511
0
      return !this->required;
512
0
    }
513
0
  }
514
0
  if (!failed)
515
0
  {
516
0
    if (speed)
517
0
    {
518
0
      *speed = bench_aead(this, alg, create, key_size);
519
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points "
520
0
         "(%zd bit key)", encryption_algorithm_names, alg,
521
0
         plugin_name, tested, *speed, key_size * 8);
522
0
    }
523
0
    else
524
0
    {
525
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
526
0
         encryption_algorithm_names, alg, plugin_name, tested);
527
0
    }
528
0
  }
529
0
  return !failed;
530
0
}
531
532
/**
533
 * Benchmark a signer
534
 */
535
static u_int bench_signer(private_crypto_tester_t *this,
536
  integrity_algorithm_t alg, signer_constructor_t create)
537
0
{
538
0
  signer_t *signer;
539
540
0
  signer = create(alg);
541
0
  if (signer)
542
0
  {
543
0
    char key[signer->get_key_size(signer)];
544
0
    char mac[signer->get_block_size(signer)];
545
0
    chunk_t buf;
546
0
    struct timespec start;
547
0
    u_int runs;
548
549
0
    memset(key, 0x12, sizeof(key));
550
0
    if (!signer->set_key(signer, chunk_from_thing(key)))
551
0
    {
552
0
      return 0;
553
0
    }
554
555
0
    buf = chunk_alloc(this->bench_size);
556
0
    memset(buf.ptr, 0x34, buf.len);
557
558
0
    runs = 0;
559
0
    start_timing(&start);
560
0
    while (end_timing(&start) < this->bench_time)
561
0
    {
562
0
      if (signer->get_signature(signer, buf, mac))
563
0
      {
564
0
        runs++;
565
0
      }
566
0
      if (signer->verify_signature(signer, buf, chunk_from_thing(mac)))
567
0
      {
568
0
        runs++;
569
0
      }
570
0
    }
571
0
    free(buf.ptr);
572
0
    signer->destroy(signer);
573
574
0
    return runs;
575
0
  }
576
0
  return 0;
577
0
}
578
579
METHOD(crypto_tester_t, test_signer, bool,
580
  private_crypto_tester_t *this, integrity_algorithm_t alg,
581
  signer_constructor_t create, u_int *speed, const char *plugin_name)
582
0
{
583
0
  enumerator_t *enumerator;
584
0
  signer_test_vector_t *vector;
585
0
  bool failed = FALSE;
586
0
  u_int tested = 0;
587
588
0
  enumerator = this->signer->create_enumerator(this->signer);
589
0
  while (enumerator->enumerate(enumerator, &vector))
590
0
  {
591
0
    signer_t *signer;
592
0
    chunk_t key, data, mac = chunk_empty;
593
594
0
    if (vector->alg != alg)
595
0
    {
596
0
      continue;
597
0
    }
598
599
0
    tested++;
600
0
    failed = TRUE;
601
0
    signer = create(alg);
602
0
    if (!signer)
603
0
    {
604
0
      DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
605
0
         integrity_algorithm_names, alg, plugin_name);
606
0
      break;
607
0
    }
608
609
0
    data = chunk_create(vector->data, vector->len);
610
0
    key = chunk_create(vector->key, signer->get_key_size(signer));
611
0
    if (!signer->set_key(signer, key))
612
0
    {
613
0
      goto failure;
614
0
    }
615
    /* do partial append mode and check if key gets set correctly */
616
0
    if (!signer->get_signature(signer, data, NULL))
617
0
    {
618
0
      goto failure;
619
0
    }
620
0
    if (!signer->set_key(signer, key))
621
0
    {
622
0
      goto failure;
623
0
    }
624
    /* allocated signature */
625
0
    if (!signer->allocate_signature(signer, data, &mac))
626
0
    {
627
0
      goto failure;
628
0
    }
629
0
    if (mac.len != signer->get_block_size(signer))
630
0
    {
631
0
      goto failure;
632
0
    }
633
0
    if (!memeq(vector->mac, mac.ptr, mac.len))
634
0
    {
635
0
      goto failure;
636
0
    }
637
    /* signature to existing buffer */
638
0
    memset(mac.ptr, 0, mac.len);
639
0
    if (!signer->get_signature(signer, data, mac.ptr))
640
0
    {
641
0
      goto failure;
642
0
    }
643
0
    if (!memeq(vector->mac, mac.ptr, mac.len))
644
0
    {
645
0
      goto failure;
646
0
    }
647
    /* signature verification, good case */
648
0
    if (!signer->verify_signature(signer, data, mac))
649
0
    {
650
0
      goto failure;
651
0
    }
652
    /* signature verification, bad case */
653
0
    *(mac.ptr + mac.len - 1) += 1;
654
0
    if (signer->verify_signature(signer, data, mac))
655
0
    {
656
0
      goto failure;
657
0
    }
658
    /* signature to existing buffer, using append mode */
659
0
    if (data.len > 2)
660
0
    {
661
0
      if (!signer->allocate_signature(signer,
662
0
                      chunk_create(data.ptr, 1), NULL))
663
0
      {
664
0
        goto failure;
665
0
      }
666
0
      if (!signer->get_signature(signer,
667
0
                     chunk_create(data.ptr + 1, 1), NULL))
668
0
      {
669
0
        goto failure;
670
0
      }
671
0
      if (!signer->verify_signature(signer, chunk_skip(data, 2),
672
0
                      chunk_create(vector->mac, mac.len)))
673
0
      {
674
0
        goto failure;
675
0
      }
676
0
    }
677
678
0
    failed = FALSE;
679
0
failure:
680
0
    signer->destroy(signer);
681
0
    chunk_free(&mac);
682
0
    if (failed)
683
0
    {
684
0
      DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
685
0
         integrity_algorithm_names, alg, plugin_name, get_name(vector));
686
0
      break;
687
0
    }
688
0
  }
689
0
  enumerator->destroy(enumerator);
690
0
  if (!tested)
691
0
  {
692
0
    DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
693
0
       this->required ? "disabled" : "enabled ",
694
0
       integrity_algorithm_names, alg, plugin_name);
695
0
    return !this->required;
696
0
  }
697
0
  if (!failed)
698
0
  {
699
0
    if (speed)
700
0
    {
701
0
      *speed = bench_signer(this, alg, create);
702
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
703
0
         integrity_algorithm_names, alg, plugin_name, tested, *speed);
704
0
    }
705
0
    else
706
0
    {
707
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
708
0
         integrity_algorithm_names, alg, plugin_name, tested);
709
0
    }
710
0
  }
711
0
  return !failed;
712
0
}
713
714
/**
715
 * Benchmark a hasher
716
 */
717
static u_int bench_hasher(private_crypto_tester_t *this,
718
  hash_algorithm_t alg, hasher_constructor_t create)
719
0
{
720
0
  hasher_t *hasher;
721
722
0
  hasher = create(alg);
723
0
  if (hasher)
724
0
  {
725
0
    char hash[hasher->get_hash_size(hasher)];
726
0
    chunk_t buf;
727
0
    struct timespec start;
728
0
    u_int runs;
729
730
0
    buf = chunk_alloc(this->bench_size);
731
0
    memset(buf.ptr, 0x34, buf.len);
732
733
0
    runs = 0;
734
0
    start_timing(&start);
735
0
    while (end_timing(&start) < this->bench_time)
736
0
    {
737
0
      if (hasher->get_hash(hasher, buf, hash))
738
0
      {
739
0
        runs++;
740
0
      }
741
0
    }
742
0
    free(buf.ptr);
743
0
    hasher->destroy(hasher);
744
745
0
    return runs;
746
0
  }
747
0
  return 0;
748
0
}
749
750
METHOD(crypto_tester_t, test_hasher, bool,
751
  private_crypto_tester_t *this, hash_algorithm_t alg,
752
  hasher_constructor_t create, u_int *speed, const char *plugin_name)
753
0
{
754
0
  enumerator_t *enumerator;
755
0
  hasher_test_vector_t *vector;
756
0
  bool failed = FALSE;
757
0
  u_int tested = 0;
758
759
0
  enumerator = this->hasher->create_enumerator(this->hasher);
760
0
  while (enumerator->enumerate(enumerator, &vector))
761
0
  {
762
0
    hasher_t *hasher;
763
0
    chunk_t data, hash;
764
765
0
    if (vector->alg != alg)
766
0
    {
767
0
      continue;
768
0
    }
769
770
0
    tested++;
771
0
    failed = TRUE;
772
0
    hasher = create(alg);
773
0
    if (!hasher)
774
0
    {
775
0
      DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
776
0
         hash_algorithm_names, alg, plugin_name);
777
0
      break;
778
0
    }
779
780
    /* allocated hash */
781
0
    data = chunk_create(vector->data, vector->len);
782
0
    if (!hasher->allocate_hash(hasher, data, &hash))
783
0
    {
784
0
      goto failure;
785
0
    }
786
0
    if (hash.len != hasher->get_hash_size(hasher))
787
0
    {
788
0
      goto failure;
789
0
    }
790
0
    if (!memeq(vector->hash, hash.ptr, hash.len))
791
0
    {
792
0
      goto failure;
793
0
    }
794
    /* hash to existing buffer, with a reset */
795
0
    memset(hash.ptr, 0, hash.len);
796
0
    if (!hasher->get_hash(hasher, data, NULL))
797
0
    {
798
0
      goto failure;
799
0
    }
800
0
    if (!hasher->reset(hasher))
801
0
    {
802
0
      goto failure;
803
0
    }
804
0
    if (!hasher->get_hash(hasher, data, hash.ptr))
805
0
    {
806
0
      goto failure;
807
0
    }
808
0
    if (!memeq(vector->hash, hash.ptr, hash.len))
809
0
    {
810
0
      goto failure;
811
0
    }
812
    /* hasher to existing buffer, using append mode */
813
0
    if (data.len > 2)
814
0
    {
815
0
      memset(hash.ptr, 0, hash.len);
816
0
      if (!hasher->allocate_hash(hasher, chunk_create(data.ptr, 1), NULL))
817
0
      {
818
0
        goto failure;
819
0
      }
820
0
      if (!hasher->get_hash(hasher, chunk_create(data.ptr + 1, 1), NULL))
821
0
      {
822
0
        goto failure;
823
0
      }
824
0
      if (!hasher->get_hash(hasher, chunk_skip(data, 2), hash.ptr))
825
0
      {
826
0
        goto failure;
827
0
      }
828
0
      if (!memeq(vector->hash, hash.ptr, hash.len))
829
0
      {
830
0
        goto failure;
831
0
      }
832
0
    }
833
834
0
    failed = FALSE;
835
0
failure:
836
0
    hasher->destroy(hasher);
837
0
    chunk_free(&hash);
838
0
    if (failed)
839
0
    {
840
0
      DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
841
0
         hash_algorithm_names, alg, plugin_name, get_name(vector));
842
0
      break;
843
0
    }
844
0
  }
845
0
  enumerator->destroy(enumerator);
846
0
  if (!tested)
847
0
  {
848
0
    DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
849
0
       this->required ? "disabled" : "enabled ",
850
0
       hash_algorithm_names, alg, plugin_name);
851
0
    return !this->required;
852
0
  }
853
0
  if (!failed)
854
0
  {
855
0
    if (speed)
856
0
    {
857
0
      *speed = bench_hasher(this, alg, create);
858
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
859
0
         hash_algorithm_names, alg, plugin_name, tested, *speed);
860
0
    }
861
0
    else
862
0
    {
863
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
864
0
         hash_algorithm_names, alg, plugin_name, tested);
865
0
    }
866
0
  }
867
0
  return !failed;
868
0
}
869
870
/**
871
 * Benchmark a PRF
872
 */
873
static u_int bench_prf(private_crypto_tester_t *this,
874
             pseudo_random_function_t alg, prf_constructor_t create)
875
0
{
876
0
  prf_t *prf;
877
878
0
  prf = create(alg);
879
0
  if (prf)
880
0
  {
881
0
    char bytes[prf->get_block_size(prf)], key[prf->get_block_size(prf)];
882
0
    chunk_t buf;
883
0
    struct timespec start;
884
0
    u_int runs;
885
886
0
    memset(key, 0x56, prf->get_block_size(prf));
887
0
    if (!prf->set_key(prf, chunk_create(key, prf->get_block_size(prf))))
888
0
    {
889
0
      prf->destroy(prf);
890
0
      return 0;
891
0
    }
892
893
0
    buf = chunk_alloc(this->bench_size);
894
0
    memset(buf.ptr, 0x34, buf.len);
895
896
0
    runs = 0;
897
0
    start_timing(&start);
898
0
    while (end_timing(&start) < this->bench_time)
899
0
    {
900
0
      if (prf->get_bytes(prf, buf, bytes))
901
0
      {
902
0
        runs++;
903
0
      }
904
0
    }
905
0
    free(buf.ptr);
906
0
    prf->destroy(prf);
907
908
0
    return runs;
909
0
  }
910
0
  return 0;
911
0
}
912
913
METHOD(crypto_tester_t, test_prf, bool,
914
  private_crypto_tester_t *this, pseudo_random_function_t alg,
915
  prf_constructor_t create, u_int *speed, const char *plugin_name)
916
0
{
917
0
  enumerator_t *enumerator;
918
0
  prf_test_vector_t *vector;
919
0
  bool failed = FALSE;
920
0
  u_int tested = 0;
921
922
0
  enumerator = this->prf->create_enumerator(this->prf);
923
0
  while (enumerator->enumerate(enumerator, &vector))
924
0
  {
925
0
    prf_t *prf;
926
0
    chunk_t key, seed, out = chunk_empty;
927
928
0
    if (vector->alg != alg)
929
0
    {
930
0
      continue;
931
0
    }
932
933
0
    tested++;
934
0
    failed = TRUE;
935
0
    prf = create(alg);
936
0
    if (!prf)
937
0
    {
938
0
      DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
939
0
         pseudo_random_function_names, alg, plugin_name);
940
0
      break;
941
0
    }
942
943
0
    seed = chunk_create(vector->seed, vector->len);
944
0
    key = chunk_create(vector->key, vector->key_size);
945
0
    if (!prf->set_key(prf, key))
946
0
    {
947
0
      goto failure;
948
0
    }
949
0
    if (alg != PRF_FIPS_SHA1_160)
950
0
    {
951
      /* do partial append mode and check if key gets set correctly */
952
0
      if (!prf->get_bytes(prf, seed, NULL))
953
0
      {
954
0
        goto failure;
955
0
      }
956
0
      if (!prf->set_key(prf, key))
957
0
      {
958
0
        goto failure;
959
0
      }
960
0
    }
961
    /* allocated bytes */
962
0
    if (!prf->allocate_bytes(prf, seed, &out))
963
0
    {
964
0
      goto failure;
965
0
    }
966
0
    if (out.len != prf->get_block_size(prf))
967
0
    {
968
0
      goto failure;
969
0
    }
970
0
    if (!memeq(vector->out, out.ptr, out.len))
971
0
    {
972
0
      goto failure;
973
0
    }
974
    /* bytes to existing buffer */
975
0
    memset(out.ptr, 0, out.len);
976
0
    if (vector->stateful)
977
0
    {
978
0
      if (!prf->set_key(prf, key))
979
0
      {
980
0
        goto failure;
981
0
      }
982
0
    }
983
0
    if (!prf->get_bytes(prf, seed, out.ptr))
984
0
    {
985
0
      goto failure;
986
0
    }
987
0
    if (!memeq(vector->out, out.ptr, out.len))
988
0
    {
989
0
      goto failure;
990
0
    }
991
    /* bytes to existing buffer, using append mode */
992
0
    if (alg != PRF_FIPS_SHA1_160 && seed.len > 2)
993
0
    {
994
0
      memset(out.ptr, 0, out.len);
995
0
      if (vector->stateful)
996
0
      {
997
0
        if (!prf->set_key(prf, key))
998
0
        {
999
0
          goto failure;
1000
0
        }
1001
0
      }
1002
0
      if (!prf->allocate_bytes(prf, chunk_create(seed.ptr, 1), NULL))
1003
0
      {
1004
0
        goto failure;
1005
0
      }
1006
0
      if (!prf->get_bytes(prf, chunk_create(seed.ptr + 1, 1), NULL))
1007
0
      {
1008
0
        goto failure;
1009
0
      }
1010
0
      if (!prf->get_bytes(prf, chunk_skip(seed, 2), out.ptr))
1011
0
      {
1012
0
        goto failure;
1013
0
      }
1014
0
      if (!memeq(vector->out, out.ptr, out.len))
1015
0
      {
1016
0
        goto failure;
1017
0
      }
1018
0
    }
1019
1020
0
    failed = FALSE;
1021
0
failure:
1022
0
    prf->destroy(prf);
1023
0
    chunk_free(&out);
1024
0
    if (failed)
1025
0
    {
1026
0
      DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
1027
0
         pseudo_random_function_names, alg, plugin_name, get_name(vector));
1028
0
      break;
1029
0
    }
1030
0
  }
1031
0
  enumerator->destroy(enumerator);
1032
0
  if (!tested)
1033
0
  {
1034
0
    DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
1035
0
       this->required ? "disabled" : "enabled ",
1036
0
       pseudo_random_function_names, alg, plugin_name);
1037
0
    return !this->required;
1038
0
  }
1039
0
  if (!failed)
1040
0
  {
1041
0
    if (speed)
1042
0
    {
1043
0
      *speed = bench_prf(this, alg, create);
1044
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
1045
0
         pseudo_random_function_names, alg, plugin_name, tested, *speed);
1046
0
    }
1047
0
    else
1048
0
    {
1049
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
1050
0
         pseudo_random_function_names, alg, plugin_name, tested);
1051
0
    }
1052
0
  }
1053
0
  return !failed;
1054
0
}
1055
1056
/**
1057
 * Benchmark an XOF
1058
 */
1059
static u_int bench_xof(private_crypto_tester_t *this,
1060
             ext_out_function_t alg, xof_constructor_t create)
1061
0
{
1062
0
  xof_t *xof;
1063
1064
0
  xof = create(alg);
1065
0
  if (xof)
1066
0
  {
1067
0
    char seed[xof->get_seed_size(xof)];
1068
0
    char bytes[xof->get_block_size(xof)];
1069
0
    struct timespec start;
1070
0
    u_int runs;
1071
1072
0
    memset(seed, 0x56, xof->get_seed_size(xof));
1073
0
    if (!xof->set_seed(xof, chunk_create(seed, xof->get_seed_size(xof))))
1074
0
    {
1075
0
      xof->destroy(xof);
1076
0
      return 0;
1077
0
    }
1078
1079
0
    runs = 0;
1080
0
    start_timing(&start);
1081
0
    while (end_timing(&start) < this->bench_time)
1082
0
    {
1083
0
      if (xof->get_bytes(xof, xof->get_block_size(xof), bytes))
1084
0
      {
1085
0
        runs++;
1086
0
      }
1087
0
    }
1088
0
    xof->destroy(xof);
1089
1090
0
    return runs;
1091
0
  }
1092
0
  return 0;
1093
0
}
1094
1095
METHOD(crypto_tester_t, test_xof, bool,
1096
  private_crypto_tester_t *this, ext_out_function_t alg,
1097
  xof_constructor_t create, u_int *speed, const char *plugin_name)
1098
0
{
1099
0
  enumerator_t *enumerator;
1100
0
  xof_test_vector_t *vector;
1101
0
  bool failed = FALSE;
1102
0
  u_int tested = 0;
1103
1104
0
  enumerator = this->xof->create_enumerator(this->xof);
1105
0
  while (enumerator->enumerate(enumerator, &vector))
1106
0
  {
1107
0
    xof_t *xof;
1108
0
    chunk_t seed, out = chunk_empty;
1109
1110
0
    if (vector->alg != alg)
1111
0
    {
1112
0
      continue;
1113
0
    }
1114
1115
0
    tested++;
1116
0
    failed = TRUE;
1117
0
    xof = create(alg);
1118
0
    if (!xof)
1119
0
    {
1120
0
      DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
1121
0
         ext_out_function_names, alg, plugin_name);
1122
0
      break;
1123
0
    }
1124
1125
0
    seed = chunk_create(vector->seed, vector->len);
1126
0
    if (!xof->set_seed(xof, seed))
1127
0
    {
1128
0
      goto failure;
1129
0
    }
1130
    /* allocated bytes */
1131
0
    if (!xof->allocate_bytes(xof, vector->out_len, &out))
1132
0
    {
1133
0
      goto failure;
1134
0
    }
1135
0
    if (out.len != vector->out_len)
1136
0
    {
1137
0
      goto failure;
1138
0
    }
1139
0
    if (!memeq(vector->out, out.ptr, out.len))
1140
0
    {
1141
0
      goto failure;
1142
0
    }
1143
    /* bytes to existing buffer */
1144
0
    memset(out.ptr, 0, out.len);
1145
0
    if (!xof->set_seed(xof, seed))
1146
0
    {
1147
0
      goto failure;
1148
0
    }
1149
0
    if (!xof->get_bytes(xof, vector->out_len, out.ptr))
1150
0
    {
1151
0
      goto failure;
1152
0
    }
1153
0
    if (!memeq(vector->out, out.ptr, vector->out_len))
1154
0
    {
1155
0
      goto failure;
1156
0
    }
1157
    /* bytes to existing buffer, using append mode */
1158
    /* TODO */
1159
1160
0
    failed = FALSE;
1161
0
failure:
1162
0
    xof->destroy(xof);
1163
0
    chunk_free(&out);
1164
0
    if (failed)
1165
0
    {
1166
0
      DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
1167
0
         ext_out_function_names, alg, plugin_name, get_name(vector));
1168
0
      break;
1169
0
    }
1170
0
  }
1171
0
  enumerator->destroy(enumerator);
1172
0
  if (!tested)
1173
0
  {
1174
0
    DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
1175
0
       this->required ? "disabled" : "enabled ",
1176
0
       ext_out_function_names, alg, plugin_name);
1177
0
    return !this->required;
1178
0
  }
1179
0
  if (!failed)
1180
0
  {
1181
0
    if (speed)
1182
0
    {
1183
0
      *speed = bench_xof(this, alg, create);
1184
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
1185
0
         ext_out_function_names, alg, plugin_name, tested, *speed);
1186
0
    }
1187
0
    else
1188
0
    {
1189
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
1190
0
         ext_out_function_names, alg, plugin_name, tested);
1191
0
    }
1192
0
  }
1193
0
  return !failed;
1194
0
}
1195
1196
1197
1198
/**
1199
 * Create a KDF using the given arguments
1200
 */
1201
static kdf_t *create_kdf_args(kdf_constructor_t create,
1202
                key_derivation_function_t alg, ...)
1203
0
{
1204
0
  va_list args;
1205
0
  kdf_t *kdf;
1206
1207
0
  va_start(args, alg);
1208
0
  kdf = create(alg, args);
1209
0
  va_end(args);
1210
0
  return kdf;
1211
0
}
1212
1213
/**
1214
 * Create a KDF using arguments from the given test vector
1215
 */
1216
static kdf_t *create_kdf_vector(kdf_constructor_t create,
1217
                key_derivation_function_t alg,
1218
                kdf_test_vector_t *vector)
1219
0
{
1220
0
  switch (alg)
1221
0
  {
1222
0
    case KDF_PRF:
1223
0
    case KDF_PRF_PLUS:
1224
0
      return create_kdf_args(create, alg, vector->arg.prf);
1225
0
    case KDF_UNDEFINED:
1226
0
      break;
1227
0
  }
1228
0
  return NULL;
1229
0
}
1230
1231
/**
1232
 * Check if the given test vector applies to the passed arguments
1233
 */
1234
static bool kdf_vector_applies(key_derivation_function_t alg,
1235
                 kdf_test_args_t *args, kdf_test_vector_t *vector)
1236
0
{
1237
0
  bool applies = FALSE;
1238
1239
0
  switch (alg)
1240
0
  {
1241
0
    case KDF_PRF:
1242
0
    case KDF_PRF_PLUS:
1243
0
    {
1244
0
      pseudo_random_function_t prf;
1245
0
      VA_ARGS_VGET(args->args, prf);
1246
0
      applies = (prf == vector->arg.prf);
1247
0
      break;
1248
0
    }
1249
0
    case KDF_UNDEFINED:
1250
0
      break;
1251
0
  }
1252
0
  return applies;
1253
0
}
1254
1255
METHOD(crypto_tester_t, test_kdf, bool,
1256
  private_crypto_tester_t *this, key_derivation_function_t alg,
1257
  kdf_constructor_t create, kdf_test_args_t *args, u_int *speed,
1258
  const char *plugin_name)
1259
0
{
1260
0
  enumerator_t *enumerator;
1261
0
  kdf_test_vector_t *vector;
1262
0
  va_list copy;
1263
0
  bool failed = FALSE;
1264
0
  u_int tested = 0, construction_failed = 0;
1265
1266
0
  enumerator = this->kdf->create_enumerator(this->kdf);
1267
0
  while (enumerator->enumerate(enumerator, &vector))
1268
0
  {
1269
0
    kdf_t *kdf;
1270
0
    chunk_t out = chunk_empty;
1271
1272
0
    if (vector->alg != alg ||
1273
0
      (args && !kdf_vector_applies(alg, args, vector)))
1274
0
    {
1275
0
      continue;
1276
0
    }
1277
1278
0
    tested++;
1279
0
    failed = TRUE;
1280
0
    if (args)
1281
0
    {
1282
0
      va_copy(copy, args->args);
1283
0
      kdf = create(alg, copy);
1284
0
      va_end(copy);
1285
0
    }
1286
0
    else
1287
0
    {
1288
0
      kdf = create_kdf_vector(create, alg, vector);
1289
0
    }
1290
0
    if (!kdf)
1291
0
    {
1292
0
      if (args)
1293
0
      {
1294
0
        DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
1295
0
           key_derivation_function_names, alg, plugin_name);
1296
0
        break;
1297
0
      }
1298
      /* while there could be a problem, the constructor might just not
1299
       * be able to create an instance for this test vector, we check
1300
       * for that at the end */
1301
0
      construction_failed++;
1302
0
      failed = FALSE;
1303
0
      continue;
1304
0
    }
1305
1306
0
    if (vector->key.len &&
1307
0
      !kdf->set_param(kdf, KDF_PARAM_KEY, vector->key))
1308
0
    {
1309
0
      goto failure;
1310
0
    }
1311
0
    if (vector->salt.len &&
1312
0
      !kdf->set_param(kdf, KDF_PARAM_SALT, vector->salt))
1313
0
    {
1314
0
      goto failure;
1315
0
    }
1316
0
    if (kdf_has_fixed_output_length(alg))
1317
0
    {
1318
0
      if (kdf->get_length(kdf) != vector->out.len)
1319
0
      {
1320
0
        goto failure;
1321
0
      }
1322
0
    }
1323
0
    else if (kdf->get_length(kdf) != SIZE_MAX)
1324
0
    {
1325
0
      goto failure;
1326
0
    }
1327
    /* allocated bytes */
1328
0
    if (!kdf->allocate_bytes(kdf, vector->out.len, &out))
1329
0
    {
1330
0
      goto failure;
1331
0
    }
1332
0
    if (!chunk_equals(out, vector->out))
1333
0
    {
1334
0
      goto failure;
1335
0
    }
1336
    /* allocate without knowing the length */
1337
0
    if (kdf_has_fixed_output_length(alg))
1338
0
    {
1339
0
      chunk_free(&out);
1340
0
      if (!kdf->allocate_bytes(kdf, 0, &out))
1341
0
      {
1342
0
        goto failure;
1343
0
      }
1344
0
      if (!chunk_equals(out, vector->out))
1345
0
      {
1346
0
        goto failure;
1347
0
      }
1348
0
    }
1349
    /* bytes to existing buffer */
1350
0
    memset(out.ptr, 0, out.len);
1351
0
    if (!kdf->get_bytes(kdf, out.len, out.ptr))
1352
0
    {
1353
0
      goto failure;
1354
0
    }
1355
0
    if (!chunk_equals(out, vector->out))
1356
0
    {
1357
0
      goto failure;
1358
0
    }
1359
1360
0
    failed = FALSE;
1361
0
failure:
1362
0
    kdf->destroy(kdf);
1363
0
    chunk_free(&out);
1364
0
    if (failed)
1365
0
    {
1366
0
      DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
1367
0
         key_derivation_function_names, alg, plugin_name,
1368
0
         get_name(vector));
1369
0
      break;
1370
0
    }
1371
0
  }
1372
0
  enumerator->destroy(enumerator);
1373
0
  if (!tested)
1374
0
  {
1375
0
    DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
1376
0
       this->required ? "disabled" : "enabled ",
1377
0
       key_derivation_function_names, alg, plugin_name);
1378
0
    return !this->required;
1379
0
  }
1380
0
  tested -= construction_failed;
1381
0
  if (!tested)
1382
0
  {
1383
0
    DBG1(DBG_LIB, "%s %N[%s]: unable to apply any available test vectors",
1384
0
       this->required ? "disabled" : "enabled ",
1385
0
       key_derivation_function_names, alg, plugin_name);
1386
0
    return !this->required;
1387
0
  }
1388
0
  if (!failed)
1389
0
  {
1390
0
    if (speed)
1391
0
    {
1392
0
      DBG2(DBG_LIB, "benchmarking for %N is currently not supported",
1393
0
         key_derivation_function_names, alg);
1394
0
    }
1395
0
    DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
1396
0
       key_derivation_function_names, alg, plugin_name, tested);
1397
0
  }
1398
0
  return !failed;
1399
0
}
1400
1401
/**
1402
 * Benchmark a DRBG
1403
 */
1404
static u_int bench_drbg(private_crypto_tester_t *this,
1405
            drbg_type_t type, drbg_constructor_t create)
1406
0
{
1407
0
  drbg_t *drbg;
1408
0
  rng_t *entropy;
1409
0
  uint32_t strength = 128;
1410
0
  chunk_t seed = chunk_alloca(48);
1411
1412
0
  memset(seed.ptr, 0x81, seed.len);
1413
0
  entropy = rng_tester_create(seed);
1414
1415
0
  drbg = create(type, strength, entropy, chunk_empty);
1416
0
  if (drbg)
1417
0
  {
1418
0
    struct timespec start;
1419
0
    u_int runs = 0;
1420
0
    size_t out_len = 128;
1421
0
    char out_buf[out_len];
1422
1423
0
    start_timing(&start);
1424
0
    while (end_timing(&start) < this->bench_time)
1425
0
    {
1426
0
      if (drbg->generate(drbg, out_len, out_buf))
1427
0
      {
1428
0
        runs++;
1429
0
      }
1430
0
    }
1431
0
    drbg->destroy(drbg);
1432
1433
0
    return runs;
1434
0
  }
1435
0
  return 0;
1436
0
}
1437
1438
METHOD(crypto_tester_t, test_drbg, bool,
1439
  private_crypto_tester_t *this, drbg_type_t type,
1440
  drbg_constructor_t create, u_int *speed, const char *plugin_name)
1441
0
{
1442
0
  enumerator_t *enumerator;
1443
0
  drbg_test_vector_t *vector;
1444
0
  bool failed = FALSE;
1445
0
  u_int tested = 0;
1446
1447
0
  enumerator = this->drbg->create_enumerator(this->drbg);
1448
0
  while (enumerator->enumerate(enumerator, &vector))
1449
0
  {
1450
0
    drbg_t *drbg;
1451
0
    rng_t *entropy;
1452
0
    chunk_t out = chunk_empty;
1453
1454
0
    if (vector->type != type)
1455
0
    {
1456
0
      continue;
1457
0
    }
1458
0
    tested++;
1459
0
    failed = TRUE;
1460
1461
0
    entropy = rng_tester_create(vector->entropy);
1462
0
    out = chunk_alloc(vector->out.len);
1463
1464
0
    drbg = create(type, vector->strength, entropy,
1465
0
            vector->personalization_str);
1466
0
    if (!drbg)
1467
0
    {
1468
0
      DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
1469
0
         drbg_type_names, type, plugin_name);
1470
0
      entropy->destroy(entropy);
1471
0
      chunk_free(&out);
1472
0
      break;
1473
0
    }
1474
0
    if (!drbg->reseed(drbg))
1475
0
    {
1476
0
      goto failure;
1477
0
    }
1478
0
    if (!drbg->generate(drbg, out.len, out.ptr))
1479
0
    {
1480
0
      goto failure;
1481
0
    }
1482
0
    if (!drbg->generate(drbg, out.len, out.ptr))
1483
0
    {
1484
0
      goto failure;
1485
0
    }
1486
0
    if (!chunk_equals(out, vector->out))
1487
0
    {
1488
0
      goto failure;
1489
0
    }
1490
0
    failed = FALSE;
1491
1492
0
failure:
1493
0
    drbg->destroy(drbg);
1494
0
    chunk_free(&out);
1495
0
    if (failed)
1496
0
    {
1497
0
      DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
1498
0
         drbg_type_names, type, plugin_name, get_name(vector));
1499
0
      break;
1500
0
    }
1501
0
  }
1502
0
  enumerator->destroy(enumerator);
1503
0
  if (!tested)
1504
0
  {
1505
0
    DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
1506
0
       this->required ? "disabled" : "enabled ",
1507
0
       drbg_type_names, type, plugin_name);
1508
0
    return !this->required;
1509
0
  }
1510
0
  if (!failed)
1511
0
  {
1512
0
    if (speed)
1513
0
    {
1514
0
      *speed = bench_drbg(this, type, create);
1515
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
1516
0
         drbg_type_names, type, plugin_name, tested, *speed);
1517
0
    }
1518
0
    else
1519
0
    {
1520
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
1521
0
         drbg_type_names, type, plugin_name, tested);
1522
0
    }
1523
0
  }
1524
0
  return !failed;
1525
0
}
1526
1527
/**
1528
 * Benchmark a RNG
1529
 */
1530
static u_int bench_rng(private_crypto_tester_t *this,
1531
             rng_quality_t quality, rng_constructor_t create)
1532
0
{
1533
0
  rng_t *rng;
1534
1535
0
  rng = create(quality);
1536
0
  if (rng)
1537
0
  {
1538
0
    struct timespec start;
1539
0
    chunk_t buf;
1540
0
    u_int runs;
1541
1542
0
    runs = 0;
1543
0
    buf = chunk_alloc(this->bench_size);
1544
0
    start_timing(&start);
1545
0
    while (end_timing(&start) < this->bench_time)
1546
0
    {
1547
0
      if (!rng->get_bytes(rng, buf.len, buf.ptr))
1548
0
      {
1549
0
        runs = 0;
1550
0
        break;
1551
0
      }
1552
0
      runs++;
1553
0
    }
1554
0
    free(buf.ptr);
1555
0
    rng->destroy(rng);
1556
1557
0
    return runs;
1558
0
  }
1559
0
  return 0;
1560
0
}
1561
1562
METHOD(crypto_tester_t, test_rng, bool,
1563
  private_crypto_tester_t *this, rng_quality_t quality,
1564
  rng_constructor_t create, u_int *speed, const char *plugin_name)
1565
0
{
1566
0
  enumerator_t *enumerator;
1567
0
  rng_test_vector_t *vector;
1568
0
  bool failed = FALSE;
1569
0
  u_int tested = 0;
1570
1571
0
  if (!this->rng_true && quality == RNG_TRUE)
1572
0
  {
1573
0
    DBG1(DBG_LIB, "enabled  %N[%s]: skipping test (disabled by config)",
1574
0
       rng_quality_names, quality, plugin_name);
1575
0
    return TRUE;
1576
0
  }
1577
1578
0
  enumerator = this->rng->create_enumerator(this->rng);
1579
0
  while (enumerator->enumerate(enumerator, &vector))
1580
0
  {
1581
0
    chunk_t data = chunk_empty;
1582
0
    rng_t *rng;
1583
1584
0
    if (vector->quality != quality)
1585
0
    {
1586
0
      continue;
1587
0
    }
1588
1589
0
    tested++;
1590
0
    failed = TRUE;
1591
0
    rng = create(quality);
1592
0
    if (!rng)
1593
0
    {
1594
0
      DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
1595
0
         rng_quality_names, quality, plugin_name);
1596
0
      break;
1597
0
    }
1598
1599
    /* allocated bytes */
1600
0
    if (!rng->allocate_bytes(rng, vector->len, &data) ||
1601
0
      data.len != vector->len ||
1602
0
      !vector->test(vector->user, data))
1603
0
    {
1604
0
      goto failure;
1605
0
    }
1606
    /* write bytes into existing buffer */
1607
0
    memset(data.ptr, 0, data.len);
1608
0
    if (!rng->get_bytes(rng, vector->len, data.ptr))
1609
0
    {
1610
0
      goto failure;
1611
0
    }
1612
0
    if (!vector->test(vector->user, data))
1613
0
    {
1614
0
      goto failure;
1615
0
    }
1616
1617
0
    failed = FALSE;
1618
0
failure:
1619
0
    rng->destroy(rng);
1620
0
    chunk_free(&data);
1621
0
    if (failed)
1622
0
    {
1623
0
      DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
1624
0
         rng_quality_names, quality, plugin_name, get_name(vector));
1625
0
      break;
1626
0
    }
1627
0
  }
1628
0
  enumerator->destroy(enumerator);
1629
0
  if (!tested)
1630
0
  {
1631
0
    DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
1632
0
       this->required ? ", disabled" : "enabled ",
1633
0
       rng_quality_names, quality, plugin_name);
1634
0
    return !this->required;
1635
0
  }
1636
0
  if (!failed)
1637
0
  {
1638
0
    if (speed)
1639
0
    {
1640
0
      *speed = bench_rng(this, quality, create);
1641
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
1642
0
         rng_quality_names, quality, plugin_name, tested, *speed);
1643
0
    }
1644
0
    else
1645
0
    {
1646
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
1647
0
         rng_quality_names, quality, plugin_name, tested);
1648
0
    }
1649
0
  }
1650
0
  return !failed;
1651
0
}
1652
1653
/**
1654
 * Benchmark a key exchange backend
1655
 */
1656
static u_int bench_ke(private_crypto_tester_t *this,
1657
            key_exchange_method_t method, ke_constructor_t create)
1658
0
{
1659
0
  chunk_t pub = chunk_empty, shared = chunk_empty;
1660
0
  key_exchange_t *ke;
1661
0
  struct timespec start;
1662
0
  u_int runs;
1663
1664
0
  runs = 0;
1665
0
  start_timing(&start);
1666
0
  while (end_timing(&start) < this->bench_time)
1667
0
  {
1668
0
    ke = create(method);
1669
0
    if (!ke)
1670
0
    {
1671
0
      return 0;
1672
0
    }
1673
0
    if (ke->get_public_key(ke, &pub) &&
1674
0
      ke->set_public_key(ke, pub) &&
1675
0
      ke->get_shared_secret(ke, &shared))
1676
0
    {
1677
0
      runs++;
1678
0
    }
1679
0
    chunk_free(&pub);
1680
0
    chunk_free(&shared);
1681
0
    ke->destroy(ke);
1682
0
  }
1683
0
  return runs;
1684
0
}
1685
1686
METHOD(crypto_tester_t, test_ke, bool,
1687
  private_crypto_tester_t *this, key_exchange_method_t method,
1688
  ke_constructor_t create, u_int *speed, const char *plugin_name)
1689
0
{
1690
0
  enumerator_t *enumerator;
1691
0
  ke_test_vector_t *v;
1692
0
  bool failed = FALSE;
1693
0
  u_int tested = 0;
1694
1695
0
  enumerator = this->ke->create_enumerator(this->ke);
1696
0
  while (enumerator->enumerate(enumerator, &v))
1697
0
  {
1698
0
    key_exchange_t *a, *b;
1699
0
    chunk_t apub, bpub, asec, bsec;
1700
1701
0
    if (v->method != method)
1702
0
    {
1703
0
      continue;
1704
0
    }
1705
1706
0
    a = create(method);
1707
0
    b = create(method);
1708
0
    if (!a || !b)
1709
0
    {
1710
0
      DESTROY_IF(a);
1711
0
      DESTROY_IF(b);
1712
0
      failed = TRUE;
1713
0
      tested++;
1714
0
      DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
1715
0
         key_exchange_method_names, method, plugin_name);
1716
0
      break;
1717
0
    }
1718
1719
0
    if (!a->set_private_key || !b->set_private_key)
1720
0
    { /* does not support testing */
1721
0
      a->destroy(a);
1722
0
      b->destroy(b);
1723
0
      continue;
1724
0
    }
1725
0
    failed = TRUE;
1726
0
    tested++;
1727
1728
0
    apub = bpub = asec = bsec = chunk_empty;
1729
1730
0
    if (!a->set_private_key(a, chunk_create(v->priv_a, v->priv_len)) ||
1731
0
      !b->set_private_key(b, chunk_create(v->priv_b, v->priv_len)))
1732
0
    {
1733
0
      goto failure;
1734
0
    }
1735
0
    if (!a->get_public_key(a, &apub) ||
1736
0
      !chunk_equals(apub, chunk_create(v->pub_a, v->pub_len)))
1737
0
    {
1738
0
      goto failure;
1739
0
    }
1740
0
    if (!b->get_public_key(b, &bpub) ||
1741
0
      !chunk_equals(bpub, chunk_create(v->pub_b, v->pub_len)))
1742
0
    {
1743
0
      goto failure;
1744
0
    }
1745
0
    if (!a->set_public_key(a, bpub) ||
1746
0
      !b->set_public_key(b, apub))
1747
0
    {
1748
0
      goto failure;
1749
0
    }
1750
0
    if (!a->get_shared_secret(a, &asec) ||
1751
0
      !chunk_equals(asec, chunk_create(v->shared, v->shared_len)))
1752
0
    {
1753
0
      goto failure;
1754
0
    }
1755
0
    if (!b->get_shared_secret(b, &bsec) ||
1756
0
      !chunk_equals(bsec, chunk_create(v->shared, v->shared_len)))
1757
0
    {
1758
0
      goto failure;
1759
0
    }
1760
1761
0
    failed = FALSE;
1762
0
failure:
1763
0
    a->destroy(a);
1764
0
    b->destroy(b);
1765
0
    chunk_free(&apub);
1766
0
    chunk_free(&bpub);
1767
0
    chunk_free(&asec);
1768
0
    chunk_free(&bsec);
1769
0
    if (failed)
1770
0
    {
1771
0
      DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
1772
0
         key_exchange_method_names, method, plugin_name, get_name(v));
1773
0
      break;
1774
0
    }
1775
0
  }
1776
0
  enumerator->destroy(enumerator);
1777
0
  if (!tested)
1778
0
  {
1779
0
    DBG1(DBG_LIB, "%s %N[%s]: no test vectors found / untestable",
1780
0
       this->required ? "disabled" : "enabled ",
1781
0
       key_exchange_method_names, method, plugin_name);
1782
0
    return !this->required;
1783
0
  }
1784
0
  if (!failed)
1785
0
  {
1786
0
    if (speed)
1787
0
    {
1788
0
      *speed = bench_ke(this, method, create);
1789
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
1790
0
         key_exchange_method_names, method, plugin_name, tested, *speed);
1791
0
    }
1792
0
    else
1793
0
    {
1794
0
      DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
1795
0
         key_exchange_method_names, method, plugin_name, tested);
1796
0
    }
1797
0
  }
1798
0
  return !failed;
1799
0
}
1800
1801
METHOD(crypto_tester_t, add_crypter_vector, void,
1802
  private_crypto_tester_t *this, crypter_test_vector_t *vector)
1803
0
{
1804
0
  this->crypter->insert_last(this->crypter, vector);
1805
0
}
1806
1807
METHOD(crypto_tester_t, add_aead_vector, void,
1808
  private_crypto_tester_t *this, aead_test_vector_t *vector)
1809
0
{
1810
0
  this->aead->insert_last(this->aead, vector);
1811
0
}
1812
1813
METHOD(crypto_tester_t, add_signer_vector, void,
1814
  private_crypto_tester_t *this, signer_test_vector_t *vector)
1815
0
{
1816
0
  this->signer->insert_last(this->signer, vector);
1817
0
}
1818
1819
METHOD(crypto_tester_t, add_hasher_vector, void,
1820
  private_crypto_tester_t *this, hasher_test_vector_t *vector)
1821
0
{
1822
0
  this->hasher->insert_last(this->hasher, vector);
1823
0
}
1824
1825
METHOD(crypto_tester_t, add_prf_vector, void,
1826
  private_crypto_tester_t *this, prf_test_vector_t *vector)
1827
0
{
1828
0
  this->prf->insert_last(this->prf, vector);
1829
0
}
1830
1831
METHOD(crypto_tester_t, add_xof_vector, void,
1832
  private_crypto_tester_t *this, xof_test_vector_t *vector)
1833
0
{
1834
0
  this->xof->insert_last(this->xof, vector);
1835
0
}
1836
1837
METHOD(crypto_tester_t, add_kdf_vector, void,
1838
  private_crypto_tester_t *this, kdf_test_vector_t *vector)
1839
0
{
1840
0
  this->kdf->insert_last(this->kdf, vector);
1841
0
}
1842
1843
METHOD(crypto_tester_t, add_drbg_vector, void,
1844
  private_crypto_tester_t *this, drbg_test_vector_t *vector)
1845
0
{
1846
0
  this->drbg->insert_last(this->drbg, vector);
1847
0
}
1848
1849
METHOD(crypto_tester_t, add_rng_vector, void,
1850
  private_crypto_tester_t *this, rng_test_vector_t *vector)
1851
0
{
1852
0
  this->rng->insert_last(this->rng, vector);
1853
0
}
1854
1855
METHOD(crypto_tester_t, add_ke_vector, void,
1856
  private_crypto_tester_t *this, ke_test_vector_t *vector)
1857
0
{
1858
0
  this->ke->insert_last(this->ke, vector);
1859
0
}
1860
1861
METHOD(crypto_tester_t, destroy, void,
1862
  private_crypto_tester_t *this)
1863
3.92k
{
1864
3.92k
  this->crypter->destroy(this->crypter);
1865
3.92k
  this->aead->destroy(this->aead);
1866
3.92k
  this->signer->destroy(this->signer);
1867
3.92k
  this->hasher->destroy(this->hasher);
1868
3.92k
  this->prf->destroy(this->prf);
1869
3.92k
  this->xof->destroy(this->xof);
1870
3.92k
  this->kdf->destroy(this->kdf);
1871
3.92k
  this->drbg->destroy(this->drbg);
1872
3.92k
  this->rng->destroy(this->rng);
1873
3.92k
  this->ke->destroy(this->ke);
1874
3.92k
  free(this);
1875
3.92k
}
1876
1877
/**
1878
 * See header
1879
 */
1880
crypto_tester_t *crypto_tester_create()
1881
3.92k
{
1882
3.92k
  private_crypto_tester_t *this;
1883
1884
3.92k
  INIT(this,
1885
3.92k
    .public = {
1886
3.92k
      .test_crypter = _test_crypter,
1887
3.92k
      .test_aead = _test_aead,
1888
3.92k
      .test_signer = _test_signer,
1889
3.92k
      .test_hasher = _test_hasher,
1890
3.92k
      .test_prf = _test_prf,
1891
3.92k
      .test_xof = _test_xof,
1892
3.92k
      .test_kdf = _test_kdf,
1893
3.92k
      .test_drbg = _test_drbg,
1894
3.92k
      .test_rng = _test_rng,
1895
3.92k
      .test_ke = _test_ke,
1896
3.92k
      .add_crypter_vector = _add_crypter_vector,
1897
3.92k
      .add_aead_vector = _add_aead_vector,
1898
3.92k
      .add_signer_vector = _add_signer_vector,
1899
3.92k
      .add_hasher_vector = _add_hasher_vector,
1900
3.92k
      .add_prf_vector = _add_prf_vector,
1901
3.92k
      .add_xof_vector = _add_xof_vector,
1902
3.92k
      .add_kdf_vector = _add_kdf_vector,
1903
3.92k
      .add_drbg_vector = _add_drbg_vector,
1904
3.92k
      .add_rng_vector = _add_rng_vector,
1905
3.92k
      .add_ke_vector = _add_ke_vector,
1906
3.92k
      .destroy = _destroy,
1907
3.92k
    },
1908
3.92k
    .crypter = linked_list_create(),
1909
3.92k
    .aead = linked_list_create(),
1910
3.92k
    .signer = linked_list_create(),
1911
3.92k
    .hasher = linked_list_create(),
1912
3.92k
    .prf = linked_list_create(),
1913
3.92k
    .xof = linked_list_create(),
1914
3.92k
    .kdf = linked_list_create(),
1915
3.92k
    .drbg = linked_list_create(),
1916
3.92k
    .rng = linked_list_create(),
1917
3.92k
    .ke = linked_list_create(),
1918
1919
3.92k
    .required = lib->settings->get_bool(lib->settings,
1920
3.92k
                "%s.crypto_test.required", FALSE, lib->ns),
1921
3.92k
    .rng_true = lib->settings->get_bool(lib->settings,
1922
3.92k
                "%s.crypto_test.rng_true", FALSE, lib->ns),
1923
3.92k
    .bench_time = lib->settings->get_int(lib->settings,
1924
3.92k
                "%s.crypto_test.bench_time", 50, lib->ns),
1925
3.92k
    .bench_size = lib->settings->get_int(lib->settings,
1926
3.92k
                "%s.crypto_test.bench_size", 1024, lib->ns),
1927
3.92k
  );
1928
1929
  /* enforce a block size of 16, should be fine for all algorithms */
1930
3.92k
  this->bench_size = this->bench_size / 16 * 16;
1931
1932
3.92k
  return &this->public;
1933
3.92k
}