]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/encoding/payloads/proposal_substructure.c
ikev1: Get and set the lifetimes of the selected proposal/transform
[thirdparty/strongswan.git] / src / libcharon / encoding / payloads / proposal_substructure.c
CommitLineData
da42afc5 1/*
7da3143a 2 * Copyright (C) 2012-2020 Tobias Brunner
806b69a4 3 * Copyright (C) 2005-2010 Martin Willi
c71d53ba 4 * Copyright (C) 2005 Jan Hutter
1b671669 5 * HSR Hochschule fuer Technik Rapperswil
da42afc5
JH
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 */
5113680f 17
da42afc5
JH
18#include <stddef.h>
19
20#include "proposal_substructure.h"
21
4a962238
MW
22#include <encoding/payloads/encodings.h>
23#include <encoding/payloads/transform_substructure.h>
db7ef624 24#include <library.h>
12642a68 25#include <collections/linked_list.h>
60356f33 26#include <daemon.h>
da42afc5 27
c3dc864e 28/**
1bf2971f 29 * IKEv2 Value for a proposal payload.
c3dc864e
MW
30 */
31#define PROPOSAL_TYPE_VALUE 2
32
95c61cb9
JH
33typedef struct private_proposal_substructure_t private_proposal_substructure_t;
34
da42afc5 35/**
3fe05870 36 * Private data of an proposal_substructure_t object.
da42afc5 37 */
95c61cb9 38struct private_proposal_substructure_t {
806b69a4 39
da42afc5 40 /**
3fe05870 41 * Public proposal_substructure_t interface.
da42afc5
JH
42 */
43 proposal_substructure_t public;
7daf5226 44
da42afc5 45 /**
3fe05870 46 * Next payload type.
da42afc5 47 */
b12c53ce 48 uint8_t next_payload;
da42afc5 49
c93c7a75
MW
50 /**
51 * reserved byte
52 */
b12c53ce 53 uint8_t reserved;
c93c7a75 54
da42afc5 55 /**
3fe05870 56 * Length of this payload.
da42afc5 57 */
b12c53ce 58 uint16_t proposal_length;
7daf5226 59
da42afc5 60 /**
3fe05870 61 * Proposal number.
da42afc5 62 */
b12c53ce 63 uint8_t proposal_number;
7daf5226 64
da42afc5 65 /**
3fe05870 66 * Protocol ID.
da42afc5 67 */
b12c53ce 68 uint8_t protocol_id;
da42afc5
JH
69
70 /**
3fe05870 71 * SPI size of the following SPI.
da42afc5 72 */
b12c53ce 73 uint8_t spi_size;
da42afc5
JH
74
75 /**
3fe05870 76 * Number of transforms.
da42afc5 77 */
b12c53ce 78 uint8_t transforms_count;
7daf5226 79
7b3814f7
MW
80 /**
81 * SPI is stored as chunk.
82 */
83 chunk_t spi;
7daf5226 84
7b3814f7
MW
85 /**
86 * Transforms are stored in a linked_list_t.
87 */
1bf2971f
MW
88 linked_list_t *transforms;
89
90 /**
3ecfc83c 91 * Type of this payload, PLV2_PROPOSAL_SUBSTRUCTURE or PLV1_PROPOSAL_SUBSTRUCTURE
1bf2971f
MW
92 */
93 payload_type_t type;
da42afc5
JH
94};
95
96/**
1bf2971f 97 * Encoding rules for a IKEv1 Proposal substructure.
da42afc5 98 */
1bf2971f
MW
99static encoding_rule_t encodings_v1[] = {
100 /* 1 Byte next payload type, stored in the field next_payload */
101 { U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
102 /* 1 Reserved Byte */
103 { RESERVED_BYTE, offsetof(private_proposal_substructure_t, reserved) },
104 /* Length of the whole proposal substructure payload*/
105 { PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) },
106 /* proposal number is a number of 8 bit */
107 { U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) },
108 /* protocol ID is a number of 8 bit */
109 { U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) },
110 /* SPI Size has its own type */
111 { SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) },
112 /* Number of transforms is a number of 8 bit */
113 { U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) },
114 /* SPI is a chunk of variable size*/
115 { SPI, offsetof(private_proposal_substructure_t, spi) },
f62a7c7c 116 /* Transforms are stored in a transform substructure list */
3ecfc83c 117 { PAYLOAD_LIST + PLV1_TRANSFORM_SUBSTRUCTURE,
f62a7c7c 118 offsetof(private_proposal_substructure_t, transforms) },
1bf2971f
MW
119};
120
121/**
122 * Encoding rules for a IKEv2 Proposal substructure.
123 */
124static encoding_rule_t encodings_v2[] = {
7b3814f7 125 /* 1 Byte next payload type, stored in the field next_payload */
806b69a4 126 { U_INT_8, offsetof(private_proposal_substructure_t, next_payload) },
c93c7a75
MW
127 /* 1 Reserved Byte */
128 { RESERVED_BYTE, offsetof(private_proposal_substructure_t, reserved) },
b860cffd 129 /* Length of the whole proposal substructure payload*/
806b69a4 130 { PAYLOAD_LENGTH, offsetof(private_proposal_substructure_t, proposal_length) },
da42afc5 131 /* proposal number is a number of 8 bit */
806b69a4 132 { U_INT_8, offsetof(private_proposal_substructure_t, proposal_number) },
da42afc5 133 /* protocol ID is a number of 8 bit */
806b69a4 134 { U_INT_8, offsetof(private_proposal_substructure_t, protocol_id) },
da42afc5 135 /* SPI Size has its own type */
806b69a4 136 { SPI_SIZE, offsetof(private_proposal_substructure_t, spi_size) },
da42afc5 137 /* Number of transforms is a number of 8 bit */
806b69a4 138 { U_INT_8, offsetof(private_proposal_substructure_t, transforms_count) },
da42afc5 139 /* SPI is a chunk of variable size*/
806b69a4 140 { SPI, offsetof(private_proposal_substructure_t, spi) },
f62a7c7c 141 /* Transforms are stored in a transform substructure list */
3ecfc83c 142 { PAYLOAD_LIST + PLV2_TRANSFORM_SUBSTRUCTURE,
f62a7c7c 143 offsetof(private_proposal_substructure_t, transforms) },
da42afc5
JH
144};
145
e31eb71e
JH
146/*
147 1 2 3
148 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
149 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
150 ! 0 (last) or 2 ! RESERVED ! Proposal Length !
151 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
152 ! Proposal # ! Protocol ID ! SPI Size !# of Transforms!
153 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154 ~ SPI (variable) ~
155 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156 ! !
157 ~ <Transforms> ~
158 ! !
159 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
160*/
161
1bf2971f
MW
162/**
163 * Encryption.
164 */
165typedef enum {
166 IKEV1_ENCR_DES_CBC = 1,
167 IKEV1_ENCR_IDEA_CBC = 2,
168 IKEV1_ENCR_BLOWFISH_CBC = 3,
169 IKEV1_ENCR_RC5_R16_B64_CBC = 4,
170 IKEV1_ENCR_3DES_CBC = 5,
171 IKEV1_ENCR_CAST_CBC = 6,
172 IKEV1_ENCR_AES_CBC = 7,
173 IKEV1_ENCR_CAMELLIA_CBC = 8,
4b797f46
AS
174 /* FreeS/WAN proprietary */
175 IKEV1_ENCR_SERPENT_CBC = 65004,
176 IKEV1_ENCR_TWOFISH_CBC = 65005,
1bf2971f
MW
177} ikev1_encryption_t;
178
179/**
180 * IKEv1 hash.
181 */
182typedef enum {
183 IKEV1_HASH_MD5 = 1,
184 IKEV1_HASH_SHA1 = 2,
185 IKEV1_HASH_TIGER = 3,
186 IKEV1_HASH_SHA2_256 = 4,
187 IKEV1_HASH_SHA2_384 = 5,
188 IKEV1_HASH_SHA2_512 = 6,
189} ikev1_hash_t;
190
191/**
192 * IKEv1 Transform ID IKE.
193 */
194typedef enum {
195 IKEV1_TRANSID_KEY_IKE = 1,
196} ikev1_ike_transid_t;
197
198/**
4b797f46 199 * IKEv1 Transform ID ESP encryption algorithm.
1bf2971f
MW
200 */
201typedef enum {
4b797f46
AS
202 IKEV1_ESP_ENCR_DES_IV64 = 1,
203 IKEV1_ESP_ENCR_DES = 2,
204 IKEV1_ESP_ENCR_3DES = 3,
205 IKEV1_ESP_ENCR_RC5 = 4,
206 IKEV1_ESP_ENCR_IDEA = 5,
207 IKEV1_ESP_ENCR_CAST = 6,
208 IKEV1_ESP_ENCR_BLOWFISH = 7,
209 IKEV1_ESP_ENCR_3IDEA = 8,
210 IKEV1_ESP_ENCR_DES_IV32 = 9,
211 IKEV1_ESP_ENCR_RC4 = 10,
212 IKEV1_ESP_ENCR_NULL = 11,
213 IKEV1_ESP_ENCR_AES_CBC = 12,
214 IKEV1_ESP_ENCR_AES_CTR = 13,
215 IKEV1_ESP_ENCR_AES_CCM_8 = 14,
216 IKEV1_ESP_ENCR_AES_CCM_12 = 15,
217 IKEV1_ESP_ENCR_AES_CCM_16 = 16,
218 IKEV1_ESP_ENCR_AES_GCM_8 = 18,
219 IKEV1_ESP_ENCR_AES_GCM_12 = 19,
220 IKEV1_ESP_ENCR_AES_GCM_16 = 20,
221 IKEV1_ESP_ENCR_SEED_CBC = 21,
222 IKEV1_ESP_ENCR_CAMELLIA = 22,
223 IKEV1_ESP_ENCR_NULL_AUTH_AES_GMAC = 23,
224 /* FreeS/WAN proprietary */
225 IKEV1_ESP_ENCR_SERPENT = 252,
226 IKEV1_ESP_ENCR_TWOFISH = 253,
728f529c 227} ikev1_esp_transid_t;
1bf2971f 228
3771b858
MW
229/**
230 * IKEv1 Transform ID AH authentication algorithm.
231 */
232typedef enum {
233 IKEV1_AH_HMAC_MD5 = 2,
234 IKEV1_AH_HMAC_SHA = 3,
235 IKEV1_AH_DES_MAC = 4,
236 IKEV1_AH_HMAC_SHA2_256 = 5,
237 IKEV1_AH_HMAC_SHA2_384 = 6,
238 IKEV1_AH_HMAC_SHA2_512 = 7,
239 IKEV1_AH_RIPEMD = 8,
240 IKEV1_AH_AES_XCBC_MAC = 9,
241 IKEV1_AH_RSA = 10,
242 IKEV1_AH_AES_128_GMAC = 11,
243 IKEV1_AH_AES_192_GMAC = 12,
244 IKEV1_AH_AES_256_GMAC = 13,
245} ikev1_ah_transid_t;
246
728f529c
TB
247/**
248 * IKEv1 authentication algorithm.
249 */
250typedef enum {
251 IKEV1_AUTH_HMAC_MD5 = 1,
252 IKEV1_AUTH_HMAC_SHA = 2,
253 IKEV1_AUTH_DES_MAC = 3,
254 IKEV1_AUTH_KPDK = 4,
255 IKEV1_AUTH_HMAC_SHA2_256 = 5,
256 IKEV1_AUTH_HMAC_SHA2_384 = 6,
257 IKEV1_AUTH_HMAC_SHA2_512 = 7,
258 IKEV1_AUTH_HMAC_RIPEMD = 8,
259 IKEV1_AUTH_AES_XCBC_MAC = 9,
260 IKEV1_AUTH_SIG_RSA = 10,
261 IKEV1_AUTH_AES_128_GMAC = 11,
262 IKEV1_AUTH_AES_192_GMAC = 12,
263 IKEV1_AUTH_AES_256_GMAC = 13,
264} ikev1_auth_algo_t;
265
1bf2971f
MW
266/**
267 * IKEv1 ESP Encapsulation mode.
268 */
269typedef enum {
270 IKEV1_ENCAP_TUNNEL = 1,
271 IKEV1_ENCAP_TRANSPORT = 2,
272 IKEV1_ENCAP_UDP_TUNNEL = 3,
273 IKEV1_ENCAP_UDP_TRANSPORT = 4,
0ff8d20a
VR
274 IKEV1_ENCAP_UDP_TUNNEL_DRAFT_00_03 = 61443,
275 IKEV1_ENCAP_UDP_TRANSPORT_DRAFT_00_03 = 61444,
1bf2971f
MW
276} ikev1_esp_encap_t;
277
278/**
279 * IKEv1 Life duration types.
280 */
281typedef enum {
282 IKEV1_LIFE_TYPE_SECONDS = 1,
283 IKEV1_LIFE_TYPE_KILOBYTES = 2,
284} ikev1_life_type_t;
285
717333da 286/**
4b797f46 287 * IKEv1 authentication methods
717333da
MW
288 */
289typedef enum {
290 IKEV1_AUTH_PSK = 1,
291 IKEV1_AUTH_DSS_SIG = 2,
292 IKEV1_AUTH_RSA_SIG = 3,
293 IKEV1_AUTH_RSA_ENC = 4,
294 IKEV1_AUTH_RSA_ENC_REV = 5,
6261c0c3
MW
295 IKEV1_AUTH_ECDSA_256 = 9,
296 IKEV1_AUTH_ECDSA_384 = 10,
297 IKEV1_AUTH_ECDSA_521 = 11,
4b797f46 298 /* XAuth Modes */
8b30286f
CO
299 IKEV1_AUTH_XAUTH_INIT_PSK = 65001,
300 IKEV1_AUTH_XAUTH_RESP_PSK = 65002,
301 IKEV1_AUTH_XAUTH_INIT_DSS = 65003,
302 IKEV1_AUTH_XAUTH_RESP_DSS = 65004,
303 IKEV1_AUTH_XAUTH_INIT_RSA = 65005,
304 IKEV1_AUTH_XAUTH_RESP_RSA = 65006,
305 IKEV1_AUTH_XAUTH_INIT_RSA_ENC = 65007,
306 IKEV1_AUTH_XAUTH_RESP_RSA_ENC = 65008,
307 IKEV1_AUTH_XAUTH_INIT_RSA_ENC_REV = 65009,
308 IKEV1_AUTH_XAUTH_RESP_RSA_ENC_REV = 65010,
4b797f46 309 /* Hybrid Modes */
51da01a7
MW
310 IKEV1_AUTH_HYBRID_INIT_RSA = 64221,
311 IKEV1_AUTH_HYBRID_RESP_RSA = 64222,
312 IKEV1_AUTH_HYBRID_INIT_DSS = 64223,
313 IKEV1_AUTH_HYBRID_RESP_DSS = 64224,
717333da
MW
314} ikev1_auth_method_t;
315
7a75cae8
TB
316/**
317 * IKEv1 IPComp transform IDs
318 */
319typedef enum {
320 IKEV1_IPCOMP_OUI = 1,
321 IKEV1_IPCOMP_DEFLATE = 2,
322 IKEV1_IPCOMP_LZS = 3,
323} ikev1_ipcomp_transform_t;
324
806b69a4
MW
325METHOD(payload_t, verify, status_t,
326 private_proposal_substructure_t *this)
e31eb71e 327{
346af6f3 328 status_t status = SUCCESS;
806b69a4
MW
329 enumerator_t *enumerator;
330 payload_t *current;
7daf5226 331
3ecfc83c 332 if (this->next_payload != PL_NONE && this->next_payload != 2)
e31eb71e
JH
333 {
334 /* must be 0 or 2 */
b83806d8 335 DBG1(DBG_ENC, "inconsistent next payload");
e31eb71e
JH
336 return FAILED;
337 }
338 if (this->transforms_count != this->transforms->get_count(this->transforms))
339 {
340 /* must be the same! */
b83806d8 341 DBG1(DBG_ENC, "transform count invalid");
e31eb71e
JH
342 return FAILED;
343 }
344
fe04e93a
MW
345 switch (this->protocol_id)
346 {
7a75cae8 347 case PROTO_IPCOMP:
4141f016 348 if (this->spi.len != 2 && this->spi.len != 4)
7a75cae8
TB
349 {
350 DBG1(DBG_ENC, "invalid CPI length in IPCOMP proposal");
351 return FAILED;
352 }
353 break;
fe04e93a
MW
354 case PROTO_AH:
355 case PROTO_ESP:
356 if (this->spi.len != 4)
357 {
b83806d8 358 DBG1(DBG_ENC, "invalid SPI length in %N proposal",
7a75cae8 359 protocol_id_names, this->protocol_id);
fe04e93a
MW
360 return FAILED;
361 }
362 break;
363 case PROTO_IKE:
3ecfc83c 364 if (this->type == PLV1_PROPOSAL_SUBSTRUCTURE)
fe04e93a 365 {
a30e0001
TB
366 if (this->spi.len <= 16)
367 { /* according to RFC 2409, section 3.5 anything between
368 * 0 and 16 is fine */
369 break;
370 }
fe04e93a 371 }
a30e0001
TB
372 else if (this->spi.len == 0 || this->spi.len == 8)
373 {
374 break;
375 }
376 DBG1(DBG_ENC, "invalid SPI length in IKE proposal");
377 return FAILED;
fe04e93a 378 default:
806b69a4 379 break;
e31eb71e 380 }
806b69a4
MW
381 enumerator = this->transforms->create_enumerator(this->transforms);
382 while (enumerator->enumerate(enumerator, &current))
346af6f3 383 {
806b69a4 384 status = current->verify(current);
346af6f3
JH
385 if (status != SUCCESS)
386 {
b83806d8 387 DBG1(DBG_ENC, "TRANSFORM_SUBSTRUCTURE verification failed");
346af6f3
JH
388 break;
389 }
390 }
806b69a4 391 enumerator->destroy(enumerator);
7daf5226
MW
392
393 /* proposal number is checked in SA payload */
346af6f3 394 return status;
e31eb71e
JH
395}
396
e9b55b83
MW
397METHOD(payload_t, get_encoding_rules, int,
398 private_proposal_substructure_t *this, encoding_rule_t **rules)
da42afc5 399{
3ecfc83c 400 if (this->type == PLV2_PROPOSAL_SUBSTRUCTURE)
1bf2971f
MW
401 {
402 *rules = encodings_v2;
e9b55b83 403 return countof(encodings_v2);
1bf2971f 404 }
e9b55b83
MW
405 *rules = encodings_v1;
406 return countof(encodings_v1);
da42afc5
JH
407}
408
38fb67fb
MW
409METHOD(payload_t, get_header_length, int,
410 private_proposal_substructure_t *this)
411{
412 return 8 + this->spi_size;
413}
414
806b69a4
MW
415METHOD(payload_t, get_type, payload_type_t,
416 private_proposal_substructure_t *this)
da42afc5 417{
1bf2971f 418 return this->type;
da42afc5
JH
419}
420
806b69a4
MW
421METHOD(payload_t, get_next_type, payload_type_t,
422 private_proposal_substructure_t *this)
da42afc5 423{
806b69a4 424 return this->next_payload;
da42afc5
JH
425}
426
806b69a4
MW
427METHOD(payload_t, set_next_type, void,
428 private_proposal_substructure_t *this, payload_type_t type)
32cbc7bc 429{
32cbc7bc
JH
430}
431
60356f33
MW
432/**
433 * (re-)compute the length of the payload.
434 */
435static void compute_length(private_proposal_substructure_t *this)
436{
1f5b2bec
MW
437 enumerator_t *enumerator;
438 payload_t *transform;
7daf5226 439
1f5b2bec 440 this->transforms_count = 0;
38fb67fb 441 this->proposal_length = get_header_length(this);
1f5b2bec
MW
442 enumerator = this->transforms->create_enumerator(this->transforms);
443 while (enumerator->enumerate(enumerator, &transform))
60356f33 444 {
1f5b2bec
MW
445 this->proposal_length += transform->get_length(transform);
446 this->transforms_count++;
60356f33 447 }
1f5b2bec 448 enumerator->destroy(enumerator);
60356f33
MW
449}
450
806b69a4
MW
451METHOD(payload_t, get_length, size_t,
452 private_proposal_substructure_t *this)
da42afc5
JH
453{
454 return this->proposal_length;
455}
456
b860cffd 457/**
806b69a4 458 * Add a transform substructure to the proposal
b860cffd 459 */
806b69a4
MW
460static void add_transform_substructure(private_proposal_substructure_t *this,
461 transform_substructure_t *transform)
b860cffd 462{
a14dffd1
JH
463 if (this->transforms->get_count(this->transforms) > 0)
464 {
806b69a4 465 transform_substructure_t *last;
a14dffd1 466
806b69a4
MW
467 this->transforms->get_last(this->transforms, (void **)&last);
468 last->set_is_last_transform(last, FALSE);
a14dffd1
JH
469 }
470 transform->set_is_last_transform(transform,TRUE);
806b69a4 471 this->transforms->insert_last(this->transforms, transform);
60356f33 472 compute_length(this);
67978e0b
JH
473}
474
806b69a4
MW
475METHOD(proposal_substructure_t, set_is_last_proposal, void,
476 private_proposal_substructure_t *this, bool is_last)
b737e9d9 477{
806b69a4 478 this->next_payload = is_last ? 0 : PROPOSAL_TYPE_VALUE;
b737e9d9
JH
479}
480
806b69a4 481METHOD(proposal_substructure_t, set_proposal_number, void,
b12c53ce 482 private_proposal_substructure_t *this,uint8_t proposal_number)
67978e0b
JH
483{
484 this->proposal_number = proposal_number;
67978e0b
JH
485}
486
b12c53ce 487METHOD(proposal_substructure_t, get_proposal_number, uint8_t,
806b69a4 488 private_proposal_substructure_t *this)
67978e0b 489{
806b69a4 490 return this->proposal_number;
67978e0b
JH
491}
492
806b69a4 493METHOD(proposal_substructure_t, set_protocol_id, void,
b12c53ce 494 private_proposal_substructure_t *this,uint8_t protocol_id)
67978e0b
JH
495{
496 this->protocol_id = protocol_id;
67978e0b
JH
497}
498
b12c53ce 499METHOD(proposal_substructure_t, get_protocol_id, uint8_t,
806b69a4 500 private_proposal_substructure_t *this)
67978e0b 501{
806b69a4 502 return this->protocol_id;
b860cffd
JH
503}
504
806b69a4
MW
505METHOD(proposal_substructure_t, set_spi, void,
506 private_proposal_substructure_t *this, chunk_t spi)
67978e0b 507{
806b69a4
MW
508 free(this->spi.ptr);
509 this->spi = chunk_clone(spi);
67978e0b 510 this->spi_size = spi.len;
60356f33 511 compute_length(this);
67978e0b
JH
512}
513
806b69a4
MW
514METHOD(proposal_substructure_t, get_spi, chunk_t,
515 private_proposal_substructure_t *this)
67978e0b 516{
806b69a4 517 return this->spi;
67978e0b
JH
518}
519
7a75cae8 520METHOD(proposal_substructure_t, get_cpi, bool,
b12c53ce 521 private_proposal_substructure_t *this, uint16_t *cpi)
7a75cae8
TB
522{
523
524 transform_substructure_t *transform;
525 enumerator_t *enumerator;
526
527 if (this->protocol_id != PROTO_IPCOMP)
528 {
529 return FALSE;
530 }
531
532 enumerator = this->transforms->create_enumerator(this->transforms);
533 while (enumerator->enumerate(enumerator, &transform))
534 {
535 if (transform->get_transform_id(transform) == IKEV1_IPCOMP_DEFLATE)
536 {
537 if (cpi)
538 {
4141f016 539 *cpi = htons(untoh16(this->spi.ptr + this->spi.len - 2));
7a75cae8
TB
540 }
541 enumerator->destroy(enumerator);
542 return TRUE;
543 }
544 }
545 enumerator->destroy(enumerator);
546 return FALSE;
547}
548
1bf2971f
MW
549/**
550 * Add a transform to a proposal for IKEv2
551 */
552static void add_to_proposal_v2(proposal_t *proposal,
553 transform_substructure_t *transform)
554{
555 transform_attribute_t *tattr;
556 enumerator_t *enumerator;
b12c53ce 557 uint16_t key_length = 0;
1bf2971f
MW
558
559 enumerator = transform->create_attribute_enumerator(transform);
560 while (enumerator->enumerate(enumerator, &tattr))
561 {
562 if (tattr->get_attribute_type(tattr) == TATTR_IKEV2_KEY_LENGTH)
563 {
564 key_length = tattr->get_value(tattr);
565 break;
566 }
567 }
568 enumerator->destroy(enumerator);
569
570 proposal->add_algorithm(proposal,
571 transform->get_transform_type_or_number(transform),
572 transform->get_transform_id(transform), key_length);
573}
574
3a470f30
MW
575/**
576 * Map IKEv1 to IKEv2 algorithms
577 */
578typedef struct {
b12c53ce
AS
579 uint16_t ikev1;
580 uint16_t ikev2;
3a470f30
MW
581} algo_map_t;
582
583/**
584 * Encryption algorithm mapping
585 */
586static algo_map_t map_encr[] = {
587 { IKEV1_ENCR_DES_CBC, ENCR_DES },
588 { IKEV1_ENCR_IDEA_CBC, ENCR_IDEA },
589 { IKEV1_ENCR_BLOWFISH_CBC, ENCR_BLOWFISH },
590 { IKEV1_ENCR_3DES_CBC, ENCR_3DES },
591 { IKEV1_ENCR_CAST_CBC, ENCR_CAST },
592 { IKEV1_ENCR_AES_CBC, ENCR_AES_CBC },
593 { IKEV1_ENCR_CAMELLIA_CBC, ENCR_CAMELLIA_CBC },
4b797f46
AS
594 { IKEV1_ENCR_SERPENT_CBC, ENCR_SERPENT_CBC },
595 { IKEV1_ENCR_TWOFISH_CBC, ENCR_TWOFISH_CBC },
3a470f30
MW
596};
597
598/**
599 * Integrity algorithm mapping
600 */
601static algo_map_t map_integ[] = {
602 { IKEV1_HASH_MD5, AUTH_HMAC_MD5_96 },
603 { IKEV1_HASH_SHA1, AUTH_HMAC_SHA1_96 },
604 { IKEV1_HASH_SHA2_256, AUTH_HMAC_SHA2_256_128 },
605 { IKEV1_HASH_SHA2_384, AUTH_HMAC_SHA2_384_192 },
606 { IKEV1_HASH_SHA2_512, AUTH_HMAC_SHA2_512_256 },
607};
608
609/**
610 * PRF algorithm mapping
611 */
612static algo_map_t map_prf[] = {
613 { IKEV1_HASH_MD5, PRF_HMAC_MD5 },
614 { IKEV1_HASH_SHA1, PRF_HMAC_SHA1 },
615 { IKEV1_HASH_SHA2_256, PRF_HMAC_SHA2_256 },
616 { IKEV1_HASH_SHA2_384, PRF_HMAC_SHA2_384 },
617 { IKEV1_HASH_SHA2_512, PRF_HMAC_SHA2_512 },
618};
619
4b797f46
AS
620/**
621 * ESP encryption algorithm mapping
622 */
728f529c 623static algo_map_t map_esp[] = {
4b797f46
AS
624 { IKEV1_ESP_ENCR_DES_IV64, ENCR_DES_IV64 },
625 { IKEV1_ESP_ENCR_DES, ENCR_DES },
626 { IKEV1_ESP_ENCR_3DES, ENCR_3DES },
627 { IKEV1_ESP_ENCR_RC5, ENCR_RC5 },
628 { IKEV1_ESP_ENCR_IDEA, ENCR_IDEA },
629 { IKEV1_ESP_ENCR_CAST, ENCR_CAST },
630 { IKEV1_ESP_ENCR_BLOWFISH, ENCR_BLOWFISH },
631 { IKEV1_ESP_ENCR_3IDEA, ENCR_3IDEA },
632 { IKEV1_ESP_ENCR_DES_IV32, ENCR_DES_IV32 },
633 { IKEV1_ESP_ENCR_NULL, ENCR_NULL },
634 { IKEV1_ESP_ENCR_AES_CBC, ENCR_AES_CBC },
635 { IKEV1_ESP_ENCR_AES_CTR, ENCR_AES_CTR },
636 { IKEV1_ESP_ENCR_AES_CCM_8, ENCR_AES_CCM_ICV8 },
637 { IKEV1_ESP_ENCR_AES_CCM_12, ENCR_AES_CCM_ICV12 },
638 { IKEV1_ESP_ENCR_AES_CCM_16, ENCR_AES_CCM_ICV16 },
639 { IKEV1_ESP_ENCR_AES_GCM_8, ENCR_AES_GCM_ICV8 },
640 { IKEV1_ESP_ENCR_AES_GCM_12, ENCR_AES_GCM_ICV12 },
641 { IKEV1_ESP_ENCR_AES_GCM_16, ENCR_AES_GCM_ICV16 },
642 { IKEV1_ESP_ENCR_CAMELLIA, ENCR_CAMELLIA_CBC },
643 { IKEV1_ESP_ENCR_NULL_AUTH_AES_GMAC, ENCR_NULL_AUTH_AES_GMAC },
644 { IKEV1_ESP_ENCR_SERPENT, ENCR_SERPENT_CBC },
645 { IKEV1_ESP_ENCR_TWOFISH, ENCR_TWOFISH_CBC },
646};
647
3771b858
MW
648/**
649 * AH authentication algorithm mapping
650 */
651static algo_map_t map_ah[] = {
652 { IKEV1_AH_HMAC_MD5, AUTH_HMAC_MD5_96 },
653 { IKEV1_AH_HMAC_SHA, AUTH_HMAC_SHA1_96 },
654 { IKEV1_AH_DES_MAC, AUTH_DES_MAC },
655 { IKEV1_AH_HMAC_SHA2_256, AUTH_HMAC_SHA2_256_128 },
656 { IKEV1_AH_HMAC_SHA2_384, AUTH_HMAC_SHA2_384_192 },
657 { IKEV1_AH_HMAC_SHA2_512, AUTH_HMAC_SHA2_512_256 },
658 { IKEV1_AH_AES_XCBC_MAC, AUTH_AES_XCBC_96 },
659 { IKEV1_AH_AES_128_GMAC, AUTH_AES_128_GMAC },
660 { IKEV1_AH_AES_192_GMAC, AUTH_AES_192_GMAC },
661 { IKEV1_AH_AES_256_GMAC, AUTH_AES_256_GMAC },
662};
663
1bf2971f 664/**
728f529c 665 * ESP/AH authentication algorithm mapping
1bf2971f 666 */
728f529c
TB
667static algo_map_t map_auth[] = {
668 { IKEV1_AUTH_HMAC_MD5, AUTH_HMAC_MD5_96 },
669 { IKEV1_AUTH_HMAC_SHA, AUTH_HMAC_SHA1_96 },
670 { IKEV1_AUTH_DES_MAC, AUTH_DES_MAC },
671 { IKEV1_AUTH_KPDK, AUTH_KPDK_MD5 },
672 { IKEV1_AUTH_HMAC_SHA2_256, AUTH_HMAC_SHA2_256_128 },
673 { IKEV1_AUTH_HMAC_SHA2_384, AUTH_HMAC_SHA2_384_192 },
674 { IKEV1_AUTH_HMAC_SHA2_512, AUTH_HMAC_SHA2_512_256 },
675 { IKEV1_AUTH_AES_XCBC_MAC, AUTH_AES_XCBC_96 },
676 { IKEV1_AUTH_AES_128_GMAC, AUTH_AES_128_GMAC },
677 { IKEV1_AUTH_AES_192_GMAC, AUTH_AES_192_GMAC },
678 { IKEV1_AUTH_AES_256_GMAC, AUTH_AES_256_GMAC },
679};
680
681/**
682 * Map an IKEv1 to an IKEv2 identifier
683 */
b12c53ce
AS
684static uint16_t ikev2_from_ikev1(algo_map_t *map, int count, uint16_t def,
685 uint16_t value)
1bf2971f 686{
728f529c 687 int i;
1bf2971f 688
1bf2971f
MW
689 for (i = 0; i < count; i++)
690 {
691 if (map[i].ikev1 == value)
692 {
693 return map[i].ikev2;
694 }
695 }
696 return def;
697}
698
3a470f30 699/**
728f529c 700 * Map an IKEv2 to an IKEv1 identifier
3a470f30 701 */
b12c53ce 702static uint16_t ikev1_from_ikev2(algo_map_t *map, int count, uint16_t value)
3a470f30 703{
728f529c 704 int i;
3a470f30 705
3a470f30
MW
706 for (i = 0; i < count; i++)
707 {
708 if (map[i].ikev2 == value)
709 {
710 return map[i].ikev1;
711 }
712 }
713 return 0;
714}
715
4b797f46 716/**
728f529c 717 * Get IKEv2 algorithm from IKEv1 identifier
4b797f46 718 */
b12c53ce 719static uint16_t get_alg_from_ikev1(transform_type_t type, uint16_t value)
4b797f46 720{
4b797f46
AS
721 switch (type)
722 {
723 case ENCRYPTION_ALGORITHM:
728f529c
TB
724 return ikev2_from_ikev1(map_encr, countof(map_encr),
725 ENCR_UNDEFINED, value);
4b797f46 726 case INTEGRITY_ALGORITHM:
728f529c
TB
727 return ikev2_from_ikev1(map_integ, countof(map_integ),
728 AUTH_UNDEFINED, value);
729 case PSEUDO_RANDOM_FUNCTION:
730 return ikev2_from_ikev1(map_prf, countof(map_prf),
731 PRF_UNDEFINED, value);
4b797f46
AS
732 default:
733 return 0;
734 }
728f529c
TB
735}
736
737/**
738 * Get IKEv1 algorithm from IKEv2 identifier
739 */
b12c53ce 740static uint16_t get_ikev1_from_alg(transform_type_t type, uint16_t value)
728f529c
TB
741{
742 switch (type)
4b797f46 743 {
728f529c
TB
744 case ENCRYPTION_ALGORITHM:
745 return ikev1_from_ikev2(map_encr, countof(map_encr), value);
746 case INTEGRITY_ALGORITHM:
747 return ikev1_from_ikev2(map_integ, countof(map_integ), value);
748 case PSEUDO_RANDOM_FUNCTION:
749 return ikev1_from_ikev2(map_prf, countof(map_prf), value);
750 default:
751 return 0;
4b797f46 752 }
4b797f46
AS
753}
754
755/**
728f529c 756 * Get IKEv2 algorithm from IKEv1 ESP/AH transform ID
4b797f46 757 */
b12c53ce
AS
758static uint16_t get_alg_from_ikev1_transid(transform_type_t type,
759 uint16_t value)
4b797f46 760{
4b797f46
AS
761 switch (type)
762 {
763 case ENCRYPTION_ALGORITHM:
728f529c
TB
764 return ikev2_from_ikev1(map_esp, countof(map_esp),
765 ENCR_UNDEFINED, value);
4b797f46 766 case INTEGRITY_ALGORITHM:
728f529c
TB
767 return ikev2_from_ikev1(map_ah, countof(map_ah),
768 AUTH_UNDEFINED, value);
4b797f46
AS
769 default:
770 return 0;
771 }
728f529c
TB
772}
773
774/**
775 * Get IKEv1 ESP/AH transform ID from IKEv2 identifier
776 */
b12c53ce
AS
777static uint16_t get_ikev1_transid_from_alg(transform_type_t type,
778 uint16_t value)
728f529c
TB
779{
780 switch (type)
4b797f46 781 {
728f529c
TB
782 case ENCRYPTION_ALGORITHM:
783 return ikev1_from_ikev2(map_esp, countof(map_esp), value);
784 case INTEGRITY_ALGORITHM:
785 return ikev1_from_ikev2(map_ah, countof(map_ah), value);
786 default:
787 return 0;
4b797f46 788 }
4b797f46 789}
728f529c
TB
790
791/**
792 * Get IKEv1 authentication algorithm from IKEv2 identifier
793 */
b12c53ce 794static uint16_t get_alg_from_ikev1_auth(uint16_t value)
728f529c
TB
795{
796 return ikev2_from_ikev1(map_auth, countof(map_auth), AUTH_UNDEFINED, value);
797}
798
799/**
800 * Get IKEv1 authentication algorithm from IKEv2 identifier
801 */
b12c53ce 802static uint16_t get_ikev1_auth_from_alg(uint16_t value)
728f529c
TB
803{
804 return ikev1_from_ikev2(map_auth, countof(map_auth), value);
805}
806
fbebc2a0
MW
807/**
808 * Get IKEv1 authentication attribute from auth_method_t
809 */
b12c53ce 810static uint16_t get_ikev1_auth(auth_method_t method)
fbebc2a0
MW
811{
812 switch (method)
813 {
814 case AUTH_RSA:
815 return IKEV1_AUTH_RSA_SIG;
816 case AUTH_DSS:
817 return IKEV1_AUTH_DSS_SIG;
b4e81535
MW
818 case AUTH_XAUTH_INIT_PSK:
819 return IKEV1_AUTH_XAUTH_INIT_PSK;
a9aa75b9
MW
820 case AUTH_XAUTH_RESP_PSK:
821 return IKEV1_AUTH_XAUTH_RESP_PSK;
b4e81535
MW
822 case AUTH_XAUTH_INIT_RSA:
823 return IKEV1_AUTH_XAUTH_INIT_RSA;
a9aa75b9
MW
824 case AUTH_XAUTH_RESP_RSA:
825 return IKEV1_AUTH_XAUTH_RESP_RSA;
51da01a7
MW
826 case AUTH_HYBRID_INIT_RSA:
827 return IKEV1_AUTH_HYBRID_INIT_RSA;
a9aa75b9
MW
828 case AUTH_HYBRID_RESP_RSA:
829 return IKEV1_AUTH_HYBRID_RESP_RSA;
6261c0c3
MW
830 case AUTH_ECDSA_256:
831 return IKEV1_AUTH_ECDSA_256;
832 case AUTH_ECDSA_384:
833 return IKEV1_AUTH_ECDSA_384;
834 case AUTH_ECDSA_521:
835 return IKEV1_AUTH_ECDSA_521;
fbebc2a0 836 case AUTH_PSK:
6261c0c3 837 default:
fbebc2a0
MW
838 return IKEV1_AUTH_PSK;
839 }
840}
841
842/**
843 * Get IKEv1 encapsulation mode
844 */
b12c53ce 845static uint16_t get_ikev1_mode(ipsec_mode_t mode, encap_t udp)
fbebc2a0
MW
846{
847 switch (mode)
848 {
849 case MODE_TUNNEL:
0ff8d20a
VR
850 switch (udp)
851 {
852 case ENCAP_UDP:
853 return IKEV1_ENCAP_UDP_TUNNEL;
854 case ENCAP_UDP_DRAFT_00_03:
855 return IKEV1_ENCAP_UDP_TUNNEL_DRAFT_00_03;
856 default:
857 return IKEV1_ENCAP_TUNNEL;
858 }
fbebc2a0 859 case MODE_TRANSPORT:
0ff8d20a
VR
860 switch (udp)
861 {
862 case ENCAP_UDP:
863 return IKEV1_ENCAP_UDP_TRANSPORT;
864 case ENCAP_UDP_DRAFT_00_03:
865 return IKEV1_ENCAP_UDP_TRANSPORT_DRAFT_00_03;
866 default:
867 return IKEV1_ENCAP_TRANSPORT;
868 }
fbebc2a0
MW
869 default:
870 return IKEV1_ENCAP_TUNNEL;
871 }
872}
873
1bf2971f
MW
874/**
875 * Add an IKE transform to a proposal for IKEv1
876 */
877static void add_to_proposal_v1_ike(proposal_t *proposal,
878 transform_substructure_t *transform)
879{
880 transform_attribute_type_t type;
881 transform_attribute_t *tattr;
882 enumerator_t *enumerator;
b12c53ce
AS
883 uint16_t value, key_length = 0;
884 uint16_t encr = ENCR_UNDEFINED;
1bf2971f
MW
885
886 enumerator = transform->create_attribute_enumerator(transform);
887 while (enumerator->enumerate(enumerator, &tattr))
888 {
889 type = tattr->get_attribute_type(tattr);
890 value = tattr->get_value(tattr);
891 switch (type)
892 {
893 case TATTR_PH1_ENCRYPTION_ALGORITHM:
894 encr = get_alg_from_ikev1(ENCRYPTION_ALGORITHM, value);
895 break;
896 case TATTR_PH1_KEY_LENGTH:
897 key_length = value;
898 break;
899 case TATTR_PH1_HASH_ALGORITHM:
900 proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM,
901 get_alg_from_ikev1(INTEGRITY_ALGORITHM, value), 0);
902 proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION,
903 get_alg_from_ikev1(PSEUDO_RANDOM_FUNCTION, value), 0);
904 break;
905 case TATTR_PH1_GROUP:
906 proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
907 value, 0);
908 break;
909 default:
1bf2971f
MW
910 break;
911 }
912 }
913 enumerator->destroy(enumerator);
914
915 if (encr != ENCR_UNDEFINED)
916 {
636b2e9b
TB
917 if (encr == ENCR_AES_CBC && !key_length)
918 { /* some implementations don't send a Key Length attribute for
919 * AES-128, early drafts of RFC 3602 allowed that */
920 key_length = 128;
921 }
1bf2971f
MW
922 proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, key_length);
923 }
924}
925
926/**
3771b858 927 * Add an ESP/AH transform to a proposal for IKEv1
1bf2971f 928 */
3771b858
MW
929static void add_to_proposal_v1(proposal_t *proposal,
930 transform_substructure_t *transform, protocol_id_t proto)
1bf2971f 931{
cc9629d8
MW
932 transform_attribute_type_t type;
933 transform_attribute_t *tattr;
934 enumerator_t *enumerator;
b12c53ce 935 uint16_t encr, value, key_length = 0;
40bb4677 936 extended_sequence_numbers_t esn = NO_EXT_SEQ_NUMBERS;
cc9629d8
MW
937
938 enumerator = transform->create_attribute_enumerator(transform);
939 while (enumerator->enumerate(enumerator, &tattr))
940 {
941 type = tattr->get_attribute_type(tattr);
942 value = tattr->get_value(tattr);
943 switch (type)
944 {
945 case TATTR_PH2_KEY_LENGTH:
946 key_length = value;
947 break;
948 case TATTR_PH2_AUTH_ALGORITHM:
949 proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM,
728f529c 950 get_alg_from_ikev1_auth(value), 0);
cc9629d8 951 break;
9bb4de1d
MW
952 case TATTR_PH2_GROUP:
953 proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP,
954 value, 0);
955 break;
40bb4677
TE
956 case TATTR_PH2_EXT_SEQ_NUMBER:
957 esn = EXT_SEQ_NUMBERS;
958 break;
cc9629d8 959 default:
cc9629d8
MW
960 break;
961 }
962 }
963 enumerator->destroy(enumerator);
964
40bb4677 965 proposal->add_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS, esn, 0);
3771b858 966 if (proto == PROTO_ESP)
4b797f46 967 {
728f529c 968 encr = get_alg_from_ikev1_transid(ENCRYPTION_ALGORITHM,
3771b858
MW
969 transform->get_transform_id(transform));
970 if (encr)
971 {
636b2e9b
TB
972 if (encr == ENCR_AES_CBC && !key_length)
973 { /* some implementations don't send a Key Length attribute for
974 * AES-128, early drafts of RFC 3602 allowed that for IKE, some
975 * also seem to do it for ESP */
976 key_length = 128;
977 }
3771b858
MW
978 proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr,
979 key_length);
980 }
4b797f46 981 }
1bf2971f
MW
982}
983
d50152a7
MW
984METHOD(proposal_substructure_t, get_proposals, void,
985 private_proposal_substructure_t *this, linked_list_t *proposals)
b737e9d9 986{
191a26a6 987 transform_substructure_t *transform;
1bf2971f 988 enumerator_t *enumerator;
d50152a7 989 proposal_t *proposal = NULL;
b12c53ce 990 uint64_t spi = 0;
7daf5226 991
d50152a7
MW
992 switch (this->spi.len)
993 {
994 case 4:
b12c53ce 995 spi = *((uint32_t*)this->spi.ptr);
d50152a7
MW
996 break;
997 case 8:
b12c53ce 998 spi = *((uint64_t*)this->spi.ptr);
d50152a7
MW
999 break;
1000 default:
1001 break;
1002 }
7daf5226 1003
806b69a4
MW
1004 enumerator = this->transforms->create_enumerator(this->transforms);
1005 while (enumerator->enumerate(enumerator, &transform))
c06dbbab 1006 {
3ecfc83c 1007 if (this->type == PLV2_PROPOSAL_SUBSTRUCTURE)
1bf2971f 1008 {
7da3143a
TB
1009 if (!proposal)
1010 {
1011 proposal = proposal_create(this->protocol_id,
1012 this->proposal_number);
1013 proposal->set_spi(proposal, spi);
1014 proposals->insert_last(proposals, proposal);
1015 }
1bf2971f
MW
1016 add_to_proposal_v2(proposal, transform);
1017 }
1018 else
1019 {
7da3143a
TB
1020 /* create a new proposal for each transform in IKEv1 */
1021 proposal = proposal_create_v1(
1022 this->protocol_id, this->proposal_number,
1023 transform->get_transform_type_or_number(transform));
1024 proposal->set_spi(proposal, spi);
1025 proposals->insert_last(proposals, proposal);
1bf2971f
MW
1026 switch (this->protocol_id)
1027 {
1028 case PROTO_IKE:
1029 add_to_proposal_v1_ike(proposal, transform);
1030 break;
1031 case PROTO_ESP:
3771b858
MW
1032 case PROTO_AH:
1033 add_to_proposal_v1(proposal, transform, this->protocol_id);
1bf2971f
MW
1034 break;
1035 default:
1036 break;
1037 }
1bf2971f 1038 }
c06dbbab 1039 }
806b69a4 1040 enumerator->destroy(enumerator);
c06dbbab
MW
1041}
1042
54f2bdd6
MW
1043METHOD(proposal_substructure_t, create_substructure_enumerator, enumerator_t*,
1044 private_proposal_substructure_t *this)
1045{
1046 return this->transforms->create_enumerator(this->transforms);
1047}
1048
914ec2db 1049/**
927c1dd9 1050 * Get an attribute from any transform, 0 if not found
914ec2db 1051 */
b12c53ce 1052static uint64_t get_attr(private_proposal_substructure_t *this,
927c1dd9 1053 transform_attribute_type_t type)
914ec2db 1054{
927c1dd9
MW
1055 enumerator_t *transforms, *attributes;
1056 transform_substructure_t *transform;
914ec2db 1057 transform_attribute_t *attr;
914ec2db 1058
927c1dd9
MW
1059 transforms = this->transforms->create_enumerator(this->transforms);
1060 while (transforms->enumerate(transforms, &transform))
914ec2db 1061 {
927c1dd9
MW
1062 attributes = transform->create_attribute_enumerator(transform);
1063 while (attributes->enumerate(attributes, &attr))
914ec2db 1064 {
927c1dd9
MW
1065 if (attr->get_attribute_type(attr) == type)
1066 {
1067 attributes->destroy(attributes);
1068 transforms->destroy(transforms);
1069 return attr->get_value(attr);
1070 }
914ec2db 1071 }
927c1dd9 1072 attributes->destroy(attributes);
914ec2db 1073 }
927c1dd9
MW
1074 transforms->destroy(transforms);
1075 return 0;
914ec2db
MW
1076}
1077
914ec2db 1078/**
927c1dd9 1079 * Look up a lifetime duration of a given kind in all transforms
914ec2db 1080 */
b12c53ce 1081static uint64_t get_life_duration(private_proposal_substructure_t *this,
e0dd36c9
TB
1082 uint8_t number, transform_attribute_type_t type_attr,
1083 ikev1_life_type_t type, transform_attribute_type_t dur_attr)
914ec2db 1084{
927c1dd9 1085 enumerator_t *transforms, *attributes;
914ec2db 1086 transform_substructure_t *transform;
927c1dd9 1087 transform_attribute_t *attr;
914ec2db 1088
927c1dd9
MW
1089 transforms = this->transforms->create_enumerator(this->transforms);
1090 while (transforms->enumerate(transforms, &transform))
914ec2db 1091 {
e0dd36c9
TB
1092 if (transform->get_transform_type_or_number(transform) != number)
1093 {
1094 continue;
1095 }
927c1dd9
MW
1096 attributes = transform->create_attribute_enumerator(transform);
1097 while (attributes->enumerate(attributes, &attr))
914ec2db 1098 {
927c1dd9
MW
1099 if (attr->get_attribute_type(attr) == type_attr &&
1100 attr->get_value(attr) == type)
1101 { /* got type attribute, look for duration following next */
1102 while (attributes->enumerate(attributes, &attr))
1103 {
1104 if (attr->get_attribute_type(attr) == dur_attr)
1105 {
1106 attributes->destroy(attributes);
1107 transforms->destroy(transforms);
1108 return attr->get_value(attr);
1109 }
1110 }
914ec2db 1111 }
914ec2db 1112 }
927c1dd9 1113 attributes->destroy(attributes);
914ec2db 1114 }
927c1dd9
MW
1115 transforms->destroy(transforms);
1116 return 0;
914ec2db
MW
1117}
1118
b12c53ce 1119METHOD(proposal_substructure_t, get_lifetime, uint32_t,
e0dd36c9 1120 private_proposal_substructure_t *this, uint8_t transform)
914ec2db 1121{
b12c53ce 1122 uint32_t duration;
914ec2db
MW
1123
1124 switch (this->protocol_id)
1125 {
1126 case PROTO_IKE:
e0dd36c9
TB
1127 return get_life_duration(this, transform, TATTR_PH1_LIFE_TYPE,
1128 IKEV1_LIFE_TYPE_SECONDS, TATTR_PH1_LIFE_DURATION);
914ec2db 1129 case PROTO_ESP:
3771b858 1130 case PROTO_AH:
e0dd36c9
TB
1131 duration = get_life_duration(this, transform,
1132 TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS,
1133 TATTR_PH2_SA_LIFE_DURATION);
927c1dd9 1134 if (!duration)
914ec2db
MW
1135 { /* default to 8 hours, RFC 2407 */
1136 return 28800;
1137 }
927c1dd9 1138 return duration;
914ec2db 1139 default:
927c1dd9 1140 return 0;
914ec2db 1141 }
914ec2db
MW
1142}
1143
b12c53ce 1144METHOD(proposal_substructure_t, get_lifebytes, uint64_t,
e0dd36c9 1145 private_proposal_substructure_t *this, uint8_t transform)
914ec2db 1146{
914ec2db
MW
1147 switch (this->protocol_id)
1148 {
914ec2db 1149 case PROTO_ESP:
3771b858 1150 case PROTO_AH:
e0dd36c9
TB
1151 return 1000 * get_life_duration(this, transform,
1152 TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_KILOBYTES,
1153 TATTR_PH2_SA_LIFE_DURATION);
927c1dd9 1154 case PROTO_IKE:
914ec2db 1155 default:
927c1dd9 1156 return 0;
914ec2db 1157 }
914ec2db
MW
1158}
1159
1160METHOD(proposal_substructure_t, get_auth_method, auth_method_t,
1161 private_proposal_substructure_t *this)
1162{
927c1dd9 1163 switch (get_attr(this, TATTR_PH1_AUTH_METHOD))
914ec2db
MW
1164 {
1165 case IKEV1_AUTH_PSK:
1166 return AUTH_PSK;
1167 case IKEV1_AUTH_RSA_SIG:
1168 return AUTH_RSA;
1169 case IKEV1_AUTH_DSS_SIG:
1170 return AUTH_DSS;
b4e81535
MW
1171 case IKEV1_AUTH_XAUTH_INIT_PSK:
1172 return AUTH_XAUTH_INIT_PSK;
a9aa75b9
MW
1173 case IKEV1_AUTH_XAUTH_RESP_PSK:
1174 return AUTH_XAUTH_RESP_PSK;
b4e81535
MW
1175 case IKEV1_AUTH_XAUTH_INIT_RSA:
1176 return AUTH_XAUTH_INIT_RSA;
a9aa75b9
MW
1177 case IKEV1_AUTH_XAUTH_RESP_RSA:
1178 return AUTH_XAUTH_RESP_RSA;
51da01a7
MW
1179 case IKEV1_AUTH_HYBRID_INIT_RSA:
1180 return AUTH_HYBRID_INIT_RSA;
a9aa75b9
MW
1181 case IKEV1_AUTH_HYBRID_RESP_RSA:
1182 return AUTH_HYBRID_RESP_RSA;
6261c0c3
MW
1183 case IKEV1_AUTH_ECDSA_256:
1184 return AUTH_ECDSA_256;
1185 case IKEV1_AUTH_ECDSA_384:
1186 return AUTH_ECDSA_384;
1187 case IKEV1_AUTH_ECDSA_521:
1188 return AUTH_ECDSA_521;
914ec2db 1189 default:
914ec2db
MW
1190 return AUTH_NONE;
1191 }
1192}
1193
1194METHOD(proposal_substructure_t, get_encap_mode, ipsec_mode_t,
1195 private_proposal_substructure_t *this, bool *udp)
1196{
1197 *udp = FALSE;
927c1dd9 1198 switch (get_attr(this, TATTR_PH2_ENCAP_MODE))
914ec2db
MW
1199 {
1200 case IKEV1_ENCAP_TRANSPORT:
1201 return MODE_TRANSPORT;
1202 case IKEV1_ENCAP_TUNNEL:
5ed4b727 1203 return MODE_TUNNEL;
914ec2db 1204 case IKEV1_ENCAP_UDP_TRANSPORT:
0ff8d20a 1205 case IKEV1_ENCAP_UDP_TRANSPORT_DRAFT_00_03:
914ec2db
MW
1206 *udp = TRUE;
1207 return MODE_TRANSPORT;
1208 case IKEV1_ENCAP_UDP_TUNNEL:
0ff8d20a 1209 case IKEV1_ENCAP_UDP_TUNNEL_DRAFT_00_03:
914ec2db
MW
1210 *udp = TRUE;
1211 return MODE_TUNNEL;
1212 default:
1213 /* default to TUNNEL, RFC 2407 says implementation specific */
1214 return MODE_TUNNEL;
1215 }
1216}
1217
806b69a4
MW
1218METHOD2(payload_t, proposal_substructure_t, destroy, void,
1219 private_proposal_substructure_t *this)
b9459040 1220{
55bbff11 1221 this->transforms->destroy_offset(this->transforms,
1bf2971f 1222 offsetof(payload_t, destroy));
55bbff11 1223 chunk_free(&this->spi);
5113680f 1224 free(this);
b9459040 1225}
67978e0b 1226
da42afc5 1227/*
3fe05870 1228 * Described in header.
da42afc5 1229 */
1bf2971f 1230proposal_substructure_t *proposal_substructure_create(payload_type_t type)
da42afc5 1231{
806b69a4
MW
1232 private_proposal_substructure_t *this;
1233
1234 INIT(this,
1235 .public = {
1236 .payload_interface = {
1237 .verify = _verify,
1238 .get_encoding_rules = _get_encoding_rules,
38fb67fb 1239 .get_header_length = _get_header_length,
806b69a4
MW
1240 .get_length = _get_length,
1241 .get_next_type = _get_next_type,
1242 .set_next_type = _set_next_type,
1243 .get_type = _get_type,
1244 .destroy = _destroy,
1245 },
1246 .set_proposal_number = _set_proposal_number,
1247 .get_proposal_number = _get_proposal_number,
1248 .set_protocol_id = _set_protocol_id,
1249 .get_protocol_id = _get_protocol_id,
1250 .set_is_last_proposal = _set_is_last_proposal,
d50152a7 1251 .get_proposals = _get_proposals,
54f2bdd6 1252 .create_substructure_enumerator = _create_substructure_enumerator,
806b69a4
MW
1253 .set_spi = _set_spi,
1254 .get_spi = _get_spi,
7a75cae8 1255 .get_cpi = _get_cpi,
914ec2db
MW
1256 .get_lifetime = _get_lifetime,
1257 .get_lifebytes = _get_lifebytes,
1258 .get_auth_method = _get_auth_method,
1259 .get_encap_mode = _get_encap_mode,
806b69a4
MW
1260 .destroy = _destroy,
1261 },
3ecfc83c 1262 .next_payload = PL_NONE,
806b69a4 1263 .transforms = linked_list_create(),
1bf2971f 1264 .type = type,
806b69a4 1265 );
38fb67fb 1266 compute_length(this);
806b69a4
MW
1267
1268 return &this->public;
da42afc5 1269}
384efc76 1270
3a470f30
MW
1271/**
1272 * Add an IKEv1 IKE proposal to the substructure
384efc76 1273 */
3a470f30 1274static void set_from_proposal_v1_ike(private_proposal_substructure_t *this,
b12c53ce 1275 proposal_t *proposal, uint32_t lifetime,
fbebc2a0 1276 auth_method_t method, int number)
384efc76 1277{
384efc76 1278 transform_substructure_t *transform;
b12c53ce 1279 uint16_t alg, key_size;
3c7e72f5 1280 enumerator_t *enumerator;
1bf2971f 1281
3ecfc83c 1282 transform = transform_substructure_create_type(PLV1_TRANSFORM_SUBSTRUCTURE,
62a27ba3 1283 number, IKEV1_TRANSID_KEY_IKE);
3a470f30
MW
1284
1285 enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
a0f6f393 1286 while (enumerator->enumerate(enumerator, &alg, &key_size))
3a470f30
MW
1287 {
1288 alg = get_ikev1_from_alg(ENCRYPTION_ALGORITHM, alg);
1289 if (alg)
1290 {
1291 transform->add_transform_attribute(transform,
3ecfc83c 1292 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
3a470f30
MW
1293 TATTR_PH1_ENCRYPTION_ALGORITHM, alg));
1294 if (key_size)
1295 {
1296 transform->add_transform_attribute(transform,
3ecfc83c 1297 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
3a470f30
MW
1298 TATTR_PH1_KEY_LENGTH, key_size));
1299 }
a0f6f393 1300 break;
3a470f30
MW
1301 }
1302 }
1303 enumerator->destroy(enumerator);
1304
1305 /* encode the integrity algorithm as hash and assume use the same PRF */
1306 enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
a0f6f393 1307 while (enumerator->enumerate(enumerator, &alg, &key_size))
1bf2971f 1308 {
3a470f30
MW
1309 alg = get_ikev1_from_alg(INTEGRITY_ALGORITHM, alg);
1310 if (alg)
1311 {
1312 transform->add_transform_attribute(transform,
3ecfc83c 1313 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
3a470f30 1314 TATTR_PH1_HASH_ALGORITHM, alg));
a0f6f393 1315 break;
3a470f30 1316 }
1bf2971f 1317 }
3a470f30 1318 enumerator->destroy(enumerator);
7daf5226 1319
3a470f30 1320 enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
cd89f1a0 1321 if (enumerator->enumerate(enumerator, &alg, &key_size))
3a470f30
MW
1322 {
1323 transform->add_transform_attribute(transform,
3ecfc83c 1324 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
3a470f30
MW
1325 TATTR_PH1_GROUP, alg));
1326 }
1327 enumerator->destroy(enumerator);
1328
717333da 1329 transform->add_transform_attribute(transform,
3ecfc83c 1330 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
fbebc2a0 1331 TATTR_PH1_AUTH_METHOD, get_ikev1_auth(method)));
f5c00960 1332 transform->add_transform_attribute(transform,
3ecfc83c 1333 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
f5c00960
MW
1334 TATTR_PH1_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
1335 transform->add_transform_attribute(transform,
3ecfc83c 1336 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
fbebc2a0 1337 TATTR_PH1_LIFE_DURATION, lifetime));
3a470f30
MW
1338
1339 add_transform_substructure(this, transform);
1340}
1341
1342/**
3771b858 1343 * Add an IKEv1 ESP/AH proposal to the substructure
3a470f30 1344 */
3771b858 1345static void set_from_proposal_v1(private_proposal_substructure_t *this,
b12c53ce 1346 proposal_t *proposal, uint32_t lifetime, uint64_t lifebytes,
0ff8d20a 1347 ipsec_mode_t mode, encap_t udp, int number)
3a470f30 1348{
cc9629d8 1349 transform_substructure_t *transform = NULL;
b12c53ce 1350 uint16_t alg, transid, key_size;
cc9629d8
MW
1351 enumerator_t *enumerator;
1352
1353 enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
1354 if (enumerator->enumerate(enumerator, &alg, &key_size))
1355 {
728f529c
TB
1356 transid = get_ikev1_transid_from_alg(ENCRYPTION_ALGORITHM, alg);
1357 if (transid)
cc9629d8 1358 {
3771b858 1359 transform = transform_substructure_create_type(
728f529c 1360 PLV1_TRANSFORM_SUBSTRUCTURE, number, transid);
4b797f46
AS
1361 if (key_size)
1362 {
1363 transform->add_transform_attribute(transform,
3ecfc83c 1364 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
4b797f46
AS
1365 TATTR_PH2_KEY_LENGTH, key_size));
1366 }
cc9629d8
MW
1367 }
1368 }
1369 enumerator->destroy(enumerator);
cc9629d8
MW
1370
1371 enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
cd89f1a0 1372 if (enumerator->enumerate(enumerator, &alg, &key_size))
cc9629d8 1373 {
5d580ae0 1374 transid = get_ikev1_transid_from_alg(INTEGRITY_ALGORITHM, alg);
728f529c 1375 alg = get_ikev1_auth_from_alg(alg);
8456d6f5 1376 if (alg)
cc9629d8 1377 {
8456d6f5 1378 if (!transform && transid)
3771b858
MW
1379 {
1380 transform = transform_substructure_create_type(
728f529c 1381 PLV1_TRANSFORM_SUBSTRUCTURE, number, transid);
3771b858 1382 }
8456d6f5
TE
1383 if (transform)
1384 {
1385 transform->add_transform_attribute(transform,
1386 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
1387 TATTR_PH2_AUTH_ALGORITHM, alg));
1388 }
cc9629d8
MW
1389 }
1390 }
1391 enumerator->destroy(enumerator);
1392
3771b858
MW
1393 if (!transform)
1394 {
1395 return;
1396 }
1397
9bb4de1d
MW
1398 enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
1399 if (enumerator->enumerate(enumerator, &alg, &key_size))
1400 {
1401 transform->add_transform_attribute(transform,
3ecfc83c 1402 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
9bb4de1d
MW
1403 TATTR_PH2_GROUP, alg));
1404 }
1405 enumerator->destroy(enumerator);
1406
f5c00960 1407 transform->add_transform_attribute(transform,
3ecfc83c 1408 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
fbebc2a0
MW
1409 TATTR_PH2_ENCAP_MODE, get_ikev1_mode(mode, udp)));
1410 if (lifetime)
1411 {
1412 transform->add_transform_attribute(transform,
3ecfc83c 1413 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
f5c00960 1414 TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
fbebc2a0 1415 transform->add_transform_attribute(transform,
3ecfc83c 1416 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
fbebc2a0
MW
1417 TATTR_PH2_SA_LIFE_DURATION, lifetime));
1418 }
927c1dd9 1419 if (lifebytes)
fbebc2a0
MW
1420 {
1421 transform->add_transform_attribute(transform,
3ecfc83c 1422 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
fbebc2a0
MW
1423 TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_KILOBYTES));
1424 transform->add_transform_attribute(transform,
3ecfc83c 1425 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
fbebc2a0
MW
1426 TATTR_PH2_SA_LIFE_DURATION, lifebytes / 1000));
1427 }
cc9629d8 1428
40bb4677
TE
1429 enumerator = proposal->create_enumerator(proposal,
1430 EXTENDED_SEQUENCE_NUMBERS);
1431 while (enumerator->enumerate(enumerator, &alg, NULL))
1432 {
1433 if (alg == EXT_SEQ_NUMBERS)
1434 {
1435 transform->add_transform_attribute(transform,
1436 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
1437 TATTR_PH2_EXT_SEQ_NUMBER, alg));
1438 }
1439 }
1440 enumerator->destroy(enumerator);
cc9629d8 1441 add_transform_substructure(this, transform);
3a470f30
MW
1442}
1443
1444/**
1445 * Add an IKEv2 proposal to the substructure
1446 */
1447static void set_from_proposal_v2(private_proposal_substructure_t *this,
1448 proposal_t *proposal)
1449{
1450 transform_substructure_t *transform;
b12c53ce 1451 uint16_t alg, key_size;
3a470f30 1452 enumerator_t *enumerator;
7daf5226 1453
f3bb1bd0 1454 /* encryption algorithm is only available in ESP */
3c7e72f5
MW
1455 enumerator = proposal->create_enumerator(proposal, ENCRYPTION_ALGORITHM);
1456 while (enumerator->enumerate(enumerator, &alg, &key_size))
384efc76 1457 {
3ecfc83c 1458 transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
3a470f30
MW
1459 ENCRYPTION_ALGORITHM, alg);
1460 if (key_size)
1461 {
1462 transform->add_transform_attribute(transform,
3ecfc83c 1463 transform_attribute_create_value(PLV2_TRANSFORM_ATTRIBUTE,
3a470f30
MW
1464 TATTR_IKEV2_KEY_LENGTH, key_size));
1465 }
3c7e72f5 1466 add_transform_substructure(this, transform);
384efc76 1467 }
3c7e72f5 1468 enumerator->destroy(enumerator);
7daf5226 1469
384efc76 1470 /* integrity algorithms */
3c7e72f5
MW
1471 enumerator = proposal->create_enumerator(proposal, INTEGRITY_ALGORITHM);
1472 while (enumerator->enumerate(enumerator, &alg, &key_size))
384efc76 1473 {
3ecfc83c 1474 transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
3a470f30 1475 INTEGRITY_ALGORITHM, alg);
3c7e72f5 1476 add_transform_substructure(this, transform);
384efc76 1477 }
3c7e72f5 1478 enumerator->destroy(enumerator);
7daf5226 1479
c06dbbab 1480 /* prf algorithms */
3c7e72f5
MW
1481 enumerator = proposal->create_enumerator(proposal, PSEUDO_RANDOM_FUNCTION);
1482 while (enumerator->enumerate(enumerator, &alg, &key_size))
c06dbbab 1483 {
3ecfc83c 1484 transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
3a470f30 1485 PSEUDO_RANDOM_FUNCTION, alg);
3c7e72f5 1486 add_transform_substructure(this, transform);
c06dbbab 1487 }
3c7e72f5 1488 enumerator->destroy(enumerator);
7daf5226 1489
384efc76 1490 /* dh groups */
3c7e72f5
MW
1491 enumerator = proposal->create_enumerator(proposal, DIFFIE_HELLMAN_GROUP);
1492 while (enumerator->enumerate(enumerator, &alg, NULL))
384efc76 1493 {
3ecfc83c 1494 transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
3a470f30 1495 DIFFIE_HELLMAN_GROUP, alg);
3c7e72f5 1496 add_transform_substructure(this, transform);
384efc76 1497 }
3c7e72f5 1498 enumerator->destroy(enumerator);
7daf5226 1499
384efc76 1500 /* extended sequence numbers */
3c7e72f5
MW
1501 enumerator = proposal->create_enumerator(proposal, EXTENDED_SEQUENCE_NUMBERS);
1502 while (enumerator->enumerate(enumerator, &alg, NULL))
384efc76 1503 {
3ecfc83c 1504 transform = transform_substructure_create_type(PLV2_TRANSFORM_SUBSTRUCTURE,
3a470f30 1505 EXTENDED_SEQUENCE_NUMBERS, alg);
3c7e72f5 1506 add_transform_substructure(this, transform);
384efc76 1507 }
3c7e72f5 1508 enumerator->destroy(enumerator);
3a470f30
MW
1509}
1510
fbebc2a0
MW
1511/**
1512 * Set SPI and other data from proposal, compute length
3a470f30 1513 */
fbebc2a0 1514static void set_data(private_proposal_substructure_t *this, proposal_t *proposal)
3a470f30 1515{
b12c53ce
AS
1516 uint64_t spi64;
1517 uint32_t spi32;
3a470f30 1518
fe04e93a
MW
1519 /* add SPI, if necessary */
1520 switch (proposal->get_protocol(proposal))
8d77edde 1521 {
fe04e93a
MW
1522 case PROTO_AH:
1523 case PROTO_ESP:
3a470f30
MW
1524 spi32 = proposal->get_spi(proposal);
1525 this->spi = chunk_clone(chunk_from_thing(spi32));
1526 this->spi_size = this->spi.len;
fe04e93a
MW
1527 break;
1528 case PROTO_IKE:
3a470f30
MW
1529 spi64 = proposal->get_spi(proposal);
1530 if (spi64)
fe04e93a 1531 { /* IKE only uses SPIS when rekeying, but on initial setup */
3a470f30
MW
1532 this->spi = chunk_clone(chunk_from_thing(spi64));
1533 this->spi_size = this->spi.len;
fe04e93a
MW
1534 }
1535 break;
4c23a8c9
MW
1536 default:
1537 break;
8d77edde 1538 }
1c6b43b8
TB
1539 /* default to 1 if no number is set (mainly for IKEv1, for IKEv2 the numbers
1540 * are explicitly set when proposals are added to the SA payload) */
1541 this->proposal_number = proposal->get_number(proposal) ?: 1;
8d77edde 1542 this->protocol_id = proposal->get_protocol(proposal);
2ecbd618 1543 compute_length(this);
fbebc2a0
MW
1544}
1545
1546/*
1547 * Described in header.
1548 */
1549proposal_substructure_t *proposal_substructure_create_from_proposal_v2(
1550 proposal_t *proposal)
1551{
1552 private_proposal_substructure_t *this;
1553
1554 this = (private_proposal_substructure_t*)
de77957e 1555 proposal_substructure_create(PLV2_PROPOSAL_SUBSTRUCTURE);
fbebc2a0
MW
1556 set_from_proposal_v2(this, proposal);
1557 set_data(this, proposal);
1558
1559 return &this->public;
1560}
1561
1562/**
859f9c8c 1563 * Creates an IKEv1 proposal_substructure_t from a proposal_t.
fbebc2a0 1564 */
859f9c8c 1565static proposal_substructure_t *proposal_substructure_create_from_proposal_v1(
b12c53ce 1566 proposal_t *proposal, uint32_t lifetime, uint64_t lifebytes,
859f9c8c 1567 auth_method_t auth, ipsec_mode_t mode, encap_t udp, uint8_t number)
fbebc2a0
MW
1568{
1569 private_proposal_substructure_t *this;
1570
1571 this = (private_proposal_substructure_t*)
3ecfc83c 1572 proposal_substructure_create(PLV1_PROPOSAL_SUBSTRUCTURE);
fbebc2a0
MW
1573 switch (proposal->get_protocol(proposal))
1574 {
1575 case PROTO_IKE:
859f9c8c 1576 set_from_proposal_v1_ike(this, proposal, lifetime, auth, number);
fbebc2a0
MW
1577 break;
1578 case PROTO_ESP:
3771b858
MW
1579 case PROTO_AH:
1580 set_from_proposal_v1(this, proposal, lifetime,
859f9c8c 1581 lifebytes, mode, udp, number);
fbebc2a0
MW
1582 break;
1583 default:
1584 break;
1585 }
1586 set_data(this, proposal);
7daf5226 1587
fe04e93a 1588 return &this->public;
384efc76 1589}
62a27ba3
MW
1590
1591/**
1592 * See header.
1593 */
fbebc2a0 1594proposal_substructure_t *proposal_substructure_create_from_proposals_v1(
b12c53ce 1595 linked_list_t *proposals, uint32_t lifetime, uint64_t lifebytes,
0ff8d20a 1596 auth_method_t auth, ipsec_mode_t mode, encap_t udp)
62a27ba3
MW
1597{
1598 private_proposal_substructure_t *this = NULL;
1599 enumerator_t *enumerator;
1600 proposal_t *proposal;
859f9c8c 1601 int number = 1;
62a27ba3
MW
1602
1603 enumerator = proposals->create_enumerator(proposals);
1604 while (enumerator->enumerate(enumerator, &proposal))
1605 {
1606 if (!this)
859f9c8c
TB
1607 { /* as responder the transform number is set and we only have a
1608 * single proposal, start with 1 otherwise */
62a27ba3 1609 this = (private_proposal_substructure_t*)
fbebc2a0 1610 proposal_substructure_create_from_proposal_v1(
859f9c8c
TB
1611 proposal, lifetime, lifebytes, auth, mode, udp,
1612 proposal->get_transform_number(proposal) ?: number);
62a27ba3
MW
1613 }
1614 else
1615 {
1616 switch (proposal->get_protocol(proposal))
1617 {
1618 case PROTO_IKE:
fbebc2a0
MW
1619 set_from_proposal_v1_ike(this, proposal, lifetime,
1620 auth, ++number);
62a27ba3
MW
1621 break;
1622 case PROTO_ESP:
3771b858
MW
1623 case PROTO_AH:
1624 set_from_proposal_v1(this, proposal, lifetime,
1625 lifebytes, mode, udp, ++number);
62a27ba3
MW
1626 break;
1627 default:
1628 break;
1629 }
1630 }
1631 }
1632 enumerator->destroy(enumerator);
1633
1634 return &this->public;
1635}
7a75cae8
TB
1636
1637/**
1638 * See header.
1639 */
1640proposal_substructure_t *proposal_substructure_create_for_ipcomp_v1(
b12c53ce
AS
1641 uint32_t lifetime, uint64_t lifebytes, uint16_t cpi,
1642 ipsec_mode_t mode, encap_t udp, uint8_t proposal_number)
7a75cae8
TB
1643{
1644 private_proposal_substructure_t *this;
1645 transform_substructure_t *transform;
1646
1647
1648 this = (private_proposal_substructure_t*)
3ecfc83c 1649 proposal_substructure_create(PLV1_PROPOSAL_SUBSTRUCTURE);
7a75cae8
TB
1650
1651 /* we currently support DEFLATE only */
3ecfc83c 1652 transform = transform_substructure_create_type(PLV1_TRANSFORM_SUBSTRUCTURE,
7a75cae8
TB
1653 1, IKEV1_IPCOMP_DEFLATE);
1654
daab61e5 1655 transform->add_transform_attribute(transform,
3ecfc83c 1656 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
daab61e5 1657 TATTR_PH2_ENCAP_MODE, get_ikev1_mode(mode, udp)));
7a75cae8
TB
1658 if (lifetime)
1659 {
1660 transform->add_transform_attribute(transform,
3ecfc83c 1661 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
7a75cae8
TB
1662 TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_SECONDS));
1663 transform->add_transform_attribute(transform,
3ecfc83c 1664 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
7a75cae8
TB
1665 TATTR_PH2_SA_LIFE_DURATION, lifetime));
1666 }
1667 if (lifebytes)
1668 {
1669 transform->add_transform_attribute(transform,
3ecfc83c 1670 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
7a75cae8
TB
1671 TATTR_PH2_SA_LIFE_TYPE, IKEV1_LIFE_TYPE_KILOBYTES));
1672 transform->add_transform_attribute(transform,
3ecfc83c 1673 transform_attribute_create_value(PLV1_TRANSFORM_ATTRIBUTE,
7a75cae8
TB
1674 TATTR_PH2_SA_LIFE_DURATION, lifebytes / 1000));
1675 }
1676
1677 add_transform_substructure(this, transform);
1678
1679 this->spi = chunk_clone(chunk_from_thing(cpi));
1680 this->spi_size = this->spi.len;
1681 this->protocol_id = PROTO_IPCOMP;
1682 this->proposal_number = proposal_number;
1683
1684 compute_length(this);
1685
1686 return &this->public;
a9aa75b9 1687}