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