2 * Copyright (C) 2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include "crypto_tester.h"
22 #include <utils/linked_list.h>
24 typedef struct private_crypto_tester_t private_crypto_tester_t
;
27 * Private data of an crypto_tester_t object.
29 struct private_crypto_tester_t
{
32 * Public crypto_tester_t interface.
34 crypto_tester_t
public;
37 * List of crypter test vectors
39 linked_list_t
*crypter
;
42 * List of signer test vectors
44 linked_list_t
*signer
;
47 * List of hasher test vectors
49 linked_list_t
*hasher
;
52 * List of PRF test vectors
57 * List of RNG test vectors
62 * Is a test vector required to pass a test?
67 * should we run RNG_TRUE tests? Enough entropy?
73 * Get the name of a test vector, if available
75 static const char* get_name(void *sym
)
80 if (dladdr(sym
, &dli
))
89 * Implementation of crypto_tester_t.test_crypter
91 static bool test_crypter(private_crypto_tester_t
*this,
92 encryption_algorithm_t alg
, size_t key_size
, crypter_constructor_t create
)
94 enumerator_t
*enumerator
;
95 crypter_test_vector_t
*vector
;
99 enumerator
= this->crypter
->create_enumerator(this->crypter
);
100 while (enumerator
->enumerate(enumerator
, &vector
))
103 chunk_t key
, plain
, cipher
, iv
;
105 if (vector
->alg
!= alg
)
109 if (key_size
&& key_size
!= vector
->key_size
)
110 { /* test only vectors with a specific key size, if key size given */
113 crypter
= create(alg
, vector
->key_size
);
115 { /* key size not supported... */
122 key
= chunk_create(vector
->key
, crypter
->get_key_size(crypter
));
123 crypter
->set_key(crypter
, key
);
124 iv
= chunk_create(vector
->iv
, crypter
->get_block_size(crypter
));
126 /* allocated encryption */
127 plain
= chunk_create(vector
->plain
, vector
->len
);
128 crypter
->encrypt(crypter
, plain
, iv
, &cipher
);
129 if (!memeq(vector
->cipher
, cipher
.ptr
, cipher
.len
))
133 /* inline decryption */
134 crypter
->decrypt(crypter
, cipher
, iv
, NULL
);
135 if (!memeq(vector
->plain
, cipher
.ptr
, cipher
.len
))
140 /* allocated decryption */
141 cipher
= chunk_create(vector
->cipher
, vector
->len
);
142 crypter
->decrypt(crypter
, cipher
, iv
, &plain
);
143 if (!memeq(vector
->plain
, plain
.ptr
, plain
.len
))
147 /* inline encryption */
148 crypter
->encrypt(crypter
, plain
, iv
, NULL
);
149 if (!memeq(vector
->cipher
, plain
.ptr
, plain
.len
))
155 crypter
->destroy(crypter
);
158 DBG1(DBG_LIB
, "disabled %N: %s test vector failed",
159 encryption_algorithm_names
, alg
, get_name(vector
));
163 enumerator
->destroy(enumerator
);
166 DBG1(DBG_LIB
, "%s %N: no test vectors found",
167 this->required ?
"disabled" : "enabled ",
168 encryption_algorithm_names
, alg
);
169 return !this->required
;
173 DBG1(DBG_LIB
, "enabled %N: passed %u test vectors",
174 encryption_algorithm_names
, alg
, tested
);
180 * Implementation of crypto_tester_t.test_signer
182 static bool test_signer(private_crypto_tester_t
*this,
183 integrity_algorithm_t alg
, signer_constructor_t create
)
185 enumerator_t
*enumerator
;
186 signer_test_vector_t
*vector
;
190 enumerator
= this->signer
->create_enumerator(this->signer
);
191 while (enumerator
->enumerate(enumerator
, &vector
))
194 chunk_t key
, data
, mac
;
196 if (vector
->alg
!= alg
)
202 signer
= create(alg
);
205 DBG1(DBG_LIB
, "disabled %N: creating instance failed",
206 integrity_algorithm_names
, alg
);
213 key
= chunk_create(vector
->key
, signer
->get_key_size(signer
));
214 signer
->set_key(signer
, key
);
216 /* allocated signature */
217 data
= chunk_create(vector
->data
, vector
->len
);
218 signer
->allocate_signature(signer
, data
, &mac
);
219 if (mac
.len
!= signer
->get_block_size(signer
))
223 if (!memeq(vector
->mac
, mac
.ptr
, mac
.len
))
227 /* signature to existing buffer */
228 memset(mac
.ptr
, 0, mac
.len
);
229 signer
->get_signature(signer
, data
, mac
.ptr
);
230 if (!memeq(vector
->mac
, mac
.ptr
, mac
.len
))
234 /* signature verification, good case */
235 if (!signer
->verify_signature(signer
, data
, mac
))
239 /* signature verification, bad case */
240 *(mac
.ptr
+ mac
.len
- 1) += 1;
241 if (signer
->verify_signature(signer
, data
, mac
))
245 /* signature to existing buffer, using append mode */
248 memset(mac
.ptr
, 0, mac
.len
);
249 signer
->allocate_signature(signer
, chunk_create(data
.ptr
, 1), NULL
);
250 signer
->get_signature(signer
, chunk_create(data
.ptr
+ 1, 1), NULL
);
251 signer
->get_signature(signer
, chunk_skip(data
, 2), mac
.ptr
);
252 if (!memeq(vector
->mac
, mac
.ptr
, mac
.len
))
259 signer
->destroy(signer
);
262 DBG1(DBG_LIB
, "disabled %N: %s test vector failed",
263 integrity_algorithm_names
, alg
, get_name(vector
));
267 enumerator
->destroy(enumerator
);
270 DBG1(DBG_LIB
, "%s %N: no test vectors found",
271 this->required ?
"disabled" : "enabled ",
272 integrity_algorithm_names
, alg
);
273 return !this->required
;
277 DBG1(DBG_LIB
, "enabled %N: passed %u test vectors",
278 integrity_algorithm_names
, alg
, tested
);
284 * Implementation of hasher_t.test_hasher
286 static bool test_hasher(private_crypto_tester_t
*this, hash_algorithm_t alg
,
287 hasher_constructor_t create
)
289 enumerator_t
*enumerator
;
290 hasher_test_vector_t
*vector
;
294 enumerator
= this->hasher
->create_enumerator(this->hasher
);
295 while (enumerator
->enumerate(enumerator
, &vector
))
300 if (vector
->alg
!= alg
)
306 hasher
= create(alg
);
309 DBG1(DBG_LIB
, "disabled %N: creating instance failed",
310 hash_algorithm_names
, alg
);
318 data
= chunk_create(vector
->data
, vector
->len
);
319 hasher
->allocate_hash(hasher
, data
, &hash
);
320 if (hash
.len
!= hasher
->get_hash_size(hasher
))
324 if (!memeq(vector
->hash
, hash
.ptr
, hash
.len
))
328 /* hash to existing buffer */
329 memset(hash
.ptr
, 0, hash
.len
);
330 hasher
->get_hash(hasher
, data
, hash
.ptr
);
331 if (!memeq(vector
->hash
, hash
.ptr
, hash
.len
))
335 /* hasher to existing buffer, using append mode */
338 memset(hash
.ptr
, 0, hash
.len
);
339 hasher
->allocate_hash(hasher
, chunk_create(data
.ptr
, 1), NULL
);
340 hasher
->get_hash(hasher
, chunk_create(data
.ptr
+ 1, 1), NULL
);
341 hasher
->get_hash(hasher
, chunk_skip(data
, 2), hash
.ptr
);
342 if (!memeq(vector
->hash
, hash
.ptr
, hash
.len
))
349 hasher
->destroy(hasher
);
352 DBG1(DBG_LIB
, "disabled %N: %s test vector failed",
353 hash_algorithm_names
, alg
, get_name(vector
));
357 enumerator
->destroy(enumerator
);
360 DBG1(DBG_LIB
, "%s %N: no test vectors found",
361 this->required ?
"disabled" : "enabled ",
362 hash_algorithm_names
, alg
);
363 return !this->required
;
367 DBG1(DBG_LIB
, "enabled %N: passed %u test vectors",
368 hash_algorithm_names
, alg
, tested
);
374 * Implementation of crypto_tester_t.test_prf
376 static bool test_prf(private_crypto_tester_t
*this,
377 pseudo_random_function_t alg
, prf_constructor_t create
)
379 enumerator_t
*enumerator
;
380 prf_test_vector_t
*vector
;
384 enumerator
= this->prf
->create_enumerator(this->prf
);
385 while (enumerator
->enumerate(enumerator
, &vector
))
388 chunk_t key
, seed
, out
;
390 if (vector
->alg
!= alg
)
399 DBG1(DBG_LIB
, "disabled %N: creating instance failed",
400 pseudo_random_function_names
, alg
);
407 key
= chunk_create(vector
->key
, vector
->key_size
);
408 prf
->set_key(prf
, key
);
410 /* allocated bytes */
411 seed
= chunk_create(vector
->seed
, vector
->len
);
412 prf
->allocate_bytes(prf
, seed
, &out
);
413 if (out
.len
!= prf
->get_block_size(prf
))
417 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
421 /* bytes to existing buffer */
422 memset(out
.ptr
, 0, out
.len
);
423 if (vector
->stateful
)
425 prf
->set_key(prf
, key
);
427 prf
->get_bytes(prf
, seed
, out
.ptr
);
428 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
432 /* bytes to existing buffer, using append mode */
435 memset(out
.ptr
, 0, out
.len
);
436 if (vector
->stateful
)
438 prf
->set_key(prf
, key
);
440 prf
->allocate_bytes(prf
, chunk_create(seed
.ptr
, 1), NULL
);
441 prf
->get_bytes(prf
, chunk_create(seed
.ptr
+ 1, 1), NULL
);
442 prf
->get_bytes(prf
, chunk_skip(seed
, 2), out
.ptr
);
443 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
453 DBG1(DBG_LIB
, "disabled %N: %s test vector failed",
454 pseudo_random_function_names
, alg
, get_name(vector
));
458 enumerator
->destroy(enumerator
);
461 DBG1(DBG_LIB
, "%s %N: no test vectors found",
462 this->required ?
"disabled" : "enabled ",
463 pseudo_random_function_names
, alg
);
464 return !this->required
;
468 DBG1(DBG_LIB
, "enabled %N: passed %u test vectors",
469 pseudo_random_function_names
, alg
, tested
);
475 * Implementation of crypto_tester_t.test_rng
477 static bool test_rng(private_crypto_tester_t
*this, rng_quality_t quality
,
478 rng_constructor_t create
)
480 enumerator_t
*enumerator
;
481 rng_test_vector_t
*vector
;
485 if (!this->rng_true
&& quality
== RNG_TRUE
)
487 DBG1(DBG_LIB
, "enabled %N: skipping test (disabled by config)",
488 rng_quality_names
, quality
);
492 enumerator
= this->rng
->create_enumerator(this->rng
);
493 while (enumerator
->enumerate(enumerator
, &vector
))
498 if (vector
->quality
!= quality
)
504 rng
= create(quality
);
507 DBG1(DBG_LIB
, "disabled %N: creating instance failed",
508 rng_quality_names
, quality
);
515 /* allocated bytes */
516 rng
->allocate_bytes(rng
, vector
->len
, &data
);
517 if (data
.len
!= vector
->len
)
521 if (!vector
->test(vector
->user
, data
))
525 /* bytes to existing buffer */
526 memset(data
.ptr
, 0, data
.len
);
527 rng
->get_bytes(rng
, vector
->len
, data
.ptr
);
528 if (!vector
->test(vector
->user
, data
))
537 DBG1(DBG_LIB
, "disabled %N: %s test vector failed",
538 rng_quality_names
, quality
, get_name(vector
));
542 enumerator
->destroy(enumerator
);
545 DBG1(DBG_LIB
, "%s %N: no test vectors found",
546 this->required ?
", disabled" : "enabled ",
547 rng_quality_names
, quality
);
548 return !this->required
;
552 DBG1(DBG_LIB
, "enabled %N: passed %u test vectors",
553 rng_quality_names
, quality
, tested
);
559 * Implementation of crypter_tester_t.add_crypter_vector
561 static void add_crypter_vector(private_crypto_tester_t
*this,
562 crypter_test_vector_t
*vector
)
564 this->crypter
->insert_last(this->crypter
, vector
);
568 * Implementation of crypter_tester_t.add_signer_vector
570 static void add_signer_vector(private_crypto_tester_t
*this,
571 signer_test_vector_t
*vector
)
573 this->signer
->insert_last(this->signer
, vector
);
577 * Implementation of crypter_tester_t.add_hasher_vector
579 static void add_hasher_vector(private_crypto_tester_t
*this,
580 hasher_test_vector_t
*vector
)
582 this->hasher
->insert_last(this->hasher
, vector
);
586 * Implementation of crypter_tester_t.add_prf_vector
588 static void add_prf_vector(private_crypto_tester_t
*this,
589 prf_test_vector_t
*vector
)
591 this->prf
->insert_last(this->prf
, vector
);
595 * Implementation of crypter_tester_t.add_rng_vector
597 static void add_rng_vector(private_crypto_tester_t
*this,
598 rng_test_vector_t
*vector
)
600 this->rng
->insert_last(this->rng
, vector
);
604 * Implementation of crypto_tester_t.destroy.
606 static void destroy(private_crypto_tester_t
*this)
608 this->crypter
->destroy(this->crypter
);
609 this->signer
->destroy(this->signer
);
610 this->hasher
->destroy(this->hasher
);
611 this->prf
->destroy(this->prf
);
612 this->rng
->destroy(this->rng
);
619 crypto_tester_t
*crypto_tester_create()
621 private_crypto_tester_t
*this = malloc_thing(private_crypto_tester_t
);
623 this->public.test_crypter
= (bool(*)(crypto_tester_t
*, encryption_algorithm_t alg
,size_t key_size
, crypter_constructor_t create
))test_crypter
;
624 this->public.test_signer
= (bool(*)(crypto_tester_t
*, integrity_algorithm_t alg
, signer_constructor_t create
))test_signer
;
625 this->public.test_hasher
= (bool(*)(crypto_tester_t
*, hash_algorithm_t alg
, hasher_constructor_t create
))test_hasher
;
626 this->public.test_prf
= (bool(*)(crypto_tester_t
*, pseudo_random_function_t alg
, prf_constructor_t create
))test_prf
;
627 this->public.test_rng
= (bool(*)(crypto_tester_t
*, rng_quality_t quality
, rng_constructor_t create
))test_rng
;
628 this->public.add_crypter_vector
= (void(*)(crypto_tester_t
*, crypter_test_vector_t
*vector
))add_crypter_vector
;
629 this->public.add_signer_vector
= (void(*)(crypto_tester_t
*, signer_test_vector_t
*vector
))add_signer_vector
;
630 this->public.add_hasher_vector
= (void(*)(crypto_tester_t
*, hasher_test_vector_t
*vector
))add_hasher_vector
;
631 this->public.add_prf_vector
= (void(*)(crypto_tester_t
*, prf_test_vector_t
*vector
))add_prf_vector
;
632 this->public.add_rng_vector
= (void(*)(crypto_tester_t
*, rng_test_vector_t
*vector
))add_rng_vector
;
633 this->public.destroy
= (void(*)(crypto_tester_t
*))destroy
;
635 this->crypter
= linked_list_create();
636 this->signer
= linked_list_create();
637 this->hasher
= linked_list_create();
638 this->prf
= linked_list_create();
639 this->rng
= linked_list_create();
641 this->required
= lib
->settings
->get_bool(lib
->settings
,
642 "libstrongswan.crypto_test.required", FALSE
);
643 this->rng_true
= lib
->settings
->get_bool(lib
->settings
,
644 "libstrongswan.crypto_test.rng_true", FALSE
);
646 return &this->public;