Coverage Report

Created: 2024-02-29 06:05

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