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