]>
Commit | Line | Data |
---|---|---|
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 |
24 | const char *default_plugin_name = "default"; |
25 | ||
94822086 | 26 | typedef struct entry_t entry_t; |
5932f41f | 27 | |
94822086 | 28 | struct 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 | ||
60 | typedef struct private_crypto_factory_t private_crypto_factory_t; | |
61 | ||
62 | /** | |
63 | * private data of crypto_factory | |
64 | */ | |
65 | struct 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 |
143 | METHOD(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 |
176 | METHOD(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 |
209 | METHOD(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 |
241 | METHOD(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 |
273 | METHOD(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 |
305 | METHOD(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 |
337 | METHOD(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 | 356 | METHOD(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 | */ |
399 | static 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, ¤t)) | |
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 |
432 | METHOD(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 |
449 | METHOD(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 |
469 | METHOD(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 | ||
486 | METHOD(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 |
506 | METHOD(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 |
523 | METHOD(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 |
543 | METHOD(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 |
560 | METHOD(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 |
580 | METHOD(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 |
597 | METHOD(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 | 617 | METHOD(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 |
634 | METHOD(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 | 654 | METHOD(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 | ||
662 | METHOD(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 |
682 | METHOD(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 |
690 | METHOD(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 | */ | |
713 | static 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 | */ | |
721 | static 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 | */ | |
735 | static 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 |
749 | static 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 |
757 | METHOD(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 |
763 | METHOD(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 |
772 | static 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 |
780 | METHOD(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 |
789 | static 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 |
797 | METHOD(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 |
806 | static 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 |
814 | METHOD(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 |
823 | static 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 |
831 | METHOD(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 | */ |
840 | static 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 | ||
848 | METHOD(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 | */ | |
857 | static 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 | ||
863 | METHOD(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 |
869 | METHOD(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 |
892 | METHOD(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 |
898 | METHOD(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 | */ | |
917 | crypto_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 | } |