- wrote ke_payload class
[strongswan.git] / Source / charon / payloads / ke_payload.c
1 /**
2 * @file ke_payload.c
3 *
4 * @brief Declaration of the class ke_payload_t.
5 *
6 * An object of this type represents an IKEv2 KE-Payload.
7 *
8 * See section 3.4 of RFC for details of this payload type.
9 *
10 */
11
12 /*
13 * Copyright (C) 2005 Jan Hutter, Martin Willi
14 * Hochschule fuer Technik Rapperswil
15 *
16 * This program is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 2 of the License, or (at your
19 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
20 *
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * for more details.
25 */
26
27 /* offsetof macro */
28 #include <stddef.h>
29
30 #include "ke_payload.h"
31
32 #include "encodings.h"
33 #include "../utils/allocator.h"
34 #include "../utils/linked_list.h"
35
36
37 /**
38 * Private data of an ke_payload_t Object
39 *
40 */
41 typedef struct private_ke_payload_s private_ke_payload_t;
42
43 struct private_ke_payload_s {
44 /**
45 * public ke_payload_t interface
46 */
47 ke_payload_t public;
48
49 /**
50 * next payload type
51 */
52 u_int8_t next_payload;
53
54 /**
55 * Critical flag
56 */
57 bool critical;
58
59 /**
60 * Length of this payload
61 */
62 u_int16_t payload_length;
63
64
65 /**
66 * DH Group Number
67 */
68 u_int16_t dh_group_number;
69
70 /**
71 * Key Exchange Data of this KE payload
72 */
73 chunk_t key_exchange_data;
74
75 /**
76 * @brief Computes the length of this payload.
77 *
78 * @param this calling private_ke_payload_t object
79 * @return
80 * SUCCESS in any case
81 */
82 status_t (*compute_length) (private_ke_payload_t *this);
83 };
84
85 /**
86 * Encoding rules to parse or generate a IKEv2-KE Payload
87 *
88 * The defined offsets are the positions in a object of type
89 * private_ke_payload_t.
90 *
91 */
92 encoding_rule_t ke_payload_encodings[] = {
93 /* 1 Byte next payload type, stored in the field next_payload */
94 { U_INT_8, offsetof(private_ke_payload_t, next_payload) },
95 /* the critical bit */
96 { FLAG, offsetof(private_ke_payload_t, critical) },
97 /* 7 Bit reserved bits, nowhere stored */
98 { RESERVED_BIT, 0 },
99 { RESERVED_BIT, 0 },
100 { RESERVED_BIT, 0 },
101 { RESERVED_BIT, 0 },
102 { RESERVED_BIT, 0 },
103 { RESERVED_BIT, 0 },
104 { RESERVED_BIT, 0 },
105 /* Length of the whole payload*/
106 { PAYLOAD_LENGTH, offsetof(private_ke_payload_t, payload_length) },
107 /* DH Group number as 16 bit field*/
108 { U_INT_16, offsetof(private_ke_payload_t, dh_group_number) },
109 { RESERVED_BYTE, 0 },
110 { RESERVED_BYTE, 0 },
111 /* Key Exchange Data is from variable size */
112 { KEY_EXCHANGE_DATA, offsetof(private_ke_payload_t, key_exchange_data) }
113 };
114
115 /**
116 * Implements payload_t's and ke_payload_t's destroy function.
117 * See #payload_s.destroy or ke_payload_s.destroy for description.
118 */
119 static status_t destroy(private_ke_payload_t *this)
120 {
121 if (this->key_exchange_data.ptr != NULL);
122 allocator_free(this->key_exchange_data.ptr);
123 allocator_free(this);
124 return SUCCESS;
125 }
126
127 /**
128 * Implements payload_t's get_encoding_rules function.
129 * See #payload_s.get_encoding_rules for description.
130 */
131 static status_t get_encoding_rules(private_ke_payload_t *this, encoding_rule_t **rules, size_t *rule_count)
132 {
133 *rules = ke_payload_encodings;
134 *rule_count = sizeof(ke_payload_encodings) / sizeof(encoding_rule_t);
135
136 return SUCCESS;
137 }
138
139 /**
140 * Implements payload_t's get_type function.
141 * See #payload_s.get_type for description.
142 */
143 static payload_type_t get_type(private_ke_payload_t *this)
144 {
145 return KEY_EXCHANGE;
146 }
147
148 /**
149 * Implements payload_t's get_next_type function.
150 * See #payload_s.get_next_type for description.
151 */
152 static payload_type_t get_next_type(private_ke_payload_t *this)
153 {
154 return (this->next_payload);
155 }
156
157 /**
158 * Implements payload_t's set_next_type function.
159 * See #payload_s.set_next_type for description.
160 */
161 static status_t set_next_type(private_ke_payload_t *this,payload_type_t type)
162 {
163 this->next_payload = type;
164 return SUCCESS;
165 }
166
167 /**
168 * Implements payload_t's get_length function.
169 * See #payload_s.get_length for description.
170 */
171 static size_t get_length(private_ke_payload_t *this)
172 {
173 this->compute_length(this);
174 return this->payload_length;
175 }
176
177 /**
178 * Implements private_ke_payload_t's compute_length function.
179 * See #private_ke_payload_s.compute_length for description.
180 */
181 static status_t compute_length (private_ke_payload_t *this)
182 {
183 size_t length = KE_PAYLOAD_HEADER_LENGTH;
184 if (this->key_exchange_data.ptr != NULL)
185 {
186 length += this->key_exchange_data.len;
187 }
188
189 this->payload_length = length;
190
191 return SUCCESS;
192 }
193
194
195 /**
196 * Implements ke_payload_t's get_key_exchange_data function.
197 * See #ke_payload_t.get_key_exchange_data for description.
198 */
199 chunk_t get_key_exchange_data(private_ke_payload_t *this)
200 {
201 return (this->key_exchange_data);
202 }
203
204 /**
205 * Implements ke_payload_t's set_key_exchange_data function.
206 * See #ke_payload_t.set_key_exchange_data for description.
207 */
208 status_t set_key_exchange_data(private_ke_payload_t *this, chunk_t key_exchange_data)
209 {
210 /* destroy existing data first */
211 if (this->key_exchange_data.ptr != NULL)
212 {
213 /* free existing value */
214 allocator_free(this->key_exchange_data.ptr);
215 this->key_exchange_data.ptr = NULL;
216 this->key_exchange_data.len = 0;
217
218 }
219
220 this->key_exchange_data.ptr = allocator_clone_bytes(key_exchange_data.ptr,key_exchange_data.len);
221 if (this->key_exchange_data.ptr == NULL)
222 {
223 return OUT_OF_RES;
224 }
225 this->key_exchange_data.len = key_exchange_data.len;
226 this->compute_length(this);
227
228 return SUCCESS;
229 }
230
231 /**
232 * Implements ke_payload_t's get_dh_group_number function.
233 * See #ke_payload_t.get_dh_group_number for description.
234 */
235 u_int16_t get_dh_group_number(private_ke_payload_t *this)
236 {
237 return this->dh_group_number;
238 }
239
240 /**
241 * Implements ke_payload_t's set_dh_group_number function.
242 * See #ke_payload_t.set_dh_group_number for description.
243 */
244 status_t set_dh_group_number(private_ke_payload_t *this, u_int16_t dh_group_number)
245 {
246 this->dh_group_number = dh_group_number;
247 return SUCCESS;
248 }
249
250 /*
251 * Described in header
252 */
253 ke_payload_t *ke_payload_create()
254 {
255 private_ke_payload_t *this = allocator_alloc_thing(private_ke_payload_t);
256 if (this == NULL)
257 {
258 return NULL;
259 }
260 /* interface functions */
261 this->public.payload_interface.get_encoding_rules = (status_t (*) (payload_t *, encoding_rule_t **, size_t *) ) get_encoding_rules;
262 this->public.payload_interface.get_length = (size_t (*) (payload_t *)) get_length;
263 this->public.payload_interface.get_next_type = (payload_type_t (*) (payload_t *)) get_next_type;
264 this->public.payload_interface.set_next_type = (status_t (*) (payload_t *,payload_type_t)) set_next_type;
265 this->public.payload_interface.get_type = (payload_type_t (*) (payload_t *)) get_type;
266 this->public.payload_interface.destroy = (status_t (*) (payload_t *))destroy;
267
268 /* public functions */
269 this->public.get_key_exchange_data = (chunk_t (*) (ke_payload_t *)) get_key_exchange_data;
270 this->public.set_key_exchange_data = (status_t (*) (ke_payload_t *,chunk_t)) set_key_exchange_data;
271 this->public.get_dh_group_number = (u_int16_t (*) (ke_payload_t *)) get_dh_group_number;
272 this->public.set_dh_group_number =(status_t (*) (ke_payload_t *,u_int16_t)) set_dh_group_number;
273 this->public.destroy = (status_t (*) (ke_payload_t *)) destroy;
274
275 /* private functions */
276 this->compute_length = compute_length;
277
278 /* set default values of the fields */
279 this->critical = KE_PAYLOAD_CRITICAL_FLAG;
280 this->next_payload = NO_PAYLOAD;
281 this->payload_length = KE_PAYLOAD_HEADER_LENGTH;
282 this->key_exchange_data.ptr = NULL;
283 this->key_exchange_data.len = 0;
284 this->dh_group_number = 0;
285
286 return (&(this->public));
287 }