- created encoding package
[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 * Private data of an transform_substructure_t' Object
38 *
39 */
40 typedef struct private_transform_substructure_s private_transform_substructure_t;
41
42 struct private_transform_substructure_s {
43 /**
44 * public transform_substructure_t interface
45 */
46 transform_substructure_t public;
47
48 /**
49 * next payload type
50 */
51 u_int8_t next_payload;
52
53
54 /**
55 * Length of this payload
56 */
57 u_int16_t transform_length;
58
59
60 /**
61 * Type of the transform
62 */
63 u_int8_t transform_type;
64
65 /**
66 * Transform ID
67 */
68 u_int16_t transform_id;
69
70 /**
71 * Transforms Attributes are stored in a linked_list_t
72 */
73 linked_list_t *attributes;
74
75 /**
76 * @brief Computes the length of this substructure.
77 *
78 * @param this calling private_transform_substructure_t object
79 * @return
80 * SUCCESS in any case
81 */
82 status_t (*compute_length) (private_transform_substructure_t *this);
83 };
84
85
86 /**
87 * string mappings for transform_type_t
88 */
89 mapping_t transform_type_m[] = {
90 {UNDEFINED_TRANSFORM_TYPE, "UNDEFINED_TRANSFORM_TYPE"},
91 {ENCRYPTION_ALGORITHM, "ENCRYPTION_ALGORITHM"},
92 {PSEUDO_RANDOM_FUNCTION, "PSEUDO_RANDOM_FUNCTION"},
93 {INTEGRITIY_ALGORITHM, "INTEGRITIY_ALGORITHM"},
94 {DIFFIE_HELLMAN_GROUP, "DIFFIE_HELLMAN_GROUP"},
95 {EXTENDED_SEQUENCE_NUNBERS, "EXTENDED_SEQUENCE_NUNBERS"},
96 {MAPPING_END, NULL}
97 };
98
99
100 /**
101 * string mappings for encryption_algorithm_t
102 */
103 mapping_t encryption_algorithm_m[] = {
104 {ENCR_UNDEFINED, "ENCR_UNDEFINED"},
105 {ENCR_DES_IV64, "ENCR_DES_IV64"},
106 {ENCR_DES, "ENCR_DES"},
107 {ENCR_3DES, "ENCR_3DES"},
108 {ENCR_RC5, "ENCR_RC5"},
109 {ENCR_IDEA, "ENCR_IDEA"},
110 {ENCR_CAST, "ENCR_CAST"},
111 {ENCR_BLOWFISH, "ENCR_BLOWFISH"},
112 {ENCR_3IDEA, "ENCR_3IDEA"},
113 {ENCR_DES_IV32, "ENCR_DES_IV32"},
114 {ENCR_NULL, "ENCR_NULL"},
115 {ENCR_AES_CBC, "ENCR_AES_CBC"},
116 {ENCR_AES_CTR, "ENCR_AES_CTR"},
117 {MAPPING_END, NULL}
118 };
119
120 /**
121 * string mappings for encryption_algorithm_t
122 */
123 mapping_t pseudo_random_function_m[] = {
124 {PRF_UNDEFINED, "PRF_UNDEFINED"},
125 {PRF_HMAC_MD5, "PRF_HMAC_MD5"},
126 {PRF_HMAC_SHA1, "PRF_HMAC_SHA1"},
127 {PRF_HMAC_TIGER, "PRF_HMAC_TIGER"},
128 {PRF_AES128_CBC, "PRF_AES128_CBC"},
129 {MAPPING_END, NULL}
130 };
131
132 /**
133 * string mappings for integrity_algorithm_t
134 */
135 mapping_t integrity_algorithm_m[] = {
136 {AUTH_UNDEFINED, "AUTH_UNDEFINED"},
137 {AUTH_HMAC_MD5_96, "AUTH_HMAC_MD5_96"},
138 {AUTH_HMAC_SHA1_96, "AUTH_HMAC_SHA1_96"},
139 {AUTH_DES_MAC, "AUTH_DES_MAC"},
140 {AUTH_KPDK_MD5, "AUTH_KPDK_MD5"},
141 {AUTH_AES_XCBC_96, "AUTH_AES_XCBC_96"},
142 {MAPPING_END, NULL}
143 };
144
145 /**
146 * string mappings for diffie_hellman_group_t
147 */
148 mapping_t diffie_hellman_group_m[] = {
149 {MODP_UNDEFINED, "MODP_UNDEFINED"},
150 {MODP_768_BIT, "MODP_768_BIT"},
151 {MODP_1024_BIT, "MODP_1024_BIT"},
152 {MODP_1536_BIT, "MODP_1536_BIT"},
153 {MODP_2048_BIT, "MODP_2048_BIT"},
154 {MODP_3072_BIT, "MODP_3072_BIT"},
155 {MODP_4096_BIT, "MODP_4096_BIT"},
156 {MODP_6144_BIT, "MODP_6144_BIT"},
157 {MODP_8192_BIT, "MODP_8192_BIT"},
158 {MAPPING_END, NULL}
159 };
160
161 /**
162 * string mappings for extended_sequence_numbers_t
163 */
164 mapping_t extended_sequence_numbers_m[] = {
165 {NO_EXT_SEQ_NUMBERS, "NO_EXT_SEQ_NUMBERS"},
166 {EXT_SEQ_NUMBERS, "EXT_SEQ_NUMBERS"},
167 {MAPPING_END, NULL}
168 };
169
170 /**
171 * Encoding rules to parse or generate a Transform substructure
172 *
173 * The defined offsets are the positions in a object of type
174 * private_transform_substructure_t.
175 *
176 */
177 encoding_rule_t transform_substructure_encodings[] = {
178 /* 1 Byte next payload type, stored in the field next_payload */
179 { U_INT_8, offsetof(private_transform_substructure_t, next_payload) },
180 /* Reserved Byte is skipped */
181 { RESERVED_BYTE, 0 },
182 /* Length of the whole transform substructure*/
183 { PAYLOAD_LENGTH, offsetof(private_transform_substructure_t, transform_length) },
184 /* transform type is a number of 8 bit */
185 { U_INT_8, offsetof(private_transform_substructure_t, transform_type) },
186 /* Reserved Byte is skipped */
187 { RESERVED_BYTE, 0 },
188 /* tranform ID is a number of 8 bit */
189 { U_INT_16, offsetof(private_transform_substructure_t, transform_id) },
190 /* Attributes are stored in a transform attribute,
191 offset points to a linked_list_t pointer */
192 { TRANSFORM_ATTRIBUTES, offsetof(private_transform_substructure_t, attributes) }
193 };
194
195 /*
196 1 2 3
197 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
198 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
199 ! 0 (last) or 3 ! RESERVED ! Transform Length !
200 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
201 !Transform Type ! RESERVED ! Transform ID !
202 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
203 ! !
204 ~ Transform Attributes ~
205 ! !
206 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
207 */
208
209
210 /**
211 * Implements payload_t's verify function.
212 * See #payload_s.verify for description.
213 */
214 static status_t verify(private_transform_substructure_t *this)
215 {
216 if ((this->next_payload != NO_PAYLOAD) && (this->next_payload != TRANSFORM_SUBSTRUCTURE))
217 {
218 /* must be 0 or 3 */
219 return FAILED;
220 }
221
222 switch (this->transform_type)
223 {
224 case ENCRYPTION_ALGORITHM:
225 {
226 if ((this->transform_id < ENCR_DES_IV64) || (this->transform_id > ENCR_AES_CTR))
227 {
228 return FAILED;
229 }
230 break;
231 }
232 case PSEUDO_RANDOM_FUNCTION:
233 {
234 if ((this->transform_id < PRF_HMAC_MD5) || (this->transform_id > PRF_AES128_CBC))
235 {
236 return FAILED;
237 }
238 break;
239 }
240 case INTEGRITIY_ALGORITHM:
241 {
242 if ((this->transform_id < AUTH_HMAC_MD5_96) || (this->transform_id > AUTH_AES_XCBC_96))
243 {
244 return FAILED;
245 }
246 break;
247 }
248 case DIFFIE_HELLMAN_GROUP:
249 {
250 switch (this->transform_id)
251 {
252 case MODP_768_BIT:
253 case MODP_1024_BIT:
254 case MODP_1536_BIT:
255 case MODP_2048_BIT:
256 case MODP_3072_BIT:
257 case MODP_4096_BIT:
258 case MODP_6144_BIT:
259 case MODP_8192_BIT:
260 {
261 break;
262 }
263 default:
264 {
265 return FAILED;
266 }
267 }
268
269
270 break;
271 }
272 case EXTENDED_SEQUENCE_NUNBERS:
273 {
274 if ((this->transform_id != NO_EXT_SEQ_NUMBERS) && (this->transform_id != EXT_SEQ_NUMBERS))
275 {
276 return FAILED;
277 }
278 break;
279 }
280 default:
281 {
282 /* not a supported transform type! */
283 return FAILED;
284 }
285 }
286
287 /* proposal number is checked in SA payload */
288 return SUCCESS;
289 }
290
291 /**
292 * Implements payload_t's get_encoding_rules function.
293 * See #payload_s.get_encoding_rules for description.
294 */
295 static status_t get_encoding_rules(private_transform_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
296 {
297 *rules = transform_substructure_encodings;
298 *rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t);
299
300 return SUCCESS;
301 }
302
303 /**
304 * Implements payload_t's get_type function.
305 * See #payload_s.get_type for description.
306 */
307 static payload_type_t get_type(private_transform_substructure_t *this)
308 {
309 return TRANSFORM_SUBSTRUCTURE;
310 }
311
312 /**
313 * Implements payload_t's get_next_type function.
314 * See #payload_s.get_next_type for description.
315 */
316 static payload_type_t get_next_type(private_transform_substructure_t *this)
317 {
318 return (this->next_payload);
319 }
320
321 /**
322 * Implements payload_t's get_length function.
323 * See #payload_s.get_length for description.
324 */
325 static size_t get_length(private_transform_substructure_t *this)
326 {
327 this->compute_length(this);
328
329 return this->transform_length;
330 }
331
332 /**
333 * Implements transform_substructure_t's create_transform_attribute_iterator function.
334 * See #transform_substructure_s.create_transform_attribute_iterator for description.
335 */
336 static status_t create_transform_attribute_iterator (private_transform_substructure_t *this,linked_list_iterator_t **iterator,bool forward)
337 {
338 return (this->attributes->create_iterator(this->attributes,iterator,forward));
339 }
340
341 /**
342 * Implements transform_substructure_t's add_transform_attribute function.
343 * See #transform_substructure_s.add_transform_attribute for description.
344 */
345 static status_t add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute)
346 {
347 status_t status;
348 status = this->attributes->insert_last(this->attributes,(void *) attribute);
349 this->compute_length(this);
350 return status;
351 }
352
353 /**
354 * Implements transform_substructure_t's set_is_last_transform function.
355 * See #transform_substructure_s.set_is_last_transform for description.
356 */
357 static status_t set_is_last_transform (private_transform_substructure_t *this, bool is_last)
358 {
359 this->next_payload = (is_last) ? 0: TRANSFORM_TYPE_VALUE;
360 return SUCCESS;
361 }
362
363 /**
364 * Implements transform_substructure_t's get_is_last_transform function.
365 * See #transform_substructure_s.get_is_last_transform for description.
366 */
367 static bool get_is_last_transform (private_transform_substructure_t *this)
368 {
369 return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE);
370 }
371
372 /**
373 * Implements payload_t's set_next_type function.
374 * See #payload_s.set_next_type for description.
375 */
376 static status_t set_next_type(private_transform_substructure_t *this,payload_type_t type)
377 {
378 return SUCCESS;
379 }
380
381 /**
382 * Implements transform_substructure_t's set_transform_type function.
383 * See #transform_substructure_s.set_transform_type for description.
384 */
385 static status_t set_transform_type (private_transform_substructure_t *this,u_int8_t type)
386 {
387 this->transform_type = type;
388 return SUCCESS;
389 }
390
391 /**
392 * Implements transform_substructure_t's get_transform_type function.
393 * See #transform_substructure_s.get_transform_type for description.
394 */
395 static u_int8_t get_transform_type (private_transform_substructure_t *this)
396 {
397 return this->transform_type;
398 }
399
400 /**
401 * Implements transform_substructure_t's set_transform_id function.
402 * See #transform_substructure_s.set_transform_id for description.
403 */
404 static status_t set_transform_id (private_transform_substructure_t *this,u_int16_t id)
405 {
406 this->transform_id = id;
407 return SUCCESS;
408 }
409
410 /**
411 * Implements transform_substructure_t's get_transform_id function.
412 * See #transform_substructure_s.get_transform_id for description.
413 */
414 static u_int16_t get_transform_id (private_transform_substructure_t *this)
415 {
416 return this->transform_id;
417 }
418
419 /**
420 * Implements private_transform_substructure_t's compute_length function.
421 * See #private_transform_substructure_s.compute_length for description.
422 */
423 static status_t compute_length (private_transform_substructure_t *this)
424 {
425 linked_list_iterator_t *iterator;
426 status_t status;
427 size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
428 status = this->attributes->create_iterator(this->attributes,&iterator,TRUE);
429 if (status != SUCCESS)
430 {
431 return length;
432 }
433 while (iterator->has_next(iterator))
434 {
435 payload_t * current_attribute;
436 iterator->current(iterator,(void **) &current_attribute);
437 length += current_attribute->get_length(current_attribute);
438 }
439 iterator->destroy(iterator);
440
441 this->transform_length = length;
442
443 return SUCCESS;
444 }
445
446 /**
447 * Implements transform_substructure_t's clone function.
448 * See transform_substructure_s.clone for description.
449 */
450 static status_t clone(private_transform_substructure_t *this,transform_substructure_t **clone)
451 {
452 private_transform_substructure_t *new_clone;
453 linked_list_iterator_t *attributes;
454 status_t status;
455
456 new_clone = (private_transform_substructure_t *) transform_substructure_create();
457
458 new_clone->next_payload = this->next_payload;
459 new_clone->transform_type = this->transform_type;
460 new_clone->transform_id = this->transform_id;
461
462 status = this->attributes->create_iterator(this->attributes,&attributes,FALSE);
463 if (status != SUCCESS)
464 {
465 new_clone->public.destroy(&(new_clone->public));
466 return status;
467 }
468
469 while (attributes->has_next(attributes))
470 {
471 transform_attribute_t *current_attribute;
472 transform_attribute_t *current_attribute_clone;
473 status = attributes->current(attributes,(void **) &current_attribute);
474 if (status != SUCCESS)
475 {
476 attributes->destroy(attributes);
477 new_clone->public.destroy(&(new_clone->public));
478 return status;
479 }
480 status = current_attribute->clone(current_attribute,&current_attribute_clone);
481 if (status != SUCCESS)
482 {
483 attributes->destroy(attributes);
484 new_clone->public.destroy(&(new_clone->public));
485 return status;
486 }
487
488 status = new_clone->public.add_transform_attribute(&(new_clone->public),current_attribute_clone);
489 if (status != SUCCESS)
490 {
491 attributes->destroy(attributes);
492 current_attribute_clone->destroy(current_attribute_clone);
493 new_clone->public.destroy(&(new_clone->public));
494 return status;
495 }
496 }
497
498 attributes->destroy(attributes);
499
500 *clone = &(new_clone->public);
501 return SUCCESS;
502 }
503
504
505 /**
506 * Implements payload_t's and transform_substructure_t's destroy function.
507 * See #payload_s.destroy or transform_substructure_s.destroy for description.
508 */
509 static status_t destroy(private_transform_substructure_t *this)
510 {
511 /* all proposals are getting destroyed */
512 while (this->attributes->get_count(this->attributes) > 0)
513 {
514 transform_attribute_t *current_attribute;
515 if (this->attributes->remove_last(this->attributes,(void **)&current_attribute) != SUCCESS)
516 {
517 break;
518 }
519 current_attribute->destroy(current_attribute);
520 }
521 this->attributes->destroy(this->attributes);
522
523 allocator_free(this);
524
525 return SUCCESS;
526 }
527
528 /*
529 * Described in header
530 */
531 transform_substructure_t *transform_substructure_create()
532 {
533 private_transform_substructure_t *this = allocator_alloc_thing(private_transform_substructure_t);
534 if (this == NULL)
535 {
536 return NULL;
537 }
538
539 /* payload interface */
540 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
541 this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
542 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
543 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
544 this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
545 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
546 this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
547
548 /* public functions */
549 this->public.create_transform_attribute_iterator = (status_t (*) (transform_substructure_t *,linked_list_iterator_t **,bool)) create_transform_attribute_iterator;
550 this->public.add_transform_attribute = (status_t (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute;
551 this->public.set_is_last_transform = (status_t (*) (transform_substructure_t *,bool)) set_is_last_transform;
552 this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform;
553 this->public.set_transform_type = (status_t (*) (transform_substructure_t *,u_int8_t)) set_transform_type;
554 this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type;
555 this->public.set_transform_id = (status_t (*) (transform_substructure_t *,u_int16_t)) set_transform_id;
556 this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id;
557 this->public.clone = (status_t (*) (transform_substructure_t *,transform_substructure_t **)) clone;
558 this->public.destroy = (status_t (*) (transform_substructure_t *)) destroy;
559
560 /* private functions */
561 this->compute_length = compute_length;
562
563 /* set default values of the fields */
564 this->next_payload = NO_PAYLOAD;
565 this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
566 this->transform_id = 0;
567 this->transform_type = 0;
568
569 this->attributes = linked_list_create();
570
571 if (this->attributes == NULL)
572 {
573 allocator_free(this);
574 return NULL;
575 }
576 return (&(this->public));
577 }