2 * @file transform_substructure.h
4 * @brief Implementation of transform_substructure_t.
9 * Copyright (C) 2005-2006 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * 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/linked_list.h>
32 #include <utils/logger_manager.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
;
80 * @brief Computes the length of this substructure.
82 * @param this calling private_transform_substructure_t object
84 void (*compute_length
) (private_transform_substructure_t
*this);
89 * Encoding rules to parse or generate a Transform substructure.
91 * The defined offsets are the positions in a object of type
92 * private_transform_substructure_t.
95 encoding_rule_t transform_substructure_encodings
[] = {
96 /* 1 Byte next payload type, stored in the field next_payload */
97 { U_INT_8
, offsetof(private_transform_substructure_t
, next_payload
) },
98 /* Reserved Byte is skipped */
100 /* Length of the whole transform substructure*/
101 { PAYLOAD_LENGTH
, offsetof(private_transform_substructure_t
, transform_length
) },
102 /* transform type is a number of 8 bit */
103 { U_INT_8
, offsetof(private_transform_substructure_t
, transform_type
) },
104 /* Reserved Byte is skipped */
105 { RESERVED_BYTE
, 0 },
106 /* tranform ID is a number of 8 bit */
107 { U_INT_16
, offsetof(private_transform_substructure_t
, transform_id
) },
108 /* Attributes are stored in a transform attribute,
109 offset points to a linked_list_t pointer */
110 { TRANSFORM_ATTRIBUTES
, offsetof(private_transform_substructure_t
, attributes
) }
115 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
116 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117 ! 0 (last) or 3 ! RESERVED ! Transform Length !
118 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119 !Transform Type ! RESERVED ! Transform ID !
120 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122 ~ Transform Attributes ~
124 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129 * Implementation of payload_t.verify.
131 static status_t
verify(private_transform_substructure_t
*this)
133 status_t status
= SUCCESS
;
134 iterator_t
*iterator
;
136 if ((this->next_payload
!= NO_PAYLOAD
) && (this->next_payload
!= 3))
139 this->logger
->log(this->logger
, ERROR
, "inconsistent next payload");
143 switch (this->transform_type
)
145 case ENCRYPTION_ALGORITHM
:
146 case PSEUDO_RANDOM_FUNCTION
:
147 case INTEGRITY_ALGORITHM
:
148 case DIFFIE_HELLMAN_GROUP
:
149 case EXTENDED_SEQUENCE_NUMBERS
:
150 /* we don't check transform ID, we want to reply
151 * cleanly with NO_PROPOSAL_CHOSEN or so if we don't support it */
155 this->logger
->log(this->logger
, ERROR
, "invalid transform type: %d",
156 this->transform_type
);
160 iterator
= this->attributes
->create_iterator(this->attributes
,TRUE
);
162 while(iterator
->has_next(iterator
))
164 payload_t
*current_attributes
;
165 iterator
->current(iterator
,(void **)¤t_attributes
);
167 status
= current_attributes
->verify(current_attributes
);
168 if (status
!= SUCCESS
)
170 this->logger
->log(this->logger
, ERROR
,
171 "TRANSFORM_ATTRIBUTE verification failed");
174 iterator
->destroy(iterator
);
176 /* proposal number is checked in SA payload */
181 * Implementation of payload_t.get_encoding_rules.
183 static void get_encoding_rules(private_transform_substructure_t
*this, encoding_rule_t
**rules
, size_t *rule_count
)
185 *rules
= transform_substructure_encodings
;
186 *rule_count
= sizeof(transform_substructure_encodings
) / sizeof(encoding_rule_t
);
190 * Implementation of payload_t.get_type.
192 static payload_type_t
get_type(private_transform_substructure_t
*this)
194 return TRANSFORM_SUBSTRUCTURE
;
198 * Implementation of payload_t.get_next_type.
200 static payload_type_t
get_next_type(private_transform_substructure_t
*this)
202 return (this->next_payload
);
206 * Implementation of payload_t.get_length.
208 static size_t get_length(private_transform_substructure_t
*this)
210 this->compute_length(this);
212 return this->transform_length
;
216 * Implementation of transform_substructure_t.create_transform_attribute_iterator.
218 static iterator_t
*create_transform_attribute_iterator (private_transform_substructure_t
*this,bool forward
)
220 return this->attributes
->create_iterator(this->attributes
,forward
);
224 * Implementation of transform_substructure_t.add_transform_attribute.
226 static void add_transform_attribute (private_transform_substructure_t
*this,transform_attribute_t
*attribute
)
228 this->attributes
->insert_last(this->attributes
,(void *) attribute
);
229 this->compute_length(this);
233 * Implementation of transform_substructure_t.set_is_last_transform.
235 static void set_is_last_transform (private_transform_substructure_t
*this, bool is_last
)
237 this->next_payload
= (is_last
) ?
0: TRANSFORM_TYPE_VALUE
;
241 * Implementation of transform_substructure_t.get_is_last_transform.
243 static bool get_is_last_transform (private_transform_substructure_t
*this)
245 return ((this->next_payload
== TRANSFORM_TYPE_VALUE
) ? FALSE
: TRUE
);
249 * Implementation of payload_t.set_next_type.
251 static void set_next_type(private_transform_substructure_t
*this,payload_type_t type
)
256 * Implementation of transform_substructure_t.set_transform_type.
258 static void set_transform_type (private_transform_substructure_t
*this,u_int8_t type
)
260 this->transform_type
= type
;
264 * Implementation of transform_substructure_t.get_transform_type.
266 static u_int8_t
get_transform_type (private_transform_substructure_t
*this)
268 return this->transform_type
;
272 * Implementation of transform_substructure_t.set_transform_id.
274 static void set_transform_id (private_transform_substructure_t
*this,u_int16_t id
)
276 this->transform_id
= id
;
280 * Implementation of transform_substructure_t.get_transform_id.
282 static u_int16_t
get_transform_id (private_transform_substructure_t
*this)
284 return this->transform_id
;
288 * Implementation of private_transform_substructure_t.compute_length.
290 static void compute_length (private_transform_substructure_t
*this)
292 iterator_t
*iterator
;
293 size_t length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
294 iterator
= this->attributes
->create_iterator(this->attributes
,TRUE
);
295 while (iterator
->has_next(iterator
))
297 payload_t
* current_attribute
;
298 iterator
->current(iterator
,(void **) ¤t_attribute
);
299 length
+= current_attribute
->get_length(current_attribute
);
301 iterator
->destroy(iterator
);
303 this->transform_length
= length
;
307 * Implementation of transform_substructure_t.clone.
309 static transform_substructure_t
*clone_(private_transform_substructure_t
*this)
311 private_transform_substructure_t
*new_clone
;
312 iterator_t
*attributes
;
314 new_clone
= (private_transform_substructure_t
*) transform_substructure_create();
316 new_clone
->next_payload
= this->next_payload
;
317 new_clone
->transform_type
= this->transform_type
;
318 new_clone
->transform_id
= this->transform_id
;
320 attributes
= this->attributes
->create_iterator(this->attributes
,FALSE
);
322 while (attributes
->has_next(attributes
))
324 transform_attribute_t
*current_attribute
;
325 transform_attribute_t
*current_attribute_clone
;
326 attributes
->current(attributes
,(void **) ¤t_attribute
);
328 current_attribute_clone
= current_attribute
->clone(current_attribute
);
330 new_clone
->public.add_transform_attribute(&(new_clone
->public),current_attribute_clone
);
333 attributes
->destroy(attributes
);
335 return &(new_clone
->public);
340 * Implementation of transform_substructure_t.get_key_length.
342 static status_t
get_key_length(private_transform_substructure_t
*this, u_int16_t
*key_length
)
344 iterator_t
*attributes
;
346 attributes
= this->attributes
->create_iterator(this->attributes
,TRUE
);
348 while (attributes
->has_next(attributes
))
350 transform_attribute_t
*current_attribute
;
351 attributes
->current(attributes
,(void **) ¤t_attribute
);
353 if (current_attribute
->get_attribute_type(current_attribute
) == KEY_LENGTH
)
355 *key_length
= current_attribute
->get_value(current_attribute
);
356 attributes
->destroy(attributes
);
361 attributes
->destroy(attributes
);
368 * Implementation of transform_substructure_t.destroy and payload_t.destroy.
370 static void destroy(private_transform_substructure_t
*this)
372 /* all proposals are getting destroyed */
373 while (this->attributes
->get_count(this->attributes
) > 0)
375 transform_attribute_t
*current_attribute
;
376 this->attributes
->remove_last(this->attributes
,(void **)¤t_attribute
);
377 current_attribute
->destroy(current_attribute
);
379 this->attributes
->destroy(this->attributes
);
385 * Described in header.
387 transform_substructure_t
*transform_substructure_create()
389 private_transform_substructure_t
*this = malloc_thing(private_transform_substructure_t
);
391 /* payload interface */
392 this->public.payload_interface
.verify
= (status_t (*) (payload_t
*))verify
;
393 this->public.payload_interface
.get_encoding_rules
= (void (*) (payload_t
*, encoding_rule_t
**, size_t *) ) get_encoding_rules
;
394 this->public.payload_interface
.get_length
= (size_t (*) (payload_t
*)) get_length
;
395 this->public.payload_interface
.get_next_type
= (payload_type_t (*) (payload_t
*)) get_next_type
;
396 this->public.payload_interface
.set_next_type
= (void (*) (payload_t
*,payload_type_t
)) set_next_type
;
397 this->public.payload_interface
.get_type
= (payload_type_t (*) (payload_t
*)) get_type
;
398 this->public.payload_interface
.destroy
= (void (*) (payload_t
*))destroy
;
400 /* public functions */
401 this->public.create_transform_attribute_iterator
= (iterator_t
* (*) (transform_substructure_t
*,bool)) create_transform_attribute_iterator
;
402 this->public.add_transform_attribute
= (void (*) (transform_substructure_t
*,transform_attribute_t
*)) add_transform_attribute
;
403 this->public.set_is_last_transform
= (void (*) (transform_substructure_t
*,bool)) set_is_last_transform
;
404 this->public.get_is_last_transform
= (bool (*) (transform_substructure_t
*)) get_is_last_transform
;
405 this->public.set_transform_type
= (void (*) (transform_substructure_t
*,u_int8_t
)) set_transform_type
;
406 this->public.get_transform_type
= (u_int8_t (*) (transform_substructure_t
*)) get_transform_type
;
407 this->public.set_transform_id
= (void (*) (transform_substructure_t
*,u_int16_t
)) set_transform_id
;
408 this->public.get_transform_id
= (u_int16_t (*) (transform_substructure_t
*)) get_transform_id
;
409 this->public.get_key_length
= (status_t (*) (transform_substructure_t
*,u_int16_t
*)) get_key_length
;
410 this->public.clone
= (transform_substructure_t
* (*) (transform_substructure_t
*)) clone_
;
411 this->public.destroy
= (void (*) (transform_substructure_t
*)) destroy
;
413 /* private functions */
414 this->compute_length
= compute_length
;
416 /* set default values of the fields */
417 this->next_payload
= NO_PAYLOAD
;
418 this->transform_length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
419 this->transform_id
= 0;
420 this->transform_type
= 0;
421 this->attributes
= linked_list_create();
422 this->logger
= logger_manager
->get_logger(logger_manager
, PAYLOAD
);
424 return (&(this->public));
428 * Described in header
430 transform_substructure_t
*transform_substructure_create_type(transform_type_t transform_type
, u_int16_t transform_id
, u_int16_t key_length
)
432 transform_substructure_t
*transform
= transform_substructure_create();
434 transform
->set_transform_type(transform
,transform_type
);
435 transform
->set_transform_id(transform
,transform_id
);
437 /* a keylength attribute is only created for variable length algos */
438 if (transform_type
== ENCRYPTION_ALGORITHM
&&
439 (transform_id
== ENCR_AES_CBC
||
440 transform_id
== ENCR_IDEA
||
441 transform_id
== ENCR_CAST
||
442 transform_id
== ENCR_BLOWFISH
))
444 transform_attribute_t
*attribute
= transform_attribute_create_key_length(key_length
);
445 transform
->add_transform_attribute(transform
,attribute
);