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 status_t status
= SUCCESS
;
152 iterator_t
*iterator
;
154 if ((this->next_payload
!= NO_PAYLOAD
) && (this->next_payload
!= 3))
160 switch (this->transform_type
)
162 case ENCRYPTION_ALGORITHM
:
164 if ((this->transform_id
< ENCR_DES_IV64
) || (this->transform_id
> ENCR_AES_CTR
))
170 case PSEUDO_RANDOM_FUNCTION
:
172 if ((this->transform_id
< PRF_HMAC_MD5
) || (this->transform_id
> PRF_AES128_CBC
))
178 case INTEGRITY_ALGORITHM
:
180 if ((this->transform_id
< AUTH_HMAC_MD5_96
) || (this->transform_id
> AUTH_AES_XCBC_96
))
186 case DIFFIE_HELLMAN_GROUP
:
188 switch (this->transform_id
)
210 case EXTENDED_SEQUENCE_NUNBERS
:
212 if ((this->transform_id
!= NO_EXT_SEQ_NUMBERS
) && (this->transform_id
!= EXT_SEQ_NUMBERS
))
220 /* not a supported transform type! */
224 iterator
= this->attributes
->create_iterator(this->attributes
,TRUE
);
226 while(iterator
->has_next(iterator
))
228 payload_t
*current_attributes
;
229 iterator
->current(iterator
,(void **)¤t_attributes
);
231 status
= current_attributes
->verify(current_attributes
);
232 if (status
!= SUCCESS
)
238 iterator
->destroy(iterator
);
241 /* proposal number is checked in SA payload */
246 * Implementation of payload_t.get_encoding_rules.
248 static void get_encoding_rules(private_transform_substructure_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
250 *rules
= transform_substructure_encodings
;
251 *rule_count
= sizeof(transform_substructure_encodings
) / sizeof(encoding_rule_t
);
255 * Implementation of payload_t.get_type.
257 static payload_type_t
get_type(private_transform_substructure_t
*this)
259 return TRANSFORM_SUBSTRUCTURE
;
263 * Implementation of payload_t.get_next_type.
265 static payload_type_t
get_next_type(private_transform_substructure_t
*this)
267 return (this->next_payload
);
271 * Implementation of payload_t.get_length.
273 static size_t get_length(private_transform_substructure_t
*this)
275 this->compute_length(this);
277 return this->transform_length
;
281 * Implementation of transform_substructure_t.create_transform_attribute_iterator.
283 static iterator_t
*create_transform_attribute_iterator (private_transform_substructure_t
*this,bool forward
)
285 return this->attributes
->create_iterator(this->attributes
,forward
);
289 * Implementation of transform_substructure_t.add_transform_attribute.
291 static void add_transform_attribute (private_transform_substructure_t
*this,transform_attribute_t
*attribute
)
293 this->attributes
->insert_last(this->attributes
,(void *) attribute
);
294 this->compute_length(this);
298 * Implementation of transform_substructure_t.set_is_last_transform.
300 static void set_is_last_transform (private_transform_substructure_t
*this, bool is_last
)
302 this->next_payload
= (is_last
) ?
0: TRANSFORM_TYPE_VALUE
;
306 * Implementation of transform_substructure_t.get_is_last_transform.
308 static bool get_is_last_transform (private_transform_substructure_t
*this)
310 return ((this->next_payload
== TRANSFORM_TYPE_VALUE
) ? FALSE
: TRUE
);
314 * Implementation of payload_t.set_next_type.
316 static void set_next_type(private_transform_substructure_t
*this,payload_type_t type
)
321 * Implementation of transform_substructure_t.set_transform_type.
323 static void set_transform_type (private_transform_substructure_t
*this,u_int8_t type
)
325 this->transform_type
= type
;
329 * Implementation of transform_substructure_t.get_transform_type.
331 static u_int8_t
get_transform_type (private_transform_substructure_t
*this)
333 return this->transform_type
;
337 * Implementation of transform_substructure_t.set_transform_id.
339 static void set_transform_id (private_transform_substructure_t
*this,u_int16_t id
)
341 this->transform_id
= id
;
345 * Implementation of transform_substructure_t.get_transform_id.
347 static u_int16_t
get_transform_id (private_transform_substructure_t
*this)
349 return this->transform_id
;
353 * Implementation of private_transform_substructure_t.compute_length.
355 static void compute_length (private_transform_substructure_t
*this)
357 iterator_t
*iterator
;
358 size_t length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
359 iterator
= this->attributes
->create_iterator(this->attributes
,TRUE
);
360 while (iterator
->has_next(iterator
))
362 payload_t
* current_attribute
;
363 iterator
->current(iterator
,(void **) ¤t_attribute
);
364 length
+= current_attribute
->get_length(current_attribute
);
366 iterator
->destroy(iterator
);
368 this->transform_length
= length
;
373 * Implementation of transform_substructure_t.clone.
375 static transform_substructure_t
*clone(private_transform_substructure_t
*this)
377 private_transform_substructure_t
*new_clone
;
378 iterator_t
*attributes
;
380 new_clone
= (private_transform_substructure_t
*) transform_substructure_create();
382 new_clone
->next_payload
= this->next_payload
;
383 new_clone
->transform_type
= this->transform_type
;
384 new_clone
->transform_id
= this->transform_id
;
386 attributes
= this->attributes
->create_iterator(this->attributes
,FALSE
);
388 while (attributes
->has_next(attributes
))
390 transform_attribute_t
*current_attribute
;
391 transform_attribute_t
*current_attribute_clone
;
392 attributes
->current(attributes
,(void **) ¤t_attribute
);
394 current_attribute_clone
= current_attribute
->clone(current_attribute
);
396 new_clone
->public.add_transform_attribute(&(new_clone
->public),current_attribute_clone
);
399 attributes
->destroy(attributes
);
401 return &(new_clone
->public);
406 * Implementation of transform_substructure_t.get_key_length.
408 static status_t
get_key_length(private_transform_substructure_t
*this, u_int16_t
*key_length
)
410 iterator_t
*attributes
;
412 attributes
= this->attributes
->create_iterator(this->attributes
,TRUE
);
414 while (attributes
->has_next(attributes
))
416 transform_attribute_t
*current_attribute
;
417 attributes
->current(attributes
,(void **) ¤t_attribute
);
419 if (current_attribute
->get_attribute_type(current_attribute
) == KEY_LENGTH
)
421 *key_length
= current_attribute
->get_value(current_attribute
);
422 attributes
->destroy(attributes
);
427 attributes
->destroy(attributes
);
434 * Implementation of transform_substructure_t.destroy and payload_t.destroy.
436 static void destroy(private_transform_substructure_t
*this)
438 /* all proposals are getting destroyed */
439 while (this->attributes
->get_count(this->attributes
) > 0)
441 transform_attribute_t
*current_attribute
;
442 this->attributes
->remove_last(this->attributes
,(void **)¤t_attribute
);
443 current_attribute
->destroy(current_attribute
);
445 this->attributes
->destroy(this->attributes
);
447 allocator_free(this);
451 * Described in header.
453 transform_substructure_t
*transform_substructure_create()
455 private_transform_substructure_t
*this = allocator_alloc_thing(private_transform_substructure_t
);
457 /* payload interface */
458 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
459 this->public.payload_interface
.get_encoding_rules
= (void (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
460 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
461 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
462 this->public.payload_interface
.set_next_type
= (void (*) (payload_t
*,payload_type_t
)) set_next_type
;
463 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
464 this->public.payload_interface
.destroy
= (void (*) (payload_t
*))destroy
;
466 /* public functions */
467 this->public.create_transform_attribute_iterator
= (iterator_t
* (*) (transform_substructure_t
*,bool)) create_transform_attribute_iterator
;
468 this->public.add_transform_attribute
= (void (*) (transform_substructure_t
*,transform_attribute_t
*)) add_transform_attribute
;
469 this->public.set_is_last_transform
= (void (*) (transform_substructure_t
*,bool)) set_is_last_transform
;
470 this->public.get_is_last_transform
= (bool (*) (transform_substructure_t
*)) get_is_last_transform
;
471 this->public.set_transform_type
= (void (*) (transform_substructure_t
*,u_int8_t
)) set_transform_type
;
472 this->public.get_transform_type
= (u_int8_t (*) (transform_substructure_t
*)) get_transform_type
;
473 this->public.set_transform_id
= (void (*) (transform_substructure_t
*,u_int16_t
)) set_transform_id
;
474 this->public.get_transform_id
= (u_int16_t (*) (transform_substructure_t
*)) get_transform_id
;
475 this->public.get_key_length
= (status_t (*) (transform_substructure_t
*,u_int16_t
*)) get_key_length
;
476 this->public.clone
= (transform_substructure_t
* (*) (transform_substructure_t
*)) clone
;
477 this->public.destroy
= (void (*) (transform_substructure_t
*)) destroy
;
479 /* private functions */
480 this->compute_length
= compute_length
;
482 /* set default values of the fields */
483 this->next_payload
= NO_PAYLOAD
;
484 this->transform_length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
485 this->transform_id
= 0;
486 this->transform_type
= 0;
487 this->attributes
= linked_list_create();
489 return (&(this->public));
493 * Described in header
495 transform_substructure_t
*transform_substructure_create_type(transform_type_t transform_type
, u_int16_t transform_id
, u_int16_t key_length
)
497 transform_substructure_t
*transform
= transform_substructure_create();
499 transform
->set_transform_type(transform
,transform_type
);
500 transform
->set_transform_id(transform
,transform_id
);
502 switch (transform_type
)
504 case ENCRYPTION_ALGORITHM
:
505 case PSEUDO_RANDOM_FUNCTION
:
506 case INTEGRITY_ALGORITHM
:
508 transform_attribute_t
*attribute
= transform_attribute_create_key_length(key_length
);
509 transform
->add_transform_attribute(transform
,attribute
);
514 /* no keylength attribute is created */