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