]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/crypto/proposal/proposal.c
bc9b2037a4093ed0495c219739cb8e047f182914
[thirdparty/strongswan.git] / src / libstrongswan / crypto / proposal / proposal.c
1 /*
2 * Copyright (C) 2008-2018 Tobias Brunner
3 * Copyright (C) 2006-2010 Martin Willi
4 * Copyright (C) 2013-2015 Andreas Steffen
5 * HSR Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include <string.h>
19
20 #include "proposal.h"
21
22 #include <collections/array.h>
23 #include <utils/identification.h>
24
25 #include <crypto/transform.h>
26 #include <crypto/prfs/prf.h>
27 #include <crypto/crypters/crypter.h>
28 #include <crypto/signers/signer.h>
29
30 ENUM(protocol_id_names, PROTO_NONE, PROTO_IPCOMP,
31 "PROTO_NONE",
32 "IKE",
33 "AH",
34 "ESP",
35 "IPCOMP",
36 );
37
38 typedef struct private_proposal_t private_proposal_t;
39
40 /**
41 * Private data of an proposal_t object
42 */
43 struct private_proposal_t {
44
45 /**
46 * Public part
47 */
48 proposal_t public;
49
50 /**
51 * protocol (ESP or AH)
52 */
53 protocol_id_t protocol;
54
55 /**
56 * Priority ordered list of transforms, as entry_t
57 */
58 array_t *transforms;
59
60 /**
61 * senders SPI
62 */
63 uint64_t spi;
64
65 /**
66 * Proposal number
67 */
68 u_int number;
69 };
70
71 /**
72 * Struct used to store different kinds of algorithms.
73 */
74 typedef struct {
75 /** Type of the transform */
76 transform_type_t type;
77 /** algorithm identifier */
78 uint16_t alg;
79 /** key size in bits, or zero if not needed */
80 uint16_t key_size;
81 } entry_t;
82
83 METHOD(proposal_t, add_algorithm, void,
84 private_proposal_t *this, transform_type_t type,
85 uint16_t alg, uint16_t key_size)
86 {
87 entry_t entry = {
88 .type = type,
89 .alg = alg,
90 .key_size = key_size,
91 };
92
93 array_insert(this->transforms, ARRAY_TAIL, &entry);
94 }
95
96 CALLBACK(alg_filter, bool,
97 uintptr_t type, enumerator_t *orig, va_list args)
98 {
99 entry_t *entry;
100 uint16_t *alg, *key_size;
101
102 VA_ARGS_VGET(args, alg, key_size);
103
104 while (orig->enumerate(orig, &entry))
105 {
106 if (entry->type != type)
107 {
108 continue;
109 }
110 if (alg)
111 {
112 *alg = entry->alg;
113 }
114 if (key_size)
115 {
116 *key_size = entry->key_size;
117 }
118 return TRUE;
119 }
120 return FALSE;
121 }
122
123 METHOD(proposal_t, create_enumerator, enumerator_t*,
124 private_proposal_t *this, transform_type_t type)
125 {
126 return enumerator_create_filter(
127 array_create_enumerator(this->transforms),
128 alg_filter, (void*)(uintptr_t)type, NULL);
129 }
130
131 METHOD(proposal_t, get_algorithm, bool,
132 private_proposal_t *this, transform_type_t type,
133 uint16_t *alg, uint16_t *key_size)
134 {
135 enumerator_t *enumerator;
136 bool found = FALSE;
137
138 enumerator = create_enumerator(this, type);
139 if (enumerator->enumerate(enumerator, alg, key_size))
140 {
141 found = TRUE;
142 }
143 enumerator->destroy(enumerator);
144
145 return found;
146 }
147
148 METHOD(proposal_t, has_dh_group, bool,
149 private_proposal_t *this, diffie_hellman_group_t group)
150 {
151 bool found = FALSE, any = FALSE;
152 enumerator_t *enumerator;
153 uint16_t current;
154
155 enumerator = create_enumerator(this, DIFFIE_HELLMAN_GROUP);
156 while (enumerator->enumerate(enumerator, &current, NULL))
157 {
158 any = TRUE;
159 if (current == group)
160 {
161 found = TRUE;
162 break;
163 }
164 }
165 enumerator->destroy(enumerator);
166
167 if (!any && group == MODP_NONE)
168 {
169 found = TRUE;
170 }
171 return found;
172 }
173
174 METHOD(proposal_t, promote_dh_group, bool,
175 private_proposal_t *this, diffie_hellman_group_t group)
176 {
177 enumerator_t *enumerator;
178 entry_t *entry;
179 bool found = FALSE;
180
181 enumerator = array_create_enumerator(this->transforms);
182 while (enumerator->enumerate(enumerator, &entry))
183 {
184 if (entry->type == DIFFIE_HELLMAN_GROUP &&
185 entry->alg == group)
186 {
187 array_remove_at(this->transforms, enumerator);
188 found = TRUE;
189 }
190 }
191 enumerator->destroy(enumerator);
192
193 if (found)
194 {
195 entry_t entry = {
196 .type = DIFFIE_HELLMAN_GROUP,
197 .alg = group,
198 };
199 array_insert(this->transforms, ARRAY_HEAD, &entry);
200 }
201 return found;
202 }
203
204 METHOD(proposal_t, strip_dh, void,
205 private_proposal_t *this, diffie_hellman_group_t keep)
206 {
207 enumerator_t *enumerator;
208 entry_t *entry;
209
210 enumerator = array_create_enumerator(this->transforms);
211 while (enumerator->enumerate(enumerator, &entry))
212 {
213 if (entry->type == DIFFIE_HELLMAN_GROUP &&
214 entry->alg != keep)
215 {
216 array_remove_at(this->transforms, enumerator);
217 }
218 }
219 enumerator->destroy(enumerator);
220 }
221
222 /**
223 * Select a matching proposal from this and other, insert into selected.
224 */
225 static bool select_algo(private_proposal_t *this, proposal_t *other,
226 proposal_t *selected, transform_type_t type, bool priv)
227 {
228 enumerator_t *e1, *e2;
229 uint16_t alg1, alg2, ks1, ks2;
230 bool found = FALSE, optional = FALSE;
231
232 if (type == INTEGRITY_ALGORITHM &&
233 selected->get_algorithm(selected, ENCRYPTION_ALGORITHM, &alg1, NULL) &&
234 encryption_algorithm_is_aead(alg1))
235 {
236 /* no integrity algorithm required, we have an AEAD */
237 return TRUE;
238 }
239 if (type == DIFFIE_HELLMAN_GROUP)
240 {
241 optional = this->protocol == PROTO_ESP || this->protocol == PROTO_AH;
242 }
243
244 e1 = create_enumerator(this, type);
245 e2 = other->create_enumerator(other, type);
246 if (!e1->enumerate(e1, &alg1, NULL))
247 {
248 if (!e2->enumerate(e2, &alg2, NULL))
249 {
250 found = TRUE;
251 }
252 else if (optional)
253 {
254 do
255 { /* if NONE is proposed, we accept the proposal */
256 found = !alg2;
257 }
258 while (!found && e2->enumerate(e2, &alg2, NULL));
259 }
260 }
261 else if (!e2->enumerate(e2, NULL, NULL))
262 {
263 if (optional)
264 {
265 do
266 { /* if NONE is proposed, we accept the proposal */
267 found = !alg1;
268 }
269 while (!found && e1->enumerate(e1, &alg1, NULL));
270 }
271 }
272
273 e1->destroy(e1);
274 e1 = create_enumerator(this, type);
275 /* compare algs, order of algs in "first" is preferred */
276 while (!found && e1->enumerate(e1, &alg1, &ks1))
277 {
278 e2->destroy(e2);
279 e2 = other->create_enumerator(other, type);
280 while (e2->enumerate(e2, &alg2, &ks2))
281 {
282 if (alg1 == alg2 && ks1 == ks2)
283 {
284 if (!priv && alg1 >= 1024)
285 {
286 /* accept private use algorithms only if requested */
287 DBG1(DBG_CFG, "an algorithm from private space would match, "
288 "but peer implementation is unknown, skipped");
289 continue;
290 }
291 selected->add_algorithm(selected, type, alg1, ks1);
292 found = TRUE;
293 break;
294 }
295 }
296 }
297 /* no match in all comparisons */
298 e1->destroy(e1);
299 e2->destroy(e2);
300
301 if (!found)
302 {
303 DBG2(DBG_CFG, " no acceptable %N found", transform_type_names, type);
304 }
305 return found;
306 }
307
308 METHOD(proposal_t, select_proposal, proposal_t*,
309 private_proposal_t *this, proposal_t *other, bool other_remote,
310 bool private)
311 {
312 proposal_t *selected;
313
314 DBG2(DBG_CFG, "selecting proposal:");
315
316 if (this->protocol != other->get_protocol(other))
317 {
318 DBG2(DBG_CFG, " protocol mismatch, skipping");
319 return NULL;
320 }
321
322 if (other_remote)
323 {
324 selected = proposal_create(this->protocol, other->get_number(other));
325 selected->set_spi(selected, other->get_spi(other));
326 }
327 else
328 {
329 selected = proposal_create(this->protocol, this->number);
330 selected->set_spi(selected, this->spi);
331
332 }
333
334 if (!select_algo(this, other, selected, ENCRYPTION_ALGORITHM, private) ||
335 !select_algo(this, other, selected, PSEUDO_RANDOM_FUNCTION, private) ||
336 !select_algo(this, other, selected, INTEGRITY_ALGORITHM, private) ||
337 !select_algo(this, other, selected, DIFFIE_HELLMAN_GROUP, private) ||
338 !select_algo(this, other, selected, EXTENDED_SEQUENCE_NUMBERS, private))
339 {
340 selected->destroy(selected);
341 return NULL;
342 }
343
344 DBG2(DBG_CFG, " proposal matches");
345 return selected;
346 }
347
348 METHOD(proposal_t, get_protocol, protocol_id_t,
349 private_proposal_t *this)
350 {
351 return this->protocol;
352 }
353
354 METHOD(proposal_t, set_spi, void,
355 private_proposal_t *this, uint64_t spi)
356 {
357 this->spi = spi;
358 }
359
360 METHOD(proposal_t, get_spi, uint64_t,
361 private_proposal_t *this)
362 {
363 return this->spi;
364 }
365
366 /**
367 * Check if two proposals have the same algorithms for a given transform type
368 */
369 static bool algo_list_equals(private_proposal_t *this, proposal_t *other,
370 transform_type_t type)
371 {
372 enumerator_t *e1, *e2;
373 uint16_t alg1, alg2, ks1, ks2;
374 bool equals = TRUE;
375
376 e1 = create_enumerator(this, type);
377 e2 = other->create_enumerator(other, type);
378 while (e1->enumerate(e1, &alg1, &ks1))
379 {
380 if (!e2->enumerate(e2, &alg2, &ks2))
381 {
382 /* this has more algs */
383 equals = FALSE;
384 break;
385 }
386 if (alg1 != alg2 || ks1 != ks2)
387 {
388 equals = FALSE;
389 break;
390 }
391 }
392 if (e2->enumerate(e2, &alg2, &ks2))
393 {
394 /* other has more algs */
395 equals = FALSE;
396 }
397 e1->destroy(e1);
398 e2->destroy(e2);
399
400 return equals;
401 }
402
403 METHOD(proposal_t, get_number, u_int,
404 private_proposal_t *this)
405 {
406 return this->number;
407 }
408
409 METHOD(proposal_t, equals, bool,
410 private_proposal_t *this, proposal_t *other)
411 {
412 if (&this->public == other)
413 {
414 return TRUE;
415 }
416 return (
417 algo_list_equals(this, other, ENCRYPTION_ALGORITHM) &&
418 algo_list_equals(this, other, INTEGRITY_ALGORITHM) &&
419 algo_list_equals(this, other, PSEUDO_RANDOM_FUNCTION) &&
420 algo_list_equals(this, other, DIFFIE_HELLMAN_GROUP) &&
421 algo_list_equals(this, other, EXTENDED_SEQUENCE_NUMBERS));
422 }
423
424 METHOD(proposal_t, clone_, proposal_t*,
425 private_proposal_t *this)
426 {
427 private_proposal_t *clone;
428 enumerator_t *enumerator;
429 entry_t *entry;
430
431 clone = (private_proposal_t*)proposal_create(this->protocol, 0);
432
433 enumerator = array_create_enumerator(this->transforms);
434 while (enumerator->enumerate(enumerator, &entry))
435 {
436 array_insert(clone->transforms, ARRAY_TAIL, entry);
437 }
438 enumerator->destroy(enumerator);
439
440 clone->spi = this->spi;
441 clone->number = this->number;
442
443 return &clone->public;
444 }
445
446 /**
447 * Map integrity algorithms to the PRF functions using the same algorithm.
448 */
449 static const struct {
450 integrity_algorithm_t integ;
451 pseudo_random_function_t prf;
452 } integ_prf_map[] = {
453 {AUTH_HMAC_SHA1_96, PRF_HMAC_SHA1 },
454 {AUTH_HMAC_SHA1_160, PRF_HMAC_SHA1 },
455 {AUTH_HMAC_SHA2_256_128, PRF_HMAC_SHA2_256 },
456 {AUTH_HMAC_SHA2_384_192, PRF_HMAC_SHA2_384 },
457 {AUTH_HMAC_SHA2_512_256, PRF_HMAC_SHA2_512 },
458 {AUTH_HMAC_MD5_96, PRF_HMAC_MD5 },
459 {AUTH_HMAC_MD5_128, PRF_HMAC_MD5 },
460 {AUTH_AES_XCBC_96, PRF_AES128_XCBC },
461 {AUTH_CAMELLIA_XCBC_96, PRF_CAMELLIA128_XCBC },
462 {AUTH_AES_CMAC_96, PRF_AES128_CMAC },
463 };
464
465 /**
466 * Remove all entries of the given transform type
467 */
468 static void remove_transform(private_proposal_t *this, transform_type_t type)
469 {
470 enumerator_t *e;
471 entry_t *entry;
472
473 e = array_create_enumerator(this->transforms);
474 while (e->enumerate(e, &entry))
475 {
476 if (entry->type == type)
477 {
478 array_remove_at(this->transforms, e);
479 }
480 }
481 e->destroy(e);
482 }
483
484 /**
485 * Checks the proposal read from a string.
486 */
487 static bool check_proposal(private_proposal_t *this)
488 {
489 enumerator_t *e;
490 entry_t *entry;
491 uint16_t alg, ks;
492 bool all_aead = TRUE, any_aead = FALSE, any_enc = FALSE;
493 int i;
494
495 if (this->protocol == PROTO_IKE)
496 {
497 if (!get_algorithm(this, PSEUDO_RANDOM_FUNCTION, NULL, NULL))
498 { /* No explicit PRF found. We assume the same algorithm as used
499 * for integrity checking. */
500 e = create_enumerator(this, INTEGRITY_ALGORITHM);
501 while (e->enumerate(e, &alg, &ks))
502 {
503 for (i = 0; i < countof(integ_prf_map); i++)
504 {
505 if (alg == integ_prf_map[i].integ)
506 {
507 add_algorithm(this, PSEUDO_RANDOM_FUNCTION,
508 integ_prf_map[i].prf, 0);
509 break;
510 }
511 }
512 }
513 e->destroy(e);
514 }
515 if (!get_algorithm(this, PSEUDO_RANDOM_FUNCTION, NULL, NULL))
516 {
517 DBG1(DBG_CFG, "a PRF algorithm is mandatory in IKE proposals");
518 return FALSE;
519 }
520 /* remove MODP_NONE from IKE proposal */
521 e = array_create_enumerator(this->transforms);
522 while (e->enumerate(e, &entry))
523 {
524 if (entry->type == DIFFIE_HELLMAN_GROUP && !entry->alg)
525 {
526 array_remove_at(this->transforms, e);
527 }
528 }
529 e->destroy(e);
530 if (!get_algorithm(this, DIFFIE_HELLMAN_GROUP, NULL, NULL))
531 {
532 DBG1(DBG_CFG, "a DH group is mandatory in IKE proposals");
533 return FALSE;
534 }
535 }
536 else
537 { /* remove PRFs from ESP/AH proposals */
538 remove_transform(this, PSEUDO_RANDOM_FUNCTION);
539 }
540
541 if (this->protocol == PROTO_IKE || this->protocol == PROTO_ESP)
542 {
543 e = create_enumerator(this, ENCRYPTION_ALGORITHM);
544 while (e->enumerate(e, &alg, &ks))
545 {
546 any_enc = TRUE;
547 if (encryption_algorithm_is_aead(alg))
548 {
549 any_aead = TRUE;
550 continue;
551 }
552 all_aead = FALSE;
553 }
554 e->destroy(e);
555
556 if (!any_enc)
557 {
558 DBG1(DBG_CFG, "an encryption algorithm is mandatory in %N proposals",
559 protocol_id_names, this->protocol);
560 return FALSE;
561 }
562 else if (any_aead && !all_aead)
563 {
564 DBG1(DBG_CFG, "classic and combined-mode (AEAD) encryption "
565 "algorithms can't be contained in the same %N proposal",
566 protocol_id_names, this->protocol);
567 return FALSE;
568 }
569 else if (all_aead)
570 { /* if all encryption algorithms in the proposal are AEADs,
571 * we MUST NOT propose any integrity algorithms */
572 remove_transform(this, INTEGRITY_ALGORITHM);
573 }
574 }
575 else
576 { /* AES-GMAC is parsed as encryption algorithm, so we map that to the
577 * proper integrity algorithm */
578 e = array_create_enumerator(this->transforms);
579 while (e->enumerate(e, &entry))
580 {
581 if (entry->type == ENCRYPTION_ALGORITHM)
582 {
583 if (entry->alg == ENCR_NULL_AUTH_AES_GMAC)
584 {
585 entry->type = INTEGRITY_ALGORITHM;
586 ks = entry->key_size;
587 entry->key_size = 0;
588 switch (ks)
589 {
590 case 128:
591 entry->alg = AUTH_AES_128_GMAC;
592 continue;
593 case 192:
594 entry->alg = AUTH_AES_192_GMAC;
595 continue;
596 case 256:
597 entry->alg = AUTH_AES_256_GMAC;
598 continue;
599 default:
600 break;
601 }
602 }
603 /* remove all other encryption algorithms */
604 array_remove_at(this->transforms, e);
605 }
606 }
607 e->destroy(e);
608
609 if (!get_algorithm(this, INTEGRITY_ALGORITHM, NULL, NULL))
610 {
611 DBG1(DBG_CFG, "an integrity algorithm is mandatory in AH "
612 "proposals");
613 return FALSE;
614 }
615 }
616
617 if (this->protocol == PROTO_AH || this->protocol == PROTO_ESP)
618 {
619 if (!get_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NULL, NULL))
620 { /* ESN not specified, assume not supported */
621 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
622 }
623 }
624
625 array_compress(this->transforms);
626 return TRUE;
627 }
628
629 /**
630 * add a algorithm identified by a string to the proposal.
631 */
632 static bool add_string_algo(private_proposal_t *this, const char *alg)
633 {
634 const proposal_token_t *token;
635
636 token = lib->proposal->get_token(lib->proposal, alg);
637 if (token == NULL)
638 {
639 DBG1(DBG_CFG, "algorithm '%s' not recognized", alg);
640 return FALSE;
641 }
642
643 add_algorithm(this, token->type, token->algorithm, token->keysize);
644
645 return TRUE;
646 }
647
648 /**
649 * print all algorithms of a kind to buffer
650 */
651 static int print_alg(private_proposal_t *this, printf_hook_data_t *data,
652 u_int kind, void *names, bool *first)
653 {
654 enumerator_t *enumerator;
655 size_t written = 0;
656 uint16_t alg, size;
657
658 enumerator = create_enumerator(this, kind);
659 while (enumerator->enumerate(enumerator, &alg, &size))
660 {
661 if (*first)
662 {
663 written += print_in_hook(data, "%N", names, alg);
664 *first = FALSE;
665 }
666 else
667 {
668 written += print_in_hook(data, "/%N", names, alg);
669 }
670 if (size)
671 {
672 written += print_in_hook(data, "_%u", size);
673 }
674 }
675 enumerator->destroy(enumerator);
676 return written;
677 }
678
679 /**
680 * Described in header.
681 */
682 int proposal_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
683 const void *const *args)
684 {
685 private_proposal_t *this = *((private_proposal_t**)(args[0]));
686 linked_list_t *list = *((linked_list_t**)(args[0]));
687 enumerator_t *enumerator;
688 size_t written = 0;
689 bool first = TRUE;
690
691 if (this == NULL)
692 {
693 return print_in_hook(data, "(null)");
694 }
695
696 if (spec->hash)
697 {
698 enumerator = list->create_enumerator(list);
699 while (enumerator->enumerate(enumerator, &this))
700 { /* call recursively */
701 if (first)
702 {
703 written += print_in_hook(data, "%P", this);
704 first = FALSE;
705 }
706 else
707 {
708 written += print_in_hook(data, ", %P", this);
709 }
710 }
711 enumerator->destroy(enumerator);
712 return written;
713 }
714
715 written = print_in_hook(data, "%N:", protocol_id_names, this->protocol);
716 written += print_alg(this, data, ENCRYPTION_ALGORITHM,
717 encryption_algorithm_names, &first);
718 written += print_alg(this, data, INTEGRITY_ALGORITHM,
719 integrity_algorithm_names, &first);
720 written += print_alg(this, data, PSEUDO_RANDOM_FUNCTION,
721 pseudo_random_function_names, &first);
722 written += print_alg(this, data, DIFFIE_HELLMAN_GROUP,
723 diffie_hellman_group_names, &first);
724 written += print_alg(this, data, EXTENDED_SEQUENCE_NUMBERS,
725 extended_sequence_numbers_names, &first);
726 return written;
727 }
728
729 METHOD(proposal_t, destroy, void,
730 private_proposal_t *this)
731 {
732 array_destroy(this->transforms);
733 free(this);
734 }
735
736 /*
737 * Described in header
738 */
739 proposal_t *proposal_create(protocol_id_t protocol, u_int number)
740 {
741 private_proposal_t *this;
742
743 INIT(this,
744 .public = {
745 .add_algorithm = _add_algorithm,
746 .create_enumerator = _create_enumerator,
747 .get_algorithm = _get_algorithm,
748 .has_dh_group = _has_dh_group,
749 .promote_dh_group = _promote_dh_group,
750 .strip_dh = _strip_dh,
751 .select = _select_proposal,
752 .get_protocol = _get_protocol,
753 .set_spi = _set_spi,
754 .get_spi = _get_spi,
755 .get_number = _get_number,
756 .equals = _equals,
757 .clone = _clone_,
758 .destroy = _destroy,
759 },
760 .protocol = protocol,
761 .number = number,
762 .transforms = array_create(sizeof(entry_t), 0),
763 );
764
765 return &this->public;
766 }
767
768 /**
769 * Add supported IKE algorithms to proposal
770 */
771 static bool proposal_add_supported_ike(private_proposal_t *this, bool aead)
772 {
773 enumerator_t *enumerator;
774 encryption_algorithm_t encryption;
775 integrity_algorithm_t integrity;
776 pseudo_random_function_t prf;
777 diffie_hellman_group_t group;
778 const char *plugin_name;
779
780 if (aead)
781 {
782 /* Round 1 adds algorithms with at least 128 bit security strength */
783 enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
784 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
785 {
786 switch (encryption)
787 {
788 case ENCR_AES_GCM_ICV16:
789 case ENCR_AES_CCM_ICV16:
790 case ENCR_CAMELLIA_CCM_ICV16:
791 /* we assume that we support all AES/Camellia sizes */
792 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128);
793 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192);
794 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256);
795 break;
796 case ENCR_CHACHA20_POLY1305:
797 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256);
798 break;
799 default:
800 break;
801 }
802 }
803 enumerator->destroy(enumerator);
804
805 /* Round 2 adds algorithms with less than 128 bit security strength */
806 enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
807 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
808 {
809 switch (encryption)
810 {
811 case ENCR_AES_GCM_ICV12:
812 case ENCR_AES_GCM_ICV8:
813 case ENCR_AES_CCM_ICV12:
814 case ENCR_AES_CCM_ICV8:
815 case ENCR_CAMELLIA_CCM_ICV12:
816 case ENCR_CAMELLIA_CCM_ICV8:
817 /* we assume that we support all AES/Camellia sizes */
818 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128);
819 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192);
820 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256);
821 break;
822 default:
823 break;
824 }
825 }
826 enumerator->destroy(enumerator);
827
828 if (!array_count(this->transforms))
829 {
830 return FALSE;
831 }
832 }
833 else
834 {
835 /* Round 1 adds algorithms with at least 128 bit security strength */
836 enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
837 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
838 {
839 switch (encryption)
840 {
841 case ENCR_AES_CBC:
842 case ENCR_AES_CTR:
843 case ENCR_CAMELLIA_CBC:
844 case ENCR_CAMELLIA_CTR:
845 /* we assume that we support all AES/Camellia sizes */
846 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 128);
847 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 192);
848 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 256);
849 break;
850 default:
851 break;
852 }
853 }
854 enumerator->destroy(enumerator);
855
856 /* Round 2 adds algorithms with less than 128 bit security strength */
857 enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
858 while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
859 {
860 switch (encryption)
861 {
862 case ENCR_3DES:
863 add_algorithm(this, ENCRYPTION_ALGORITHM, encryption, 0);
864 break;
865 case ENCR_DES:
866 /* no, thanks */
867 break;
868 default:
869 break;
870 }
871 }
872 enumerator->destroy(enumerator);
873
874 if (!array_count(this->transforms))
875 {
876 return FALSE;
877 }
878
879 /* Round 1 adds algorithms with at least 128 bit security strength */
880 enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
881 while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
882 {
883 switch (integrity)
884 {
885 case AUTH_HMAC_SHA2_256_128:
886 case AUTH_HMAC_SHA2_384_192:
887 case AUTH_HMAC_SHA2_512_256:
888 add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0);
889 break;
890 default:
891 break;
892 }
893 }
894 enumerator->destroy(enumerator);
895
896 /* Round 2 adds algorithms with less than 128 bit security strength */
897 enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
898 while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
899 {
900 switch (integrity)
901 {
902 case AUTH_AES_XCBC_96:
903 case AUTH_AES_CMAC_96:
904 case AUTH_HMAC_SHA1_96:
905 add_algorithm(this, INTEGRITY_ALGORITHM, integrity, 0);
906 break;
907 case AUTH_HMAC_MD5_96:
908 /* no, thanks */
909 default:
910 break;
911 }
912 }
913 enumerator->destroy(enumerator);
914 }
915
916 /* Round 1 adds algorithms with at least 128 bit security strength */
917 enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
918 while (enumerator->enumerate(enumerator, &prf, &plugin_name))
919 {
920 switch (prf)
921 {
922 case PRF_HMAC_SHA2_256:
923 case PRF_HMAC_SHA2_384:
924 case PRF_HMAC_SHA2_512:
925 case PRF_AES128_XCBC:
926 case PRF_AES128_CMAC:
927 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
928 break;
929 default:
930 break;
931 }
932 }
933 enumerator->destroy(enumerator);
934
935 /* Round 2 adds algorithms with less than 128 bit security strength */
936 enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
937 while (enumerator->enumerate(enumerator, &prf, &plugin_name))
938 {
939 switch (prf)
940 {
941 case PRF_HMAC_SHA1:
942 add_algorithm(this, PSEUDO_RANDOM_FUNCTION, prf, 0);
943 break;
944 case PRF_HMAC_MD5:
945 /* no, thanks */
946 break;
947 default:
948 break;
949 }
950 }
951 enumerator->destroy(enumerator);
952
953 /* Round 1 adds ECC and NTRU algorithms with at least 128 bit security strength */
954 enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
955 while (enumerator->enumerate(enumerator, &group, &plugin_name))
956 {
957 switch (group)
958 {
959 case ECP_256_BIT:
960 case ECP_384_BIT:
961 case ECP_521_BIT:
962 case ECP_256_BP:
963 case ECP_384_BP:
964 case ECP_512_BP:
965 case CURVE_25519:
966 case CURVE_448:
967 case NTRU_128_BIT:
968 case NTRU_192_BIT:
969 case NTRU_256_BIT:
970 case NH_128_BIT:
971 add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
972 break;
973 default:
974 break;
975 }
976 }
977 enumerator->destroy(enumerator);
978
979 /* Round 2 adds other algorithms with at least 128 bit security strength */
980 enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
981 while (enumerator->enumerate(enumerator, &group, &plugin_name))
982 {
983 switch (group)
984 {
985 case MODP_3072_BIT:
986 case MODP_4096_BIT:
987 case MODP_8192_BIT:
988 add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
989 break;
990 default:
991 break;
992 }
993 }
994 enumerator->destroy(enumerator);
995
996 /* Round 3 adds algorithms with less than 128 bit security strength */
997 enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
998 while (enumerator->enumerate(enumerator, &group, &plugin_name))
999 {
1000 switch (group)
1001 {
1002 case MODP_NULL:
1003 /* only for testing purposes */
1004 break;
1005 case MODP_768_BIT:
1006 case MODP_1024_BIT:
1007 case MODP_1536_BIT:
1008 /* weak */
1009 break;
1010 case MODP_1024_160:
1011 case MODP_2048_224:
1012 case MODP_2048_256:
1013 /* RFC 5114 primes are of questionable source */
1014 break;
1015 case ECP_224_BIT:
1016 case ECP_224_BP:
1017 case ECP_192_BIT:
1018 case NTRU_112_BIT:
1019 /* rarely used */
1020 break;
1021 case MODP_2048_BIT:
1022 add_algorithm(this, DIFFIE_HELLMAN_GROUP, group, 0);
1023 break;
1024 default:
1025 break;
1026 }
1027 }
1028 enumerator->destroy(enumerator);
1029
1030 return TRUE;
1031 }
1032
1033 /*
1034 * Described in header
1035 */
1036 proposal_t *proposal_create_default(protocol_id_t protocol)
1037 {
1038 private_proposal_t *this = (private_proposal_t*)proposal_create(protocol, 0);
1039
1040 switch (protocol)
1041 {
1042 case PROTO_IKE:
1043 if (!proposal_add_supported_ike(this, FALSE))
1044 {
1045 destroy(this);
1046 return NULL;
1047 }
1048 break;
1049 case PROTO_ESP:
1050 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128);
1051 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192);
1052 add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256);
1053 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0);
1054 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0);
1055 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0);
1056 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
1057 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
1058 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
1059 break;
1060 case PROTO_AH:
1061 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0);
1062 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0);
1063 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0);
1064 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
1065 add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0);
1066 add_algorithm(this, EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0);
1067 break;
1068 default:
1069 break;
1070 }
1071 return &this->public;
1072 }
1073
1074 /*
1075 * Described in header
1076 */
1077 proposal_t *proposal_create_default_aead(protocol_id_t protocol)
1078 {
1079 private_proposal_t *this;
1080
1081 switch (protocol)
1082 {
1083 case PROTO_IKE:
1084 this = (private_proposal_t*)proposal_create(protocol, 0);
1085 if (!proposal_add_supported_ike(this, TRUE))
1086 {
1087 destroy(this);
1088 return NULL;
1089 }
1090 return &this->public;
1091 case PROTO_ESP:
1092 /* we currently don't include any AEAD proposal for ESP, as we
1093 * don't know if our kernel backend actually supports it. */
1094 return NULL;
1095 case PROTO_AH:
1096 default:
1097 return NULL;
1098 }
1099 }
1100
1101 /*
1102 * Described in header
1103 */
1104 proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs)
1105 {
1106 private_proposal_t *this;
1107 enumerator_t *enumerator;
1108 bool failed = TRUE;
1109 char *alg;
1110
1111 this = (private_proposal_t*)proposal_create(protocol, 0);
1112
1113 /* get all tokens, separated by '-' */
1114 enumerator = enumerator_create_token(algs, "-", " ");
1115 while (enumerator->enumerate(enumerator, &alg))
1116 {
1117 if (!add_string_algo(this, alg))
1118 {
1119 failed = TRUE;
1120 break;
1121 }
1122 failed = FALSE;
1123 }
1124 enumerator->destroy(enumerator);
1125
1126 if (failed || !check_proposal(this))
1127 {
1128 destroy(this);
1129 return NULL;
1130 }
1131
1132 return &this->public;
1133 }