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_XAUTH_INIT_PSK
= 65001,
241 IKEV1_AUTH_XAUTH_RESP_PSK
= 65002,
242 IKEV1_AUTH_XAUTH_INIT_DSS
= 65003,
243 IKEV1_AUTH_XAUTH_RESP_DSS
= 65004,
244 IKEV1_AUTH_XAUTH_INIT_RSA
= 65005,
245 IKEV1_AUTH_XAUTH_RESP_RSA
= 65006,
246 IKEV1_AUTH_XAUTH_INIT_RSA_ENC
= 65007,
247 IKEV1_AUTH_XAUTH_RESP_RSA_ENC
= 65008,
248 IKEV1_AUTH_XAUTH_INIT_RSA_ENC_REV
= 65009,
249 IKEV1_AUTH_XAUTH_RESP_RSA_ENC_REV
= 65010,
250 } ikev1_auth_method_t
;
252 METHOD(payload_t
, verify
, status_t
,
253 private_proposal_substructure_t
*this)
255 status_t status
= SUCCESS
;
256 enumerator_t
*enumerator
;
259 if (this->next_payload
!= NO_PAYLOAD
&& this->next_payload
!= 2)
262 DBG1(DBG_ENC
, "inconsistent next payload");
265 if (this->transforms_count
!= this->transforms
->get_count(this->transforms
))
267 /* must be the same! */
268 DBG1(DBG_ENC
, "transform count invalid");
272 switch (this->protocol_id
)
276 if (this->spi
.len
!= 4)
278 DBG1(DBG_ENC
, "invalid SPI length in %N proposal",
279 protocol_id_names
, this->protocol_id
);
284 if (this->spi
.len
!= 0 && this->spi
.len
!= 8)
286 DBG1(DBG_ENC
, "invalid SPI length in IKE proposal");
293 enumerator
= this->transforms
->create_enumerator(this->transforms
);
294 while (enumerator
->enumerate(enumerator
, ¤t
))
296 status
= current
->verify(current
);
297 if (status
!= SUCCESS
)
299 DBG1(DBG_ENC
, "TRANSFORM_SUBSTRUCTURE verification failed");
303 enumerator
->destroy(enumerator
);
305 /* proposal number is checked in SA payload */
309 METHOD(payload_t
, get_encoding_rules
, int,
310 private_proposal_substructure_t
*this, encoding_rule_t
**rules
)
312 if (this->type
== PROPOSAL_SUBSTRUCTURE
)
314 *rules
= encodings_v2
;
315 return countof(encodings_v2
);
317 *rules
= encodings_v1
;
318 return countof(encodings_v1
);
321 METHOD(payload_t
, get_header_length
, int,
322 private_proposal_substructure_t
*this)
324 return 8 + this->spi_size
;
327 METHOD(payload_t
, get_type
, payload_type_t
,
328 private_proposal_substructure_t
*this)
333 METHOD(payload_t
, get_next_type
, payload_type_t
,
334 private_proposal_substructure_t
*this)
336 return this->next_payload
;
339 METHOD(payload_t
, set_next_type
, void,
340 private_proposal_substructure_t
*this, payload_type_t type
)
345 * (re-)compute the length of the payload.
347 static void compute_length(private_proposal_substructure_t
*this)
349 enumerator_t
*enumerator
;
350 payload_t
*transform
;
352 this->transforms_count
= 0;
353 this->proposal_length
= get_header_length(this);
354 enumerator
= this->transforms
->create_enumerator(this->transforms
);
355 while (enumerator
->enumerate(enumerator
, &transform
))
357 this->proposal_length
+= transform
->get_length(transform
);
358 this->transforms_count
++;
360 enumerator
->destroy(enumerator
);
363 METHOD(payload_t
, get_length
, size_t,
364 private_proposal_substructure_t
*this)
366 return this->proposal_length
;
370 * Add a transform substructure to the proposal
372 static void add_transform_substructure(private_proposal_substructure_t
*this,
373 transform_substructure_t
*transform
)
375 if (this->transforms
->get_count(this->transforms
) > 0)
377 transform_substructure_t
*last
;
379 this->transforms
->get_last(this->transforms
, (void **)&last
);
380 last
->set_is_last_transform(last
, FALSE
);
382 transform
->set_is_last_transform(transform
,TRUE
);
383 this->transforms
->insert_last(this->transforms
, transform
);
384 compute_length(this);
387 METHOD(proposal_substructure_t
, set_is_last_proposal
, void,
388 private_proposal_substructure_t
*this, bool is_last
)
390 this->next_payload
= is_last ?
0 : PROPOSAL_TYPE_VALUE
;
393 METHOD(proposal_substructure_t
, set_proposal_number
, void,
394 private_proposal_substructure_t
*this,u_int8_t proposal_number
)
396 this->proposal_number
= proposal_number
;
399 METHOD(proposal_substructure_t
, get_proposal_number
, u_int8_t
,
400 private_proposal_substructure_t
*this)
402 return this->proposal_number
;
405 METHOD(proposal_substructure_t
, set_protocol_id
, void,
406 private_proposal_substructure_t
*this,u_int8_t protocol_id
)
408 this->protocol_id
= protocol_id
;
411 METHOD(proposal_substructure_t
, get_protocol_id
, u_int8_t
,
412 private_proposal_substructure_t
*this)
414 return this->protocol_id
;
417 METHOD(proposal_substructure_t
, set_spi
, void,
418 private_proposal_substructure_t
*this, chunk_t spi
)
421 this->spi
= chunk_clone(spi
);
422 this->spi_size
= spi
.len
;
423 compute_length(this);
426 METHOD(proposal_substructure_t
, get_spi
, chunk_t
,
427 private_proposal_substructure_t
*this)
433 * Add a transform to a proposal for IKEv2
435 static void add_to_proposal_v2(proposal_t
*proposal
,
436 transform_substructure_t
*transform
)
438 transform_attribute_t
*tattr
;
439 enumerator_t
*enumerator
;
440 u_int16_t key_length
= 0;
442 enumerator
= transform
->create_attribute_enumerator(transform
);
443 while (enumerator
->enumerate(enumerator
, &tattr
))
445 if (tattr
->get_attribute_type(tattr
) == TATTR_IKEV2_KEY_LENGTH
)
447 key_length
= tattr
->get_value(tattr
);
451 enumerator
->destroy(enumerator
);
453 proposal
->add_algorithm(proposal
,
454 transform
->get_transform_type_or_number(transform
),
455 transform
->get_transform_id(transform
), key_length
);
459 * Map IKEv1 to IKEv2 algorithms
467 * Encryption algorithm mapping
469 static algo_map_t map_encr
[] = {
470 { IKEV1_ENCR_DES_CBC
, ENCR_DES
},
471 { IKEV1_ENCR_IDEA_CBC
, ENCR_IDEA
},
472 { IKEV1_ENCR_BLOWFISH_CBC
, ENCR_BLOWFISH
},
473 { IKEV1_ENCR_3DES_CBC
, ENCR_3DES
},
474 { IKEV1_ENCR_CAST_CBC
, ENCR_CAST
},
475 { IKEV1_ENCR_AES_CBC
, ENCR_AES_CBC
},
476 { IKEV1_ENCR_CAMELLIA_CBC
, ENCR_CAMELLIA_CBC
},
480 * Integrity algorithm mapping
482 static algo_map_t map_integ
[] = {
483 { IKEV1_HASH_MD5
, AUTH_HMAC_MD5_96
},
484 { IKEV1_HASH_SHA1
, AUTH_HMAC_SHA1_96
},
485 { IKEV1_HASH_SHA2_256
, AUTH_HMAC_SHA2_256_128
},
486 { IKEV1_HASH_SHA2_384
, AUTH_HMAC_SHA2_384_192
},
487 { IKEV1_HASH_SHA2_512
, AUTH_HMAC_SHA2_512_256
},
491 * PRF algorithm mapping
493 static algo_map_t map_prf
[] = {
494 { IKEV1_HASH_MD5
, PRF_HMAC_MD5
},
495 { IKEV1_HASH_SHA1
, PRF_HMAC_SHA1
},
496 { IKEV1_HASH_SHA2_256
, PRF_HMAC_SHA2_256
},
497 { IKEV1_HASH_SHA2_384
, PRF_HMAC_SHA2_384
},
498 { IKEV1_HASH_SHA2_512
, PRF_HMAC_SHA2_512
},
502 * Get IKEv2 algorithm from IKEv1 identifier
504 static u_int16_t
get_alg_from_ikev1(transform_type_t type
, u_int16_t value
)
512 case ENCRYPTION_ALGORITHM
:
514 count
= countof(map_encr
);
515 def
= ENCR_UNDEFINED
;
517 case INTEGRITY_ALGORITHM
:
519 count
= countof(map_integ
);
520 def
= AUTH_UNDEFINED
;
522 case PSEUDO_RANDOM_FUNCTION
:
524 count
= countof(map_prf
);
530 for (i
= 0; i
< count
; i
++)
532 if (map
[i
].ikev1
== value
)
541 * Get IKEv1 algorithm from IKEv2 identifier
543 static u_int16_t
get_ikev1_from_alg(transform_type_t type
, u_int16_t value
)
550 case ENCRYPTION_ALGORITHM
:
552 count
= countof(map_encr
);
554 case INTEGRITY_ALGORITHM
:
556 count
= countof(map_integ
);
558 case PSEUDO_RANDOM_FUNCTION
:
560 count
= countof(map_prf
);
565 for (i
= 0; i
< count
; i
++)
567 if (map
[i
].ikev2
== value
)
576 * Add an IKE transform to a proposal for IKEv1
578 static void add_to_proposal_v1_ike(proposal_t
*proposal
,
579 transform_substructure_t
*transform
)
581 transform_attribute_type_t type
;
582 transform_attribute_t
*tattr
;
583 enumerator_t
*enumerator
;
584 u_int16_t value
, key_length
= 0;
585 u_int16_t encr
= ENCR_UNDEFINED
;
587 enumerator
= transform
->create_attribute_enumerator(transform
);
588 while (enumerator
->enumerate(enumerator
, &tattr
))
590 type
= tattr
->get_attribute_type(tattr
);
591 value
= tattr
->get_value(tattr
);
594 case TATTR_PH1_ENCRYPTION_ALGORITHM
:
595 encr
= get_alg_from_ikev1(ENCRYPTION_ALGORITHM
, value
);
597 case TATTR_PH1_KEY_LENGTH
:
600 case TATTR_PH1_HASH_ALGORITHM
:
601 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
,
602 get_alg_from_ikev1(INTEGRITY_ALGORITHM
, value
), 0);
603 proposal
->add_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
,
604 get_alg_from_ikev1(PSEUDO_RANDOM_FUNCTION
, value
), 0);
606 case TATTR_PH1_GROUP
:
607 proposal
->add_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
,
611 /* TODO-IKEv1: lifetimes, authentication and other attributes */
615 enumerator
->destroy(enumerator
);
617 if (encr
!= ENCR_UNDEFINED
)
619 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, key_length
);
624 * Add an ESP transform to a proposal for IKEv1
626 static void add_to_proposal_v1_esp(proposal_t
*proposal
,
627 transform_substructure_t
*transform
)
629 transform_attribute_type_t type
;
630 transform_attribute_t
*tattr
;
631 enumerator_t
*enumerator
;
632 u_int16_t value
, key_length
= 0;
634 enumerator
= transform
->create_attribute_enumerator(transform
);
635 while (enumerator
->enumerate(enumerator
, &tattr
))
637 type
= tattr
->get_attribute_type(tattr
);
638 value
= tattr
->get_value(tattr
);
641 case TATTR_PH2_KEY_LENGTH
:
644 case TATTR_PH2_AUTH_ALGORITHM
:
645 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
,
646 get_alg_from_ikev1(INTEGRITY_ALGORITHM
, value
), 0);
649 /* TODO-IKEv1: lifetimes other attributes */
653 enumerator
->destroy(enumerator
);
655 /* TODO-IKEv1: handle ESN attribute */
656 proposal
->add_algorithm(proposal
, EXTENDED_SEQUENCE_NUMBERS
,
657 NO_EXT_SEQ_NUMBERS
, 0);
659 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
,
660 transform
->get_transform_id(transform
), key_length
);
663 METHOD(proposal_substructure_t
, get_proposals
, void,
664 private_proposal_substructure_t
*this, linked_list_t
*proposals
)
666 transform_substructure_t
*transform
;
667 enumerator_t
*enumerator
;
668 proposal_t
*proposal
= NULL
;
671 switch (this->spi
.len
)
674 spi
= *((u_int32_t
*)this->spi
.ptr
);
677 spi
= *((u_int64_t
*)this->spi
.ptr
);
683 enumerator
= this->transforms
->create_enumerator(this->transforms
);
684 while (enumerator
->enumerate(enumerator
, &transform
))
688 proposal
= proposal_create(this->protocol_id
, this->proposal_number
);
689 proposal
->set_spi(proposal
, spi
);
690 proposals
->insert_last(proposals
, proposal
);
692 if (this->type
== PROPOSAL_SUBSTRUCTURE
)
694 add_to_proposal_v2(proposal
, transform
);
698 switch (this->protocol_id
)
701 add_to_proposal_v1_ike(proposal
, transform
);
704 add_to_proposal_v1_esp(proposal
, transform
);
709 /* create a new proposal for each transform in IKEv1 */
713 enumerator
->destroy(enumerator
);
716 METHOD(proposal_substructure_t
, create_substructure_enumerator
, enumerator_t
*,
717 private_proposal_substructure_t
*this)
719 return this->transforms
->create_enumerator(this->transforms
);
722 METHOD2(payload_t
, proposal_substructure_t
, destroy
, void,
723 private_proposal_substructure_t
*this)
725 this->transforms
->destroy_offset(this->transforms
,
726 offsetof(payload_t
, destroy
));
727 chunk_free(&this->spi
);
732 * Described in header.
734 proposal_substructure_t
*proposal_substructure_create(payload_type_t type
)
736 private_proposal_substructure_t
*this;
740 .payload_interface
= {
742 .get_encoding_rules
= _get_encoding_rules
,
743 .get_header_length
= _get_header_length
,
744 .get_length
= _get_length
,
745 .get_next_type
= _get_next_type
,
746 .set_next_type
= _set_next_type
,
747 .get_type
= _get_type
,
750 .set_proposal_number
= _set_proposal_number
,
751 .get_proposal_number
= _get_proposal_number
,
752 .set_protocol_id
= _set_protocol_id
,
753 .get_protocol_id
= _get_protocol_id
,
754 .set_is_last_proposal
= _set_is_last_proposal
,
755 .get_proposals
= _get_proposals
,
756 .create_substructure_enumerator
= _create_substructure_enumerator
,
761 .next_payload
= NO_PAYLOAD
,
762 .transforms
= linked_list_create(),
765 compute_length(this);
767 return &this->public;
771 * Add an IKEv1 IKE proposal to the substructure
773 static void set_from_proposal_v1_ike(private_proposal_substructure_t
*this,
774 proposal_t
*proposal
, int number
)
776 transform_substructure_t
*transform
;
777 u_int16_t alg
, key_size
;
778 enumerator_t
*enumerator
;
780 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1
,
781 number
, IKEV1_TRANSID_KEY_IKE
);
783 enumerator
= proposal
->create_enumerator(proposal
, ENCRYPTION_ALGORITHM
);
784 if (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
786 alg
= get_ikev1_from_alg(ENCRYPTION_ALGORITHM
, alg
);
789 transform
->add_transform_attribute(transform
,
790 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
791 TATTR_PH1_ENCRYPTION_ALGORITHM
, alg
));
794 transform
->add_transform_attribute(transform
,
795 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
796 TATTR_PH1_KEY_LENGTH
, key_size
));
800 enumerator
->destroy(enumerator
);
802 /* encode the integrity algorithm as hash and assume use the same PRF */
803 enumerator
= proposal
->create_enumerator(proposal
, INTEGRITY_ALGORITHM
);
804 if (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
806 alg
= get_ikev1_from_alg(INTEGRITY_ALGORITHM
, alg
);
809 transform
->add_transform_attribute(transform
,
810 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
811 TATTR_PH1_HASH_ALGORITHM
, alg
));
814 enumerator
->destroy(enumerator
);
816 enumerator
= proposal
->create_enumerator(proposal
, DIFFIE_HELLMAN_GROUP
);
817 if (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
819 transform
->add_transform_attribute(transform
,
820 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
821 TATTR_PH1_GROUP
, alg
));
823 enumerator
->destroy(enumerator
);
825 /* TODO-IKEv1: Add lifetime, non-fixed auth-method and other attributes */
826 if(1) /* TODO-IKEv1: Change to 0 if XAUTH is desired. */
828 transform
->add_transform_attribute(transform
,
829 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
830 TATTR_PH1_AUTH_METHOD
, IKEV1_AUTH_PSK
));
832 transform
->add_transform_attribute(transform
,
833 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
834 TATTR_PH1_AUTH_METHOD
, IKEV1_AUTH_XAUTH_INIT_PSK
));
836 transform
->add_transform_attribute(transform
,
837 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
838 TATTR_PH1_LIFE_TYPE
, IKEV1_LIFE_TYPE_SECONDS
));
839 transform
->add_transform_attribute(transform
,
840 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
841 TATTR_PH1_LIFE_DURATION
, 10800));
843 add_transform_substructure(this, transform
);
847 * Add an IKEv1 ESP proposal to the substructure
849 static void set_from_proposal_v1_esp(private_proposal_substructure_t
*this,
850 proposal_t
*proposal
, int number
)
852 transform_substructure_t
*transform
= NULL
;
853 u_int16_t alg
, key_size
;
854 enumerator_t
*enumerator
;
856 enumerator
= proposal
->create_enumerator(proposal
, ENCRYPTION_ALGORITHM
);
857 if (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
859 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE_V1
,
863 transform
->add_transform_attribute(transform
,
864 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
865 TATTR_PH2_KEY_LENGTH
, key_size
));
868 enumerator
->destroy(enumerator
);
874 enumerator
= proposal
->create_enumerator(proposal
, INTEGRITY_ALGORITHM
);
875 if (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
877 alg
= get_ikev1_from_alg(INTEGRITY_ALGORITHM
, alg
);
880 transform
->add_transform_attribute(transform
,
881 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
882 TATTR_PH2_AUTH_ALGORITHM
, alg
));
885 enumerator
->destroy(enumerator
);
887 /* TODO-IKEv1: Add lifetime and other attributes, ESN */
888 transform
->add_transform_attribute(transform
,
889 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
890 TATTR_PH2_ENCAP_MODE
, IKEV1_ENCAP_TUNNEL
));
891 transform
->add_transform_attribute(transform
,
892 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
893 TATTR_PH2_SA_LIFE_TYPE
, IKEV1_LIFE_TYPE_SECONDS
));
894 transform
->add_transform_attribute(transform
,
895 transform_attribute_create_value(TRANSFORM_ATTRIBUTE_V1
,
896 TATTR_PH2_SA_LIFE_DURATION
, 3600));
898 add_transform_substructure(this, transform
);
902 * Add an IKEv2 proposal to the substructure
904 static void set_from_proposal_v2(private_proposal_substructure_t
*this,
905 proposal_t
*proposal
)
907 transform_substructure_t
*transform
;
908 u_int16_t alg
, key_size
;
909 enumerator_t
*enumerator
;
911 /* encryption algorithm is only available in ESP */
912 enumerator
= proposal
->create_enumerator(proposal
, ENCRYPTION_ALGORITHM
);
913 while (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
915 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE
,
916 ENCRYPTION_ALGORITHM
, alg
);
919 transform
->add_transform_attribute(transform
,
920 transform_attribute_create_value(TRANSFORM_ATTRIBUTE
,
921 TATTR_IKEV2_KEY_LENGTH
, key_size
));
923 add_transform_substructure(this, transform
);
925 enumerator
->destroy(enumerator
);
927 /* integrity algorithms */
928 enumerator
= proposal
->create_enumerator(proposal
, INTEGRITY_ALGORITHM
);
929 while (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
931 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE
,
932 INTEGRITY_ALGORITHM
, alg
);
933 add_transform_substructure(this, transform
);
935 enumerator
->destroy(enumerator
);
938 enumerator
= proposal
->create_enumerator(proposal
, PSEUDO_RANDOM_FUNCTION
);
939 while (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
941 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE
,
942 PSEUDO_RANDOM_FUNCTION
, alg
);
943 add_transform_substructure(this, transform
);
945 enumerator
->destroy(enumerator
);
948 enumerator
= proposal
->create_enumerator(proposal
, DIFFIE_HELLMAN_GROUP
);
949 while (enumerator
->enumerate(enumerator
, &alg
, NULL
))
951 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE
,
952 DIFFIE_HELLMAN_GROUP
, alg
);
953 add_transform_substructure(this, transform
);
955 enumerator
->destroy(enumerator
);
957 /* extended sequence numbers */
958 enumerator
= proposal
->create_enumerator(proposal
, EXTENDED_SEQUENCE_NUMBERS
);
959 while (enumerator
->enumerate(enumerator
, &alg
, NULL
))
961 transform
= transform_substructure_create_type(TRANSFORM_SUBSTRUCTURE
,
962 EXTENDED_SEQUENCE_NUMBERS
, alg
);
963 add_transform_substructure(this, transform
);
965 enumerator
->destroy(enumerator
);
969 * Described in header.
971 proposal_substructure_t
*proposal_substructure_create_from_proposal(
972 payload_type_t type
, proposal_t
*proposal
)
974 private_proposal_substructure_t
*this;
978 this = (private_proposal_substructure_t
*)proposal_substructure_create(type
);
980 if (type
== PROPOSAL_SUBSTRUCTURE
)
982 set_from_proposal_v2(this, proposal
);
986 switch (proposal
->get_protocol(proposal
))
989 set_from_proposal_v1_ike(this, proposal
, 0);
992 set_from_proposal_v1_esp(this, proposal
, 0);
998 /* add SPI, if necessary */
999 switch (proposal
->get_protocol(proposal
))
1003 spi32
= proposal
->get_spi(proposal
);
1004 this->spi
= chunk_clone(chunk_from_thing(spi32
));
1005 this->spi_size
= this->spi
.len
;
1008 spi64
= proposal
->get_spi(proposal
);
1010 { /* IKE only uses SPIS when rekeying, but on initial setup */
1011 this->spi
= chunk_clone(chunk_from_thing(spi64
));
1012 this->spi_size
= this->spi
.len
;
1018 this->proposal_number
= proposal
->get_number(proposal
);
1019 this->protocol_id
= proposal
->get_protocol(proposal
);
1020 compute_length(this);
1022 return &this->public;
1028 proposal_substructure_t
*proposal_substructure_create_from_proposals(
1029 linked_list_t
*proposals
)
1031 private_proposal_substructure_t
*this = NULL
;
1032 enumerator_t
*enumerator
;
1033 proposal_t
*proposal
;
1036 enumerator
= proposals
->create_enumerator(proposals
);
1037 while (enumerator
->enumerate(enumerator
, &proposal
))
1041 this = (private_proposal_substructure_t
*)
1042 proposal_substructure_create_from_proposal(
1043 PROPOSAL_SUBSTRUCTURE_V1
, proposal
);
1047 switch (proposal
->get_protocol(proposal
))
1050 set_from_proposal_v1_ike(this, proposal
, ++number
);
1053 set_from_proposal_v1_esp(this, proposal
, ++number
);
1060 enumerator
->destroy(enumerator
);
1062 return &this->public;