ec52ec81a91cb9d1bbd34444e2744ef28ada330d
[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 * Implements payload_t's and transform_substructure_t's destroy function.
197 * See #payload_s.destroy or transform_substructure_s.destroy for description.
198 */
199 static status_t destroy(private_transform_substructure_t *this)
200 {
201 /* all proposals are getting destroyed */
202 while (this->attributes->get_count(this->attributes) > 0)
203 {
204 transform_attribute_t *current_attribute;
205 if (this->attributes->remove_last(this->attributes,(void **)&current_attribute) != SUCCESS)
206 {
207 break;
208 }
209 current_attribute->destroy(current_attribute);
210 }
211 this->attributes->destroy(this->attributes);
212
213 allocator_free(this);
214
215 return SUCCESS;
216 }
217
218 /**
219 * Implements payload_t's get_encoding_rules function.
220 * See #payload_s.get_encoding_rules for description.
221 */
222 static status_t get_encoding_rules(private_transform_substructure_t *this, encoding_rule_t **rules, size_t *rule_count)
223 {
224 *rules = transform_substructure_encodings;
225 *rule_count = sizeof(transform_substructure_encodings) / sizeof(encoding_rule_t);
226
227 return SUCCESS;
228 }
229
230 /**
231 * Implements payload_t's get_type function.
232 * See #payload_s.get_type for description.
233 */
234 static payload_type_t get_type(private_transform_substructure_t *this)
235 {
236 return TRANSFORM_SUBSTRUCTURE;
237 }
238
239 /**
240 * Implements payload_t's get_next_type function.
241 * See #payload_s.get_next_type for description.
242 */
243 static payload_type_t get_next_type(private_transform_substructure_t *this)
244 {
245 return (this->next_payload);
246 }
247
248 /**
249 * Implements payload_t's get_length function.
250 * See #payload_s.get_length for description.
251 */
252 static size_t get_length(private_transform_substructure_t *this)
253 {
254 this->compute_length(this);
255
256 return this->transform_length;
257 }
258
259 /**
260 * Implements transform_substructure_t's create_transform_attribute_iterator function.
261 * See #transform_substructure_s.create_transform_attribute_iterator for description.
262 */
263 static status_t create_transform_attribute_iterator (private_transform_substructure_t *this,linked_list_iterator_t **iterator,bool forward)
264 {
265 return (this->attributes->create_iterator(this->attributes,iterator,forward));
266 }
267
268 /**
269 * Implements transform_substructure_t's add_transform_attribute function.
270 * See #transform_substructure_s.add_transform_attribute for description.
271 */
272 static status_t add_transform_attribute (private_transform_substructure_t *this,transform_attribute_t *attribute)
273 {
274 status_t status;
275 status = this->attributes->insert_last(this->attributes,(void *) attribute);
276 this->compute_length(this);
277 return status;
278 }
279
280 /**
281 * Implements transform_substructure_t's set_is_last_transform function.
282 * See #transform_substructure_s.set_is_last_transform for description.
283 */
284 static status_t set_is_last_transform (private_transform_substructure_t *this, bool is_last)
285 {
286 this->next_payload = (is_last) ? 0: TRANSFORM_TYPE_VALUE;
287 return SUCCESS;
288 }
289
290 /**
291 * Implements transform_substructure_t's get_is_last_transform function.
292 * See #transform_substructure_s.get_is_last_transform for description.
293 */
294 static bool get_is_last_transform (private_transform_substructure_t *this)
295 {
296 return ((this->next_payload == TRANSFORM_TYPE_VALUE) ? FALSE : TRUE);
297 }
298
299 /**
300 * Implements payload_t's set_next_type function.
301 * See #payload_s.set_next_type for description.
302 */
303 static status_t set_next_type(private_transform_substructure_t *this,payload_type_t type)
304 {
305 return SUCCESS;
306 }
307
308 /**
309 * Implements transform_substructure_t's set_transform_type function.
310 * See #transform_substructure_s.set_transform_type for description.
311 */
312 static status_t set_transform_type (private_transform_substructure_t *this,u_int8_t type)
313 {
314 this->transform_type = type;
315 return SUCCESS;
316 }
317
318 /**
319 * Implements transform_substructure_t's get_transform_type function.
320 * See #transform_substructure_s.get_transform_type for description.
321 */
322 static u_int8_t get_transform_type (private_transform_substructure_t *this)
323 {
324 return this->transform_type;
325 }
326
327 /**
328 * Implements transform_substructure_t's set_transform_id function.
329 * See #transform_substructure_s.set_transform_id for description.
330 */
331 static status_t set_transform_id (private_transform_substructure_t *this,u_int16_t id)
332 {
333 this->transform_id = id;
334 return SUCCESS;
335 }
336
337 /**
338 * Implements transform_substructure_t's get_transform_id function.
339 * See #transform_substructure_s.get_transform_id for description.
340 */
341 static u_int16_t get_transform_id (private_transform_substructure_t *this)
342 {
343 return this->transform_id;
344 }
345
346 /**
347 * Implements private_transform_substructure_t's compute_length function.
348 * See #private_transform_substructure_s.compute_length for description.
349 */
350 static status_t compute_length (private_transform_substructure_t *this)
351 {
352 linked_list_iterator_t *iterator;
353 status_t status;
354 size_t length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
355 status = this->attributes->create_iterator(this->attributes,&iterator,TRUE);
356 if (status != SUCCESS)
357 {
358 return length;
359 }
360 while (iterator->has_next(iterator))
361 {
362 payload_t * current_attribute;
363 iterator->current(iterator,(void **) &current_attribute);
364 length += current_attribute->get_length(current_attribute);
365 }
366 iterator->destroy(iterator);
367
368 this->transform_length = length;
369
370 return SUCCESS;
371 }
372
373 /*
374 * Described in header
375 */
376 transform_substructure_t *transform_substructure_create()
377 {
378 private_transform_substructure_t *this = allocator_alloc_thing(private_transform_substructure_t);
379 if (this == NULL)
380 {
381 return NULL;
382 }
383
384 this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
385 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
386 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
387 this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
388 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
389 this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
390 this->public.create_transform_attribute_iterator = (status_t (*) (transform_substructure_t *,linked_list_iterator_t **,bool)) create_transform_attribute_iterator;
391 this->public.add_transform_attribute = (status_t (*) (transform_substructure_t *,transform_attribute_t *)) add_transform_attribute;
392 this->public.set_is_last_transform = (status_t (*) (transform_substructure_t *,bool)) set_is_last_transform;
393 this->public.get_is_last_transform = (bool (*) (transform_substructure_t *)) get_is_last_transform;
394 this->public.set_transform_type = (status_t (*) (transform_substructure_t *,u_int8_t)) set_transform_type;
395 this->public.get_transform_type = (u_int8_t (*) (transform_substructure_t *)) get_transform_type;
396 this->public.set_transform_id = (status_t (*) (transform_substructure_t *,u_int16_t)) set_transform_id;
397 this->public.get_transform_id = (u_int16_t (*) (transform_substructure_t *)) get_transform_id;
398 this->public.destroy = (status_t (*) (transform_substructure_t *)) destroy;
399
400 /* private functions */
401 this->compute_length = compute_length;
402
403 /* set default values of the fields */
404 this->next_payload = NO_PAYLOAD;
405 this->transform_length = TRANSFORM_SUBSTRUCTURE_HEADER_LENGTH;
406 this->transform_id = 0;
407 this->transform_type = 0;
408
409 this->attributes = linked_list_create();
410
411 if (this->attributes == NULL)
412 {
413 allocator_free(this);
414 return NULL;
415 }
416 return (&(this->public));
417 }