2 * @file transform_substructure.h
4 * @brief Declaration of the class transform_substructure_t.
6 * An object of this type represents an IKEv2 TRANSFORM Substructure and contains Attributes.
11 * Copyright (C) 2005 Jan Hutter, Martin Willi
12 * Hochschule fuer Technik Rapperswil
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
28 #include "transform_substructure.h"
30 #include <encoding/payloads/transform_attribute.h>
31 #include <encoding/payloads/encodings.h>
33 #include <utils/allocator.h>
34 #include <utils/linked_list.h>
37 typedef struct private_transform_substructure_t private_transform_substructure_t
;
40 * Private data of an transform_substructure_t' Object
43 struct private_transform_substructure_t
{
45 * public transform_substructure_t interface
47 transform_substructure_t
public;
52 u_int8_t next_payload
;
56 * Length of this payload
58 u_int16_t transform_length
;
62 * Type of the transform
64 u_int8_t transform_type
;
69 u_int16_t transform_id
;
72 * Transforms Attributes are stored in a linked_list_t
74 linked_list_t
*attributes
;
77 * @brief Computes the length of this substructure.
79 * @param this calling private_transform_substructure_t object
83 status_t (*compute_length
) (private_transform_substructure_t
*this);
88 * string mappings for transform_type_t
90 mapping_t transform_type_m
[] = {
91 {UNDEFINED_TRANSFORM_TYPE
, "UNDEFINED_TRANSFORM_TYPE"},
92 {ENCRYPTION_ALGORITHM
, "ENCRYPTION_ALGORITHM"},
93 {PSEUDO_RANDOM_FUNCTION
, "PSEUDO_RANDOM_FUNCTION"},
94 {INTEGRITIY_ALGORITHM
, "INTEGRITIY_ALGORITHM"},
95 {DIFFIE_HELLMAN_GROUP
, "DIFFIE_HELLMAN_GROUP"},
96 {EXTENDED_SEQUENCE_NUNBERS
, "EXTENDED_SEQUENCE_NUNBERS"},
102 * string mappings for encryption_algorithm_t
104 mapping_t encryption_algorithm_m
[] = {
105 {ENCR_UNDEFINED
, "ENCR_UNDEFINED"},
106 {ENCR_DES_IV64
, "ENCR_DES_IV64"},
107 {ENCR_DES
, "ENCR_DES"},
108 {ENCR_3DES
, "ENCR_3DES"},
109 {ENCR_RC5
, "ENCR_RC5"},
110 {ENCR_IDEA
, "ENCR_IDEA"},
111 {ENCR_CAST
, "ENCR_CAST"},
112 {ENCR_BLOWFISH
, "ENCR_BLOWFISH"},
113 {ENCR_3IDEA
, "ENCR_3IDEA"},
114 {ENCR_DES_IV32
, "ENCR_DES_IV32"},
115 {ENCR_NULL
, "ENCR_NULL"},
116 {ENCR_AES_CBC
, "ENCR_AES_CBC"},
117 {ENCR_AES_CTR
, "ENCR_AES_CTR"},
122 * string mappings for encryption_algorithm_t
124 mapping_t pseudo_random_function_m
[] = {
125 {PRF_UNDEFINED
, "PRF_UNDEFINED"},
126 {PRF_HMAC_MD5
, "PRF_HMAC_MD5"},
127 {PRF_HMAC_SHA1
, "PRF_HMAC_SHA1"},
128 {PRF_HMAC_TIGER
, "PRF_HMAC_TIGER"},
129 {PRF_AES128_CBC
, "PRF_AES128_CBC"},
134 * string mappings for integrity_algorithm_t
136 mapping_t integrity_algorithm_m
[] = {
137 {AUTH_UNDEFINED
, "AUTH_UNDEFINED"},
138 {AUTH_HMAC_MD5_96
, "AUTH_HMAC_MD5_96"},
139 {AUTH_HMAC_SHA1_96
, "AUTH_HMAC_SHA1_96"},
140 {AUTH_DES_MAC
, "AUTH_DES_MAC"},
141 {AUTH_KPDK_MD5
, "AUTH_KPDK_MD5"},
142 {AUTH_AES_XCBC_96
, "AUTH_AES_XCBC_96"},
147 * string mappings for diffie_hellman_group_t
149 mapping_t diffie_hellman_group_m
[] = {
150 {MODP_UNDEFINED
, "MODP_UNDEFINED"},
151 {MODP_768_BIT
, "MODP_768_BIT"},
152 {MODP_1024_BIT
, "MODP_1024_BIT"},
153 {MODP_1536_BIT
, "MODP_1536_BIT"},
154 {MODP_2048_BIT
, "MODP_2048_BIT"},
155 {MODP_3072_BIT
, "MODP_3072_BIT"},
156 {MODP_4096_BIT
, "MODP_4096_BIT"},
157 {MODP_6144_BIT
, "MODP_6144_BIT"},
158 {MODP_8192_BIT
, "MODP_8192_BIT"},
163 * string mappings for extended_sequence_numbers_t
165 mapping_t extended_sequence_numbers_m
[] = {
166 {NO_EXT_SEQ_NUMBERS
, "NO_EXT_SEQ_NUMBERS"},
167 {EXT_SEQ_NUMBERS
, "EXT_SEQ_NUMBERS"},
172 * Encoding rules to parse or generate a Transform substructure
174 * The defined offsets are the positions in a object of type
175 * private_transform_substructure_t.
178 encoding_rule_t transform_substructure_encodings
[] = {
179 /* 1 Byte next payload type, stored in the field next_payload */
180 { U_INT_8
, offsetof(private_transform_substructure_t
, next_payload
) },
181 /* Reserved Byte is skipped */
182 { RESERVED_BYTE
, 0 },
183 /* Length of the whole transform substructure*/
184 { PAYLOAD_LENGTH
, offsetof(private_transform_substructure_t
, transform_length
) },
185 /* transform type is a number of 8 bit */
186 { U_INT_8
, offsetof(private_transform_substructure_t
, transform_type
) },
187 /* Reserved Byte is skipped */
188 { RESERVED_BYTE
, 0 },
189 /* tranform ID is a number of 8 bit */
190 { U_INT_16
, offsetof(private_transform_substructure_t
, transform_id
) },
191 /* Attributes are stored in a transform attribute,
192 offset points to a linked_list_t pointer */
193 { TRANSFORM_ATTRIBUTES
, offsetof(private_transform_substructure_t
, attributes
) }
198 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
199 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
200 ! 0 (last) or 3 ! RESERVED ! Transform Length !
201 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
202 !Transform Type ! RESERVED ! Transform ID !
203 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
205 ~ Transform Attributes ~
207 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
212 * Implements payload_t's verify function.
213 * See #payload_s.verify for description.
215 static status_t
verify(private_transform_substructure_t
*this)
217 if ((this->next_payload
!= NO_PAYLOAD
) && (this->next_payload
!= TRANSFORM_SUBSTRUCTURE
))
223 switch (this->transform_type
)
225 case ENCRYPTION_ALGORITHM
:
227 if ((this->transform_id
< ENCR_DES_IV64
) || (this->transform_id
> ENCR_AES_CTR
))
233 case PSEUDO_RANDOM_FUNCTION
:
235 if ((this->transform_id
< PRF_HMAC_MD5
) || (this->transform_id
> PRF_AES128_CBC
))
241 case INTEGRITIY_ALGORITHM
:
243 if ((this->transform_id
< AUTH_HMAC_MD5_96
) || (this->transform_id
> AUTH_AES_XCBC_96
))
249 case DIFFIE_HELLMAN_GROUP
:
251 switch (this->transform_id
)
273 case EXTENDED_SEQUENCE_NUNBERS
:
275 if ((this->transform_id
!= NO_EXT_SEQ_NUMBERS
) && (this->transform_id
!= EXT_SEQ_NUMBERS
))
283 /* not a supported transform type! */
288 /* proposal number is checked in SA payload */
293 * Implements payload_t's get_encoding_rules function.
294 * See #payload_s.get_encoding_rules for description.
296 static status_t
get_encoding_rules(private_transform_substructure_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
298 *rules
= transform_substructure_encodings
;
299 *rule_count
= sizeof(transform_substructure_encodings
) / sizeof(encoding_rule_t
);
305 * Implements payload_t's get_type function.
306 * See #payload_s.get_type for description.
308 static payload_type_t
get_type(private_transform_substructure_t
*this)
310 return TRANSFORM_SUBSTRUCTURE
;
314 * Implements payload_t's get_next_type function.
315 * See #payload_s.get_next_type for description.
317 static payload_type_t
get_next_type(private_transform_substructure_t
*this)
319 return (this->next_payload
);
323 * Implements payload_t's get_length function.
324 * See #payload_s.get_length for description.
326 static size_t get_length(private_transform_substructure_t
*this)
328 this->compute_length(this);
330 return this->transform_length
;
334 * Implements transform_substructure_t's create_transform_attribute_iterator function.
335 * See #transform_substructure_s.create_transform_attribute_iterator for description.
337 static status_t
create_transform_attribute_iterator (private_transform_substructure_t
*this,iterator_t
**iterator
,bool forward
)
339 return (this->attributes
->create_iterator(this->attributes
,iterator
,forward
));
343 * Implements transform_substructure_t's add_transform_attribute function.
344 * See #transform_substructure_s.add_transform_attribute for description.
346 static status_t
add_transform_attribute (private_transform_substructure_t
*this,transform_attribute_t
*attribute
)
349 status
= this->attributes
->insert_last(this->attributes
,(void *) attribute
);
350 this->compute_length(this);
355 * Implements transform_substructure_t's set_is_last_transform function.
356 * See #transform_substructure_s.set_is_last_transform for description.
358 static status_t
set_is_last_transform (private_transform_substructure_t
*this, bool is_last
)
360 this->next_payload
= (is_last
) ?
0: TRANSFORM_TYPE_VALUE
;
365 * Implements transform_substructure_t's get_is_last_transform function.
366 * See #transform_substructure_s.get_is_last_transform for description.
368 static bool get_is_last_transform (private_transform_substructure_t
*this)
370 return ((this->next_payload
== TRANSFORM_TYPE_VALUE
) ? FALSE
: TRUE
);
374 * Implements payload_t's set_next_type function.
375 * See #payload_s.set_next_type for description.
377 static status_t
set_next_type(private_transform_substructure_t
*this,payload_type_t type
)
383 * Implements transform_substructure_t's set_transform_type function.
384 * See #transform_substructure_s.set_transform_type for description.
386 static status_t
set_transform_type (private_transform_substructure_t
*this,u_int8_t type
)
388 this->transform_type
= type
;
393 * Implements transform_substructure_t's get_transform_type function.
394 * See #transform_substructure_s.get_transform_type for description.
396 static u_int8_t
get_transform_type (private_transform_substructure_t
*this)
398 return this->transform_type
;
402 * Implements transform_substructure_t's set_transform_id function.
403 * See #transform_substructure_s.set_transform_id for description.
405 static status_t
set_transform_id (private_transform_substructure_t
*this,u_int16_t id
)
407 this->transform_id
= id
;
412 * Implements transform_substructure_t's get_transform_id function.
413 * See #transform_substructure_s.get_transform_id for description.
415 static u_int16_t
get_transform_id (private_transform_substructure_t
*this)
417 return this->transform_id
;
421 * Implements private_transform_substructure_t's compute_length function.
422 * See #private_transform_substructure_s.compute_length for description.
424 static status_t
compute_length (private_transform_substructure_t
*this)
426 iterator_t
*iterator
;
428 size_t length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
429 status
= this->attributes
->create_iterator(this->attributes
,&iterator
,TRUE
);
430 if (status
!= SUCCESS
)
434 while (iterator
->has_next(iterator
))
436 payload_t
* current_attribute
;
437 iterator
->current(iterator
,(void **) ¤t_attribute
);
438 length
+= current_attribute
->get_length(current_attribute
);
440 iterator
->destroy(iterator
);
442 this->transform_length
= length
;
448 * Implements transform_substructure_t's clone function.
449 * See transform_substructure_s.clone for description.
451 static status_t
clone(private_transform_substructure_t
*this,transform_substructure_t
**clone
)
453 private_transform_substructure_t
*new_clone
;
454 iterator_t
*attributes
;
457 new_clone
= (private_transform_substructure_t
*) transform_substructure_create();
459 new_clone
->next_payload
= this->next_payload
;
460 new_clone
->transform_type
= this->transform_type
;
461 new_clone
->transform_id
= this->transform_id
;
463 status
= this->attributes
->create_iterator(this->attributes
,&attributes
,FALSE
);
464 if (status
!= SUCCESS
)
466 new_clone
->public.destroy(&(new_clone
->public));
470 while (attributes
->has_next(attributes
))
472 transform_attribute_t
*current_attribute
;
473 transform_attribute_t
*current_attribute_clone
;
474 status
= attributes
->current(attributes
,(void **) ¤t_attribute
);
475 if (status
!= SUCCESS
)
477 attributes
->destroy(attributes
);
478 new_clone
->public.destroy(&(new_clone
->public));
481 status
= current_attribute
->clone(current_attribute
,¤t_attribute_clone
);
482 if (status
!= SUCCESS
)
484 attributes
->destroy(attributes
);
485 new_clone
->public.destroy(&(new_clone
->public));
489 status
= new_clone
->public.add_transform_attribute(&(new_clone
->public),current_attribute_clone
);
490 if (status
!= SUCCESS
)
492 attributes
->destroy(attributes
);
493 current_attribute_clone
->destroy(current_attribute_clone
);
494 new_clone
->public.destroy(&(new_clone
->public));
499 attributes
->destroy(attributes
);
501 *clone
= &(new_clone
->public);
507 * Implements payload_t's and transform_substructure_t's destroy function.
508 * See #payload_s.destroy or transform_substructure_s.destroy for description.
510 static status_t
destroy(private_transform_substructure_t
*this)
512 /* all proposals are getting destroyed */
513 while (this->attributes
->get_count(this->attributes
) > 0)
515 transform_attribute_t
*current_attribute
;
516 if (this->attributes
->remove_last(this->attributes
,(void **)¤t_attribute
) != SUCCESS
)
520 current_attribute
->destroy(current_attribute
);
522 this->attributes
->destroy(this->attributes
);
524 allocator_free(this);
530 * Described in header
532 transform_substructure_t
*transform_substructure_create()
534 private_transform_substructure_t
*this = allocator_alloc_thing(private_transform_substructure_t
);
540 /* payload interface */
541 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
542 this->public.payload_interface
.get_encoding_rules
= (status_t (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
543 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
544 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
545 this->public.payload_interface
.set_next_type
= (status_t (*) (payload_t
*,payload_type_t
)) set_next_type
;
546 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
547 this->public.payload_interface
.destroy
= (status_t (*) (payload_t
*))destroy
;
549 /* public functions */
550 this->public.create_transform_attribute_iterator
= (status_t (*) (transform_substructure_t
*,iterator_t
**,bool)) create_transform_attribute_iterator
;
551 this->public.add_transform_attribute
= (status_t (*) (transform_substructure_t
*,transform_attribute_t
*)) add_transform_attribute
;
552 this->public.set_is_last_transform
= (status_t (*) (transform_substructure_t
*,bool)) set_is_last_transform
;
553 this->public.get_is_last_transform
= (bool (*) (transform_substructure_t
*)) get_is_last_transform
;
554 this->public.set_transform_type
= (status_t (*) (transform_substructure_t
*,u_int8_t
)) set_transform_type
;
555 this->public.get_transform_type
= (u_int8_t (*) (transform_substructure_t
*)) get_transform_type
;
556 this->public.set_transform_id
= (status_t (*) (transform_substructure_t
*,u_int16_t
)) set_transform_id
;
557 this->public.get_transform_id
= (u_int16_t (*) (transform_substructure_t
*)) get_transform_id
;
558 this->public.clone
= (status_t (*) (transform_substructure_t
*,transform_substructure_t
**)) clone
;
559 this->public.destroy
= (status_t (*) (transform_substructure_t
*)) destroy
;
561 /* private functions */
562 this->compute_length
= compute_length
;
564 /* set default values of the fields */
565 this->next_payload
= NO_PAYLOAD
;
566 this->transform_length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
567 this->transform_id
= 0;
568 this->transform_type
= 0;
570 this->attributes
= linked_list_create();
572 if (this->attributes
== NULL
)
574 allocator_free(this);
577 return (&(this->public));