2 * @file transform_substructure.h
4 * @brief Implementation of transform_substructure_t.
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 #include "transform_substructure.h"
28 #include <encoding/payloads/transform_attribute.h>
29 #include <encoding/payloads/encodings.h>
31 #include <utils/allocator.h>
32 #include <utils/linked_list.h>
35 typedef struct private_transform_substructure_t private_transform_substructure_t
;
38 * Private data of an transform_substructure_t object.
41 struct private_transform_substructure_t
{
43 * Public transform_substructure_t interface.
45 transform_substructure_t
public;
50 u_int8_t next_payload
;
54 * Length of this payload.
56 u_int16_t transform_length
;
60 * Type of the transform.
62 u_int8_t transform_type
;
67 u_int16_t transform_id
;
70 * Transforms Attributes are stored in a linked_list_t.
72 linked_list_t
*attributes
;
75 * @brief Computes the length of this substructure.
77 * @param this calling private_transform_substructure_t object
79 void (*compute_length
) (private_transform_substructure_t
*this);
84 * String mappings for transform_type_t.
86 mapping_t transform_type_m
[] = {
87 {UNDEFINED_TRANSFORM_TYPE
, "UNDEFINED_TRANSFORM_TYPE"},
88 {ENCRYPTION_ALGORITHM
, "ENCRYPTION_ALGORITHM"},
89 {PSEUDO_RANDOM_FUNCTION
, "PSEUDO_RANDOM_FUNCTION"},
90 {INTEGRITY_ALGORITHM
, "INTEGRITY_ALGORITHM"},
91 {DIFFIE_HELLMAN_GROUP
, "DIFFIE_HELLMAN_GROUP"},
92 {EXTENDED_SEQUENCE_NUNBERS
, "EXTENDED_SEQUENCE_NUNBERS"},
98 * String mappings for extended_sequence_numbers_t.
100 mapping_t extended_sequence_numbers_m
[] = {
101 {NO_EXT_SEQ_NUMBERS
, "NO_EXT_SEQ_NUMBERS"},
102 {EXT_SEQ_NUMBERS
, "EXT_SEQ_NUMBERS"},
107 * Encoding rules to parse or generate a Transform substructure.
109 * The defined offsets are the positions in a object of type
110 * private_transform_substructure_t.
113 encoding_rule_t transform_substructure_encodings
[] = {
114 /* 1 Byte next payload type, stored in the field next_payload */
115 { U_INT_8
, offsetof(private_transform_substructure_t
, next_payload
) },
116 /* Reserved Byte is skipped */
117 { RESERVED_BYTE
, 0 },
118 /* Length of the whole transform substructure*/
119 { PAYLOAD_LENGTH
, offsetof(private_transform_substructure_t
, transform_length
) },
120 /* transform type is a number of 8 bit */
121 { U_INT_8
, offsetof(private_transform_substructure_t
, transform_type
) },
122 /* Reserved Byte is skipped */
123 { RESERVED_BYTE
, 0 },
124 /* tranform ID is a number of 8 bit */
125 { U_INT_16
, offsetof(private_transform_substructure_t
, transform_id
) },
126 /* Attributes are stored in a transform attribute,
127 offset points to a linked_list_t pointer */
128 { TRANSFORM_ATTRIBUTES
, offsetof(private_transform_substructure_t
, attributes
) }
133 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
134 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135 ! 0 (last) or 3 ! RESERVED ! Transform Length !
136 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
137 !Transform Type ! RESERVED ! Transform ID !
138 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
140 ~ Transform Attributes ~
142 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
147 * Implementation of payload_t.verify.
149 static status_t
verify(private_transform_substructure_t
*this)
151 if ((this->next_payload
!= NO_PAYLOAD
) && (this->next_payload
!= TRANSFORM_SUBSTRUCTURE
))
157 switch (this->transform_type
)
159 case ENCRYPTION_ALGORITHM
:
161 if ((this->transform_id
< ENCR_DES_IV64
) || (this->transform_id
> ENCR_AES_CTR
))
167 case PSEUDO_RANDOM_FUNCTION
:
169 if ((this->transform_id
< PRF_HMAC_MD5
) || (this->transform_id
> PRF_AES128_CBC
))
175 case INTEGRITY_ALGORITHM
:
177 if ((this->transform_id
< AUTH_HMAC_MD5_96
) || (this->transform_id
> AUTH_AES_XCBC_96
))
183 case DIFFIE_HELLMAN_GROUP
:
185 switch (this->transform_id
)
207 case EXTENDED_SEQUENCE_NUNBERS
:
209 if ((this->transform_id
!= NO_EXT_SEQ_NUMBERS
) && (this->transform_id
!= EXT_SEQ_NUMBERS
))
217 /* not a supported transform type! */
222 /* proposal number is checked in SA payload */
227 * Implementation of payload_t.get_encoding_rules.
229 static void get_encoding_rules(private_transform_substructure_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
231 *rules
= transform_substructure_encodings
;
232 *rule_count
= sizeof(transform_substructure_encodings
) / sizeof(encoding_rule_t
);
236 * Implementation of payload_t.get_type.
238 static payload_type_t
get_type(private_transform_substructure_t
*this)
240 return TRANSFORM_SUBSTRUCTURE
;
244 * Implementation of payload_t.get_next_type.
246 static payload_type_t
get_next_type(private_transform_substructure_t
*this)
248 return (this->next_payload
);
252 * Implementation of payload_t.get_length.
254 static size_t get_length(private_transform_substructure_t
*this)
256 this->compute_length(this);
258 return this->transform_length
;
262 * Implementation of transform_substructure_t.create_transform_attribute_iterator.
264 static iterator_t
*create_transform_attribute_iterator (private_transform_substructure_t
*this,bool forward
)
266 return this->attributes
->create_iterator(this->attributes
,forward
);
270 * Implementation of transform_substructure_t.add_transform_attribute.
272 static void add_transform_attribute (private_transform_substructure_t
*this,transform_attribute_t
*attribute
)
274 this->attributes
->insert_last(this->attributes
,(void *) attribute
);
275 this->compute_length(this);
279 * Implementation of transform_substructure_t.set_is_last_transform.
281 static void set_is_last_transform (private_transform_substructure_t
*this, bool is_last
)
283 this->next_payload
= (is_last
) ?
0: TRANSFORM_TYPE_VALUE
;
287 * Implementation of transform_substructure_t.get_is_last_transform.
289 static bool get_is_last_transform (private_transform_substructure_t
*this)
291 return ((this->next_payload
== TRANSFORM_TYPE_VALUE
) ? FALSE
: TRUE
);
295 * Implementation of payload_t.set_next_type.
297 static void set_next_type(private_transform_substructure_t
*this,payload_type_t type
)
302 * Implementation of transform_substructure_t.set_transform_type.
304 static void set_transform_type (private_transform_substructure_t
*this,u_int8_t type
)
306 this->transform_type
= type
;
310 * Implementation of transform_substructure_t.get_transform_type.
312 static u_int8_t
get_transform_type (private_transform_substructure_t
*this)
314 return this->transform_type
;
318 * Implementation of transform_substructure_t.set_transform_id.
320 static void set_transform_id (private_transform_substructure_t
*this,u_int16_t id
)
322 this->transform_id
= id
;
326 * Implementation of transform_substructure_t.get_transform_id.
328 static u_int16_t
get_transform_id (private_transform_substructure_t
*this)
330 return this->transform_id
;
334 * Implementation of private_transform_substructure_t.compute_length.
336 static void compute_length (private_transform_substructure_t
*this)
338 iterator_t
*iterator
;
339 size_t length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
340 iterator
= this->attributes
->create_iterator(this->attributes
,TRUE
);
341 while (iterator
->has_next(iterator
))
343 payload_t
* current_attribute
;
344 iterator
->current(iterator
,(void **) ¤t_attribute
);
345 length
+= current_attribute
->get_length(current_attribute
);
347 iterator
->destroy(iterator
);
349 this->transform_length
= length
;
354 * Implementation of transform_substructure_t.clone.
356 static transform_substructure_t
*clone(private_transform_substructure_t
*this)
358 private_transform_substructure_t
*new_clone
;
359 iterator_t
*attributes
;
361 new_clone
= (private_transform_substructure_t
*) transform_substructure_create();
363 new_clone
->next_payload
= this->next_payload
;
364 new_clone
->transform_type
= this->transform_type
;
365 new_clone
->transform_id
= this->transform_id
;
367 attributes
= this->attributes
->create_iterator(this->attributes
,FALSE
);
369 while (attributes
->has_next(attributes
))
371 transform_attribute_t
*current_attribute
;
372 transform_attribute_t
*current_attribute_clone
;
373 attributes
->current(attributes
,(void **) ¤t_attribute
);
375 current_attribute_clone
= current_attribute
->clone(current_attribute
);
377 new_clone
->public.add_transform_attribute(&(new_clone
->public),current_attribute_clone
);
380 attributes
->destroy(attributes
);
382 return &(new_clone
->public);
387 * Implementation of transform_substructure_t.get_key_length.
389 static status_t
get_key_length(private_transform_substructure_t
*this, u_int16_t
*key_length
)
391 iterator_t
*attributes
;
393 attributes
= this->attributes
->create_iterator(this->attributes
,TRUE
);
395 while (attributes
->has_next(attributes
))
397 transform_attribute_t
*current_attribute
;
398 attributes
->current(attributes
,(void **) ¤t_attribute
);
400 if (current_attribute
->get_attribute_type(current_attribute
) == KEY_LENGTH
)
402 *key_length
= current_attribute
->get_value(current_attribute
);
403 attributes
->destroy(attributes
);
408 attributes
->destroy(attributes
);
415 * Implementation of transform_substructure_t.destroy and payload_t.destroy.
417 static void destroy(private_transform_substructure_t
*this)
419 /* all proposals are getting destroyed */
420 while (this->attributes
->get_count(this->attributes
) > 0)
422 transform_attribute_t
*current_attribute
;
423 this->attributes
->remove_last(this->attributes
,(void **)¤t_attribute
);
424 current_attribute
->destroy(current_attribute
);
426 this->attributes
->destroy(this->attributes
);
428 allocator_free(this);
432 * Described in header
434 transform_substructure_t
*transform_substructure_create()
436 private_transform_substructure_t
*this = allocator_alloc_thing(private_transform_substructure_t
);
438 /* payload interface */
439 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
440 this->public.payload_interface
.get_encoding_rules
= (void (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
441 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
442 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
443 this->public.payload_interface
.set_next_type
= (void (*) (payload_t
*,payload_type_t
)) set_next_type
;
444 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
445 this->public.payload_interface
.destroy
= (void (*) (payload_t
*))destroy
;
447 /* public functions */
448 this->public.create_transform_attribute_iterator
= (iterator_t
* (*) (transform_substructure_t
*,bool)) create_transform_attribute_iterator
;
449 this->public.add_transform_attribute
= (void (*) (transform_substructure_t
*,transform_attribute_t
*)) add_transform_attribute
;
450 this->public.set_is_last_transform
= (void (*) (transform_substructure_t
*,bool)) set_is_last_transform
;
451 this->public.get_is_last_transform
= (bool (*) (transform_substructure_t
*)) get_is_last_transform
;
452 this->public.set_transform_type
= (void (*) (transform_substructure_t
*,u_int8_t
)) set_transform_type
;
453 this->public.get_transform_type
= (u_int8_t (*) (transform_substructure_t
*)) get_transform_type
;
454 this->public.set_transform_id
= (void (*) (transform_substructure_t
*,u_int16_t
)) set_transform_id
;
455 this->public.get_transform_id
= (u_int16_t (*) (transform_substructure_t
*)) get_transform_id
;
456 this->public.get_key_length
= (status_t (*) (transform_substructure_t
*,u_int16_t
*)) get_key_length
;
457 this->public.clone
= (transform_substructure_t
* (*) (transform_substructure_t
*)) clone
;
458 this->public.destroy
= (void (*) (transform_substructure_t
*)) destroy
;
460 /* private functions */
461 this->compute_length
= compute_length
;
463 /* set default values of the fields */
464 this->next_payload
= NO_PAYLOAD
;
465 this->transform_length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
466 this->transform_id
= 0;
467 this->transform_type
= 0;
468 this->attributes
= linked_list_create();
470 return (&(this->public));