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