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
16 #include "crypto_tester.h"
19 #include <utils/linked_list.h>
21 typedef struct private_crypto_tester_t private_crypto_tester_t
;
24 * Private data of an crypto_tester_t object.
26 struct private_crypto_tester_t
{
29 * Public crypto_tester_t interface.
31 crypto_tester_t
public;
34 * List of crypter test vectors
36 linked_list_t
*crypter
;
39 * List of signer test vectors
41 linked_list_t
*signer
;
44 * List of hasher test vectors
46 linked_list_t
*hasher
;
49 * List of PRF test vectors
54 * List of RNG test vectors
59 * Is a test vector required to pass a test?
64 * should we run RNG_TRUE tests? Enough entropy?
70 * Implementation of crypto_tester_t.test_crypter
72 static bool test_crypter(private_crypto_tester_t
*this,
73 encryption_algorithm_t alg
, size_t key_size
, crypter_constructor_t create
)
75 enumerator_t
*enumerator
;
76 crypter_test_vector_t
*vector
;
80 enumerator
= this->crypter
->create_enumerator(this->crypter
);
81 while (enumerator
->enumerate(enumerator
, &vector
))
84 chunk_t key
, plain
, cipher
, iv
;
86 if (vector
->alg
!= alg
)
90 if (key_size
&& key_size
!= vector
->key_size
)
91 { /* test only vectors with a specific key size, if key size given */
94 crypter
= create(alg
, vector
->key_size
);
96 { /* key size not supported... */
103 key
= chunk_create(vector
->key
, crypter
->get_key_size(crypter
));
104 crypter
->set_key(crypter
, key
);
105 iv
= chunk_create(vector
->iv
, crypter
->get_block_size(crypter
));
107 /* allocated encryption */
108 plain
= chunk_create(vector
->plain
, vector
->len
);
109 crypter
->encrypt(crypter
, plain
, iv
, &cipher
);
110 if (!memeq(vector
->cipher
, cipher
.ptr
, cipher
.len
))
114 /* inline decryption */
115 crypter
->decrypt(crypter
, cipher
, iv
, NULL
);
116 if (!memeq(vector
->plain
, cipher
.ptr
, cipher
.len
))
121 /* allocated decryption */
122 cipher
= chunk_create(vector
->cipher
, vector
->len
);
123 crypter
->decrypt(crypter
, cipher
, iv
, &plain
);
124 if (!memeq(vector
->plain
, plain
.ptr
, plain
.len
))
128 /* inline encryption */
129 crypter
->encrypt(crypter
, plain
, iv
, NULL
);
130 if (!memeq(vector
->cipher
, plain
.ptr
, plain
.len
))
136 crypter
->destroy(crypter
);
139 DBG1("test vector %d failed, %N disabled",
140 tested
, encryption_algorithm_names
, alg
);
143 DBG2("%N test vector %d successful",
144 encryption_algorithm_names
, alg
, tested
);
146 enumerator
->destroy(enumerator
);
149 DBG1("no test vectors found for %N%s",
150 encryption_algorithm_names
, alg
,
151 this->required ?
", disabled" : "");
152 return !this->required
;
156 DBG2("successfully tested %d test vectors for %N",
157 tested
, encryption_algorithm_names
, alg
);
163 * Implementation of crypto_tester_t.test_signer
165 static bool test_signer(private_crypto_tester_t
*this,
166 integrity_algorithm_t alg
, signer_constructor_t create
)
168 enumerator_t
*enumerator
;
169 signer_test_vector_t
*vector
;
173 enumerator
= this->signer
->create_enumerator(this->signer
);
174 while (enumerator
->enumerate(enumerator
, &vector
))
177 chunk_t key
, data
, mac
;
179 if (vector
->alg
!= alg
)
185 signer
= create(alg
);
188 DBG1("creating instance failed, %N disabled",
189 integrity_algorithm_names
, alg
);
196 key
= chunk_create(vector
->key
, signer
->get_key_size(signer
));
197 signer
->set_key(signer
, key
);
199 /* allocated signature */
200 data
= chunk_create(vector
->data
, vector
->len
);
201 signer
->allocate_signature(signer
, data
, &mac
);
202 if (mac
.len
!= signer
->get_block_size(signer
))
206 if (!memeq(vector
->mac
, mac
.ptr
, mac
.len
))
210 /* signature to existing buffer */
211 memset(mac
.ptr
, 0, mac
.len
);
212 signer
->get_signature(signer
, data
, mac
.ptr
);
213 if (!memeq(vector
->mac
, mac
.ptr
, mac
.len
))
217 /* signature verification, good case */
218 if (!signer
->verify_signature(signer
, data
, mac
))
222 /* signature verification, bad case */
223 *(mac
.ptr
+ mac
.len
- 1) += 1;
224 if (signer
->verify_signature(signer
, data
, mac
))
228 /* signature to existing buffer, using append mode */
231 memset(mac
.ptr
, 0, mac
.len
);
232 signer
->allocate_signature(signer
, chunk_create(data
.ptr
, 1), NULL
);
233 signer
->get_signature(signer
, chunk_create(data
.ptr
+ 1, 1), NULL
);
234 signer
->get_signature(signer
, chunk_skip(data
, 2), mac
.ptr
);
235 if (!memeq(vector
->mac
, mac
.ptr
, mac
.len
))
242 signer
->destroy(signer
);
245 DBG1("test vector %d failed, %N disabled",
246 tested
, integrity_algorithm_names
, alg
);
249 DBG2(" %N test vector %d successful",
250 integrity_algorithm_names
, alg
, tested
);
252 enumerator
->destroy(enumerator
);
255 DBG1("no test vectors found for %N%s",
256 integrity_algorithm_names
, alg
,
257 this->required ?
", disabled" : "");
258 return !this->required
;
262 DBG2("successfully tested %d test vectors for %N",
263 tested
, integrity_algorithm_names
, alg
);
269 * Implementation of hasher_t.test_hasher
271 static bool test_hasher(private_crypto_tester_t
*this, hash_algorithm_t alg
,
272 hasher_constructor_t create
)
274 enumerator_t
*enumerator
;
275 hasher_test_vector_t
*vector
;
279 enumerator
= this->hasher
->create_enumerator(this->hasher
);
280 while (enumerator
->enumerate(enumerator
, &vector
))
285 if (vector
->alg
!= alg
)
291 hasher
= create(alg
);
294 DBG1("creating instance failed, %N disabled",
295 hash_algorithm_names
, alg
);
303 data
= chunk_create(vector
->data
, vector
->len
);
304 hasher
->allocate_hash(hasher
, data
, &hash
);
305 if (hash
.len
!= hasher
->get_hash_size(hasher
))
309 if (!memeq(vector
->hash
, hash
.ptr
, hash
.len
))
313 /* hash to existing buffer */
314 memset(hash
.ptr
, 0, hash
.len
);
315 hasher
->get_hash(hasher
, data
, hash
.ptr
);
316 if (!memeq(vector
->hash
, hash
.ptr
, hash
.len
))
320 /* hasher to existing buffer, using append mode */
323 memset(hash
.ptr
, 0, hash
.len
);
324 hasher
->allocate_hash(hasher
, chunk_create(data
.ptr
, 1), NULL
);
325 hasher
->get_hash(hasher
, chunk_create(data
.ptr
+ 1, 1), NULL
);
326 hasher
->get_hash(hasher
, chunk_skip(data
, 2), hash
.ptr
);
327 if (!memeq(vector
->hash
, hash
.ptr
, hash
.len
))
334 hasher
->destroy(hasher
);
337 DBG1("test vector %d failed, %N disabled",
338 tested
, hash_algorithm_names
, alg
);
341 DBG2("%N test vector %d successful",
342 hash_algorithm_names
, alg
, tested
);
344 enumerator
->destroy(enumerator
);
347 DBG1("no test vectors found for %N%s",
348 hash_algorithm_names
, alg
,
349 this->required ?
", disabled" : "");
350 return !this->required
;
354 DBG2("successfully tested %d test vectors for %N",
355 tested
, hash_algorithm_names
, alg
);
361 * Implementation of crypto_tester_t.test_prf
363 static bool test_prf(private_crypto_tester_t
*this,
364 pseudo_random_function_t alg
, prf_constructor_t create
)
366 enumerator_t
*enumerator
;
367 prf_test_vector_t
*vector
;
371 enumerator
= this->prf
->create_enumerator(this->prf
);
372 while (enumerator
->enumerate(enumerator
, &vector
))
375 chunk_t key
, seed
, out
;
377 if (vector
->alg
!= alg
)
386 DBG1("creating instance failed, %N disabled",
387 pseudo_random_function_names
, alg
);
394 key
= chunk_create(vector
->key
, vector
->key_size
);
395 prf
->set_key(prf
, key
);
397 /* allocated bytes */
398 seed
= chunk_create(vector
->seed
, vector
->len
);
399 prf
->allocate_bytes(prf
, seed
, &out
);
400 if (out
.len
!= prf
->get_block_size(prf
))
404 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
408 /* bytes to existing buffer */
409 memset(out
.ptr
, 0, out
.len
);
410 prf
->get_bytes(prf
, seed
, out
.ptr
);
411 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
415 /* bytes to existing buffer, using append mode */
418 memset(out
.ptr
, 0, out
.len
);
419 prf
->allocate_bytes(prf
, chunk_create(seed
.ptr
, 1), NULL
);
420 prf
->get_bytes(prf
, chunk_create(seed
.ptr
+ 1, 1), NULL
);
421 prf
->get_bytes(prf
, chunk_skip(seed
, 2), out
.ptr
);
422 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
432 DBG1("test vector %d failed, %N disabled",
433 tested
, pseudo_random_function_names
, alg
);
436 DBG2("%N test vector %d successful",
437 pseudo_random_function_names
, alg
, tested
);
439 enumerator
->destroy(enumerator
);
442 DBG1("no test vectors found for %N%s",
443 pseudo_random_function_names
, alg
,
444 this->required ?
", disabled" : "");
445 return !this->required
;
449 DBG2("successfully tested %d testvectors for %N",
450 tested
, pseudo_random_function_names
, alg
);
456 * Implementation of crypto_tester_t.test_rng
458 static bool test_rng(private_crypto_tester_t
*this, rng_quality_t quality
,
459 rng_constructor_t create
)
461 enumerator_t
*enumerator
;
462 rng_test_vector_t
*vector
;
466 if (!this->rng_true
&& quality
== RNG_TRUE
)
468 DBG1("skipping %N test, disabled by config", rng_quality_names
, quality
);
472 enumerator
= this->rng
->create_enumerator(this->rng
);
473 while (enumerator
->enumerate(enumerator
, &vector
))
478 if (vector
->quality
!= quality
)
484 rng
= create(quality
);
487 DBG1("creating instance failed, %N disabled",
488 rng_quality_names
, quality
);
495 /* allocated bytes */
496 rng
->allocate_bytes(rng
, vector
->len
, &data
);
497 if (data
.len
!= vector
->len
)
501 if (!vector
->test(vector
->user
, data
))
505 /* bytes to existing buffer */
506 memset(data
.ptr
, 0, data
.len
);
507 rng
->get_bytes(rng
, vector
->len
, data
.ptr
);
508 if (!vector
->test(vector
->user
, data
))
517 DBG1("test vector %d failed, %N disabled",
518 tested
, rng_quality_names
, quality
);
521 DBG2("%N test vector %d successful", rng_quality_names
, quality
, tested
);
523 enumerator
->destroy(enumerator
);
526 DBG1("no test vectors found for %N%s",
527 rng_quality_names
, quality
, this->required ?
", disabled" : "");
528 return !this->required
;
532 DBG2("successfully tested %d testvectors for %N",
533 tested
, rng_quality_names
, quality
);
539 * Implementation of crypter_tester_t.add_crypter_vector
541 static void add_crypter_vector(private_crypto_tester_t
*this,
542 crypter_test_vector_t
*vector
)
544 this->crypter
->insert_last(this->crypter
, vector
);
548 * Implementation of crypter_tester_t.add_signer_vector
550 static void add_signer_vector(private_crypto_tester_t
*this,
551 signer_test_vector_t
*vector
)
553 this->signer
->insert_last(this->signer
, vector
);
557 * Implementation of crypter_tester_t.add_hasher_vector
559 static void add_hasher_vector(private_crypto_tester_t
*this,
560 hasher_test_vector_t
*vector
)
562 this->hasher
->insert_last(this->hasher
, vector
);
566 * Implementation of crypter_tester_t.add_prf_vector
568 static void add_prf_vector(private_crypto_tester_t
*this,
569 prf_test_vector_t
*vector
)
571 this->prf
->insert_last(this->prf
, vector
);
575 * Implementation of crypter_tester_t.add_rng_vector
577 static void add_rng_vector(private_crypto_tester_t
*this,
578 rng_test_vector_t
*vector
)
580 this->rng
->insert_last(this->rng
, vector
);
584 * Implementation of crypto_tester_t.destroy.
586 static void destroy(private_crypto_tester_t
*this)
588 this->crypter
->destroy(this->crypter
);
589 this->signer
->destroy(this->signer
);
590 this->hasher
->destroy(this->hasher
);
591 this->prf
->destroy(this->prf
);
592 this->rng
->destroy(this->rng
);
599 crypto_tester_t
*crypto_tester_create()
601 private_crypto_tester_t
*this = malloc_thing(private_crypto_tester_t
);
603 this->public.test_crypter
= (bool(*)(crypto_tester_t
*, encryption_algorithm_t alg
,size_t key_size
, crypter_constructor_t create
))test_crypter
;
604 this->public.test_signer
= (bool(*)(crypto_tester_t
*, integrity_algorithm_t alg
, signer_constructor_t create
))test_signer
;
605 this->public.test_hasher
= (bool(*)(crypto_tester_t
*, hash_algorithm_t alg
, hasher_constructor_t create
))test_hasher
;
606 this->public.test_prf
= (bool(*)(crypto_tester_t
*, pseudo_random_function_t alg
, prf_constructor_t create
))test_prf
;
607 this->public.test_rng
= (bool(*)(crypto_tester_t
*, rng_quality_t quality
, rng_constructor_t create
))test_rng
;
608 this->public.add_crypter_vector
= (void(*)(crypto_tester_t
*, crypter_test_vector_t
*vector
))add_crypter_vector
;
609 this->public.add_signer_vector
= (void(*)(crypto_tester_t
*, signer_test_vector_t
*vector
))add_signer_vector
;
610 this->public.add_hasher_vector
= (void(*)(crypto_tester_t
*, hasher_test_vector_t
*vector
))add_hasher_vector
;
611 this->public.add_prf_vector
= (void(*)(crypto_tester_t
*, prf_test_vector_t
*vector
))add_prf_vector
;
612 this->public.add_rng_vector
= (void(*)(crypto_tester_t
*, rng_test_vector_t
*vector
))add_rng_vector
;
613 this->public.destroy
= (void(*)(crypto_tester_t
*))destroy
;
615 this->crypter
= linked_list_create();
616 this->signer
= linked_list_create();
617 this->hasher
= linked_list_create();
618 this->prf
= linked_list_create();
619 this->rng
= linked_list_create();
621 this->required
= lib
->settings
->get_bool(lib
->settings
,
622 "libstrongswan.crypto.test.required", FALSE
);
623 this->rng_true
= lib
->settings
->get_bool(lib
->settings
,
624 "libstrongswan.crypto.test.rng_true", FALSE
);
626 return &this->public;