2 * Copyright (C) 2005-2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 #include "transform_substructure.h"
22 #include <encoding/payloads/transform_attribute.h>
23 #include <encoding/payloads/encodings.h>
25 #include <utils/linked_list.h>
28 typedef struct private_transform_substructure_t private_transform_substructure_t
;
31 * Private data of an transform_substructure_t object.
33 struct private_transform_substructure_t
{
36 * Public transform_substructure_t interface.
38 transform_substructure_t
public;
43 u_int8_t next_payload
;
50 * Length of this payload.
52 u_int16_t transform_length
;
55 * Type of the transform.
57 u_int8_t transform_type
;
62 u_int16_t transform_id
;
65 * Transforms Attributes are stored in a linked_list_t.
67 linked_list_t
*attributes
;
71 * Encoding rules to parse or generate a Transform substructure.
73 * The defined offsets are the positions in a object of type
74 * private_transform_substructure_t.
76 encoding_rule_t transform_substructure_encodings
[] = {
77 /* 1 Byte next payload type, stored in the field next_payload */
78 { U_INT_8
, offsetof(private_transform_substructure_t
, next_payload
) },
80 { RESERVED_BYTE
, offsetof(private_transform_substructure_t
, reserved
[0]) },
81 /* Length of the whole transform substructure*/
82 { PAYLOAD_LENGTH
, offsetof(private_transform_substructure_t
, transform_length
)},
83 /* transform type is a number of 8 bit */
84 { U_INT_8
, offsetof(private_transform_substructure_t
, transform_type
) },
86 { RESERVED_BYTE
, offsetof(private_transform_substructure_t
, reserved
[1]) },
87 /* transform ID is a number of 8 bit */
88 { U_INT_16
, offsetof(private_transform_substructure_t
, transform_id
) },
89 /* Attributes are stored in a transform attribute,
90 offset points to a linked_list_t pointer */
91 { TRANSFORM_ATTRIBUTES
, offsetof(private_transform_substructure_t
, attributes
) }
96 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
97 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
98 ! 0 (last) or 3 ! RESERVED ! Transform Length !
99 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100 !Transform Type ! RESERVED ! Transform ID !
101 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103 ~ Transform Attributes ~
105 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
108 METHOD(payload_t
, verify
, status_t
,
109 private_transform_substructure_t
*this)
111 status_t status
= SUCCESS
;
112 enumerator_t
*enumerator
;
113 payload_t
*attribute
;
115 if (this->next_payload
!= NO_PAYLOAD
&& this->next_payload
!= 3)
117 DBG1(DBG_ENC
, "inconsistent next payload");
121 switch (this->transform_type
)
123 case ENCRYPTION_ALGORITHM
:
124 case PSEUDO_RANDOM_FUNCTION
:
125 case INTEGRITY_ALGORITHM
:
126 case DIFFIE_HELLMAN_GROUP
:
127 case EXTENDED_SEQUENCE_NUMBERS
:
128 /* we don't check transform ID, we want to reply
129 * cleanly with NO_PROPOSAL_CHOSEN or so if we don't support it */
133 DBG1(DBG_ENC
, "invalid transform type: %d", this->transform_type
);
138 enumerator
= this->attributes
->create_enumerator(this->attributes
);
139 while (enumerator
->enumerate(enumerator
, &attribute
))
141 status
= attribute
->verify(attribute
);
142 if (status
!= SUCCESS
)
144 DBG1(DBG_ENC
, "TRANSFORM_ATTRIBUTE verification failed");
148 enumerator
->destroy(enumerator
);
150 /* proposal number is checked in SA payload */
154 METHOD(payload_t
, get_encoding_rules
, void,
155 private_transform_substructure_t
*this, encoding_rule_t
**rules
,
158 *rules
= transform_substructure_encodings
;
159 *rule_count
= countof(transform_substructure_encodings
);
162 METHOD(payload_t
, get_type
, payload_type_t
,
163 private_transform_substructure_t
*this)
165 return TRANSFORM_SUBSTRUCTURE
;
168 METHOD(payload_t
, get_next_type
, payload_type_t
,
169 private_transform_substructure_t
*this)
171 return this->next_payload
;
175 * recompute the length of the payload.
177 static void compute_length (private_transform_substructure_t
*this)
179 enumerator_t
*enumerator
;
180 payload_t
*attribute
;
182 this->transform_length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
;
183 enumerator
= this->attributes
->create_enumerator(this->attributes
);
184 while (enumerator
->enumerate(enumerator
, &attribute
))
186 this->transform_length
+= attribute
->get_length(attribute
);
188 enumerator
->destroy(enumerator
);
191 METHOD(payload_t
, get_length
, size_t,
192 private_transform_substructure_t
*this)
194 return this->transform_length
;
197 METHOD(transform_substructure_t
, set_is_last_transform
, void,
198 private_transform_substructure_t
*this, bool is_last
)
200 this->next_payload
= is_last ?
0: TRANSFORM_TYPE_VALUE
;
203 METHOD(payload_t
, set_next_type
, void,
204 private_transform_substructure_t
*this,payload_type_t type
)
208 METHOD(transform_substructure_t
, get_transform_type
, u_int8_t
,
209 private_transform_substructure_t
*this)
211 return this->transform_type
;
214 METHOD(transform_substructure_t
, get_transform_id
, u_int16_t
,
215 private_transform_substructure_t
*this)
217 return this->transform_id
;
220 METHOD(transform_substructure_t
, get_key_length
, status_t
,
221 private_transform_substructure_t
*this, u_int16_t
*key_length
)
223 enumerator_t
*enumerator
;
224 transform_attribute_t
*attribute
;
226 enumerator
= this->attributes
->create_enumerator(this->attributes
);
227 while (enumerator
->enumerate(enumerator
, &attribute
))
229 if (attribute
->get_attribute_type(attribute
) == KEY_LENGTH
)
231 *key_length
= attribute
->get_value(attribute
);
232 enumerator
->destroy(enumerator
);
236 enumerator
->destroy(enumerator
);
240 METHOD2(payload_t
, transform_substructure_t
, destroy
, void,
241 private_transform_substructure_t
*this)
243 this->attributes
->destroy_offset(this->attributes
,
244 offsetof(transform_attribute_t
, destroy
));
249 * Described in header.
251 transform_substructure_t
*transform_substructure_create()
253 private_transform_substructure_t
*this;
257 .payload_interface
= {
259 .get_encoding_rules
= _get_encoding_rules
,
260 .get_length
= _get_length
,
261 .get_next_type
= _get_next_type
,
262 .set_next_type
= _set_next_type
,
263 .get_type
= _get_type
,
266 .set_is_last_transform
= _set_is_last_transform
,
267 .get_transform_type
= _get_transform_type
,
268 .get_transform_id
= _get_transform_id
,
269 .get_key_length
= _get_key_length
,
272 .next_payload
= NO_PAYLOAD
,
273 .transform_length
= TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH
,
274 .attributes
= linked_list_create(),
276 return &this->public;
280 * Described in header
282 transform_substructure_t
*transform_substructure_create_type(
283 transform_type_t type
, u_int16_t id
, u_int16_t key_length
)
285 private_transform_substructure_t
*this;
287 this = (private_transform_substructure_t
*)transform_substructure_create();
289 this->transform_type
= type
;
290 this->transform_id
= id
;
293 this->attributes
->insert_last(this->attributes
,
294 (void*)transform_attribute_create_key_length(key_length
));
295 compute_length(this);
297 return &this->public;