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,
116 offset points to a linked_list_t pointer */
117 { TRANSFORMS_V1
, 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,
141 offset points to a linked_list_t pointer */
142 { TRANSFORMS
, 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,
231 METHOD(payload_t
, verify
, status_t
,
232 private_proposal_substructure_t
*this)
234 status_t status
= SUCCESS
;
235 enumerator_t
*enumerator
;
238 if (this->next_payload
!= NO_PAYLOAD
&& this->next_payload
!= 2)
241 DBG1(DBG_ENC
, "inconsistent next payload");
244 if (this->transforms_count
!= this->transforms
->get_count(this->transforms
))
246 /* must be the same! */
247 DBG1(DBG_ENC
, "transform count invalid");
251 switch (this->protocol_id
)
255 if (this->spi
.len
!= 4)
257 DBG1(DBG_ENC
, "invalid SPI length in %N proposal",
258 protocol_id_names
, this->protocol_id
);
263 if (this->spi
.len
!= 0 && this->spi
.len
!= 8)
265 DBG1(DBG_ENC
, "invalid SPI length in IKE proposal");
272 enumerator
= this->transforms
->create_enumerator(this->transforms
);
273 while (enumerator
->enumerate(enumerator
, ¤t
))
275 status
= current
->verify(current
);
276 if (status
!= SUCCESS
)
278 DBG1(DBG_ENC
, "TRANSFORM_SUBSTRUCTURE verification failed");
282 enumerator
->destroy(enumerator
);
284 /* proposal number is checked in SA payload */
288 METHOD(payload_t
, get_encoding_rules
, void,
289 private_proposal_substructure_t
*this, encoding_rule_t
**rules
,
292 if (this->type
== PROPOSAL_SUBSTRUCTURE
)
294 *rules
= encodings_v2
;
295 *rule_count
= countof(encodings_v2
);
299 *rules
= encodings_v1
;
300 *rule_count
= countof(encodings_v1
);
304 METHOD(payload_t
, get_type
, payload_type_t
,
305 private_proposal_substructure_t
*this)
310 METHOD(payload_t
, get_next_type
, payload_type_t
,
311 private_proposal_substructure_t
*this)
313 return this->next_payload
;
316 METHOD(payload_t
, set_next_type
, void,
317 private_proposal_substructure_t
*this, payload_type_t type
)
322 * (re-)compute the length of the payload.
324 static void compute_length(private_proposal_substructure_t
*this)
326 enumerator_t
*enumerator
;
327 payload_t
*transform
;
329 this->transforms_count
= 0;
330 this->proposal_length
= PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
+ this->spi
.len
;
331 enumerator
= this->transforms
->create_enumerator(this->transforms
);
332 while (enumerator
->enumerate(enumerator
, &transform
))
334 this->proposal_length
+= transform
->get_length(transform
);
335 this->transforms_count
++;
337 enumerator
->destroy(enumerator
);
340 METHOD(payload_t
, get_length
, size_t,
341 private_proposal_substructure_t
*this)
343 return this->proposal_length
;
347 * Add a transform substructure to the proposal
349 static void add_transform_substructure(private_proposal_substructure_t
*this,
350 transform_substructure_t
*transform
)
352 if (this->transforms
->get_count(this->transforms
) > 0)
354 transform_substructure_t
*last
;
356 this->transforms
->get_last(this->transforms
, (void **)&last
);
357 last
->set_is_last_transform(last
, FALSE
);
359 transform
->set_is_last_transform(transform
,TRUE
);
360 this->transforms
->insert_last(this->transforms
, transform
);
361 compute_length(this);
364 METHOD(proposal_substructure_t
, set_is_last_proposal
, void,
365 private_proposal_substructure_t
*this, bool is_last
)
367 this->next_payload
= is_last ?
0 : PROPOSAL_TYPE_VALUE
;
370 METHOD(proposal_substructure_t
, set_proposal_number
, void,
371 private_proposal_substructure_t
*this,u_int8_t proposal_number
)
373 this->proposal_number
= proposal_number
;
376 METHOD(proposal_substructure_t
, get_proposal_number
, u_int8_t
,
377 private_proposal_substructure_t
*this)
379 return this->proposal_number
;
382 METHOD(proposal_substructure_t
, set_protocol_id
, void,
383 private_proposal_substructure_t
*this,u_int8_t protocol_id
)
385 this->protocol_id
= protocol_id
;
388 METHOD(proposal_substructure_t
, get_protocol_id
, u_int8_t
,
389 private_proposal_substructure_t
*this)
391 return this->protocol_id
;
394 METHOD(proposal_substructure_t
, set_spi
, void,
395 private_proposal_substructure_t
*this, chunk_t spi
)
398 this->spi
= chunk_clone(spi
);
399 this->spi_size
= spi
.len
;
400 compute_length(this);
403 METHOD(proposal_substructure_t
, get_spi
, chunk_t
,
404 private_proposal_substructure_t
*this)
410 * Add a transform to a proposal for IKEv2
412 static void add_to_proposal_v2(proposal_t
*proposal
,
413 transform_substructure_t
*transform
)
415 transform_attribute_t
*tattr
;
416 enumerator_t
*enumerator
;
417 u_int16_t key_length
= 0;
419 enumerator
= transform
->create_attribute_enumerator(transform
);
420 while (enumerator
->enumerate(enumerator
, &tattr
))
422 if (tattr
->get_attribute_type(tattr
) == TATTR_IKEV2_KEY_LENGTH
)
424 key_length
= tattr
->get_value(tattr
);
428 enumerator
->destroy(enumerator
);
430 proposal
->add_algorithm(proposal
,
431 transform
->get_transform_type_or_number(transform
),
432 transform
->get_transform_id(transform
), key_length
);
436 * Get IKEv2 algorithm from IKEv1 identifier
438 static u_int16_t
get_alg_from_ikev1(transform_type_t type
, u_int16_t value
)
445 static algo_map_t encr
[] = {
446 { IKEV1_ENCR_DES_CBC
, ENCR_DES
},
447 { IKEV1_ENCR_IDEA_CBC
, ENCR_IDEA
},
448 { IKEV1_ENCR_BLOWFISH_CBC
, ENCR_BLOWFISH
},
449 { IKEV1_ENCR_3DES_CBC
, ENCR_3DES
},
450 { IKEV1_ENCR_CAST_CBC
, ENCR_CAST
},
451 { IKEV1_ENCR_AES_CBC
, ENCR_AES_CBC
},
452 { IKEV1_ENCR_CAMELLIA_CBC
, ENCR_CAMELLIA_CBC
},
454 static algo_map_t integ
[] = {
455 { IKEV1_HASH_MD5
, AUTH_HMAC_MD5_96
},
456 { IKEV1_HASH_SHA1
, AUTH_HMAC_SHA1_96
},
457 { IKEV1_HASH_SHA2_256
, AUTH_HMAC_SHA2_256_128
},
458 { IKEV1_HASH_SHA2_384
, AUTH_HMAC_SHA2_384_192
},
459 { IKEV1_HASH_SHA2_512
, AUTH_HMAC_SHA2_512_256
},
461 static algo_map_t prf
[] = {
462 { IKEV1_HASH_MD5
, PRF_HMAC_MD5
},
463 { IKEV1_HASH_SHA1
, PRF_HMAC_SHA1
},
464 { IKEV1_HASH_SHA2_256
, PRF_HMAC_SHA2_256
},
465 { IKEV1_HASH_SHA2_384
, PRF_HMAC_SHA2_384
},
466 { IKEV1_HASH_SHA2_512
, PRF_HMAC_SHA2_512
},
474 case ENCRYPTION_ALGORITHM
:
476 count
= countof(encr
);
477 def
= ENCR_UNDEFINED
;
479 case INTEGRITY_ALGORITHM
:
481 count
= countof(integ
);
482 def
= AUTH_UNDEFINED
;
484 case PSEUDO_RANDOM_FUNCTION
:
486 count
= countof(prf
);
493 for (i
= 0; i
< count
; i
++)
495 if (map
[i
].ikev1
== value
)
504 * Add an IKE transform to a proposal for IKEv1
506 static void add_to_proposal_v1_ike(proposal_t
*proposal
,
507 transform_substructure_t
*transform
)
509 transform_attribute_type_t type
;
510 transform_attribute_t
*tattr
;
511 enumerator_t
*enumerator
;
512 u_int16_t value
, key_length
= 0;
513 u_int16_t encr
= ENCR_UNDEFINED
;
515 enumerator
= transform
->create_attribute_enumerator(transform
);
516 while (enumerator
->enumerate(enumerator
, &tattr
))
518 type
= tattr
->get_attribute_type(tattr
);
519 value
= tattr
->get_value(tattr
);
522 case TATTR_PH1_ENCRYPTION_ALGORITHM
:
523 encr
= get_alg_from_ikev1(ENCRYPTION_ALGORITHM
, value
);
525 case TATTR_PH1_KEY_LENGTH
:
528 case TATTR_PH1_HASH_ALGORITHM
:
529 proposal
->add_algorithm(proposal
, INTEGRITY_ALGORITHM
,
530 get_alg_from_ikev1(INTEGRITY_ALGORITHM
, value
), 0);
531 proposal
->add_algorithm(proposal
, PSEUDO_RANDOM_FUNCTION
,
532 get_alg_from_ikev1(PSEUDO_RANDOM_FUNCTION
, value
), 0);
534 case TATTR_PH1_GROUP
:
535 proposal
->add_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
,
539 /* TODO-IKEv1: lifetimes, authentication and other attributes */
543 enumerator
->destroy(enumerator
);
545 if (encr
!= ENCR_UNDEFINED
)
547 proposal
->add_algorithm(proposal
, ENCRYPTION_ALGORITHM
, encr
, key_length
);
552 * Add an ESP transform to a proposal for IKEv1
554 static void add_to_proposal_v1_esp(proposal_t
*proposal
,
555 transform_substructure_t
*transform
)
557 /* TODO-IKEv1: create ESP proposals */
560 METHOD(proposal_substructure_t
, get_proposal
, proposal_t
*,
561 private_proposal_substructure_t
*this)
563 transform_substructure_t
*transform
;
564 enumerator_t
*enumerator
;
565 proposal_t
*proposal
;
567 proposal
= proposal_create(this->protocol_id
, this->proposal_number
);
569 enumerator
= this->transforms
->create_enumerator(this->transforms
);
570 while (enumerator
->enumerate(enumerator
, &transform
))
572 if (this->type
== PROPOSAL_SUBSTRUCTURE
)
574 add_to_proposal_v2(proposal
, transform
);
578 switch (this->protocol_id
)
581 add_to_proposal_v1_ike(proposal
, transform
);
584 add_to_proposal_v1_esp(proposal
, transform
);
589 /* TODO-IKEv1: We currently accept the first set of transforms
590 * in a substructure only. We need to return multiple proposals,
591 * but this messes up proposal numbering, as we don't support
592 * transform numbering. */
596 enumerator
->destroy(enumerator
);
598 switch (this->spi
.len
)
601 proposal
->set_spi(proposal
, *((u_int32_t
*)this->spi
.ptr
));
604 proposal
->set_spi(proposal
, *((u_int64_t
*)this->spi
.ptr
));
613 METHOD(proposal_substructure_t
, create_substructure_enumerator
, enumerator_t
*,
614 private_proposal_substructure_t
*this)
616 return this->transforms
->create_enumerator(this->transforms
);
619 METHOD2(payload_t
, proposal_substructure_t
, destroy
, void,
620 private_proposal_substructure_t
*this)
622 this->transforms
->destroy_offset(this->transforms
,
623 offsetof(payload_t
, destroy
));
624 chunk_free(&this->spi
);
629 * Described in header.
631 proposal_substructure_t
*proposal_substructure_create(payload_type_t type
)
633 private_proposal_substructure_t
*this;
637 .payload_interface
= {
639 .get_encoding_rules
= _get_encoding_rules
,
640 .get_length
= _get_length
,
641 .get_next_type
= _get_next_type
,
642 .set_next_type
= _set_next_type
,
643 .get_type
= _get_type
,
646 .set_proposal_number
= _set_proposal_number
,
647 .get_proposal_number
= _get_proposal_number
,
648 .set_protocol_id
= _set_protocol_id
,
649 .get_protocol_id
= _get_protocol_id
,
650 .set_is_last_proposal
= _set_is_last_proposal
,
651 .get_proposal
= _get_proposal
,
652 .create_substructure_enumerator
= _create_substructure_enumerator
,
657 .next_payload
= NO_PAYLOAD
,
658 .proposal_length
= PROPOSAL_SUBSTRUCTURE_HEADER_LENGTH
,
659 .transforms
= linked_list_create(),
663 return &this->public;
667 * Described in header.
669 proposal_substructure_t
*proposal_substructure_create_from_proposal(
670 payload_type_t type
, proposal_t
*proposal
)
672 transform_substructure_t
*transform
;
673 private_proposal_substructure_t
*this;
674 u_int16_t alg
, key_size
;
675 enumerator_t
*enumerator
;
676 payload_type_t subtype
= TRANSFORM_SUBSTRUCTURE
;
678 if (type
== PROPOSAL_SUBSTRUCTURE_V1
)
680 /* TODO-IKEv1: IKEv1 specific proposal encoding */
681 subtype
= TRANSFORM_SUBSTRUCTURE_V1
;
684 this = (private_proposal_substructure_t
*)proposal_substructure_create(type
);
686 /* encryption algorithm is only available in ESP */
687 enumerator
= proposal
->create_enumerator(proposal
, ENCRYPTION_ALGORITHM
);
688 while (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
690 transform
= transform_substructure_create_type(subtype
,
691 ENCRYPTION_ALGORITHM
, alg
, key_size
);
692 add_transform_substructure(this, transform
);
694 enumerator
->destroy(enumerator
);
696 /* integrity algorithms */
697 enumerator
= proposal
->create_enumerator(proposal
, INTEGRITY_ALGORITHM
);
698 while (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
700 transform
= transform_substructure_create_type(subtype
,
701 INTEGRITY_ALGORITHM
, alg
, key_size
);
702 add_transform_substructure(this, transform
);
704 enumerator
->destroy(enumerator
);
707 enumerator
= proposal
->create_enumerator(proposal
, PSEUDO_RANDOM_FUNCTION
);
708 while (enumerator
->enumerate(enumerator
, &alg
, &key_size
))
710 transform
= transform_substructure_create_type(subtype
,
711 PSEUDO_RANDOM_FUNCTION
, alg
, key_size
);
712 add_transform_substructure(this, transform
);
714 enumerator
->destroy(enumerator
);
717 enumerator
= proposal
->create_enumerator(proposal
, DIFFIE_HELLMAN_GROUP
);
718 while (enumerator
->enumerate(enumerator
, &alg
, NULL
))
720 transform
= transform_substructure_create_type(subtype
,
721 DIFFIE_HELLMAN_GROUP
, alg
, 0);
722 add_transform_substructure(this, transform
);
724 enumerator
->destroy(enumerator
);
726 /* extended sequence numbers */
727 enumerator
= proposal
->create_enumerator(proposal
, EXTENDED_SEQUENCE_NUMBERS
);
728 while (enumerator
->enumerate(enumerator
, &alg
, NULL
))
730 transform
= transform_substructure_create_type(subtype
,
731 EXTENDED_SEQUENCE_NUMBERS
, alg
, 0);
732 add_transform_substructure(this, transform
);
734 enumerator
->destroy(enumerator
);
736 /* add SPI, if necessary */
737 switch (proposal
->get_protocol(proposal
))
741 this->spi_size
= this->spi
.len
= 4;
742 this->spi
.ptr
= malloc(this->spi_size
);
743 *((u_int32_t
*)this->spi
.ptr
) = proposal
->get_spi(proposal
);
746 if (proposal
->get_spi(proposal
))
747 { /* IKE only uses SPIS when rekeying, but on initial setup */
748 this->spi_size
= this->spi
.len
= 8;
749 this->spi
.ptr
= malloc(this->spi_size
);
750 *((u_int64_t
*)this->spi
.ptr
) = proposal
->get_spi(proposal
);
756 this->proposal_number
= proposal
->get_number(proposal
);
757 this->protocol_id
= proposal
->get_protocol(proposal
);
758 compute_length(this);
760 return &this->public;