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