2 * Copyright (C) 2012 Reto Buerki
3 * Copyright (C) 2012 Adrian-Ken Rueegsegger
4 * Hochschule fuer Technik Rapperswil
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>.
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
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>
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"
32 /** From linux/in.h */
33 #ifndef IP_XFRM_POLICY
34 #define IP_XFRM_POLICY 17
37 typedef struct private_tkm_kernel_ipsec_t private_tkm_kernel_ipsec_t
;
40 * Private variables and functions of TKM kernel ipsec instance.
42 struct private_tkm_kernel_ipsec_t
{
45 * Public tkm_kernel_ipsec interface.
47 tkm_kernel_ipsec_t
public;
50 * RNG used for SPI generation.
55 * CHILD/ESP SA database.
57 tkm_kernel_sad_t
*sad
;
61 METHOD(kernel_ipsec_t
, get_spi
, status_t
,
62 private_tkm_kernel_ipsec_t
*this, host_t
*src
, host_t
*dst
,
63 u_int8_t protocol
, u_int32_t reqid
, u_int32_t
*spi
)
69 this->rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_WEAK
);
72 DBG1(DBG_KNL
, "unable to create RNG");
77 DBG1(DBG_KNL
, "getting SPI for reqid {%u}", reqid
);
78 result
= this->rng
->get_bytes(this->rng
, sizeof(u_int32_t
),
80 return result ? SUCCESS
: FAILED
;
83 METHOD(kernel_ipsec_t
, get_cpi
, status_t
,
84 private_tkm_kernel_ipsec_t
*this, host_t
*src
, host_t
*dst
,
85 u_int32_t reqid
, u_int16_t
*cpi
)
90 METHOD(kernel_ipsec_t
, add_sa
, status_t
,
91 private_tkm_kernel_ipsec_t
*this, host_t
*src
, host_t
*dst
,
92 u_int32_t spi
, u_int8_t protocol
, u_int32_t reqid
, mark_t mark
,
93 u_int32_t tfc
, lifetime_cfg_t
*lifetime
, u_int16_t enc_alg
, chunk_t enc_key
,
94 u_int16_t int_alg
, chunk_t int_key
, ipsec_mode_t mode
, u_int16_t ipcomp
,
95 u_int16_t cpi
, bool encap
, bool esn
, bool inbound
,
96 traffic_selector_t
* src_ts
, traffic_selector_t
* dst_ts
)
100 esp_spi_type spi_loc
, spi_rem
;
101 host_t
*local
, *peer
;
102 chunk_t
*nonce_loc
, *nonce_rem
;
103 nc_id_type nonce_loc_id
;
107 if (enc_key
.ptr
== NULL
)
109 DBG1(DBG_KNL
, "Unable to get ESA information");
112 esa
= *(esa_info_t
*)(enc_key
.ptr
);
114 /* only handle the case where we have both distinct ESP spi's available */
115 if (esa
.spi_r
== spi
)
117 chunk_free(&esa
.nonce_i
);
118 chunk_free(&esa
.nonce_r
);
122 /* Initiator if encr_r is passed as enc_key to the inbound add_sa call */
123 initiator
= esa
.is_encr_r
&& inbound
;
130 nonce_loc
= &esa
.nonce_i
;
131 nonce_rem
= &esa
.nonce_r
;
139 nonce_loc
= &esa
.nonce_r
;
140 nonce_rem
= &esa
.nonce_i
;
143 esa_id
= tkm
->idmgr
->acquire_id(tkm
->idmgr
, TKM_CTX_ESA
);
144 if (!this->sad
->insert(this->sad
, esa_id
, peer
, local
, spi_loc
, protocol
))
146 DBG1(DBG_KNL
, "unable to add entry (%llu) to SAD", esa_id
);
151 * creation of first CHILD SA:
152 * no nonce and no dh contexts because the ones from the IKE SA are re-used
154 nonce_loc_id
= tkm
->chunk_map
->get_id(tkm
->chunk_map
, nonce_loc
);
155 if (nonce_loc_id
== 0 && esa
.dh_id
== 0)
157 if (ike_esa_create_first(esa_id
, esa
.isa_id
, reqid
, 1, spi_loc
, spi_rem
)
160 DBG1(DBG_KNL
, "child SA (%llu, first) creation failed", esa_id
);
164 /* creation of child SA without PFS: no dh context */
165 else if (nonce_loc_id
!= 0 && esa
.dh_id
== 0)
167 chunk_to_sequence(nonce_rem
, &nc_rem
, sizeof(nonce_type
));
168 if (ike_esa_create_no_pfs(esa_id
, esa
.isa_id
, reqid
, 1, nonce_loc_id
,
169 nc_rem
, initiator
, spi_loc
, spi_rem
)
172 DBG1(DBG_KNL
, "child SA (%llu, no PFS) creation failed", esa_id
);
175 tkm
->idmgr
->release_id(tkm
->idmgr
, TKM_CTX_NONCE
, nonce_loc_id
);
177 /* creation of subsequent child SA with PFS: nonce and dh context are set */
180 chunk_to_sequence(nonce_rem
, &nc_rem
, sizeof(nonce_type
));
181 if (ike_esa_create(esa_id
, esa
.isa_id
, reqid
, 1, esa
.dh_id
, nonce_loc_id
,
182 nc_rem
, initiator
, spi_loc
, spi_rem
) != TKM_OK
)
184 DBG1(DBG_KNL
, "child SA (%llu) creation failed", esa_id
);
187 tkm
->idmgr
->release_id(tkm
->idmgr
, TKM_CTX_NONCE
, nonce_loc_id
);
189 if (ike_esa_select(esa_id
) != TKM_OK
)
191 DBG1(DBG_KNL
, "error selecting new child SA (%llu)", esa_id
);
192 if (ike_esa_reset(esa_id
) != TKM_OK
)
194 DBG1(DBG_KNL
, "child SA (%llu) deletion failed", esa_id
);
199 DBG1(DBG_KNL
, "added child SA (esa: %llu, isa: %llu, esp_spi_loc: %x, "
200 "esp_spi_rem: %x, role: %s)", esa_id
, esa
.isa_id
, ntohl(spi_loc
),
201 ntohl(spi_rem
), initiator ?
"initiator" : "responder");
202 chunk_free(&esa
.nonce_i
);
203 chunk_free(&esa
.nonce_r
);
208 this->sad
->remove(this->sad
, esa_id
);
210 tkm
->idmgr
->release_id(tkm
->idmgr
, TKM_CTX_ESA
, esa_id
);
211 chunk_free(&esa
.nonce_i
);
212 chunk_free(&esa
.nonce_r
);
216 METHOD(kernel_ipsec_t
, query_sa
, status_t
,
217 private_tkm_kernel_ipsec_t
*this, host_t
*src
, host_t
*dst
,
218 u_int32_t spi
, u_int8_t protocol
, mark_t mark
, u_int64_t
*bytes
,
221 return NOT_SUPPORTED
;
224 METHOD(kernel_ipsec_t
, del_sa
, status_t
,
225 private_tkm_kernel_ipsec_t
*this, host_t
*src
, host_t
*dst
,
226 u_int32_t spi
, u_int8_t protocol
, u_int16_t cpi
, mark_t mark
)
230 esa_id
= this->sad
->get_esa_id(this->sad
, src
, dst
, spi
, protocol
);
233 DBG1(DBG_KNL
, "deleting child SA (esa: %llu, spi: %x)", esa_id
,
235 if (ike_esa_reset(esa_id
) != TKM_OK
)
237 DBG1(DBG_KNL
, "child SA (%llu) deletion failed", esa_id
);
240 this->sad
->remove(this->sad
, esa_id
);
241 tkm
->idmgr
->release_id(tkm
->idmgr
, TKM_CTX_ESA
, esa_id
);
246 METHOD(kernel_ipsec_t
, update_sa
, status_t
,
247 private_tkm_kernel_ipsec_t
*this, u_int32_t spi
, u_int8_t protocol
,
248 u_int16_t cpi
, host_t
*src
, host_t
*dst
, host_t
*new_src
, host_t
*new_dst
,
249 bool old_encap
, bool new_encap
, mark_t mark
)
251 return NOT_SUPPORTED
;
254 METHOD(kernel_ipsec_t
, flush_sas
, status_t
,
255 private_tkm_kernel_ipsec_t
*this)
257 DBG1(DBG_KNL
, "flushing child SA entries");
261 METHOD(kernel_ipsec_t
, add_policy
, status_t
,
262 private_tkm_kernel_ipsec_t
*this, host_t
*src
, host_t
*dst
,
263 traffic_selector_t
*src_ts
, traffic_selector_t
*dst_ts
,
264 policy_dir_t direction
, policy_type_t type
, ipsec_sa_cfg_t
*sa
,
265 mark_t mark
, policy_priority_t priority
)
270 METHOD(kernel_ipsec_t
, query_policy
, status_t
,
271 private_tkm_kernel_ipsec_t
*this, traffic_selector_t
*src_ts
,
272 traffic_selector_t
*dst_ts
, policy_dir_t direction
, mark_t mark
,
275 return NOT_SUPPORTED
;
278 METHOD(kernel_ipsec_t
, del_policy
, status_t
,
279 private_tkm_kernel_ipsec_t
*this, traffic_selector_t
*src_ts
,
280 traffic_selector_t
*dst_ts
, policy_dir_t direction
, u_int32_t reqid
,
281 mark_t mark
, policy_priority_t prio
)
286 METHOD(kernel_ipsec_t
, flush_policies
, status_t
,
287 private_tkm_kernel_ipsec_t
*this)
293 METHOD(kernel_ipsec_t
, bypass_socket
, bool,
294 private_tkm_kernel_ipsec_t
*this, int fd
, int family
)
296 struct xfrm_userpolicy_info policy
;
297 u_int sol
, ipsec_policy
;
303 ipsec_policy
= IP_XFRM_POLICY
;
307 ipsec_policy
= IPV6_XFRM_POLICY
;
313 memset(&policy
, 0, sizeof(policy
));
314 policy
.action
= XFRM_POLICY_ALLOW
;
315 policy
.sel
.family
= family
;
317 policy
.dir
= XFRM_POLICY_OUT
;
318 if (setsockopt(fd
, sol
, ipsec_policy
, &policy
, sizeof(policy
)) < 0)
320 DBG1(DBG_KNL
, "unable to set IPSEC_POLICY on socket: %s",
324 policy
.dir
= XFRM_POLICY_IN
;
325 if (setsockopt(fd
, sol
, ipsec_policy
, &policy
, sizeof(policy
)) < 0)
327 DBG1(DBG_KNL
, "unable to set IPSEC_POLICY on socket: %s",
334 METHOD(kernel_ipsec_t
, enable_udp_decap
, bool,
335 private_tkm_kernel_ipsec_t
*this, int fd
, int family
, u_int16_t port
)
337 int type
= UDP_ENCAP_ESPINUDP
;
339 if (setsockopt(fd
, SOL_UDP
, UDP_ENCAP
, &type
, sizeof(type
)) < 0)
341 DBG1(DBG_KNL
, "unable to set UDP_ENCAP: %s", strerror(errno
));
347 METHOD(kernel_ipsec_t
, destroy
, void,
348 private_tkm_kernel_ipsec_t
*this)
350 DESTROY_IF(this->rng
);
351 DESTROY_IF(this->sad
);
356 * Described in header.
358 tkm_kernel_ipsec_t
*tkm_kernel_ipsec_create()
360 private_tkm_kernel_ipsec_t
*this;
368 .update_sa
= _update_sa
,
369 .query_sa
= _query_sa
,
371 .flush_sas
= _flush_sas
,
372 .add_policy
= _add_policy
,
373 .query_policy
= _query_policy
,
374 .del_policy
= _del_policy
,
375 .flush_policies
= _flush_policies
,
376 .bypass_socket
= _bypass_socket
,
377 .enable_udp_decap
= _enable_udp_decap
,
381 .sad
= tkm_kernel_sad_create(),
386 DBG1(DBG_KNL
, "unable to create SAD");
391 return &this->public;