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