aead: Support custom AEAD salt sizes
[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 data = chunk_from_thing(feature->arg.crypter);
77 break;
78 case FEATURE_AEAD:
79 data = chunk_from_thing(feature->arg.aead);
80 break;
81 case FEATURE_SIGNER:
82 data = chunk_from_thing(feature->arg.signer);
83 break;
84 case FEATURE_HASHER:
85 data = chunk_from_thing(feature->arg.hasher);
86 break;
87 case FEATURE_PRF:
88 data = chunk_from_thing(feature->arg.prf);
89 break;
90 case FEATURE_DH:
91 data = chunk_from_thing(feature->arg.dh_group);
92 break;
93 case FEATURE_PRIVKEY:
94 data = chunk_from_thing(feature->arg.privkey);
95 break;
96 case FEATURE_PRIVKEY_GEN:
97 data = chunk_from_thing(feature->arg.privkey_gen);
98 break;
99 case FEATURE_PUBKEY:
100 data = chunk_from_thing(feature->arg.pubkey);
101 break;
102 case FEATURE_PRIVKEY_SIGN:
103 data = chunk_from_thing(feature->arg.privkey_sign);
104 break;
105 case FEATURE_PUBKEY_VERIFY:
106 data = chunk_from_thing(feature->arg.pubkey_verify);
107 break;
108 case FEATURE_PRIVKEY_DECRYPT:
109 data = chunk_from_thing(feature->arg.privkey_decrypt);
110 break;
111 case FEATURE_PUBKEY_ENCRYPT:
112 data = chunk_from_thing(feature->arg.pubkey_encrypt);
113 break;
114 case FEATURE_CERT_DECODE:
115 case FEATURE_CERT_ENCODE:
116 data = chunk_from_thing(feature->arg.cert);
117 break;
118 case FEATURE_CONTAINER_DECODE:
119 case FEATURE_CONTAINER_ENCODE:
120 data = chunk_from_thing(feature->arg.container);
121 break;
122 case FEATURE_EAP_SERVER:
123 case FEATURE_EAP_PEER:
124 data = chunk_from_thing(feature->arg.eap);
125 break;
126 case FEATURE_CUSTOM:
127 data = chunk_create(feature->arg.custom,
128 strlen(feature->arg.custom));
129 break;
130 case FEATURE_XAUTH_SERVER:
131 case FEATURE_XAUTH_PEER:
132 data = chunk_create(feature->arg.xauth,
133 strlen(feature->arg.xauth));
134 break;
135 }
136 return chunk_hash_inc(chunk_from_thing(feature->type),
137 chunk_hash(data));
138 }
139
140 /**
141 * See header.
142 */
143 bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b)
144 {
145 if (a->type == b->type)
146 {
147 switch (a->type)
148 {
149 case FEATURE_NONE:
150 return FALSE;
151 case FEATURE_CRYPTER:
152 return a->arg.crypter.alg == b->arg.crypter.alg &&
153 a->arg.crypter.key_size == b->arg.crypter.key_size;
154 case FEATURE_AEAD:
155 return a->arg.aead.alg == b->arg.aead.alg &&
156 a->arg.aead.key_size == b->arg.aead.key_size;
157 case FEATURE_SIGNER:
158 return a->arg.signer == b->arg.signer;
159 case FEATURE_HASHER:
160 return a->arg.hasher == b->arg.hasher;
161 case FEATURE_PRF:
162 return a->arg.prf == b->arg.prf;
163 case FEATURE_DH:
164 return a->arg.dh_group == b->arg.dh_group;
165 case FEATURE_RNG:
166 return a->arg.rng_quality <= b->arg.rng_quality;
167 case FEATURE_NONCE_GEN:
168 case FEATURE_RESOLVER:
169 return TRUE;
170 case FEATURE_PRIVKEY:
171 case FEATURE_PRIVKEY_GEN:
172 case FEATURE_PUBKEY:
173 return a->arg.privkey == b->arg.privkey;
174 case FEATURE_PRIVKEY_SIGN:
175 case FEATURE_PUBKEY_VERIFY:
176 return a->arg.privkey_sign == b->arg.privkey_sign;
177 case FEATURE_PRIVKEY_DECRYPT:
178 case FEATURE_PUBKEY_ENCRYPT:
179 return a->arg.privkey_decrypt == b->arg.privkey_decrypt;
180 case FEATURE_CERT_DECODE:
181 case FEATURE_CERT_ENCODE:
182 return a->arg.cert == b->arg.cert;
183 case FEATURE_CONTAINER_DECODE:
184 case FEATURE_CONTAINER_ENCODE:
185 return a->arg.container == b->arg.container;
186 case FEATURE_EAP_SERVER:
187 case FEATURE_EAP_PEER:
188 return a->arg.eap == b->arg.eap;
189 case FEATURE_DATABASE:
190 return a->arg.database == DB_ANY ||
191 a->arg.database == b->arg.database;
192 case FEATURE_FETCHER:
193 return a->arg.fetcher == NULL ||
194 streq(a->arg.fetcher, b->arg.fetcher);
195 case FEATURE_CUSTOM:
196 return streq(a->arg.custom, b->arg.custom);
197 case FEATURE_XAUTH_SERVER:
198 case FEATURE_XAUTH_PEER:
199 return streq(a->arg.xauth, b->arg.xauth);
200 }
201 }
202 return FALSE;
203 }
204
205 /**
206 * See header.
207 */
208 bool plugin_feature_equals(plugin_feature_t *a, plugin_feature_t *b)
209 {
210 if (a->type == b->type)
211 {
212 switch (a->type)
213 {
214 case FEATURE_NONE:
215 case FEATURE_CRYPTER:
216 case FEATURE_AEAD:
217 case FEATURE_SIGNER:
218 case FEATURE_HASHER:
219 case FEATURE_PRF:
220 case FEATURE_DH:
221 case FEATURE_NONCE_GEN:
222 case FEATURE_RESOLVER:
223 case FEATURE_PRIVKEY:
224 case FEATURE_PRIVKEY_GEN:
225 case FEATURE_PUBKEY:
226 case FEATURE_PRIVKEY_SIGN:
227 case FEATURE_PUBKEY_VERIFY:
228 case FEATURE_PRIVKEY_DECRYPT:
229 case FEATURE_PUBKEY_ENCRYPT:
230 case FEATURE_CERT_DECODE:
231 case FEATURE_CERT_ENCODE:
232 case FEATURE_CONTAINER_DECODE:
233 case FEATURE_CONTAINER_ENCODE:
234 case FEATURE_EAP_SERVER:
235 case FEATURE_EAP_PEER:
236 case FEATURE_CUSTOM:
237 case FEATURE_XAUTH_SERVER:
238 case FEATURE_XAUTH_PEER:
239 return plugin_feature_matches(a, b);
240 case FEATURE_RNG:
241 return a->arg.rng_quality == b->arg.rng_quality;
242 case FEATURE_DATABASE:
243 return a->arg.database == b->arg.database;
244 case FEATURE_FETCHER:
245 if (a->arg.fetcher && b->arg.fetcher)
246 {
247 return streq(a->arg.fetcher, b->arg.fetcher);
248 }
249 return !a->arg.fetcher && !b->arg.fetcher;
250 }
251 }
252 return FALSE;
253 }
254
255 /**
256 * See header.
257 */
258 char* plugin_feature_get_string(plugin_feature_t *feature)
259 {
260 char *str = NULL;
261
262 if (feature->kind == FEATURE_REGISTER)
263 {
264 return strdup("(register function)");
265 }
266 switch (feature->type)
267 {
268 case FEATURE_NONE:
269 return strdup("NONE");
270 case FEATURE_CRYPTER:
271 if (asprintf(&str, "%N:%N-%d", plugin_feature_names, feature->type,
272 encryption_algorithm_names, feature->arg.crypter.alg,
273 feature->arg.crypter.key_size) > 0)
274 {
275 return str;
276 }
277 break;
278 case FEATURE_AEAD:
279 if (asprintf(&str, "%N:%N-%d", plugin_feature_names, feature->type,
280 encryption_algorithm_names, feature->arg.aead.alg,
281 feature->arg.aead.key_size) > 0)
282 {
283 return str;
284 }
285 break;
286 case FEATURE_SIGNER:
287 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
288 integrity_algorithm_names, feature->arg.signer) > 0)
289 {
290 return str;
291 }
292 break;
293 case FEATURE_HASHER:
294 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
295 hash_algorithm_names, feature->arg.hasher) > 0)
296 {
297 return str;
298 }
299 break;
300 case FEATURE_PRF:
301 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
302 pseudo_random_function_names, feature->arg.prf) > 0)
303 {
304 return str;
305 }
306 break;
307 case FEATURE_DH:
308 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
309 diffie_hellman_group_names, feature->arg.dh_group) > 0)
310 {
311 return str;
312 }
313 break;
314 case FEATURE_RNG:
315 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
316 rng_quality_names, feature->arg.rng_quality) > 0)
317 {
318 return str;
319 }
320 break;
321 case FEATURE_NONCE_GEN:
322 case FEATURE_RESOLVER:
323 if (asprintf(&str, "%N", plugin_feature_names, feature->type) > 0)
324 {
325 return str;
326 }
327 break;
328 case FEATURE_PRIVKEY:
329 case FEATURE_PRIVKEY_GEN:
330 case FEATURE_PUBKEY:
331 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
332 key_type_names, feature->arg.privkey) > 0)
333 {
334 return str;
335 }
336 break;
337 case FEATURE_PRIVKEY_SIGN:
338 case FEATURE_PUBKEY_VERIFY:
339 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
340 signature_scheme_names, feature->arg.privkey_sign) > 0)
341 {
342 return str;
343 }
344 break;
345 case FEATURE_PRIVKEY_DECRYPT:
346 case FEATURE_PUBKEY_ENCRYPT:
347 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
348 encryption_scheme_names, feature->arg.privkey_decrypt) > 0)
349 {
350 return str;
351 }
352 break;
353 case FEATURE_CERT_DECODE:
354 case FEATURE_CERT_ENCODE:
355 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
356 certificate_type_names, feature->arg.cert) > 0)
357 {
358 return str;
359 }
360 break;
361 case FEATURE_CONTAINER_DECODE:
362 case FEATURE_CONTAINER_ENCODE:
363 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
364 container_type_names, feature->arg.container) > 0)
365 {
366 return str;
367 }
368 break;
369 case FEATURE_EAP_SERVER:
370 case FEATURE_EAP_PEER:
371 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
372 eap_type_short_names, feature->arg.eap) > 0)
373 {
374 return str;
375 }
376 break;
377 case FEATURE_DATABASE:
378 if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
379 db_driver_names, feature->arg.database) > 0)
380 {
381 return str;
382 }
383 break;
384 case FEATURE_FETCHER:
385 if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type,
386 feature->arg.fetcher) > 0)
387 {
388 return str;
389 }
390 break;
391 case FEATURE_CUSTOM:
392 if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type,
393 feature->arg.custom) > 0)
394 {
395 return str;
396 }
397 break;
398 case FEATURE_XAUTH_SERVER:
399 case FEATURE_XAUTH_PEER:
400 if (asprintf(&str, "%N:%s", plugin_feature_names, feature->type,
401 feature->arg.xauth) > 0)
402 {
403 return str;
404 }
405 break;
406 }
407 if (!str)
408 {
409 str = strdup("(invalid)");
410 }
411 return str;
412 }
413
414 /**
415 * See header.
416 */
417 bool plugin_feature_load(plugin_t *plugin, plugin_feature_t *feature,
418 plugin_feature_t *reg)
419 {
420 char *name;
421
422 if (!reg)
423 { /* noting to do for this feature */
424 return TRUE;
425 }
426 if (reg->kind == FEATURE_CALLBACK)
427 {
428 if (!reg->arg.cb.f ||
429 reg->arg.cb.f(plugin, feature, TRUE, reg->arg.cb.data))
430 {
431 return TRUE;
432 }
433 return FALSE;
434 }
435 name = plugin->get_name(plugin);
436 switch (feature->type)
437 {
438 case FEATURE_CRYPTER:
439 lib->crypto->add_crypter(lib->crypto, feature->arg.crypter.alg,
440 name, reg->arg.reg.f);
441 break;
442 case FEATURE_AEAD:
443 lib->crypto->add_aead(lib->crypto, feature->arg.aead.alg,
444 name, reg->arg.reg.f);
445 break;
446 case FEATURE_SIGNER:
447 lib->crypto->add_signer(lib->crypto, feature->arg.signer,
448 name, reg->arg.reg.f);
449 break;
450 case FEATURE_HASHER:
451 lib->crypto->add_hasher(lib->crypto, feature->arg.hasher,
452 name, reg->arg.reg.f);
453 break;
454 case FEATURE_PRF:
455 lib->crypto->add_prf(lib->crypto, feature->arg.prf,
456 name, reg->arg.reg.f);
457 break;
458 case FEATURE_DH:
459 lib->crypto->add_dh(lib->crypto, feature->arg.dh_group,
460 name, reg->arg.reg.f);
461 break;
462 case FEATURE_RNG:
463 lib->crypto->add_rng(lib->crypto, feature->arg.rng_quality,
464 name, reg->arg.reg.f);
465 break;
466 case FEATURE_NONCE_GEN:
467 lib->crypto->add_nonce_gen(lib->crypto,
468 name, reg->arg.reg.f);
469 break;
470 case FEATURE_PRIVKEY:
471 case FEATURE_PRIVKEY_GEN:
472 lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY,
473 feature->arg.privkey, reg->arg.reg.final,
474 reg->arg.reg.f);
475 break;
476 case FEATURE_PUBKEY:
477 lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY,
478 feature->arg.pubkey, reg->arg.reg.final,
479 reg->arg.reg.f);
480 break;
481 case FEATURE_CERT_DECODE:
482 case FEATURE_CERT_ENCODE:
483 lib->creds->add_builder(lib->creds, CRED_CERTIFICATE,
484 feature->arg.cert, reg->arg.reg.final,
485 reg->arg.reg.f);
486 break;
487 case FEATURE_CONTAINER_DECODE:
488 case FEATURE_CONTAINER_ENCODE:
489 lib->creds->add_builder(lib->creds, CRED_CONTAINER,
490 feature->arg.container, reg->arg.reg.final,
491 reg->arg.reg.f);
492 break;
493 case FEATURE_DATABASE:
494 lib->db->add_database(lib->db, reg->arg.reg.f);
495 break;
496 case FEATURE_FETCHER:
497 lib->fetcher->add_fetcher(lib->fetcher, reg->arg.reg.f,
498 feature->arg.fetcher);
499 break;
500 case FEATURE_RESOLVER:
501 lib->resolver->add_resolver(lib->resolver, reg->arg.reg.f);
502 break;
503 default:
504 break;
505 }
506 return TRUE;
507 }
508
509 /**
510 * See header.
511 */
512 bool plugin_feature_unload(plugin_t *plugin, plugin_feature_t *feature,
513 plugin_feature_t *reg)
514 {
515 if (!reg)
516 { /* noting to do for this feature */
517 return TRUE;
518 }
519 if (reg->kind == FEATURE_CALLBACK)
520 {
521 if (!reg->arg.cb.f ||
522 reg->arg.cb.f(plugin, feature, FALSE, reg->arg.cb.data))
523 {
524 return TRUE;
525 }
526 return FALSE;
527 }
528 switch (feature->type)
529 {
530 case FEATURE_CRYPTER:
531 lib->crypto->remove_crypter(lib->crypto, reg->arg.reg.f);
532 break;
533 case FEATURE_AEAD:
534 lib->crypto->remove_aead(lib->crypto, reg->arg.reg.f);
535 break;
536 case FEATURE_SIGNER:
537 lib->crypto->remove_signer(lib->crypto, reg->arg.reg.f);
538 break;
539 case FEATURE_HASHER:
540 lib->crypto->remove_hasher(lib->crypto, reg->arg.reg.f);
541 break;
542 case FEATURE_PRF:
543 lib->crypto->remove_prf(lib->crypto, reg->arg.reg.f);
544 break;
545 case FEATURE_DH:
546 lib->crypto->remove_dh(lib->crypto, reg->arg.reg.f);
547 break;
548 case FEATURE_RNG:
549 lib->crypto->remove_rng(lib->crypto, reg->arg.reg.f);
550 break;
551 case FEATURE_NONCE_GEN:
552 lib->crypto->remove_nonce_gen(lib->crypto, reg->arg.reg.f);
553 break;
554 case FEATURE_PRIVKEY:
555 case FEATURE_PRIVKEY_GEN:
556 lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
557 break;
558 case FEATURE_PUBKEY:
559 lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
560 break;
561 case FEATURE_CERT_DECODE:
562 case FEATURE_CERT_ENCODE:
563 lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
564 break;
565 case FEATURE_CONTAINER_DECODE:
566 case FEATURE_CONTAINER_ENCODE:
567 lib->creds->remove_builder(lib->creds, reg->arg.reg.f);
568 break;
569 case FEATURE_DATABASE:
570 lib->db->remove_database(lib->db, reg->arg.reg.f);
571 break;
572 case FEATURE_FETCHER:
573 lib->fetcher->remove_fetcher(lib->fetcher, reg->arg.reg.f);
574 break;
575 case FEATURE_RESOLVER:
576 lib->resolver->remove_resolver(lib->resolver, reg->arg.reg.f);
577 break;
578 default:
579 break;
580 }
581 return TRUE;
582 }