1a9643ea8Slogwang /* $FreeBSD$ */
2a9643ea8Slogwang /* $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */
3a9643ea8Slogwang
4a9643ea8Slogwang /*-
5*22ce4affSfengbojiang * SPDX-License-Identifier: BSD-3-Clause
6*22ce4affSfengbojiang *
7a9643ea8Slogwang * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
8a9643ea8Slogwang * All rights reserved.
9a9643ea8Slogwang *
10a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without
11a9643ea8Slogwang * modification, are permitted provided that the following conditions
12a9643ea8Slogwang * are met:
13a9643ea8Slogwang * 1. Redistributions of source code must retain the above copyright
14a9643ea8Slogwang * notice, this list of conditions and the following disclaimer.
15a9643ea8Slogwang * 2. Redistributions in binary form must reproduce the above copyright
16a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in the
17a9643ea8Slogwang * documentation and/or other materials provided with the distribution.
18a9643ea8Slogwang * 3. Neither the name of the project nor the names of its contributors
19a9643ea8Slogwang * may be used to endorse or promote products derived from this software
20a9643ea8Slogwang * without specific prior written permission.
21a9643ea8Slogwang *
22a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
23a9643ea8Slogwang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24a9643ea8Slogwang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25a9643ea8Slogwang * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
26a9643ea8Slogwang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27a9643ea8Slogwang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28a9643ea8Slogwang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29a9643ea8Slogwang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30a9643ea8Slogwang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31a9643ea8Slogwang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32a9643ea8Slogwang * SUCH DAMAGE.
33a9643ea8Slogwang */
34a9643ea8Slogwang
35a9643ea8Slogwang /*
36a9643ea8Slogwang * IPsec controller part.
37a9643ea8Slogwang */
38a9643ea8Slogwang
39a9643ea8Slogwang #include "opt_inet.h"
40a9643ea8Slogwang #include "opt_inet6.h"
41a9643ea8Slogwang #include "opt_ipsec.h"
42a9643ea8Slogwang
43a9643ea8Slogwang #include <sys/param.h>
44a9643ea8Slogwang #include <sys/systm.h>
45a9643ea8Slogwang #include <sys/malloc.h>
46a9643ea8Slogwang #include <sys/mbuf.h>
47a9643ea8Slogwang #include <sys/domain.h>
48a9643ea8Slogwang #include <sys/priv.h>
49a9643ea8Slogwang #include <sys/protosw.h>
50a9643ea8Slogwang #include <sys/socket.h>
51a9643ea8Slogwang #include <sys/socketvar.h>
52a9643ea8Slogwang #include <sys/errno.h>
53a9643ea8Slogwang #include <sys/hhook.h>
54a9643ea8Slogwang #include <sys/time.h>
55a9643ea8Slogwang #include <sys/kernel.h>
56a9643ea8Slogwang #include <sys/syslog.h>
57a9643ea8Slogwang #include <sys/sysctl.h>
58a9643ea8Slogwang #include <sys/proc.h>
59a9643ea8Slogwang
60a9643ea8Slogwang #include <net/if.h>
61a9643ea8Slogwang #include <net/if_enc.h>
62a9643ea8Slogwang #include <net/if_var.h>
63a9643ea8Slogwang #include <net/vnet.h>
64a9643ea8Slogwang
65a9643ea8Slogwang #include <netinet/in.h>
66a9643ea8Slogwang #include <netinet/in_systm.h>
67a9643ea8Slogwang #include <netinet/ip.h>
68a9643ea8Slogwang #include <netinet/ip_var.h>
69a9643ea8Slogwang #include <netinet/in_var.h>
70a9643ea8Slogwang #include <netinet/udp.h>
71a9643ea8Slogwang #include <netinet/udp_var.h>
72a9643ea8Slogwang #include <netinet/tcp.h>
73a9643ea8Slogwang #include <netinet/udp.h>
74a9643ea8Slogwang
75a9643ea8Slogwang #include <netinet/ip6.h>
76a9643ea8Slogwang #ifdef INET6
77a9643ea8Slogwang #include <netinet6/ip6_var.h>
78a9643ea8Slogwang #endif
79a9643ea8Slogwang #include <netinet/in_pcb.h>
80a9643ea8Slogwang #ifdef INET6
81a9643ea8Slogwang #include <netinet/icmp6.h>
82a9643ea8Slogwang #endif
83a9643ea8Slogwang
84a9643ea8Slogwang #include <sys/types.h>
85a9643ea8Slogwang #include <netipsec/ipsec.h>
86a9643ea8Slogwang #ifdef INET6
87a9643ea8Slogwang #include <netipsec/ipsec6.h>
88a9643ea8Slogwang #endif
89a9643ea8Slogwang #include <netipsec/ah_var.h>
90a9643ea8Slogwang #include <netipsec/esp_var.h>
91a9643ea8Slogwang #include <netipsec/ipcomp.h> /*XXX*/
92a9643ea8Slogwang #include <netipsec/ipcomp_var.h>
93*22ce4affSfengbojiang #include <netipsec/ipsec_support.h>
94a9643ea8Slogwang
95a9643ea8Slogwang #include <netipsec/key.h>
96a9643ea8Slogwang #include <netipsec/keydb.h>
97a9643ea8Slogwang #include <netipsec/key_debug.h>
98a9643ea8Slogwang
99a9643ea8Slogwang #include <netipsec/xform.h>
100a9643ea8Slogwang
101a9643ea8Slogwang #include <machine/in_cksum.h>
102a9643ea8Slogwang
103a9643ea8Slogwang #include <opencrypto/cryptodev.h>
104a9643ea8Slogwang
105a9643ea8Slogwang /* NB: name changed so netstat doesn't use it. */
106a9643ea8Slogwang VNET_PCPUSTAT_DEFINE(struct ipsecstat, ipsec4stat);
107a9643ea8Slogwang VNET_PCPUSTAT_SYSINIT(ipsec4stat);
108a9643ea8Slogwang
109a9643ea8Slogwang #ifdef VIMAGE
110a9643ea8Slogwang VNET_PCPUSTAT_SYSUNINIT(ipsec4stat);
111a9643ea8Slogwang #endif /* VIMAGE */
112a9643ea8Slogwang
113a9643ea8Slogwang /* DF bit on encap. 0: clear 1: set 2: copy */
114a9643ea8Slogwang VNET_DEFINE(int, ip4_ipsec_dfbit) = 0;
115a9643ea8Slogwang VNET_DEFINE(int, ip4_esp_trans_deflev) = IPSEC_LEVEL_USE;
116a9643ea8Slogwang VNET_DEFINE(int, ip4_esp_net_deflev) = IPSEC_LEVEL_USE;
117a9643ea8Slogwang VNET_DEFINE(int, ip4_ah_trans_deflev) = IPSEC_LEVEL_USE;
118a9643ea8Slogwang VNET_DEFINE(int, ip4_ah_net_deflev) = IPSEC_LEVEL_USE;
119a9643ea8Slogwang /* ECN ignore(-1)/forbidden(0)/allowed(1) */
120a9643ea8Slogwang VNET_DEFINE(int, ip4_ipsec_ecn) = 0;
121a9643ea8Slogwang
122*22ce4affSfengbojiang VNET_DEFINE_STATIC(int, ip4_filtertunnel) = 0;
123*22ce4affSfengbojiang #define V_ip4_filtertunnel VNET(ip4_filtertunnel)
124*22ce4affSfengbojiang VNET_DEFINE_STATIC(int, check_policy_history) = 0;
125*22ce4affSfengbojiang #define V_check_policy_history VNET(check_policy_history)
126*22ce4affSfengbojiang VNET_DEFINE_STATIC(struct secpolicy *, def_policy) = NULL;
127a9643ea8Slogwang #define V_def_policy VNET(def_policy)
128*22ce4affSfengbojiang static int
sysctl_def_policy(SYSCTL_HANDLER_ARGS)129*22ce4affSfengbojiang sysctl_def_policy(SYSCTL_HANDLER_ARGS)
130*22ce4affSfengbojiang {
131*22ce4affSfengbojiang int error, value;
132*22ce4affSfengbojiang
133*22ce4affSfengbojiang value = V_def_policy->policy;
134*22ce4affSfengbojiang error = sysctl_handle_int(oidp, &value, 0, req);
135*22ce4affSfengbojiang if (error == 0) {
136*22ce4affSfengbojiang if (value != IPSEC_POLICY_DISCARD &&
137*22ce4affSfengbojiang value != IPSEC_POLICY_NONE)
138*22ce4affSfengbojiang return (EINVAL);
139*22ce4affSfengbojiang V_def_policy->policy = value;
140*22ce4affSfengbojiang }
141*22ce4affSfengbojiang return (error);
142*22ce4affSfengbojiang }
143*22ce4affSfengbojiang
144a9643ea8Slogwang /*
145a9643ea8Slogwang * Crypto support requirements:
146a9643ea8Slogwang *
147a9643ea8Slogwang * 1 require hardware support
148a9643ea8Slogwang * -1 require software support
149a9643ea8Slogwang * 0 take anything
150a9643ea8Slogwang */
151a9643ea8Slogwang VNET_DEFINE(int, crypto_support) = CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
152a9643ea8Slogwang
153*22ce4affSfengbojiang /*
154*22ce4affSfengbojiang * Use asynchronous mode to parallelize crypto jobs:
155*22ce4affSfengbojiang *
156*22ce4affSfengbojiang * 0 - disabled
157*22ce4affSfengbojiang * 1 - enabled
158*22ce4affSfengbojiang */
159*22ce4affSfengbojiang VNET_DEFINE(int, async_crypto) = 0;
160*22ce4affSfengbojiang
161*22ce4affSfengbojiang /*
162*22ce4affSfengbojiang * TCP/UDP checksum handling policy for transport mode NAT-T (RFC3948)
163*22ce4affSfengbojiang *
164*22ce4affSfengbojiang * 0 - auto: incrementally recompute, when checksum delta is known;
165*22ce4affSfengbojiang * if checksum delta isn't known, reset checksum to zero for UDP,
166*22ce4affSfengbojiang * and mark csum_flags as valid for TCP.
167*22ce4affSfengbojiang * 1 - fully recompute TCP/UDP checksum.
168*22ce4affSfengbojiang */
169*22ce4affSfengbojiang VNET_DEFINE(int, natt_cksum_policy) = 0;
170*22ce4affSfengbojiang
171a9643ea8Slogwang FEATURE(ipsec, "Internet Protocol Security (IPsec)");
172a9643ea8Slogwang FEATURE(ipsec_natt, "UDP Encapsulation of IPsec ESP Packets ('NAT-T')");
173a9643ea8Slogwang
174a9643ea8Slogwang SYSCTL_DECL(_net_inet_ipsec);
175a9643ea8Slogwang
176a9643ea8Slogwang /* net.inet.ipsec */
177*22ce4affSfengbojiang SYSCTL_PROC(_net_inet_ipsec, IPSECCTL_DEF_POLICY, def_policy,
178*22ce4affSfengbojiang CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
179*22ce4affSfengbojiang 0, 0, sysctl_def_policy, "I",
180a9643ea8Slogwang "IPsec default policy.");
181a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
182a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_esp_trans_deflev), 0,
183a9643ea8Slogwang "Default ESP transport mode level");
184a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
185a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_esp_net_deflev), 0,
186a9643ea8Slogwang "Default ESP tunnel mode level.");
187a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
188a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ah_trans_deflev), 0,
189a9643ea8Slogwang "AH transfer mode default level.");
190a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
191a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ah_net_deflev), 0,
192a9643ea8Slogwang "AH tunnel mode default level.");
193a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS, ah_cleartos,
194a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ah_cleartos), 0,
195*22ce4affSfengbojiang "If set, clear type-of-service field when doing AH computation.");
196a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT, dfbit,
197a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ipsec_dfbit), 0,
198a9643ea8Slogwang "Do not fragment bit on encap.");
199a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN, ecn,
200a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_ipsec_ecn), 0,
201a9643ea8Slogwang "Explicit Congestion Notification handling.");
202a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, OID_AUTO, crypto_support,
203a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(crypto_support), 0,
204a9643ea8Slogwang "Crypto driver selection.");
205*22ce4affSfengbojiang SYSCTL_INT(_net_inet_ipsec, OID_AUTO, async_crypto,
206*22ce4affSfengbojiang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(async_crypto), 0,
207*22ce4affSfengbojiang "Use asynchronous mode to parallelize crypto jobs.");
208*22ce4affSfengbojiang SYSCTL_INT(_net_inet_ipsec, OID_AUTO, check_policy_history,
209*22ce4affSfengbojiang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(check_policy_history), 0,
210*22ce4affSfengbojiang "Use strict check of inbound packets to security policy compliance.");
211*22ce4affSfengbojiang SYSCTL_INT(_net_inet_ipsec, OID_AUTO, natt_cksum_policy,
212*22ce4affSfengbojiang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(natt_cksum_policy), 0,
213*22ce4affSfengbojiang "Method to fix TCP/UDP checksum for transport mode IPsec after NAT.");
214*22ce4affSfengbojiang SYSCTL_INT(_net_inet_ipsec, OID_AUTO, filtertunnel,
215*22ce4affSfengbojiang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip4_filtertunnel), 0,
216*22ce4affSfengbojiang "If set, filter packets from an IPsec tunnel.");
217a9643ea8Slogwang SYSCTL_VNET_PCPUSTAT(_net_inet_ipsec, OID_AUTO, ipsecstats, struct ipsecstat,
218a9643ea8Slogwang ipsec4stat, "IPsec IPv4 statistics.");
219a9643ea8Slogwang
220a9643ea8Slogwang #ifdef REGRESSION
221a9643ea8Slogwang /*
222a9643ea8Slogwang * When set to 1, IPsec will send packets with the same sequence number.
223a9643ea8Slogwang * This allows to verify if the other side has proper replay attacks detection.
224a9643ea8Slogwang */
225a9643ea8Slogwang VNET_DEFINE(int, ipsec_replay) = 0;
226a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, OID_AUTO, test_replay,
227a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipsec_replay), 0,
228a9643ea8Slogwang "Emulate replay attack");
229a9643ea8Slogwang /*
230a9643ea8Slogwang * When set 1, IPsec will send packets with corrupted HMAC.
231a9643ea8Slogwang * This allows to verify if the other side properly detects modified packets.
232a9643ea8Slogwang */
233a9643ea8Slogwang VNET_DEFINE(int, ipsec_integrity) = 0;
234a9643ea8Slogwang SYSCTL_INT(_net_inet_ipsec, OID_AUTO, test_integrity,
235a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ipsec_integrity), 0,
236a9643ea8Slogwang "Emulate man-in-the-middle attack");
237a9643ea8Slogwang #endif
238a9643ea8Slogwang
239a9643ea8Slogwang #ifdef INET6
240a9643ea8Slogwang VNET_PCPUSTAT_DEFINE(struct ipsecstat, ipsec6stat);
241a9643ea8Slogwang VNET_PCPUSTAT_SYSINIT(ipsec6stat);
242a9643ea8Slogwang
243a9643ea8Slogwang #ifdef VIMAGE
244a9643ea8Slogwang VNET_PCPUSTAT_SYSUNINIT(ipsec6stat);
245a9643ea8Slogwang #endif /* VIMAGE */
246a9643ea8Slogwang
247a9643ea8Slogwang VNET_DEFINE(int, ip6_esp_trans_deflev) = IPSEC_LEVEL_USE;
248a9643ea8Slogwang VNET_DEFINE(int, ip6_esp_net_deflev) = IPSEC_LEVEL_USE;
249a9643ea8Slogwang VNET_DEFINE(int, ip6_ah_trans_deflev) = IPSEC_LEVEL_USE;
250a9643ea8Slogwang VNET_DEFINE(int, ip6_ah_net_deflev) = IPSEC_LEVEL_USE;
251a9643ea8Slogwang VNET_DEFINE(int, ip6_ipsec_ecn) = 0; /* ECN ignore(-1)/forbidden(0)/allowed(1) */
252a9643ea8Slogwang
253*22ce4affSfengbojiang VNET_DEFINE_STATIC(int, ip6_filtertunnel) = 0;
254*22ce4affSfengbojiang #define V_ip6_filtertunnel VNET(ip6_filtertunnel)
255*22ce4affSfengbojiang
256a9643ea8Slogwang SYSCTL_DECL(_net_inet6_ipsec6);
257a9643ea8Slogwang
258a9643ea8Slogwang /* net.inet6.ipsec6 */
259*22ce4affSfengbojiang SYSCTL_PROC(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY, def_policy,
260*22ce4affSfengbojiang CTLTYPE_INT | CTLFLAG_VNET | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
261*22ce4affSfengbojiang 0, 0, sysctl_def_policy, "I",
262a9643ea8Slogwang "IPsec default policy.");
263a9643ea8Slogwang SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
264a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_esp_trans_deflev), 0,
265a9643ea8Slogwang "Default ESP transport mode level.");
266a9643ea8Slogwang SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
267a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_esp_net_deflev), 0,
268a9643ea8Slogwang "Default ESP tunnel mode level.");
269a9643ea8Slogwang SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
270a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_ah_trans_deflev), 0,
271a9643ea8Slogwang "AH transfer mode default level.");
272a9643ea8Slogwang SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
273a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_ah_net_deflev), 0,
274a9643ea8Slogwang "AH tunnel mode default level.");
275a9643ea8Slogwang SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN, ecn,
276a9643ea8Slogwang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_ipsec_ecn), 0,
277a9643ea8Slogwang "Explicit Congestion Notification handling.");
278*22ce4affSfengbojiang SYSCTL_INT(_net_inet6_ipsec6, OID_AUTO, filtertunnel,
279*22ce4affSfengbojiang CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_filtertunnel), 0,
280*22ce4affSfengbojiang "If set, filter packets from an IPsec tunnel.");
281a9643ea8Slogwang SYSCTL_VNET_PCPUSTAT(_net_inet6_ipsec6, IPSECCTL_STATS, ipsecstats,
282a9643ea8Slogwang struct ipsecstat, ipsec6stat, "IPsec IPv6 statistics.");
283a9643ea8Slogwang #endif /* INET6 */
284a9643ea8Slogwang
285*22ce4affSfengbojiang static int ipsec_in_reject(struct secpolicy *, struct inpcb *,
286*22ce4affSfengbojiang const struct mbuf *);
287*22ce4affSfengbojiang
288*22ce4affSfengbojiang #ifdef INET
289*22ce4affSfengbojiang static void ipsec4_get_ulp(const struct mbuf *, struct secpolicyindex *, int);
290*22ce4affSfengbojiang static void ipsec4_setspidx_ipaddr(const struct mbuf *,
291*22ce4affSfengbojiang struct secpolicyindex *);
292*22ce4affSfengbojiang #endif
293a9643ea8Slogwang #ifdef INET6
294a9643ea8Slogwang static void ipsec6_get_ulp(const struct mbuf *m, struct secpolicyindex *, int);
295*22ce4affSfengbojiang static void ipsec6_setspidx_ipaddr(const struct mbuf *,
296*22ce4affSfengbojiang struct secpolicyindex *);
297a9643ea8Slogwang #endif
298a9643ea8Slogwang
299a9643ea8Slogwang /*
300a9643ea8Slogwang * Return a held reference to the default SP.
301a9643ea8Slogwang */
302a9643ea8Slogwang static struct secpolicy *
key_allocsp_default(void)303*22ce4affSfengbojiang key_allocsp_default(void)
304*22ce4affSfengbojiang {
305*22ce4affSfengbojiang
306*22ce4affSfengbojiang key_addref(V_def_policy);
307*22ce4affSfengbojiang return (V_def_policy);
308*22ce4affSfengbojiang }
309*22ce4affSfengbojiang
310*22ce4affSfengbojiang static void
ipsec_invalidate_cache(struct inpcb * inp,u_int dir)311*22ce4affSfengbojiang ipsec_invalidate_cache(struct inpcb *inp, u_int dir)
312a9643ea8Slogwang {
313a9643ea8Slogwang struct secpolicy *sp;
314a9643ea8Slogwang
315*22ce4affSfengbojiang INP_WLOCK_ASSERT(inp);
316*22ce4affSfengbojiang if (dir == IPSEC_DIR_OUTBOUND) {
317*22ce4affSfengbojiang if (inp->inp_sp->flags & INP_INBOUND_POLICY)
318*22ce4affSfengbojiang return;
319*22ce4affSfengbojiang sp = inp->inp_sp->sp_in;
320*22ce4affSfengbojiang inp->inp_sp->sp_in = NULL;
321*22ce4affSfengbojiang } else {
322*22ce4affSfengbojiang if (inp->inp_sp->flags & INP_OUTBOUND_POLICY)
323*22ce4affSfengbojiang return;
324*22ce4affSfengbojiang sp = inp->inp_sp->sp_out;
325*22ce4affSfengbojiang inp->inp_sp->sp_out = NULL;
326a9643ea8Slogwang }
327*22ce4affSfengbojiang if (sp != NULL)
328*22ce4affSfengbojiang key_freesp(&sp); /* release extra reference */
329a9643ea8Slogwang }
330a9643ea8Slogwang
331*22ce4affSfengbojiang static void
ipsec_cachepolicy(struct inpcb * inp,struct secpolicy * sp,u_int dir)332*22ce4affSfengbojiang ipsec_cachepolicy(struct inpcb *inp, struct secpolicy *sp, u_int dir)
333*22ce4affSfengbojiang {
334*22ce4affSfengbojiang uint32_t genid;
335*22ce4affSfengbojiang int downgrade;
336*22ce4affSfengbojiang
337*22ce4affSfengbojiang INP_LOCK_ASSERT(inp);
338*22ce4affSfengbojiang
339*22ce4affSfengbojiang if (dir == IPSEC_DIR_OUTBOUND) {
340*22ce4affSfengbojiang /* Do we have configured PCB policy? */
341*22ce4affSfengbojiang if (inp->inp_sp->flags & INP_OUTBOUND_POLICY)
342*22ce4affSfengbojiang return;
343*22ce4affSfengbojiang /* Another thread has already set cached policy */
344*22ce4affSfengbojiang if (inp->inp_sp->sp_out != NULL)
345*22ce4affSfengbojiang return;
346a9643ea8Slogwang /*
347*22ce4affSfengbojiang * Do not cache OUTBOUND policy if PCB isn't connected,
348*22ce4affSfengbojiang * i.e. foreign address is INADDR_ANY/UNSPECIFIED.
349a9643ea8Slogwang */
350*22ce4affSfengbojiang #ifdef INET
351*22ce4affSfengbojiang if ((inp->inp_vflag & INP_IPV4) != 0 &&
352*22ce4affSfengbojiang inp->inp_faddr.s_addr == INADDR_ANY)
353*22ce4affSfengbojiang return;
354*22ce4affSfengbojiang #endif
355*22ce4affSfengbojiang #ifdef INET6
356*22ce4affSfengbojiang if ((inp->inp_vflag & INP_IPV6) != 0 &&
357*22ce4affSfengbojiang IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
358*22ce4affSfengbojiang return;
359*22ce4affSfengbojiang #endif
360*22ce4affSfengbojiang } else {
361*22ce4affSfengbojiang /* Do we have configured PCB policy? */
362*22ce4affSfengbojiang if (inp->inp_sp->flags & INP_INBOUND_POLICY)
363*22ce4affSfengbojiang return;
364*22ce4affSfengbojiang /* Another thread has already set cached policy */
365*22ce4affSfengbojiang if (inp->inp_sp->sp_in != NULL)
366*22ce4affSfengbojiang return;
367a9643ea8Slogwang /*
368*22ce4affSfengbojiang * Do not cache INBOUND policy for listen socket,
369*22ce4affSfengbojiang * that is bound to INADDR_ANY/UNSPECIFIED address.
370a9643ea8Slogwang */
371*22ce4affSfengbojiang #ifdef INET
372*22ce4affSfengbojiang if ((inp->inp_vflag & INP_IPV4) != 0 &&
373*22ce4affSfengbojiang inp->inp_faddr.s_addr == INADDR_ANY)
374*22ce4affSfengbojiang return;
375*22ce4affSfengbojiang #endif
376*22ce4affSfengbojiang #ifdef INET6
377*22ce4affSfengbojiang if ((inp->inp_vflag & INP_IPV6) != 0 &&
378*22ce4affSfengbojiang IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
379*22ce4affSfengbojiang return;
380*22ce4affSfengbojiang #endif
381a9643ea8Slogwang }
382*22ce4affSfengbojiang downgrade = 0;
383*22ce4affSfengbojiang if (!INP_WLOCKED(inp)) {
384*22ce4affSfengbojiang if ((downgrade = INP_TRY_UPGRADE(inp)) == 0)
385*22ce4affSfengbojiang return;
386a9643ea8Slogwang }
387*22ce4affSfengbojiang if (dir == IPSEC_DIR_OUTBOUND)
388*22ce4affSfengbojiang inp->inp_sp->sp_out = sp;
389a9643ea8Slogwang else
390*22ce4affSfengbojiang inp->inp_sp->sp_in = sp;
391*22ce4affSfengbojiang /*
392*22ce4affSfengbojiang * SP is already referenced by the lookup code.
393*22ce4affSfengbojiang * We take extra reference here to avoid race in the
394*22ce4affSfengbojiang * ipsec_getpcbpolicy() function - SP will not be freed in the
395*22ce4affSfengbojiang * time between we take SP pointer from the cache and key_addref()
396*22ce4affSfengbojiang * call.
397*22ce4affSfengbojiang */
398*22ce4affSfengbojiang key_addref(sp);
399*22ce4affSfengbojiang genid = key_getspgen();
400*22ce4affSfengbojiang if (genid != inp->inp_sp->genid) {
401*22ce4affSfengbojiang ipsec_invalidate_cache(inp, dir);
402*22ce4affSfengbojiang inp->inp_sp->genid = genid;
403a9643ea8Slogwang }
404*22ce4affSfengbojiang KEYDBG(IPSEC_STAMP,
405*22ce4affSfengbojiang printf("%s: PCB(%p): cached %s SP(%p)\n",
406*22ce4affSfengbojiang __func__, inp, dir == IPSEC_DIR_OUTBOUND ? "OUTBOUND":
407*22ce4affSfengbojiang "INBOUND", sp));
408*22ce4affSfengbojiang if (downgrade != 0)
409*22ce4affSfengbojiang INP_DOWNGRADE(inp);
410*22ce4affSfengbojiang }
411*22ce4affSfengbojiang
412*22ce4affSfengbojiang static struct secpolicy *
ipsec_checkpolicy(struct secpolicy * sp,struct inpcb * inp,int * error)413*22ce4affSfengbojiang ipsec_checkpolicy(struct secpolicy *sp, struct inpcb *inp, int *error)
414*22ce4affSfengbojiang {
415*22ce4affSfengbojiang
416*22ce4affSfengbojiang /* Save found OUTBOUND policy into PCB SP cache. */
417*22ce4affSfengbojiang if (inp != NULL && inp->inp_sp != NULL && inp->inp_sp->sp_out == NULL)
418*22ce4affSfengbojiang ipsec_cachepolicy(inp, sp, IPSEC_DIR_OUTBOUND);
419*22ce4affSfengbojiang
420a9643ea8Slogwang switch (sp->policy) {
421a9643ea8Slogwang default:
422a9643ea8Slogwang printf("%s: invalid policy %u\n", __func__, sp->policy);
423a9643ea8Slogwang /* FALLTHROUGH */
424a9643ea8Slogwang case IPSEC_POLICY_DISCARD:
425a9643ea8Slogwang *error = -EINVAL; /* Packet is discarded by caller. */
426*22ce4affSfengbojiang /* FALLTHROUGH */
427a9643ea8Slogwang case IPSEC_POLICY_BYPASS:
428a9643ea8Slogwang case IPSEC_POLICY_NONE:
429*22ce4affSfengbojiang key_freesp(&sp);
430a9643ea8Slogwang sp = NULL; /* NB: force NULL result. */
431a9643ea8Slogwang break;
432a9643ea8Slogwang case IPSEC_POLICY_IPSEC:
433*22ce4affSfengbojiang /* XXXAE: handle LARVAL SP */
434a9643ea8Slogwang break;
435a9643ea8Slogwang }
436*22ce4affSfengbojiang KEYDBG(IPSEC_DUMP,
437*22ce4affSfengbojiang printf("%s: get SP(%p), error %d\n", __func__, sp, *error));
438a9643ea8Slogwang return (sp);
439a9643ea8Slogwang }
440a9643ea8Slogwang
441*22ce4affSfengbojiang static struct secpolicy *
ipsec_getpcbpolicy(struct inpcb * inp,u_int dir)442*22ce4affSfengbojiang ipsec_getpcbpolicy(struct inpcb *inp, u_int dir)
443a9643ea8Slogwang {
444*22ce4affSfengbojiang struct secpolicy *sp;
445*22ce4affSfengbojiang int flags, downgrade;
446a9643ea8Slogwang
447*22ce4affSfengbojiang if (inp == NULL || inp->inp_sp == NULL)
448*22ce4affSfengbojiang return (NULL);
449a9643ea8Slogwang
450*22ce4affSfengbojiang INP_LOCK_ASSERT(inp);
451*22ce4affSfengbojiang
452*22ce4affSfengbojiang flags = inp->inp_sp->flags;
453*22ce4affSfengbojiang if (dir == IPSEC_DIR_OUTBOUND) {
454*22ce4affSfengbojiang sp = inp->inp_sp->sp_out;
455*22ce4affSfengbojiang flags &= INP_OUTBOUND_POLICY;
456a9643ea8Slogwang } else {
457*22ce4affSfengbojiang sp = inp->inp_sp->sp_in;
458*22ce4affSfengbojiang flags &= INP_INBOUND_POLICY;
459a9643ea8Slogwang }
460a9643ea8Slogwang /*
461*22ce4affSfengbojiang * Check flags. If we have PCB SP, just return it.
462*22ce4affSfengbojiang * Otherwise we need to check that cached SP entry isn't stale.
463a9643ea8Slogwang */
464*22ce4affSfengbojiang if (flags == 0) {
465*22ce4affSfengbojiang if (sp == NULL)
466*22ce4affSfengbojiang return (NULL);
467*22ce4affSfengbojiang if (inp->inp_sp->genid != key_getspgen()) {
468*22ce4affSfengbojiang /* Invalidate the cache. */
469*22ce4affSfengbojiang downgrade = 0;
470*22ce4affSfengbojiang if (!INP_WLOCKED(inp)) {
471*22ce4affSfengbojiang if ((downgrade = INP_TRY_UPGRADE(inp)) == 0)
472*22ce4affSfengbojiang return (NULL);
473*22ce4affSfengbojiang }
474*22ce4affSfengbojiang ipsec_invalidate_cache(inp, IPSEC_DIR_OUTBOUND);
475*22ce4affSfengbojiang ipsec_invalidate_cache(inp, IPSEC_DIR_INBOUND);
476*22ce4affSfengbojiang if (downgrade != 0)
477*22ce4affSfengbojiang INP_DOWNGRADE(inp);
478*22ce4affSfengbojiang return (NULL);
479*22ce4affSfengbojiang }
480*22ce4affSfengbojiang KEYDBG(IPSEC_STAMP,
481*22ce4affSfengbojiang printf("%s: PCB(%p): cache hit SP(%p)\n",
482*22ce4affSfengbojiang __func__, inp, sp));
483*22ce4affSfengbojiang /* Return referenced cached policy */
484*22ce4affSfengbojiang }
485*22ce4affSfengbojiang key_addref(sp);
486*22ce4affSfengbojiang return (sp);
487a9643ea8Slogwang }
488a9643ea8Slogwang
489*22ce4affSfengbojiang #ifdef INET
490a9643ea8Slogwang static void
ipsec4_get_ulp(const struct mbuf * m,struct secpolicyindex * spidx,int needport)491a9643ea8Slogwang ipsec4_get_ulp(const struct mbuf *m, struct secpolicyindex *spidx,
492a9643ea8Slogwang int needport)
493a9643ea8Slogwang {
494*22ce4affSfengbojiang uint8_t nxt;
495a9643ea8Slogwang int off;
496a9643ea8Slogwang
497a9643ea8Slogwang /* Sanity check. */
498*22ce4affSfengbojiang IPSEC_ASSERT(m->m_pkthdr.len >= sizeof(struct ip),
499*22ce4affSfengbojiang ("packet too short"));
500a9643ea8Slogwang
501a9643ea8Slogwang if (m->m_len >= sizeof (struct ip)) {
502a9643ea8Slogwang const struct ip *ip = mtod(m, const struct ip *);
503a9643ea8Slogwang if (ip->ip_off & htons(IP_MF | IP_OFFMASK))
504a9643ea8Slogwang goto done;
505a9643ea8Slogwang off = ip->ip_hl << 2;
506a9643ea8Slogwang nxt = ip->ip_p;
507a9643ea8Slogwang } else {
508a9643ea8Slogwang struct ip ih;
509a9643ea8Slogwang
510a9643ea8Slogwang m_copydata(m, 0, sizeof (struct ip), (caddr_t) &ih);
511a9643ea8Slogwang if (ih.ip_off & htons(IP_MF | IP_OFFMASK))
512a9643ea8Slogwang goto done;
513a9643ea8Slogwang off = ih.ip_hl << 2;
514a9643ea8Slogwang nxt = ih.ip_p;
515a9643ea8Slogwang }
516a9643ea8Slogwang
517a9643ea8Slogwang while (off < m->m_pkthdr.len) {
518a9643ea8Slogwang struct ip6_ext ip6e;
519a9643ea8Slogwang struct tcphdr th;
520a9643ea8Slogwang struct udphdr uh;
521a9643ea8Slogwang
522a9643ea8Slogwang switch (nxt) {
523a9643ea8Slogwang case IPPROTO_TCP:
524a9643ea8Slogwang spidx->ul_proto = nxt;
525a9643ea8Slogwang if (!needport)
526a9643ea8Slogwang goto done_proto;
527a9643ea8Slogwang if (off + sizeof(struct tcphdr) > m->m_pkthdr.len)
528a9643ea8Slogwang goto done;
529a9643ea8Slogwang m_copydata(m, off, sizeof (th), (caddr_t) &th);
530a9643ea8Slogwang spidx->src.sin.sin_port = th.th_sport;
531a9643ea8Slogwang spidx->dst.sin.sin_port = th.th_dport;
532a9643ea8Slogwang return;
533a9643ea8Slogwang case IPPROTO_UDP:
534a9643ea8Slogwang spidx->ul_proto = nxt;
535a9643ea8Slogwang if (!needport)
536a9643ea8Slogwang goto done_proto;
537a9643ea8Slogwang if (off + sizeof(struct udphdr) > m->m_pkthdr.len)
538a9643ea8Slogwang goto done;
539a9643ea8Slogwang m_copydata(m, off, sizeof (uh), (caddr_t) &uh);
540a9643ea8Slogwang spidx->src.sin.sin_port = uh.uh_sport;
541a9643ea8Slogwang spidx->dst.sin.sin_port = uh.uh_dport;
542a9643ea8Slogwang return;
543a9643ea8Slogwang case IPPROTO_AH:
544a9643ea8Slogwang if (off + sizeof(ip6e) > m->m_pkthdr.len)
545a9643ea8Slogwang goto done;
546a9643ea8Slogwang /* XXX Sigh, this works but is totally bogus. */
547a9643ea8Slogwang m_copydata(m, off, sizeof(ip6e), (caddr_t) &ip6e);
548a9643ea8Slogwang off += (ip6e.ip6e_len + 2) << 2;
549a9643ea8Slogwang nxt = ip6e.ip6e_nxt;
550a9643ea8Slogwang break;
551a9643ea8Slogwang case IPPROTO_ICMP:
552a9643ea8Slogwang default:
553a9643ea8Slogwang /* XXX Intermediate headers??? */
554a9643ea8Slogwang spidx->ul_proto = nxt;
555a9643ea8Slogwang goto done_proto;
556a9643ea8Slogwang }
557a9643ea8Slogwang }
558a9643ea8Slogwang done:
559a9643ea8Slogwang spidx->ul_proto = IPSEC_ULPROTO_ANY;
560a9643ea8Slogwang done_proto:
561a9643ea8Slogwang spidx->src.sin.sin_port = IPSEC_PORT_ANY;
562a9643ea8Slogwang spidx->dst.sin.sin_port = IPSEC_PORT_ANY;
563*22ce4affSfengbojiang KEYDBG(IPSEC_DUMP,
564*22ce4affSfengbojiang printf("%s: ", __func__); kdebug_secpolicyindex(spidx, NULL));
565a9643ea8Slogwang }
566a9643ea8Slogwang
567*22ce4affSfengbojiang static void
ipsec4_setspidx_ipaddr(const struct mbuf * m,struct secpolicyindex * spidx)568a9643ea8Slogwang ipsec4_setspidx_ipaddr(const struct mbuf *m, struct secpolicyindex *spidx)
569a9643ea8Slogwang {
570a9643ea8Slogwang
571*22ce4affSfengbojiang ipsec4_setsockaddrs(m, &spidx->src, &spidx->dst);
572a9643ea8Slogwang spidx->prefs = sizeof(struct in_addr) << 3;
573a9643ea8Slogwang spidx->prefd = sizeof(struct in_addr) << 3;
574a9643ea8Slogwang }
575a9643ea8Slogwang
576*22ce4affSfengbojiang static struct secpolicy *
ipsec4_getpolicy(const struct mbuf * m,struct inpcb * inp,u_int dir,int needport)577*22ce4affSfengbojiang ipsec4_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir,
578*22ce4affSfengbojiang int needport)
579*22ce4affSfengbojiang {
580*22ce4affSfengbojiang struct secpolicyindex spidx;
581*22ce4affSfengbojiang struct secpolicy *sp;
582*22ce4affSfengbojiang
583*22ce4affSfengbojiang sp = ipsec_getpcbpolicy(inp, dir);
584*22ce4affSfengbojiang if (sp == NULL && key_havesp(dir)) {
585*22ce4affSfengbojiang /* Make an index to look for a policy. */
586*22ce4affSfengbojiang ipsec4_setspidx_ipaddr(m, &spidx);
587*22ce4affSfengbojiang ipsec4_get_ulp(m, &spidx, needport);
588*22ce4affSfengbojiang spidx.dir = dir;
589*22ce4affSfengbojiang sp = key_allocsp(&spidx, dir);
590*22ce4affSfengbojiang }
591*22ce4affSfengbojiang if (sp == NULL) /* No SP found, use system default. */
592*22ce4affSfengbojiang sp = key_allocsp_default();
593*22ce4affSfengbojiang return (sp);
594*22ce4affSfengbojiang }
595*22ce4affSfengbojiang
596*22ce4affSfengbojiang /*
597*22ce4affSfengbojiang * Check security policy for *OUTBOUND* IPv4 packet.
598*22ce4affSfengbojiang */
599*22ce4affSfengbojiang struct secpolicy *
ipsec4_checkpolicy(const struct mbuf * m,struct inpcb * inp,int * error,int needport)600*22ce4affSfengbojiang ipsec4_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error,
601*22ce4affSfengbojiang int needport)
602*22ce4affSfengbojiang {
603*22ce4affSfengbojiang struct secpolicy *sp;
604*22ce4affSfengbojiang
605*22ce4affSfengbojiang *error = 0;
606*22ce4affSfengbojiang sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_OUTBOUND, needport);
607*22ce4affSfengbojiang if (sp != NULL)
608*22ce4affSfengbojiang sp = ipsec_checkpolicy(sp, inp, error);
609*22ce4affSfengbojiang if (sp == NULL) {
610*22ce4affSfengbojiang switch (*error) {
611*22ce4affSfengbojiang case 0: /* No IPsec required: BYPASS or NONE */
612*22ce4affSfengbojiang break;
613*22ce4affSfengbojiang case -EINVAL:
614*22ce4affSfengbojiang IPSECSTAT_INC(ips_out_polvio);
615*22ce4affSfengbojiang break;
616*22ce4affSfengbojiang default:
617*22ce4affSfengbojiang IPSECSTAT_INC(ips_out_inval);
618*22ce4affSfengbojiang }
619*22ce4affSfengbojiang }
620*22ce4affSfengbojiang KEYDBG(IPSEC_STAMP,
621*22ce4affSfengbojiang printf("%s: using SP(%p), error %d\n", __func__, sp, *error));
622*22ce4affSfengbojiang if (sp != NULL)
623*22ce4affSfengbojiang KEYDBG(IPSEC_DATA, kdebug_secpolicy(sp));
624*22ce4affSfengbojiang return (sp);
625*22ce4affSfengbojiang }
626*22ce4affSfengbojiang
627*22ce4affSfengbojiang /*
628*22ce4affSfengbojiang * Check IPv4 packet against *INBOUND* security policy.
629*22ce4affSfengbojiang * This function is called from tcp_input(), udp_input(),
630*22ce4affSfengbojiang * rip_input() and sctp_input().
631*22ce4affSfengbojiang */
632*22ce4affSfengbojiang int
ipsec4_in_reject(const struct mbuf * m,struct inpcb * inp)633*22ce4affSfengbojiang ipsec4_in_reject(const struct mbuf *m, struct inpcb *inp)
634*22ce4affSfengbojiang {
635*22ce4affSfengbojiang struct secpolicy *sp;
636*22ce4affSfengbojiang int result;
637*22ce4affSfengbojiang
638*22ce4affSfengbojiang sp = ipsec4_getpolicy(m, inp, IPSEC_DIR_INBOUND, 0);
639*22ce4affSfengbojiang result = ipsec_in_reject(sp, inp, m);
640*22ce4affSfengbojiang key_freesp(&sp);
641*22ce4affSfengbojiang if (result != 0)
642*22ce4affSfengbojiang IPSECSTAT_INC(ips_in_polvio);
643*22ce4affSfengbojiang return (result);
644*22ce4affSfengbojiang }
645*22ce4affSfengbojiang
646*22ce4affSfengbojiang /*
647*22ce4affSfengbojiang * IPSEC_CAP() method implementation for IPv4.
648*22ce4affSfengbojiang */
649*22ce4affSfengbojiang int
ipsec4_capability(struct mbuf * m,u_int cap)650*22ce4affSfengbojiang ipsec4_capability(struct mbuf *m, u_int cap)
651*22ce4affSfengbojiang {
652*22ce4affSfengbojiang
653*22ce4affSfengbojiang switch (cap) {
654*22ce4affSfengbojiang case IPSEC_CAP_BYPASS_FILTER:
655*22ce4affSfengbojiang /*
656*22ce4affSfengbojiang * Bypass packet filtering for packets previously handled
657*22ce4affSfengbojiang * by IPsec.
658*22ce4affSfengbojiang */
659*22ce4affSfengbojiang if (!V_ip4_filtertunnel &&
660*22ce4affSfengbojiang m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL)
661*22ce4affSfengbojiang return (1);
662*22ce4affSfengbojiang return (0);
663*22ce4affSfengbojiang case IPSEC_CAP_OPERABLE:
664*22ce4affSfengbojiang /* Do we have active security policies? */
665*22ce4affSfengbojiang if (key_havesp(IPSEC_DIR_INBOUND) != 0 ||
666*22ce4affSfengbojiang key_havesp(IPSEC_DIR_OUTBOUND) != 0)
667*22ce4affSfengbojiang return (1);
668*22ce4affSfengbojiang return (0);
669*22ce4affSfengbojiang };
670*22ce4affSfengbojiang return (EOPNOTSUPP);
671*22ce4affSfengbojiang }
672*22ce4affSfengbojiang
673*22ce4affSfengbojiang #endif /* INET */
674*22ce4affSfengbojiang
675a9643ea8Slogwang #ifdef INET6
676a9643ea8Slogwang static void
ipsec6_get_ulp(const struct mbuf * m,struct secpolicyindex * spidx,int needport)677a9643ea8Slogwang ipsec6_get_ulp(const struct mbuf *m, struct secpolicyindex *spidx,
678a9643ea8Slogwang int needport)
679a9643ea8Slogwang {
680a9643ea8Slogwang struct tcphdr th;
681a9643ea8Slogwang struct udphdr uh;
682a9643ea8Slogwang struct icmp6_hdr ih;
683*22ce4affSfengbojiang int off, nxt;
684a9643ea8Slogwang
685*22ce4affSfengbojiang IPSEC_ASSERT(m->m_pkthdr.len >= sizeof(struct ip6_hdr),
686*22ce4affSfengbojiang ("packet too short"));
687a9643ea8Slogwang
688a9643ea8Slogwang /* Set default. */
689a9643ea8Slogwang spidx->ul_proto = IPSEC_ULPROTO_ANY;
690*22ce4affSfengbojiang spidx->src.sin6.sin6_port = IPSEC_PORT_ANY;
691*22ce4affSfengbojiang spidx->dst.sin6.sin6_port = IPSEC_PORT_ANY;
692a9643ea8Slogwang
693a9643ea8Slogwang nxt = -1;
694a9643ea8Slogwang off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
695a9643ea8Slogwang if (off < 0 || m->m_pkthdr.len < off)
696a9643ea8Slogwang return;
697a9643ea8Slogwang
698a9643ea8Slogwang switch (nxt) {
699a9643ea8Slogwang case IPPROTO_TCP:
700a9643ea8Slogwang spidx->ul_proto = nxt;
701a9643ea8Slogwang if (!needport)
702a9643ea8Slogwang break;
703a9643ea8Slogwang if (off + sizeof(struct tcphdr) > m->m_pkthdr.len)
704a9643ea8Slogwang break;
705a9643ea8Slogwang m_copydata(m, off, sizeof(th), (caddr_t)&th);
706*22ce4affSfengbojiang spidx->src.sin6.sin6_port = th.th_sport;
707*22ce4affSfengbojiang spidx->dst.sin6.sin6_port = th.th_dport;
708a9643ea8Slogwang break;
709a9643ea8Slogwang case IPPROTO_UDP:
710a9643ea8Slogwang spidx->ul_proto = nxt;
711a9643ea8Slogwang if (!needport)
712a9643ea8Slogwang break;
713a9643ea8Slogwang if (off + sizeof(struct udphdr) > m->m_pkthdr.len)
714a9643ea8Slogwang break;
715a9643ea8Slogwang m_copydata(m, off, sizeof(uh), (caddr_t)&uh);
716*22ce4affSfengbojiang spidx->src.sin6.sin6_port = uh.uh_sport;
717*22ce4affSfengbojiang spidx->dst.sin6.sin6_port = uh.uh_dport;
718a9643ea8Slogwang break;
719a9643ea8Slogwang case IPPROTO_ICMPV6:
720a9643ea8Slogwang spidx->ul_proto = nxt;
721a9643ea8Slogwang if (off + sizeof(struct icmp6_hdr) > m->m_pkthdr.len)
722a9643ea8Slogwang break;
723a9643ea8Slogwang m_copydata(m, off, sizeof(ih), (caddr_t)&ih);
724*22ce4affSfengbojiang spidx->src.sin6.sin6_port = htons((uint16_t)ih.icmp6_type);
725*22ce4affSfengbojiang spidx->dst.sin6.sin6_port = htons((uint16_t)ih.icmp6_code);
726a9643ea8Slogwang break;
727a9643ea8Slogwang default:
728a9643ea8Slogwang /* XXX Intermediate headers??? */
729a9643ea8Slogwang spidx->ul_proto = nxt;
730a9643ea8Slogwang break;
731a9643ea8Slogwang }
732*22ce4affSfengbojiang KEYDBG(IPSEC_DUMP,
733*22ce4affSfengbojiang printf("%s: ", __func__); kdebug_secpolicyindex(spidx, NULL));
734a9643ea8Slogwang }
735a9643ea8Slogwang
736*22ce4affSfengbojiang static void
ipsec6_setspidx_ipaddr(const struct mbuf * m,struct secpolicyindex * spidx)737a9643ea8Slogwang ipsec6_setspidx_ipaddr(const struct mbuf *m, struct secpolicyindex *spidx)
738a9643ea8Slogwang {
739a9643ea8Slogwang
740*22ce4affSfengbojiang ipsec6_setsockaddrs(m, &spidx->src, &spidx->dst);
741a9643ea8Slogwang spidx->prefs = sizeof(struct in6_addr) << 3;
742a9643ea8Slogwang spidx->prefd = sizeof(struct in6_addr) << 3;
743a9643ea8Slogwang }
744*22ce4affSfengbojiang
745*22ce4affSfengbojiang static struct secpolicy *
ipsec6_getpolicy(const struct mbuf * m,struct inpcb * inp,u_int dir,int needport)746*22ce4affSfengbojiang ipsec6_getpolicy(const struct mbuf *m, struct inpcb *inp, u_int dir,
747*22ce4affSfengbojiang int needport)
748*22ce4affSfengbojiang {
749*22ce4affSfengbojiang struct secpolicyindex spidx;
750*22ce4affSfengbojiang struct secpolicy *sp;
751*22ce4affSfengbojiang
752*22ce4affSfengbojiang sp = ipsec_getpcbpolicy(inp, dir);
753*22ce4affSfengbojiang if (sp == NULL && key_havesp(dir)) {
754*22ce4affSfengbojiang /* Make an index to look for a policy. */
755*22ce4affSfengbojiang ipsec6_setspidx_ipaddr(m, &spidx);
756*22ce4affSfengbojiang ipsec6_get_ulp(m, &spidx, needport);
757*22ce4affSfengbojiang spidx.dir = dir;
758*22ce4affSfengbojiang sp = key_allocsp(&spidx, dir);
759*22ce4affSfengbojiang }
760*22ce4affSfengbojiang if (sp == NULL) /* No SP found, use system default. */
761*22ce4affSfengbojiang sp = key_allocsp_default();
762*22ce4affSfengbojiang return (sp);
763*22ce4affSfengbojiang }
764*22ce4affSfengbojiang
765*22ce4affSfengbojiang /*
766*22ce4affSfengbojiang * Check security policy for *OUTBOUND* IPv6 packet.
767*22ce4affSfengbojiang */
768*22ce4affSfengbojiang struct secpolicy *
ipsec6_checkpolicy(const struct mbuf * m,struct inpcb * inp,int * error,int needport)769*22ce4affSfengbojiang ipsec6_checkpolicy(const struct mbuf *m, struct inpcb *inp, int *error,
770*22ce4affSfengbojiang int needport)
771*22ce4affSfengbojiang {
772*22ce4affSfengbojiang struct secpolicy *sp;
773*22ce4affSfengbojiang
774*22ce4affSfengbojiang *error = 0;
775*22ce4affSfengbojiang sp = ipsec6_getpolicy(m, inp, IPSEC_DIR_OUTBOUND, needport);
776*22ce4affSfengbojiang if (sp != NULL)
777*22ce4affSfengbojiang sp = ipsec_checkpolicy(sp, inp, error);
778*22ce4affSfengbojiang if (sp == NULL) {
779*22ce4affSfengbojiang switch (*error) {
780*22ce4affSfengbojiang case 0: /* No IPsec required: BYPASS or NONE */
781*22ce4affSfengbojiang break;
782*22ce4affSfengbojiang case -EINVAL:
783*22ce4affSfengbojiang IPSEC6STAT_INC(ips_out_polvio);
784*22ce4affSfengbojiang break;
785*22ce4affSfengbojiang default:
786*22ce4affSfengbojiang IPSEC6STAT_INC(ips_out_inval);
787*22ce4affSfengbojiang }
788*22ce4affSfengbojiang }
789*22ce4affSfengbojiang KEYDBG(IPSEC_STAMP,
790*22ce4affSfengbojiang printf("%s: using SP(%p), error %d\n", __func__, sp, *error));
791*22ce4affSfengbojiang if (sp != NULL)
792*22ce4affSfengbojiang KEYDBG(IPSEC_DATA, kdebug_secpolicy(sp));
793*22ce4affSfengbojiang return (sp);
794*22ce4affSfengbojiang }
795*22ce4affSfengbojiang
796*22ce4affSfengbojiang /*
797*22ce4affSfengbojiang * Check IPv6 packet against inbound security policy.
798*22ce4affSfengbojiang * This function is called from tcp6_input(), udp6_input(),
799*22ce4affSfengbojiang * rip6_input() and sctp_input().
800*22ce4affSfengbojiang */
801*22ce4affSfengbojiang int
ipsec6_in_reject(const struct mbuf * m,struct inpcb * inp)802*22ce4affSfengbojiang ipsec6_in_reject(const struct mbuf *m, struct inpcb *inp)
803*22ce4affSfengbojiang {
804*22ce4affSfengbojiang struct secpolicy *sp;
805*22ce4affSfengbojiang int result;
806*22ce4affSfengbojiang
807*22ce4affSfengbojiang sp = ipsec6_getpolicy(m, inp, IPSEC_DIR_INBOUND, 0);
808*22ce4affSfengbojiang result = ipsec_in_reject(sp, inp, m);
809*22ce4affSfengbojiang key_freesp(&sp);
810*22ce4affSfengbojiang if (result)
811*22ce4affSfengbojiang IPSEC6STAT_INC(ips_in_polvio);
812*22ce4affSfengbojiang return (result);
813*22ce4affSfengbojiang }
814*22ce4affSfengbojiang
815*22ce4affSfengbojiang /*
816*22ce4affSfengbojiang * IPSEC_CAP() method implementation for IPv6.
817*22ce4affSfengbojiang */
818*22ce4affSfengbojiang int
ipsec6_capability(struct mbuf * m,u_int cap)819*22ce4affSfengbojiang ipsec6_capability(struct mbuf *m, u_int cap)
820*22ce4affSfengbojiang {
821*22ce4affSfengbojiang
822*22ce4affSfengbojiang switch (cap) {
823*22ce4affSfengbojiang case IPSEC_CAP_BYPASS_FILTER:
824*22ce4affSfengbojiang /*
825*22ce4affSfengbojiang * Bypass packet filtering for packets previously handled
826*22ce4affSfengbojiang * by IPsec.
827*22ce4affSfengbojiang */
828*22ce4affSfengbojiang if (!V_ip6_filtertunnel &&
829*22ce4affSfengbojiang m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) != NULL)
830*22ce4affSfengbojiang return (1);
831*22ce4affSfengbojiang return (0);
832*22ce4affSfengbojiang case IPSEC_CAP_OPERABLE:
833*22ce4affSfengbojiang /* Do we have active security policies? */
834*22ce4affSfengbojiang if (key_havesp(IPSEC_DIR_INBOUND) != 0 ||
835*22ce4affSfengbojiang key_havesp(IPSEC_DIR_OUTBOUND) != 0)
836*22ce4affSfengbojiang return (1);
837*22ce4affSfengbojiang return (0);
838*22ce4affSfengbojiang };
839*22ce4affSfengbojiang return (EOPNOTSUPP);
840*22ce4affSfengbojiang }
841*22ce4affSfengbojiang #endif /* INET6 */
842a9643ea8Slogwang
843a9643ea8Slogwang int
ipsec_run_hhooks(struct ipsec_ctx_data * ctx,int type)844a9643ea8Slogwang ipsec_run_hhooks(struct ipsec_ctx_data *ctx, int type)
845a9643ea8Slogwang {
846a9643ea8Slogwang int idx;
847a9643ea8Slogwang
848a9643ea8Slogwang switch (ctx->af) {
849a9643ea8Slogwang #ifdef INET
850a9643ea8Slogwang case AF_INET:
851a9643ea8Slogwang idx = HHOOK_IPSEC_INET;
852a9643ea8Slogwang break;
853a9643ea8Slogwang #endif
854a9643ea8Slogwang #ifdef INET6
855a9643ea8Slogwang case AF_INET6:
856a9643ea8Slogwang idx = HHOOK_IPSEC_INET6;
857a9643ea8Slogwang break;
858a9643ea8Slogwang #endif
859a9643ea8Slogwang default:
860a9643ea8Slogwang return (EPFNOSUPPORT);
861a9643ea8Slogwang }
862a9643ea8Slogwang if (type == HHOOK_TYPE_IPSEC_IN)
863a9643ea8Slogwang HHOOKS_RUN_IF(V_ipsec_hhh_in[idx], ctx, NULL);
864a9643ea8Slogwang else
865a9643ea8Slogwang HHOOKS_RUN_IF(V_ipsec_hhh_out[idx], ctx, NULL);
866a9643ea8Slogwang if (*ctx->mp == NULL)
867a9643ea8Slogwang return (EACCES);
868a9643ea8Slogwang return (0);
869a9643ea8Slogwang }
870a9643ea8Slogwang
871a9643ea8Slogwang /*
872a9643ea8Slogwang * Return current level.
873a9643ea8Slogwang * Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned.
874a9643ea8Slogwang */
875a9643ea8Slogwang u_int
ipsec_get_reqlevel(struct secpolicy * sp,u_int idx)876*22ce4affSfengbojiang ipsec_get_reqlevel(struct secpolicy *sp, u_int idx)
877a9643ea8Slogwang {
878*22ce4affSfengbojiang struct ipsecrequest *isr;
879a9643ea8Slogwang u_int esp_trans_deflev, esp_net_deflev;
880a9643ea8Slogwang u_int ah_trans_deflev, ah_net_deflev;
881*22ce4affSfengbojiang u_int level = 0;
882a9643ea8Slogwang
883*22ce4affSfengbojiang IPSEC_ASSERT(idx < sp->tcount, ("Wrong IPsec request index %d", idx));
884a9643ea8Slogwang /* XXX Note that we have ipseclog() expanded here - code sync issue. */
885a9643ea8Slogwang #define IPSEC_CHECK_DEFAULT(lev) \
886*22ce4affSfengbojiang (((lev) != IPSEC_LEVEL_USE && (lev) != IPSEC_LEVEL_REQUIRE && \
887*22ce4affSfengbojiang (lev) != IPSEC_LEVEL_UNIQUE) \
888*22ce4affSfengbojiang ? (V_ipsec_debug ? \
889*22ce4affSfengbojiang log(LOG_INFO, "fixed system default level " #lev ":%d->%d\n",\
890*22ce4affSfengbojiang (lev), IPSEC_LEVEL_REQUIRE) : 0), \
891*22ce4affSfengbojiang (lev) = IPSEC_LEVEL_REQUIRE, (lev) : (lev))
892*22ce4affSfengbojiang
893*22ce4affSfengbojiang /*
894*22ce4affSfengbojiang * IPsec VTI uses unique security policy with fake spidx filled
895*22ce4affSfengbojiang * with zeroes. Just return IPSEC_LEVEL_REQUIRE instead of doing
896*22ce4affSfengbojiang * full level lookup for such policies.
897*22ce4affSfengbojiang */
898*22ce4affSfengbojiang if (sp->state == IPSEC_SPSTATE_IFNET) {
899*22ce4affSfengbojiang IPSEC_ASSERT(sp->req[idx]->level == IPSEC_LEVEL_UNIQUE,
900*22ce4affSfengbojiang ("Wrong IPsec request level %d", sp->req[idx]->level));
901*22ce4affSfengbojiang return (IPSEC_LEVEL_REQUIRE);
902*22ce4affSfengbojiang }
903a9643ea8Slogwang
904a9643ea8Slogwang /* Set default level. */
905*22ce4affSfengbojiang switch (sp->spidx.src.sa.sa_family) {
906a9643ea8Slogwang #ifdef INET
907a9643ea8Slogwang case AF_INET:
908a9643ea8Slogwang esp_trans_deflev = IPSEC_CHECK_DEFAULT(V_ip4_esp_trans_deflev);
909a9643ea8Slogwang esp_net_deflev = IPSEC_CHECK_DEFAULT(V_ip4_esp_net_deflev);
910a9643ea8Slogwang ah_trans_deflev = IPSEC_CHECK_DEFAULT(V_ip4_ah_trans_deflev);
911a9643ea8Slogwang ah_net_deflev = IPSEC_CHECK_DEFAULT(V_ip4_ah_net_deflev);
912a9643ea8Slogwang break;
913a9643ea8Slogwang #endif
914a9643ea8Slogwang #ifdef INET6
915a9643ea8Slogwang case AF_INET6:
916a9643ea8Slogwang esp_trans_deflev = IPSEC_CHECK_DEFAULT(V_ip6_esp_trans_deflev);
917a9643ea8Slogwang esp_net_deflev = IPSEC_CHECK_DEFAULT(V_ip6_esp_net_deflev);
918a9643ea8Slogwang ah_trans_deflev = IPSEC_CHECK_DEFAULT(V_ip6_ah_trans_deflev);
919a9643ea8Slogwang ah_net_deflev = IPSEC_CHECK_DEFAULT(V_ip6_ah_net_deflev);
920a9643ea8Slogwang break;
921a9643ea8Slogwang #endif /* INET6 */
922a9643ea8Slogwang default:
923a9643ea8Slogwang panic("%s: unknown af %u",
924*22ce4affSfengbojiang __func__, sp->spidx.src.sa.sa_family);
925a9643ea8Slogwang }
926a9643ea8Slogwang
927a9643ea8Slogwang #undef IPSEC_CHECK_DEFAULT
928a9643ea8Slogwang
929*22ce4affSfengbojiang isr = sp->req[idx];
930a9643ea8Slogwang /* Set level. */
931a9643ea8Slogwang switch (isr->level) {
932a9643ea8Slogwang case IPSEC_LEVEL_DEFAULT:
933a9643ea8Slogwang switch (isr->saidx.proto) {
934a9643ea8Slogwang case IPPROTO_ESP:
935a9643ea8Slogwang if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
936a9643ea8Slogwang level = esp_net_deflev;
937a9643ea8Slogwang else
938a9643ea8Slogwang level = esp_trans_deflev;
939a9643ea8Slogwang break;
940a9643ea8Slogwang case IPPROTO_AH:
941a9643ea8Slogwang if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
942a9643ea8Slogwang level = ah_net_deflev;
943a9643ea8Slogwang else
944a9643ea8Slogwang level = ah_trans_deflev;
945a9643ea8Slogwang break;
946a9643ea8Slogwang case IPPROTO_IPCOMP:
947a9643ea8Slogwang /*
948a9643ea8Slogwang * We don't really care, as IPcomp document says that
949a9643ea8Slogwang * we shouldn't compress small packets.
950a9643ea8Slogwang */
951a9643ea8Slogwang level = IPSEC_LEVEL_USE;
952a9643ea8Slogwang break;
953a9643ea8Slogwang default:
954a9643ea8Slogwang panic("%s: Illegal protocol defined %u\n", __func__,
955a9643ea8Slogwang isr->saidx.proto);
956a9643ea8Slogwang }
957a9643ea8Slogwang break;
958a9643ea8Slogwang
959a9643ea8Slogwang case IPSEC_LEVEL_USE:
960a9643ea8Slogwang case IPSEC_LEVEL_REQUIRE:
961a9643ea8Slogwang level = isr->level;
962a9643ea8Slogwang break;
963a9643ea8Slogwang case IPSEC_LEVEL_UNIQUE:
964a9643ea8Slogwang level = IPSEC_LEVEL_REQUIRE;
965a9643ea8Slogwang break;
966a9643ea8Slogwang
967a9643ea8Slogwang default:
968a9643ea8Slogwang panic("%s: Illegal IPsec level %u\n", __func__, isr->level);
969a9643ea8Slogwang }
970a9643ea8Slogwang
971a9643ea8Slogwang return (level);
972a9643ea8Slogwang }
973a9643ea8Slogwang
974*22ce4affSfengbojiang static int
ipsec_check_history(const struct mbuf * m,struct secpolicy * sp,u_int idx)975*22ce4affSfengbojiang ipsec_check_history(const struct mbuf *m, struct secpolicy *sp, u_int idx)
976*22ce4affSfengbojiang {
977*22ce4affSfengbojiang struct xform_history *xh;
978*22ce4affSfengbojiang struct m_tag *mtag;
979*22ce4affSfengbojiang
980*22ce4affSfengbojiang mtag = NULL;
981*22ce4affSfengbojiang while ((mtag = m_tag_find(__DECONST(struct mbuf *, m),
982*22ce4affSfengbojiang PACKET_TAG_IPSEC_IN_DONE, mtag)) != NULL) {
983*22ce4affSfengbojiang xh = (struct xform_history *)(mtag + 1);
984*22ce4affSfengbojiang KEYDBG(IPSEC_DATA,
985*22ce4affSfengbojiang char buf[IPSEC_ADDRSTRLEN];
986*22ce4affSfengbojiang printf("%s: mode %s proto %u dst %s\n", __func__,
987*22ce4affSfengbojiang kdebug_secasindex_mode(xh->mode), xh->proto,
988*22ce4affSfengbojiang ipsec_address(&xh->dst, buf, sizeof(buf))));
989*22ce4affSfengbojiang if (xh->proto != sp->req[idx]->saidx.proto)
990*22ce4affSfengbojiang continue;
991*22ce4affSfengbojiang /* If SA had IPSEC_MODE_ANY, consider this as match. */
992*22ce4affSfengbojiang if (xh->mode != sp->req[idx]->saidx.mode &&
993*22ce4affSfengbojiang xh->mode != IPSEC_MODE_ANY)
994*22ce4affSfengbojiang continue;
995*22ce4affSfengbojiang /*
996*22ce4affSfengbojiang * For transport mode IPsec request doesn't contain
997*22ce4affSfengbojiang * addresses. We need to use address from spidx.
998*22ce4affSfengbojiang */
999*22ce4affSfengbojiang if (sp->req[idx]->saidx.mode == IPSEC_MODE_TRANSPORT) {
1000*22ce4affSfengbojiang if (key_sockaddrcmp_withmask(&xh->dst.sa,
1001*22ce4affSfengbojiang &sp->spidx.dst.sa, sp->spidx.prefd) != 0)
1002*22ce4affSfengbojiang continue;
1003*22ce4affSfengbojiang } else {
1004*22ce4affSfengbojiang if (key_sockaddrcmp(&xh->dst.sa,
1005*22ce4affSfengbojiang &sp->req[idx]->saidx.dst.sa, 0) != 0)
1006*22ce4affSfengbojiang continue;
1007*22ce4affSfengbojiang }
1008*22ce4affSfengbojiang return (0); /* matched */
1009*22ce4affSfengbojiang }
1010*22ce4affSfengbojiang return (1);
1011*22ce4affSfengbojiang }
1012*22ce4affSfengbojiang
1013a9643ea8Slogwang /*
1014a9643ea8Slogwang * Check security policy requirements against the actual
1015a9643ea8Slogwang * packet contents. Return one if the packet should be
1016a9643ea8Slogwang * reject as "invalid"; otherwiser return zero to have the
1017a9643ea8Slogwang * packet treated as "valid".
1018a9643ea8Slogwang *
1019a9643ea8Slogwang * OUT:
1020a9643ea8Slogwang * 0: valid
1021a9643ea8Slogwang * 1: invalid
1022a9643ea8Slogwang */
1023a9643ea8Slogwang static int
ipsec_in_reject(struct secpolicy * sp,struct inpcb * inp,const struct mbuf * m)1024*22ce4affSfengbojiang ipsec_in_reject(struct secpolicy *sp, struct inpcb *inp, const struct mbuf *m)
1025a9643ea8Slogwang {
1026*22ce4affSfengbojiang int i;
1027a9643ea8Slogwang
1028*22ce4affSfengbojiang KEYDBG(IPSEC_STAMP,
1029*22ce4affSfengbojiang printf("%s: PCB(%p): using SP(%p)\n", __func__, inp, sp));
1030*22ce4affSfengbojiang KEYDBG(IPSEC_DATA, kdebug_secpolicy(sp));
1031*22ce4affSfengbojiang
1032*22ce4affSfengbojiang if (inp != NULL && inp->inp_sp != NULL && inp->inp_sp->sp_in == NULL)
1033*22ce4affSfengbojiang ipsec_cachepolicy(inp, sp, IPSEC_DIR_INBOUND);
1034a9643ea8Slogwang
1035a9643ea8Slogwang /* Check policy. */
1036a9643ea8Slogwang switch (sp->policy) {
1037a9643ea8Slogwang case IPSEC_POLICY_DISCARD:
1038a9643ea8Slogwang return (1);
1039a9643ea8Slogwang case IPSEC_POLICY_BYPASS:
1040a9643ea8Slogwang case IPSEC_POLICY_NONE:
1041a9643ea8Slogwang return (0);
1042a9643ea8Slogwang }
1043a9643ea8Slogwang
1044a9643ea8Slogwang IPSEC_ASSERT(sp->policy == IPSEC_POLICY_IPSEC,
1045a9643ea8Slogwang ("invalid policy %u", sp->policy));
1046a9643ea8Slogwang
1047*22ce4affSfengbojiang /*
1048*22ce4affSfengbojiang * ipsec[46]_common_input_cb after each transform adds
1049*22ce4affSfengbojiang * PACKET_TAG_IPSEC_IN_DONE mbuf tag. It contains SPI, proto, mode
1050*22ce4affSfengbojiang * and destination address from saidx. We can compare info from
1051*22ce4affSfengbojiang * these tags with requirements in SP.
1052*22ce4affSfengbojiang */
1053*22ce4affSfengbojiang for (i = 0; i < sp->tcount; i++) {
1054*22ce4affSfengbojiang /*
1055*22ce4affSfengbojiang * Do not check IPcomp, since IPcomp document
1056*22ce4affSfengbojiang * says that we shouldn't compress small packets.
1057*22ce4affSfengbojiang * IPComp policy should always be treated as being
1058*22ce4affSfengbojiang * in "use" level.
1059*22ce4affSfengbojiang */
1060*22ce4affSfengbojiang if (sp->req[i]->saidx.proto == IPPROTO_IPCOMP ||
1061*22ce4affSfengbojiang ipsec_get_reqlevel(sp, i) != IPSEC_LEVEL_REQUIRE)
1062a9643ea8Slogwang continue;
1063*22ce4affSfengbojiang if (V_check_policy_history != 0 &&
1064*22ce4affSfengbojiang ipsec_check_history(m, sp, i) != 0)
1065*22ce4affSfengbojiang return (1);
1066*22ce4affSfengbojiang else switch (sp->req[i]->saidx.proto) {
1067a9643ea8Slogwang case IPPROTO_ESP:
1068a9643ea8Slogwang if ((m->m_flags & M_DECRYPTED) == 0) {
1069*22ce4affSfengbojiang KEYDBG(IPSEC_DUMP,
1070a9643ea8Slogwang printf("%s: ESP m_flags:%x\n", __func__,
1071a9643ea8Slogwang m->m_flags));
1072a9643ea8Slogwang return (1);
1073a9643ea8Slogwang }
1074a9643ea8Slogwang break;
1075a9643ea8Slogwang case IPPROTO_AH:
1076a9643ea8Slogwang if ((m->m_flags & M_AUTHIPHDR) == 0) {
1077*22ce4affSfengbojiang KEYDBG(IPSEC_DUMP,
1078a9643ea8Slogwang printf("%s: AH m_flags:%x\n", __func__,
1079a9643ea8Slogwang m->m_flags));
1080a9643ea8Slogwang return (1);
1081a9643ea8Slogwang }
1082a9643ea8Slogwang break;
1083a9643ea8Slogwang }
1084a9643ea8Slogwang }
1085a9643ea8Slogwang return (0); /* Valid. */
1086a9643ea8Slogwang }
1087a9643ea8Slogwang
1088a9643ea8Slogwang /*
1089a9643ea8Slogwang * Compute the byte size to be occupied by IPsec header.
1090a9643ea8Slogwang * In case it is tunnelled, it includes the size of outer IP header.
1091a9643ea8Slogwang */
1092a9643ea8Slogwang static size_t
ipsec_hdrsiz_internal(struct secpolicy * sp)1093a9643ea8Slogwang ipsec_hdrsiz_internal(struct secpolicy *sp)
1094a9643ea8Slogwang {
1095a9643ea8Slogwang size_t size;
1096*22ce4affSfengbojiang int i;
1097a9643ea8Slogwang
1098*22ce4affSfengbojiang KEYDBG(IPSEC_STAMP, printf("%s: using SP(%p)\n", __func__, sp));
1099*22ce4affSfengbojiang KEYDBG(IPSEC_DATA, kdebug_secpolicy(sp));
1100a9643ea8Slogwang
1101a9643ea8Slogwang switch (sp->policy) {
1102a9643ea8Slogwang case IPSEC_POLICY_DISCARD:
1103a9643ea8Slogwang case IPSEC_POLICY_BYPASS:
1104a9643ea8Slogwang case IPSEC_POLICY_NONE:
1105a9643ea8Slogwang return (0);
1106a9643ea8Slogwang }
1107a9643ea8Slogwang
1108a9643ea8Slogwang IPSEC_ASSERT(sp->policy == IPSEC_POLICY_IPSEC,
1109a9643ea8Slogwang ("invalid policy %u", sp->policy));
1110a9643ea8Slogwang
1111*22ce4affSfengbojiang /*
1112*22ce4affSfengbojiang * XXX: for each transform we need to lookup suitable SA
1113*22ce4affSfengbojiang * and use info from SA to calculate headers size.
1114*22ce4affSfengbojiang * XXX: for NAT-T we need to cosider UDP header size.
1115*22ce4affSfengbojiang */
1116a9643ea8Slogwang size = 0;
1117*22ce4affSfengbojiang for (i = 0; i < sp->tcount; i++) {
1118*22ce4affSfengbojiang switch (sp->req[i]->saidx.proto) {
1119a9643ea8Slogwang case IPPROTO_ESP:
1120*22ce4affSfengbojiang size += esp_hdrsiz(NULL);
1121a9643ea8Slogwang break;
1122a9643ea8Slogwang case IPPROTO_AH:
1123*22ce4affSfengbojiang size += ah_hdrsiz(NULL);
1124a9643ea8Slogwang break;
1125a9643ea8Slogwang case IPPROTO_IPCOMP:
1126*22ce4affSfengbojiang size += sizeof(struct ipcomp);
1127a9643ea8Slogwang break;
1128a9643ea8Slogwang }
1129a9643ea8Slogwang
1130*22ce4affSfengbojiang if (sp->req[i]->saidx.mode == IPSEC_MODE_TUNNEL) {
1131*22ce4affSfengbojiang switch (sp->req[i]->saidx.dst.sa.sa_family) {
1132*22ce4affSfengbojiang #ifdef INET
1133a9643ea8Slogwang case AF_INET:
1134*22ce4affSfengbojiang size += sizeof(struct ip);
1135a9643ea8Slogwang break;
1136*22ce4affSfengbojiang #endif
1137a9643ea8Slogwang #ifdef INET6
1138a9643ea8Slogwang case AF_INET6:
1139*22ce4affSfengbojiang size += sizeof(struct ip6_hdr);
1140a9643ea8Slogwang break;
1141a9643ea8Slogwang #endif
1142a9643ea8Slogwang default:
1143a9643ea8Slogwang ipseclog((LOG_ERR, "%s: unknown AF %d in "
1144a9643ea8Slogwang "IPsec tunnel SA\n", __func__,
1145*22ce4affSfengbojiang sp->req[i]->saidx.dst.sa.sa_family));
1146a9643ea8Slogwang break;
1147a9643ea8Slogwang }
1148a9643ea8Slogwang }
1149a9643ea8Slogwang }
1150a9643ea8Slogwang return (size);
1151a9643ea8Slogwang }
1152a9643ea8Slogwang
1153a9643ea8Slogwang /*
1154*22ce4affSfengbojiang * Compute ESP/AH header size for protocols with PCB, including
1155*22ce4affSfengbojiang * outer IP header. Currently only tcp_output() uses it.
1156a9643ea8Slogwang */
1157a9643ea8Slogwang size_t
ipsec_hdrsiz_inpcb(struct inpcb * inp)1158*22ce4affSfengbojiang ipsec_hdrsiz_inpcb(struct inpcb *inp)
1159a9643ea8Slogwang {
1160*22ce4affSfengbojiang struct secpolicyindex spidx;
1161a9643ea8Slogwang struct secpolicy *sp;
1162*22ce4affSfengbojiang size_t sz;
1163a9643ea8Slogwang
1164*22ce4affSfengbojiang sp = ipsec_getpcbpolicy(inp, IPSEC_DIR_OUTBOUND);
1165*22ce4affSfengbojiang if (sp == NULL && key_havesp(IPSEC_DIR_OUTBOUND)) {
1166*22ce4affSfengbojiang ipsec_setspidx_inpcb(inp, &spidx, IPSEC_DIR_OUTBOUND);
1167*22ce4affSfengbojiang sp = key_allocsp(&spidx, IPSEC_DIR_OUTBOUND);
1168a9643ea8Slogwang }
1169*22ce4affSfengbojiang if (sp == NULL)
1170*22ce4affSfengbojiang sp = key_allocsp_default();
1171*22ce4affSfengbojiang sz = ipsec_hdrsiz_internal(sp);
1172*22ce4affSfengbojiang key_freesp(&sp);
1173*22ce4affSfengbojiang return (sz);
1174*22ce4affSfengbojiang }
1175*22ce4affSfengbojiang
1176*22ce4affSfengbojiang
1177*22ce4affSfengbojiang #define IPSEC_BITMAP_INDEX_MASK(w) (w - 1)
1178*22ce4affSfengbojiang #define IPSEC_REDUNDANT_BIT_SHIFTS 5
1179*22ce4affSfengbojiang #define IPSEC_REDUNDANT_BITS (1 << IPSEC_REDUNDANT_BIT_SHIFTS)
1180*22ce4affSfengbojiang #define IPSEC_BITMAP_LOC_MASK (IPSEC_REDUNDANT_BITS - 1)
1181*22ce4affSfengbojiang
1182*22ce4affSfengbojiang /*
1183*22ce4affSfengbojiang * Functions below are responsible for checking and updating bitmap.
1184*22ce4affSfengbojiang * These are used to separate ipsec_chkreplay() and ipsec_updatereplay()
1185*22ce4affSfengbojiang * from window implementation
1186*22ce4affSfengbojiang *
1187*22ce4affSfengbojiang * Based on RFC 6479. Blocks are 32 bits unsigned integers
1188*22ce4affSfengbojiang */
1189*22ce4affSfengbojiang
1190*22ce4affSfengbojiang static inline int
check_window(const struct secreplay * replay,uint64_t seq)1191*22ce4affSfengbojiang check_window(const struct secreplay *replay, uint64_t seq)
1192*22ce4affSfengbojiang {
1193*22ce4affSfengbojiang int index, bit_location;
1194*22ce4affSfengbojiang
1195*22ce4affSfengbojiang bit_location = seq & IPSEC_BITMAP_LOC_MASK;
1196*22ce4affSfengbojiang index = (seq >> IPSEC_REDUNDANT_BIT_SHIFTS)
1197*22ce4affSfengbojiang & IPSEC_BITMAP_INDEX_MASK(replay->bitmap_size);
1198*22ce4affSfengbojiang
1199*22ce4affSfengbojiang /* This packet already seen? */
1200*22ce4affSfengbojiang return ((replay->bitmap)[index] & (1 << bit_location));
1201*22ce4affSfengbojiang }
1202*22ce4affSfengbojiang
1203*22ce4affSfengbojiang static inline void
advance_window(const struct secreplay * replay,uint64_t seq)1204*22ce4affSfengbojiang advance_window(const struct secreplay *replay, uint64_t seq)
1205*22ce4affSfengbojiang {
1206*22ce4affSfengbojiang int i;
1207*22ce4affSfengbojiang uint64_t index, index_cur, diff;
1208*22ce4affSfengbojiang
1209*22ce4affSfengbojiang index_cur = replay->last >> IPSEC_REDUNDANT_BIT_SHIFTS;
1210*22ce4affSfengbojiang index = seq >> IPSEC_REDUNDANT_BIT_SHIFTS;
1211*22ce4affSfengbojiang diff = index - index_cur;
1212*22ce4affSfengbojiang
1213*22ce4affSfengbojiang if (diff > replay->bitmap_size) {
1214*22ce4affSfengbojiang /* something unusual in this case */
1215*22ce4affSfengbojiang diff = replay->bitmap_size;
1216*22ce4affSfengbojiang }
1217*22ce4affSfengbojiang
1218*22ce4affSfengbojiang for (i = 0; i < diff; i++) {
1219*22ce4affSfengbojiang replay->bitmap[(i + index_cur + 1)
1220*22ce4affSfengbojiang & IPSEC_BITMAP_INDEX_MASK(replay->bitmap_size)] = 0;
1221*22ce4affSfengbojiang }
1222*22ce4affSfengbojiang }
1223*22ce4affSfengbojiang
1224*22ce4affSfengbojiang static inline void
set_window(const struct secreplay * replay,uint64_t seq)1225*22ce4affSfengbojiang set_window(const struct secreplay *replay, uint64_t seq)
1226*22ce4affSfengbojiang {
1227*22ce4affSfengbojiang int index, bit_location;
1228*22ce4affSfengbojiang
1229*22ce4affSfengbojiang bit_location = seq & IPSEC_BITMAP_LOC_MASK;
1230*22ce4affSfengbojiang index = (seq >> IPSEC_REDUNDANT_BIT_SHIFTS)
1231*22ce4affSfengbojiang & IPSEC_BITMAP_INDEX_MASK(replay->bitmap_size);
1232*22ce4affSfengbojiang
1233*22ce4affSfengbojiang replay->bitmap[index] |= (1 << bit_location);
1234a9643ea8Slogwang }
1235a9643ea8Slogwang
1236a9643ea8Slogwang /*
1237a9643ea8Slogwang * Check the variable replay window.
1238a9643ea8Slogwang * ipsec_chkreplay() performs replay check before ICV verification.
1239a9643ea8Slogwang * ipsec_updatereplay() updates replay bitmap. This must be called after
1240a9643ea8Slogwang * ICV verification (it also performs replay check, which is usually done
1241a9643ea8Slogwang * beforehand).
1242a9643ea8Slogwang * 0 (zero) is returned if packet disallowed, 1 if packet permitted.
1243a9643ea8Slogwang *
1244*22ce4affSfengbojiang * Based on RFC 4303
1245a9643ea8Slogwang */
1246*22ce4affSfengbojiang
1247a9643ea8Slogwang int
ipsec_chkreplay(uint32_t seq,uint32_t * seqhigh,struct secasvar * sav)1248*22ce4affSfengbojiang ipsec_chkreplay(uint32_t seq, uint32_t *seqhigh, struct secasvar *sav)
1249a9643ea8Slogwang {
1250*22ce4affSfengbojiang char buf[128];
1251*22ce4affSfengbojiang struct secreplay *replay;
1252*22ce4affSfengbojiang uint32_t window;
1253*22ce4affSfengbojiang uint32_t tl, th, bl;
1254*22ce4affSfengbojiang uint32_t seqh;
1255a9643ea8Slogwang
1256a9643ea8Slogwang IPSEC_ASSERT(sav != NULL, ("Null SA"));
1257a9643ea8Slogwang IPSEC_ASSERT(sav->replay != NULL, ("Null replay state"));
1258a9643ea8Slogwang
1259a9643ea8Slogwang replay = sav->replay;
1260a9643ea8Slogwang
1261*22ce4affSfengbojiang /* No need to check replay if disabled. */
1262a9643ea8Slogwang if (replay->wsize == 0)
1263a9643ea8Slogwang return (1);
1264a9643ea8Slogwang
1265*22ce4affSfengbojiang /* Zero sequence number is not allowed. */
1266*22ce4affSfengbojiang if (seq == 0 && replay->last == 0)
1267a9643ea8Slogwang return (0);
1268a9643ea8Slogwang
1269*22ce4affSfengbojiang window = replay->wsize << 3; /* Size of window */
1270*22ce4affSfengbojiang tl = (uint32_t)replay->last; /* Top of window, lower part */
1271*22ce4affSfengbojiang th = (uint32_t)(replay->last >> 32); /* Top of window, high part */
1272*22ce4affSfengbojiang bl = tl - window + 1; /* Bottom of window, lower part */
1273a9643ea8Slogwang
1274*22ce4affSfengbojiang /*
1275*22ce4affSfengbojiang * We keep the high part intact when:
1276*22ce4affSfengbojiang * 1) the seq is within [bl, 0xffffffff] and the whole window is
1277*22ce4affSfengbojiang * within one subspace;
1278*22ce4affSfengbojiang * 2) the seq is within [0, bl) and window spans two subspaces.
1279*22ce4affSfengbojiang */
1280*22ce4affSfengbojiang if ((tl >= window - 1 && seq >= bl) ||
1281*22ce4affSfengbojiang (tl < window - 1 && seq < bl)) {
1282*22ce4affSfengbojiang *seqhigh = th;
1283*22ce4affSfengbojiang if (seq <= tl) {
1284*22ce4affSfengbojiang /* Sequence number inside window - check against replay */
1285*22ce4affSfengbojiang if (check_window(replay, seq))
1286a9643ea8Slogwang return (0);
1287*22ce4affSfengbojiang }
1288a9643ea8Slogwang
1289*22ce4affSfengbojiang /* Sequence number above top of window or not found in bitmap */
1290a9643ea8Slogwang return (1);
1291a9643ea8Slogwang }
1292*22ce4affSfengbojiang
1293*22ce4affSfengbojiang /*
1294*22ce4affSfengbojiang * If ESN is not enabled and packet with highest sequence number
1295*22ce4affSfengbojiang * was received we should report overflow
1296*22ce4affSfengbojiang */
1297*22ce4affSfengbojiang if (tl == 0xffffffff && !(sav->flags & SADB_X_SAFLAGS_ESN)) {
1298*22ce4affSfengbojiang /* Set overflow flag. */
1299*22ce4affSfengbojiang replay->overflow++;
1300*22ce4affSfengbojiang
1301*22ce4affSfengbojiang if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
1302*22ce4affSfengbojiang if (sav->sah->saidx.proto == IPPROTO_ESP)
1303*22ce4affSfengbojiang ESPSTAT_INC(esps_wrap);
1304*22ce4affSfengbojiang else if (sav->sah->saidx.proto == IPPROTO_AH)
1305*22ce4affSfengbojiang AHSTAT_INC(ahs_wrap);
1306*22ce4affSfengbojiang return (0);
1307*22ce4affSfengbojiang }
1308*22ce4affSfengbojiang
1309*22ce4affSfengbojiang ipseclog((LOG_WARNING, "%s: replay counter made %d cycle. %s\n",
1310*22ce4affSfengbojiang __func__, replay->overflow,
1311*22ce4affSfengbojiang ipsec_sa2str(sav, buf, sizeof(buf))));
1312*22ce4affSfengbojiang }
1313*22ce4affSfengbojiang
1314*22ce4affSfengbojiang /*
1315*22ce4affSfengbojiang * Seq is within [bl, 0xffffffff] and bl is within
1316*22ce4affSfengbojiang * [0xffffffff-window, 0xffffffff]. This means we got a seq
1317*22ce4affSfengbojiang * which is within our replay window, but in the previous
1318*22ce4affSfengbojiang * subspace.
1319*22ce4affSfengbojiang */
1320*22ce4affSfengbojiang if (tl < window - 1 && seq >= bl) {
1321*22ce4affSfengbojiang if (th == 0)
1322*22ce4affSfengbojiang return (0);
1323*22ce4affSfengbojiang *seqhigh = th - 1;
1324*22ce4affSfengbojiang seqh = th - 1;
1325*22ce4affSfengbojiang if (check_window(replay, seq))
1326*22ce4affSfengbojiang return (0);
1327*22ce4affSfengbojiang return (1);
1328*22ce4affSfengbojiang }
1329*22ce4affSfengbojiang
1330*22ce4affSfengbojiang /*
1331*22ce4affSfengbojiang * Seq is within [0, bl) but the whole window is within one subspace.
1332*22ce4affSfengbojiang * This means that seq has wrapped and is in next subspace
1333*22ce4affSfengbojiang */
1334*22ce4affSfengbojiang *seqhigh = th + 1;
1335*22ce4affSfengbojiang seqh = th + 1;
1336*22ce4affSfengbojiang
1337*22ce4affSfengbojiang /* Don't let high part wrap. */
1338*22ce4affSfengbojiang if (seqh == 0) {
1339*22ce4affSfengbojiang /* Set overflow flag. */
1340*22ce4affSfengbojiang replay->overflow++;
1341*22ce4affSfengbojiang
1342*22ce4affSfengbojiang if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) {
1343*22ce4affSfengbojiang if (sav->sah->saidx.proto == IPPROTO_ESP)
1344*22ce4affSfengbojiang ESPSTAT_INC(esps_wrap);
1345*22ce4affSfengbojiang else if (sav->sah->saidx.proto == IPPROTO_AH)
1346*22ce4affSfengbojiang AHSTAT_INC(ahs_wrap);
1347*22ce4affSfengbojiang return (0);
1348*22ce4affSfengbojiang }
1349*22ce4affSfengbojiang
1350*22ce4affSfengbojiang ipseclog((LOG_WARNING, "%s: replay counter made %d cycle. %s\n",
1351*22ce4affSfengbojiang __func__, replay->overflow,
1352*22ce4affSfengbojiang ipsec_sa2str(sav, buf, sizeof(buf))));
1353*22ce4affSfengbojiang }
1354*22ce4affSfengbojiang
1355*22ce4affSfengbojiang return (1);
1356a9643ea8Slogwang }
1357a9643ea8Slogwang
1358a9643ea8Slogwang /*
1359a9643ea8Slogwang * Check replay counter whether to update or not.
1360a9643ea8Slogwang * OUT: 0: OK
1361a9643ea8Slogwang * 1: NG
1362a9643ea8Slogwang */
1363a9643ea8Slogwang int
ipsec_updatereplay(uint32_t seq,struct secasvar * sav)1364*22ce4affSfengbojiang ipsec_updatereplay(uint32_t seq, struct secasvar *sav)
1365a9643ea8Slogwang {
1366a9643ea8Slogwang struct secreplay *replay;
1367*22ce4affSfengbojiang uint32_t window;
1368*22ce4affSfengbojiang uint32_t tl, th, bl;
1369*22ce4affSfengbojiang uint32_t seqh;
1370a9643ea8Slogwang
1371a9643ea8Slogwang IPSEC_ASSERT(sav != NULL, ("Null SA"));
1372a9643ea8Slogwang IPSEC_ASSERT(sav->replay != NULL, ("Null replay state"));
1373a9643ea8Slogwang
1374a9643ea8Slogwang replay = sav->replay;
1375a9643ea8Slogwang
1376*22ce4affSfengbojiang /* No need to check replay if disabled. */
1377a9643ea8Slogwang if (replay->wsize == 0)
1378*22ce4affSfengbojiang return (0);
1379a9643ea8Slogwang
1380*22ce4affSfengbojiang /* Zero sequence number is not allowed. */
1381*22ce4affSfengbojiang if (seq == 0 && replay->last == 0)
1382a9643ea8Slogwang return (1);
1383a9643ea8Slogwang
1384*22ce4affSfengbojiang window = replay->wsize << 3; /* Size of window */
1385*22ce4affSfengbojiang tl = (uint32_t)replay->last; /* Top of window, lower part */
1386*22ce4affSfengbojiang th = (uint32_t)(replay->last >> 32); /* Top of window, high part */
1387*22ce4affSfengbojiang bl = tl - window + 1; /* Bottom of window, lower part */
1388a9643ea8Slogwang
1389*22ce4affSfengbojiang /*
1390*22ce4affSfengbojiang * We keep the high part intact when:
1391*22ce4affSfengbojiang * 1) the seq is within [bl, 0xffffffff] and the whole window is
1392*22ce4affSfengbojiang * within one subspace;
1393*22ce4affSfengbojiang * 2) the seq is within [0, bl) and window spans two subspaces.
1394*22ce4affSfengbojiang */
1395*22ce4affSfengbojiang if ((tl >= window - 1 && seq >= bl) ||
1396*22ce4affSfengbojiang (tl < window - 1 && seq < bl)) {
1397*22ce4affSfengbojiang seqh = th;
1398*22ce4affSfengbojiang if (seq <= tl) {
1399*22ce4affSfengbojiang /* Sequence number inside window - check against replay */
1400*22ce4affSfengbojiang if (check_window(replay, seq))
1401*22ce4affSfengbojiang return (1);
1402*22ce4affSfengbojiang set_window(replay, seq);
1403a9643ea8Slogwang } else {
1404*22ce4affSfengbojiang advance_window(replay, ((uint64_t)seqh << 32) | seq);
1405*22ce4affSfengbojiang set_window(replay, seq);
1406*22ce4affSfengbojiang replay->last = ((uint64_t)seqh << 32) | seq;
1407a9643ea8Slogwang }
1408a9643ea8Slogwang
1409*22ce4affSfengbojiang /* Sequence number above top of window or not found in bitmap */
1410a9643ea8Slogwang replay->count++;
1411*22ce4affSfengbojiang return (0);
1412*22ce4affSfengbojiang }
1413a9643ea8Slogwang
1414*22ce4affSfengbojiang if (!(sav->flags & SADB_X_SAFLAGS_ESN))
1415*22ce4affSfengbojiang return (1);
1416*22ce4affSfengbojiang
1417*22ce4affSfengbojiang /*
1418*22ce4affSfengbojiang * Seq is within [bl, 0xffffffff] and bl is within
1419*22ce4affSfengbojiang * [0xffffffff-window, 0xffffffff]. This means we got a seq
1420*22ce4affSfengbojiang * which is within our replay window, but in the previous
1421*22ce4affSfengbojiang * subspace.
1422*22ce4affSfengbojiang */
1423*22ce4affSfengbojiang if (tl < window - 1 && seq >= bl) {
1424*22ce4affSfengbojiang if (th == 0)
1425*22ce4affSfengbojiang return (1);
1426*22ce4affSfengbojiang if (check_window(replay, seq))
1427*22ce4affSfengbojiang return (1);
1428*22ce4affSfengbojiang
1429*22ce4affSfengbojiang set_window(replay, seq);
1430*22ce4affSfengbojiang replay->count++;
1431a9643ea8Slogwang return (0);
1432a9643ea8Slogwang }
1433a9643ea8Slogwang
1434a9643ea8Slogwang /*
1435*22ce4affSfengbojiang * Seq is within [0, bl) but the whole window is within one subspace.
1436*22ce4affSfengbojiang * This means that seq has wrapped and is in next subspace
1437a9643ea8Slogwang */
1438*22ce4affSfengbojiang seqh = th + 1;
1439*22ce4affSfengbojiang
1440*22ce4affSfengbojiang /* Don't let high part wrap. */
1441*22ce4affSfengbojiang if (seqh == 0)
1442*22ce4affSfengbojiang return (1);
1443*22ce4affSfengbojiang
1444*22ce4affSfengbojiang advance_window(replay, ((uint64_t)seqh << 32) | seq);
1445*22ce4affSfengbojiang set_window(replay, seq);
1446*22ce4affSfengbojiang replay->last = ((uint64_t)seqh << 32) | seq;
1447*22ce4affSfengbojiang replay->count++;
1448*22ce4affSfengbojiang return (0);
1449*22ce4affSfengbojiang }
1450*22ce4affSfengbojiang int
ipsec_updateid(struct secasvar * sav,crypto_session_t * new,crypto_session_t * old)1451*22ce4affSfengbojiang ipsec_updateid(struct secasvar *sav, crypto_session_t *new,
1452*22ce4affSfengbojiang crypto_session_t *old)
1453a9643ea8Slogwang {
1454*22ce4affSfengbojiang crypto_session_t tmp;
1455a9643ea8Slogwang
1456*22ce4affSfengbojiang /*
1457*22ce4affSfengbojiang * tdb_cryptoid is initialized by xform_init().
1458*22ce4affSfengbojiang * Then it can be changed only when some crypto error occurred or
1459*22ce4affSfengbojiang * when SA is deleted. We stored used cryptoid in the xform_data
1460*22ce4affSfengbojiang * structure. In case when crypto error occurred and crypto
1461*22ce4affSfengbojiang * subsystem has reinited the session, it returns new cryptoid
1462*22ce4affSfengbojiang * and EAGAIN error code.
1463*22ce4affSfengbojiang *
1464*22ce4affSfengbojiang * This function will be called when we got EAGAIN from crypto
1465*22ce4affSfengbojiang * subsystem.
1466*22ce4affSfengbojiang * *new is cryptoid that was returned by crypto subsystem in
1467*22ce4affSfengbojiang * the crp_sid.
1468*22ce4affSfengbojiang * *old is the original cryptoid that we stored in xform_data.
1469*22ce4affSfengbojiang *
1470*22ce4affSfengbojiang * For first failed request *old == sav->tdb_cryptoid, then
1471*22ce4affSfengbojiang * we update sav->tdb_cryptoid and redo crypto_dispatch().
1472*22ce4affSfengbojiang * For next failed request *old != sav->tdb_cryptoid, then
1473*22ce4affSfengbojiang * we store cryptoid from first request into the *new variable
1474*22ce4affSfengbojiang * and crp_sid from this second session will be returned via
1475*22ce4affSfengbojiang * *old pointer, so caller can release second session.
1476*22ce4affSfengbojiang *
1477*22ce4affSfengbojiang * XXXAE: check this more carefully.
1478*22ce4affSfengbojiang */
1479*22ce4affSfengbojiang KEYDBG(IPSEC_STAMP,
1480*22ce4affSfengbojiang printf("%s: SA(%p) moves cryptoid %p -> %p\n",
1481*22ce4affSfengbojiang __func__, sav, *old, *new));
1482*22ce4affSfengbojiang KEYDBG(IPSEC_DATA, kdebug_secasv(sav));
1483*22ce4affSfengbojiang SECASVAR_LOCK(sav);
1484*22ce4affSfengbojiang if (sav->tdb_cryptoid != *old) {
1485*22ce4affSfengbojiang /* cryptoid was already updated */
1486*22ce4affSfengbojiang tmp = *new;
1487*22ce4affSfengbojiang *new = sav->tdb_cryptoid;
1488*22ce4affSfengbojiang *old = tmp;
1489*22ce4affSfengbojiang SECASVAR_UNLOCK(sav);
1490*22ce4affSfengbojiang return (1);
1491a9643ea8Slogwang }
1492*22ce4affSfengbojiang sav->tdb_cryptoid = *new;
1493*22ce4affSfengbojiang SECASVAR_UNLOCK(sav);
1494*22ce4affSfengbojiang return (0);
1495a9643ea8Slogwang }
1496a9643ea8Slogwang
1497*22ce4affSfengbojiang int
ipsec_initialized(void)1498*22ce4affSfengbojiang ipsec_initialized(void)
1499a9643ea8Slogwang {
1500a9643ea8Slogwang
1501*22ce4affSfengbojiang return (V_def_policy != NULL);
1502a9643ea8Slogwang }
1503a9643ea8Slogwang
1504a9643ea8Slogwang static void
def_policy_init(const void * unused __unused)1505a9643ea8Slogwang def_policy_init(const void *unused __unused)
1506a9643ea8Slogwang {
1507a9643ea8Slogwang
1508*22ce4affSfengbojiang V_def_policy = key_newsp();
1509*22ce4affSfengbojiang if (V_def_policy != NULL) {
1510*22ce4affSfengbojiang V_def_policy->policy = IPSEC_POLICY_NONE;
1511*22ce4affSfengbojiang /* Force INPCB SP cache invalidation */
1512*22ce4affSfengbojiang key_bumpspgen();
1513*22ce4affSfengbojiang } else
1514*22ce4affSfengbojiang printf("%s: failed to initialize default policy\n", __func__);
1515a9643ea8Slogwang }
1516*22ce4affSfengbojiang
1517*22ce4affSfengbojiang static void
def_policy_uninit(const void * unused __unused)1518*22ce4affSfengbojiang def_policy_uninit(const void *unused __unused)
1519*22ce4affSfengbojiang {
1520*22ce4affSfengbojiang
1521*22ce4affSfengbojiang if (V_def_policy != NULL) {
1522*22ce4affSfengbojiang key_freesp(&V_def_policy);
1523*22ce4affSfengbojiang key_bumpspgen();
1524*22ce4affSfengbojiang }
1525*22ce4affSfengbojiang }
1526*22ce4affSfengbojiang
1527a9643ea8Slogwang VNET_SYSINIT(def_policy_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST,
1528a9643ea8Slogwang def_policy_init, NULL);
1529*22ce4affSfengbojiang VNET_SYSUNINIT(def_policy_uninit, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST,
1530*22ce4affSfengbojiang def_policy_uninit, NULL);
1531