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