removed superfluous print argument
[strongswan.git] / src / libstrongswan / crypto / crypto_tester.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
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>.
9 *
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
13 * for more details.
14 */
15
16 #include "crypto_tester.h"
17
18 #include <debug.h>
19 #include <utils/linked_list.h>
20
21 typedef struct private_crypto_tester_t private_crypto_tester_t;
22
23 /**
24 * Private data of an crypto_tester_t object.
25 */
26 struct private_crypto_tester_t {
27
28 /**
29 * Public crypto_tester_t interface.
30 */
31 crypto_tester_t public;
32
33 /**
34 * List of crypter test vectors
35 */
36 linked_list_t *crypter;
37
38 /**
39 * List of signer test vectors
40 */
41 linked_list_t *signer;
42
43 /**
44 * List of hasher test vectors
45 */
46 linked_list_t *hasher;
47
48 /**
49 * List of PRF test vectors
50 */
51 linked_list_t *prf;
52
53 /**
54 * List of RNG test vectors
55 */
56 linked_list_t *rng;
57
58 /**
59 * Is a test vector required to pass a test?
60 */
61 bool required;
62
63 /**
64 * should we run RNG_TRUE tests? Enough entropy?
65 */
66 bool rng_true;
67 };
68
69 /**
70 * Implementation of crypto_tester_t.test_crypter
71 */
72 static bool test_crypter(private_crypto_tester_t *this,
73 encryption_algorithm_t alg, size_t key_size, crypter_constructor_t create)
74 {
75 enumerator_t *enumerator;
76 crypter_test_vector_t *vector;
77 bool failed = FALSE;
78 u_int tested = 0;
79
80 enumerator = this->crypter->create_enumerator(this->crypter);
81 while (enumerator->enumerate(enumerator, &vector))
82 {
83 crypter_t *crypter;
84 chunk_t key, plain, cipher, iv;
85
86 if (vector->alg != alg)
87 {
88 continue;
89 }
90 if (key_size && key_size != vector->key_size)
91 { /* test only vectors with a specific key size, if key size given */
92 continue;
93 }
94 crypter = create(alg, vector->key_size);
95 if (!crypter)
96 { /* key size not supported... */
97 continue;
98 }
99
100 failed = FALSE;
101 tested++;
102
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));
106
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))
111 {
112 failed = TRUE;
113 }
114 /* inline decryption */
115 crypter->decrypt(crypter, cipher, iv, NULL);
116 if (!memeq(vector->plain, cipher.ptr, cipher.len))
117 {
118 failed = TRUE;
119 }
120 free(cipher.ptr);
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))
125 {
126 failed = TRUE;
127 }
128 /* inline encryption */
129 crypter->encrypt(crypter, plain, iv, NULL);
130 if (!memeq(vector->cipher, plain.ptr, plain.len))
131 {
132 failed = TRUE;
133 }
134 free(plain.ptr);
135
136 crypter->destroy(crypter);
137 if (failed)
138 {
139 DBG1("disabled %N: test vector %d failed",
140 encryption_algorithm_names, alg, tested);
141 break;
142 }
143 }
144 enumerator->destroy(enumerator);
145 if (!tested)
146 {
147 DBG1("%s %N: no test vectors found",
148 this->required ? "disabled" : "enabled ",
149 encryption_algorithm_names, alg);
150 return !this->required;
151 }
152 if (!failed)
153 {
154 DBG1("enabled %N: successfully passed %d test vectors",
155 encryption_algorithm_names, alg, tested);
156 }
157 return !failed;
158 }
159
160 /**
161 * Implementation of crypto_tester_t.test_signer
162 */
163 static bool test_signer(private_crypto_tester_t *this,
164 integrity_algorithm_t alg, signer_constructor_t create)
165 {
166 enumerator_t *enumerator;
167 signer_test_vector_t *vector;
168 bool failed = FALSE;
169 u_int tested = 0;
170
171 enumerator = this->signer->create_enumerator(this->signer);
172 while (enumerator->enumerate(enumerator, &vector))
173 {
174 signer_t *signer;
175 chunk_t key, data, mac;
176
177 if (vector->alg != alg)
178 {
179 continue;
180 }
181
182 tested++;
183 signer = create(alg);
184 if (!signer)
185 {
186 DBG1("disabled %N: creating instance failed",
187 integrity_algorithm_names, alg);
188 failed = TRUE;
189 break;
190 }
191
192 failed = FALSE;
193
194 key = chunk_create(vector->key, signer->get_key_size(signer));
195 signer->set_key(signer, key);
196
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))
201 {
202 failed = TRUE;
203 }
204 if (!memeq(vector->mac, mac.ptr, mac.len))
205 {
206 failed = TRUE;
207 }
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))
212 {
213 failed = TRUE;
214 }
215 /* signature verification, good case */
216 if (!signer->verify_signature(signer, data, mac))
217 {
218 failed = TRUE;
219 }
220 /* signature verification, bad case */
221 *(mac.ptr + mac.len - 1) += 1;
222 if (signer->verify_signature(signer, data, mac))
223 {
224 failed = TRUE;
225 }
226 /* signature to existing buffer, using append mode */
227 if (data.len > 2)
228 {
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))
234 {
235 failed = TRUE;
236 }
237 }
238 free(mac.ptr);
239
240 signer->destroy(signer);
241 if (failed)
242 {
243 DBG1("disabled %N: test vector %d failed",
244 integrity_algorithm_names, alg, tested);
245 break;
246 }
247 }
248 enumerator->destroy(enumerator);
249 if (!tested)
250 {
251 DBG1("%s %N: no test vectors found",
252 this->required ? "disabled" : "enabled ",
253 integrity_algorithm_names, alg);
254 return !this->required;
255 }
256 if (!failed)
257 {
258 DBG1("enabled %N: successfully passed %d test vectors",
259 integrity_algorithm_names, alg, tested);
260 }
261 return !failed;
262 }
263
264 /**
265 * Implementation of hasher_t.test_hasher
266 */
267 static bool test_hasher(private_crypto_tester_t *this, hash_algorithm_t alg,
268 hasher_constructor_t create)
269 {
270 enumerator_t *enumerator;
271 hasher_test_vector_t *vector;
272 bool failed = FALSE;
273 u_int tested = 0;
274
275 enumerator = this->hasher->create_enumerator(this->hasher);
276 while (enumerator->enumerate(enumerator, &vector))
277 {
278 hasher_t *hasher;
279 chunk_t data, hash;
280
281 if (vector->alg != alg)
282 {
283 continue;
284 }
285
286 tested++;
287 hasher = create(alg);
288 if (!hasher)
289 {
290 DBG1("disabled %N: creating instance failed",
291 hash_algorithm_names, alg);
292 failed = TRUE;
293 break;
294 }
295
296 failed = FALSE;
297
298 /* allocated hash */
299 data = chunk_create(vector->data, vector->len);
300 hasher->allocate_hash(hasher, data, &hash);
301 if (hash.len != hasher->get_hash_size(hasher))
302 {
303 failed = TRUE;
304 }
305 if (!memeq(vector->hash, hash.ptr, hash.len))
306 {
307 failed = TRUE;
308 }
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))
313 {
314 failed = TRUE;
315 }
316 /* hasher to existing buffer, using append mode */
317 if (data.len > 2)
318 {
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))
324 {
325 failed = TRUE;
326 }
327 }
328 free(hash.ptr);
329
330 hasher->destroy(hasher);
331 if (failed)
332 {
333 DBG1("disabled %N: test vector %d failed",
334 hash_algorithm_names, alg), tested;
335 break;
336 }
337 }
338 enumerator->destroy(enumerator);
339 if (!tested)
340 {
341 DBG1("%s %N: no test vectors found",
342 this->required ? "disabled" : "enabled ",
343 hash_algorithm_names, alg);
344 return !this->required;
345 }
346 if (!failed)
347 {
348 DBG1("enabled %N: successfully passed %d test vectors",
349 hash_algorithm_names, alg, tested);
350 }
351 return !failed;
352 }
353
354 /**
355 * Implementation of crypto_tester_t.test_prf
356 */
357 static bool test_prf(private_crypto_tester_t *this,
358 pseudo_random_function_t alg, prf_constructor_t create)
359 {
360 enumerator_t *enumerator;
361 prf_test_vector_t *vector;
362 bool failed = FALSE;
363 u_int tested = 0;
364
365 enumerator = this->prf->create_enumerator(this->prf);
366 while (enumerator->enumerate(enumerator, &vector))
367 {
368 prf_t *prf;
369 chunk_t key, seed, out;
370
371 if (vector->alg != alg)
372 {
373 continue;
374 }
375
376 tested++;
377 prf = create(alg);
378 if (!prf)
379 {
380 DBG1("disabled %N: creating instance failed",
381 pseudo_random_function_names, alg);
382 failed = TRUE;
383 break;
384 }
385
386 failed = FALSE;
387
388 key = chunk_create(vector->key, vector->key_size);
389 prf->set_key(prf, key);
390
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))
395 {
396 failed = TRUE;
397 }
398 if (!memeq(vector->out, out.ptr, out.len))
399 {
400 failed = TRUE;
401 }
402 /* bytes to existing buffer */
403 memset(out.ptr, 0, out.len);
404 if (vector->stateful)
405 {
406 prf->set_key(prf, key);
407 }
408 prf->get_bytes(prf, seed, out.ptr);
409 if (!memeq(vector->out, out.ptr, out.len))
410 {
411 failed = TRUE;
412 }
413 /* bytes to existing buffer, using append mode */
414 if (seed.len > 2)
415 {
416 memset(out.ptr, 0, out.len);
417 if (vector->stateful)
418 {
419 prf->set_key(prf, key);
420 }
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))
425 {
426 failed = TRUE;
427 }
428 }
429 free(out.ptr);
430
431 prf->destroy(prf);
432 if (failed)
433 {
434 DBG1("disabled %N: test vector %d failed",
435 pseudo_random_function_names, alg, tested);
436 break;
437 }
438 }
439 enumerator->destroy(enumerator);
440 if (!tested)
441 {
442 DBG1("%s %N: no test vectors found",
443 this->required ? "disabled" : "enabled ",
444 pseudo_random_function_names, alg);
445 return !this->required;
446 }
447 if (!failed)
448 {
449 DBG1("enabled %N: successfully passed %d test vectors",
450 pseudo_random_function_names, alg, tested);
451 }
452 return !failed;
453 }
454
455 /**
456 * Implementation of crypto_tester_t.test_rng
457 */
458 static bool test_rng(private_crypto_tester_t *this, rng_quality_t quality,
459 rng_constructor_t create)
460 {
461 enumerator_t *enumerator;
462 rng_test_vector_t *vector;
463 bool failed = FALSE;
464 u_int tested = 0;
465
466 if (!this->rng_true && quality == RNG_TRUE)
467 {
468 DBG1("enabled %N: skipping test (disabled by config)",
469 rng_quality_names, quality);
470 return TRUE;
471 }
472
473 enumerator = this->rng->create_enumerator(this->rng);
474 while (enumerator->enumerate(enumerator, &vector))
475 {
476 rng_t *rng;
477 chunk_t data;
478
479 if (vector->quality != quality)
480 {
481 continue;
482 }
483
484 tested++;
485 rng = create(quality);
486 if (!rng)
487 {
488 DBG1("disabled %N: creating instance failed",
489 rng_quality_names, quality);
490 failed = TRUE;
491 break;
492 }
493
494 failed = FALSE;
495
496 /* allocated bytes */
497 rng->allocate_bytes(rng, vector->len, &data);
498 if (data.len != vector->len)
499 {
500 failed = TRUE;
501 }
502 if (!vector->test(vector->user, data))
503 {
504 failed = TRUE;
505 }
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))
510 {
511 failed = TRUE;
512 }
513 free(data.ptr);
514
515 rng->destroy(rng);
516 if (failed)
517 {
518 DBG1("disabled %N: test vector %d failed",
519 rng_quality_names, quality, tested);
520 break;
521 }
522 }
523 enumerator->destroy(enumerator);
524 if (!tested)
525 {
526 DBG1("%s %N: no test vectors found",
527 this->required ? ", disabled" : "enabled ",
528 rng_quality_names, quality);
529 return !this->required;
530 }
531 if (!failed)
532 {
533 DBG1("enabled %N: successfully passed %d test vectors",
534 rng_quality_names, quality, tested);
535 }
536 return !failed;
537 }
538
539 /**
540 * Implementation of crypter_tester_t.add_crypter_vector
541 */
542 static void add_crypter_vector(private_crypto_tester_t *this,
543 crypter_test_vector_t *vector)
544 {
545 this->crypter->insert_last(this->crypter, vector);
546 }
547
548 /**
549 * Implementation of crypter_tester_t.add_signer_vector
550 */
551 static void add_signer_vector(private_crypto_tester_t *this,
552 signer_test_vector_t *vector)
553 {
554 this->signer->insert_last(this->signer, vector);
555 }
556
557 /**
558 * Implementation of crypter_tester_t.add_hasher_vector
559 */
560 static void add_hasher_vector(private_crypto_tester_t *this,
561 hasher_test_vector_t *vector)
562 {
563 this->hasher->insert_last(this->hasher, vector);
564 }
565
566 /**
567 * Implementation of crypter_tester_t.add_prf_vector
568 */
569 static void add_prf_vector(private_crypto_tester_t *this,
570 prf_test_vector_t *vector)
571 {
572 this->prf->insert_last(this->prf, vector);
573 }
574
575 /**
576 * Implementation of crypter_tester_t.add_rng_vector
577 */
578 static void add_rng_vector(private_crypto_tester_t *this,
579 rng_test_vector_t *vector)
580 {
581 this->rng->insert_last(this->rng, vector);
582 }
583
584 /**
585 * Implementation of crypto_tester_t.destroy.
586 */
587 static void destroy(private_crypto_tester_t *this)
588 {
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);
594 free(this);
595 }
596
597 /**
598 * See header
599 */
600 crypto_tester_t *crypto_tester_create()
601 {
602 private_crypto_tester_t *this = malloc_thing(private_crypto_tester_t);
603
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;
615
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();
621
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);
626
627 return &this->public;
628 }
629