2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include "proposal_substructure.h"
21 #include <encoding/payloads/encodings.h>
22 #include <encoding/payloads/transform_substructure.h>
24 #include <utils/linked_list.h>
28 * IKEv2 Value for a proposal payload.
30 #define PROPOSAL_TYPE_VALUE 2
32 typedef struct private_proposal_substructure_t private_proposal_substructure_t
;
35 * Private data of an proposal_substructure_t object.
37 struct private_proposal_substructure_t
{
40 * Public proposal_substructure_t interface.
42 proposal_substructure_t
public;
47 u_int8_t next_payload
;
55 * Length of this payload.
57 u_int16_t proposal_length
;
62 u_int8_t proposal_number
;
70 * SPI size of the following SPI.
75 * Number of transforms.
77 u_int8_t transforms_count
;
80 * SPI is stored as chunk.
85 * Transforms are stored in a linked_list_t.
87 linked_list_t
*transforms
;
90 * Type of this payload, PROPOSAL_SUBSTRUCTURE or PROPOSAL_SUBSTRUCTURE_V1
96 * Encoding rules for a IKEv1 Proposal substructure.
98 static encoding_rule_t encodings_v1
[] = {
99 /* 1 Byte next payload type, stored in the field next_payload */
100 { U_INT_8
, offsetof(private_proposal_substructure_t
, next_payload
) },
101 /* 1 Reserved Byte */
102 { RESERVED_BYTE
, offsetof(private_proposal_substructure_t
, reserved
) },
103 /* Length of the whole proposal substructure payload*/
104 { PAYLOAD_LENGTH
, offsetof(private_proposal_substructure_t
, proposal_length
) },
105 /* proposal number is a number of 8 bit */
106 { U_INT_8
, offsetof(private_proposal_substructure_t
, proposal_number
) },
107 /* protocol ID is a number of 8 bit */
108 { U_INT_8
, offsetof(private_proposal_substructure_t
, protocol_id
) },
109 /* SPI Size has its own type */
110 { SPI_SIZE
, offsetof(private_proposal_substructure_t
, spi_size
) },
111 /* Number of transforms is a number of 8 bit */
112 { U_INT_8
, offsetof(private_proposal_substructure_t
, transforms_count
) },
113 /* SPI is a chunk of variable size*/
114 { SPI
, offsetof(private_proposal_substructure_t
, spi
) },
115 /* Transforms are stored in a transform substructure list */
116 { PAYLOAD_LIST
+ TRANSFORM_SUBSTRUCTURE_V1
,
117 offsetof(private_proposal_substructure_t
, transforms
) },
121 * Encoding rules for a IKEv2 Proposal substructure.
123 static encoding_rule_t encodings_v2
[] = {
124 /* 1 Byte next payload type, stored in the field next_payload */
125 { U_INT_8
, offsetof(private_proposal_substructure_t
, next_payload
) },
126 /* 1 Reserved Byte */
127 { RESERVED_BYTE
, offsetof(private_proposal_substructure_t
, reserved
) },
128 /* Length of the whole proposal substructure payload*/
129 { PAYLOAD_LENGTH
, offsetof(private_proposal_substructure_t
, proposal_length
) },
130 /* proposal number is a number of 8 bit */
131 { U_INT_8
, offsetof(private_proposal_substructure_t
, proposal_number
) },
132 /* protocol ID is a number of 8 bit */
133 { U_INT_8
, offsetof(private_proposal_substructure_t
, protocol_id
) },
134 /* SPI Size has its own type */
135 { SPI_SIZE
, offsetof(private_proposal_substructure_t
, spi_size
) },
136 /* Number of transforms is a number of 8 bit */
137 { U_INT_8
, offsetof(private_proposal_substructure_t
, transforms_count
) },
138 /* SPI is a chunk of variable size*/
139 { SPI
, offsetof(private_proposal_substructure_t
, spi
) },
140 /* Transforms are stored in a transform substructure list */
141 { PAYLOAD_LIST
+ TRANSFORM_SUBSTRUCTURE
,
142 offsetof(private_proposal_substructure_t
, transforms
) },
147 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
148 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
149 ! 0 (last) or 2 ! RESERVED ! Proposal Length !
150 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
151 ! Proposal # ! Protocol ID ! SPI Size !# of Transforms!
152 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
158 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
165 IKEV1_ENCR_DES_CBC
= 1,
166 IKEV1_ENCR_IDEA_CBC
= 2,
167 IKEV1_ENCR_BLOWFISH_CBC
= 3,
168 IKEV1_ENCR_RC5_R16_B64_CBC
= 4,
169 IKEV1_ENCR_3DES_CBC
= 5,
170 IKEV1_ENCR_CAST_CBC
= 6,
171 IKEV1_ENCR_AES_CBC
= 7,
172 IKEV1_ENCR_CAMELLIA_CBC
= 8,
174 } ikev1_encryption_t
;
182 IKEV1_HASH_TIGER
= 3,
183 IKEV1_HASH_SHA2_256
= 4,
184 IKEV1_HASH_SHA2_384
= 5,
185 IKEV1_HASH_SHA2_512
= 6,
189 * IKEv1 Transform ID IKE.
192 IKEV1_TRANSID_KEY_IKE
= 1,
193 } ikev1_ike_transid_t
;
196 * IKEv1 Transform ID ESP.
199 IKEV1_TRANSID_ESP_DES_IV64
= 1,
200 IKEV1_TRANSID_ESP_DES
= 2,
201 IKEV1_TRANSID_ESP_3DES
= 3,
202 IKEV1_TRANSID_ESP_RC5
= 4,
203 IKEV1_TRANSID_ESP_IDEA
= 5,
204 IKEV1_TRANSID_ESP_CAST
= 6,
205 IKEV1_TRANSID_ESP_BLOWFISH
= 7,
206 IKEV1_TRANSID_ESP_3IDEA
= 8,
207 IKEV1_TRANSID_ESP_DES_IV32
= 9,
208 IKEV1_TRANSID_ESP_RC4
= 10,
209 IKEV1_TRANSID_ESP_NULL
= 11,
210 IKEV1_TRANSID_ESP_AES_CBC
= 12,
211 } ikev1_esp_transid_t
;
214 * IKEv1 ESP Encapsulation mode.
217 IKEV1_ENCAP_TUNNEL
= 1,
218 IKEV1_ENCAP_TRANSPORT
= 2,
219 IKEV1_ENCAP_UDP_TUNNEL
= 3,
220 IKEV1_ENCAP_UDP_TRANSPORT
= 4,
224 * IKEv1 Life duration types.
227 IKEV1_LIFE_TYPE_SECONDS
= 1,
228 IKEV1_LIFE_TYPE_KILOBYTES
= 2,
232 * IKEv1 authenticaiton methods
236 IKEV1_AUTH_DSS_SIG
= 2,
237 IKEV1_AUTH_RSA_SIG
= 3,
238 IKEV1_AUTH_RSA_ENC
= 4,
239 IKEV1_AUTH_RSA_ENC_REV
= 5,
240 } ikev1_auth_method_t
;
242 METHOD(payload_t
, verify
, status_t
,
243 private_proposal_substructure_t
*this)
245 status_t status
= SUCCESS
;
246 enumerator_t
*enumerator
;
249 if (this->next_payload
!= NO_PAYLOAD
&& this->next_payload
!= 2)
252 DBG1(DBG_ENC
, "inconsistent next payload");
255 if (this->transforms_count
!= this->transforms
->get_count(this->transforms
))
257 /* must be the same! */
258 DBG1(DBG_ENC
, "transform count invalid");
262 switch (this->protocol_id
)
266 if (this->spi
.len
!= 4)
268 DBG1(DBG_ENC
, "invalid SPI length in %N proposal",
269 protocol_id_names
, this->protocol_id
);
274 if (this->spi
.len
!= 0 && this->spi
.len
!= 8)
276 DBG1(DBG_ENC
, "invalid SPI length in IKE proposal");
283 enumerator
= this->transforms
->create_enumerator(this->transforms
);
284 while (enumerator
->enumerate(enumerator
, ¤t
))
286 status
= current
->verify(current
);
287 if (status
!= SUCCESS
)
289 DBG1(DBG_ENC
, "TRANSFORM_SUBSTRUCTURE verification failed");
293 enumerator
->destroy(enumerator
);
295 /* proposal number is checked in SA payload */
299 METHOD(payload_t
, get_encoding_rules
, int,
300 private_proposal_substructure_t
*this, encoding_rule_t
**rules
)
302 if (this->type
== PROPOSAL_SUBSTRUCTURE
)
304 *rules
= encodings_v2
;
305 return countof(encodings_v2
);
307 *rules
= encodings_v1
;
308 return countof(encodings_v1
);
311 METHOD(payload_t
, get_header_length
, int,
312 private_proposal_substructure_t
*this)
314 return 8 + this->spi_size
;
317 METHOD(payload_t
, get_type
, payload_type_t
,
318 private_proposal_substructure_t
*this)
323 METHOD(payload_t
, get_next_type
, payload_type_t
,
324 private_proposal_substructure_t
*this)
326 return this->next_payload
;
329 METHOD(payload_t
, set_next_type
, void,
330 private_proposal_substructure_t
*this, payload_type_t type
)
335 * (re-)compute the length of the payload.
337 static void compute_length(private_proposal_substructure_t
*this)
339 enumerator_t
*enumerator
;
340 payload_t
*transform
;
342 this->transforms_count
= 0;
343 this->proposal_length
= get_header_length(this);
344 enumerator
= this->transforms
->create_enumerator(this->transforms
);
345 while (enumerator
->enumerate(enumerator
, &transform
))
347 this->proposal_length
+= transform
->get_length(transform
);
348 this->transforms_count
++;
350 enumerator
->destroy(enumerator
);
353 METHOD(payload_t
, get_length
, size_t,
354 private_proposal_substructure_t
*this)
356 return this->proposal_length
;
360 * Add a transform substructure to the proposal
362 static void add_transform_substructure(private_proposal_substructure_t
*this,
363 transform_substructure_t
*transform
)
365 if (this->transforms
->get_count(this->transforms
) > 0)
367 transform_substructure_t
*last
;
369 this->transforms
->get_last(this->transforms
, (void **)&last
);
370 last
->set_is_last_transform(last
, FALSE
);
372 transform
->set_is_last_transform(transform
,TRUE
);
373 this->transforms
->insert_last(this->transforms
, transform
);
374 compute_length(this);
377 METHOD(proposal_substructure_t
, set_is_last_proposal
, void,
378 private_proposal_substructure_t
*this, bool is_last
)
380 this->next_payload
= is_last ?
0 : PROPOSAL_TYPE_VALUE
;
383 METHOD(proposal_substructure_t
, set_proposal_number
, void,
384 private_proposal_substructure_t
*this,u_int8_t proposal_number
)
386 this->proposal_number
= proposal_number
;
389 METHOD(proposal_substructure_t
, get_proposal_number
, u_int8_t
,
390 private_proposal_substructure_t
*this)
392 return this->proposal_number
;
395 METHOD(proposal_substructure_t
, set_protocol_id
, void,
396 private_proposal_substructure_t
*this,u_int8_t protocol_id
)
398 this->protocol_id
= protocol_id
;
401 METHOD(proposal_substructure_t
, get_protocol_id
, u_int8_t
,
402 private_proposal_substructure_t
*this)
404 return this->protocol_id
;
407 METHOD(proposal_substructure_t
, set_spi
, void,
408 private_proposal_substructure_t
*this, chunk_t spi
)
411 this->spi
= chunk_clone(spi
);
412 this->spi_size
= spi
.len
;
413 compute_length(this);
416 METHOD(proposal_substructure_t
, get_spi
, chunk_t
,
417 private_proposal_substructure_t
*this)
423 * Add a transform to a proposal for IKEv2
425 static void add_to_proposal_v2(proposal_t
*proposal
,
426 transform_substructure_t
*transform
)
428 transform_attribute_t
*tattr
;
429 enumerator_t
*enumerator
;
430 u_int16_t key_length
= 0;
432 enumerator
= transform
->create_attribute_enumerator(transform
);
433 while (enumerator
->enumerate(enumerator
, &tattr
))
435 if (tattr
->get_attribute_type(tattr
) == TATTR_IKEV2_KEY_LENGTH
)
437 key_length
= tattr
->get_value(tattr
);
441 enumerator
->destroy(enumerator
);
443 proposal
->add_algorithm(proposal
,
444 transform
->get_transform_type_or_number(transform
),
445 transform
->get_transform_id(transform
), key_length
);
449 * Map IKEv1 to IKEv2 algorithms
457 * Encryption algorithm mapping
459 static algo_map_t map_encr
[] = {
460 { IKEV1_ENCR_DES_CBC
, ENCR_DES
},
461 { IKEV1_ENCR_IDEA_CBC
, ENCR_IDEA
},
462 { IKEV1_ENCR_BLOWFISH_CBC
, ENCR_BLOWFISH
},
463 { IKEV1_ENCR_3DES_CBC
, ENCR_3DES
},
464 { IKEV1_ENCR_CAST_CBC
, ENCR_CAST
},
465 { IKEV1_ENCR_AES_CBC
, ENCR_AES_CBC
},
466 { IKEV1_ENCR_CAMELLIA_CBC
, ENCR_CAMELLIA_CBC
},
470 * Integrity algorithm mapping
472 static algo_map_t map_integ
[] = {
473 { IKEV1_HASH_MD5
, AUTH_HMAC_MD5_96
},
474 { IKEV1_HASH_SHA1
, AUTH_HMAC_SHA1_96
},
475 { IKEV1_HASH_SHA2_256
, AUTH_HMAC_SHA2_256_128
},
476 { IKEV1_HASH_SHA2_384
, AUTH_HMAC_SHA2_384_192
},
477 { IKEV1_HASH_SHA2_512
, AUTH_HMAC_SHA2_512_256
},
481 * PRF algorithm mapping
483 static algo_map_t map_prf
[] = {
484 { IKEV1_HASH_MD5
, PRF_HMAC_MD5
},
485 { IKEV1_HASH_SHA1
, PRF_HMAC_SHA1
},
486 { IKEV1_HASH_SHA2_256
, PRF_HMAC_SHA2_256
},
487 { IKEV1_HASH_SHA2_384
, PRF_HMAC_SHA2_384
},
488 { IKEV1_HASH_SHA2_512
, PRF_HMAC_SHA2_512
},
492 * Get IKEv2 algorithm from IKEv1 identifier
494 static u_int16_t
get_alg_from_ikev1(transform_type_t type
, u_int16_t value
)
502 case ENCRYPTION_ALGORITHM
:
504 count
= countof(map_encr
);
505 def
= ENCR_UNDEFINED
;
507 case INTEGRITY_ALGORITHM
:
509 count
= countof(map_integ
);
510 def
= AUTH_UNDEFINED
;
512 case PSEUDO_RANDOM_FUNCTION
:
514 count
= countof(map_prf
);
520 for (i
= 0; i
< count
; i
++)
522 if (map
[i
].ikev1
== value
)
531 * Get IKEv1 algorithm from IKEv2 identifier
533 static u_int16_t
get_ikev1_from_alg(transform_type_t type
, u_int16_t value
)
540 case ENCRYPTION_ALGORITHM
:
542 count
= countof(map_encr
);
544 case INTEGRITY_ALGORITHM
:
546 count
= countof(map_integ
);
548 case PSEUDO_RANDOM_FUNCTION
:
550 count
= countof(map_prf
);
555 for (i
= 0; i
< count
; i
++)
557 if (map
[i
].ikev2
== value
)
566 * Add an IKE transform to a proposal for IKEv1
568 static void add_to_proposal_v1_ike(proposal_t
*proposal
,
569 transform_substructure_t
*transform
)
571 transform_attribute_type_t type
;
572 transform_attribute_t
*tattr
;
573 enumerator_t
*enumerator
;
574 u_int16_t value
, key_length
= 0;
575 u_int16_t encr
= ENCR_UNDEFINED
;
577 enumerator
= transform
->create_attribute_enumerator(transform
);
578 while (enumerator
->enumerate(enumerator
, &tattr
))
580 type
= tattr
->get_attribute_type(tattr
);
581 value
= tattr
->get_value(tattr
);
584 case TATTR_PH1_ENCRYPTION_ALGORITHM
:
585 encr
= get_alg_from_ikev1(ENCRYPTION_ALGORITHM
, value
);
587 case TATTR_PH1_KEY_LENGTH
:
590 case TATTR_PH1_HASH_ALGORITHM
:
591 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
,
592 get_alg_from_ikev1(INTEGRITY_ALGORITHM
, value
), 0);
593 proposal
->add_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
,
594 get_alg_from_ikev1(PSEUDO_RANDOM_FUNCTION
, value
), 0);
596 case TATTR_PH1_GROUP
:
597 proposal
->add_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
,
601 /* TODO-IKEv1: lifetimes, authentication and other attributes */
605 enumerator
->destroy(enumerator
);
607 if (encr
!= ENCR_UNDEFINED
)
609 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, key_length
);
614 * Add an ESP transform to a proposal for IKEv1
616 static void add_to_proposal_v1_esp(proposal_t
*proposal
,
617 transform_substructure_t
*transform
)
619 /* TODO-IKEv1: create ESP proposals */
622 METHOD(proposal_substructure_t
, get_proposal
, proposal_t
*,
623 private_proposal_substructure_t
*this)
625 transform_substructure_t
*transform
;
626 enumerator_t
*enumerator
;
627 proposal_t
*proposal
;
629 proposal
= proposal_create(this->protocol_id
, this->proposal_number
);
631 enumerator
= this->transforms
->create_enumerator(this->transforms
);
632 while (enumerator
->enumerate(enumerator
, &transform
))
634 if (this->type
== PROPOSAL_SUBSTRUCTURE
)
636 add_to_proposal_v2(proposal
, transform
);
640 switch (this->protocol_id
)
643 add_to_proposal_v1_ike(proposal
, transform
);
646 add_to_proposal_v1_esp(proposal
, transform
);
651 /* TODO-IKEv1: We currently accept the first set of transforms
652 * in a substructure only. We need to return multiple proposals,
653 * but this messes up proposal numbering, as we don't support
654 * transform numbering. */
658 enumerator
->destroy(enumerator
);
660 switch (this->spi
.len
)
663 proposal
->set_spi(proposal
, *((u_int32_t
*)this->spi
.ptr
));
666 proposal
->set_spi(proposal
, *((u_int64_t
*)this->spi
.ptr
));
674 METHOD(proposal_substructure_t
, create_substructure_enumerator
, enumerator_t
*,
675 private_proposal_substructure_t
*this)
677 return this->transforms
->create_enumerator(this->transforms
);
680 METHOD2(payload_t
, proposal_substructure_t
, destroy
, void,
681 private_proposal_substructure_t
*this)
683 this->transforms
->destroy_offset(this->transforms
,
684 offsetof(payload_t
, destroy
));
685 chunk_free(&this->spi
);
690 * Described in header.
692 proposal_substructure_t
*proposal_substructure_create(payload_type_t type
)
694 private_proposal_substructure_t
*this;
698 .payload_interface
= {
700 .get_encoding_rules
= _get_encoding_rules
,
701 .get_header_length
= _get_header_length
,
702 .get_length
= _get_length
,
703 .get_next_type
= _get_next_type
,
704 .set_next_type
= _set_next_type
,
705 .get_type
= _get_type
,
708 .set_proposal_number
= _set_proposal_number
,
709 .get_proposal_number
= _get_proposal_number
,
710 .set_protocol_id
= _set_protocol_id
,
711 .get_protocol_id
= _get_protocol_id
,
712 .set_is_last_proposal
= _set_is_last_proposal
,
713 .get_proposal
= _get_proposal
,
714 .create_substructure_enumerator
= _create_substructure_enumerator
,
719 .next_payload
= NO_PAYLOAD
,
720 .transforms
= linked_list_create(),
723 compute_length(this);
725 return &this->public;
729 * Add an IKEv1 IKE proposal to the substructure
731 static void set_from_proposal_v1_ike(private_proposal_substructure_t
*this,
732 proposal_t
*proposal
)
734 transform_substructure_t
*transform
;
735 u_int16_t alg
, key_size
;
736 enumerator_t
*enumerator
;
738 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1
,
739 0, IKEV1_TRANSID_KEY_IKE
);
741 enumerator
= proposal
->create_enumerator(proposal
, ENCRYPTION_ALGORITHM
);
742 while (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
744 alg
= get_ikev1_from_alg(ENCRYPTION_ALGORITHM
, alg
);
747 transform
->add_transform_attribute(transform
,
748 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
749 TATTR_PH1_ENCRYPTION_ALGORITHM
, alg
));
752 transform
->add_transform_attribute(transform
,
753 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
754 TATTR_PH1_KEY_LENGTH
, key_size
));
758 enumerator
->destroy(enumerator
);
760 /* encode the integrity algorithm as hash and assume use the same PRF */
761 enumerator
= proposal
->create_enumerator(proposal
, INTEGRITY_ALGORITHM
);
762 while (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
764 alg
= get_ikev1_from_alg(INTEGRITY_ALGORITHM
, alg
);
767 transform
->add_transform_attribute(transform
,
768 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
769 TATTR_PH1_HASH_ALGORITHM
, alg
));
772 enumerator
->destroy(enumerator
);
774 enumerator
= proposal
->create_enumerator(proposal
, DIFFIE_HELLMAN_GROUP
);
775 while (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
777 transform
->add_transform_attribute(transform
,
778 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
779 TATTR_PH1_GROUP
, alg
));
781 enumerator
->destroy(enumerator
);
783 /* TODO-IKEv1: Add lifetime, non-fixed auth-method and other attributes */
784 transform
->add_transform_attribute(transform
,
785 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
786 TATTR_PH1_AUTH_METHOD
, IKEV1_AUTH_PSK
));
788 add_transform_substructure(this, transform
);
792 * Add an IKEv1 ESP proposal to the substructure
794 static void set_from_proposal_v1_esp(private_proposal_substructure_t
*this,
795 proposal_t
*proposal
)
797 /* TODO-IKEv1: add ESP proposal to transform substr */
801 * Add an IKEv2 proposal to the substructure
803 static void set_from_proposal_v2(private_proposal_substructure_t
*this,
804 proposal_t
*proposal
)
806 transform_substructure_t
*transform
;
807 u_int16_t alg
, key_size
;
808 enumerator_t
*enumerator
;
810 /* encryption algorithm is only available in ESP */
811 enumerator
= proposal
->create_enumerator(proposal
, ENCRYPTION_ALGORITHM
);
812 while (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
814 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE
,
815 ENCRYPTION_ALGORITHM
, alg
);
818 transform
->add_transform_attribute(transform
,
819 transform_attribute_create_value(TRANSFORM_ATTRIBUTE
,
820 TATTR_IKEV2_KEY_LENGTH
, key_size
));
822 add_transform_substructure(this, transform
);
824 enumerator
->destroy(enumerator
);
826 /* integrity algorithms */
827 enumerator
= proposal
->create_enumerator(proposal
, INTEGRITY_ALGORITHM
);
828 while (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
830 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE
,
831 INTEGRITY_ALGORITHM
, alg
);
832 add_transform_substructure(this, transform
);
834 enumerator
->destroy(enumerator
);
837 enumerator
= proposal
->create_enumerator(proposal
, PSEUDO_RANDOM_FUNCTION
);
838 while (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
840 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE
,
841 PSEUDO_RANDOM_FUNCTION
, alg
);
842 add_transform_substructure(this, transform
);
844 enumerator
->destroy(enumerator
);
847 enumerator
= proposal
->create_enumerator(proposal
, DIFFIE_HELLMAN_GROUP
);
848 while (enumerator
->enumerate(enumerator
, &alg
, NULL
))
850 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE
,
851 DIFFIE_HELLMAN_GROUP
, alg
);
852 add_transform_substructure(this, transform
);
854 enumerator
->destroy(enumerator
);
856 /* extended sequence numbers */
857 enumerator
= proposal
->create_enumerator(proposal
, EXTENDED_SEQUENCE_NUMBERS
);
858 while (enumerator
->enumerate(enumerator
, &alg
, NULL
))
860 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE
,
861 EXTENDED_SEQUENCE_NUMBERS
, alg
);
862 add_transform_substructure(this, transform
);
864 enumerator
->destroy(enumerator
);
868 * Described in header.
870 proposal_substructure_t
*proposal_substructure_create_from_proposal(
871 payload_type_t type
, proposal_t
*proposal
)
873 private_proposal_substructure_t
*this;
877 this = (private_proposal_substructure_t
*)proposal_substructure_create(type
);
879 if (type
== PROPOSAL_SUBSTRUCTURE
)
881 set_from_proposal_v2(this, proposal
);
885 switch (proposal
->get_protocol(proposal
))
888 set_from_proposal_v1_ike(this, proposal
);
891 set_from_proposal_v1_esp(this, proposal
);
897 /* add SPI, if necessary */
898 switch (proposal
->get_protocol(proposal
))
902 spi32
= proposal
->get_spi(proposal
);
903 this->spi
= chunk_clone(chunk_from_thing(spi32
));
904 this->spi_size
= this->spi
.len
;
907 spi64
= proposal
->get_spi(proposal
);
909 { /* IKE only uses SPIS when rekeying, but on initial setup */
910 this->spi
= chunk_clone(chunk_from_thing(spi64
));
911 this->spi_size
= this->spi
.len
;
917 this->proposal_number
= proposal
->get_number(proposal
);
918 this->protocol_id
= proposal
->get_protocol(proposal
);
919 compute_length(this);
921 return &this->public;