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("disabled %N: test vector %d failed",
140 encryption_algorithm_names
, alg
, tested
);
144 enumerator
->destroy(enumerator
);
147 DBG1("%s %N: no test vectors found",
148 this->required ?
"disabled" : "enabled ",
149 encryption_algorithm_names
, alg
);
150 return !this->required
;
154 DBG1("enabled %N: successfully passed %d test vectors",
155 encryption_algorithm_names
, alg
, tested
);
161 * Implementation of crypto_tester_t.test_signer
163 static bool test_signer(private_crypto_tester_t
*this,
164 integrity_algorithm_t alg
, signer_constructor_t create
)
166 enumerator_t
*enumerator
;
167 signer_test_vector_t
*vector
;
171 enumerator
= this->signer
->create_enumerator(this->signer
);
172 while (enumerator
->enumerate(enumerator
, &vector
))
175 chunk_t key
, data
, mac
;
177 if (vector
->alg
!= alg
)
183 signer
= create(alg
);
186 DBG1("disabled %N: creating instance failed",
187 integrity_algorithm_names
, alg
);
194 key
= chunk_create(vector
->key
, signer
->get_key_size(signer
));
195 signer
->set_key(signer
, key
);
197 /* allocated signature */
198 data
= chunk_create(vector
->data
, vector
->len
);
199 signer
->allocate_signature(signer
, data
, &mac
);
200 if (mac
.len
!= signer
->get_block_size(signer
))
204 if (!memeq(vector
->mac
, mac
.ptr
, mac
.len
))
208 /* signature to existing buffer */
209 memset(mac
.ptr
, 0, mac
.len
);
210 signer
->get_signature(signer
, data
, mac
.ptr
);
211 if (!memeq(vector
->mac
, mac
.ptr
, mac
.len
))
215 /* signature verification, good case */
216 if (!signer
->verify_signature(signer
, data
, mac
))
220 /* signature verification, bad case */
221 *(mac
.ptr
+ mac
.len
- 1) += 1;
222 if (signer
->verify_signature(signer
, data
, mac
))
226 /* signature to existing buffer, using append mode */
229 memset(mac
.ptr
, 0, mac
.len
);
230 signer
->allocate_signature(signer
, chunk_create(data
.ptr
, 1), NULL
);
231 signer
->get_signature(signer
, chunk_create(data
.ptr
+ 1, 1), NULL
);
232 signer
->get_signature(signer
, chunk_skip(data
, 2), mac
.ptr
);
233 if (!memeq(vector
->mac
, mac
.ptr
, mac
.len
))
240 signer
->destroy(signer
);
243 DBG1("disabled %N: test vector %d failed",
244 integrity_algorithm_names
, alg
, tested
);
248 enumerator
->destroy(enumerator
);
251 DBG1("%s %N: no test vectors found",
252 this->required ?
"disabled" : "enabled ",
253 integrity_algorithm_names
, alg
);
254 return !this->required
;
258 DBG1("enabled %N: successfully passed %d test vectors",
259 integrity_algorithm_names
, alg
, tested
);
265 * Implementation of hasher_t.test_hasher
267 static bool test_hasher(private_crypto_tester_t
*this, hash_algorithm_t alg
,
268 hasher_constructor_t create
)
270 enumerator_t
*enumerator
;
271 hasher_test_vector_t
*vector
;
275 enumerator
= this->hasher
->create_enumerator(this->hasher
);
276 while (enumerator
->enumerate(enumerator
, &vector
))
281 if (vector
->alg
!= alg
)
287 hasher
= create(alg
);
290 DBG1("disabled %N: creating instance failed",
291 hash_algorithm_names
, alg
);
299 data
= chunk_create(vector
->data
, vector
->len
);
300 hasher
->allocate_hash(hasher
, data
, &hash
);
301 if (hash
.len
!= hasher
->get_hash_size(hasher
))
305 if (!memeq(vector
->hash
, hash
.ptr
, hash
.len
))
309 /* hash to existing buffer */
310 memset(hash
.ptr
, 0, hash
.len
);
311 hasher
->get_hash(hasher
, data
, hash
.ptr
);
312 if (!memeq(vector
->hash
, hash
.ptr
, hash
.len
))
316 /* hasher to existing buffer, using append mode */
319 memset(hash
.ptr
, 0, hash
.len
);
320 hasher
->allocate_hash(hasher
, chunk_create(data
.ptr
, 1), NULL
);
321 hasher
->get_hash(hasher
, chunk_create(data
.ptr
+ 1, 1), NULL
);
322 hasher
->get_hash(hasher
, chunk_skip(data
, 2), hash
.ptr
);
323 if (!memeq(vector
->hash
, hash
.ptr
, hash
.len
))
330 hasher
->destroy(hasher
);
333 DBG1("disabled %N: test vector %d failed",
334 hash_algorithm_names
, alg
), tested
;
338 enumerator
->destroy(enumerator
);
341 DBG1("%s %N: no test vectors found",
342 this->required ?
"disabled" : "enabled ",
343 hash_algorithm_names
, alg
);
344 return !this->required
;
348 DBG1("enabled %N: successfully passed %d test vectors",
349 hash_algorithm_names
, alg
, tested
);
355 * Implementation of crypto_tester_t.test_prf
357 static bool test_prf(private_crypto_tester_t
*this,
358 pseudo_random_function_t alg
, prf_constructor_t create
)
360 enumerator_t
*enumerator
;
361 prf_test_vector_t
*vector
;
365 enumerator
= this->prf
->create_enumerator(this->prf
);
366 while (enumerator
->enumerate(enumerator
, &vector
))
369 chunk_t key
, seed
, out
;
371 if (vector
->alg
!= alg
)
380 DBG1("disabled %N: creating instance failed",
381 pseudo_random_function_names
, alg
);
388 key
= chunk_create(vector
->key
, vector
->key_size
);
389 prf
->set_key(prf
, key
);
391 /* allocated bytes */
392 seed
= chunk_create(vector
->seed
, vector
->len
);
393 prf
->allocate_bytes(prf
, seed
, &out
);
394 if (out
.len
!= prf
->get_block_size(prf
))
398 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
402 /* bytes to existing buffer */
403 memset(out
.ptr
, 0, out
.len
);
404 if (vector
->stateful
)
406 prf
->set_key(prf
, key
);
408 prf
->get_bytes(prf
, seed
, out
.ptr
);
409 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
413 /* bytes to existing buffer, using append mode */
416 memset(out
.ptr
, 0, out
.len
);
417 if (vector
->stateful
)
419 prf
->set_key(prf
, key
);
421 prf
->allocate_bytes(prf
, chunk_create(seed
.ptr
, 1), NULL
);
422 prf
->get_bytes(prf
, chunk_create(seed
.ptr
+ 1, 1), NULL
);
423 prf
->get_bytes(prf
, chunk_skip(seed
, 2), out
.ptr
);
424 if (!memeq(vector
->out
, out
.ptr
, out
.len
))
434 DBG1("disabled %N: test vector %d failed",
435 pseudo_random_function_names
, alg
, tested
);
439 enumerator
->destroy(enumerator
);
442 DBG1("%s %N: no test vectors found",
443 this->required ?
"disabled" : "enabled ",
444 pseudo_random_function_names
, alg
);
445 return !this->required
;
449 DBG1("enabled %N: successfully passed %d test vectors",
450 pseudo_random_function_names
, alg
, tested
);
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("enabled %N: skipping test (disabled by config)",
469 rng_quality_names
, quality
);
473 enumerator
= this->rng
->create_enumerator(this->rng
);
474 while (enumerator
->enumerate(enumerator
, &vector
))
479 if (vector
->quality
!= quality
)
485 rng
= create(quality
);
488 DBG1("disabled %N: creating instance failed",
489 rng_quality_names
, quality
);
496 /* allocated bytes */
497 rng
->allocate_bytes(rng
, vector
->len
, &data
);
498 if (data
.len
!= vector
->len
)
502 if (!vector
->test(vector
->user
, data
))
506 /* bytes to existing buffer */
507 memset(data
.ptr
, 0, data
.len
);
508 rng
->get_bytes(rng
, vector
->len
, data
.ptr
);
509 if (!vector
->test(vector
->user
, data
))
518 DBG1("disabled %N: test vector %d failed",
519 rng_quality_names
, quality
, tested
);
523 enumerator
->destroy(enumerator
);
526 DBG1("%s %N: no test vectors found",
527 this->required ?
", disabled" : "enabled ",
528 rng_quality_names
, quality
);
529 return !this->required
;
533 DBG1("enabled %N: successfully passed %d test vectors",
534 rng_quality_names
, quality
, tested
);
540 * Implementation of crypter_tester_t.add_crypter_vector
542 static void add_crypter_vector(private_crypto_tester_t
*this,
543 crypter_test_vector_t
*vector
)
545 this->crypter
->insert_last(this->crypter
, vector
);
549 * Implementation of crypter_tester_t.add_signer_vector
551 static void add_signer_vector(private_crypto_tester_t
*this,
552 signer_test_vector_t
*vector
)
554 this->signer
->insert_last(this->signer
, vector
);
558 * Implementation of crypter_tester_t.add_hasher_vector
560 static void add_hasher_vector(private_crypto_tester_t
*this,
561 hasher_test_vector_t
*vector
)
563 this->hasher
->insert_last(this->hasher
, vector
);
567 * Implementation of crypter_tester_t.add_prf_vector
569 static void add_prf_vector(private_crypto_tester_t
*this,
570 prf_test_vector_t
*vector
)
572 this->prf
->insert_last(this->prf
, vector
);
576 * Implementation of crypter_tester_t.add_rng_vector
578 static void add_rng_vector(private_crypto_tester_t
*this,
579 rng_test_vector_t
*vector
)
581 this->rng
->insert_last(this->rng
, vector
);
585 * Implementation of crypto_tester_t.destroy.
587 static void destroy(private_crypto_tester_t
*this)
589 this->crypter
->destroy(this->crypter
);
590 this->signer
->destroy(this->signer
);
591 this->hasher
->destroy(this->hasher
);
592 this->prf
->destroy(this->prf
);
593 this->rng
->destroy(this->rng
);
600 crypto_tester_t
*crypto_tester_create()
602 private_crypto_tester_t
*this = malloc_thing(private_crypto_tester_t
);
604 this->public.test_crypter
= (bool(*)(crypto_tester_t
*, encryption_algorithm_t alg
,size_t key_size
, crypter_constructor_t create
))test_crypter
;
605 this->public.test_signer
= (bool(*)(crypto_tester_t
*, integrity_algorithm_t alg
, signer_constructor_t create
))test_signer
;
606 this->public.test_hasher
= (bool(*)(crypto_tester_t
*, hash_algorithm_t alg
, hasher_constructor_t create
))test_hasher
;
607 this->public.test_prf
= (bool(*)(crypto_tester_t
*, pseudo_random_function_t alg
, prf_constructor_t create
))test_prf
;
608 this->public.test_rng
= (bool(*)(crypto_tester_t
*, rng_quality_t quality
, rng_constructor_t create
))test_rng
;
609 this->public.add_crypter_vector
= (void(*)(crypto_tester_t
*, crypter_test_vector_t
*vector
))add_crypter_vector
;
610 this->public.add_signer_vector
= (void(*)(crypto_tester_t
*, signer_test_vector_t
*vector
))add_signer_vector
;
611 this->public.add_hasher_vector
= (void(*)(crypto_tester_t
*, hasher_test_vector_t
*vector
))add_hasher_vector
;
612 this->public.add_prf_vector
= (void(*)(crypto_tester_t
*, prf_test_vector_t
*vector
))add_prf_vector
;
613 this->public.add_rng_vector
= (void(*)(crypto_tester_t
*, rng_test_vector_t
*vector
))add_rng_vector
;
614 this->public.destroy
= (void(*)(crypto_tester_t
*))destroy
;
616 this->crypter
= linked_list_create();
617 this->signer
= linked_list_create();
618 this->hasher
= linked_list_create();
619 this->prf
= linked_list_create();
620 this->rng
= linked_list_create();
622 this->required
= lib
->settings
->get_bool(lib
->settings
,
623 "libstrongswan.crypto_test.required", FALSE
);
624 this->rng_true
= lib
->settings
->get_bool(lib
->settings
,
625 "libstrongswan.crypto_test.rng_true", FALSE
);
627 return &this->public;