]>
Commit | Line | Data |
---|---|---|
b860cffd JH |
1 | /** |
2 | * @file transform_substructure.h | |
3 | * | |
3fe05870 | 4 | * @brief Implementation of transform_substructure_t. |
b860cffd JH |
5 | * |
6 | */ | |
7 | ||
8 | /* | |
9 | * Copyright (C) 2005 Jan Hutter, Martin Willi | |
10 | * Hochschule fuer Technik Rapperswil | |
11 | * | |
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>. | |
16 | * | |
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 | |
20 | * for more details. | |
21 | */ | |
5113680f | 22 | |
b860cffd JH |
23 | #include <stddef.h> |
24 | ||
25 | #include "transform_substructure.h" | |
26 | ||
4a962238 MW |
27 | #include <encoding/payloads/transform_attribute.h> |
28 | #include <encoding/payloads/encodings.h> | |
696be022 | 29 | #include <types.h> |
696be022 | 30 | #include <utils/linked_list.h> |
b860cffd | 31 | |
95c61cb9 JH |
32 | |
33 | typedef struct private_transform_substructure_t private_transform_substructure_t; | |
34 | ||
b860cffd | 35 | /** |
3fe05870 | 36 | * Private data of an transform_substructure_t object. |
b860cffd JH |
37 | * |
38 | */ | |
95c61cb9 | 39 | struct private_transform_substructure_t { |
b860cffd | 40 | /** |
3fe05870 | 41 | * Public transform_substructure_t interface. |
b860cffd JH |
42 | */ |
43 | transform_substructure_t public; | |
44 | ||
45 | /** | |
3fe05870 | 46 | * Next payload type. |
b860cffd JH |
47 | */ |
48 | u_int8_t next_payload; | |
49 | ||
50 | ||
51 | /** | |
3fe05870 | 52 | * Length of this payload. |
b860cffd JH |
53 | */ |
54 | u_int16_t transform_length; | |
55 | ||
56 | ||
57 | /** | |
3fe05870 | 58 | * Type of the transform. |
b860cffd JH |
59 | */ |
60 | u_int8_t transform_type; | |
61 | ||
62 | /** | |
3fe05870 | 63 | * Transform ID. |
b860cffd | 64 | */ |
f3c01a28 | 65 | u_int16_t transform_id; |
b860cffd JH |
66 | |
67 | /** | |
3fe05870 | 68 | * Transforms Attributes are stored in a linked_list_t. |
b860cffd | 69 | */ |
f3c01a28 | 70 | linked_list_t *attributes; |
b3fd2b72 JH |
71 | |
72 | /** | |
73 | * @brief Computes the length of this substructure. | |
74 | * | |
75 | * @param this calling private_transform_substructure_t object | |
b3fd2b72 | 76 | */ |
3fe05870 | 77 | void (*compute_length) (private_transform_substructure_t *this); |
b860cffd JH |
78 | }; |
79 | ||
80 | ||
81 | /** | |
3fe05870 | 82 | * Encoding rules to parse or generate a Transform substructure. |
b860cffd JH |
83 | * |
84 | * The defined offsets are the positions in a object of type | |
85 | * private_transform_substructure_t. | |
86 | * | |
87 | */ | |
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 */ | |
92 | { RESERVED_BYTE, 0 }, | |
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 */ | |
98 | { RESERVED_BYTE, 0 }, | |
99 | /* tranform ID is a number of 8 bit */ | |
f3c01a28 | 100 | { U_INT_16, offsetof(private_transform_substructure_t, transform_id) }, |
b860cffd JH |
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) } | |
104 | }; | |
105 | ||
e31eb71e JH |
106 | /* |
107 | 1 2 3 | |
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 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
114 | ! ! | |
115 | ~ Transform Attributes ~ | |
116 | ! ! | |
117 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
118 | */ | |
119 | ||
120 | ||
121 | /** | |
3fe05870 | 122 | * Implementation of payload_t.verify. |
e31eb71e JH |
123 | */ |
124 | static status_t verify(private_transform_substructure_t *this) | |
125 | { | |
346af6f3 JH |
126 | status_t status = SUCCESS; |
127 | iterator_t *iterator; | |
128 | ||
129 | if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != 3)) | |
e31eb71e JH |
130 | { |
131 | /* must be 0 or 3 */ | |
132 | return FAILED; | |
133 | } | |
134 | ||
135 | switch (this->transform_type) | |
136 | { | |
137 | case ENCRYPTION_ALGORITHM: | |
138 | { | |
139 | if ((this->transform_id < ENCR_DES_IV64) || (this->transform_id > ENCR_AES_CTR)) | |
140 | { | |
141 | return FAILED; | |
142 | } | |
143 | break; | |
144 | } | |
c06dbbab | 145 | case PSEUDO_RANDOM_FUNCTION: |
e31eb71e JH |
146 | { |
147 | if ((this->transform_id < PRF_HMAC_MD5) || (this->transform_id > PRF_AES128_CBC)) | |
148 | { | |
149 | return FAILED; | |
150 | } | |
151 | break; | |
152 | } | |
b9d9f188 | 153 | case INTEGRITY_ALGORITHM: |
e31eb71e JH |
154 | { |
155 | if ((this->transform_id < AUTH_HMAC_MD5_96) || (this->transform_id > AUTH_AES_XCBC_96)) | |
156 | { | |
157 | return FAILED; | |
158 | } | |
159 | break; | |
160 | } | |
161 | case DIFFIE_HELLMAN_GROUP: | |
162 | { | |
163 | switch (this->transform_id) | |
164 | { | |
165 | case MODP_768_BIT: | |
166 | case MODP_1024_BIT: | |
167 | case MODP_1536_BIT: | |
168 | case MODP_2048_BIT: | |
169 | case MODP_3072_BIT: | |
170 | case MODP_4096_BIT: | |
171 | case MODP_6144_BIT: | |
172 | case MODP_8192_BIT: | |
173 | { | |
174 | break; | |
175 | } | |
176 | default: | |
177 | { | |
178 | return FAILED; | |
179 | } | |
180 | } | |
181 | ||
182 | ||
183 | break; | |
184 | } | |
343acebe | 185 | case EXTENDED_SEQUENCE_NUMBERS: |
e31eb71e JH |
186 | { |
187 | if ((this->transform_id != NO_EXT_SEQ_NUMBERS) && (this->transform_id != EXT_SEQ_NUMBERS)) | |
188 | { | |
189 | return FAILED; | |
190 | } | |
191 | break; | |
192 | } | |
193 | default: | |
194 | { | |
195 | /* not a supported transform type! */ | |
196 | return FAILED; | |
197 | } | |
198 | } | |
346af6f3 JH |
199 | iterator = this->attributes->create_iterator(this->attributes,TRUE); |
200 | ||
201 | while(iterator->has_next(iterator)) | |
202 | { | |
203 | payload_t *current_attributes; | |
204 | iterator->current(iterator,(void **)¤t_attributes); | |
205 | ||
206 | status = current_attributes->verify(current_attributes); | |
207 | if (status != SUCCESS) | |
208 | { | |
209 | break; | |
210 | } | |
211 | } | |
212 | ||
213 | iterator->destroy(iterator); | |
214 | ||
e31eb71e JH |
215 | |
216 | /* proposal number is checked in SA payload */ | |
346af6f3 | 217 | return status; |
e31eb71e JH |
218 | } |
219 | ||
b860cffd | 220 | /** |
3fe05870 | 221 | * Implementation of payload_t.get_encoding_rules. |
b860cffd | 222 | */ |
3fe05870 | 223 | static void get_encoding_rules(private_transform_substructure_t *this, encoding_rule_t **rules, size_t *rule_count) |
b860cffd JH |
224 | { |
225 | *rules = transform_substructure_encodings; | |
226 | *rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t); | |
b860cffd JH |
227 | } |
228 | ||
229 | /** | |
3fe05870 | 230 | * Implementation of payload_t.get_type. |
b860cffd JH |
231 | */ |
232 | static payload_type_t get_type(private_transform_substructure_t *this) | |
233 | { | |
234 | return TRANSFORM_SUBSTRUCTURE; | |
235 | } | |
236 | ||
237 | /** | |
3fe05870 | 238 | * Implementation of payload_t.get_next_type. |
b860cffd JH |
239 | */ |
240 | static payload_type_t get_next_type(private_transform_substructure_t *this) | |
241 | { | |
242 | return (this->next_payload); | |
243 | } | |
244 | ||
245 | /** | |
3fe05870 | 246 | * Implementation of payload_t.get_length. |
b860cffd JH |
247 | */ |
248 | static size_t get_length(private_transform_substructure_t *this) | |
249 | { | |
b3fd2b72 | 250 | this->compute_length(this); |
f3c01a28 | 251 | |
b860cffd JH |
252 | return this->transform_length; |
253 | } | |
254 | ||
255 | /** | |
3fe05870 | 256 | * Implementation of transform_substructure_t.create_transform_attribute_iterator. |
b860cffd | 257 | */ |
a0753941 | 258 | static iterator_t *create_transform_attribute_iterator (private_transform_substructure_t *this,bool forward) |
b860cffd | 259 | { |
a0753941 | 260 | return this->attributes->create_iterator(this->attributes,forward); |
b860cffd JH |
261 | } |
262 | ||
263 | /** | |
3fe05870 | 264 | * Implementation of transform_substructure_t.add_transform_attribute. |
b860cffd | 265 | */ |
3fe05870 | 266 | static void add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute) |
b860cffd | 267 | { |
3fe05870 | 268 | this->attributes->insert_last(this->attributes,(void *) attribute); |
b3fd2b72 | 269 | this->compute_length(this); |
f3c01a28 JH |
270 | } |
271 | ||
272 | /** | |
3fe05870 | 273 | * Implementation of transform_substructure_t.set_is_last_transform. |
f3c01a28 | 274 | */ |
3fe05870 | 275 | static void set_is_last_transform (private_transform_substructure_t *this, bool is_last) |
f3c01a28 | 276 | { |
a14dffd1 | 277 | this->next_payload = (is_last) ? 0: TRANSFORM_TYPE_VALUE; |
f3c01a28 JH |
278 | } |
279 | ||
280 | /** | |
3fe05870 | 281 | * Implementation of transform_substructure_t.get_is_last_transform. |
f3c01a28 JH |
282 | */ |
283 | static bool get_is_last_transform (private_transform_substructure_t *this) | |
284 | { | |
285 | return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE); | |
286 | } | |
287 | ||
32cbc7bc | 288 | /** |
3fe05870 | 289 | * Implementation of payload_t.set_next_type. |
32cbc7bc | 290 | */ |
3fe05870 | 291 | static void set_next_type(private_transform_substructure_t *this,payload_type_t type) |
32cbc7bc | 292 | { |
32cbc7bc JH |
293 | } |
294 | ||
f3c01a28 | 295 | /** |
3fe05870 | 296 | * Implementation of transform_substructure_t.set_transform_type. |
f3c01a28 | 297 | */ |
3fe05870 | 298 | static void set_transform_type (private_transform_substructure_t *this,u_int8_t type) |
f3c01a28 JH |
299 | { |
300 | this->transform_type = type; | |
f3c01a28 JH |
301 | } |
302 | ||
303 | /** | |
3fe05870 | 304 | * Implementation of transform_substructure_t.get_transform_type. |
f3c01a28 JH |
305 | */ |
306 | static u_int8_t get_transform_type (private_transform_substructure_t *this) | |
307 | { | |
308 | return this->transform_type; | |
b860cffd JH |
309 | } |
310 | ||
f3c01a28 | 311 | /** |
3fe05870 | 312 | * Implementation of transform_substructure_t.set_transform_id. |
f3c01a28 | 313 | */ |
3fe05870 | 314 | static void set_transform_id (private_transform_substructure_t *this,u_int16_t id) |
f3c01a28 JH |
315 | { |
316 | this->transform_id = id; | |
f3c01a28 JH |
317 | } |
318 | ||
319 | /** | |
3fe05870 | 320 | * Implementation of transform_substructure_t.get_transform_id. |
f3c01a28 JH |
321 | */ |
322 | static u_int16_t get_transform_id (private_transform_substructure_t *this) | |
323 | { | |
324 | return this->transform_id; | |
325 | } | |
b860cffd | 326 | |
b3fd2b72 | 327 | /** |
3fe05870 | 328 | * Implementation of private_transform_substructure_t.compute_length. |
b3fd2b72 | 329 | */ |
3fe05870 | 330 | static void compute_length (private_transform_substructure_t *this) |
b3fd2b72 | 331 | { |
bdb141cb | 332 | iterator_t *iterator; |
b3fd2b72 | 333 | size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; |
a0753941 | 334 | iterator = this->attributes->create_iterator(this->attributes,TRUE); |
b3fd2b72 JH |
335 | while (iterator->has_next(iterator)) |
336 | { | |
337 | payload_t * current_attribute; | |
338 | iterator->current(iterator,(void **) ¤t_attribute); | |
339 | length += current_attribute->get_length(current_attribute); | |
340 | } | |
a14dffd1 | 341 | iterator->destroy(iterator); |
32cbc7bc JH |
342 | |
343 | this->transform_length = length; | |
b3fd2b72 JH |
344 | } |
345 | ||
b9459040 | 346 | /** |
3fe05870 | 347 | * Implementation of transform_substructure_t.clone. |
b9459040 | 348 | */ |
a0753941 | 349 | static transform_substructure_t *clone(private_transform_substructure_t *this) |
b9459040 JH |
350 | { |
351 | private_transform_substructure_t *new_clone; | |
bdb141cb | 352 | iterator_t *attributes; |
b9459040 JH |
353 | |
354 | new_clone = (private_transform_substructure_t *) transform_substructure_create(); | |
355 | ||
356 | new_clone->next_payload = this->next_payload; | |
357 | new_clone->transform_type = this->transform_type; | |
358 | new_clone->transform_id = this->transform_id; | |
359 | ||
a0753941 | 360 | attributes = this->attributes->create_iterator(this->attributes,FALSE); |
b9459040 JH |
361 | |
362 | while (attributes->has_next(attributes)) | |
363 | { | |
364 | transform_attribute_t *current_attribute; | |
365 | transform_attribute_t *current_attribute_clone; | |
3fe05870 JH |
366 | attributes->current(attributes,(void **) ¤t_attribute); |
367 | ||
a0753941 | 368 | current_attribute_clone = current_attribute->clone(current_attribute); |
b9459040 | 369 | |
3fe05870 | 370 | new_clone->public.add_transform_attribute(&(new_clone->public),current_attribute_clone); |
b9459040 JH |
371 | } |
372 | ||
373 | attributes->destroy(attributes); | |
374 | ||
a0753941 | 375 | return &(new_clone->public); |
b9459040 JH |
376 | } |
377 | ||
378 | ||
b9d9f188 JH |
379 | /** |
380 | * Implementation of transform_substructure_t.get_key_length. | |
381 | */ | |
382 | static status_t get_key_length(private_transform_substructure_t *this, u_int16_t *key_length) | |
383 | { | |
384 | iterator_t *attributes; | |
b9d9f188 | 385 | |
a0753941 | 386 | attributes = this->attributes->create_iterator(this->attributes,TRUE); |
3fe05870 | 387 | |
b9d9f188 JH |
388 | while (attributes->has_next(attributes)) |
389 | { | |
390 | transform_attribute_t *current_attribute; | |
3fe05870 JH |
391 | attributes->current(attributes,(void **) ¤t_attribute); |
392 | ||
b9d9f188 JH |
393 | if (current_attribute->get_attribute_type(current_attribute) == KEY_LENGTH) |
394 | { | |
395 | *key_length = current_attribute->get_value(current_attribute); | |
396 | attributes->destroy(attributes); | |
397 | return SUCCESS; | |
398 | } | |
399 | ||
400 | } | |
401 | attributes->destroy(attributes); | |
402 | ||
403 | return FAILED; | |
404 | } | |
405 | ||
406 | ||
b9459040 | 407 | /** |
3fe05870 | 408 | * Implementation of transform_substructure_t.destroy and payload_t.destroy. |
b9459040 | 409 | */ |
3fe05870 | 410 | static void destroy(private_transform_substructure_t *this) |
b9459040 JH |
411 | { |
412 | /* all proposals are getting destroyed */ | |
413 | while (this->attributes->get_count(this->attributes) > 0) | |
414 | { | |
415 | transform_attribute_t *current_attribute; | |
3fe05870 | 416 | this->attributes->remove_last(this->attributes,(void **)¤t_attribute); |
b9459040 JH |
417 | current_attribute->destroy(current_attribute); |
418 | } | |
419 | this->attributes->destroy(this->attributes); | |
420 | ||
5113680f | 421 | free(this); |
b9459040 JH |
422 | } |
423 | ||
b860cffd | 424 | /* |
b737e9d9 | 425 | * Described in header. |
b860cffd JH |
426 | */ |
427 | transform_substructure_t *transform_substructure_create() | |
428 | { | |
5113680f | 429 | private_transform_substructure_t *this = malloc_thing(private_transform_substructure_t); |
3fe05870 | 430 | |
e31eb71e JH |
431 | /* payload interface */ |
432 | this->public.payload_interface.verify = (status_t (*) (payload_t *))verify; | |
3fe05870 | 433 | this->public.payload_interface.get_encoding_rules = (void (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules; |
b860cffd JH |
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; | |
3fe05870 | 436 | this->public.payload_interface.set_next_type = (void (*) (payload_t *,payload_type_t)) set_next_type; |
b860cffd | 437 | this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type; |
3fe05870 | 438 | this->public.payload_interface.destroy = (void (*) (payload_t *))destroy; |
e31eb71e JH |
439 | |
440 | /* public functions */ | |
a0753941 | 441 | this->public.create_transform_attribute_iterator = (iterator_t * (*) (transform_substructure_t *,bool)) create_transform_attribute_iterator; |
3fe05870 JH |
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; | |
f3c01a28 | 444 | this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform; |
3fe05870 | 445 | this->public.set_transform_type = (void (*) (transform_substructure_t *,u_int8_t)) set_transform_type; |
f3c01a28 | 446 | this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type; |
3fe05870 | 447 | this->public.set_transform_id = (void (*) (transform_substructure_t *,u_int16_t)) set_transform_id; |
f3c01a28 | 448 | this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id; |
b9d9f188 | 449 | this->public.get_key_length = (status_t (*) (transform_substructure_t *,u_int16_t *)) get_key_length; |
a0753941 | 450 | this->public.clone = (transform_substructure_t* (*) (transform_substructure_t *)) clone; |
3fe05870 | 451 | this->public.destroy = (void (*) (transform_substructure_t *)) destroy; |
b860cffd | 452 | |
b3fd2b72 JH |
453 | /* private functions */ |
454 | this->compute_length = compute_length; | |
455 | ||
b860cffd JH |
456 | /* set default values of the fields */ |
457 | this->next_payload = NO_PAYLOAD; | |
f3c01a28 | 458 | this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH; |
b860cffd JH |
459 | this->transform_id = 0; |
460 | this->transform_type = 0; | |
b860cffd JH |
461 | this->attributes = linked_list_create(); |
462 | ||
b860cffd JH |
463 | return (&(this->public)); |
464 | } | |
b737e9d9 JH |
465 | |
466 | /* | |
467 | * Described in header | |
468 | */ | |
469 | transform_substructure_t *transform_substructure_create_type(transform_type_t transform_type, u_int16_t transform_id, u_int16_t key_length) | |
470 | { | |
471 | transform_substructure_t *transform = transform_substructure_create(); | |
472 | ||
473 | transform->set_transform_type(transform,transform_type); | |
474 | transform->set_transform_id(transform,transform_id); | |
475 | ||
30b5b412 MW |
476 | /* a keylength attribute is only created for AES encryption */ |
477 | if (transform_type == ENCRYPTION_ALGORITHM && | |
478 | transform_id == ENCR_AES_CBC) | |
b737e9d9 | 479 | { |
30b5b412 MW |
480 | transform_attribute_t *attribute = transform_attribute_create_key_length(key_length); |
481 | transform->add_transform_attribute(transform,attribute); | |
482 | } | |
483 | ||
b737e9d9 JH |
484 | return transform; |
485 | } |