Set sp_id to reqid when creating ESA
[strongswan.git] / src / charon-tkm / src / tkm / tkm_kernel_ipsec.c
1 /*
2 * Copyright (C) 2012 Reto Buerki
3 * Copyright (C) 2012 Adrian-Ken Rueegsegger
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
17 #include <errno.h>
18 #include <netinet/udp.h>
19 #include <linux/xfrm.h>
20 #include <utils/debug.h>
21 #include <utils/chunk.h>
22 #include <tkm/constants.h>
23 #include <tkm/client.h>
24
25 #include "tkm.h"
26 #include "tkm_utils.h"
27 #include "tkm_types.h"
28 #include "tkm_keymat.h"
29 #include "tkm_kernel_sad.h"
30 #include "tkm_kernel_ipsec.h"
31
32 typedef struct private_tkm_kernel_ipsec_t private_tkm_kernel_ipsec_t;
33
34 /**
35 * Private variables and functions of TKM kernel ipsec instance.
36 */
37 struct private_tkm_kernel_ipsec_t {
38
39 /**
40 * Public tkm_kernel_ipsec interface.
41 */
42 tkm_kernel_ipsec_t public;
43
44 /**
45 * RNG used for SPI generation.
46 */
47 rng_t *rng;
48
49 /**
50 * CHILD/ESP SA database.
51 */
52 tkm_kernel_sad_t *sad;
53
54 };
55
56 METHOD(kernel_ipsec_t, get_spi, status_t,
57 private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
58 u_int8_t protocol, u_int32_t reqid, u_int32_t *spi)
59 {
60 DBG1(DBG_KNL, "getting SPI for reqid {%u}", reqid);
61 const bool result = this->rng->get_bytes(this->rng, sizeof(u_int32_t),
62 (u_int8_t *)spi);
63 return result ? SUCCESS : FAILED;
64 }
65
66 METHOD(kernel_ipsec_t, get_cpi, status_t,
67 private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
68 u_int32_t reqid, u_int16_t *cpi)
69 {
70 return NOT_SUPPORTED;
71 }
72
73 METHOD(kernel_ipsec_t, add_sa, status_t,
74 private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
75 u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark,
76 u_int32_t tfc, lifetime_cfg_t *lifetime, u_int16_t enc_alg, chunk_t enc_key,
77 u_int16_t int_alg, chunk_t int_key, ipsec_mode_t mode, u_int16_t ipcomp,
78 u_int16_t cpi, bool encap, bool esn, bool inbound,
79 traffic_selector_t* src_ts, traffic_selector_t* dst_ts)
80 {
81 if (enc_key.ptr == NULL)
82 {
83 DBG1(DBG_KNL, "Unable to get ESA information");
84 return FAILED;
85 }
86 esa_info_t esa = *(esa_info_t *)(enc_key.ptr);
87
88 /* only handle the case where we have both distinct ESP spi's available */
89 if (esa.spi_r == spi)
90 {
91 chunk_free(&esa.nonce_i);
92 chunk_free(&esa.nonce_r);
93 return SUCCESS;
94 }
95
96 /* Initiator if encr_r is passed as enc_key to the inbound add_sa call */
97 const bool initiator = esa.is_encr_r && inbound;
98
99 esp_spi_type spi_loc, spi_rem;
100 host_t *local, *peer;
101 chunk_t *nonce_loc, *nonce_rem;
102 if (initiator)
103 {
104 spi_loc = spi;
105 spi_rem = esa.spi_r;
106 local = dst;
107 peer = src;
108 nonce_loc = &esa.nonce_i;
109 nonce_rem = &esa.nonce_r;
110 }
111 else
112 {
113 spi_loc = esa.spi_r;
114 spi_rem = spi;
115 local = src;
116 peer = dst;
117 nonce_loc = &esa.nonce_r;
118 nonce_rem = &esa.nonce_i;
119 }
120
121 const nc_id_type nonce_loc_id = tkm->chunk_map->get_id(tkm->chunk_map,
122 nonce_loc);
123
124 const esa_id_type esa_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ESA);
125 if (!this->sad->insert(this->sad, esa_id, peer, local, spi_loc, protocol))
126 {
127 DBG1(DBG_KNL, "unable to add entry (%llu) to SAD", esa_id);
128 goto sad_failure;
129 }
130
131 /*
132 * creation of first CHILD SA:
133 * no nonce and no dh contexts because the ones from the IKE SA are re-used
134 */
135 if (nonce_loc_id == 0 && esa.dh_id == 0)
136 {
137 if (ike_esa_create_first(esa_id, esa.isa_id, reqid, 1, ntohl(spi_loc),
138 ntohl(spi_rem)) != TKM_OK)
139 {
140 DBG1(DBG_KNL, "child SA (%llu, first) creation failed", esa_id);
141 goto failure;
142 }
143 }
144 /* creation of child SA without PFS: no dh context */
145 else if (nonce_loc_id != 0 && esa.dh_id == 0)
146 {
147 nonce_type nc_rem;
148 chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type));
149 if (ike_esa_create_no_pfs(esa_id, esa.isa_id, reqid, 1, nonce_loc_id,
150 nc_rem, initiator, ntohl(spi_loc),
151 ntohl(spi_rem)) != TKM_OK)
152 {
153 DBG1(DBG_KNL, "child SA (%llu, no PFS) creation failed", esa_id);
154 goto failure;
155 }
156 tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nonce_loc_id);
157 }
158 /* creation of subsequent child SA with PFS: nonce and dh context are set */
159 else
160 {
161 nonce_type nc_rem;
162 chunk_to_sequence(nonce_rem, &nc_rem, sizeof(nonce_type));
163 if (ike_esa_create(esa_id, esa.isa_id, reqid, 1, esa.dh_id, nonce_loc_id,
164 nc_rem, initiator, ntohl(spi_loc),
165 ntohl(spi_rem)) != TKM_OK)
166 {
167 DBG1(DBG_KNL, "child SA (%llu) creation failed", esa_id);
168 goto failure;
169 }
170 tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nonce_loc_id);
171 }
172 if (ike_esa_select(esa_id) != TKM_OK)
173 {
174 DBG1(DBG_KNL, "error selecting new child SA (%llu)", esa_id);
175 if (ike_esa_reset(esa_id) != TKM_OK)
176 {
177 DBG1(DBG_KNL, "child SA (%llu) deletion failed", esa_id);
178 }
179 goto failure;
180 }
181
182 DBG1(DBG_KNL, "added child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, "
183 "esp_spi_rem: %x, role: %s)", esa_id, esa.isa_id, ntohl(spi_loc),
184 ntohl(spi_rem), initiator ? "initiator" : "responder");
185 chunk_free(&esa.nonce_i);
186 chunk_free(&esa.nonce_r);
187
188 return SUCCESS;
189
190 failure:
191 this->sad->remove(this->sad, esa_id);
192 sad_failure:
193 tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id);
194 chunk_free(&esa.nonce_i);
195 chunk_free(&esa.nonce_r);
196 return FAILED;
197 }
198
199 METHOD(kernel_ipsec_t, query_sa, status_t,
200 private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
201 u_int32_t spi, u_int8_t protocol, mark_t mark, u_int64_t *bytes,
202 u_int64_t *packets)
203 {
204 return NOT_SUPPORTED;
205 }
206
207 METHOD(kernel_ipsec_t, del_sa, status_t,
208 private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
209 u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark)
210 {
211 const esa_id_type esa_id = this->sad->get_esa_id(this->sad, src, dst, spi,
212 protocol);
213 if (esa_id)
214 {
215 DBG1(DBG_KNL, "deleting child SA (esa: %llu, spi: %x)", esa_id,
216 ntohl(spi));
217 if (ike_esa_reset(esa_id) != TKM_OK)
218 {
219 DBG1(DBG_KNL, "child SA (%llu) deletion failed", esa_id);
220 return FAILED;
221 }
222 this->sad->remove(this->sad, esa_id);
223 tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_ESA, esa_id);
224 }
225 return SUCCESS;
226 }
227
228 METHOD(kernel_ipsec_t, update_sa, status_t,
229 private_tkm_kernel_ipsec_t *this, u_int32_t spi, u_int8_t protocol,
230 u_int16_t cpi, host_t *src, host_t *dst, host_t *new_src, host_t *new_dst,
231 bool old_encap, bool new_encap, mark_t mark)
232 {
233 return NOT_SUPPORTED;
234 }
235
236 METHOD(kernel_ipsec_t, flush_sas, status_t,
237 private_tkm_kernel_ipsec_t *this)
238 {
239 DBG1(DBG_KNL, "flushing child SA entries");
240 return SUCCESS;
241 }
242
243 METHOD(kernel_ipsec_t, add_policy, status_t,
244 private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
245 traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
246 policy_dir_t direction, policy_type_t type, ipsec_sa_cfg_t *sa,
247 mark_t mark, policy_priority_t priority)
248 {
249 return SUCCESS;
250 }
251
252 METHOD(kernel_ipsec_t, query_policy, status_t,
253 private_tkm_kernel_ipsec_t *this, traffic_selector_t *src_ts,
254 traffic_selector_t *dst_ts, policy_dir_t direction, mark_t mark,
255 u_int32_t *use_time)
256 {
257 return NOT_SUPPORTED;
258 }
259
260 METHOD(kernel_ipsec_t, del_policy, status_t,
261 private_tkm_kernel_ipsec_t *this, traffic_selector_t *src_ts,
262 traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid,
263 mark_t mark, policy_priority_t prio)
264 {
265 return SUCCESS;
266 }
267
268 METHOD(kernel_ipsec_t, flush_policies, status_t,
269 private_tkm_kernel_ipsec_t *this)
270 {
271 return SUCCESS;
272 }
273
274
275 METHOD(kernel_ipsec_t, bypass_socket, bool,
276 private_tkm_kernel_ipsec_t *this, int fd, int family)
277 {
278 struct xfrm_userpolicy_info policy;
279 u_int sol, ipsec_policy;
280
281 switch (family)
282 {
283 case AF_INET:
284 sol = SOL_IP;
285 ipsec_policy = IP_XFRM_POLICY;
286 break;
287 case AF_INET6:
288 sol = SOL_IPV6;
289 ipsec_policy = IPV6_XFRM_POLICY;
290 break;
291 default:
292 return FALSE;
293 }
294
295 memset(&policy, 0, sizeof(policy));
296 policy.action = XFRM_POLICY_ALLOW;
297 policy.sel.family = family;
298
299 policy.dir = XFRM_POLICY_OUT;
300 if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
301 {
302 DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
303 strerror(errno));
304 return FALSE;
305 }
306 policy.dir = XFRM_POLICY_IN;
307 if (setsockopt(fd, sol, ipsec_policy, &policy, sizeof(policy)) < 0)
308 {
309 DBG1(DBG_KNL, "unable to set IPSEC_POLICY on socket: %s",
310 strerror(errno));
311 return FALSE;
312 }
313 return TRUE;
314 }
315
316 METHOD(kernel_ipsec_t, enable_udp_decap, bool,
317 private_tkm_kernel_ipsec_t *this, int fd, int family, u_int16_t port)
318 {
319 int type = UDP_ENCAP_ESPINUDP;
320
321 if (setsockopt(fd, SOL_UDP, UDP_ENCAP, &type, sizeof(type)) < 0)
322 {
323 DBG1(DBG_KNL, "unable to set UDP_ENCAP: %s", strerror(errno));
324 return FALSE;
325 }
326 return TRUE;
327 }
328
329 METHOD(kernel_ipsec_t, destroy, void,
330 private_tkm_kernel_ipsec_t *this)
331 {
332 DESTROY_IF(this->rng);
333 DESTROY_IF(this->sad);
334 free(this);
335 }
336
337 /*
338 * Described in header.
339 */
340 tkm_kernel_ipsec_t *tkm_kernel_ipsec_create()
341 {
342 private_tkm_kernel_ipsec_t *this;
343
344 INIT(this,
345 .public = {
346 .interface = {
347 .get_spi = _get_spi,
348 .get_cpi = _get_cpi,
349 .add_sa = _add_sa,
350 .update_sa = _update_sa,
351 .query_sa = _query_sa,
352 .del_sa = _del_sa,
353 .flush_sas = _flush_sas,
354 .add_policy = _add_policy,
355 .query_policy = _query_policy,
356 .del_policy = _del_policy,
357 .flush_policies = _flush_policies,
358 .bypass_socket = _bypass_socket,
359 .enable_udp_decap = _enable_udp_decap,
360 .destroy = _destroy,
361 },
362 },
363 .rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
364 .sad = tkm_kernel_sad_create(),
365 );
366
367 if (!this->rng)
368 {
369 DBG1(DBG_KNL, "unable to create RNG");
370 destroy(this);
371 return NULL;
372 }
373 if (!this->sad)
374 {
375 DBG1(DBG_KNL, "unable to create SAD");
376 destroy(this);
377 return NULL;
378 }
379
380 return &this->public;
381 }