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