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 "transform_attribute.h"
31 #include "encodings.h"
33 #include "../utils/allocator.h"
34 #include "../utils/linked_list.h"
37 * Private data of an transform_substructure_t' Object
40 typedef struct private_transform_substructure_s private_transform_substructure_t
;
42 struct private_transform_substructure_s
{
44 * public transform_substructure_t interface
46 transform_substructure_t
public;
51 u_int8_t next_payload
;
55 * Length of this payload
57 u_int16_t transform_length
;
61 * Type of the transform
63 u_int8_t transform_type
;
68 u_int16_t transform_id
;
71 * Transforms Attributes are stored in a linked_list_t
73 linked_list_t
*attributes
;
76 * @brief Computes the length of this substructure.
78 * @param this calling private_transform_substructure_t object
82 status_t (*compute_length
) (private_transform_substructure_t
*this);
87 * string mappings for transform_type_t
89 mapping_t transform_type_m
[] = {
90 {UNDEFINED_TRANSFORM_TYPE
, "UNDEFINED_TRANSFORM_TYPE"},
91 {ENCRYPTION_ALGORITHM
, "ENCRYPTION_ALGORITHM"},
92 {PSEUDO_RANDOM_FUNCTION
, "PSEUDO_RANDOM_FUNCTION"},
93 {INTEGRITIY_ALGORITHM
, "INTEGRITIY_ALGORITHM"},
94 {DIFFIE_HELLMAN_GROUP
, "DIFFIE_HELLMAN_GROUP"},
95 {EXTENDED_SEQUENCE_NUNBERS
, "EXTENDED_SEQUENCE_NUNBERS"},
101 * string mappings for encryption_algorithm_t
103 mapping_t encryption_algorithm_m
[] = {
104 {ENCR_UNDEFINED
, "ENCR_UNDEFINED"},
105 {ENCR_DES_IV64
, "ENCR_DES_IV64"},
106 {ENCR_DES
, "ENCR_DES"},
107 {ENCR_3DES
, "ENCR_3DES"},
108 {ENCR_RC5
, "ENCR_RC5"},
109 {ENCR_IDEA
, "ENCR_IDEA"},
110 {ENCR_CAST
, "ENCR_CAST"},
111 {ENCR_BLOWFISH
, "ENCR_BLOWFISH"},
112 {ENCR_3IDEA
, "ENCR_3IDEA"},
113 {ENCR_DES_IV32
, "ENCR_DES_IV32"},
114 {ENCR_NULL
, "ENCR_NULL"},
115 {ENCR_AES_CBC
, "ENCR_AES_CBC"},
116 {ENCR_AES_CTR
, "ENCR_AES_CTR"},
121 * string mappings for encryption_algorithm_t
123 mapping_t pseudo_random_function_m
[] = {
124 {PRF_UNDEFINED
, "PRF_UNDEFINED"},
125 {PRF_HMAC_MD5
, "PRF_HMAC_SHA1"},
126 {PRF_HMAC_SHA1
, "PRF_HMAC_SHA1"},
127 {PRF_HMAC_TIGER
, "PRF_HMAC_TIGER"},
128 {PRF_AES128_CBC
, "PRF_AES128_CBC"},
133 * string mappings for integrity_algorithm_t
135 mapping_t integrity_algorithm_m
[] = {
136 {AUTH_UNDEFINED
, "AUTH_UNDEFINED"},
137 {AUTH_HMAC_MD5_96
, "AUTH_HMAC_MD5_96"},
138 {AUTH_HMAC_SHA1_96
, "AUTH_HMAC_SHA1_96"},
139 {AUTH_DES_MAC
, "AUTH_DES_MAC"},
140 {AUTH_KPDK_MD5
, "AUTH_KPDK_MD5"},
141 {AUTH_AES_XCBC_96
, "AUTH_AES_XCBC_96"},
146 * string mappings for diffie_hellman_group_t
148 mapping_t diffie_hellman_group_m
[] = {
149 {MODP_UNDEFINED
, "MODP_UNDEFINED"},
150 {MODP_768_BIT
, "MODP_768_BIT"},
151 {MODP_1024_BIT
, "MODP_1024_BIT"},
152 {MODP_1536_BIT
, "MODP_1536_BIT"},
153 {MODP_2048_BIT
, "MODP_2048_BIT"},
154 {MODP_3072_BIT
, "MODP_3072_BIT"},
155 {MODP_4096_BIT
, "MODP_4096_BIT"},
156 {MODP_6144_BIT
, "MODP_6144_BIT"},
157 {MODP_8192_BIT
, "MODP_8192_BIT"},
162 * string mappings for extended_sequence_numbers_t
164 mapping_t extended_sequence_numbers_m
[] = {
165 {NO_EXT_SEQ_NUMBERS
, "NO_EXT_SEQ_NUMBERS"},
166 {EXT_SEQ_NUMBERS
, "EXT_SEQ_NUMBERS"},
171 * Encoding rules to parse or generate a Transform substructure
173 * The defined offsets are the positions in a object of type
174 * private_transform_substructure_t.
177 encoding_rule_t transform_substructure_encodings
[] = {
178 /* 1 Byte next payload type, stored in the field next_payload */
179 { U_INT_8
, offsetof(private_transform_substructure_t
, next_payload
) },
180 /* Reserved Byte is skipped */
181 { RESERVED_BYTE
, 0 },
182 /* Length of the whole transform substructure*/
183 { PAYLOAD_LENGTH
, offsetof(private_transform_substructure_t
, transform_length
) },
184 /* transform type is a number of 8 bit */
185 { U_INT_8
, offsetof(private_transform_substructure_t
, transform_type
) },
186 /* Reserved Byte is skipped */
187 { RESERVED_BYTE
, 0 },
188 /* tranform ID is a number of 8 bit */
189 { U_INT_16
, offsetof(private_transform_substructure_t
, transform_id
) },
190 /* Attributes are stored in a transform attribute,
191 offset points to a linked_list_t pointer */
192 { TRANSFORM_ATTRIBUTES
, offsetof(private_transform_substructure_t
, attributes
) }
197 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
198 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
199 ! 0 (last) or 3 ! RESERVED ! Transform Length !
200 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
201 !Transform Type ! RESERVED ! Transform ID !
202 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
204 ~ Transform Attributes ~
206 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
211 * Implements payload_t's verify function.
212 * See #payload_s.verify for description.
214 static status_t
verify(private_transform_substructure_t
*this)
216 if ((this->next_payload
!= NO_PAYLOAD
) && (this->next_payload
!= TRANSFORM_SUBSTRUCTURE
))
222 switch (this->transform_type
)
224 case ENCRYPTION_ALGORITHM
:
226 if ((this->transform_id
< ENCR_DES_IV64
) || (this->transform_id
> ENCR_AES_CTR
))
232 case PSEUDO_RANDOM_FUNCTION
:
234 if ((this->transform_id
< PRF_HMAC_MD5
) || (this->transform_id
> PRF_AES128_CBC
))
240 case INTEGRITIY_ALGORITHM
:
242 if ((this->transform_id
< AUTH_HMAC_MD5_96
) || (this->transform_id
> AUTH_AES_XCBC_96
))
248 case DIFFIE_HELLMAN_GROUP
:
250 switch (this->transform_id
)
272 case EXTENDED_SEQUENCE_NUNBERS
:
274 if ((this->transform_id
!= NO_EXT_SEQ_NUMBERS
) && (this->transform_id
!= EXT_SEQ_NUMBERS
))
282 /* not a supported transform type! */
287 /* proposal number is checked in SA payload */
292 * Implements payload_t's and transform_substructure_t's destroy function.
293 * See #payload_s.destroy or transform_substructure_s.destroy for description.
295 static status_t
destroy(private_transform_substructure_t
*this)
297 /* all proposals are getting destroyed */
298 while (this->attributes
->get_count(this->attributes
) > 0)
300 transform_attribute_t
*current_attribute
;
301 if (this->attributes
->remove_last(this->attributes
,(void **)¤t_attribute
) != SUCCESS
)
305 current_attribute
->destroy(current_attribute
);
307 this->attributes
->destroy(this->attributes
);
309 allocator_free(this);
315 * Implements payload_t's get_encoding_rules function.
316 * See #payload_s.get_encoding_rules for description.
318 static status_t
get_encoding_rules(private_transform_substructure_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
320 *rules
= transform_substructure_encodings
;
321 *rule_count
= sizeof(transform_substructure_encodings
) / sizeof(encoding_rule_t
);
327 * Implements payload_t's get_type function.
328 * See #payload_s.get_type for description.
330 static payload_type_t
get_type(private_transform_substructure_t
*this)
332 return TRANSFORM_SUBSTRUCTURE
;
336 * Implements payload_t's get_next_type function.
337 * See #payload_s.get_next_type for description.
339 static payload_type_t
get_next_type(private_transform_substructure_t
*this)
341 return (this->next_payload
);
345 * Implements payload_t's get_length function.
346 * See #payload_s.get_length for description.
348 static size_t get_length(private_transform_substructure_t
*this)
350 this->compute_length(this);
352 return this->transform_length
;
356 * Implements transform_substructure_t's create_transform_attribute_iterator function.
357 * See #transform_substructure_s.create_transform_attribute_iterator for description.
359 static status_t
create_transform_attribute_iterator (private_transform_substructure_t
*this,linked_list_iterator_t
**iterator
,bool forward
)
361 return (this->attributes
->create_iterator(this->attributes
,iterator
,forward
));
365 * Implements transform_substructure_t's add_transform_attribute function.
366 * See #transform_substructure_s.add_transform_attribute for description.
368 static status_t
add_transform_attribute (private_transform_substructure_t
*this,transform_attribute_t
*attribute
)
371 status
= this->attributes
->insert_last(this->attributes
,(void *) attribute
);
372 this->compute_length(this);
377 * Implements transform_substructure_t's set_is_last_transform function.
378 * See #transform_substructure_s.set_is_last_transform for description.
380 static status_t
set_is_last_transform (private_transform_substructure_t
*this, bool is_last
)
382 this->next_payload
= (is_last
) ?
0: TRANSFORM_TYPE_VALUE
;
387 * Implements transform_substructure_t's get_is_last_transform function.
388 * See #transform_substructure_s.get_is_last_transform for description.
390 static bool get_is_last_transform (private_transform_substructure_t
*this)
392 return ((this->next_payload
== TRANSFORM_TYPE_VALUE
) ? FALSE
: TRUE
);
396 * Implements payload_t's set_next_type function.
397 * See #payload_s.set_next_type for description.
399 static status_t
set_next_type(private_transform_substructure_t
*this,payload_type_t type
)
405 * Implements transform_substructure_t's set_transform_type function.
406 * See #transform_substructure_s.set_transform_type for description.
408 static status_t
set_transform_type (private_transform_substructure_t
*this,u_int8_t type
)
410 this->transform_type
= type
;
415 * Implements transform_substructure_t's get_transform_type function.
416 * See #transform_substructure_s.get_transform_type for description.
418 static u_int8_t
get_transform_type (private_transform_substructure_t
*this)
420 return this->transform_type
;
424 * Implements transform_substructure_t's set_transform_id function.
425 * See #transform_substructure_s.set_transform_id for description.
427 static status_t
set_transform_id (private_transform_substructure_t
*this,u_int16_t id
)
429 this->transform_id
= id
;
434 * Implements transform_substructure_t's get_transform_id function.
435 * See #transform_substructure_s.get_transform_id for description.
437 static u_int16_t
get_transform_id (private_transform_substructure_t
*this)
439 return this->transform_id
;
443 * Implements private_transform_substructure_t's compute_length function.
444 * See #private_transform_substructure_s.compute_length for description.
446 static status_t
compute_length (private_transform_substructure_t
*this)
448 linked_list_iterator_t
*iterator
;
450 size_t length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
451 status
= this->attributes
->create_iterator(this->attributes
,&iterator
,TRUE
);
452 if (status
!= SUCCESS
)
456 while (iterator
->has_next(iterator
))
458 payload_t
* current_attribute
;
459 iterator
->current(iterator
,(void **) ¤t_attribute
);
460 length
+= current_attribute
->get_length(current_attribute
);
462 iterator
->destroy(iterator
);
464 this->transform_length
= length
;
470 * Described in header
472 transform_substructure_t
*transform_substructure_create()
474 private_transform_substructure_t
*this = allocator_alloc_thing(private_transform_substructure_t
);
480 /* payload interface */
481 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
482 this->public.payload_interface
.get_encoding_rules
= (status_t (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
483 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
484 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
485 this->public.payload_interface
.set_next_type
= (status_t (*) (payload_t
*,payload_type_t
)) set_next_type
;
486 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
487 this->public.payload_interface
.destroy
= (status_t (*) (payload_t
*))destroy
;
489 /* public functions */
490 this->public.create_transform_attribute_iterator
= (status_t (*) (transform_substructure_t
*,linked_list_iterator_t
**,bool)) create_transform_attribute_iterator
;
491 this->public.add_transform_attribute
= (status_t (*) (transform_substructure_t
*,transform_attribute_t
*)) add_transform_attribute
;
492 this->public.set_is_last_transform
= (status_t (*) (transform_substructure_t
*,bool)) set_is_last_transform
;
493 this->public.get_is_last_transform
= (bool (*) (transform_substructure_t
*)) get_is_last_transform
;
494 this->public.set_transform_type
= (status_t (*) (transform_substructure_t
*,u_int8_t
)) set_transform_type
;
495 this->public.get_transform_type
= (u_int8_t (*) (transform_substructure_t
*)) get_transform_type
;
496 this->public.set_transform_id
= (status_t (*) (transform_substructure_t
*,u_int16_t
)) set_transform_id
;
497 this->public.get_transform_id
= (u_int16_t (*) (transform_substructure_t
*)) get_transform_id
;
498 this->public.destroy
= (status_t (*) (transform_substructure_t
*)) destroy
;
500 /* private functions */
501 this->compute_length
= compute_length
;
503 /* set default values of the fields */
504 this->next_payload
= NO_PAYLOAD
;
505 this->transform_length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
506 this->transform_id
= 0;
507 this->transform_type
= 0;
509 this->attributes
= linked_list_create();
511 if (this->attributes
== NULL
)
513 allocator_free(this);
516 return (&(this->public));