921cff610c262aad4c3e0f1cb1b4f44beb108543
[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("test vector %d failed, %N disabled",
140 tested, encryption_algorithm_names, alg);
141 break;
142 }
143 DBG2("%N test vector %d successful",
144 encryption_algorithm_names, alg, tested);
145 }
146 enumerator->destroy(enumerator);
147 if (!tested)
148 {
149 DBG1("no test vectors found for %N%s",
150 encryption_algorithm_names, alg,
151 this->required ? ", disabled" : "");
152 return !this->required;
153 }
154 if (!failed)
155 {
156 DBG2("successfully tested %d test vectors for %N",
157 tested, encryption_algorithm_names, alg);
158 }
159 return !failed;
160 }
161
162 /**
163 * Implementation of crypto_tester_t.test_signer
164 */
165 static bool test_signer(private_crypto_tester_t *this,
166 integrity_algorithm_t alg, signer_constructor_t create)
167 {
168 enumerator_t *enumerator;
169 signer_test_vector_t *vector;
170 bool failed = FALSE;
171 u_int tested = 0;
172
173 enumerator = this->signer->create_enumerator(this->signer);
174 while (enumerator->enumerate(enumerator, &vector))
175 {
176 signer_t *signer;
177 chunk_t key, data, mac;
178
179 if (vector->alg != alg)
180 {
181 continue;
182 }
183
184 tested++;
185 signer = create(alg);
186 if (!signer)
187 {
188 DBG1("creating instance failed, %N disabled",
189 integrity_algorithm_names, alg);
190 failed = TRUE;
191 break;
192 }
193
194 failed = FALSE;
195
196 key = chunk_create(vector->key, signer->get_key_size(signer));
197 signer->set_key(signer, key);
198
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))
203 {
204 failed = TRUE;
205 }
206 if (!memeq(vector->mac, mac.ptr, mac.len))
207 {
208 failed = TRUE;
209 }
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))
214 {
215 failed = TRUE;
216 }
217 /* signature verification, good case */
218 if (!signer->verify_signature(signer, data, mac))
219 {
220 failed = TRUE;
221 }
222 /* signature verification, bad case */
223 *(mac.ptr + mac.len - 1) += 1;
224 if (signer->verify_signature(signer, data, mac))
225 {
226 failed = TRUE;
227 }
228 /* signature to existing buffer, using append mode */
229 if (data.len > 2)
230 {
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))
236 {
237 failed = TRUE;
238 }
239 }
240 free(mac.ptr);
241
242 signer->destroy(signer);
243 if (failed)
244 {
245 DBG1("test vector %d failed, %N disabled",
246 tested, integrity_algorithm_names, alg);
247 break;
248 }
249 DBG2(" %N test vector %d successful",
250 integrity_algorithm_names, alg, tested);
251 }
252 enumerator->destroy(enumerator);
253 if (!tested)
254 {
255 DBG1("no test vectors found for %N%s",
256 integrity_algorithm_names, alg,
257 this->required ? ", disabled" : "");
258 return !this->required;
259 }
260 if (!failed)
261 {
262 DBG2("successfully tested %d test vectors for %N",
263 tested, integrity_algorithm_names, alg);
264 }
265 return !failed;
266 }
267
268 /**
269 * Implementation of hasher_t.test_hasher
270 */
271 static bool test_hasher(private_crypto_tester_t *this, hash_algorithm_t alg,
272 hasher_constructor_t create)
273 {
274 enumerator_t *enumerator;
275 hasher_test_vector_t *vector;
276 bool failed = FALSE;
277 u_int tested = 0;
278
279 enumerator = this->hasher->create_enumerator(this->hasher);
280 while (enumerator->enumerate(enumerator, &vector))
281 {
282 hasher_t *hasher;
283 chunk_t data, hash;
284
285 if (vector->alg != alg)
286 {
287 continue;
288 }
289
290 tested++;
291 hasher = create(alg);
292 if (!hasher)
293 {
294 DBG1("creating instance failed, %N disabled",
295 hash_algorithm_names, alg);
296 failed = TRUE;
297 break;
298 }
299
300 failed = FALSE;
301
302 /* allocated hash */
303 data = chunk_create(vector->data, vector->len);
304 hasher->allocate_hash(hasher, data, &hash);
305 if (hash.len != hasher->get_hash_size(hasher))
306 {
307 failed = TRUE;
308 }
309 if (!memeq(vector->hash, hash.ptr, hash.len))
310 {
311 failed = TRUE;
312 }
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))
317 {
318 failed = TRUE;
319 }
320 /* hasher to existing buffer, using append mode */
321 if (data.len > 2)
322 {
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))
328 {
329 failed = TRUE;
330 }
331 }
332 free(hash.ptr);
333
334 hasher->destroy(hasher);
335 if (failed)
336 {
337 DBG1("test vector %d failed, %N disabled",
338 tested, hash_algorithm_names, alg);
339 break;
340 }
341 DBG2("%N test vector %d successful",
342 hash_algorithm_names, alg, tested);
343 }
344 enumerator->destroy(enumerator);
345 if (!tested)
346 {
347 DBG1("no test vectors found for %N%s",
348 hash_algorithm_names, alg,
349 this->required ? ", disabled" : "");
350 return !this->required;
351 }
352 if (!failed)
353 {
354 DBG2("successfully tested %d test vectors for %N",
355 tested, hash_algorithm_names, alg);
356 }
357 return !failed;
358 }
359
360 /**
361 * Implementation of crypto_tester_t.test_prf
362 */
363 static bool test_prf(private_crypto_tester_t *this,
364 pseudo_random_function_t alg, prf_constructor_t create)
365 {
366 enumerator_t *enumerator;
367 prf_test_vector_t *vector;
368 bool failed = FALSE;
369 u_int tested = 0;
370
371 enumerator = this->prf->create_enumerator(this->prf);
372 while (enumerator->enumerate(enumerator, &vector))
373 {
374 prf_t *prf;
375 chunk_t key, seed, out;
376
377 if (vector->alg != alg)
378 {
379 continue;
380 }
381
382 tested++;
383 prf = create(alg);
384 if (!prf)
385 {
386 DBG1("creating instance failed, %N disabled",
387 pseudo_random_function_names, alg);
388 failed = TRUE;
389 break;
390 }
391
392 failed = FALSE;
393
394 key = chunk_create(vector->key, vector->key_size);
395 prf->set_key(prf, key);
396
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))
401 {
402 failed = TRUE;
403 }
404 if (!memeq(vector->out, out.ptr, out.len))
405 {
406 failed = TRUE;
407 }
408 /* bytes to existing buffer */
409 memset(out.ptr, 0, out.len);
410 if (vector->stateful)
411 {
412 prf->set_key(prf, key);
413 }
414 prf->get_bytes(prf, seed, out.ptr);
415 if (!memeq(vector->out, out.ptr, out.len))
416 {
417 failed = TRUE;
418 }
419 /* bytes to existing buffer, using append mode */
420 if (seed.len > 2)
421 {
422 memset(out.ptr, 0, out.len);
423 if (vector->stateful)
424 {
425 prf->set_key(prf, key);
426 }
427 prf->allocate_bytes(prf, chunk_create(seed.ptr, 1), NULL);
428 prf->get_bytes(prf, chunk_create(seed.ptr + 1, 1), NULL);
429 prf->get_bytes(prf, chunk_skip(seed, 2), out.ptr);
430 if (!memeq(vector->out, out.ptr, out.len))
431 {
432 failed = TRUE;
433 }
434 }
435 free(out.ptr);
436
437 prf->destroy(prf);
438 if (failed)
439 {
440 DBG1("test vector %d failed, %N disabled",
441 tested, pseudo_random_function_names, alg);
442 break;
443 }
444 DBG2("%N test vector %d successful",
445 pseudo_random_function_names, alg, tested);
446 }
447 enumerator->destroy(enumerator);
448 if (!tested)
449 {
450 DBG1("no test vectors found for %N%s",
451 pseudo_random_function_names, alg,
452 this->required ? ", disabled" : "");
453 return !this->required;
454 }
455 if (!failed)
456 {
457 DBG2("successfully tested %d testvectors for %N",
458 tested, pseudo_random_function_names, alg);
459 }
460 return !failed;
461 }
462
463 /**
464 * Implementation of crypto_tester_t.test_rng
465 */
466 static bool test_rng(private_crypto_tester_t *this, rng_quality_t quality,
467 rng_constructor_t create)
468 {
469 enumerator_t *enumerator;
470 rng_test_vector_t *vector;
471 bool failed = FALSE;
472 u_int tested = 0;
473
474 if (!this->rng_true && quality == RNG_TRUE)
475 {
476 DBG1("skipping %N test, disabled by config", rng_quality_names, quality);
477 return TRUE;
478 }
479
480 enumerator = this->rng->create_enumerator(this->rng);
481 while (enumerator->enumerate(enumerator, &vector))
482 {
483 rng_t *rng;
484 chunk_t data;
485
486 if (vector->quality != quality)
487 {
488 continue;
489 }
490
491 tested++;
492 rng = create(quality);
493 if (!rng)
494 {
495 DBG1("creating instance failed, %N disabled",
496 rng_quality_names, quality);
497 failed = TRUE;
498 break;
499 }
500
501 failed = FALSE;
502
503 /* allocated bytes */
504 rng->allocate_bytes(rng, vector->len, &data);
505 if (data.len != vector->len)
506 {
507 failed = TRUE;
508 }
509 if (!vector->test(vector->user, data))
510 {
511 failed = TRUE;
512 }
513 /* bytes to existing buffer */
514 memset(data.ptr, 0, data.len);
515 rng->get_bytes(rng, vector->len, data.ptr);
516 if (!vector->test(vector->user, data))
517 {
518 failed = TRUE;
519 }
520 free(data.ptr);
521
522 rng->destroy(rng);
523 if (failed)
524 {
525 DBG1("test vector %d failed, %N disabled",
526 tested, rng_quality_names, quality);
527 break;
528 }
529 DBG2("%N test vector %d successful", rng_quality_names, quality, tested);
530 }
531 enumerator->destroy(enumerator);
532 if (!tested)
533 {
534 DBG1("no test vectors found for %N%s",
535 rng_quality_names, quality, this->required ? ", disabled" : "");
536 return !this->required;
537 }
538 if (!failed)
539 {
540 DBG2("successfully tested %d testvectors for %N",
541 tested, rng_quality_names, quality);
542 }
543 return !failed;
544 }
545
546 /**
547 * Implementation of crypter_tester_t.add_crypter_vector
548 */
549 static void add_crypter_vector(private_crypto_tester_t *this,
550 crypter_test_vector_t *vector)
551 {
552 this->crypter->insert_last(this->crypter, vector);
553 }
554
555 /**
556 * Implementation of crypter_tester_t.add_signer_vector
557 */
558 static void add_signer_vector(private_crypto_tester_t *this,
559 signer_test_vector_t *vector)
560 {
561 this->signer->insert_last(this->signer, vector);
562 }
563
564 /**
565 * Implementation of crypter_tester_t.add_hasher_vector
566 */
567 static void add_hasher_vector(private_crypto_tester_t *this,
568 hasher_test_vector_t *vector)
569 {
570 this->hasher->insert_last(this->hasher, vector);
571 }
572
573 /**
574 * Implementation of crypter_tester_t.add_prf_vector
575 */
576 static void add_prf_vector(private_crypto_tester_t *this,
577 prf_test_vector_t *vector)
578 {
579 this->prf->insert_last(this->prf, vector);
580 }
581
582 /**
583 * Implementation of crypter_tester_t.add_rng_vector
584 */
585 static void add_rng_vector(private_crypto_tester_t *this,
586 rng_test_vector_t *vector)
587 {
588 this->rng->insert_last(this->rng, vector);
589 }
590
591 /**
592 * Implementation of crypto_tester_t.destroy.
593 */
594 static void destroy(private_crypto_tester_t *this)
595 {
596 this->crypter->destroy(this->crypter);
597 this->signer->destroy(this->signer);
598 this->hasher->destroy(this->hasher);
599 this->prf->destroy(this->prf);
600 this->rng->destroy(this->rng);
601 free(this);
602 }
603
604 /**
605 * See header
606 */
607 crypto_tester_t *crypto_tester_create()
608 {
609 private_crypto_tester_t *this = malloc_thing(private_crypto_tester_t);
610
611 this->public.test_crypter = (bool(*)(crypto_tester_t*, encryption_algorithm_t alg,size_t key_size, crypter_constructor_t create))test_crypter;
612 this->public.test_signer = (bool(*)(crypto_tester_t*, integrity_algorithm_t alg, signer_constructor_t create))test_signer;
613 this->public.test_hasher = (bool(*)(crypto_tester_t*, hash_algorithm_t alg, hasher_constructor_t create))test_hasher;
614 this->public.test_prf = (bool(*)(crypto_tester_t*, pseudo_random_function_t alg, prf_constructor_t create))test_prf;
615 this->public.test_rng = (bool(*)(crypto_tester_t*, rng_quality_t quality, rng_constructor_t create))test_rng;
616 this->public.add_crypter_vector = (void(*)(crypto_tester_t*, crypter_test_vector_t *vector))add_crypter_vector;
617 this->public.add_signer_vector = (void(*)(crypto_tester_t*, signer_test_vector_t *vector))add_signer_vector;
618 this->public.add_hasher_vector = (void(*)(crypto_tester_t*, hasher_test_vector_t *vector))add_hasher_vector;
619 this->public.add_prf_vector = (void(*)(crypto_tester_t*, prf_test_vector_t *vector))add_prf_vector;
620 this->public.add_rng_vector = (void(*)(crypto_tester_t*, rng_test_vector_t *vector))add_rng_vector;
621 this->public.destroy = (void(*)(crypto_tester_t*))destroy;
622
623 this->crypter = linked_list_create();
624 this->signer = linked_list_create();
625 this->hasher = linked_list_create();
626 this->prf = linked_list_create();
627 this->rng = linked_list_create();
628
629 this->required = lib->settings->get_bool(lib->settings,
630 "libstrongswan.crypto_test.required", FALSE);
631 this->rng_true = lib->settings->get_bool(lib->settings,
632 "libstrongswan.crypto_test.rng_true", FALSE);
633
634 return &this->public;
635 }
636