pkcs12: Add plugin dependencies with soft dependencies on the most common algorithms
[strongswan.git] / src / libstrongswan / plugins / plugin_feature.c
1 /*
2 * Copyright (C) 2012-2013 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2011 Martin Willi
6 * Copyright (C) 2011 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #define _GNU_SOURCE
20 #include <stdio.h>
21
22 #include "plugin_feature.h"
23
24 #include <utils/debug.h>
25
26 ENUM(plugin_feature_names, FEATURE_NONE, FEATURE_CUSTOM,
27 "NONE",
28 "CRYPTER",
29 "AEAD",
30 "SIGNER",
31 "HASHER",
32 "PRF",
33 "DH",
34 "RNG",
35 "NONCE_GEN",
36 "PRIVKEY",
37 "PRIVKEY_GEN",
38 "PRIVKEY_SIGN",
39 "PRIVKEY_DECRYPT",
40 "PUBKEY",
41 "PUBKEY_VERIFY",
42 "PUBKEY_ENCRYPT",
43 "CERT_DECODE",
44 "CERT_ENCODE",
45 "CONTAINER_DECODE",
46 "CONTAINER_ENCODE",
47 "EAP_SERVER",
48 "EAP_CLIENT",
49 "XAUTH_SERVER",
50 "XAUTH_CLIENT",
51 "DATABASE",
52 "FETCHER",
53 "RESOLVER",
54 "CUSTOM",
55 );
56
57 /**
58 * See header.
59 */
60 u_int32_t plugin_feature_hash(plugin_feature_t *feature)
61 {
62 chunk_t data;
63
64 switch (feature->type)
65 {
66 case FEATURE_NONE:
67 case FEATURE_RNG:
68 case FEATURE_NONCE_GEN:
69 case FEATURE_DATABASE:
70 case FEATURE_FETCHER:
71 case FEATURE_RESOLVER:
72 /* put these special cases in their (type-specific) buckets */
73 data = chunk_empty;
74 break;
75 case FEATURE_CRYPTER:
76 case FEATURE_AEAD:
77 case FEATURE_SIGNER:
78 case FEATURE_HASHER:
79 case FEATURE_PRF:
80 case FEATURE_DH:
81 case FEATURE_PRIVKEY:
82 case FEATURE_PRIVKEY_GEN:
83 case FEATURE_PUBKEY:
84 case FEATURE_PRIVKEY_SIGN:
85 case FEATURE_PUBKEY_VERIFY:
86 case FEATURE_PRIVKEY_DECRYPT:
87 case FEATURE_PUBKEY_ENCRYPT:
88 case FEATURE_CERT_DECODE:
89 case FEATURE_CERT_ENCODE:
90 case FEATURE_CONTAINER_DECODE:
91 case FEATURE_CONTAINER_ENCODE:
92 case FEATURE_EAP_SERVER:
93 case FEATURE_EAP_PEER:
94 data = chunk_from_thing(feature->arg);
95 break;
96 case FEATURE_CUSTOM:
97 data = chunk_create(feature->arg.custom,
98 strlen(feature->arg.custom));
99 break;
100 case FEATURE_XAUTH_SERVER:
101 case FEATURE_XAUTH_PEER:
102 data = chunk_create(feature->arg.xauth,
103 strlen(feature->arg.xauth));
104 break;
105 }
106 return chunk_hash_inc(chunk_from_thing(feature->type),
107 chunk_hash(data));
108 }
109
110 /**
111 * See header.
112 */
113 bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b)
114 {
115 if (a->type == b->type)
116 {
117 switch (a->type)
118 {
119 case FEATURE_NONE:
120 return FALSE;
121 case FEATURE_CRYPTER:
122 return a->arg.crypter.alg == b->arg.crypter.alg &&
123 a->arg.crypter.key_size == b->arg.crypter.key_size;
124 case FEATURE_AEAD:
125 return a->arg.aead.alg == b->arg.aead.alg &&
126 a->arg.aead.key_size == b->arg.aead.key_size;
127 case FEATURE_SIGNER:
128 return a->arg.signer == b->arg.signer;
129 case FEATURE_HASHER:
130 return a->arg.hasher == b->arg.hasher;
131 case FEATURE_PRF:
132 return a->arg.prf == b->arg.prf;
133 case FEATURE_DH:
134 return a->arg.dh_group == b->arg.dh_group;
135 case FEATURE_RNG:
136 return a->arg.rng_quality <= b->arg.rng_quality;
137 case FEATURE_NONCE_GEN:
138 case FEATURE_RESOLVER:
139 return TRUE;
140 case FEATURE_PRIVKEY:
141 case FEATURE_PRIVKEY_GEN:
142 case FEATURE_PUBKEY:
143 return a->arg.privkey == b->arg.privkey;
144 case FEATURE_PRIVKEY_SIGN:
145 case FEATURE_PUBKEY_VERIFY:
146 return a->arg.privkey_sign == b->arg.privkey_sign;
147 case FEATURE_PRIVKEY_DECRYPT:
148 case FEATURE_PUBKEY_ENCRYPT:
149 return a->arg.privkey_decrypt == b->arg.privkey_decrypt;
150 case FEATURE_CERT_DECODE:
151 case FEATURE_CERT_ENCODE:
152 return a->arg.cert == b->arg.cert;
153 case FEATURE_CONTAINER_DECODE:
154 case FEATURE_CONTAINER_ENCODE:
155 return a->arg.container == b->arg.container;
156 case FEATURE_EAP_SERVER:
157 case FEATURE_EAP_PEER:
158 return a->arg.eap == b->arg.eap;
159 case FEATURE_DATABASE:
160 return a->arg.database == DB_ANY ||
161 a->arg.database == b->arg.database;
162 case FEATURE_FETCHER:
163 return a->arg.fetcher == NULL ||
164 streq(a->arg.fetcher, b->arg.fetcher);
165 case FEATURE_CUSTOM:
166 return streq(a->arg.custom, b->arg.custom);
167 case FEATURE_XAUTH_SERVER:
168 case FEATURE_XAUTH_PEER:
169 return streq(a->arg.xauth, b->arg.xauth);
170 }
171 }
172 return FALSE;
173 }
174
175 /**
176 * See header.
177 */
178 bool plugin_feature_equals(plugin_feature_t *a, plugin_feature_t *b)
179 {
180 if (a->type == b->type)
181 {
182 switch (a->type)
183 {
184 case FEATURE_NONE:
185 case FEATURE_CRYPTER:
186 case FEATURE_AEAD:
187 case FEATURE_SIGNER:
188 case FEATURE_HASHER:
189 case FEATURE_PRF:
190 case FEATURE_DH:
191 case FEATURE_NONCE_GEN:
192 case FEATURE_RESOLVER:
193 case FEATURE_PRIVKEY:
194 case FEATURE_PRIVKEY_GEN:
195 case FEATURE_PUBKEY:
196 case FEATURE_PRIVKEY_SIGN:
197 case FEATURE_PUBKEY_VERIFY:
198 case FEATURE_PRIVKEY_DECRYPT:
199 case FEATURE_PUBKEY_ENCRYPT:
200 case FEATURE_CERT_DECODE:
201 case FEATURE_CERT_ENCODE:
202 case FEATURE_CONTAINER_DECODE:
203 case FEATURE_CONTAINER_ENCODE:
204 case FEATURE_EAP_SERVER:
205 case FEATURE_EAP_PEER:
206 case FEATURE_CUSTOM:
207 case FEATURE_XAUTH_SERVER:
208 case FEATURE_XAUTH_PEER:
209 return plugin_feature_matches(a, b);
210 case FEATURE_RNG:
211 return a->arg.rng_quality == b->arg.rng_quality;
212 case FEATURE_DATABASE:
213 return a->arg.database == b->arg.database;
214 case FEATURE_FETCHER:
215 if (a->arg.fetcher && b->arg.fetcher)
216 {
217 return streq(a->arg.fetcher, b->arg.fetcher);
218 }
219 return !a->arg.fetcher && !b->arg.fetcher;
220 }
221 }
222 return FALSE;
223 }
224
225 /**
226 * See header.
227 */
228 char* plugin_feature_get_string(plugin_feature_t *feature)
229 {
230 char *str = NULL;
231
232 if (feature->kind == FEATURE_REGISTER)
233 {
234 return strdup("(register function)");
235 }
236 switch (feature->type)
237 {
238 case FEATURE_NONE:
239 return strdup("NONE");
240 case FEATURE_CRYPTER:
241 if (asprintf(&str, "%N:%N-%d", plugin_feature_names, feature->type,
242 encryption_algorithm_names, feature->arg.crypter.alg,
243 feature->arg.crypter.key_size) > 0)
244 {
245 return str;
246 }
247 break;
248 case FEATURE_AEAD:
249 if (asprintf(&str, "%N:%N-%d", plugin_feature_names, feature->type,
250 encryption_algorithm_names, feature->arg.aead.alg,
251 feature->arg.aead.key_size) > 0)
252 {
253 return str;
254 }
255 break;
256 case FEATURE_SIGNER:
257 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
258 integrity_algorithm_names, feature->arg.signer) > 0)
259 {
260 return str;
261 }
262 break;
263 case FEATURE_HASHER:
264 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
265 hash_algorithm_names, feature->arg.hasher) > 0)
266 {
267 return str;
268 }
269 break;
270 case FEATURE_PRF:
271 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
272 pseudo_random_function_names, feature->arg.prf) > 0)
273 {
274 return str;
275 }
276 break;
277 case FEATURE_DH:
278 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
279 diffie_hellman_group_names, feature->arg.dh_group) > 0)
280 {
281 return str;
282 }
283 break;
284 case FEATURE_RNG:
285 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
286 rng_quality_names, feature->arg.rng_quality) > 0)
287 {
288 return str;
289 }
290 break;
291 case FEATURE_NONCE_GEN:
292 case FEATURE_RESOLVER:
293 if (asprintf(&str, "%N", plugin_feature_names, feature->type) > 0)
294 {
295 return str;
296 }
297 break;
298 case FEATURE_PRIVKEY:
299 case FEATURE_PRIVKEY_GEN:
300 case FEATURE_PUBKEY:
301 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
302 key_type_names, feature->arg.privkey) > 0)
303 {
304 return str;
305 }
306 break;
307 case FEATURE_PRIVKEY_SIGN:
308 case FEATURE_PUBKEY_VERIFY:
309 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
310 signature_scheme_names, feature->arg.privkey_sign) > 0)
311 {
312 return str;
313 }
314 break;
315 case FEATURE_PRIVKEY_DECRYPT:
316 case FEATURE_PUBKEY_ENCRYPT:
317 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
318 encryption_scheme_names, feature->arg.privkey_decrypt) > 0)
319 {
320 return str;
321 }
322 break;
323 case FEATURE_CERT_DECODE:
324 case FEATURE_CERT_ENCODE:
325 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
326 certificate_type_names, feature->arg.cert) > 0)
327 {
328 return str;
329 }
330 break;
331 case FEATURE_CONTAINER_DECODE:
332 case FEATURE_CONTAINER_ENCODE:
333 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
334 container_type_names, feature->arg.container) > 0)
335 {
336 return str;
337 }
338 break;
339 case FEATURE_EAP_SERVER:
340 case FEATURE_EAP_PEER:
341 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
342 eap_type_short_names, feature->arg.eap) > 0)
343 {
344 return str;
345 }
346 break;
347 case FEATURE_DATABASE:
348 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
349 db_driver_names, feature->arg.database) > 0)
350 {
351 return str;
352 }
353 break;
354 case FEATURE_FETCHER:
355 if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type,
356 feature->arg.fetcher) > 0)
357 {
358 return str;
359 }
360 break;
361 case FEATURE_CUSTOM:
362 if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type,
363 feature->arg.custom) > 0)
364 {
365 return str;
366 }
367 break;
368 case FEATURE_XAUTH_SERVER:
369 case FEATURE_XAUTH_PEER:
370 if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type,
371 feature->arg.xauth) > 0)
372 {
373 return str;
374 }
375 break;
376 }
377 if (!str)
378 {
379 str = strdup("(invalid)");
380 }
381 return str;
382 }
383
384 /**
385 * See header.
386 */
387 bool plugin_feature_load(plugin_t *plugin, plugin_feature_t *feature,
388 plugin_feature_t *reg)
389 {
390 char *name;
391
392 if (!reg)
393 { /* noting to do for this feature */
394 return TRUE;
395 }
396 if (reg->kind == FEATURE_CALLBACK)
397 {
398 if (!reg->arg.cb.f ||
399 reg->arg.cb.f(plugin, feature, TRUE, reg->arg.cb.data))
400 {
401 return TRUE;
402 }
403 return FALSE;
404 }
405 name = plugin->get_name(plugin);
406 switch (feature->type)
407 {
408 case FEATURE_CRYPTER:
409 lib->crypto->add_crypter(lib->crypto, feature->arg.crypter.alg,
410 name, reg->arg.reg.f);
411 break;
412 case FEATURE_AEAD:
413 lib->crypto->add_aead(lib->crypto, feature->arg.aead.alg,
414 name, reg->arg.reg.f);
415 break;
416 case FEATURE_SIGNER:
417 lib->crypto->add_signer(lib->crypto, feature->arg.signer,
418 name, reg->arg.reg.f);
419 break;
420 case FEATURE_HASHER:
421 lib->crypto->add_hasher(lib->crypto, feature->arg.hasher,
422 name, reg->arg.reg.f);
423 break;
424 case FEATURE_PRF:
425 lib->crypto->add_prf(lib->crypto, feature->arg.prf,
426 name, reg->arg.reg.f);
427 break;
428 case FEATURE_DH:
429 lib->crypto->add_dh(lib->crypto, feature->arg.dh_group,
430 name, reg->arg.reg.f);
431 break;
432 case FEATURE_RNG:
433 lib->crypto->add_rng(lib->crypto, feature->arg.rng_quality,
434 name, reg->arg.reg.f);
435 break;
436 case FEATURE_NONCE_GEN:
437 lib->crypto->add_nonce_gen(lib->crypto,
438 name, reg->arg.reg.f);
439 break;
440 case FEATURE_PRIVKEY:
441 case FEATURE_PRIVKEY_GEN:
442 lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY,
443 feature->arg.privkey, reg->arg.reg.final,
444 reg->arg.reg.f);
445 break;
446 case FEATURE_PUBKEY:
447 lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY,
448 feature->arg.pubkey, reg->arg.reg.final,
449 reg->arg.reg.f);
450 break;
451 case FEATURE_CERT_DECODE:
452 case FEATURE_CERT_ENCODE:
453 lib->creds->add_builder(lib->creds, CRED_CERTIFICATE,
454 feature->arg.cert, reg->arg.reg.final,
455 reg->arg.reg.f);
456 break;
457 case FEATURE_CONTAINER_DECODE:
458 case FEATURE_CONTAINER_ENCODE:
459 lib->creds->add_builder(lib->creds, CRED_CONTAINER,
460 feature->arg.container, reg->arg.reg.final,
461 reg->arg.reg.f);
462 break;
463 case FEATURE_DATABASE:
464 lib->db->add_database(lib->db, reg->arg.reg.f);
465 break;
466 case FEATURE_FETCHER:
467 lib->fetcher->add_fetcher(lib->fetcher, reg->arg.reg.f,
468 feature->arg.fetcher);
469 break;
470 case FEATURE_RESOLVER:
471 lib->resolver->add_resolver(lib->resolver, reg->arg.reg.f);
472 break;
473 default:
474 break;
475 }
476 return TRUE;
477 }
478
479 /**
480 * See header.
481 */
482 bool plugin_feature_unload(plugin_t *plugin, plugin_feature_t *feature,
483 plugin_feature_t *reg)
484 {
485 if (!reg)
486 { /* noting to do for this feature */
487 return TRUE;
488 }
489 if (reg->kind == FEATURE_CALLBACK)
490 {
491 if (!reg->arg.cb.f ||
492 reg->arg.cb.f(plugin, feature, FALSE, reg->arg.cb.data))
493 {
494 return TRUE;
495 }
496 return FALSE;
497 }
498 switch (feature->type)
499 {
500 case FEATURE_CRYPTER:
501 lib->crypto->remove_crypter(lib->crypto, reg->arg.reg.f);
502 break;
503 case FEATURE_AEAD:
504 lib->crypto->remove_aead(lib->crypto, reg->arg.reg.f);
505 break;
506 case FEATURE_SIGNER:
507 lib->crypto->remove_signer(lib->crypto, reg->arg.reg.f);
508 break;
509 case FEATURE_HASHER:
510 lib->crypto->remove_hasher(lib->crypto, reg->arg.reg.f);
511 break;
512 case FEATURE_PRF:
513 lib->crypto->remove_prf(lib->crypto, reg->arg.reg.f);
514 break;
515 case FEATURE_DH:
516 lib->crypto->remove_dh(lib->crypto, reg->arg.reg.f);
517 break;
518 case FEATURE_RNG:
519 lib->crypto->remove_rng(lib->crypto, reg->arg.reg.f);
520 break;
521 case FEATURE_NONCE_GEN:
522 lib->crypto->remove_nonce_gen(lib->crypto, reg->arg.reg.f);
523 break;
524 case FEATURE_PRIVKEY:
525 case FEATURE_PRIVKEY_GEN:
526 lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
527 break;
528 case FEATURE_PUBKEY:
529 lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
530 break;
531 case FEATURE_CERT_DECODE:
532 case FEATURE_CERT_ENCODE:
533 lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
534 break;
535 case FEATURE_CONTAINER_DECODE:
536 case FEATURE_CONTAINER_ENCODE:
537 lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
538 break;
539 case FEATURE_DATABASE:
540 lib->db->remove_database(lib->db, reg->arg.reg.f);
541 break;
542 case FEATURE_FETCHER:
543 lib->fetcher->remove_fetcher(lib->fetcher, reg->arg.reg.f);
544 break;
545 case FEATURE_RESOLVER:
546 lib->resolver->remove_resolver(lib->resolver, reg->arg.reg.f);
547 break;
548 default:
549 break;
550 }
551 return TRUE;
552 }