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