- added verify function to all payload types
[strongswan.git] / Source / charon / 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 "transform_attribute.h"
31 #include "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_SHA1"},
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 and transform_substructure_t's destroy function.
293 * See #payload_s.destroy or transform_substructure_s.destroy for description.
294 */
295 static status_t destroy(private_transform_substructure_t *this)
296 {
297 /* all proposals are getting destroyed */
298 while (this->attributes->get_count(this->attributes) > 0)
299 {
300 transform_attribute_t *current_attribute;
301 if (this->attributes->remove_last(this->attributes,(void **)&current_attribute) != SUCCESS)
302 {
303 break;
304 }
305 current_attribute->destroy(current_attribute);
306 }
307 this->attributes->destroy(this->attributes);
308
309 allocator_free(this);
310
311 return SUCCESS;
312 }
313
314 /**
315 * Implements payload_t's get_encoding_rules function.
316 * See #payload_s.get_encoding_rules for description.
317 */
318 static status_t get_encoding_rules(private_transform_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
319 {
320 *rules = transform_substructure_encodings;
321 *rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t);
322
323 return SUCCESS;
324 }
325
326 /**
327 * Implements payload_t's get_type function.
328 * See #payload_s.get_type for description.
329 */
330 static payload_type_t get_type(private_transform_substructure_t *this)
331 {
332 return TRANSFORM_SUBSTRUCTURE;
333 }
334
335 /**
336 * Implements payload_t's get_next_type function.
337 * See #payload_s.get_next_type for description.
338 */
339 static payload_type_t get_next_type(private_transform_substructure_t *this)
340 {
341 return (this->next_payload);
342 }
343
344 /**
345 * Implements payload_t's get_length function.
346 * See #payload_s.get_length for description.
347 */
348 static size_t get_length(private_transform_substructure_t *this)
349 {
350 this->compute_length(this);
351
352 return this->transform_length;
353 }
354
355 /**
356 * Implements transform_substructure_t's create_transform_attribute_iterator function.
357 * See #transform_substructure_s.create_transform_attribute_iterator for description.
358 */
359 static status_t create_transform_attribute_iterator (private_transform_substructure_t *this,linked_list_iterator_t **iterator,bool forward)
360 {
361 return (this->attributes->create_iterator(this->attributes,iterator,forward));
362 }
363
364 /**
365 * Implements transform_substructure_t's add_transform_attribute function.
366 * See #transform_substructure_s.add_transform_attribute for description.
367 */
368 static status_t add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute)
369 {
370 status_t status;
371 status = this->attributes->insert_last(this->attributes,(void *) attribute);
372 this->compute_length(this);
373 return status;
374 }
375
376 /**
377 * Implements transform_substructure_t's set_is_last_transform function.
378 * See #transform_substructure_s.set_is_last_transform for description.
379 */
380 static status_t set_is_last_transform (private_transform_substructure_t *this, bool is_last)
381 {
382 this->next_payload = (is_last) ? 0: TRANSFORM_TYPE_VALUE;
383 return SUCCESS;
384 }
385
386 /**
387 * Implements transform_substructure_t's get_is_last_transform function.
388 * See #transform_substructure_s.get_is_last_transform for description.
389 */
390 static bool get_is_last_transform (private_transform_substructure_t *this)
391 {
392 return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE);
393 }
394
395 /**
396 * Implements payload_t's set_next_type function.
397 * See #payload_s.set_next_type for description.
398 */
399 static status_t set_next_type(private_transform_substructure_t *this,payload_type_t type)
400 {
401 return SUCCESS;
402 }
403
404 /**
405 * Implements transform_substructure_t's set_transform_type function.
406 * See #transform_substructure_s.set_transform_type for description.
407 */
408 static status_t set_transform_type (private_transform_substructure_t *this,u_int8_t type)
409 {
410 this->transform_type = type;
411 return SUCCESS;
412 }
413
414 /**
415 * Implements transform_substructure_t's get_transform_type function.
416 * See #transform_substructure_s.get_transform_type for description.
417 */
418 static u_int8_t get_transform_type (private_transform_substructure_t *this)
419 {
420 return this->transform_type;
421 }
422
423 /**
424 * Implements transform_substructure_t's set_transform_id function.
425 * See #transform_substructure_s.set_transform_id for description.
426 */
427 static status_t set_transform_id (private_transform_substructure_t *this,u_int16_t id)
428 {
429 this->transform_id = id;
430 return SUCCESS;
431 }
432
433 /**
434 * Implements transform_substructure_t's get_transform_id function.
435 * See #transform_substructure_s.get_transform_id for description.
436 */
437 static u_int16_t get_transform_id (private_transform_substructure_t *this)
438 {
439 return this->transform_id;
440 }
441
442 /**
443 * Implements private_transform_substructure_t's compute_length function.
444 * See #private_transform_substructure_s.compute_length for description.
445 */
446 static status_t compute_length (private_transform_substructure_t *this)
447 {
448 linked_list_iterator_t *iterator;
449 status_t status;
450 size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
451 status = this->attributes->create_iterator(this->attributes,&iterator,TRUE);
452 if (status != SUCCESS)
453 {
454 return length;
455 }
456 while (iterator->has_next(iterator))
457 {
458 payload_t * current_attribute;
459 iterator->current(iterator,(void **) &current_attribute);
460 length += current_attribute->get_length(current_attribute);
461 }
462 iterator->destroy(iterator);
463
464 this->transform_length = length;
465
466 return SUCCESS;
467 }
468
469 /*
470 * Described in header
471 */
472 transform_substructure_t *transform_substructure_create()
473 {
474 private_transform_substructure_t *this = allocator_alloc_thing(private_transform_substructure_t);
475 if (this == NULL)
476 {
477 return NULL;
478 }
479
480 /* payload interface */
481 this->public.payload_interface.verify = (status_t (*) (payload_t *))verify;
482 this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
483 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
484 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
485 this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
486 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
487 this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
488
489 /* public functions */
490 this->public.create_transform_attribute_iterator = (status_t (*) (transform_substructure_t *,linked_list_iterator_t **,bool)) create_transform_attribute_iterator;
491 this->public.add_transform_attribute = (status_t (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute;
492 this->public.set_is_last_transform = (status_t (*) (transform_substructure_t *,bool)) set_is_last_transform;
493 this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform;
494 this->public.set_transform_type = (status_t (*) (transform_substructure_t *,u_int8_t)) set_transform_type;
495 this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type;
496 this->public.set_transform_id = (status_t (*) (transform_substructure_t *,u_int16_t)) set_transform_id;
497 this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id;
498 this->public.destroy = (status_t (*) (transform_substructure_t *)) destroy;
499
500 /* private functions */
501 this->compute_length = compute_length;
502
503 /* set default values of the fields */
504 this->next_payload = NO_PAYLOAD;
505 this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
506 this->transform_id = 0;
507 this->transform_type = 0;
508
509 this->attributes = linked_list_create();
510
511 if (this->attributes == NULL)
512 {
513 allocator_free(this);
514 return NULL;
515 }
516 return (&(this->public));
517 }