2 * Copyright (C) 2009-2010 Martin Willi
3 * Copyright (C) 2016-2019 Andreas Steffen
5 * Copyright (C) secunet Security Networks AG
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>.
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
24 #include "crypto_tester.h"
26 #include <utils/debug.h>
27 #include <collections/linked_list.h>
28 #include <crypto/rngs/rng_tester.h>
30 typedef struct private_crypto_tester_t private_crypto_tester_t
;
33 * Private data of an crypto_tester_t object.
35 struct private_crypto_tester_t
{
38 * Public crypto_tester_t interface.
40 crypto_tester_t
public;
43 * List of crypter test vectors
45 linked_list_t
*crypter
;
48 * List of aead test vectors
53 * List of signer test vectors
55 linked_list_t
*signer
;
58 * List of hasher test vectors
60 linked_list_t
*hasher
;
63 * List of PRF test vectors
68 * List of XOF test vectors
73 * List of KDF test vectors
78 * List of DRBG test vectors
83 * List of RNG test vectors
88 * List of key exchange method test vectors
93 * Is a test vector required to pass a test?
98 * should we run RNG_TRUE tests? Enough entropy?
103 * time we test each algorithm
108 * size of buffer we use for benchmarking
115 * Get the name of a test vector, if available
117 static const char* get_name(void *sym
)
122 if (dladdr(sym
, &dli
))
124 return dli
.dli_sname
;
131 #if defined(CLOCK_THREAD_CPUTIME_ID) && defined(HAVE_CLOCK_GETTIME)
134 * Start a benchmark timer
136 static void start_timing(struct timespec
*start
)
138 clock_gettime(CLOCK_THREAD_CPUTIME_ID
, start
);
142 * End a benchmark timer, return ms
144 static u_int
end_timing(struct timespec
*start
)
148 clock_gettime(CLOCK_THREAD_CPUTIME_ID
, &end
);
149 return (end
.tv_nsec
- start
->tv_nsec
) / 1000000 +
150 (end
.tv_sec
- start
->tv_sec
) * 1000;
153 #else /* CLOCK_THREAD_CPUTIME_ID */
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)
159 #endif /* CLOCK_THREAD_CPUTIME_ID */
162 * Benchmark a crypter
164 static u_int
bench_crypter(private_crypto_tester_t
*this,
165 encryption_algorithm_t alg
, crypter_constructor_t create
, size_t key_size
)
169 crypter
= create(alg
, key_size
);
172 char iv
[crypter
->get_iv_size(crypter
)];
173 char key
[crypter
->get_key_size(crypter
)];
175 struct timespec start
;
178 memset(iv
, 0x56, sizeof(iv
));
179 memset(key
, 0x12, sizeof(key
));
180 if (!crypter
->set_key(crypter
, chunk_from_thing(key
)))
185 buf
= chunk_alloc(this->bench_size
);
186 memset(buf
.ptr
, 0x34, buf
.len
);
189 start_timing(&start
);
190 while (end_timing(&start
) < this->bench_time
)
192 if (crypter
->encrypt(crypter
, buf
, chunk_from_thing(iv
), NULL
))
196 if (crypter
->decrypt(crypter
, buf
, chunk_from_thing(iv
), NULL
))
202 crypter
->destroy(crypter
);
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
)
213 enumerator_t
*enumerator
;
214 crypter_test_vector_t
*vector
;
218 enumerator
= this->crypter
->create_enumerator(this->crypter
);
219 while (enumerator
->enumerate(enumerator
, &vector
))
222 chunk_t key
, iv
, plain
= chunk_empty
, cipher
= chunk_empty
;
224 if (vector
->alg
!= alg
)
228 if (key_size
&& key_size
!= vector
->key_size
)
229 { /* test only vectors with a specific key size, if key size given */
233 crypter
= create(alg
, vector
->key_size
);
235 { /* key size not supported */
241 key
= chunk_create(vector
->key
, crypter
->get_key_size(crypter
));
242 if (!crypter
->set_key(crypter
, key
))
246 iv
= chunk_create(vector
->iv
, crypter
->get_iv_size(crypter
));
248 /* allocated encryption */
249 plain
= chunk_create(vector
->plain
, vector
->len
);
250 if (!crypter
->encrypt(crypter
, plain
, iv
, &cipher
))
254 if (!memeq(vector
->cipher
, cipher
.ptr
, cipher
.len
))
258 /* inline decryption */
259 if (!crypter
->decrypt(crypter
, cipher
, iv
, NULL
))
263 if (!memeq(vector
->plain
, cipher
.ptr
, cipher
.len
))
267 /* allocated decryption */
268 if (!crypter
->decrypt(crypter
,
269 chunk_create(vector
->cipher
, vector
->len
), iv
, &plain
))
273 if (!memeq(vector
->plain
, plain
.ptr
, plain
.len
))
277 /* inline encryption */
278 if (!crypter
->encrypt(crypter
, plain
, iv
, NULL
))
282 if (!memeq(vector
->cipher
, plain
.ptr
, plain
.len
))
289 crypter
->destroy(crypter
);
291 if (plain
.ptr
!= vector
->plain
)
297 DBG1(DBG_LIB
, "disabled %N[%s]: %s test vector failed",
298 encryption_algorithm_names
, alg
, plugin_name
, get_name(vector
));
302 enumerator
->destroy(enumerator
);
307 DBG1(DBG_LIB
,"disable %N[%s]: %zd byte key size not supported",
308 encryption_algorithm_names
, alg
, plugin_name
, key_size
);
313 DBG1(DBG_LIB
, "%s %N[%s]: no test vectors found",
314 this->required
? "disabled" : "enabled ",
315 encryption_algorithm_names
, alg
, plugin_name
);
316 return !this->required
;
323 *speed
= bench_crypter(this, alg
, create
, key_size
);
324 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors, %d points "
325 "(%zd bit key)", encryption_algorithm_names
, alg
,
326 plugin_name
, tested
, *speed
, key_size
* 8);
330 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors",
331 encryption_algorithm_names
, alg
, plugin_name
, tested
);
338 * Benchmark an aead transform
340 static u_int
bench_aead(private_crypto_tester_t
*this,
341 encryption_algorithm_t alg
, aead_constructor_t create
, size_t key_size
)
345 aead
= create(alg
, key_size
, 0);
348 char iv
[aead
->get_iv_size(aead
)];
349 char key
[aead
->get_key_size(aead
)];
352 struct timespec start
;
356 memset(iv
, 0x56, sizeof(iv
));
357 memset(key
, 0x12, sizeof(key
));
358 memset(assoc
, 0x78, sizeof(assoc
));
359 if (!aead
->set_key(aead
, chunk_from_thing(key
)))
363 icv
= aead
->get_icv_size(aead
);
365 buf
= chunk_alloc(this->bench_size
+ icv
);
366 memset(buf
.ptr
, 0x34, buf
.len
);
370 start_timing(&start
);
371 while (end_timing(&start
) < this->bench_time
)
373 if (aead
->encrypt(aead
, buf
, chunk_from_thing(assoc
),
374 chunk_from_thing(iv
), NULL
))
378 if (aead
->decrypt(aead
, chunk_create(buf
.ptr
, buf
.len
+ icv
),
379 chunk_from_thing(assoc
), chunk_from_thing(iv
), NULL
))
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
)
397 enumerator_t
*enumerator
;
398 aead_test_vector_t
*vector
;
402 enumerator
= this->aead
->create_enumerator(this->aead
);
403 while (enumerator
->enumerate(enumerator
, &vector
))
406 chunk_t key
, iv
, assoc
, plain
= chunk_empty
, cipher
= chunk_empty
;
409 if (vector
->alg
!= alg
)
413 if (key_size
&& key_size
!= vector
->key_size
)
414 { /* test only vectors with a specific key size, if key size given */
417 if (salt_size
&& salt_size
!= vector
->salt_size
)
424 aead
= create(alg
, vector
->key_size
, vector
->salt_size
);
427 DBG1(DBG_LIB
, "%N[%s]: %u bit key size not supported",
428 encryption_algorithm_names
, alg
, plugin_name
,
429 BITS_PER_BYTE
* vector
->key_size
);
433 key
= chunk_create(vector
->key
, aead
->get_key_size(aead
));
434 if (!aead
->set_key(aead
, key
))
438 iv
= chunk_create(vector
->iv
, aead
->get_iv_size(aead
));
439 assoc
= chunk_create(vector
->adata
, vector
->alen
);
440 icv
= aead
->get_icv_size(aead
);
442 /* allocated encryption */
443 plain
= chunk_create(vector
->plain
, vector
->len
);
444 if (!aead
->encrypt(aead
, plain
, assoc
, iv
, &cipher
))
448 if (!memeq(vector
->cipher
, cipher
.ptr
, cipher
.len
))
452 /* inline decryption */
453 if (!aead
->decrypt(aead
, cipher
, assoc
, iv
, NULL
))
457 if (!memeq(vector
->plain
, cipher
.ptr
, cipher
.len
- icv
))
461 /* allocated decryption */
462 if (!aead
->decrypt(aead
, chunk_create(vector
->cipher
, vector
->len
+ icv
),
467 if (!memeq(vector
->plain
, plain
.ptr
, plain
.len
))
471 plain
.ptr
= realloc(plain
.ptr
, plain
.len
+ icv
);
472 /* inline encryption */
473 if (!aead
->encrypt(aead
, plain
, assoc
, iv
, NULL
))
477 if (!memeq(vector
->cipher
, plain
.ptr
, plain
.len
+ icv
))
486 if (plain
.ptr
!= vector
->plain
)
492 DBG1(DBG_LIB
, "disabled %N[%s]: %s test vector failed",
493 encryption_algorithm_names
, alg
, plugin_name
, get_name(vector
));
497 enumerator
->destroy(enumerator
);
502 DBG1(DBG_LIB
,"disable %N[%s]: %zd byte key size not supported",
503 encryption_algorithm_names
, alg
, plugin_name
, key_size
);
508 DBG1(DBG_LIB
, "%s %N[%s]: no test vectors found",
509 this->required
? "disabled" : "enabled ",
510 encryption_algorithm_names
, alg
, plugin_name
);
511 return !this->required
;
518 *speed
= bench_aead(this, alg
, create
, key_size
);
519 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors, %d points "
520 "(%zd bit key)", encryption_algorithm_names
, alg
,
521 plugin_name
, tested
, *speed
, key_size
* 8);
525 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors",
526 encryption_algorithm_names
, alg
, plugin_name
, tested
);
535 static u_int
bench_signer(private_crypto_tester_t
*this,
536 integrity_algorithm_t alg
, signer_constructor_t create
)
540 signer
= create(alg
);
543 char key
[signer
->get_key_size(signer
)];
544 char mac
[signer
->get_block_size(signer
)];
546 struct timespec start
;
549 memset(key
, 0x12, sizeof(key
));
550 if (!signer
->set_key(signer
, chunk_from_thing(key
)))
555 buf
= chunk_alloc(this->bench_size
);
556 memset(buf
.ptr
, 0x34, buf
.len
);
559 start_timing(&start
);
560 while (end_timing(&start
) < this->bench_time
)
562 if (signer
->get_signature(signer
, buf
, mac
))
566 if (signer
->verify_signature(signer
, buf
, chunk_from_thing(mac
)))
572 signer
->destroy(signer
);
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
)
583 enumerator_t
*enumerator
;
584 signer_test_vector_t
*vector
;
588 enumerator
= this->signer
->create_enumerator(this->signer
);
589 while (enumerator
->enumerate(enumerator
, &vector
))
592 chunk_t key
, data
, mac
= chunk_empty
;
594 if (vector
->alg
!= alg
)
601 signer
= create(alg
);
604 DBG1(DBG_LIB
, "disabled %N[%s]: creating instance failed",
605 integrity_algorithm_names
, alg
, plugin_name
);
609 data
= chunk_create(vector
->data
, vector
->len
);
610 key
= chunk_create(vector
->key
, signer
->get_key_size(signer
));
611 if (!signer
->set_key(signer
, key
))
615 /* do partial append mode and check if key gets set correctly */
616 if (!signer
->get_signature(signer
, data
, NULL
))
620 if (!signer
->set_key(signer
, key
))
624 /* allocated signature */
625 if (!signer
->allocate_signature(signer
, data
, &mac
))
629 if (mac
.len
!= signer
->get_block_size(signer
))
633 if (!memeq(vector
->mac
, mac
.ptr
, mac
.len
))
637 /* signature to existing buffer */
638 memset(mac
.ptr
, 0, mac
.len
);
639 if (!signer
->get_signature(signer
, data
, mac
.ptr
))
643 if (!memeq(vector
->mac
, mac
.ptr
, mac
.len
))
647 /* signature verification, good case */
648 if (!signer
->verify_signature(signer
, data
, mac
))
652 /* signature verification, bad case */
653 *(mac
.ptr
+ mac
.len
- 1) += 1;
654 if (signer
->verify_signature(signer
, data
, mac
))
658 /* signature to existing buffer, using append mode */
661 if (!signer
->allocate_signature(signer
,
662 chunk_create(data
.ptr
, 1), NULL
))
666 if (!signer
->get_signature(signer
,
667 chunk_create(data
.ptr
+ 1, 1), NULL
))
671 if (!signer
->verify_signature(signer
, chunk_skip(data
, 2),
672 chunk_create(vector
->mac
, mac
.len
)))
680 signer
->destroy(signer
);
684 DBG1(DBG_LIB
, "disabled %N[%s]: %s test vector failed",
685 integrity_algorithm_names
, alg
, plugin_name
, get_name(vector
));
689 enumerator
->destroy(enumerator
);
692 DBG1(DBG_LIB
, "%s %N[%s]: no test vectors found",
693 this->required
? "disabled" : "enabled ",
694 integrity_algorithm_names
, alg
, plugin_name
);
695 return !this->required
;
701 *speed
= bench_signer(this, alg
, create
);
702 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors, %d points",
703 integrity_algorithm_names
, alg
, plugin_name
, tested
, *speed
);
707 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors",
708 integrity_algorithm_names
, alg
, plugin_name
, tested
);
717 static u_int
bench_hasher(private_crypto_tester_t
*this,
718 hash_algorithm_t alg
, hasher_constructor_t create
)
722 hasher
= create(alg
);
725 char hash
[hasher
->get_hash_size(hasher
)];
727 struct timespec start
;
730 buf
= chunk_alloc(this->bench_size
);
731 memset(buf
.ptr
, 0x34, buf
.len
);
734 start_timing(&start
);
735 while (end_timing(&start
) < this->bench_time
)
737 if (hasher
->get_hash(hasher
, buf
, hash
))
743 hasher
->destroy(hasher
);
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
)
754 enumerator_t
*enumerator
;
755 hasher_test_vector_t
*vector
;
759 enumerator
= this->hasher
->create_enumerator(this->hasher
);
760 while (enumerator
->enumerate(enumerator
, &vector
))
765 if (vector
->alg
!= alg
)
772 hasher
= create(alg
);
775 DBG1(DBG_LIB
, "disabled %N[%s]: creating instance failed",
776 hash_algorithm_names
, alg
, plugin_name
);
781 data
= chunk_create(vector
->data
, vector
->len
);
782 if (!hasher
->allocate_hash(hasher
, data
, &hash
))
786 if (hash
.len
!= hasher
->get_hash_size(hasher
))
790 if (!memeq(vector
->hash
, hash
.ptr
, hash
.len
))
794 /* hash to existing buffer, with a reset */
795 memset(hash
.ptr
, 0, hash
.len
);
796 if (!hasher
->get_hash(hasher
, data
, NULL
))
800 if (!hasher
->reset(hasher
))
804 if (!hasher
->get_hash(hasher
, data
, hash
.ptr
))
808 if (!memeq(vector
->hash
, hash
.ptr
, hash
.len
))
812 /* hasher to existing buffer, using append mode */
815 memset(hash
.ptr
, 0, hash
.len
);
816 if (!hasher
->allocate_hash(hasher
, chunk_create(data
.ptr
, 1), NULL
))
820 if (!hasher
->get_hash(hasher
, chunk_create(data
.ptr
+ 1, 1), NULL
))
824 if (!hasher
->get_hash(hasher
, chunk_skip(data
, 2), hash
.ptr
))
828 if (!memeq(vector
->hash
, hash
.ptr
, hash
.len
))
836 hasher
->destroy(hasher
);
840 DBG1(DBG_LIB
, "disabled %N[%s]: %s test vector failed",
841 hash_algorithm_names
, alg
, plugin_name
, get_name(vector
));
845 enumerator
->destroy(enumerator
);
848 DBG1(DBG_LIB
, "%s %N[%s]: no test vectors found",
849 this->required
? "disabled" : "enabled ",
850 hash_algorithm_names
, alg
, plugin_name
);
851 return !this->required
;
857 *speed
= bench_hasher(this, alg
, create
);
858 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors, %d points",
859 hash_algorithm_names
, alg
, plugin_name
, tested
, *speed
);
863 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors",
864 hash_algorithm_names
, alg
, plugin_name
, tested
);
873 static u_int
bench_prf(private_crypto_tester_t
*this,
874 pseudo_random_function_t alg
, prf_constructor_t create
)
881 char bytes
[prf
->get_block_size(prf
)], key
[prf
->get_block_size(prf
)];
883 struct timespec start
;
886 memset(key
, 0x56, prf
->get_block_size(prf
));
887 if (!prf
->set_key(prf
, chunk_create(key
, prf
->get_block_size(prf
))))
893 buf
= chunk_alloc(this->bench_size
);
894 memset(buf
.ptr
, 0x34, buf
.len
);
897 start_timing(&start
);
898 while (end_timing(&start
) < this->bench_time
)
900 if (prf
->get_bytes(prf
, buf
, bytes
))
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
)
917 enumerator_t
*enumerator
;
918 prf_test_vector_t
*vector
;
922 enumerator
= this->prf
->create_enumerator(this->prf
);
923 while (enumerator
->enumerate(enumerator
, &vector
))
926 chunk_t key
, seed
, out
= chunk_empty
;
928 if (vector
->alg
!= alg
)
938 DBG1(DBG_LIB
, "disabled %N[%s]: creating instance failed",
939 pseudo_random_function_names
, alg
, plugin_name
);
943 seed
= chunk_create(vector
->seed
, vector
->len
);
944 key
= chunk_create(vector
->key
, vector
->key_size
);
945 if (!prf
->set_key(prf
, key
))
949 if (alg
!= PRF_FIPS_SHA1_160
)
951 /* do partial append mode and check if key gets set correctly */
952 if (!prf
->get_bytes(prf
, seed
, NULL
))
956 if (!prf
->set_key(prf
, key
))
961 /* allocated bytes */
962 if (!prf
->allocate_bytes(prf
, seed
, &out
))
966 if (out
.len
!= prf
->get_block_size(prf
))
970 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
974 /* bytes to existing buffer */
975 memset(out
.ptr
, 0, out
.len
);
976 if (vector
->stateful
)
978 if (!prf
->set_key(prf
, key
))
983 if (!prf
->get_bytes(prf
, seed
, out
.ptr
))
987 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
991 /* bytes to existing buffer, using append mode */
992 if (alg
!= PRF_FIPS_SHA1_160
&& seed
.len
> 2)
994 memset(out
.ptr
, 0, out
.len
);
995 if (vector
->stateful
)
997 if (!prf
->set_key(prf
, key
))
1002 if (!prf
->allocate_bytes(prf
, chunk_create(seed
.ptr
, 1), NULL
))
1006 if (!prf
->get_bytes(prf
, chunk_create(seed
.ptr
+ 1, 1), NULL
))
1010 if (!prf
->get_bytes(prf
, chunk_skip(seed
, 2), out
.ptr
))
1014 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
1026 DBG1(DBG_LIB
, "disabled %N[%s]: %s test vector failed",
1027 pseudo_random_function_names
, alg
, plugin_name
, get_name(vector
));
1031 enumerator
->destroy(enumerator
);
1034 DBG1(DBG_LIB
, "%s %N[%s]: no test vectors found",
1035 this->required
? "disabled" : "enabled ",
1036 pseudo_random_function_names
, alg
, plugin_name
);
1037 return !this->required
;
1043 *speed
= bench_prf(this, alg
, create
);
1044 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors, %d points",
1045 pseudo_random_function_names
, alg
, plugin_name
, tested
, *speed
);
1049 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors",
1050 pseudo_random_function_names
, alg
, plugin_name
, tested
);
1059 static u_int
bench_xof(private_crypto_tester_t
*this,
1060 ext_out_function_t alg
, xof_constructor_t create
)
1067 char seed
[xof
->get_seed_size(xof
)];
1068 char bytes
[xof
->get_block_size(xof
)];
1069 struct timespec start
;
1072 memset(seed
, 0x56, xof
->get_seed_size(xof
));
1073 if (!xof
->set_seed(xof
, chunk_create(seed
, xof
->get_seed_size(xof
))))
1080 start_timing(&start
);
1081 while (end_timing(&start
) < this->bench_time
)
1083 if (xof
->get_bytes(xof
, xof
->get_block_size(xof
), bytes
))
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
)
1099 enumerator_t
*enumerator
;
1100 xof_test_vector_t
*vector
;
1101 bool failed
= FALSE
;
1104 enumerator
= this->xof
->create_enumerator(this->xof
);
1105 while (enumerator
->enumerate(enumerator
, &vector
))
1108 chunk_t seed
, out
= chunk_empty
;
1110 if (vector
->alg
!= alg
)
1120 DBG1(DBG_LIB
, "disabled %N[%s]: creating instance failed",
1121 ext_out_function_names
, alg
, plugin_name
);
1125 seed
= chunk_create(vector
->seed
, vector
->len
);
1126 if (!xof
->set_seed(xof
, seed
))
1130 /* allocated bytes */
1131 if (!xof
->allocate_bytes(xof
, vector
->out_len
, &out
))
1135 if (out
.len
!= vector
->out_len
)
1139 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
1143 /* bytes to existing buffer */
1144 memset(out
.ptr
, 0, out
.len
);
1145 if (!xof
->set_seed(xof
, seed
))
1149 if (!xof
->get_bytes(xof
, vector
->out_len
, out
.ptr
))
1153 if (!memeq(vector
->out
, out
.ptr
, vector
->out_len
))
1157 /* bytes to existing buffer, using append mode */
1166 DBG1(DBG_LIB
, "disabled %N[%s]: %s test vector failed",
1167 ext_out_function_names
, alg
, plugin_name
, get_name(vector
));
1171 enumerator
->destroy(enumerator
);
1174 DBG1(DBG_LIB
, "%s %N[%s]: no test vectors found",
1175 this->required
? "disabled" : "enabled ",
1176 ext_out_function_names
, alg
, plugin_name
);
1177 return !this->required
;
1183 *speed
= bench_xof(this, alg
, create
);
1184 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors, %d points",
1185 ext_out_function_names
, alg
, plugin_name
, tested
, *speed
);
1189 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors",
1190 ext_out_function_names
, alg
, plugin_name
, tested
);
1199 * Create a KDF using the given arguments
1201 static kdf_t
*create_kdf_args(kdf_constructor_t create
,
1202 key_derivation_function_t alg
, ...)
1207 va_start(args
, alg
);
1208 kdf
= create(alg
, args
);
1214 * Create a KDF using arguments from the given test vector
1216 static kdf_t
*create_kdf_vector(kdf_constructor_t create
,
1217 key_derivation_function_t alg
,
1218 kdf_test_vector_t
*vector
)
1224 return create_kdf_args(create
, alg
, vector
->arg
.prf
);
1232 * Check if the given test vector applies to the passed arguments
1234 static bool kdf_vector_applies(key_derivation_function_t alg
,
1235 kdf_test_args_t
*args
, kdf_test_vector_t
*vector
)
1237 bool applies
= FALSE
;
1244 pseudo_random_function_t prf
;
1245 VA_ARGS_VGET(args
->args
, prf
);
1246 applies
= (prf
== vector
->arg
.prf
);
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
)
1260 enumerator_t
*enumerator
;
1261 kdf_test_vector_t
*vector
;
1263 bool failed
= FALSE
;
1264 u_int tested
= 0, construction_failed
= 0;
1266 enumerator
= this->kdf
->create_enumerator(this->kdf
);
1267 while (enumerator
->enumerate(enumerator
, &vector
))
1270 chunk_t out
= chunk_empty
;
1272 if (vector
->alg
!= alg
||
1273 (args
&& !kdf_vector_applies(alg
, args
, vector
)))
1282 va_copy(copy
, args
->args
);
1283 kdf
= create(alg
, copy
);
1288 kdf
= create_kdf_vector(create
, alg
, vector
);
1294 DBG1(DBG_LIB
, "disabled %N[%s]: creating instance failed",
1295 key_derivation_function_names
, alg
, plugin_name
);
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 construction_failed
++;
1306 if (vector
->key
.len
&&
1307 !kdf
->set_param(kdf
, KDF_PARAM_KEY
, vector
->key
))
1311 if (vector
->salt
.len
&&
1312 !kdf
->set_param(kdf
, KDF_PARAM_SALT
, vector
->salt
))
1316 if (kdf_has_fixed_output_length(alg
))
1318 if (kdf
->get_length(kdf
) != vector
->out
.len
)
1323 else if (kdf
->get_length(kdf
) != SIZE_MAX
)
1327 /* allocated bytes */
1328 if (!kdf
->allocate_bytes(kdf
, vector
->out
.len
, &out
))
1332 if (!chunk_equals(out
, vector
->out
))
1336 /* allocate without knowing the length */
1337 if (kdf_has_fixed_output_length(alg
))
1340 if (!kdf
->allocate_bytes(kdf
, 0, &out
))
1344 if (!chunk_equals(out
, vector
->out
))
1349 /* bytes to existing buffer */
1350 memset(out
.ptr
, 0, out
.len
);
1351 if (!kdf
->get_bytes(kdf
, out
.len
, out
.ptr
))
1355 if (!chunk_equals(out
, vector
->out
))
1366 DBG1(DBG_LIB
, "disabled %N[%s]: %s test vector failed",
1367 key_derivation_function_names
, alg
, plugin_name
,
1372 enumerator
->destroy(enumerator
);
1375 DBG1(DBG_LIB
, "%s %N[%s]: no test vectors found",
1376 this->required
? "disabled" : "enabled ",
1377 key_derivation_function_names
, alg
, plugin_name
);
1378 return !this->required
;
1380 tested
-= construction_failed
;
1383 DBG1(DBG_LIB
, "%s %N[%s]: unable to apply any available test vectors",
1384 this->required
? "disabled" : "enabled ",
1385 key_derivation_function_names
, alg
, plugin_name
);
1386 return !this->required
;
1392 DBG2(DBG_LIB
, "benchmarking for %N is currently not supported",
1393 key_derivation_function_names
, alg
);
1395 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors",
1396 key_derivation_function_names
, alg
, plugin_name
, tested
);
1404 static u_int
bench_drbg(private_crypto_tester_t
*this,
1405 drbg_type_t type
, drbg_constructor_t create
)
1409 uint32_t strength
= 128;
1410 chunk_t seed
= chunk_alloca(48);
1412 memset(seed
.ptr
, 0x81, seed
.len
);
1413 entropy
= rng_tester_create(seed
);
1415 drbg
= create(type
, strength
, entropy
, chunk_empty
);
1418 struct timespec start
;
1420 size_t out_len
= 128;
1421 char out_buf
[out_len
];
1423 start_timing(&start
);
1424 while (end_timing(&start
) < this->bench_time
)
1426 if (drbg
->generate(drbg
, out_len
, out_buf
))
1431 drbg
->destroy(drbg
);
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
)
1442 enumerator_t
*enumerator
;
1443 drbg_test_vector_t
*vector
;
1444 bool failed
= FALSE
;
1447 enumerator
= this->drbg
->create_enumerator(this->drbg
);
1448 while (enumerator
->enumerate(enumerator
, &vector
))
1452 chunk_t out
= chunk_empty
;
1454 if (vector
->type
!= type
)
1461 entropy
= rng_tester_create(vector
->entropy
);
1462 out
= chunk_alloc(vector
->out
.len
);
1464 drbg
= create(type
, vector
->strength
, entropy
,
1465 vector
->personalization_str
);
1468 DBG1(DBG_LIB
, "disabled %N[%s]: creating instance failed",
1469 drbg_type_names
, type
, plugin_name
);
1470 entropy
->destroy(entropy
);
1474 if (!drbg
->reseed(drbg
))
1478 if (!drbg
->generate(drbg
, out
.len
, out
.ptr
))
1482 if (!drbg
->generate(drbg
, out
.len
, out
.ptr
))
1486 if (!chunk_equals(out
, vector
->out
))
1493 drbg
->destroy(drbg
);
1497 DBG1(DBG_LIB
, "disabled %N[%s]: %s test vector failed",
1498 drbg_type_names
, type
, plugin_name
, get_name(vector
));
1502 enumerator
->destroy(enumerator
);
1505 DBG1(DBG_LIB
, "%s %N[%s]: no test vectors found",
1506 this->required
? "disabled" : "enabled ",
1507 drbg_type_names
, type
, plugin_name
);
1508 return !this->required
;
1514 *speed
= bench_drbg(this, type
, create
);
1515 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors, %d points",
1516 drbg_type_names
, type
, plugin_name
, tested
, *speed
);
1520 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors",
1521 drbg_type_names
, type
, plugin_name
, tested
);
1530 static u_int
bench_rng(private_crypto_tester_t
*this,
1531 rng_quality_t quality
, rng_constructor_t create
)
1535 rng
= create(quality
);
1538 struct timespec start
;
1543 buf
= chunk_alloc(this->bench_size
);
1544 start_timing(&start
);
1545 while (end_timing(&start
) < this->bench_time
)
1547 if (!rng
->get_bytes(rng
, buf
.len
, buf
.ptr
))
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
)
1566 enumerator_t
*enumerator
;
1567 rng_test_vector_t
*vector
;
1568 bool failed
= FALSE
;
1571 if (!this->rng_true
&& quality
== RNG_TRUE
)
1573 DBG1(DBG_LIB
, "enabled %N[%s]: skipping test (disabled by config)",
1574 rng_quality_names
, quality
, plugin_name
);
1578 enumerator
= this->rng
->create_enumerator(this->rng
);
1579 while (enumerator
->enumerate(enumerator
, &vector
))
1581 chunk_t data
= chunk_empty
;
1584 if (vector
->quality
!= quality
)
1591 rng
= create(quality
);
1594 DBG1(DBG_LIB
, "disabled %N[%s]: creating instance failed",
1595 rng_quality_names
, quality
, plugin_name
);
1599 /* allocated bytes */
1600 if (!rng
->allocate_bytes(rng
, vector
->len
, &data
) ||
1601 data
.len
!= vector
->len
||
1602 !vector
->test(vector
->user
, data
))
1606 /* write bytes into existing buffer */
1607 memset(data
.ptr
, 0, data
.len
);
1608 if (!rng
->get_bytes(rng
, vector
->len
, data
.ptr
))
1612 if (!vector
->test(vector
->user
, data
))
1623 DBG1(DBG_LIB
, "disabled %N[%s]: %s test vector failed",
1624 rng_quality_names
, quality
, plugin_name
, get_name(vector
));
1628 enumerator
->destroy(enumerator
);
1631 DBG1(DBG_LIB
, "%s %N[%s]: no test vectors found",
1632 this->required
? ", disabled" : "enabled ",
1633 rng_quality_names
, quality
, plugin_name
);
1634 return !this->required
;
1640 *speed
= bench_rng(this, quality
, create
);
1641 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors, %d points",
1642 rng_quality_names
, quality
, plugin_name
, tested
, *speed
);
1646 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors",
1647 rng_quality_names
, quality
, plugin_name
, tested
);
1654 * Benchmark a key exchange backend
1656 static u_int
bench_ke(private_crypto_tester_t
*this,
1657 key_exchange_method_t method
, ke_constructor_t create
)
1659 chunk_t pub
= chunk_empty
, shared
= chunk_empty
;
1661 struct timespec start
;
1665 start_timing(&start
);
1666 while (end_timing(&start
) < this->bench_time
)
1668 ke
= create(method
);
1673 if (ke
->get_public_key(ke
, &pub
) &&
1674 ke
->set_public_key(ke
, pub
) &&
1675 ke
->get_shared_secret(ke
, &shared
))
1680 chunk_free(&shared
);
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
)
1690 enumerator_t
*enumerator
;
1691 ke_test_vector_t
*v
;
1692 bool failed
= FALSE
;
1695 enumerator
= this->ke
->create_enumerator(this->ke
);
1696 while (enumerator
->enumerate(enumerator
, &v
))
1698 key_exchange_t
*a
, *b
;
1699 chunk_t apub
, bpub
, asec
, bsec
;
1701 if (v
->method
!= method
)
1714 DBG1(DBG_LIB
, "disabled %N[%s]: creating instance failed",
1715 key_exchange_method_names
, method
, plugin_name
);
1719 if (!a
->set_private_key
|| !b
->set_private_key
)
1720 { /* does not support testing */
1728 apub
= bpub
= asec
= bsec
= chunk_empty
;
1730 if (!a
->set_private_key(a
, chunk_create(v
->priv_a
, v
->priv_len
)) ||
1731 !b
->set_private_key(b
, chunk_create(v
->priv_b
, v
->priv_len
)))
1735 if (!a
->get_public_key(a
, &apub
) ||
1736 !chunk_equals(apub
, chunk_create(v
->pub_a
, v
->pub_len
)))
1740 if (!b
->get_public_key(b
, &bpub
) ||
1741 !chunk_equals(bpub
, chunk_create(v
->pub_b
, v
->pub_len
)))
1745 if (!a
->set_public_key(a
, bpub
) ||
1746 !b
->set_public_key(b
, apub
))
1750 if (!a
->get_shared_secret(a
, &asec
) ||
1751 !chunk_equals(asec
, chunk_create(v
->shared
, v
->shared_len
)))
1755 if (!b
->get_shared_secret(b
, &bsec
) ||
1756 !chunk_equals(bsec
, chunk_create(v
->shared
, v
->shared_len
)))
1771 DBG1(DBG_LIB
, "disabled %N[%s]: %s test vector failed",
1772 key_exchange_method_names
, method
, plugin_name
, get_name(v
));
1776 enumerator
->destroy(enumerator
);
1779 DBG1(DBG_LIB
, "%s %N[%s]: no test vectors found / untestable",
1780 this->required
? "disabled" : "enabled ",
1781 key_exchange_method_names
, method
, plugin_name
);
1782 return !this->required
;
1788 *speed
= bench_ke(this, method
, create
);
1789 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors, %d points",
1790 key_exchange_method_names
, method
, plugin_name
, tested
, *speed
);
1794 DBG1(DBG_LIB
, "enabled %N[%s]: passed %u test vectors",
1795 key_exchange_method_names
, method
, plugin_name
, tested
);
1801 METHOD(crypto_tester_t
, add_crypter_vector
, void,
1802 private_crypto_tester_t
*this, crypter_test_vector_t
*vector
)
1804 this->crypter
->insert_last(this->crypter
, vector
);
1807 METHOD(crypto_tester_t
, add_aead_vector
, void,
1808 private_crypto_tester_t
*this, aead_test_vector_t
*vector
)
1810 this->aead
->insert_last(this->aead
, vector
);
1813 METHOD(crypto_tester_t
, add_signer_vector
, void,
1814 private_crypto_tester_t
*this, signer_test_vector_t
*vector
)
1816 this->signer
->insert_last(this->signer
, vector
);
1819 METHOD(crypto_tester_t
, add_hasher_vector
, void,
1820 private_crypto_tester_t
*this, hasher_test_vector_t
*vector
)
1822 this->hasher
->insert_last(this->hasher
, vector
);
1825 METHOD(crypto_tester_t
, add_prf_vector
, void,
1826 private_crypto_tester_t
*this, prf_test_vector_t
*vector
)
1828 this->prf
->insert_last(this->prf
, vector
);
1831 METHOD(crypto_tester_t
, add_xof_vector
, void,
1832 private_crypto_tester_t
*this, xof_test_vector_t
*vector
)
1834 this->xof
->insert_last(this->xof
, vector
);
1837 METHOD(crypto_tester_t
, add_kdf_vector
, void,
1838 private_crypto_tester_t
*this, kdf_test_vector_t
*vector
)
1840 this->kdf
->insert_last(this->kdf
, vector
);
1843 METHOD(crypto_tester_t
, add_drbg_vector
, void,
1844 private_crypto_tester_t
*this, drbg_test_vector_t
*vector
)
1846 this->drbg
->insert_last(this->drbg
, vector
);
1849 METHOD(crypto_tester_t
, add_rng_vector
, void,
1850 private_crypto_tester_t
*this, rng_test_vector_t
*vector
)
1852 this->rng
->insert_last(this->rng
, vector
);
1855 METHOD(crypto_tester_t
, add_ke_vector
, void,
1856 private_crypto_tester_t
*this, ke_test_vector_t
*vector
)
1858 this->ke
->insert_last(this->ke
, vector
);
1861 METHOD(crypto_tester_t
, destroy
, void,
1862 private_crypto_tester_t
*this)
1864 this->crypter
->destroy(this->crypter
);
1865 this->aead
->destroy(this->aead
);
1866 this->signer
->destroy(this->signer
);
1867 this->hasher
->destroy(this->hasher
);
1868 this->prf
->destroy(this->prf
);
1869 this->xof
->destroy(this->xof
);
1870 this->kdf
->destroy(this->kdf
);
1871 this->drbg
->destroy(this->drbg
);
1872 this->rng
->destroy(this->rng
);
1873 this->ke
->destroy(this->ke
);
1880 crypto_tester_t
*crypto_tester_create()
1882 private_crypto_tester_t
*this;
1886 .test_crypter
= _test_crypter
,
1887 .test_aead
= _test_aead
,
1888 .test_signer
= _test_signer
,
1889 .test_hasher
= _test_hasher
,
1890 .test_prf
= _test_prf
,
1891 .test_xof
= _test_xof
,
1892 .test_kdf
= _test_kdf
,
1893 .test_drbg
= _test_drbg
,
1894 .test_rng
= _test_rng
,
1895 .test_ke
= _test_ke
,
1896 .add_crypter_vector
= _add_crypter_vector
,
1897 .add_aead_vector
= _add_aead_vector
,
1898 .add_signer_vector
= _add_signer_vector
,
1899 .add_hasher_vector
= _add_hasher_vector
,
1900 .add_prf_vector
= _add_prf_vector
,
1901 .add_xof_vector
= _add_xof_vector
,
1902 .add_kdf_vector
= _add_kdf_vector
,
1903 .add_drbg_vector
= _add_drbg_vector
,
1904 .add_rng_vector
= _add_rng_vector
,
1905 .add_ke_vector
= _add_ke_vector
,
1906 .destroy
= _destroy
,
1908 .crypter
= linked_list_create(),
1909 .aead
= linked_list_create(),
1910 .signer
= linked_list_create(),
1911 .hasher
= linked_list_create(),
1912 .prf
= linked_list_create(),
1913 .xof
= linked_list_create(),
1914 .kdf
= linked_list_create(),
1915 .drbg
= linked_list_create(),
1916 .rng
= linked_list_create(),
1917 .ke
= linked_list_create(),
1919 .required
= lib
->settings
->get_bool(lib
->settings
,
1920 "%s.crypto_test.required", FALSE
, lib
->ns
),
1921 .rng_true
= lib
->settings
->get_bool(lib
->settings
,
1922 "%s.crypto_test.rng_true", FALSE
, lib
->ns
),
1923 .bench_time
= lib
->settings
->get_int(lib
->settings
,
1924 "%s.crypto_test.bench_time", 50, lib
->ns
),
1925 .bench_size
= lib
->settings
->get_int(lib
->settings
,
1926 "%s.crypto_test.bench_size", 1024, lib
->ns
),
1929 /* enforce a block size of 16, should be fine for all algorithms */
1930 this->bench_size
= this->bench_size
/ 16 * 16;
1932 return &this->public;