- added compution of all needed keys and also creation of needed
[strongswan.git] / Source / charon / encoding / payloads / transform_substructure.c
1 /**
2 * @file transform_substructure.h
3 *
4 * @brief Declaration of the class transform_substructure_t.
5 *
6 * An object of this type represents an IKEv2 TRANSFORM Substructure and contains Attributes.
7 *
8 */
9
10 /*
11 * Copyright (C) 2005 Jan Hutter, Martin Willi
12 * Hochschule fuer Technik Rapperswil
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 */
24
25 /* offsetof macro */
26 #include <stddef.h>
27
28 #include "transform_substructure.h"
29
30 #include <encoding/payloads/transform_attribute.h>
31 #include <encoding/payloads/encodings.h>
32 #include <types.h>
33 #include <utils/allocator.h>
34 #include <utils/linked_list.h>
35
36
37 typedef struct private_transform_substructure_t private_transform_substructure_t;
38
39 /**
40 * Private data of an transform_substructure_t' Object
41 *
42 */
43 struct private_transform_substructure_t {
44 /**
45 * public transform_substructure_t interface
46 */
47 transform_substructure_t public;
48
49 /**
50 * next payload type
51 */
52 u_int8_t next_payload;
53
54
55 /**
56 * Length of this payload
57 */
58 u_int16_t transform_length;
59
60
61 /**
62 * Type of the transform
63 */
64 u_int8_t transform_type;
65
66 /**
67 * Transform ID
68 */
69 u_int16_t transform_id;
70
71 /**
72 * Transforms Attributes are stored in a linked_list_t
73 */
74 linked_list_t *attributes;
75
76 /**
77 * @brief Computes the length of this substructure.
78 *
79 * @param this calling private_transform_substructure_t object
80 * @return
81 * SUCCESS in any case
82 */
83 status_t (*compute_length) (private_transform_substructure_t *this);
84 };
85
86
87 /**
88 * string mappings for transform_type_t
89 */
90 mapping_t transform_type_m[] = {
91 {UNDEFINED_TRANSFORM_TYPE, "UNDEFINED_TRANSFORM_TYPE"},
92 {ENCRYPTION_ALGORITHM, "ENCRYPTION_ALGORITHM"},
93 {PSEUDO_RANDOM_FUNCTION, "PSEUDO_RANDOM_FUNCTION"},
94 {INTEGRITY_ALGORITHM, "INTEGRITY_ALGORITHM"},
95 {DIFFIE_HELLMAN_GROUP, "DIFFIE_HELLMAN_GROUP"},
96 {EXTENDED_SEQUENCE_NUNBERS, "EXTENDED_SEQUENCE_NUNBERS"},
97 {MAPPING_END, NULL}
98 };
99
100
101 /**
102 * string mappings for extended_sequence_numbers_t
103 */
104 mapping_t extended_sequence_numbers_m[] = {
105 {NO_EXT_SEQ_NUMBERS, "NO_EXT_SEQ_NUMBERS"},
106 {EXT_SEQ_NUMBERS, "EXT_SEQ_NUMBERS"},
107 {MAPPING_END, NULL}
108 };
109
110 /**
111 * Encoding rules to parse or generate a Transform substructure
112 *
113 * The defined offsets are the positions in a object of type
114 * private_transform_substructure_t.
115 *
116 */
117 encoding_rule_t transform_substructure_encodings[] = {
118 /* 1 Byte next payload type, stored in the field next_payload */
119 { U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
120 /* Reserved Byte is skipped */
121 { RESERVED_BYTE, 0 },
122 /* Length of the whole transform substructure*/
123 { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length) },
124 /* transform type is a number of 8 bit */
125 { U_INT_8, offsetof(private_transform_substructure_t, transform_type) },
126 /* Reserved Byte is skipped */
127 { RESERVED_BYTE, 0 },
128 /* tranform ID is a number of 8 bit */
129 { U_INT_16, offsetof(private_transform_substructure_t, transform_id) },
130 /* Attributes are stored in a transform attribute,
131 offset points to a linked_list_t pointer */
132 { TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) }
133 };
134
135 /*
136 1 2 3
137 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
138 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
139 ! 0 (last) or 3 ! RESERVED ! Transform Length !
140 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
141 !Transform Type ! RESERVED ! Transform ID !
142 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
143 ! !
144 ~ Transform Attributes ~
145 ! !
146 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
147 */
148
149
150 /**
151 * Implements payload_t's verify function.
152 * See #payload_s.verify for description.
153 */
154 static status_t verify(private_transform_substructure_t *this)
155 {
156 if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != TRANSFORM_SUBSTRUCTURE))
157 {
158 /* must be 0 or 3 */
159 return FAILED;
160 }
161
162 switch (this->transform_type)
163 {
164 case ENCRYPTION_ALGORITHM:
165 {
166 if ((this->transform_id < ENCR_DES_IV64) || (this->transform_id > ENCR_AES_CTR))
167 {
168 return FAILED;
169 }
170 break;
171 }
172 case PSEUDO_RANDOM_FUNCTION:
173 {
174 if ((this->transform_id < PRF_HMAC_MD5) || (this->transform_id > PRF_AES128_CBC))
175 {
176 return FAILED;
177 }
178 break;
179 }
180 case INTEGRITY_ALGORITHM:
181 {
182 if ((this->transform_id < AUTH_HMAC_MD5_96) || (this->transform_id > AUTH_AES_XCBC_96))
183 {
184 return FAILED;
185 }
186 break;
187 }
188 case DIFFIE_HELLMAN_GROUP:
189 {
190 switch (this->transform_id)
191 {
192 case MODP_768_BIT:
193 case MODP_1024_BIT:
194 case MODP_1536_BIT:
195 case MODP_2048_BIT:
196 case MODP_3072_BIT:
197 case MODP_4096_BIT:
198 case MODP_6144_BIT:
199 case MODP_8192_BIT:
200 {
201 break;
202 }
203 default:
204 {
205 return FAILED;
206 }
207 }
208
209
210 break;
211 }
212 case EXTENDED_SEQUENCE_NUNBERS:
213 {
214 if ((this->transform_id != NO_EXT_SEQ_NUMBERS) && (this->transform_id != EXT_SEQ_NUMBERS))
215 {
216 return FAILED;
217 }
218 break;
219 }
220 default:
221 {
222 /* not a supported transform type! */
223 return FAILED;
224 }
225 }
226
227 /* proposal number is checked in SA payload */
228 return SUCCESS;
229 }
230
231 /**
232 * Implements payload_t's get_encoding_rules function.
233 * See #payload_s.get_encoding_rules for description.
234 */
235 static status_t get_encoding_rules(private_transform_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
236 {
237 *rules = transform_substructure_encodings;
238 *rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t);
239
240 return SUCCESS;
241 }
242
243 /**
244 * Implements payload_t's get_type function.
245 * See #payload_s.get_type for description.
246 */
247 static payload_type_t get_type(private_transform_substructure_t *this)
248 {
249 return TRANSFORM_SUBSTRUCTURE;
250 }
251
252 /**
253 * Implements payload_t's get_next_type function.
254 * See #payload_s.get_next_type for description.
255 */
256 static payload_type_t get_next_type(private_transform_substructure_t *this)
257 {
258 return (this->next_payload);
259 }
260
261 /**
262 * Implements payload_t's get_length function.
263 * See #payload_s.get_length for description.
264 */
265 static size_t get_length(private_transform_substructure_t *this)
266 {
267 this->compute_length(this);
268
269 return this->transform_length;
270 }
271
272 /**
273 * Implements transform_substructure_t's create_transform_attribute_iterator function.
274 * See #transform_substructure_s.create_transform_attribute_iterator for description.
275 */
276 static status_t create_transform_attribute_iterator (private_transform_substructure_t *this,iterator_t **iterator,bool forward)
277 {
278 return (this->attributes->create_iterator(this->attributes,iterator,forward));
279 }
280
281 /**
282 * Implements transform_substructure_t's add_transform_attribute function.
283 * See #transform_substructure_s.add_transform_attribute for description.
284 */
285 static status_t add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute)
286 {
287 status_t status;
288 status = this->attributes->insert_last(this->attributes,(void *) attribute);
289 this->compute_length(this);
290 return status;
291 }
292
293 /**
294 * Implements transform_substructure_t's set_is_last_transform function.
295 * See #transform_substructure_s.set_is_last_transform for description.
296 */
297 static status_t set_is_last_transform (private_transform_substructure_t *this, bool is_last)
298 {
299 this->next_payload = (is_last) ? 0: TRANSFORM_TYPE_VALUE;
300 return SUCCESS;
301 }
302
303 /**
304 * Implements transform_substructure_t's get_is_last_transform function.
305 * See #transform_substructure_s.get_is_last_transform for description.
306 */
307 static bool get_is_last_transform (private_transform_substructure_t *this)
308 {
309 return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE);
310 }
311
312 /**
313 * Implements payload_t's set_next_type function.
314 * See #payload_s.set_next_type for description.
315 */
316 static status_t set_next_type(private_transform_substructure_t *this,payload_type_t type)
317 {
318 return SUCCESS;
319 }
320
321 /**
322 * Implements transform_substructure_t's set_transform_type function.
323 * See #transform_substructure_s.set_transform_type for description.
324 */
325 static status_t set_transform_type (private_transform_substructure_t *this,u_int8_t type)
326 {
327 this->transform_type = type;
328 return SUCCESS;
329 }
330
331 /**
332 * Implements transform_substructure_t's get_transform_type function.
333 * See #transform_substructure_s.get_transform_type for description.
334 */
335 static u_int8_t get_transform_type (private_transform_substructure_t *this)
336 {
337 return this->transform_type;
338 }
339
340 /**
341 * Implements transform_substructure_t's set_transform_id function.
342 * See #transform_substructure_s.set_transform_id for description.
343 */
344 static status_t set_transform_id (private_transform_substructure_t *this,u_int16_t id)
345 {
346 this->transform_id = id;
347 return SUCCESS;
348 }
349
350 /**
351 * Implements transform_substructure_t's get_transform_id function.
352 * See #transform_substructure_s.get_transform_id for description.
353 */
354 static u_int16_t get_transform_id (private_transform_substructure_t *this)
355 {
356 return this->transform_id;
357 }
358
359 /**
360 * Implements private_transform_substructure_t's compute_length function.
361 * See #private_transform_substructure_s.compute_length for description.
362 */
363 static status_t compute_length (private_transform_substructure_t *this)
364 {
365 iterator_t *iterator;
366 status_t status;
367 size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
368 status = this->attributes->create_iterator(this->attributes,&iterator,TRUE);
369 if (status != SUCCESS)
370 {
371 return length;
372 }
373 while (iterator->has_next(iterator))
374 {
375 payload_t * current_attribute;
376 iterator->current(iterator,(void **) &current_attribute);
377 length += current_attribute->get_length(current_attribute);
378 }
379 iterator->destroy(iterator);
380
381 this->transform_length = length;
382
383 return SUCCESS;
384 }
385
386 /**
387 * Implements transform_substructure_t's clone function.
388 * See transform_substructure_s.clone for description.
389 */
390 static status_t clone(private_transform_substructure_t *this,transform_substructure_t **clone)
391 {
392 private_transform_substructure_t *new_clone;
393 iterator_t *attributes;
394 status_t status;
395
396 new_clone = (private_transform_substructure_t *) transform_substructure_create();
397
398 new_clone->next_payload = this->next_payload;
399 new_clone->transform_type = this->transform_type;
400 new_clone->transform_id = this->transform_id;
401
402 status = this->attributes->create_iterator(this->attributes,&attributes,FALSE);
403 if (status != SUCCESS)
404 {
405 new_clone->public.destroy(&(new_clone->public));
406 return status;
407 }
408
409 while (attributes->has_next(attributes))
410 {
411 transform_attribute_t *current_attribute;
412 transform_attribute_t *current_attribute_clone;
413 status = attributes->current(attributes,(void **) &current_attribute);
414 if (status != SUCCESS)
415 {
416 attributes->destroy(attributes);
417 new_clone->public.destroy(&(new_clone->public));
418 return status;
419 }
420 status = current_attribute->clone(current_attribute,&current_attribute_clone);
421 if (status != SUCCESS)
422 {
423 attributes->destroy(attributes);
424 new_clone->public.destroy(&(new_clone->public));
425 return status;
426 }
427
428 status = new_clone->public.add_transform_attribute(&(new_clone->public),current_attribute_clone);
429 if (status != SUCCESS)
430 {
431 attributes->destroy(attributes);
432 current_attribute_clone->destroy(current_attribute_clone);
433 new_clone->public.destroy(&(new_clone->public));
434 return status;
435 }
436 }
437
438 attributes->destroy(attributes);
439
440 *clone = &(new_clone->public);
441 return SUCCESS;
442 }
443
444
445 /**
446 * Implementation of transform_substructure_t.get_key_length.
447 */
448 static status_t get_key_length(private_transform_substructure_t *this, u_int16_t *key_length)
449 {
450 iterator_t *attributes;
451 status_t status;
452
453 status = this->attributes->create_iterator(this->attributes,&attributes,TRUE);
454 if (status != SUCCESS)
455 {
456 return status;
457 }
458
459 while (attributes->has_next(attributes))
460 {
461 transform_attribute_t *current_attribute;
462 status = attributes->current(attributes,(void **) &current_attribute);
463 if (status != SUCCESS)
464 {
465 attributes->destroy(attributes);
466 return status;
467 }
468 if (current_attribute->get_attribute_type(current_attribute) == KEY_LENGTH)
469 {
470 *key_length = current_attribute->get_value(current_attribute);
471 attributes->destroy(attributes);
472 return SUCCESS;
473 }
474
475 }
476 attributes->destroy(attributes);
477
478 return FAILED;
479 }
480
481
482 /**
483 * Implements payload_t's and transform_substructure_t's destroy function.
484 * See #payload_s.destroy or transform_substructure_s.destroy for description.
485 */
486 static status_t destroy(private_transform_substructure_t *this)
487 {
488 /* all proposals are getting destroyed */
489 while (this->attributes->get_count(this->attributes) > 0)
490 {
491 transform_attribute_t *current_attribute;
492 if (this->attributes->remove_last(this->attributes,(void **)&current_attribute) != SUCCESS)
493 {
494 break;
495 }
496 current_attribute->destroy(current_attribute);
497 }
498 this->attributes->destroy(this->attributes);
499
500 allocator_free(this);
501
502 return SUCCESS;
503 }
504
505 /*
506 * Described in header
507 */
508 transform_substructure_t *transform_substructure_create()
509 {
510 private_transform_substructure_t *this = allocator_alloc_thing(private_transform_substructure_t);
511 if (this == NULL)
512 {
513 return NULL;
514 }
515
516 /* payload interface */
517 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
518 this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
519 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
520 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
521 this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
522 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
523 this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
524
525 /* public functions */
526 this->public.create_transform_attribute_iterator = (status_t (*) (transform_substructure_t *,iterator_t **,bool)) create_transform_attribute_iterator;
527 this->public.add_transform_attribute = (status_t (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute;
528 this->public.set_is_last_transform = (status_t (*) (transform_substructure_t *,bool)) set_is_last_transform;
529 this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform;
530 this->public.set_transform_type = (status_t (*) (transform_substructure_t *,u_int8_t)) set_transform_type;
531 this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type;
532 this->public.set_transform_id = (status_t (*) (transform_substructure_t *,u_int16_t)) set_transform_id;
533 this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id;
534 this->public.get_key_length = (status_t (*) (transform_substructure_t *,u_int16_t *)) get_key_length;
535 this->public.clone = (status_t (*) (transform_substructure_t *,transform_substructure_t **)) clone;
536 this->public.destroy = (status_t (*) (transform_substructure_t *)) destroy;
537
538 /* private functions */
539 this->compute_length = compute_length;
540
541 /* set default values of the fields */
542 this->next_payload = NO_PAYLOAD;
543 this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
544 this->transform_id = 0;
545 this->transform_type = 0;
546
547 this->attributes = linked_list_create();
548
549 if (this->attributes == NULL)
550 {
551 allocator_free(this);
552 return NULL;
553 }
554 return (&(this->public));
555 }