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
25 #include "transform_substructure.h"
27 #include <encoding/payloads/transform_attribute.h>
28 #include <encoding/payloads/encodings.h>
30 #include <utils/linked_list.h>
33 typedef struct private_transform_substructure_t private_transform_substructure_t
;
36 * Private data of an transform_substructure_t object.
39 struct private_transform_substructure_t
{
41 * Public transform_substructure_t interface.
43 transform_substructure_t
public;
48 u_int8_t next_payload
;
52 * Length of this payload.
54 u_int16_t transform_length
;
58 * Type of the transform.
60 u_int8_t transform_type
;
65 u_int16_t transform_id
;
68 * Transforms Attributes are stored in a linked_list_t.
70 linked_list_t
*attributes
;
73 * @brief Computes the length of this substructure.
75 * @param this calling private_transform_substructure_t object
77 void (*compute_length
) (private_transform_substructure_t
*this);
82 * Encoding rules to parse or generate a Transform substructure.
84 * The defined offsets are the positions in a object of type
85 * private_transform_substructure_t.
88 encoding_rule_t transform_substructure_encodings
[] = {
89 /* 1 Byte next payload type, stored in the field next_payload */
90 { U_INT_8
, offsetof(private_transform_substructure_t
, next_payload
) },
91 /* Reserved Byte is skipped */
93 /* Length of the whole transform substructure*/
94 { PAYLOAD_LENGTH
, offsetof(private_transform_substructure_t
, transform_length
) },
95 /* transform type is a number of 8 bit */
96 { U_INT_8
, offsetof(private_transform_substructure_t
, transform_type
) },
97 /* Reserved Byte is skipped */
99 /* tranform ID is a number of 8 bit */
100 { U_INT_16
, offsetof(private_transform_substructure_t
, transform_id
) },
101 /* Attributes are stored in a transform attribute,
102 offset points to a linked_list_t pointer */
103 { TRANSFORM_ATTRIBUTES
, offsetof(private_transform_substructure_t
, attributes
) }
108 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
109 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
110 ! 0 (last) or 3 ! RESERVED ! Transform Length !
111 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
112 !Transform Type ! RESERVED ! Transform ID !
113 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115 ~ Transform Attributes ~
117 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122 * Implementation of payload_t.verify.
124 static status_t
verify(private_transform_substructure_t
*this)
126 status_t status
= SUCCESS
;
127 iterator_t
*iterator
;
129 if ((this->next_payload
!= NO_PAYLOAD
) && (this->next_payload
!= 3))
135 switch (this->transform_type
)
137 case ENCRYPTION_ALGORITHM
:
139 if ((this->transform_id
< ENCR_DES_IV64
) || (this->transform_id
> ENCR_AES_CTR
))
145 case PSEUDO_RANDOM_FUNCTION
:
147 if ((this->transform_id
< PRF_HMAC_MD5
) || (this->transform_id
> PRF_AES128_CBC
))
153 case INTEGRITY_ALGORITHM
:
155 if ((this->transform_id
< AUTH_HMAC_MD5_96
) || (this->transform_id
> AUTH_AES_XCBC_96
))
161 case DIFFIE_HELLMAN_GROUP
:
163 switch (this->transform_id
)
185 case EXTENDED_SEQUENCE_NUMBERS
:
187 if ((this->transform_id
!= NO_EXT_SEQ_NUMBERS
) && (this->transform_id
!= EXT_SEQ_NUMBERS
))
195 /* not a supported transform type! */
199 iterator
= this->attributes
->create_iterator(this->attributes
,TRUE
);
201 while(iterator
->has_next(iterator
))
203 payload_t
*current_attributes
;
204 iterator
->current(iterator
,(void **)¤t_attributes
);
206 status
= current_attributes
->verify(current_attributes
);
207 if (status
!= SUCCESS
)
213 iterator
->destroy(iterator
);
216 /* proposal number is checked in SA payload */
221 * Implementation of payload_t.get_encoding_rules.
223 static void get_encoding_rules(private_transform_substructure_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
225 *rules
= transform_substructure_encodings
;
226 *rule_count
= sizeof(transform_substructure_encodings
) / sizeof(encoding_rule_t
);
230 * Implementation of payload_t.get_type.
232 static payload_type_t
get_type(private_transform_substructure_t
*this)
234 return TRANSFORM_SUBSTRUCTURE
;
238 * Implementation of payload_t.get_next_type.
240 static payload_type_t
get_next_type(private_transform_substructure_t
*this)
242 return (this->next_payload
);
246 * Implementation of payload_t.get_length.
248 static size_t get_length(private_transform_substructure_t
*this)
250 this->compute_length(this);
252 return this->transform_length
;
256 * Implementation of transform_substructure_t.create_transform_attribute_iterator.
258 static iterator_t
*create_transform_attribute_iterator (private_transform_substructure_t
*this,bool forward
)
260 return this->attributes
->create_iterator(this->attributes
,forward
);
264 * Implementation of transform_substructure_t.add_transform_attribute.
266 static void add_transform_attribute (private_transform_substructure_t
*this,transform_attribute_t
*attribute
)
268 this->attributes
->insert_last(this->attributes
,(void *) attribute
);
269 this->compute_length(this);
273 * Implementation of transform_substructure_t.set_is_last_transform.
275 static void set_is_last_transform (private_transform_substructure_t
*this, bool is_last
)
277 this->next_payload
= (is_last
) ? 0: TRANSFORM_TYPE_VALUE
;
281 * Implementation of transform_substructure_t.get_is_last_transform.
283 static bool get_is_last_transform (private_transform_substructure_t
*this)
285 return ((this->next_payload
== TRANSFORM_TYPE_VALUE
) ? FALSE
: TRUE
);
289 * Implementation of payload_t.set_next_type.
291 static void set_next_type(private_transform_substructure_t
*this,payload_type_t type
)
296 * Implementation of transform_substructure_t.set_transform_type.
298 static void set_transform_type (private_transform_substructure_t
*this,u_int8_t type
)
300 this->transform_type
= type
;
304 * Implementation of transform_substructure_t.get_transform_type.
306 static u_int8_t
get_transform_type (private_transform_substructure_t
*this)
308 return this->transform_type
;
312 * Implementation of transform_substructure_t.set_transform_id.
314 static void set_transform_id (private_transform_substructure_t
*this,u_int16_t id
)
316 this->transform_id
= id
;
320 * Implementation of transform_substructure_t.get_transform_id.
322 static u_int16_t
get_transform_id (private_transform_substructure_t
*this)
324 return this->transform_id
;
328 * Implementation of private_transform_substructure_t.compute_length.
330 static void compute_length (private_transform_substructure_t
*this)
332 iterator_t
*iterator
;
333 size_t length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
334 iterator
= this->attributes
->create_iterator(this->attributes
,TRUE
);
335 while (iterator
->has_next(iterator
))
337 payload_t
* current_attribute
;
338 iterator
->current(iterator
,(void **) ¤t_attribute
);
339 length
+= current_attribute
->get_length(current_attribute
);
341 iterator
->destroy(iterator
);
343 this->transform_length
= length
;
347 * Implementation of transform_substructure_t.clone.
349 static transform_substructure_t
*clone(private_transform_substructure_t
*this)
351 private_transform_substructure_t
*new_clone
;
352 iterator_t
*attributes
;
354 new_clone
= (private_transform_substructure_t
*) transform_substructure_create();
356 new_clone
->next_payload
= this->next_payload
;
357 new_clone
->transform_type
= this->transform_type
;
358 new_clone
->transform_id
= this->transform_id
;
360 attributes
= this->attributes
->create_iterator(this->attributes
,FALSE
);
362 while (attributes
->has_next(attributes
))
364 transform_attribute_t
*current_attribute
;
365 transform_attribute_t
*current_attribute_clone
;
366 attributes
->current(attributes
,(void **) ¤t_attribute
);
368 current_attribute_clone
= current_attribute
->clone(current_attribute
);
370 new_clone
->public.add_transform_attribute(&(new_clone
->public),current_attribute_clone
);
373 attributes
->destroy(attributes
);
375 return &(new_clone
->public);
380 * Implementation of transform_substructure_t.get_key_length.
382 static status_t
get_key_length(private_transform_substructure_t
*this, u_int16_t
*key_length
)
384 iterator_t
*attributes
;
386 attributes
= this->attributes
->create_iterator(this->attributes
,TRUE
);
388 while (attributes
->has_next(attributes
))
390 transform_attribute_t
*current_attribute
;
391 attributes
->current(attributes
,(void **) ¤t_attribute
);
393 if (current_attribute
->get_attribute_type(current_attribute
) == KEY_LENGTH
)
395 *key_length
= current_attribute
->get_value(current_attribute
);
396 attributes
->destroy(attributes
);
401 attributes
->destroy(attributes
);
408 * Implementation of transform_substructure_t.destroy and payload_t.destroy.
410 static void destroy(private_transform_substructure_t
*this)
412 /* all proposals are getting destroyed */
413 while (this->attributes
->get_count(this->attributes
) > 0)
415 transform_attribute_t
*current_attribute
;
416 this->attributes
->remove_last(this->attributes
,(void **)¤t_attribute
);
417 current_attribute
->destroy(current_attribute
);
419 this->attributes
->destroy(this->attributes
);
425 * Described in header.
427 transform_substructure_t
*transform_substructure_create()
429 private_transform_substructure_t
*this = malloc_thing(private_transform_substructure_t
);
431 /* payload interface */
432 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
433 this->public.payload_interface
.get_encoding_rules
= (void (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
434 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
435 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
436 this->public.payload_interface
.set_next_type
= (void (*) (payload_t
*,payload_type_t
)) set_next_type
;
437 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
438 this->public.payload_interface
.destroy
= (void (*) (payload_t
*))destroy
;
440 /* public functions */
441 this->public.create_transform_attribute_iterator
= (iterator_t
* (*) (transform_substructure_t
*,bool)) create_transform_attribute_iterator
;
442 this->public.add_transform_attribute
= (void (*) (transform_substructure_t
*,transform_attribute_t
*)) add_transform_attribute
;
443 this->public.set_is_last_transform
= (void (*) (transform_substructure_t
*,bool)) set_is_last_transform
;
444 this->public.get_is_last_transform
= (bool (*) (transform_substructure_t
*)) get_is_last_transform
;
445 this->public.set_transform_type
= (void (*) (transform_substructure_t
*,u_int8_t
)) set_transform_type
;
446 this->public.get_transform_type
= (u_int8_t (*) (transform_substructure_t
*)) get_transform_type
;
447 this->public.set_transform_id
= (void (*) (transform_substructure_t
*,u_int16_t
)) set_transform_id
;
448 this->public.get_transform_id
= (u_int16_t (*) (transform_substructure_t
*)) get_transform_id
;
449 this->public.get_key_length
= (status_t (*) (transform_substructure_t
*,u_int16_t
*)) get_key_length
;
450 this->public.clone
= (transform_substructure_t
* (*) (transform_substructure_t
*)) clone
;
451 this->public.destroy
= (void (*) (transform_substructure_t
*)) destroy
;
453 /* private functions */
454 this->compute_length
= compute_length
;
456 /* set default values of the fields */
457 this->next_payload
= NO_PAYLOAD
;
458 this->transform_length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
459 this->transform_id
= 0;
460 this->transform_type
= 0;
461 this->attributes
= linked_list_create();
463 return (&(this->public));
467 * Described in header
469 transform_substructure_t
*transform_substructure_create_type(transform_type_t transform_type
, u_int16_t transform_id
, u_int16_t key_length
)
471 transform_substructure_t
*transform
= transform_substructure_create();
473 transform
->set_transform_type(transform
,transform_type
);
474 transform
->set_transform_id(transform
,transform_id
);
476 /* a keylength attribute is only created for AES encryption */
477 if (transform_type
== ENCRYPTION_ALGORITHM
&&
478 transform_id
== ENCR_AES_CBC
)
480 transform_attribute_t
*attribute
= transform_attribute_create_key_length(key_length
);
481 transform
->add_transform_attribute(transform
,attribute
);