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