]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/crypto/crypto_factory.c
lib: All settings use configured namespace
[thirdparty/strongswan.git] / src / libstrongswan / crypto / crypto_factory.c
CommitLineData
552cc11b 1/*
2e22333f 2 * Copyright (C) 2013 Tobias Brunner
552cc11b
MW
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
552cc11b
MW
15 */
16
17#include "crypto_factory.h"
18
f05b4272 19#include <utils/debug.h>
eba64cef 20#include <threading/rwlock.h>
12642a68 21#include <collections/linked_list.h>
28a0728b 22#include <crypto/crypto_tester.h>
552cc11b 23
5932f41f
AS
24const char *default_plugin_name = "default";
25
94822086 26typedef struct entry_t entry_t;
5932f41f 27
94822086 28struct entry_t {
5932f41f
AS
29 /**
30 * algorithm
31 */
94822086 32 u_int algo;
5932f41f
AS
33
34 /**
35 * plugin that registered this algorithm
36 */
37 const char *plugin_name;
38
39 /**
40 * benchmarked speed
41 */
1b0eff58 42 u_int speed;
5932f41f
AS
43
44 /**
45 * constructor
46 */
94822086
MW
47 union {
48 crypter_constructor_t create_crypter;
77b55e8a 49 aead_constructor_t create_aead;
94822086
MW
50 signer_constructor_t create_signer;
51 hasher_constructor_t create_hasher;
52 prf_constructor_t create_prf;
53 rng_constructor_t create_rng;
e2fc09c1 54 nonce_gen_constructor_t create_nonce_gen;
94822086 55 dh_constructor_t create_dh;
1b0eff58 56 void *create;
94822086 57 };
552cc11b
MW
58};
59
60typedef struct private_crypto_factory_t private_crypto_factory_t;
61
62/**
63 * private data of crypto_factory
64 */
65struct private_crypto_factory_t {
66
67 /**
68 * public functions
69 */
70 crypto_factory_t public;
7daf5226 71
552cc11b 72 /**
94822086 73 * registered crypters, as entry_t
552cc11b
MW
74 */
75 linked_list_t *crypters;
7daf5226 76
77b55e8a
MW
77 /**
78 * registered aead transforms, as entry_t
79 */
80 linked_list_t *aeads;
81
552cc11b 82 /**
94822086 83 * registered signers, as entry_t
552cc11b
MW
84 */
85 linked_list_t *signers;
7daf5226 86
552cc11b 87 /**
94822086 88 * registered hashers, as entry_t
552cc11b
MW
89 */
90 linked_list_t *hashers;
7daf5226 91
552cc11b 92 /**
94822086 93 * registered prfs, as entry_t
552cc11b
MW
94 */
95 linked_list_t *prfs;
7daf5226 96
6a365f07 97 /**
94822086 98 * registered rngs, as entry_t
6a365f07
MW
99 */
100 linked_list_t *rngs;
7daf5226 101
e2fc09c1
AKR
102 /**
103 * registered nonce generators, as entry_t
104 */
105 linked_list_t *nonce_gens;
106
552cc11b 107 /**
94822086 108 * registered diffie hellman, as entry_t
552cc11b
MW
109 */
110 linked_list_t *dhs;
7daf5226 111
28a0728b
MW
112 /**
113 * test manager to test crypto algorithms
114 */
115 crypto_tester_t *tester;
7daf5226 116
28a0728b
MW
117 /**
118 * whether to test algorithms during registration
119 */
120 bool test_on_add;
7daf5226 121
28a0728b
MW
122 /**
123 * whether to test algorithms on each crypto primitive construction
124 */
125 bool test_on_create;
7daf5226 126
1b0eff58
MW
127 /**
128 * run algorithm benchmark during registration
129 */
130 bool bench;
131
e9e47597
MW
132 /**
133 * Number of failed test vectors during "add".
134 */
135 u_int test_failures;
136
552cc11b 137 /**
e76078e8 138 * rwlock to lock access to modules
552cc11b 139 */
e76078e8 140 rwlock_t *lock;
552cc11b
MW
141};
142
e8bf9d6e
MW
143METHOD(crypto_factory_t, create_crypter, crypter_t*,
144 private_crypto_factory_t *this, encryption_algorithm_t algo,
145 size_t key_size)
552cc11b
MW
146{
147 enumerator_t *enumerator;
94822086 148 entry_t *entry;
552cc11b 149 crypter_t *crypter = NULL;
7daf5226 150
e76078e8 151 this->lock->read_lock(this->lock);
552cc11b
MW
152 enumerator = this->crypters->create_enumerator(this->crypters);
153 while (enumerator->enumerate(enumerator, &entry))
154 {
155 if (entry->algo == algo)
156 {
28a0728b
MW
157 if (this->test_on_create &&
158 !this->tester->test_crypter(this->tester, algo, key_size,
5932f41f
AS
159 entry->create_crypter, NULL,
160 default_plugin_name))
28a0728b
MW
161 {
162 continue;
163 }
94822086 164 crypter = entry->create_crypter(algo, key_size);
552cc11b
MW
165 if (crypter)
166 {
167 break;
168 }
169 }
170 }
171 enumerator->destroy(enumerator);
e76078e8 172 this->lock->unlock(this->lock);
552cc11b
MW
173 return crypter;
174}
175
77b55e8a
MW
176METHOD(crypto_factory_t, create_aead, aead_t*,
177 private_crypto_factory_t *this, encryption_algorithm_t algo,
178 size_t key_size)
179{
180 enumerator_t *enumerator;
181 entry_t *entry;
182 aead_t *aead = NULL;
183
184 this->lock->read_lock(this->lock);
185 enumerator = this->aeads->create_enumerator(this->aeads);
186 while (enumerator->enumerate(enumerator, &entry))
187 {
188 if (entry->algo == algo)
189 {
190 if (this->test_on_create &&
191 !this->tester->test_aead(this->tester, algo, key_size,
5932f41f
AS
192 entry->create_aead, NULL,
193 default_plugin_name))
77b55e8a
MW
194 {
195 continue;
196 }
197 aead = entry->create_aead(algo, key_size);
198 if (aead)
199 {
200 break;
201 }
202 }
203 }
204 enumerator->destroy(enumerator);
205 this->lock->unlock(this->lock);
206 return aead;
207}
208
e8bf9d6e
MW
209METHOD(crypto_factory_t, create_signer, signer_t*,
210 private_crypto_factory_t *this, integrity_algorithm_t algo)
552cc11b
MW
211{
212 enumerator_t *enumerator;
94822086 213 entry_t *entry;
552cc11b 214 signer_t *signer = NULL;
7daf5226 215
e76078e8 216 this->lock->read_lock(this->lock);
552cc11b
MW
217 enumerator = this->signers->create_enumerator(this->signers);
218 while (enumerator->enumerate(enumerator, &entry))
219 {
220 if (entry->algo == algo)
221 {
28a0728b
MW
222 if (this->test_on_create &&
223 !this->tester->test_signer(this->tester, algo,
5932f41f
AS
224 entry->create_signer, NULL,
225 default_plugin_name))
28a0728b
MW
226 {
227 continue;
228 }
94822086 229 signer = entry->create_signer(algo);
552cc11b
MW
230 if (signer)
231 {
232 break;
233 }
234 }
235 }
236 enumerator->destroy(enumerator);
e76078e8 237 this->lock->unlock(this->lock);
552cc11b
MW
238 return signer;
239}
240
e8bf9d6e
MW
241METHOD(crypto_factory_t, create_hasher, hasher_t*,
242 private_crypto_factory_t *this, hash_algorithm_t algo)
552cc11b
MW
243{
244 enumerator_t *enumerator;
94822086 245 entry_t *entry;
552cc11b
MW
246 hasher_t *hasher = NULL;
247
e76078e8 248 this->lock->read_lock(this->lock);
552cc11b
MW
249 enumerator = this->hashers->create_enumerator(this->hashers);
250 while (enumerator->enumerate(enumerator, &entry))
251 {
e2c9a03d 252 if (entry->algo == algo)
552cc11b 253 {
e2c9a03d 254 if (this->test_on_create &&
28a0728b 255 !this->tester->test_hasher(this->tester, algo,
5932f41f
AS
256 entry->create_hasher, NULL,
257 default_plugin_name))
28a0728b
MW
258 {
259 continue;
260 }
94822086 261 hasher = entry->create_hasher(entry->algo);
552cc11b
MW
262 if (hasher)
263 {
264 break;
265 }
266 }
267 }
268 enumerator->destroy(enumerator);
e76078e8 269 this->lock->unlock(this->lock);
552cc11b
MW
270 return hasher;
271}
272
e8bf9d6e
MW
273METHOD(crypto_factory_t, create_prf, prf_t*,
274 private_crypto_factory_t *this, pseudo_random_function_t algo)
552cc11b
MW
275{
276 enumerator_t *enumerator;
94822086 277 entry_t *entry;
552cc11b
MW
278 prf_t *prf = NULL;
279
e76078e8 280 this->lock->read_lock(this->lock);
552cc11b
MW
281 enumerator = this->prfs->create_enumerator(this->prfs);
282 while (enumerator->enumerate(enumerator, &entry))
283 {
284 if (entry->algo == algo)
285 {
28a0728b 286 if (this->test_on_create &&
1b0eff58 287 !this->tester->test_prf(this->tester, algo,
5932f41f
AS
288 entry->create_prf, NULL,
289 default_plugin_name))
28a0728b
MW
290 {
291 continue;
292 }
94822086 293 prf = entry->create_prf(algo);
552cc11b
MW
294 if (prf)
295 {
296 break;
297 }
298 }
299 }
300 enumerator->destroy(enumerator);
e76078e8 301 this->lock->unlock(this->lock);
552cc11b
MW
302 return prf;
303}
304
e8bf9d6e
MW
305METHOD(crypto_factory_t, create_rng, rng_t*,
306 private_crypto_factory_t *this, rng_quality_t quality)
6a365f07
MW
307{
308 enumerator_t *enumerator;
94822086 309 entry_t *entry;
ec91f15e 310 rng_t *rng = NULL;
7daf5226 311
e76078e8 312 this->lock->read_lock(this->lock);
6a365f07
MW
313 enumerator = this->rngs->create_enumerator(this->rngs);
314 while (enumerator->enumerate(enumerator, &entry))
315 { /* find the best matching quality, but at least as good as requested */
ec91f15e 316 if (entry->algo >= quality)
6a365f07 317 {
28a0728b 318 if (this->test_on_create &&
1b0eff58 319 !this->tester->test_rng(this->tester, quality,
5932f41f
AS
320 entry->create_rng, NULL,
321 default_plugin_name))
28a0728b
MW
322 {
323 continue;
324 }
ec91f15e
TB
325 rng = entry->create_rng(quality);
326 if (rng)
327 {
6a365f07
MW
328 break;
329 }
330 }
331 }
332 enumerator->destroy(enumerator);
e76078e8 333 this->lock->unlock(this->lock);
ec91f15e 334 return rng;
6a365f07
MW
335}
336
e2fc09c1
AKR
337METHOD(crypto_factory_t, create_nonce_gen, nonce_gen_t*,
338 private_crypto_factory_t *this)
339{
340 enumerator_t *enumerator;
341 entry_t *entry;
342 nonce_gen_t *nonce_gen = NULL;
343
344 this->lock->read_lock(this->lock);
345 enumerator = this->nonce_gens->create_enumerator(this->nonce_gens);
346 while (enumerator->enumerate(enumerator, &entry))
347 {
348 nonce_gen = entry->create_nonce_gen();
349 }
350 enumerator->destroy(enumerator);
351 this->lock->unlock(this->lock);
352
353 return nonce_gen;
354}
355
e8bf9d6e 356METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
0abd558a 357 private_crypto_factory_t *this, diffie_hellman_group_t group, ...)
552cc11b
MW
358{
359 enumerator_t *enumerator;
94822086 360 entry_t *entry;
11d6bc3e 361 va_list args;
24aa5586 362 chunk_t g = chunk_empty, p = chunk_empty;
552cc11b
MW
363 diffie_hellman_t *diffie_hellman = NULL;
364
11d6bc3e
MW
365 if (group == MODP_CUSTOM)
366 {
367 va_start(args, group);
368 g = va_arg(args, chunk_t);
369 p = va_arg(args, chunk_t);
370 va_end(args);
371 }
372
e76078e8 373 this->lock->read_lock(this->lock);
552cc11b
MW
374 enumerator = this->dhs->create_enumerator(this->dhs);
375 while (enumerator->enumerate(enumerator, &entry))
376 {
94822086 377 if (entry->algo == group)
552cc11b 378 {
11d6bc3e 379 diffie_hellman = entry->create_dh(group, g, p);
552cc11b
MW
380 if (diffie_hellman)
381 {
382 break;
383 }
384 }
385 }
386 enumerator->destroy(enumerator);
e76078e8 387 this->lock->unlock(this->lock);
552cc11b
MW
388 return diffie_hellman;
389}
390
1b0eff58
MW
391/**
392 * Insert an algorithm entry to a list
2e22333f
TB
393 *
394 * Entries are sorted by algorithm identifier (which is important for RNGs)
395 * while maintaining the order in which algorithms were added, unless they were
396 * benchmarked and speed is provided, which then is used to order entries of
397 * the same algorithm.
1b0eff58
MW
398 */
399static void add_entry(private_crypto_factory_t *this, linked_list_t *list,
5932f41f
AS
400 int algo, const char *plugin_name,
401 u_int speed, void *create)
1b0eff58 402{
2e22333f 403 enumerator_t *enumerator;
1b0eff58 404 entry_t *entry, *current;
1b0eff58
MW
405
406 INIT(entry,
407 .algo = algo,
5932f41f 408 .plugin_name = plugin_name,
1b0eff58
MW
409 .speed = speed,
410 );
6623dfa8 411 entry->create = create;
1b0eff58
MW
412
413 this->lock->write_lock(this->lock);
2e22333f
TB
414 enumerator = list->create_enumerator(list);
415 while (enumerator->enumerate(enumerator, &current))
416 {
417 if (current->algo > algo)
1b0eff58 418 {
2e22333f 419 break;
1b0eff58 420 }
2e22333f
TB
421 else if (current->algo == algo && speed &&
422 current->speed < speed)
1b0eff58 423 {
2e22333f 424 break;
1b0eff58 425 }
1b0eff58 426 }
2e22333f
TB
427 list->insert_before(list, enumerator, entry);
428 enumerator->destroy(enumerator);
1b0eff58
MW
429 this->lock->unlock(this->lock);
430}
431
e9e47597
MW
432METHOD(crypto_factory_t, add_crypter, bool,
433 private_crypto_factory_t *this, encryption_algorithm_t algo,
5932f41f 434 const char *plugin_name, crypter_constructor_t create)
552cc11b 435{
1b0eff58
MW
436 u_int speed = 0;
437
28a0728b 438 if (!this->test_on_add ||
1b0eff58 439 this->tester->test_crypter(this->tester, algo, 0, create,
5932f41f 440 this->bench ? &speed : NULL, plugin_name))
28a0728b 441 {
5932f41f 442 add_entry(this, this->crypters, algo, plugin_name, speed, create);
e9e47597 443 return TRUE;
28a0728b 444 }
e9e47597
MW
445 this->test_failures++;
446 return FALSE;
552cc11b
MW
447}
448
e8bf9d6e
MW
449METHOD(crypto_factory_t, remove_crypter, void,
450 private_crypto_factory_t *this, crypter_constructor_t create)
552cc11b 451{
94822086 452 entry_t *entry;
552cc11b 453 enumerator_t *enumerator;
7daf5226 454
e76078e8 455 this->lock->write_lock(this->lock);
552cc11b
MW
456 enumerator = this->crypters->create_enumerator(this->crypters);
457 while (enumerator->enumerate(enumerator, &entry))
458 {
94822086 459 if (entry->create_crypter == create)
552cc11b
MW
460 {
461 this->crypters->remove_at(this->crypters, enumerator);
462 free(entry);
463 }
464 }
465 enumerator->destroy(enumerator);
e76078e8 466 this->lock->unlock(this->lock);
552cc11b
MW
467}
468
e9e47597
MW
469METHOD(crypto_factory_t, add_aead, bool,
470 private_crypto_factory_t *this, encryption_algorithm_t algo,
5932f41f 471 const char *plugin_name, aead_constructor_t create)
77b55e8a
MW
472{
473 u_int speed = 0;
474
475 if (!this->test_on_add ||
476 this->tester->test_aead(this->tester, algo, 0, create,
5932f41f 477 this->bench ? &speed : NULL, plugin_name))
77b55e8a 478 {
5932f41f 479 add_entry(this, this->aeads, algo, plugin_name, speed, create);
e9e47597 480 return TRUE;
77b55e8a 481 }
e9e47597
MW
482 this->test_failures++;
483 return FALSE;
77b55e8a
MW
484}
485
486METHOD(crypto_factory_t, remove_aead, void,
487 private_crypto_factory_t *this, aead_constructor_t create)
488{
489 entry_t *entry;
490 enumerator_t *enumerator;
491
492 this->lock->write_lock(this->lock);
493 enumerator = this->aeads->create_enumerator(this->aeads);
494 while (enumerator->enumerate(enumerator, &entry))
495 {
496 if (entry->create_aead == create)
497 {
498 this->aeads->remove_at(this->aeads, enumerator);
499 free(entry);
500 }
501 }
502 enumerator->destroy(enumerator);
503 this->lock->unlock(this->lock);
504}
505
e9e47597
MW
506METHOD(crypto_factory_t, add_signer, bool,
507 private_crypto_factory_t *this, integrity_algorithm_t algo,
5932f41f 508 const char *plugin_name, signer_constructor_t create)
552cc11b 509{
1b0eff58
MW
510 u_int speed = 0;
511
28a0728b 512 if (!this->test_on_add ||
1b0eff58 513 this->tester->test_signer(this->tester, algo, create,
5932f41f 514 this->bench ? &speed : NULL, plugin_name))
28a0728b 515 {
5932f41f 516 add_entry(this, this->signers, algo, plugin_name, speed, create);
e9e47597 517 return TRUE;
28a0728b 518 }
e9e47597
MW
519 this->test_failures++;
520 return FALSE;
552cc11b
MW
521}
522
e8bf9d6e
MW
523METHOD(crypto_factory_t, remove_signer, void,
524 private_crypto_factory_t *this, signer_constructor_t create)
552cc11b 525{
94822086 526 entry_t *entry;
552cc11b 527 enumerator_t *enumerator;
7daf5226 528
e76078e8 529 this->lock->write_lock(this->lock);
552cc11b
MW
530 enumerator = this->signers->create_enumerator(this->signers);
531 while (enumerator->enumerate(enumerator, &entry))
532 {
94822086 533 if (entry->create_signer == create)
552cc11b
MW
534 {
535 this->signers->remove_at(this->signers, enumerator);
536 free(entry);
537 }
538 }
539 enumerator->destroy(enumerator);
e76078e8 540 this->lock->unlock(this->lock);
552cc11b
MW
541}
542
e9e47597
MW
543METHOD(crypto_factory_t, add_hasher, bool,
544 private_crypto_factory_t *this, hash_algorithm_t algo,
5932f41f 545 const char *plugin_name, hasher_constructor_t create)
552cc11b 546{
1b0eff58
MW
547 u_int speed = 0;
548
28a0728b 549 if (!this->test_on_add ||
1b0eff58 550 this->tester->test_hasher(this->tester, algo, create,
5932f41f 551 this->bench ? &speed : NULL, plugin_name))
28a0728b 552 {
5932f41f 553 add_entry(this, this->hashers, algo, plugin_name, speed, create);
e9e47597 554 return TRUE;
28a0728b 555 }
e9e47597
MW
556 this->test_failures++;
557 return FALSE;
552cc11b
MW
558}
559
e8bf9d6e
MW
560METHOD(crypto_factory_t, remove_hasher, void,
561 private_crypto_factory_t *this, hasher_constructor_t create)
552cc11b 562{
94822086 563 entry_t *entry;
552cc11b 564 enumerator_t *enumerator;
7daf5226 565
e76078e8 566 this->lock->write_lock(this->lock);
552cc11b
MW
567 enumerator = this->hashers->create_enumerator(this->hashers);
568 while (enumerator->enumerate(enumerator, &entry))
569 {
94822086 570 if (entry->create_hasher == create)
552cc11b
MW
571 {
572 this->hashers->remove_at(this->hashers, enumerator);
573 free(entry);
574 }
575 }
576 enumerator->destroy(enumerator);
e76078e8 577 this->lock->unlock(this->lock);
552cc11b
MW
578}
579
e9e47597
MW
580METHOD(crypto_factory_t, add_prf, bool,
581 private_crypto_factory_t *this, pseudo_random_function_t algo,
5932f41f 582 const char *plugin_name, prf_constructor_t create)
552cc11b 583{
1b0eff58
MW
584 u_int speed = 0;
585
28a0728b 586 if (!this->test_on_add ||
1b0eff58 587 this->tester->test_prf(this->tester, algo, create,
5932f41f 588 this->bench ? &speed : NULL, plugin_name))
28a0728b 589 {
5932f41f 590 add_entry(this, this->prfs, algo, plugin_name, speed, create);
e9e47597 591 return TRUE;
28a0728b 592 }
e9e47597
MW
593 this->test_failures++;
594 return FALSE;
552cc11b
MW
595}
596
e8bf9d6e
MW
597METHOD(crypto_factory_t, remove_prf, void,
598 private_crypto_factory_t *this, prf_constructor_t create)
552cc11b 599{
94822086 600 entry_t *entry;
552cc11b 601 enumerator_t *enumerator;
7daf5226 602
e76078e8 603 this->lock->write_lock(this->lock);
552cc11b
MW
604 enumerator = this->prfs->create_enumerator(this->prfs);
605 while (enumerator->enumerate(enumerator, &entry))
606 {
94822086 607 if (entry->create_prf == create)
552cc11b
MW
608 {
609 this->prfs->remove_at(this->prfs, enumerator);
610 free(entry);
611 }
612 }
613 enumerator->destroy(enumerator);
e76078e8 614 this->lock->unlock(this->lock);
552cc11b
MW
615}
616
e9e47597 617METHOD(crypto_factory_t, add_rng, bool,
e8bf9d6e 618 private_crypto_factory_t *this, rng_quality_t quality,
5932f41f 619 const char *plugin_name, rng_constructor_t create)
6a365f07 620{
1b0eff58
MW
621 u_int speed = 0;
622
28a0728b 623 if (!this->test_on_add ||
1b0eff58 624 this->tester->test_rng(this->tester, quality, create,
5932f41f 625 this->bench ? &speed : NULL, plugin_name))
28a0728b 626 {
5932f41f 627 add_entry(this, this->rngs, quality, plugin_name, speed, create);
e9e47597 628 return TRUE;
28a0728b 629 }
e9e47597
MW
630 this->test_failures++;
631 return FALSE;
6a365f07
MW
632}
633
e8bf9d6e
MW
634METHOD(crypto_factory_t, remove_rng, void,
635 private_crypto_factory_t *this, rng_constructor_t create)
6a365f07 636{
94822086 637 entry_t *entry;
6a365f07 638 enumerator_t *enumerator;
7daf5226 639
e76078e8 640 this->lock->write_lock(this->lock);
6a365f07
MW
641 enumerator = this->rngs->create_enumerator(this->rngs);
642 while (enumerator->enumerate(enumerator, &entry))
643 {
94822086 644 if (entry->create_rng == create)
6a365f07
MW
645 {
646 this->rngs->remove_at(this->rngs, enumerator);
647 free(entry);
648 }
649 }
650 enumerator->destroy(enumerator);
e76078e8 651 this->lock->unlock(this->lock);
6a365f07
MW
652}
653
e9e47597 654METHOD(crypto_factory_t, add_nonce_gen, bool,
e2fc09c1
AKR
655 private_crypto_factory_t *this, const char *plugin_name,
656 nonce_gen_constructor_t create)
657{
658 add_entry(this, this->nonce_gens, 0, plugin_name, 0, create);
e9e47597 659 return TRUE;
e2fc09c1
AKR
660}
661
662METHOD(crypto_factory_t, remove_nonce_gen, void,
663 private_crypto_factory_t *this, nonce_gen_constructor_t create)
664{
665 entry_t *entry;
666 enumerator_t *enumerator;
667
668 this->lock->write_lock(this->lock);
75d4e01c 669 enumerator = this->nonce_gens->create_enumerator(this->nonce_gens);
e2fc09c1
AKR
670 while (enumerator->enumerate(enumerator, &entry))
671 {
672 if (entry->create_nonce_gen == create)
673 {
674 this->nonce_gens->remove_at(this->nonce_gens, enumerator);
675 free(entry);
676 }
677 }
678 enumerator->destroy(enumerator);
679 this->lock->unlock(this->lock);
680}
681
e9e47597
MW
682METHOD(crypto_factory_t, add_dh, bool,
683 private_crypto_factory_t *this, diffie_hellman_group_t group,
684 const char *plugin_name, dh_constructor_t create)
552cc11b 685{
5932f41f 686 add_entry(this, this->dhs, group, plugin_name, 0, create);
e9e47597 687 return TRUE;
552cc11b
MW
688}
689
e8bf9d6e
MW
690METHOD(crypto_factory_t, remove_dh, void,
691 private_crypto_factory_t *this, dh_constructor_t create)
552cc11b 692{
94822086 693 entry_t *entry;
552cc11b 694 enumerator_t *enumerator;
7daf5226 695
e76078e8 696 this->lock->write_lock(this->lock);
552cc11b
MW
697 enumerator = this->dhs->create_enumerator(this->dhs);
698 while (enumerator->enumerate(enumerator, &entry))
699 {
94822086 700 if (entry->create_dh == create)
552cc11b
MW
701 {
702 this->dhs->remove_at(this->dhs, enumerator);
703 free(entry);
704 }
705 }
706 enumerator->destroy(enumerator);
e76078e8 707 this->lock->unlock(this->lock);
552cc11b
MW
708}
709
94822086
MW
710/**
711 * match algorithms of an entry?
712 */
713static bool entry_match(entry_t *a, entry_t *b)
714{
715 return a->algo == b->algo;
716}
717
718/**
719 * check for uniqueness of an entry
720 */
721static bool unique_check(linked_list_t *list, entry_t **in, entry_t **out)
722{
723 if (list->find_first(list, (void*)entry_match, NULL, *in) == SUCCESS)
724 {
725 return FALSE;
726 }
727 *out = *in;
728 list->insert_last(list, *in);
729 return TRUE;
730}
731
732/**
733 * create an enumerator over entry->algo in list with locking and unique check
734 */
735static enumerator_t *create_enumerator(private_crypto_factory_t *this,
736 linked_list_t *list, void *filter)
737{
e76078e8 738 this->lock->read_lock(this->lock);
94822086
MW
739 return enumerator_create_filter(
740 enumerator_create_filter(
741 list->create_enumerator(list), (void*)unique_check,
742 linked_list_create(), (void*)list->destroy),
e76078e8 743 filter, this->lock, (void*)this->lock->unlock);
94822086
MW
744}
745
746/**
747 * Filter function to enumerate algorithm, not entry
748 */
5932f41f
AS
749static bool crypter_filter(void *n, entry_t **entry, encryption_algorithm_t *algo,
750 void *i2, const char **plugin_name)
94822086
MW
751{
752 *algo = (*entry)->algo;
5932f41f 753 *plugin_name = (*entry)->plugin_name;
94822086
MW
754 return TRUE;
755}
756
e8bf9d6e
MW
757METHOD(crypto_factory_t, create_crypter_enumerator, enumerator_t*,
758 private_crypto_factory_t *this)
94822086
MW
759{
760 return create_enumerator(this, this->crypters, crypter_filter);
761}
762
77b55e8a
MW
763METHOD(crypto_factory_t, create_aead_enumerator, enumerator_t*,
764 private_crypto_factory_t *this)
765{
766 return create_enumerator(this, this->aeads, crypter_filter);
767}
768
94822086
MW
769/**
770 * Filter function to enumerate algorithm, not entry
771 */
5932f41f
AS
772static bool signer_filter(void *n, entry_t **entry, integrity_algorithm_t *algo,
773 void *i2, const char **plugin_name)
94822086
MW
774{
775 *algo = (*entry)->algo;
5932f41f 776 *plugin_name = (*entry)->plugin_name;
94822086
MW
777 return TRUE;
778}
779
e8bf9d6e
MW
780METHOD(crypto_factory_t, create_signer_enumerator, enumerator_t*,
781 private_crypto_factory_t *this)
94822086
MW
782{
783 return create_enumerator(this, this->signers, signer_filter);
784}
785
786/**
787 * Filter function to enumerate algorithm, not entry
788 */
5932f41f
AS
789static bool hasher_filter(void *n, entry_t **entry, hash_algorithm_t *algo,
790 void *i2, const char **plugin_name)
94822086
MW
791{
792 *algo = (*entry)->algo;
5932f41f 793 *plugin_name = (*entry)->plugin_name;
94822086
MW
794 return TRUE;
795}
796
e8bf9d6e
MW
797METHOD(crypto_factory_t, create_hasher_enumerator, enumerator_t*,
798 private_crypto_factory_t *this)
94822086
MW
799{
800 return create_enumerator(this, this->hashers, hasher_filter);
801}
802
803/**
804 * Filter function to enumerate algorithm, not entry
805 */
5932f41f
AS
806static bool prf_filter(void *n, entry_t **entry, pseudo_random_function_t *algo,
807 void *i2, const char **plugin_name)
94822086
MW
808{
809 *algo = (*entry)->algo;
5932f41f 810 *plugin_name = (*entry)->plugin_name;
94822086
MW
811 return TRUE;
812}
813
e8bf9d6e
MW
814METHOD(crypto_factory_t, create_prf_enumerator, enumerator_t*,
815 private_crypto_factory_t *this)
94822086
MW
816{
817 return create_enumerator(this, this->prfs, prf_filter);
818}
819
820/**
b826b192 821 * Filter function to enumerate group, not entry
94822086 822 */
5932f41f
AS
823static bool dh_filter(void *n, entry_t **entry, diffie_hellman_group_t *group,
824 void *i2, const char **plugin_name)
94822086
MW
825{
826 *group = (*entry)->algo;
5932f41f 827 *plugin_name = (*entry)->plugin_name;
94822086
MW
828 return TRUE;
829}
830
e8bf9d6e
MW
831METHOD(crypto_factory_t, create_dh_enumerator, enumerator_t*,
832 private_crypto_factory_t *this)
94822086
MW
833{
834 return create_enumerator(this, this->dhs, dh_filter);
835}
836
5932f41f 837/**
b826b192 838 * Filter function to enumerate strength, not entry
5932f41f
AS
839 */
840static bool rng_filter(void *n, entry_t **entry, rng_quality_t *quality,
841 void *i2, const char **plugin_name)
842{
843 *quality = (*entry)->algo;
844 *plugin_name = (*entry)->plugin_name;
845 return TRUE;
846}
847
848METHOD(crypto_factory_t, create_rng_enumerator, enumerator_t*,
849 private_crypto_factory_t *this)
850{
851 return create_enumerator(this, this->rngs, rng_filter);
852}
b826b192
TB
853
854/**
855 * Filter function to enumerate plugin name, not entry
856 */
857static bool nonce_gen_filter(void *n, entry_t **entry, const char **plugin_name)
858{
859 *plugin_name = (*entry)->plugin_name;
860 return TRUE;
861}
862
863METHOD(crypto_factory_t, create_nonce_gen_enumerator, enumerator_t*,
864 private_crypto_factory_t *this)
865{
866 return create_enumerator(this, this->nonce_gens, nonce_gen_filter);
867}
868
e8bf9d6e
MW
869METHOD(crypto_factory_t, add_test_vector, void,
870 private_crypto_factory_t *this, transform_type_t type, void *vector)
28a0728b
MW
871{
872 switch (type)
873 {
874 case ENCRYPTION_ALGORITHM:
875 return this->tester->add_crypter_vector(this->tester, vector);
77b55e8a
MW
876 case AEAD_ALGORITHM:
877 return this->tester->add_aead_vector(this->tester, vector);
28a0728b
MW
878 case INTEGRITY_ALGORITHM:
879 return this->tester->add_signer_vector(this->tester, vector);
880 case HASH_ALGORITHM:
881 return this->tester->add_hasher_vector(this->tester, vector);
882 case PSEUDO_RANDOM_FUNCTION:
883 return this->tester->add_prf_vector(this->tester, vector);
884 case RANDOM_NUMBER_GENERATOR:
885 return this->tester->add_rng_vector(this->tester, vector);
886 default:
8b0e0910 887 DBG1(DBG_LIB, "%N test vectors not supported, ignored",
28a0728b
MW
888 transform_type_names, type);
889 }
890}
891
e9e47597
MW
892METHOD(crypto_factory_t, get_test_vector_failures, u_int,
893 private_crypto_factory_t *this)
894{
895 return this->test_failures;
896}
897
e8bf9d6e
MW
898METHOD(crypto_factory_t, destroy, void,
899 private_crypto_factory_t *this)
552cc11b 900{
a369a5ec 901 this->crypters->destroy(this->crypters);
77b55e8a 902 this->aeads->destroy(this->aeads);
a369a5ec
MW
903 this->signers->destroy(this->signers);
904 this->hashers->destroy(this->hashers);
905 this->prfs->destroy(this->prfs);
906 this->rngs->destroy(this->rngs);
e2fc09c1 907 this->nonce_gens->destroy(this->nonce_gens);
a369a5ec 908 this->dhs->destroy(this->dhs);
28a0728b 909 this->tester->destroy(this->tester);
e76078e8 910 this->lock->destroy(this->lock);
552cc11b
MW
911 free(this);
912}
913
914/*
915 * see header file
916 */
917crypto_factory_t *crypto_factory_create()
918{
e8bf9d6e
MW
919 private_crypto_factory_t *this;
920
921 INIT(this,
922 .public = {
923 .create_crypter = _create_crypter,
77b55e8a 924 .create_aead = _create_aead,
e8bf9d6e
MW
925 .create_signer = _create_signer,
926 .create_hasher = _create_hasher,
927 .create_prf = _create_prf,
928 .create_rng = _create_rng,
e2fc09c1 929 .create_nonce_gen = _create_nonce_gen,
e8bf9d6e
MW
930 .create_dh = _create_dh,
931 .add_crypter = _add_crypter,
932 .remove_crypter = _remove_crypter,
77b55e8a
MW
933 .add_aead = _add_aead,
934 .remove_aead = _remove_aead,
e8bf9d6e
MW
935 .add_signer = _add_signer,
936 .remove_signer = _remove_signer,
937 .add_hasher = _add_hasher,
938 .remove_hasher = _remove_hasher,
939 .add_prf = _add_prf,
940 .remove_prf = _remove_prf,
941 .add_rng = _add_rng,
942 .remove_rng = _remove_rng,
e2fc09c1
AKR
943 .add_nonce_gen = _add_nonce_gen,
944 .remove_nonce_gen = _remove_nonce_gen,
e8bf9d6e
MW
945 .add_dh = _add_dh,
946 .remove_dh = _remove_dh,
947 .create_crypter_enumerator = _create_crypter_enumerator,
77b55e8a 948 .create_aead_enumerator = _create_aead_enumerator,
e8bf9d6e
MW
949 .create_signer_enumerator = _create_signer_enumerator,
950 .create_hasher_enumerator = _create_hasher_enumerator,
951 .create_prf_enumerator = _create_prf_enumerator,
952 .create_dh_enumerator = _create_dh_enumerator,
5932f41f 953 .create_rng_enumerator = _create_rng_enumerator,
b826b192 954 .create_nonce_gen_enumerator = _create_nonce_gen_enumerator,
e8bf9d6e 955 .add_test_vector = _add_test_vector,
e9e47597 956 .get_test_vector_failures = _get_test_vector_failures,
e8bf9d6e
MW
957 .destroy = _destroy,
958 },
959 .crypters = linked_list_create(),
77b55e8a 960 .aeads = linked_list_create(),
e8bf9d6e
MW
961 .signers = linked_list_create(),
962 .hashers = linked_list_create(),
963 .prfs = linked_list_create(),
964 .rngs = linked_list_create(),
e2fc09c1 965 .nonce_gens = linked_list_create(),
e8bf9d6e
MW
966 .dhs = linked_list_create(),
967 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
968 .tester = crypto_tester_create(),
969 .test_on_add = lib->settings->get_bool(lib->settings,
8dc6e716 970 "%s.crypto_test.on_add", FALSE, lib->ns),
e8bf9d6e 971 .test_on_create = lib->settings->get_bool(lib->settings,
8dc6e716 972 "%s.crypto_test.on_create", FALSE, lib->ns),
1b0eff58 973 .bench = lib->settings->get_bool(lib->settings,
8dc6e716 974 "%s.crypto_test.bench", FALSE, lib->ns),
e8bf9d6e 975 );
7daf5226 976
552cc11b
MW
977 return &this->public;
978}