Thu Aug 27 02:52:34 2020 UTC ()
wg: Check mbuf chain length before m_copydata.


(riastradh)
diff -r1.24 -r1.25 src/sys/net/if_wg.c
diff -r1.2 -r1.3 src/tests/net/if_wg/t_misc.sh

cvs diff -r1.24 -r1.25 src/sys/net/if_wg.c (switch to unified diff)

--- src/sys/net/if_wg.c 2020/08/26 16:03:41 1.24
+++ src/sys/net/if_wg.c 2020/08/27 02:52:33 1.25
@@ -1,1043 +1,1043 @@ @@ -1,1043 +1,1043 @@
1/* $NetBSD: if_wg.c,v 1.24 2020/08/26 16:03:41 riastradh Exp $ */ 1/* $NetBSD: if_wg.c,v 1.25 2020/08/27 02:52:33 riastradh Exp $ */
2 2
3/* 3/*
4 * Copyright (C) Ryota Ozaki <ozaki.ryota@gmail.com> 4 * Copyright (C) Ryota Ozaki <ozaki.ryota@gmail.com>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors 15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software 16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission. 17 * without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * This network interface aims to implement the WireGuard protocol. 33 * This network interface aims to implement the WireGuard protocol.
34 * The implementation is based on the paper of WireGuard as of 34 * The implementation is based on the paper of WireGuard as of
35 * 2018-06-30 [1]. The paper is referred in the source code with label 35 * 2018-06-30 [1]. The paper is referred in the source code with label
36 * [W]. Also the specification of the Noise protocol framework as of 36 * [W]. Also the specification of the Noise protocol framework as of
37 * 2018-07-11 [2] is referred with label [N]. 37 * 2018-07-11 [2] is referred with label [N].
38 * 38 *
39 * [1] https://www.wireguard.com/papers/wireguard.pdf 39 * [1] https://www.wireguard.com/papers/wireguard.pdf
40 * [2] http://noiseprotocol.org/noise.pdf 40 * [2] http://noiseprotocol.org/noise.pdf
41 */ 41 */
42 42
43#include <sys/cdefs.h> 43#include <sys/cdefs.h>
44__KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.24 2020/08/26 16:03:41 riastradh Exp $"); 44__KERNEL_RCSID(0, "$NetBSD: if_wg.c,v 1.25 2020/08/27 02:52:33 riastradh Exp $");
45 45
46#ifdef _KERNEL_OPT 46#ifdef _KERNEL_OPT
47#include "opt_inet.h" 47#include "opt_inet.h"
48#endif 48#endif
49 49
50#include <sys/param.h> 50#include <sys/param.h>
51#include <sys/systm.h> 51#include <sys/systm.h>
52#include <sys/kernel.h> 52#include <sys/kernel.h>
53#include <sys/mbuf.h> 53#include <sys/mbuf.h>
54#include <sys/socket.h> 54#include <sys/socket.h>
55#include <sys/sockio.h> 55#include <sys/sockio.h>
56#include <sys/errno.h> 56#include <sys/errno.h>
57#include <sys/ioctl.h> 57#include <sys/ioctl.h>
58#include <sys/time.h> 58#include <sys/time.h>
59#include <sys/timespec.h> 59#include <sys/timespec.h>
60#include <sys/socketvar.h> 60#include <sys/socketvar.h>
61#include <sys/syslog.h> 61#include <sys/syslog.h>
62#include <sys/cpu.h> 62#include <sys/cpu.h>
63#include <sys/intr.h> 63#include <sys/intr.h>
64#include <sys/kmem.h> 64#include <sys/kmem.h>
65#include <sys/device.h> 65#include <sys/device.h>
66#include <sys/module.h> 66#include <sys/module.h>
67#include <sys/mutex.h> 67#include <sys/mutex.h>
68#include <sys/rwlock.h> 68#include <sys/rwlock.h>
69#include <sys/pserialize.h> 69#include <sys/pserialize.h>
70#include <sys/psref.h> 70#include <sys/psref.h>
71#include <sys/kthread.h> 71#include <sys/kthread.h>
72#include <sys/cprng.h> 72#include <sys/cprng.h>
73#include <sys/atomic.h> 73#include <sys/atomic.h>
74#include <sys/sysctl.h> 74#include <sys/sysctl.h>
75#include <sys/domain.h> 75#include <sys/domain.h>
76#include <sys/pcq.h> 76#include <sys/pcq.h>
77#include <sys/queue.h> 77#include <sys/queue.h>
78#include <sys/percpu.h> 78#include <sys/percpu.h>
79#include <sys/callout.h> 79#include <sys/callout.h>
80 80
81#include <net/bpf.h> 81#include <net/bpf.h>
82#include <net/if.h> 82#include <net/if.h>
83#include <net/if_types.h> 83#include <net/if_types.h>
84#include <net/route.h> 84#include <net/route.h>
85 85
86#include <netinet/in.h> 86#include <netinet/in.h>
87#include <netinet/ip.h> 87#include <netinet/ip.h>
88#include <netinet/ip_var.h> 88#include <netinet/ip_var.h>
89#include <netinet/udp.h> 89#include <netinet/udp.h>
90#include <netinet/udp_var.h> 90#include <netinet/udp_var.h>
91#include <netinet/in_var.h> 91#include <netinet/in_var.h>
92#include <netinet/in_pcb.h> 92#include <netinet/in_pcb.h>
93 93
94#ifdef INET6 94#ifdef INET6
95#include <netinet6/in6_var.h> 95#include <netinet6/in6_var.h>
96#include <netinet/ip6.h> 96#include <netinet/ip6.h>
97#include <netinet6/ip6_var.h> 97#include <netinet6/ip6_var.h>
98#include <netinet6/in6_pcb.h> 98#include <netinet6/in6_pcb.h>
99#include <netinet6/udp6_var.h> 99#include <netinet6/udp6_var.h>
100#endif /* INET6 */ 100#endif /* INET6 */
101 101
102#include <net/if_wg.h> 102#include <net/if_wg.h>
103 103
104#include <prop/proplib.h> 104#include <prop/proplib.h>
105 105
106#include <crypto/blake2/blake2s.h> 106#include <crypto/blake2/blake2s.h>
107#include <crypto/sodium/crypto_scalarmult.h> 107#include <crypto/sodium/crypto_scalarmult.h>
108#include <crypto/sodium/crypto_aead_chacha20poly1305.h> 108#include <crypto/sodium/crypto_aead_chacha20poly1305.h>
109#include <crypto/sodium/crypto_aead_xchacha20poly1305.h> 109#include <crypto/sodium/crypto_aead_xchacha20poly1305.h>
110 110
111#include "ioconf.h" 111#include "ioconf.h"
112 112
113#ifdef WG_RUMPKERNEL 113#ifdef WG_RUMPKERNEL
114#include "wg_user.h" 114#include "wg_user.h"
115#endif 115#endif
116 116
117/* 117/*
118 * Data structures 118 * Data structures
119 * - struct wg_softc is an instance of wg interfaces 119 * - struct wg_softc is an instance of wg interfaces
120 * - It has a list of peers (struct wg_peer) 120 * - It has a list of peers (struct wg_peer)
121 * - It has a kthread that sends/receives handshake messages and 121 * - It has a kthread that sends/receives handshake messages and
122 * runs event handlers 122 * runs event handlers
123 * - It has its own two routing tables: one is for IPv4 and the other IPv6 123 * - It has its own two routing tables: one is for IPv4 and the other IPv6
124 * - struct wg_peer is a representative of a peer 124 * - struct wg_peer is a representative of a peer
125 * - It has a softint that is used to send packets over an wg interface 125 * - It has a softint that is used to send packets over an wg interface
126 * to a peer 126 * to a peer
127 * - It has a pair of session instances (struct wg_session) 127 * - It has a pair of session instances (struct wg_session)
128 * - It has a pair of endpoint instances (struct wg_sockaddr) 128 * - It has a pair of endpoint instances (struct wg_sockaddr)
129 * - Normally one endpoint is used and the second one is used only on 129 * - Normally one endpoint is used and the second one is used only on
130 * a peer migration (a change of peer's IP address) 130 * a peer migration (a change of peer's IP address)
131 * - It has a list of IP addresses and sub networks called allowedips 131 * - It has a list of IP addresses and sub networks called allowedips
132 * (struct wg_allowedip) 132 * (struct wg_allowedip)
133 * - A packets sent over a session is allowed if its destination matches 133 * - A packets sent over a session is allowed if its destination matches
134 * any IP addresses or sub networks of the list 134 * any IP addresses or sub networks of the list
135 * - struct wg_session represents a session of a secure tunnel with a peer 135 * - struct wg_session represents a session of a secure tunnel with a peer
136 * - Two instances of sessions belong to a peer; a stable session and a 136 * - Two instances of sessions belong to a peer; a stable session and a
137 * unstable session 137 * unstable session
138 * - A handshake process of a session always starts with a unstable instace 138 * - A handshake process of a session always starts with a unstable instace
139 * - Once a session is established, its instance becomes stable and the 139 * - Once a session is established, its instance becomes stable and the
140 * other becomes unstable instead 140 * other becomes unstable instead
141 * - Data messages are always sent via a stable session 141 * - Data messages are always sent via a stable session
142 * 142 *
143 * Locking notes: 143 * Locking notes:
144 * - wg interfaces (struct wg_softc, wg) is listed in wg_softcs.list and 144 * - wg interfaces (struct wg_softc, wg) is listed in wg_softcs.list and
145 * protected by wg_softcs.lock 145 * protected by wg_softcs.lock
146 * - Each wg has a mutex(9) and a rwlock(9) 146 * - Each wg has a mutex(9) and a rwlock(9)
147 * - The mutex (wg_lock) protects its peer list (wg_peers) 147 * - The mutex (wg_lock) protects its peer list (wg_peers)
148 * - A peer on the list is also protected by pserialize(9) or psref(9) 148 * - A peer on the list is also protected by pserialize(9) or psref(9)
149 * - The rwlock (wg_rwlock) protects the routing tables (wg_rtable_ipv[46]) 149 * - The rwlock (wg_rwlock) protects the routing tables (wg_rtable_ipv[46])
150 * - Each peer (struct wg_peer, wgp) has a mutex 150 * - Each peer (struct wg_peer, wgp) has a mutex
151 * - The mutex (wgp_lock) protects wgp_session_unstable and wgp_state 151 * - The mutex (wgp_lock) protects wgp_session_unstable and wgp_state
152 * - Each session (struct wg_session, wgs) has a mutex 152 * - Each session (struct wg_session, wgs) has a mutex
153 * - The mutex (wgs_lock) protects its state (wgs_state) and its handshake 153 * - The mutex (wgs_lock) protects its state (wgs_state) and its handshake
154 * states 154 * states
155 * - wgs_state of a unstable session can be changed while it never be 155 * - wgs_state of a unstable session can be changed while it never be
156 * changed on a stable session, so once get a session instace via 156 * changed on a stable session, so once get a session instace via
157 * wgp_session_stable we can safely access wgs_state without 157 * wgp_session_stable we can safely access wgs_state without
158 * holding wgs_lock 158 * holding wgs_lock
159 * - A session is protected by pserialize or psref like wgp 159 * - A session is protected by pserialize or psref like wgp
160 * - On a session swap, we must wait for all readers to release a 160 * - On a session swap, we must wait for all readers to release a
161 * reference to a stable session before changing wgs_state and 161 * reference to a stable session before changing wgs_state and
162 * session states 162 * session states
163 */ 163 */
164 164
165 165
166#define WGLOG(level, fmt, args...) \ 166#define WGLOG(level, fmt, args...) \
167 log(level, "%s: " fmt, __func__, ##args) 167 log(level, "%s: " fmt, __func__, ##args)
168 168
169/* Debug options */ 169/* Debug options */
170#ifdef WG_DEBUG 170#ifdef WG_DEBUG
171/* Output debug logs */ 171/* Output debug logs */
172#ifndef WG_DEBUG_LOG 172#ifndef WG_DEBUG_LOG
173#define WG_DEBUG_LOG 173#define WG_DEBUG_LOG
174#endif 174#endif
175/* Output trace logs */ 175/* Output trace logs */
176#ifndef WG_DEBUG_TRACE 176#ifndef WG_DEBUG_TRACE
177#define WG_DEBUG_TRACE 177#define WG_DEBUG_TRACE
178#endif 178#endif
179/* Output hash values, etc. */ 179/* Output hash values, etc. */
180#ifndef WG_DEBUG_DUMP 180#ifndef WG_DEBUG_DUMP
181#define WG_DEBUG_DUMP 181#define WG_DEBUG_DUMP
182#endif 182#endif
183/* Make some internal parameters configurable for testing and debugging */ 183/* Make some internal parameters configurable for testing and debugging */
184#ifndef WG_DEBUG_PARAMS 184#ifndef WG_DEBUG_PARAMS
185#define WG_DEBUG_PARAMS 185#define WG_DEBUG_PARAMS
186#endif 186#endif
187#endif 187#endif
188 188
189#ifdef WG_DEBUG_TRACE 189#ifdef WG_DEBUG_TRACE
190#define WG_TRACE(msg) \ 190#define WG_TRACE(msg) \
191 log(LOG_DEBUG, "%s:%d: %s\n", __func__, __LINE__, (msg)) 191 log(LOG_DEBUG, "%s:%d: %s\n", __func__, __LINE__, (msg))
192#else 192#else
193#define WG_TRACE(msg) __nothing 193#define WG_TRACE(msg) __nothing
194#endif 194#endif
195 195
196#ifdef WG_DEBUG_LOG 196#ifdef WG_DEBUG_LOG
197#define WG_DLOG(fmt, args...) log(LOG_DEBUG, "%s: " fmt, __func__, ##args) 197#define WG_DLOG(fmt, args...) log(LOG_DEBUG, "%s: " fmt, __func__, ##args)
198#else 198#else
199#define WG_DLOG(fmt, args...) __nothing 199#define WG_DLOG(fmt, args...) __nothing
200#endif 200#endif
201 201
202#define WG_LOG_RATECHECK(wgprc, level, fmt, args...) do { \ 202#define WG_LOG_RATECHECK(wgprc, level, fmt, args...) do { \
203 if (ppsratecheck(&(wgprc)->wgprc_lasttime, \ 203 if (ppsratecheck(&(wgprc)->wgprc_lasttime, \
204 &(wgprc)->wgprc_curpps, 1)) { \ 204 &(wgprc)->wgprc_curpps, 1)) { \
205 log(level, fmt, ##args); \ 205 log(level, fmt, ##args); \
206 } \ 206 } \
207} while (0) 207} while (0)
208 208
209#ifdef WG_DEBUG_PARAMS 209#ifdef WG_DEBUG_PARAMS
210static bool wg_force_underload = false; 210static bool wg_force_underload = false;
211#endif 211#endif
212 212
213#ifdef WG_DEBUG_DUMP 213#ifdef WG_DEBUG_DUMP
214 214
215#ifdef WG_RUMPKERNEL 215#ifdef WG_RUMPKERNEL
216static void 216static void
217wg_dump_buf(const char *func, const char *buf, const size_t size) 217wg_dump_buf(const char *func, const char *buf, const size_t size)
218{ 218{
219 219
220 log(LOG_DEBUG, "%s: ", func); 220 log(LOG_DEBUG, "%s: ", func);
221 for (int i = 0; i < size; i++) 221 for (int i = 0; i < size; i++)
222 log(LOG_DEBUG, "%02x ", (int)(0xff & buf[i])); 222 log(LOG_DEBUG, "%02x ", (int)(0xff & buf[i]));
223 log(LOG_DEBUG, "\n"); 223 log(LOG_DEBUG, "\n");
224} 224}
225#endif 225#endif
226 226
227static void 227static void
228wg_dump_hash(const uint8_t *func, const uint8_t *name, const uint8_t *hash, 228wg_dump_hash(const uint8_t *func, const uint8_t *name, const uint8_t *hash,
229 const size_t size) 229 const size_t size)
230{ 230{
231 231
232 log(LOG_DEBUG, "%s: %s: ", func, name); 232 log(LOG_DEBUG, "%s: %s: ", func, name);
233 for (int i = 0; i < size; i++) 233 for (int i = 0; i < size; i++)
234 log(LOG_DEBUG, "%02x ", (int)(0xff & hash[i])); 234 log(LOG_DEBUG, "%02x ", (int)(0xff & hash[i]));
235 log(LOG_DEBUG, "\n"); 235 log(LOG_DEBUG, "\n");
236} 236}
237 237
238#define WG_DUMP_HASH(name, hash) \ 238#define WG_DUMP_HASH(name, hash) \
239 wg_dump_hash(__func__, name, hash, WG_HASH_LEN) 239 wg_dump_hash(__func__, name, hash, WG_HASH_LEN)
240#define WG_DUMP_HASH48(name, hash) \ 240#define WG_DUMP_HASH48(name, hash) \
241 wg_dump_hash(__func__, name, hash, 48) 241 wg_dump_hash(__func__, name, hash, 48)
242#define WG_DUMP_BUF(buf, size) \ 242#define WG_DUMP_BUF(buf, size) \
243 wg_dump_buf(__func__, buf, size) 243 wg_dump_buf(__func__, buf, size)
244#else 244#else
245#define WG_DUMP_HASH(name, hash) __nothing 245#define WG_DUMP_HASH(name, hash) __nothing
246#define WG_DUMP_HASH48(name, hash) __nothing 246#define WG_DUMP_HASH48(name, hash) __nothing
247#define WG_DUMP_BUF(buf, size) __nothing 247#define WG_DUMP_BUF(buf, size) __nothing
248#endif /* WG_DEBUG_DUMP */ 248#endif /* WG_DEBUG_DUMP */
249 249
250#define WG_MTU 1420 250#define WG_MTU 1420
251#define WG_ALLOWEDIPS 16 251#define WG_ALLOWEDIPS 16
252 252
253#define CURVE25519_KEY_LEN 32 253#define CURVE25519_KEY_LEN 32
254#define TAI64N_LEN sizeof(uint32_t) * 3 254#define TAI64N_LEN sizeof(uint32_t) * 3
255#define POLY1305_AUTHTAG_LEN 16 255#define POLY1305_AUTHTAG_LEN 16
256#define HMAC_BLOCK_LEN 64 256#define HMAC_BLOCK_LEN 64
257 257
258/* [N] 4.1: "DHLEN must be 32 or greater." WireGuard chooses 32. */ 258/* [N] 4.1: "DHLEN must be 32 or greater." WireGuard chooses 32. */
259/* [N] 4.3: Hash functions */ 259/* [N] 4.3: Hash functions */
260#define NOISE_DHLEN 32 260#define NOISE_DHLEN 32
261/* [N] 4.3: "Must be 32 or 64." WireGuard chooses 32. */ 261/* [N] 4.3: "Must be 32 or 64." WireGuard chooses 32. */
262#define NOISE_HASHLEN 32 262#define NOISE_HASHLEN 32
263#define NOISE_BLOCKLEN 64 263#define NOISE_BLOCKLEN 64
264#define NOISE_HKDF_OUTPUT_LEN NOISE_HASHLEN 264#define NOISE_HKDF_OUTPUT_LEN NOISE_HASHLEN
265/* [N] 5.1: "k" */ 265/* [N] 5.1: "k" */
266#define NOISE_CIPHER_KEY_LEN 32 266#define NOISE_CIPHER_KEY_LEN 32
267/* 267/*
268 * [N] 9.2: "psk" 268 * [N] 9.2: "psk"
269 * "... psk is a 32-byte secret value provided by the application." 269 * "... psk is a 32-byte secret value provided by the application."
270 */ 270 */
271#define NOISE_PRESHARED_KEY_LEN 32 271#define NOISE_PRESHARED_KEY_LEN 32
272 272
273#define WG_STATIC_KEY_LEN CURVE25519_KEY_LEN 273#define WG_STATIC_KEY_LEN CURVE25519_KEY_LEN
274#define WG_TIMESTAMP_LEN TAI64N_LEN 274#define WG_TIMESTAMP_LEN TAI64N_LEN
275 275
276#define WG_PRESHARED_KEY_LEN NOISE_PRESHARED_KEY_LEN 276#define WG_PRESHARED_KEY_LEN NOISE_PRESHARED_KEY_LEN
277 277
278#define WG_COOKIE_LEN 16 278#define WG_COOKIE_LEN 16
279#define WG_MAC_LEN 16 279#define WG_MAC_LEN 16
280#define WG_RANDVAL_LEN 24 280#define WG_RANDVAL_LEN 24
281 281
282#define WG_EPHEMERAL_KEY_LEN CURVE25519_KEY_LEN 282#define WG_EPHEMERAL_KEY_LEN CURVE25519_KEY_LEN
283/* [N] 5.2: "ck: A chaining key of HASHLEN bytes" */ 283/* [N] 5.2: "ck: A chaining key of HASHLEN bytes" */
284#define WG_CHAINING_KEY_LEN NOISE_HASHLEN 284#define WG_CHAINING_KEY_LEN NOISE_HASHLEN
285/* [N] 5.2: "h: A hash output of HASHLEN bytes" */ 285/* [N] 5.2: "h: A hash output of HASHLEN bytes" */
286#define WG_HASH_LEN NOISE_HASHLEN 286#define WG_HASH_LEN NOISE_HASHLEN
287#define WG_CIPHER_KEY_LEN NOISE_CIPHER_KEY_LEN 287#define WG_CIPHER_KEY_LEN NOISE_CIPHER_KEY_LEN
288#define WG_DH_OUTPUT_LEN NOISE_DHLEN 288#define WG_DH_OUTPUT_LEN NOISE_DHLEN
289#define WG_KDF_OUTPUT_LEN NOISE_HKDF_OUTPUT_LEN 289#define WG_KDF_OUTPUT_LEN NOISE_HKDF_OUTPUT_LEN
290#define WG_AUTHTAG_LEN POLY1305_AUTHTAG_LEN 290#define WG_AUTHTAG_LEN POLY1305_AUTHTAG_LEN
291#define WG_DATA_KEY_LEN 32 291#define WG_DATA_KEY_LEN 32
292#define WG_SALT_LEN 24 292#define WG_SALT_LEN 24
293 293
294/* 294/*
295 * The protocol messages 295 * The protocol messages
296 */ 296 */
297struct wg_msg { 297struct wg_msg {
298 uint32_t wgm_type; 298 uint32_t wgm_type;
299} __packed; 299} __packed;
300 300
301/* [W] 5.4.2 First Message: Initiator to Responder */ 301/* [W] 5.4.2 First Message: Initiator to Responder */
302struct wg_msg_init { 302struct wg_msg_init {
303 uint32_t wgmi_type; 303 uint32_t wgmi_type;
304 uint32_t wgmi_sender; 304 uint32_t wgmi_sender;
305 uint8_t wgmi_ephemeral[WG_EPHEMERAL_KEY_LEN]; 305 uint8_t wgmi_ephemeral[WG_EPHEMERAL_KEY_LEN];
306 uint8_t wgmi_static[WG_STATIC_KEY_LEN + WG_AUTHTAG_LEN]; 306 uint8_t wgmi_static[WG_STATIC_KEY_LEN + WG_AUTHTAG_LEN];
307 uint8_t wgmi_timestamp[WG_TIMESTAMP_LEN + WG_AUTHTAG_LEN]; 307 uint8_t wgmi_timestamp[WG_TIMESTAMP_LEN + WG_AUTHTAG_LEN];
308 uint8_t wgmi_mac1[WG_MAC_LEN]; 308 uint8_t wgmi_mac1[WG_MAC_LEN];
309 uint8_t wgmi_mac2[WG_MAC_LEN]; 309 uint8_t wgmi_mac2[WG_MAC_LEN];
310} __packed; 310} __packed;
311 311
312/* [W] 5.4.3 Second Message: Responder to Initiator */ 312/* [W] 5.4.3 Second Message: Responder to Initiator */
313struct wg_msg_resp { 313struct wg_msg_resp {
314 uint32_t wgmr_type; 314 uint32_t wgmr_type;
315 uint32_t wgmr_sender; 315 uint32_t wgmr_sender;
316 uint32_t wgmr_receiver; 316 uint32_t wgmr_receiver;
317 uint8_t wgmr_ephemeral[WG_EPHEMERAL_KEY_LEN]; 317 uint8_t wgmr_ephemeral[WG_EPHEMERAL_KEY_LEN];
318 uint8_t wgmr_empty[0 + WG_AUTHTAG_LEN]; 318 uint8_t wgmr_empty[0 + WG_AUTHTAG_LEN];
319 uint8_t wgmr_mac1[WG_MAC_LEN]; 319 uint8_t wgmr_mac1[WG_MAC_LEN];
320 uint8_t wgmr_mac2[WG_MAC_LEN]; 320 uint8_t wgmr_mac2[WG_MAC_LEN];
321} __packed; 321} __packed;
322 322
323/* [W] 5.4.6 Subsequent Messages: Transport Data Messages */ 323/* [W] 5.4.6 Subsequent Messages: Transport Data Messages */
324struct wg_msg_data { 324struct wg_msg_data {
325 uint32_t wgmd_type; 325 uint32_t wgmd_type;
326 uint32_t wgmd_receiver; 326 uint32_t wgmd_receiver;
327 uint64_t wgmd_counter; 327 uint64_t wgmd_counter;
328 uint32_t wgmd_packet[0]; 328 uint32_t wgmd_packet[0];
329} __packed; 329} __packed;
330 330
331/* [W] 5.4.7 Under Load: Cookie Reply Message */ 331/* [W] 5.4.7 Under Load: Cookie Reply Message */
332struct wg_msg_cookie { 332struct wg_msg_cookie {
333 uint32_t wgmc_type; 333 uint32_t wgmc_type;
334 uint32_t wgmc_receiver; 334 uint32_t wgmc_receiver;
335 uint8_t wgmc_salt[WG_SALT_LEN]; 335 uint8_t wgmc_salt[WG_SALT_LEN];
336 uint8_t wgmc_cookie[WG_COOKIE_LEN + WG_AUTHTAG_LEN]; 336 uint8_t wgmc_cookie[WG_COOKIE_LEN + WG_AUTHTAG_LEN];
337} __packed; 337} __packed;
338 338
339#define WG_MSG_TYPE_INIT 1 339#define WG_MSG_TYPE_INIT 1
340#define WG_MSG_TYPE_RESP 2 340#define WG_MSG_TYPE_RESP 2
341#define WG_MSG_TYPE_COOKIE 3 341#define WG_MSG_TYPE_COOKIE 3
342#define WG_MSG_TYPE_DATA 4 342#define WG_MSG_TYPE_DATA 4
343#define WG_MSG_TYPE_MAX WG_MSG_TYPE_DATA 343#define WG_MSG_TYPE_MAX WG_MSG_TYPE_DATA
344 344
345/* Sliding windows */ 345/* Sliding windows */
346 346
347#define SLIWIN_BITS 2048u 347#define SLIWIN_BITS 2048u
348#define SLIWIN_TYPE uint32_t 348#define SLIWIN_TYPE uint32_t
349#define SLIWIN_BPW NBBY*sizeof(SLIWIN_TYPE) 349#define SLIWIN_BPW NBBY*sizeof(SLIWIN_TYPE)
350#define SLIWIN_WORDS howmany(SLIWIN_BITS, SLIWIN_BPW) 350#define SLIWIN_WORDS howmany(SLIWIN_BITS, SLIWIN_BPW)
351#define SLIWIN_NPKT (SLIWIN_BITS - NBBY*sizeof(SLIWIN_TYPE)) 351#define SLIWIN_NPKT (SLIWIN_BITS - NBBY*sizeof(SLIWIN_TYPE))
352 352
353struct sliwin { 353struct sliwin {
354 SLIWIN_TYPE B[SLIWIN_WORDS]; 354 SLIWIN_TYPE B[SLIWIN_WORDS];
355 uint64_t T; 355 uint64_t T;
356}; 356};
357 357
358static void 358static void
359sliwin_reset(struct sliwin *W) 359sliwin_reset(struct sliwin *W)
360{ 360{
361 361
362 memset(W, 0, sizeof(*W)); 362 memset(W, 0, sizeof(*W));
363} 363}
364 364
365static int 365static int
366sliwin_check_fast(const volatile struct sliwin *W, uint64_t S) 366sliwin_check_fast(const volatile struct sliwin *W, uint64_t S)
367{ 367{
368 368
369 /* 369 /*
370 * If it's more than one window older than the highest sequence 370 * If it's more than one window older than the highest sequence
371 * number we've seen, reject. 371 * number we've seen, reject.
372 */ 372 */
373#ifdef __HAVE_ATOMIC64_LOADSTORE 373#ifdef __HAVE_ATOMIC64_LOADSTORE
374 if (S + SLIWIN_NPKT < atomic_load_relaxed(&W->T)) 374 if (S + SLIWIN_NPKT < atomic_load_relaxed(&W->T))
375 return EAUTH; 375 return EAUTH;
376#endif 376#endif
377 377
378 /* 378 /*
379 * Otherwise, we need to take the lock to decide, so don't 379 * Otherwise, we need to take the lock to decide, so don't
380 * reject just yet. Caller must serialize a call to 380 * reject just yet. Caller must serialize a call to
381 * sliwin_update in this case. 381 * sliwin_update in this case.
382 */ 382 */
383 return 0; 383 return 0;
384} 384}
385 385
386static int 386static int
387sliwin_update(struct sliwin *W, uint64_t S) 387sliwin_update(struct sliwin *W, uint64_t S)
388{ 388{
389 unsigned word, bit; 389 unsigned word, bit;
390 390
391 /* 391 /*
392 * If it's more than one window older than the highest sequence 392 * If it's more than one window older than the highest sequence
393 * number we've seen, reject. 393 * number we've seen, reject.
394 */ 394 */
395 if (S + SLIWIN_NPKT < W->T) 395 if (S + SLIWIN_NPKT < W->T)
396 return EAUTH; 396 return EAUTH;
397 397
398 /* 398 /*
399 * If it's higher than the highest sequence number we've seen, 399 * If it's higher than the highest sequence number we've seen,
400 * advance the window. 400 * advance the window.
401 */ 401 */
402 if (S > W->T) { 402 if (S > W->T) {
403 uint64_t i = W->T / SLIWIN_BPW; 403 uint64_t i = W->T / SLIWIN_BPW;
404 uint64_t j = S / SLIWIN_BPW; 404 uint64_t j = S / SLIWIN_BPW;
405 unsigned k; 405 unsigned k;
406 406
407 for (k = 0; k < MIN(j - i, SLIWIN_WORDS); k++) 407 for (k = 0; k < MIN(j - i, SLIWIN_WORDS); k++)
408 W->B[(i + k + 1) % SLIWIN_WORDS] = 0; 408 W->B[(i + k + 1) % SLIWIN_WORDS] = 0;
409#ifdef __HAVE_ATOMIC64_LOADSTORE 409#ifdef __HAVE_ATOMIC64_LOADSTORE
410 atomic_store_relaxed(&W->T, S); 410 atomic_store_relaxed(&W->T, S);
411#else 411#else
412 W->T = S; 412 W->T = S;
413#endif 413#endif
414 } 414 }
415 415
416 /* Test and set the bit -- if already set, reject. */ 416 /* Test and set the bit -- if already set, reject. */
417 word = (S / SLIWIN_BPW) % SLIWIN_WORDS; 417 word = (S / SLIWIN_BPW) % SLIWIN_WORDS;
418 bit = S % SLIWIN_BPW; 418 bit = S % SLIWIN_BPW;
419 if (W->B[word] & (1UL << bit)) 419 if (W->B[word] & (1UL << bit))
420 return EAUTH; 420 return EAUTH;
421 W->B[word] |= 1UL << bit; 421 W->B[word] |= 1UL << bit;
422 422
423 /* Accept! */ 423 /* Accept! */
424 return 0; 424 return 0;
425} 425}
426 426
427struct wg_worker { 427struct wg_worker {
428 kmutex_t wgw_lock; 428 kmutex_t wgw_lock;
429 kcondvar_t wgw_cv; 429 kcondvar_t wgw_cv;
430 bool wgw_todie; 430 bool wgw_todie;
431 struct socket *wgw_so4; 431 struct socket *wgw_so4;
432 struct socket *wgw_so6; 432 struct socket *wgw_so6;
433 int wgw_wakeup_reasons; 433 int wgw_wakeup_reasons;
434#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4 __BIT(0) 434#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4 __BIT(0)
435#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6 __BIT(1) 435#define WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6 __BIT(1)
436#define WG_WAKEUP_REASON_PEER __BIT(2) 436#define WG_WAKEUP_REASON_PEER __BIT(2)
437}; 437};
438 438
439struct wg_session { 439struct wg_session {
440 struct wg_peer *wgs_peer; 440 struct wg_peer *wgs_peer;
441 struct psref_target 441 struct psref_target
442 wgs_psref; 442 wgs_psref;
443 kmutex_t *wgs_lock; 443 kmutex_t *wgs_lock;
444 444
445 int wgs_state; 445 int wgs_state;
446#define WGS_STATE_UNKNOWN 0 446#define WGS_STATE_UNKNOWN 0
447#define WGS_STATE_INIT_ACTIVE 1 447#define WGS_STATE_INIT_ACTIVE 1
448#define WGS_STATE_INIT_PASSIVE 2 448#define WGS_STATE_INIT_PASSIVE 2
449#define WGS_STATE_ESTABLISHED 3 449#define WGS_STATE_ESTABLISHED 3
450#define WGS_STATE_DESTROYING 4 450#define WGS_STATE_DESTROYING 4
451 451
452 time_t wgs_time_established; 452 time_t wgs_time_established;
453 time_t wgs_time_last_data_sent; 453 time_t wgs_time_last_data_sent;
454 bool wgs_is_initiator; 454 bool wgs_is_initiator;
455 455
456 uint32_t wgs_sender_index; 456 uint32_t wgs_sender_index;
457 uint32_t wgs_receiver_index; 457 uint32_t wgs_receiver_index;
458#ifdef __HAVE_ATOMIC64_LOADSTORE 458#ifdef __HAVE_ATOMIC64_LOADSTORE
459 volatile uint64_t 459 volatile uint64_t
460 wgs_send_counter; 460 wgs_send_counter;
461#else 461#else
462 kmutex_t wgs_send_counter_lock; 462 kmutex_t wgs_send_counter_lock;
463 uint64_t wgs_send_counter; 463 uint64_t wgs_send_counter;
464#endif 464#endif
465 465
466 struct { 466 struct {
467 kmutex_t lock; 467 kmutex_t lock;
468 struct sliwin window; 468 struct sliwin window;
469 } *wgs_recvwin; 469 } *wgs_recvwin;
470 470
471 uint8_t wgs_handshake_hash[WG_HASH_LEN]; 471 uint8_t wgs_handshake_hash[WG_HASH_LEN];
472 uint8_t wgs_chaining_key[WG_CHAINING_KEY_LEN]; 472 uint8_t wgs_chaining_key[WG_CHAINING_KEY_LEN];
473 uint8_t wgs_ephemeral_key_pub[WG_EPHEMERAL_KEY_LEN]; 473 uint8_t wgs_ephemeral_key_pub[WG_EPHEMERAL_KEY_LEN];
474 uint8_t wgs_ephemeral_key_priv[WG_EPHEMERAL_KEY_LEN]; 474 uint8_t wgs_ephemeral_key_priv[WG_EPHEMERAL_KEY_LEN];
475 uint8_t wgs_ephemeral_key_peer[WG_EPHEMERAL_KEY_LEN]; 475 uint8_t wgs_ephemeral_key_peer[WG_EPHEMERAL_KEY_LEN];
476 uint8_t wgs_tkey_send[WG_DATA_KEY_LEN]; 476 uint8_t wgs_tkey_send[WG_DATA_KEY_LEN];
477 uint8_t wgs_tkey_recv[WG_DATA_KEY_LEN]; 477 uint8_t wgs_tkey_recv[WG_DATA_KEY_LEN];
478}; 478};
479 479
480struct wg_sockaddr { 480struct wg_sockaddr {
481 union { 481 union {
482 struct sockaddr_storage _ss; 482 struct sockaddr_storage _ss;
483 struct sockaddr _sa; 483 struct sockaddr _sa;
484 struct sockaddr_in _sin; 484 struct sockaddr_in _sin;
485 struct sockaddr_in6 _sin6; 485 struct sockaddr_in6 _sin6;
486 }; 486 };
487 struct psref_target wgsa_psref; 487 struct psref_target wgsa_psref;
488}; 488};
489 489
490#define wgsatosa(wgsa) (&(wgsa)->_sa) 490#define wgsatosa(wgsa) (&(wgsa)->_sa)
491#define wgsatosin(wgsa) (&(wgsa)->_sin) 491#define wgsatosin(wgsa) (&(wgsa)->_sin)
492#define wgsatosin6(wgsa) (&(wgsa)->_sin6) 492#define wgsatosin6(wgsa) (&(wgsa)->_sin6)
493 493
494struct wg_peer; 494struct wg_peer;
495struct wg_allowedip { 495struct wg_allowedip {
496 struct radix_node wga_nodes[2]; 496 struct radix_node wga_nodes[2];
497 struct wg_sockaddr _wga_sa_addr; 497 struct wg_sockaddr _wga_sa_addr;
498 struct wg_sockaddr _wga_sa_mask; 498 struct wg_sockaddr _wga_sa_mask;
499#define wga_sa_addr _wga_sa_addr._sa 499#define wga_sa_addr _wga_sa_addr._sa
500#define wga_sa_mask _wga_sa_mask._sa 500#define wga_sa_mask _wga_sa_mask._sa
501 501
502 int wga_family; 502 int wga_family;
503 uint8_t wga_cidr; 503 uint8_t wga_cidr;
504 union { 504 union {
505 struct in_addr _ip4; 505 struct in_addr _ip4;
506 struct in6_addr _ip6; 506 struct in6_addr _ip6;
507 } wga_addr; 507 } wga_addr;
508#define wga_addr4 wga_addr._ip4 508#define wga_addr4 wga_addr._ip4
509#define wga_addr6 wga_addr._ip6 509#define wga_addr6 wga_addr._ip6
510 510
511 struct wg_peer *wga_peer; 511 struct wg_peer *wga_peer;
512}; 512};
513 513
514typedef uint8_t wg_timestamp_t[WG_TIMESTAMP_LEN]; 514typedef uint8_t wg_timestamp_t[WG_TIMESTAMP_LEN];
515 515
516struct wg_ppsratecheck { 516struct wg_ppsratecheck {
517 struct timeval wgprc_lasttime; 517 struct timeval wgprc_lasttime;
518 int wgprc_curpps; 518 int wgprc_curpps;
519}; 519};
520 520
521struct wg_softc; 521struct wg_softc;
522struct wg_peer { 522struct wg_peer {
523 struct wg_softc *wgp_sc; 523 struct wg_softc *wgp_sc;
524 char wgp_name[WG_PEER_NAME_MAXLEN + 1]; 524 char wgp_name[WG_PEER_NAME_MAXLEN + 1];
525 struct pslist_entry wgp_peerlist_entry; 525 struct pslist_entry wgp_peerlist_entry;
526 pserialize_t wgp_psz; 526 pserialize_t wgp_psz;
527 struct psref_target wgp_psref; 527 struct psref_target wgp_psref;
528 kmutex_t *wgp_lock; 528 kmutex_t *wgp_lock;
529 529
530 uint8_t wgp_pubkey[WG_STATIC_KEY_LEN]; 530 uint8_t wgp_pubkey[WG_STATIC_KEY_LEN];
531 struct wg_sockaddr *wgp_endpoint; 531 struct wg_sockaddr *wgp_endpoint;
532#define wgp_ss wgp_endpoint->_ss 532#define wgp_ss wgp_endpoint->_ss
533#define wgp_sa wgp_endpoint->_sa 533#define wgp_sa wgp_endpoint->_sa
534#define wgp_sin wgp_endpoint->_sin 534#define wgp_sin wgp_endpoint->_sin
535#define wgp_sin6 wgp_endpoint->_sin6 535#define wgp_sin6 wgp_endpoint->_sin6
536 struct wg_sockaddr *wgp_endpoint0; 536 struct wg_sockaddr *wgp_endpoint0;
537 bool wgp_endpoint_changing; 537 bool wgp_endpoint_changing;
538 bool wgp_endpoint_available; 538 bool wgp_endpoint_available;
539 539
540 /* The preshared key (optional) */ 540 /* The preshared key (optional) */
541 uint8_t wgp_psk[WG_PRESHARED_KEY_LEN]; 541 uint8_t wgp_psk[WG_PRESHARED_KEY_LEN];
542 542
543 int wgp_state; 543 int wgp_state;
544#define WGP_STATE_INIT 0 544#define WGP_STATE_INIT 0
545#define WGP_STATE_ESTABLISHED 1 545#define WGP_STATE_ESTABLISHED 1
546#define WGP_STATE_GIVEUP 2 546#define WGP_STATE_GIVEUP 2
547#define WGP_STATE_DESTROYING 3 547#define WGP_STATE_DESTROYING 3
548 548
549 void *wgp_si; 549 void *wgp_si;
550 pcq_t *wgp_q; 550 pcq_t *wgp_q;
551 551
552 struct wg_session *wgp_session_stable; 552 struct wg_session *wgp_session_stable;
553 struct wg_session *wgp_session_unstable; 553 struct wg_session *wgp_session_unstable;
554 554
555 /* timestamp in big-endian */ 555 /* timestamp in big-endian */
556 wg_timestamp_t wgp_timestamp_latest_init; 556 wg_timestamp_t wgp_timestamp_latest_init;
557 557
558 struct timespec wgp_last_handshake_time; 558 struct timespec wgp_last_handshake_time;
559 559
560 callout_t wgp_rekey_timer; 560 callout_t wgp_rekey_timer;
561 callout_t wgp_handshake_timeout_timer; 561 callout_t wgp_handshake_timeout_timer;
562 callout_t wgp_session_dtor_timer; 562 callout_t wgp_session_dtor_timer;
563 563
564 time_t wgp_handshake_start_time; 564 time_t wgp_handshake_start_time;
565 565
566 int wgp_n_allowedips; 566 int wgp_n_allowedips;
567 struct wg_allowedip wgp_allowedips[WG_ALLOWEDIPS]; 567 struct wg_allowedip wgp_allowedips[WG_ALLOWEDIPS];
568 568
569 time_t wgp_latest_cookie_time; 569 time_t wgp_latest_cookie_time;
570 uint8_t wgp_latest_cookie[WG_COOKIE_LEN]; 570 uint8_t wgp_latest_cookie[WG_COOKIE_LEN];
571 uint8_t wgp_last_sent_mac1[WG_MAC_LEN]; 571 uint8_t wgp_last_sent_mac1[WG_MAC_LEN];
572 bool wgp_last_sent_mac1_valid; 572 bool wgp_last_sent_mac1_valid;
573 uint8_t wgp_last_sent_cookie[WG_COOKIE_LEN]; 573 uint8_t wgp_last_sent_cookie[WG_COOKIE_LEN];
574 bool wgp_last_sent_cookie_valid; 574 bool wgp_last_sent_cookie_valid;
575 575
576 time_t wgp_last_msg_received_time[WG_MSG_TYPE_MAX]; 576 time_t wgp_last_msg_received_time[WG_MSG_TYPE_MAX];
577 577
578 time_t wgp_last_genrandval_time; 578 time_t wgp_last_genrandval_time;
579 uint32_t wgp_randval; 579 uint32_t wgp_randval;
580 580
581 struct wg_ppsratecheck wgp_ppsratecheck; 581 struct wg_ppsratecheck wgp_ppsratecheck;
582 582
583 volatile unsigned int wgp_tasks; 583 volatile unsigned int wgp_tasks;
584#define WGP_TASK_SEND_INIT_MESSAGE __BIT(0) 584#define WGP_TASK_SEND_INIT_MESSAGE __BIT(0)
585#define WGP_TASK_ENDPOINT_CHANGED __BIT(1) 585#define WGP_TASK_ENDPOINT_CHANGED __BIT(1)
586#define WGP_TASK_SEND_KEEPALIVE_MESSAGE __BIT(2) 586#define WGP_TASK_SEND_KEEPALIVE_MESSAGE __BIT(2)
587#define WGP_TASK_DESTROY_PREV_SESSION __BIT(3) 587#define WGP_TASK_DESTROY_PREV_SESSION __BIT(3)
588}; 588};
589 589
590struct wg_ops; 590struct wg_ops;
591 591
592struct wg_softc { 592struct wg_softc {
593 struct ifnet wg_if; 593 struct ifnet wg_if;
594 LIST_ENTRY(wg_softc) wg_list; 594 LIST_ENTRY(wg_softc) wg_list;
595 kmutex_t *wg_lock; 595 kmutex_t *wg_lock;
596 krwlock_t *wg_rwlock; 596 krwlock_t *wg_rwlock;
597 597
598 uint8_t wg_privkey[WG_STATIC_KEY_LEN]; 598 uint8_t wg_privkey[WG_STATIC_KEY_LEN];
599 uint8_t wg_pubkey[WG_STATIC_KEY_LEN]; 599 uint8_t wg_pubkey[WG_STATIC_KEY_LEN];
600 600
601 int wg_npeers; 601 int wg_npeers;
602 struct pslist_head wg_peers; 602 struct pslist_head wg_peers;
603 uint16_t wg_listen_port; 603 uint16_t wg_listen_port;
604 604
605 struct wg_worker *wg_worker; 605 struct wg_worker *wg_worker;
606 lwp_t *wg_worker_lwp; 606 lwp_t *wg_worker_lwp;
607 607
608 struct radix_node_head *wg_rtable_ipv4; 608 struct radix_node_head *wg_rtable_ipv4;
609 struct radix_node_head *wg_rtable_ipv6; 609 struct radix_node_head *wg_rtable_ipv6;
610 610
611 struct wg_ppsratecheck wg_ppsratecheck; 611 struct wg_ppsratecheck wg_ppsratecheck;
612 612
613 struct wg_ops *wg_ops; 613 struct wg_ops *wg_ops;
614 614
615#ifdef WG_RUMPKERNEL 615#ifdef WG_RUMPKERNEL
616 struct wg_user *wg_user; 616 struct wg_user *wg_user;
617#endif 617#endif
618}; 618};
619 619
620/* [W] 6.1 Preliminaries */ 620/* [W] 6.1 Preliminaries */
621#define WG_REKEY_AFTER_MESSAGES (1ULL << 60) 621#define WG_REKEY_AFTER_MESSAGES (1ULL << 60)
622#define WG_REJECT_AFTER_MESSAGES (UINT64_MAX - (1 << 13)) 622#define WG_REJECT_AFTER_MESSAGES (UINT64_MAX - (1 << 13))
623#define WG_REKEY_AFTER_TIME 120 623#define WG_REKEY_AFTER_TIME 120
624#define WG_REJECT_AFTER_TIME 180 624#define WG_REJECT_AFTER_TIME 180
625#define WG_REKEY_ATTEMPT_TIME 90 625#define WG_REKEY_ATTEMPT_TIME 90
626#define WG_REKEY_TIMEOUT 5 626#define WG_REKEY_TIMEOUT 5
627#define WG_KEEPALIVE_TIMEOUT 10 627#define WG_KEEPALIVE_TIMEOUT 10
628 628
629#define WG_COOKIE_TIME 120 629#define WG_COOKIE_TIME 120
630#define WG_RANDVAL_TIME (2 * 60) 630#define WG_RANDVAL_TIME (2 * 60)
631 631
632static uint64_t wg_rekey_after_messages = WG_REKEY_AFTER_MESSAGES; 632static uint64_t wg_rekey_after_messages = WG_REKEY_AFTER_MESSAGES;
633static uint64_t wg_reject_after_messages = WG_REJECT_AFTER_MESSAGES; 633static uint64_t wg_reject_after_messages = WG_REJECT_AFTER_MESSAGES;
634static unsigned wg_rekey_after_time = WG_REKEY_AFTER_TIME; 634static unsigned wg_rekey_after_time = WG_REKEY_AFTER_TIME;
635static unsigned wg_reject_after_time = WG_REJECT_AFTER_TIME; 635static unsigned wg_reject_after_time = WG_REJECT_AFTER_TIME;
636static unsigned wg_rekey_attempt_time = WG_REKEY_ATTEMPT_TIME; 636static unsigned wg_rekey_attempt_time = WG_REKEY_ATTEMPT_TIME;
637static unsigned wg_rekey_timeout = WG_REKEY_TIMEOUT; 637static unsigned wg_rekey_timeout = WG_REKEY_TIMEOUT;
638static unsigned wg_keepalive_timeout = WG_KEEPALIVE_TIMEOUT; 638static unsigned wg_keepalive_timeout = WG_KEEPALIVE_TIMEOUT;
639 639
640static struct mbuf * 640static struct mbuf *
641 wg_get_mbuf(size_t, size_t); 641 wg_get_mbuf(size_t, size_t);
642 642
643static void wg_wakeup_worker(struct wg_worker *, int); 643static void wg_wakeup_worker(struct wg_worker *, int);
644 644
645static int wg_send_data_msg(struct wg_peer *, struct wg_session *, 645static int wg_send_data_msg(struct wg_peer *, struct wg_session *,
646 struct mbuf *); 646 struct mbuf *);
647static int wg_send_cookie_msg(struct wg_softc *, struct wg_peer *, 647static int wg_send_cookie_msg(struct wg_softc *, struct wg_peer *,
648 const uint32_t, const uint8_t [], const struct sockaddr *); 648 const uint32_t, const uint8_t [], const struct sockaddr *);
649static int wg_send_handshake_msg_resp(struct wg_softc *, 649static int wg_send_handshake_msg_resp(struct wg_softc *,
650 struct wg_peer *, const struct wg_msg_init *); 650 struct wg_peer *, const struct wg_msg_init *);
651static void wg_send_keepalive_msg(struct wg_peer *, struct wg_session *); 651static void wg_send_keepalive_msg(struct wg_peer *, struct wg_session *);
652 652
653static struct wg_peer * 653static struct wg_peer *
654 wg_pick_peer_by_sa(struct wg_softc *, const struct sockaddr *, 654 wg_pick_peer_by_sa(struct wg_softc *, const struct sockaddr *,
655 struct psref *); 655 struct psref *);
656static struct wg_peer * 656static struct wg_peer *
657 wg_lookup_peer_by_pubkey(struct wg_softc *, 657 wg_lookup_peer_by_pubkey(struct wg_softc *,
658 const uint8_t [], struct psref *); 658 const uint8_t [], struct psref *);
659 659
660static struct wg_session * 660static struct wg_session *
661 wg_lookup_session_by_index(struct wg_softc *, 661 wg_lookup_session_by_index(struct wg_softc *,
662 const uint32_t, struct psref *); 662 const uint32_t, struct psref *);
663 663
664static void wg_update_endpoint_if_necessary(struct wg_peer *, 664static void wg_update_endpoint_if_necessary(struct wg_peer *,
665 const struct sockaddr *); 665 const struct sockaddr *);
666 666
667static void wg_schedule_rekey_timer(struct wg_peer *); 667static void wg_schedule_rekey_timer(struct wg_peer *);
668static void wg_schedule_session_dtor_timer(struct wg_peer *); 668static void wg_schedule_session_dtor_timer(struct wg_peer *);
669static void wg_stop_session_dtor_timer(struct wg_peer *); 669static void wg_stop_session_dtor_timer(struct wg_peer *);
670 670
671static bool wg_is_underload(struct wg_softc *, struct wg_peer *, int); 671static bool wg_is_underload(struct wg_softc *, struct wg_peer *, int);
672static void wg_calculate_keys(struct wg_session *, const bool); 672static void wg_calculate_keys(struct wg_session *, const bool);
673 673
674static void wg_clear_states(struct wg_session *); 674static void wg_clear_states(struct wg_session *);
675 675
676static void wg_get_peer(struct wg_peer *, struct psref *); 676static void wg_get_peer(struct wg_peer *, struct psref *);
677static void wg_put_peer(struct wg_peer *, struct psref *); 677static void wg_put_peer(struct wg_peer *, struct psref *);
678 678
679static int wg_send_so(struct wg_peer *, struct mbuf *); 679static int wg_send_so(struct wg_peer *, struct mbuf *);
680static int wg_send_udp(struct wg_peer *, struct mbuf *); 680static int wg_send_udp(struct wg_peer *, struct mbuf *);
681static int wg_output(struct ifnet *, struct mbuf *, 681static int wg_output(struct ifnet *, struct mbuf *,
682 const struct sockaddr *, const struct rtentry *); 682 const struct sockaddr *, const struct rtentry *);
683static void wg_input(struct ifnet *, struct mbuf *, const int); 683static void wg_input(struct ifnet *, struct mbuf *, const int);
684static int wg_ioctl(struct ifnet *, u_long, void *); 684static int wg_ioctl(struct ifnet *, u_long, void *);
685static int wg_bind_port(struct wg_softc *, const uint16_t); 685static int wg_bind_port(struct wg_softc *, const uint16_t);
686static int wg_init(struct ifnet *); 686static int wg_init(struct ifnet *);
687static void wg_stop(struct ifnet *, int); 687static void wg_stop(struct ifnet *, int);
688 688
689static int wg_clone_create(struct if_clone *, int); 689static int wg_clone_create(struct if_clone *, int);
690static int wg_clone_destroy(struct ifnet *); 690static int wg_clone_destroy(struct ifnet *);
691 691
692struct wg_ops { 692struct wg_ops {
693 int (*send_hs_msg)(struct wg_peer *, struct mbuf *); 693 int (*send_hs_msg)(struct wg_peer *, struct mbuf *);
694 int (*send_data_msg)(struct wg_peer *, struct mbuf *); 694 int (*send_data_msg)(struct wg_peer *, struct mbuf *);
695 void (*input)(struct ifnet *, struct mbuf *, const int); 695 void (*input)(struct ifnet *, struct mbuf *, const int);
696 int (*bind_port)(struct wg_softc *, const uint16_t); 696 int (*bind_port)(struct wg_softc *, const uint16_t);
697}; 697};
698 698
699struct wg_ops wg_ops_rumpkernel = { 699struct wg_ops wg_ops_rumpkernel = {
700 .send_hs_msg = wg_send_so, 700 .send_hs_msg = wg_send_so,
701 .send_data_msg = wg_send_udp, 701 .send_data_msg = wg_send_udp,
702 .input = wg_input, 702 .input = wg_input,
703 .bind_port = wg_bind_port, 703 .bind_port = wg_bind_port,
704}; 704};
705 705
706#ifdef WG_RUMPKERNEL 706#ifdef WG_RUMPKERNEL
707static bool wg_user_mode(struct wg_softc *); 707static bool wg_user_mode(struct wg_softc *);
708static int wg_ioctl_linkstr(struct wg_softc *, struct ifdrv *); 708static int wg_ioctl_linkstr(struct wg_softc *, struct ifdrv *);
709 709
710static int wg_send_user(struct wg_peer *, struct mbuf *); 710static int wg_send_user(struct wg_peer *, struct mbuf *);
711static void wg_input_user(struct ifnet *, struct mbuf *, const int); 711static void wg_input_user(struct ifnet *, struct mbuf *, const int);
712static int wg_bind_port_user(struct wg_softc *, const uint16_t); 712static int wg_bind_port_user(struct wg_softc *, const uint16_t);
713 713
714struct wg_ops wg_ops_rumpuser = { 714struct wg_ops wg_ops_rumpuser = {
715 .send_hs_msg = wg_send_user, 715 .send_hs_msg = wg_send_user,
716 .send_data_msg = wg_send_user, 716 .send_data_msg = wg_send_user,
717 .input = wg_input_user, 717 .input = wg_input_user,
718 .bind_port = wg_bind_port_user, 718 .bind_port = wg_bind_port_user,
719}; 719};
720#endif 720#endif
721 721
722#define WG_PEER_READER_FOREACH(wgp, wg) \ 722#define WG_PEER_READER_FOREACH(wgp, wg) \
723 PSLIST_READER_FOREACH((wgp), &(wg)->wg_peers, struct wg_peer, \ 723 PSLIST_READER_FOREACH((wgp), &(wg)->wg_peers, struct wg_peer, \
724 wgp_peerlist_entry) 724 wgp_peerlist_entry)
725#define WG_PEER_WRITER_FOREACH(wgp, wg) \ 725#define WG_PEER_WRITER_FOREACH(wgp, wg) \
726 PSLIST_WRITER_FOREACH((wgp), &(wg)->wg_peers, struct wg_peer, \ 726 PSLIST_WRITER_FOREACH((wgp), &(wg)->wg_peers, struct wg_peer, \
727 wgp_peerlist_entry) 727 wgp_peerlist_entry)
728#define WG_PEER_WRITER_INSERT_HEAD(wgp, wg) \ 728#define WG_PEER_WRITER_INSERT_HEAD(wgp, wg) \
729 PSLIST_WRITER_INSERT_HEAD(&(wg)->wg_peers, (wgp), wgp_peerlist_entry) 729 PSLIST_WRITER_INSERT_HEAD(&(wg)->wg_peers, (wgp), wgp_peerlist_entry)
730#define WG_PEER_WRITER_REMOVE(wgp) \ 730#define WG_PEER_WRITER_REMOVE(wgp) \
731 PSLIST_WRITER_REMOVE((wgp), wgp_peerlist_entry) 731 PSLIST_WRITER_REMOVE((wgp), wgp_peerlist_entry)
732 732
733struct wg_route { 733struct wg_route {
734 struct radix_node wgr_nodes[2]; 734 struct radix_node wgr_nodes[2];
735 struct wg_peer *wgr_peer; 735 struct wg_peer *wgr_peer;
736}; 736};
737 737
738static struct radix_node_head * 738static struct radix_node_head *
739wg_rnh(struct wg_softc *wg, const int family) 739wg_rnh(struct wg_softc *wg, const int family)
740{ 740{
741 741
742 switch (family) { 742 switch (family) {
743 case AF_INET: 743 case AF_INET:
744 return wg->wg_rtable_ipv4; 744 return wg->wg_rtable_ipv4;
745#ifdef INET6 745#ifdef INET6
746 case AF_INET6: 746 case AF_INET6:
747 return wg->wg_rtable_ipv6; 747 return wg->wg_rtable_ipv6;
748#endif 748#endif
749 default: 749 default:
750 return NULL; 750 return NULL;
751 } 751 }
752} 752}
753 753
754 754
755/* 755/*
756 * Global variables 756 * Global variables
757 */ 757 */
758LIST_HEAD(wg_sclist, wg_softc); 758LIST_HEAD(wg_sclist, wg_softc);
759static struct { 759static struct {
760 struct wg_sclist list; 760 struct wg_sclist list;
761 kmutex_t lock; 761 kmutex_t lock;
762} wg_softcs __cacheline_aligned; 762} wg_softcs __cacheline_aligned;
763 763
764struct psref_class *wg_psref_class __read_mostly; 764struct psref_class *wg_psref_class __read_mostly;
765 765
766static struct if_clone wg_cloner = 766static struct if_clone wg_cloner =
767 IF_CLONE_INITIALIZER("wg", wg_clone_create, wg_clone_destroy); 767 IF_CLONE_INITIALIZER("wg", wg_clone_create, wg_clone_destroy);
768 768
769 769
770void wgattach(int); 770void wgattach(int);
771/* ARGSUSED */ 771/* ARGSUSED */
772void 772void
773wgattach(int count) 773wgattach(int count)
774{ 774{
775 /* 775 /*
776 * Nothing to do here, initialization is handled by the 776 * Nothing to do here, initialization is handled by the
777 * module initialization code in wginit() below). 777 * module initialization code in wginit() below).
778 */ 778 */
779} 779}
780 780
781static void 781static void
782wginit(void) 782wginit(void)
783{ 783{
784 784
785 wg_psref_class = psref_class_create("wg", IPL_SOFTNET); 785 wg_psref_class = psref_class_create("wg", IPL_SOFTNET);
786 786
787 mutex_init(&wg_softcs.lock, MUTEX_DEFAULT, IPL_NONE); 787 mutex_init(&wg_softcs.lock, MUTEX_DEFAULT, IPL_NONE);
788 LIST_INIT(&wg_softcs.list); 788 LIST_INIT(&wg_softcs.list);
789 if_clone_attach(&wg_cloner); 789 if_clone_attach(&wg_cloner);
790} 790}
791 791
792static int 792static int
793wgdetach(void) 793wgdetach(void)
794{ 794{
795 int error = 0; 795 int error = 0;
796 796
797 mutex_enter(&wg_softcs.lock); 797 mutex_enter(&wg_softcs.lock);
798 if (!LIST_EMPTY(&wg_softcs.list)) { 798 if (!LIST_EMPTY(&wg_softcs.list)) {
799 mutex_exit(&wg_softcs.lock); 799 mutex_exit(&wg_softcs.lock);
800 error = EBUSY; 800 error = EBUSY;
801 } 801 }
802 802
803 if (error == 0) { 803 if (error == 0) {
804 psref_class_destroy(wg_psref_class); 804 psref_class_destroy(wg_psref_class);
805 805
806 if_clone_detach(&wg_cloner); 806 if_clone_detach(&wg_cloner);
807 } 807 }
808 808
809 return error; 809 return error;
810} 810}
811 811
812static void 812static void
813wg_init_key_and_hash(uint8_t ckey[WG_CHAINING_KEY_LEN], 813wg_init_key_and_hash(uint8_t ckey[WG_CHAINING_KEY_LEN],
814 uint8_t hash[WG_HASH_LEN]) 814 uint8_t hash[WG_HASH_LEN])
815{ 815{
816 /* [W] 5.4: CONSTRUCTION */ 816 /* [W] 5.4: CONSTRUCTION */
817 const char *signature = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"; 817 const char *signature = "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s";
818 /* [W] 5.4: IDENTIFIER */ 818 /* [W] 5.4: IDENTIFIER */
819 const char *id = "WireGuard v1 zx2c4 Jason@zx2c4.com"; 819 const char *id = "WireGuard v1 zx2c4 Jason@zx2c4.com";
820 struct blake2s state; 820 struct blake2s state;
821 821
822 blake2s(ckey, WG_CHAINING_KEY_LEN, NULL, 0, 822 blake2s(ckey, WG_CHAINING_KEY_LEN, NULL, 0,
823 signature, strlen(signature)); 823 signature, strlen(signature));
824 824
825 CTASSERT(WG_HASH_LEN == WG_CHAINING_KEY_LEN); 825 CTASSERT(WG_HASH_LEN == WG_CHAINING_KEY_LEN);
826 memcpy(hash, ckey, WG_CHAINING_KEY_LEN); 826 memcpy(hash, ckey, WG_CHAINING_KEY_LEN);
827 827
828 blake2s_init(&state, WG_HASH_LEN, NULL, 0); 828 blake2s_init(&state, WG_HASH_LEN, NULL, 0);
829 blake2s_update(&state, ckey, WG_CHAINING_KEY_LEN); 829 blake2s_update(&state, ckey, WG_CHAINING_KEY_LEN);
830 blake2s_update(&state, id, strlen(id)); 830 blake2s_update(&state, id, strlen(id));
831 blake2s_final(&state, hash); 831 blake2s_final(&state, hash);
832 832
833 WG_DUMP_HASH("ckey", ckey); 833 WG_DUMP_HASH("ckey", ckey);
834 WG_DUMP_HASH("hash", hash); 834 WG_DUMP_HASH("hash", hash);
835} 835}
836 836
837static void 837static void
838wg_algo_hash(uint8_t hash[WG_HASH_LEN], const uint8_t input[], 838wg_algo_hash(uint8_t hash[WG_HASH_LEN], const uint8_t input[],
839 const size_t inputsize) 839 const size_t inputsize)
840{ 840{
841 struct blake2s state; 841 struct blake2s state;
842 842
843 blake2s_init(&state, WG_HASH_LEN, NULL, 0); 843 blake2s_init(&state, WG_HASH_LEN, NULL, 0);
844 blake2s_update(&state, hash, WG_HASH_LEN); 844 blake2s_update(&state, hash, WG_HASH_LEN);
845 blake2s_update(&state, input, inputsize); 845 blake2s_update(&state, input, inputsize);
846 blake2s_final(&state, hash); 846 blake2s_final(&state, hash);
847} 847}
848 848
849static void 849static void
850wg_algo_mac(uint8_t out[], const size_t outsize, 850wg_algo_mac(uint8_t out[], const size_t outsize,
851 const uint8_t key[], const size_t keylen, 851 const uint8_t key[], const size_t keylen,
852 const uint8_t input1[], const size_t input1len, 852 const uint8_t input1[], const size_t input1len,
853 const uint8_t input2[], const size_t input2len) 853 const uint8_t input2[], const size_t input2len)
854{ 854{
855 struct blake2s state; 855 struct blake2s state;
856 856
857 blake2s_init(&state, outsize, key, keylen); 857 blake2s_init(&state, outsize, key, keylen);
858 858
859 blake2s_update(&state, input1, input1len); 859 blake2s_update(&state, input1, input1len);
860 if (input2 != NULL) 860 if (input2 != NULL)
861 blake2s_update(&state, input2, input2len); 861 blake2s_update(&state, input2, input2len);
862 blake2s_final(&state, out); 862 blake2s_final(&state, out);
863} 863}
864 864
865static void 865static void
866wg_algo_mac_mac1(uint8_t out[], const size_t outsize, 866wg_algo_mac_mac1(uint8_t out[], const size_t outsize,
867 const uint8_t input1[], const size_t input1len, 867 const uint8_t input1[], const size_t input1len,
868 const uint8_t input2[], const size_t input2len) 868 const uint8_t input2[], const size_t input2len)
869{ 869{
870 struct blake2s state; 870 struct blake2s state;
871 /* [W] 5.4: LABEL-MAC1 */ 871 /* [W] 5.4: LABEL-MAC1 */
872 const char *label = "mac1----"; 872 const char *label = "mac1----";
873 uint8_t key[WG_HASH_LEN]; 873 uint8_t key[WG_HASH_LEN];
874 874
875 blake2s_init(&state, sizeof(key), NULL, 0); 875 blake2s_init(&state, sizeof(key), NULL, 0);
876 blake2s_update(&state, label, strlen(label)); 876 blake2s_update(&state, label, strlen(label));
877 blake2s_update(&state, input1, input1len); 877 blake2s_update(&state, input1, input1len);
878 blake2s_final(&state, key); 878 blake2s_final(&state, key);
879 879
880 blake2s_init(&state, outsize, key, sizeof(key)); 880 blake2s_init(&state, outsize, key, sizeof(key));
881 if (input2 != NULL) 881 if (input2 != NULL)
882 blake2s_update(&state, input2, input2len); 882 blake2s_update(&state, input2, input2len);
883 blake2s_final(&state, out); 883 blake2s_final(&state, out);
884} 884}
885 885
886static void 886static void
887wg_algo_mac_cookie(uint8_t out[], const size_t outsize, 887wg_algo_mac_cookie(uint8_t out[], const size_t outsize,
888 const uint8_t input1[], const size_t input1len) 888 const uint8_t input1[], const size_t input1len)
889{ 889{
890 struct blake2s state; 890 struct blake2s state;
891 /* [W] 5.4: LABEL-COOKIE */ 891 /* [W] 5.4: LABEL-COOKIE */
892 const char *label = "cookie--"; 892 const char *label = "cookie--";
893 893
894 blake2s_init(&state, outsize, NULL, 0); 894 blake2s_init(&state, outsize, NULL, 0);
895 blake2s_update(&state, label, strlen(label)); 895 blake2s_update(&state, label, strlen(label));
896 blake2s_update(&state, input1, input1len); 896 blake2s_update(&state, input1, input1len);
897 blake2s_final(&state, out); 897 blake2s_final(&state, out);
898} 898}
899 899
900static void 900static void
901wg_algo_generate_keypair(uint8_t pubkey[WG_EPHEMERAL_KEY_LEN], 901wg_algo_generate_keypair(uint8_t pubkey[WG_EPHEMERAL_KEY_LEN],
902 uint8_t privkey[WG_EPHEMERAL_KEY_LEN]) 902 uint8_t privkey[WG_EPHEMERAL_KEY_LEN])
903{ 903{
904 904
905 CTASSERT(WG_EPHEMERAL_KEY_LEN == crypto_scalarmult_curve25519_BYTES); 905 CTASSERT(WG_EPHEMERAL_KEY_LEN == crypto_scalarmult_curve25519_BYTES);
906 906
907 cprng_strong(kern_cprng, privkey, WG_EPHEMERAL_KEY_LEN, 0); 907 cprng_strong(kern_cprng, privkey, WG_EPHEMERAL_KEY_LEN, 0);
908 crypto_scalarmult_base(pubkey, privkey); 908 crypto_scalarmult_base(pubkey, privkey);
909} 909}
910 910
911static void 911static void
912wg_algo_dh(uint8_t out[WG_DH_OUTPUT_LEN], 912wg_algo_dh(uint8_t out[WG_DH_OUTPUT_LEN],
913 const uint8_t privkey[WG_STATIC_KEY_LEN], 913 const uint8_t privkey[WG_STATIC_KEY_LEN],
914 const uint8_t pubkey[WG_STATIC_KEY_LEN]) 914 const uint8_t pubkey[WG_STATIC_KEY_LEN])
915{ 915{
916 916
917 CTASSERT(WG_STATIC_KEY_LEN == crypto_scalarmult_curve25519_BYTES); 917 CTASSERT(WG_STATIC_KEY_LEN == crypto_scalarmult_curve25519_BYTES);
918 918
919 int ret __diagused = crypto_scalarmult(out, privkey, pubkey); 919 int ret __diagused = crypto_scalarmult(out, privkey, pubkey);
920 KASSERT(ret == 0); 920 KASSERT(ret == 0);
921} 921}
922 922
923static void 923static void
924wg_algo_hmac(uint8_t out[], const size_t outlen, 924wg_algo_hmac(uint8_t out[], const size_t outlen,
925 const uint8_t key[], const size_t keylen, 925 const uint8_t key[], const size_t keylen,
926 const uint8_t in[], const size_t inlen) 926 const uint8_t in[], const size_t inlen)
927{ 927{
928#define IPAD 0x36 928#define IPAD 0x36
929#define OPAD 0x5c 929#define OPAD 0x5c
930 uint8_t hmackey[HMAC_BLOCK_LEN] = {0}; 930 uint8_t hmackey[HMAC_BLOCK_LEN] = {0};
931 uint8_t ipad[HMAC_BLOCK_LEN]; 931 uint8_t ipad[HMAC_BLOCK_LEN];
932 uint8_t opad[HMAC_BLOCK_LEN]; 932 uint8_t opad[HMAC_BLOCK_LEN];
933 int i; 933 int i;
934 struct blake2s state; 934 struct blake2s state;
935 935
936 KASSERT(outlen == WG_HASH_LEN); 936 KASSERT(outlen == WG_HASH_LEN);
937 KASSERT(keylen <= HMAC_BLOCK_LEN); 937 KASSERT(keylen <= HMAC_BLOCK_LEN);
938 938
939 memcpy(hmackey, key, keylen); 939 memcpy(hmackey, key, keylen);
940 940
941 for (i = 0; i < sizeof(hmackey); i++) { 941 for (i = 0; i < sizeof(hmackey); i++) {
942 ipad[i] = hmackey[i] ^ IPAD; 942 ipad[i] = hmackey[i] ^ IPAD;
943 opad[i] = hmackey[i] ^ OPAD; 943 opad[i] = hmackey[i] ^ OPAD;
944 } 944 }
945 945
946 blake2s_init(&state, WG_HASH_LEN, NULL, 0); 946 blake2s_init(&state, WG_HASH_LEN, NULL, 0);
947 blake2s_update(&state, ipad, sizeof(ipad)); 947 blake2s_update(&state, ipad, sizeof(ipad));
948 blake2s_update(&state, in, inlen); 948 blake2s_update(&state, in, inlen);
949 blake2s_final(&state, out); 949 blake2s_final(&state, out);
950 950
951 blake2s_init(&state, WG_HASH_LEN, NULL, 0); 951 blake2s_init(&state, WG_HASH_LEN, NULL, 0);
952 blake2s_update(&state, opad, sizeof(opad)); 952 blake2s_update(&state, opad, sizeof(opad));
953 blake2s_update(&state, out, WG_HASH_LEN); 953 blake2s_update(&state, out, WG_HASH_LEN);
954 blake2s_final(&state, out); 954 blake2s_final(&state, out);
955#undef IPAD 955#undef IPAD
956#undef OPAD 956#undef OPAD
957} 957}
958 958
959static void 959static void
960wg_algo_kdf(uint8_t out1[WG_KDF_OUTPUT_LEN], uint8_t out2[WG_KDF_OUTPUT_LEN], 960wg_algo_kdf(uint8_t out1[WG_KDF_OUTPUT_LEN], uint8_t out2[WG_KDF_OUTPUT_LEN],
961 uint8_t out3[WG_KDF_OUTPUT_LEN], const uint8_t ckey[WG_CHAINING_KEY_LEN], 961 uint8_t out3[WG_KDF_OUTPUT_LEN], const uint8_t ckey[WG_CHAINING_KEY_LEN],
962 const uint8_t input[], const size_t inputlen) 962 const uint8_t input[], const size_t inputlen)
963{ 963{
964 uint8_t tmp1[WG_KDF_OUTPUT_LEN], tmp2[WG_KDF_OUTPUT_LEN + 1]; 964 uint8_t tmp1[WG_KDF_OUTPUT_LEN], tmp2[WG_KDF_OUTPUT_LEN + 1];
965 uint8_t one[1]; 965 uint8_t one[1];
966 966
967 /* 967 /*
968 * [N] 4.3: "an input_key_material byte sequence with length 968 * [N] 4.3: "an input_key_material byte sequence with length
969 * either zero bytes, 32 bytes, or DHLEN bytes." 969 * either zero bytes, 32 bytes, or DHLEN bytes."
970 */ 970 */
971 KASSERT(inputlen == 0 || inputlen == 32 || inputlen == NOISE_DHLEN); 971 KASSERT(inputlen == 0 || inputlen == 32 || inputlen == NOISE_DHLEN);
972 972
973 WG_DUMP_HASH("ckey", ckey); 973 WG_DUMP_HASH("ckey", ckey);
974 if (input != NULL) 974 if (input != NULL)
975 WG_DUMP_HASH("input", input); 975 WG_DUMP_HASH("input", input);
976 wg_algo_hmac(tmp1, sizeof(tmp1), ckey, WG_CHAINING_KEY_LEN, 976 wg_algo_hmac(tmp1, sizeof(tmp1), ckey, WG_CHAINING_KEY_LEN,
977 input, inputlen); 977 input, inputlen);
978 WG_DUMP_HASH("tmp1", tmp1); 978 WG_DUMP_HASH("tmp1", tmp1);
979 one[0] = 1; 979 one[0] = 1;
980 wg_algo_hmac(out1, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1), 980 wg_algo_hmac(out1, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1),
981 one, sizeof(one)); 981 one, sizeof(one));
982 WG_DUMP_HASH("out1", out1); 982 WG_DUMP_HASH("out1", out1);
983 if (out2 == NULL) 983 if (out2 == NULL)
984 return; 984 return;
985 memcpy(tmp2, out1, WG_KDF_OUTPUT_LEN); 985 memcpy(tmp2, out1, WG_KDF_OUTPUT_LEN);
986 tmp2[WG_KDF_OUTPUT_LEN] = 2; 986 tmp2[WG_KDF_OUTPUT_LEN] = 2;
987 wg_algo_hmac(out2, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1), 987 wg_algo_hmac(out2, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1),
988 tmp2, sizeof(tmp2)); 988 tmp2, sizeof(tmp2));
989 WG_DUMP_HASH("out2", out2); 989 WG_DUMP_HASH("out2", out2);
990 if (out3 == NULL) 990 if (out3 == NULL)
991 return; 991 return;
992 memcpy(tmp2, out2, WG_KDF_OUTPUT_LEN); 992 memcpy(tmp2, out2, WG_KDF_OUTPUT_LEN);
993 tmp2[WG_KDF_OUTPUT_LEN] = 3; 993 tmp2[WG_KDF_OUTPUT_LEN] = 3;
994 wg_algo_hmac(out3, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1), 994 wg_algo_hmac(out3, WG_KDF_OUTPUT_LEN, tmp1, sizeof(tmp1),
995 tmp2, sizeof(tmp2)); 995 tmp2, sizeof(tmp2));
996 WG_DUMP_HASH("out3", out3); 996 WG_DUMP_HASH("out3", out3);
997} 997}
998 998
999static void 999static void
1000wg_algo_dh_kdf(uint8_t ckey[WG_CHAINING_KEY_LEN], 1000wg_algo_dh_kdf(uint8_t ckey[WG_CHAINING_KEY_LEN],
1001 uint8_t cipher_key[WG_CIPHER_KEY_LEN], 1001 uint8_t cipher_key[WG_CIPHER_KEY_LEN],
1002 const uint8_t local_key[WG_STATIC_KEY_LEN], 1002 const uint8_t local_key[WG_STATIC_KEY_LEN],
1003 const uint8_t remote_key[WG_STATIC_KEY_LEN]) 1003 const uint8_t remote_key[WG_STATIC_KEY_LEN])
1004{ 1004{
1005 uint8_t dhout[WG_DH_OUTPUT_LEN]; 1005 uint8_t dhout[WG_DH_OUTPUT_LEN];
1006 1006
1007 wg_algo_dh(dhout, local_key, remote_key); 1007 wg_algo_dh(dhout, local_key, remote_key);
1008 wg_algo_kdf(ckey, cipher_key, NULL, ckey, dhout, sizeof(dhout)); 1008 wg_algo_kdf(ckey, cipher_key, NULL, ckey, dhout, sizeof(dhout));
1009 1009
1010 WG_DUMP_HASH("dhout", dhout); 1010 WG_DUMP_HASH("dhout", dhout);
1011 WG_DUMP_HASH("ckey", ckey); 1011 WG_DUMP_HASH("ckey", ckey);
1012 if (cipher_key != NULL) 1012 if (cipher_key != NULL)
1013 WG_DUMP_HASH("cipher_key", cipher_key); 1013 WG_DUMP_HASH("cipher_key", cipher_key);
1014} 1014}
1015 1015
1016static void 1016static void
1017wg_algo_aead_enc(uint8_t out[], size_t expected_outsize, const uint8_t key[], 1017wg_algo_aead_enc(uint8_t out[], size_t expected_outsize, const uint8_t key[],
1018 const uint64_t counter, const uint8_t plain[], const size_t plainsize, 1018 const uint64_t counter, const uint8_t plain[], const size_t plainsize,
1019 const uint8_t auth[], size_t authlen) 1019 const uint8_t auth[], size_t authlen)
1020{ 1020{
1021 uint8_t nonce[(32 + 64) / 8] = {0}; 1021 uint8_t nonce[(32 + 64) / 8] = {0};
1022 long long unsigned int outsize; 1022 long long unsigned int outsize;
1023 int error __diagused; 1023 int error __diagused;
1024 1024
1025 memcpy(&nonce[4], &counter, sizeof(counter)); 1025 memcpy(&nonce[4], &counter, sizeof(counter));
1026 1026
1027 error = crypto_aead_chacha20poly1305_ietf_encrypt(out, &outsize, plain, 1027 error = crypto_aead_chacha20poly1305_ietf_encrypt(out, &outsize, plain,
1028 plainsize, auth, authlen, NULL, nonce, key); 1028 plainsize, auth, authlen, NULL, nonce, key);
1029 KASSERT(error == 0); 1029 KASSERT(error == 0);
1030 KASSERT(outsize == expected_outsize); 1030 KASSERT(outsize == expected_outsize);
1031} 1031}
1032 1032
1033static int 1033static int
1034wg_algo_aead_dec(uint8_t out[], size_t expected_outsize, const uint8_t key[], 1034wg_algo_aead_dec(uint8_t out[], size_t expected_outsize, const uint8_t key[],
1035 const uint64_t counter, const uint8_t encrypted[], 1035 const uint64_t counter, const uint8_t encrypted[],
1036 const size_t encryptedsize, const uint8_t auth[], size_t authlen) 1036 const size_t encryptedsize, const uint8_t auth[], size_t authlen)
1037{ 1037{
1038 uint8_t nonce[(32 + 64) / 8] = {0}; 1038 uint8_t nonce[(32 + 64) / 8] = {0};
1039 long long unsigned int outsize; 1039 long long unsigned int outsize;
1040 int error; 1040 int error;
1041 1041
1042 memcpy(&nonce[4], &counter, sizeof(counter)); 1042 memcpy(&nonce[4], &counter, sizeof(counter));
1043 1043
@@ -1919,2001 +1919,2017 @@ wg_lookup_peer_by_pubkey(struct wg_softc @@ -1919,2001 +1919,2017 @@ wg_lookup_peer_by_pubkey(struct wg_softc
1919} 1919}
1920 1920
1921static void 1921static void
1922wg_fill_msg_cookie(struct wg_softc *wg, struct wg_peer *wgp, 1922wg_fill_msg_cookie(struct wg_softc *wg, struct wg_peer *wgp,
1923 struct wg_msg_cookie *wgmc, const uint32_t sender, 1923 struct wg_msg_cookie *wgmc, const uint32_t sender,
1924 const uint8_t mac1[WG_MAC_LEN], const struct sockaddr *src) 1924 const uint8_t mac1[WG_MAC_LEN], const struct sockaddr *src)
1925{ 1925{
1926 uint8_t cookie[WG_COOKIE_LEN]; 1926 uint8_t cookie[WG_COOKIE_LEN];
1927 uint8_t key[WG_HASH_LEN]; 1927 uint8_t key[WG_HASH_LEN];
1928 uint8_t addr[sizeof(struct in6_addr)]; 1928 uint8_t addr[sizeof(struct in6_addr)];
1929 size_t addrlen; 1929 size_t addrlen;
1930 uint16_t uh_sport; /* be */ 1930 uint16_t uh_sport; /* be */
1931 1931
1932 wgmc->wgmc_type = WG_MSG_TYPE_COOKIE; 1932 wgmc->wgmc_type = WG_MSG_TYPE_COOKIE;
1933 wgmc->wgmc_receiver = sender; 1933 wgmc->wgmc_receiver = sender;
1934 cprng_fast(wgmc->wgmc_salt, sizeof(wgmc->wgmc_salt)); 1934 cprng_fast(wgmc->wgmc_salt, sizeof(wgmc->wgmc_salt));
1935 1935
1936 /* 1936 /*
1937 * [W] 5.4.7: Under Load: Cookie Reply Message 1937 * [W] 5.4.7: Under Load: Cookie Reply Message
1938 * "The secret variable, Rm, changes every two minutes to a 1938 * "The secret variable, Rm, changes every two minutes to a
1939 * random value" 1939 * random value"
1940 */ 1940 */
1941 if ((time_uptime - wgp->wgp_last_genrandval_time) > WG_RANDVAL_TIME) { 1941 if ((time_uptime - wgp->wgp_last_genrandval_time) > WG_RANDVAL_TIME) {
1942 wgp->wgp_randval = cprng_strong32(); 1942 wgp->wgp_randval = cprng_strong32();
1943 wgp->wgp_last_genrandval_time = time_uptime; 1943 wgp->wgp_last_genrandval_time = time_uptime;
1944 } 1944 }
1945 1945
1946 switch (src->sa_family) { 1946 switch (src->sa_family) {
1947 case AF_INET: { 1947 case AF_INET: {
1948 const struct sockaddr_in *sin = satocsin(src); 1948 const struct sockaddr_in *sin = satocsin(src);
1949 addrlen = sizeof(sin->sin_addr); 1949 addrlen = sizeof(sin->sin_addr);
1950 memcpy(addr, &sin->sin_addr, addrlen); 1950 memcpy(addr, &sin->sin_addr, addrlen);
1951 uh_sport = sin->sin_port; 1951 uh_sport = sin->sin_port;
1952 break; 1952 break;
1953 } 1953 }
1954#ifdef INET6 1954#ifdef INET6
1955 case AF_INET6: { 1955 case AF_INET6: {
1956 const struct sockaddr_in6 *sin6 = satocsin6(src); 1956 const struct sockaddr_in6 *sin6 = satocsin6(src);
1957 addrlen = sizeof(sin6->sin6_addr); 1957 addrlen = sizeof(sin6->sin6_addr);
1958 memcpy(addr, &sin6->sin6_addr, addrlen); 1958 memcpy(addr, &sin6->sin6_addr, addrlen);
1959 uh_sport = sin6->sin6_port; 1959 uh_sport = sin6->sin6_port;
1960 break; 1960 break;
1961 } 1961 }
1962#endif 1962#endif
1963 default: 1963 default:
1964 panic("invalid af=%d", wgp->wgp_sa.sa_family); 1964 panic("invalid af=%d", wgp->wgp_sa.sa_family);
1965 } 1965 }
1966 1966
1967 wg_algo_mac(cookie, sizeof(cookie), 1967 wg_algo_mac(cookie, sizeof(cookie),
1968 (const uint8_t *)&wgp->wgp_randval, sizeof(wgp->wgp_randval), 1968 (const uint8_t *)&wgp->wgp_randval, sizeof(wgp->wgp_randval),
1969 addr, addrlen, (const uint8_t *)&uh_sport, sizeof(uh_sport)); 1969 addr, addrlen, (const uint8_t *)&uh_sport, sizeof(uh_sport));
1970 wg_algo_mac_cookie(key, sizeof(key), wg->wg_pubkey, 1970 wg_algo_mac_cookie(key, sizeof(key), wg->wg_pubkey,
1971 sizeof(wg->wg_pubkey)); 1971 sizeof(wg->wg_pubkey));
1972 wg_algo_xaead_enc(wgmc->wgmc_cookie, sizeof(wgmc->wgmc_cookie), key, 1972 wg_algo_xaead_enc(wgmc->wgmc_cookie, sizeof(wgmc->wgmc_cookie), key,
1973 cookie, sizeof(cookie), mac1, WG_MAC_LEN, wgmc->wgmc_salt); 1973 cookie, sizeof(cookie), mac1, WG_MAC_LEN, wgmc->wgmc_salt);
1974 1974
1975 /* Need to store to calculate mac2 */ 1975 /* Need to store to calculate mac2 */
1976 memcpy(wgp->wgp_last_sent_cookie, cookie, sizeof(cookie)); 1976 memcpy(wgp->wgp_last_sent_cookie, cookie, sizeof(cookie));
1977 wgp->wgp_last_sent_cookie_valid = true; 1977 wgp->wgp_last_sent_cookie_valid = true;
1978} 1978}
1979 1979
1980static int 1980static int
1981wg_send_cookie_msg(struct wg_softc *wg, struct wg_peer *wgp, 1981wg_send_cookie_msg(struct wg_softc *wg, struct wg_peer *wgp,
1982 const uint32_t sender, const uint8_t mac1[WG_MAC_LEN], 1982 const uint32_t sender, const uint8_t mac1[WG_MAC_LEN],
1983 const struct sockaddr *src) 1983 const struct sockaddr *src)
1984{ 1984{
1985 int error; 1985 int error;
1986 struct mbuf *m; 1986 struct mbuf *m;
1987 struct wg_msg_cookie *wgmc; 1987 struct wg_msg_cookie *wgmc;
1988 1988
1989 m = m_gethdr(M_WAIT, MT_DATA); 1989 m = m_gethdr(M_WAIT, MT_DATA);
1990 m->m_pkthdr.len = m->m_len = sizeof(*wgmc); 1990 m->m_pkthdr.len = m->m_len = sizeof(*wgmc);
1991 wgmc = mtod(m, struct wg_msg_cookie *); 1991 wgmc = mtod(m, struct wg_msg_cookie *);
1992 wg_fill_msg_cookie(wg, wgp, wgmc, sender, mac1, src); 1992 wg_fill_msg_cookie(wg, wgp, wgmc, sender, mac1, src);
1993 1993
1994 error = wg->wg_ops->send_hs_msg(wgp, m); 1994 error = wg->wg_ops->send_hs_msg(wgp, m);
1995 if (error == 0) 1995 if (error == 0)
1996 WG_TRACE("cookie msg sent"); 1996 WG_TRACE("cookie msg sent");
1997 return error; 1997 return error;
1998} 1998}
1999 1999
2000static bool 2000static bool
2001wg_is_underload(struct wg_softc *wg, struct wg_peer *wgp, int msgtype) 2001wg_is_underload(struct wg_softc *wg, struct wg_peer *wgp, int msgtype)
2002{ 2002{
2003#ifdef WG_DEBUG_PARAMS 2003#ifdef WG_DEBUG_PARAMS
2004 if (wg_force_underload) 2004 if (wg_force_underload)
2005 return true; 2005 return true;
2006#endif 2006#endif
2007 2007
2008 /* 2008 /*
2009 * XXX we don't have a means of a load estimation. The purpose of 2009 * XXX we don't have a means of a load estimation. The purpose of
2010 * the mechanism is a DoS mitigation, so we consider frequent handshake 2010 * the mechanism is a DoS mitigation, so we consider frequent handshake
2011 * messages as (a kind of) load; if a message of the same type comes 2011 * messages as (a kind of) load; if a message of the same type comes
2012 * to a peer within 1 second, we consider we are under load. 2012 * to a peer within 1 second, we consider we are under load.
2013 */ 2013 */
2014 time_t last = wgp->wgp_last_msg_received_time[msgtype]; 2014 time_t last = wgp->wgp_last_msg_received_time[msgtype];
2015 wgp->wgp_last_msg_received_time[msgtype] = time_uptime; 2015 wgp->wgp_last_msg_received_time[msgtype] = time_uptime;
2016 return (time_uptime - last) == 0; 2016 return (time_uptime - last) == 0;
2017} 2017}
2018 2018
2019static void 2019static void
2020wg_calculate_keys(struct wg_session *wgs, const bool initiator) 2020wg_calculate_keys(struct wg_session *wgs, const bool initiator)
2021{ 2021{
2022 2022
2023 /* 2023 /*
2024 * [W] 5.4.5: Ti^send = Tr^recv, Ti^recv = Tr^send := KDF2(Ci = Cr, e) 2024 * [W] 5.4.5: Ti^send = Tr^recv, Ti^recv = Tr^send := KDF2(Ci = Cr, e)
2025 */ 2025 */
2026 if (initiator) { 2026 if (initiator) {
2027 wg_algo_kdf(wgs->wgs_tkey_send, wgs->wgs_tkey_recv, NULL, 2027 wg_algo_kdf(wgs->wgs_tkey_send, wgs->wgs_tkey_recv, NULL,
2028 wgs->wgs_chaining_key, NULL, 0); 2028 wgs->wgs_chaining_key, NULL, 0);
2029 } else { 2029 } else {
2030 wg_algo_kdf(wgs->wgs_tkey_recv, wgs->wgs_tkey_send, NULL, 2030 wg_algo_kdf(wgs->wgs_tkey_recv, wgs->wgs_tkey_send, NULL,
2031 wgs->wgs_chaining_key, NULL, 0); 2031 wgs->wgs_chaining_key, NULL, 0);
2032 } 2032 }
2033 WG_DUMP_HASH("wgs_tkey_send", wgs->wgs_tkey_send); 2033 WG_DUMP_HASH("wgs_tkey_send", wgs->wgs_tkey_send);
2034 WG_DUMP_HASH("wgs_tkey_recv", wgs->wgs_tkey_recv); 2034 WG_DUMP_HASH("wgs_tkey_recv", wgs->wgs_tkey_recv);
2035} 2035}
2036 2036
2037static uint64_t 2037static uint64_t
2038wg_session_get_send_counter(struct wg_session *wgs) 2038wg_session_get_send_counter(struct wg_session *wgs)
2039{ 2039{
2040#ifdef __HAVE_ATOMIC64_LOADSTORE 2040#ifdef __HAVE_ATOMIC64_LOADSTORE
2041 return atomic_load_relaxed(&wgs->wgs_send_counter); 2041 return atomic_load_relaxed(&wgs->wgs_send_counter);
2042#else 2042#else
2043 uint64_t send_counter; 2043 uint64_t send_counter;
2044 2044
2045 mutex_enter(&wgs->wgs_send_counter_lock); 2045 mutex_enter(&wgs->wgs_send_counter_lock);
2046 send_counter = wgs->wgs_send_counter; 2046 send_counter = wgs->wgs_send_counter;
2047 mutex_exit(&wgs->wgs_send_counter_lock); 2047 mutex_exit(&wgs->wgs_send_counter_lock);
2048 2048
2049 return send_counter; 2049 return send_counter;
2050#endif 2050#endif
2051} 2051}
2052 2052
2053static uint64_t 2053static uint64_t
2054wg_session_inc_send_counter(struct wg_session *wgs) 2054wg_session_inc_send_counter(struct wg_session *wgs)
2055{ 2055{
2056#ifdef __HAVE_ATOMIC64_LOADSTORE 2056#ifdef __HAVE_ATOMIC64_LOADSTORE
2057 return atomic_inc_64_nv(&wgs->wgs_send_counter) - 1; 2057 return atomic_inc_64_nv(&wgs->wgs_send_counter) - 1;
2058#else 2058#else
2059 uint64_t send_counter; 2059 uint64_t send_counter;
2060 2060
2061 mutex_enter(&wgs->wgs_send_counter_lock); 2061 mutex_enter(&wgs->wgs_send_counter_lock);
2062 send_counter = wgs->wgs_send_counter++; 2062 send_counter = wgs->wgs_send_counter++;
2063 mutex_exit(&wgs->wgs_send_counter_lock); 2063 mutex_exit(&wgs->wgs_send_counter_lock);
2064 2064
2065 return send_counter; 2065 return send_counter;
2066#endif 2066#endif
2067} 2067}
2068 2068
2069static void 2069static void
2070wg_clear_states(struct wg_session *wgs) 2070wg_clear_states(struct wg_session *wgs)
2071{ 2071{
2072 2072
2073 wgs->wgs_send_counter = 0; 2073 wgs->wgs_send_counter = 0;
2074 sliwin_reset(&wgs->wgs_recvwin->window); 2074 sliwin_reset(&wgs->wgs_recvwin->window);
2075 2075
2076#define wgs_clear(v) explicit_memset(wgs->wgs_##v, 0, sizeof(wgs->wgs_##v)) 2076#define wgs_clear(v) explicit_memset(wgs->wgs_##v, 0, sizeof(wgs->wgs_##v))
2077 wgs_clear(handshake_hash); 2077 wgs_clear(handshake_hash);
2078 wgs_clear(chaining_key); 2078 wgs_clear(chaining_key);
2079 wgs_clear(ephemeral_key_pub); 2079 wgs_clear(ephemeral_key_pub);
2080 wgs_clear(ephemeral_key_priv); 2080 wgs_clear(ephemeral_key_priv);
2081 wgs_clear(ephemeral_key_peer); 2081 wgs_clear(ephemeral_key_peer);
2082#undef wgs_clear 2082#undef wgs_clear
2083} 2083}
2084 2084
2085static struct wg_session * 2085static struct wg_session *
2086wg_lookup_session_by_index(struct wg_softc *wg, const uint32_t index, 2086wg_lookup_session_by_index(struct wg_softc *wg, const uint32_t index,
2087 struct psref *psref) 2087 struct psref *psref)
2088{ 2088{
2089 struct wg_peer *wgp; 2089 struct wg_peer *wgp;
2090 struct wg_session *wgs; 2090 struct wg_session *wgs;
2091 2091
2092 int s = pserialize_read_enter(); 2092 int s = pserialize_read_enter();
2093 /* XXX O(n) */ 2093 /* XXX O(n) */
2094 WG_PEER_READER_FOREACH(wgp, wg) { 2094 WG_PEER_READER_FOREACH(wgp, wg) {
2095 wgs = wgp->wgp_session_stable; 2095 wgs = wgp->wgp_session_stable;
2096 WG_DLOG("index=%x wgs_sender_index=%x\n", 2096 WG_DLOG("index=%x wgs_sender_index=%x\n",
2097 index, wgs->wgs_sender_index); 2097 index, wgs->wgs_sender_index);
2098 if (wgs->wgs_sender_index == index) 2098 if (wgs->wgs_sender_index == index)
2099 break; 2099 break;
2100 wgs = wgp->wgp_session_unstable; 2100 wgs = wgp->wgp_session_unstable;
2101 WG_DLOG("index=%x wgs_sender_index=%x\n", 2101 WG_DLOG("index=%x wgs_sender_index=%x\n",
2102 index, wgs->wgs_sender_index); 2102 index, wgs->wgs_sender_index);
2103 if (wgs->wgs_sender_index == index) 2103 if (wgs->wgs_sender_index == index)
2104 break; 2104 break;
2105 wgs = NULL; 2105 wgs = NULL;
2106 } 2106 }
2107 if (wgs != NULL) 2107 if (wgs != NULL)
2108 psref_acquire(psref, &wgs->wgs_psref, wg_psref_class); 2108 psref_acquire(psref, &wgs->wgs_psref, wg_psref_class);
2109 pserialize_read_exit(s); 2109 pserialize_read_exit(s);
2110 2110
2111 return wgs; 2111 return wgs;
2112} 2112}
2113 2113
2114static void 2114static void
2115wg_schedule_rekey_timer(struct wg_peer *wgp) 2115wg_schedule_rekey_timer(struct wg_peer *wgp)
2116{ 2116{
2117 int timeout = MIN(wg_rekey_after_time, INT_MAX/hz); 2117 int timeout = MIN(wg_rekey_after_time, INT_MAX/hz);
2118 2118
2119 callout_schedule(&wgp->wgp_rekey_timer, timeout * hz); 2119 callout_schedule(&wgp->wgp_rekey_timer, timeout * hz);
2120} 2120}
2121 2121
2122static void 2122static void
2123wg_send_keepalive_msg(struct wg_peer *wgp, struct wg_session *wgs) 2123wg_send_keepalive_msg(struct wg_peer *wgp, struct wg_session *wgs)
2124{ 2124{
2125 struct mbuf *m; 2125 struct mbuf *m;
2126 2126
2127 /* 2127 /*
2128 * [W] 6.5 Passive Keepalive 2128 * [W] 6.5 Passive Keepalive
2129 * "A keepalive message is simply a transport data message with 2129 * "A keepalive message is simply a transport data message with
2130 * a zero-length encapsulated encrypted inner-packet." 2130 * a zero-length encapsulated encrypted inner-packet."
2131 */ 2131 */
2132 m = m_gethdr(M_WAIT, MT_DATA); 2132 m = m_gethdr(M_WAIT, MT_DATA);
2133 wg_send_data_msg(wgp, wgs, m); 2133 wg_send_data_msg(wgp, wgs, m);
2134} 2134}
2135 2135
2136static bool 2136static bool
2137wg_need_to_send_init_message(struct wg_session *wgs) 2137wg_need_to_send_init_message(struct wg_session *wgs)
2138{ 2138{
2139 /* 2139 /*
2140 * [W] 6.2 Transport Message Limits 2140 * [W] 6.2 Transport Message Limits
2141 * "if a peer is the initiator of a current secure session, 2141 * "if a peer is the initiator of a current secure session,
2142 * WireGuard will send a handshake initiation message to begin 2142 * WireGuard will send a handshake initiation message to begin
2143 * a new secure session ... if after receiving a transport data 2143 * a new secure session ... if after receiving a transport data
2144 * message, the current secure session is (REJECT-AFTER-TIME − 2144 * message, the current secure session is (REJECT-AFTER-TIME −
2145 * KEEPALIVE-TIMEOUT − REKEY-TIMEOUT) seconds old and it has 2145 * KEEPALIVE-TIMEOUT − REKEY-TIMEOUT) seconds old and it has
2146 * not yet acted upon this event." 2146 * not yet acted upon this event."
2147 */ 2147 */
2148 return wgs->wgs_is_initiator && wgs->wgs_time_last_data_sent == 0 && 2148 return wgs->wgs_is_initiator && wgs->wgs_time_last_data_sent == 0 &&
2149 (time_uptime - wgs->wgs_time_established) >= 2149 (time_uptime - wgs->wgs_time_established) >=
2150 (wg_reject_after_time - wg_keepalive_timeout - wg_rekey_timeout); 2150 (wg_reject_after_time - wg_keepalive_timeout - wg_rekey_timeout);
2151} 2151}
2152 2152
2153static void 2153static void
2154wg_schedule_peer_task(struct wg_peer *wgp, int task) 2154wg_schedule_peer_task(struct wg_peer *wgp, int task)
2155{ 2155{
2156 2156
2157 atomic_or_uint(&wgp->wgp_tasks, task); 2157 atomic_or_uint(&wgp->wgp_tasks, task);
2158 WG_DLOG("tasks=%d, task=%d\n", wgp->wgp_tasks, task); 2158 WG_DLOG("tasks=%d, task=%d\n", wgp->wgp_tasks, task);
2159 wg_wakeup_worker(wgp->wgp_sc->wg_worker, WG_WAKEUP_REASON_PEER); 2159 wg_wakeup_worker(wgp->wgp_sc->wg_worker, WG_WAKEUP_REASON_PEER);
2160} 2160}
2161 2161
2162static void 2162static void
2163wg_change_endpoint(struct wg_peer *wgp, const struct sockaddr *new) 2163wg_change_endpoint(struct wg_peer *wgp, const struct sockaddr *new)
2164{ 2164{
2165 2165
2166 KASSERT(mutex_owned(wgp->wgp_lock)); 2166 KASSERT(mutex_owned(wgp->wgp_lock));
2167 2167
2168 WG_TRACE("Changing endpoint"); 2168 WG_TRACE("Changing endpoint");
2169 2169
2170 memcpy(wgp->wgp_endpoint0, new, new->sa_len); 2170 memcpy(wgp->wgp_endpoint0, new, new->sa_len);
2171 wgp->wgp_endpoint0 = atomic_swap_ptr(&wgp->wgp_endpoint, 2171 wgp->wgp_endpoint0 = atomic_swap_ptr(&wgp->wgp_endpoint,
2172 wgp->wgp_endpoint0); 2172 wgp->wgp_endpoint0);
2173 if (!wgp->wgp_endpoint_available) 2173 if (!wgp->wgp_endpoint_available)
2174 wgp->wgp_endpoint_available = true; 2174 wgp->wgp_endpoint_available = true;
2175 wgp->wgp_endpoint_changing = true; 2175 wgp->wgp_endpoint_changing = true;
2176 wg_schedule_peer_task(wgp, WGP_TASK_ENDPOINT_CHANGED); 2176 wg_schedule_peer_task(wgp, WGP_TASK_ENDPOINT_CHANGED);
2177} 2177}
2178 2178
2179static bool 2179static bool
2180wg_validate_inner_packet(const char *packet, size_t decrypted_len, int *af) 2180wg_validate_inner_packet(const char *packet, size_t decrypted_len, int *af)
2181{ 2181{
2182 uint16_t packet_len; 2182 uint16_t packet_len;
2183 const struct ip *ip; 2183 const struct ip *ip;
2184 2184
2185 if (__predict_false(decrypted_len < sizeof(struct ip))) 2185 if (__predict_false(decrypted_len < sizeof(struct ip)))
2186 return false; 2186 return false;
2187 2187
2188 ip = (const struct ip *)packet; 2188 ip = (const struct ip *)packet;
2189 if (ip->ip_v == 4) 2189 if (ip->ip_v == 4)
2190 *af = AF_INET; 2190 *af = AF_INET;
2191 else if (ip->ip_v == 6) 2191 else if (ip->ip_v == 6)
2192 *af = AF_INET6; 2192 *af = AF_INET6;
2193 else 2193 else
2194 return false; 2194 return false;
2195 2195
2196 WG_DLOG("af=%d\n", *af); 2196 WG_DLOG("af=%d\n", *af);
2197 2197
2198 if (*af == AF_INET) { 2198 if (*af == AF_INET) {
2199 packet_len = ntohs(ip->ip_len); 2199 packet_len = ntohs(ip->ip_len);
2200 } else { 2200 } else {
2201 const struct ip6_hdr *ip6; 2201 const struct ip6_hdr *ip6;
2202 2202
2203 if (__predict_false(decrypted_len < sizeof(struct ip6_hdr))) 2203 if (__predict_false(decrypted_len < sizeof(struct ip6_hdr)))
2204 return false; 2204 return false;
2205 2205
2206 ip6 = (const struct ip6_hdr *)packet; 2206 ip6 = (const struct ip6_hdr *)packet;
2207 packet_len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen); 2207 packet_len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
2208 } 2208 }
2209 2209
2210 WG_DLOG("packet_len=%u\n", packet_len); 2210 WG_DLOG("packet_len=%u\n", packet_len);
2211 if (packet_len > decrypted_len) 2211 if (packet_len > decrypted_len)
2212 return false; 2212 return false;
2213 2213
2214 return true; 2214 return true;
2215} 2215}
2216 2216
2217static bool 2217static bool
2218wg_validate_route(struct wg_softc *wg, struct wg_peer *wgp_expected, 2218wg_validate_route(struct wg_softc *wg, struct wg_peer *wgp_expected,
2219 int af, char *packet) 2219 int af, char *packet)
2220{ 2220{
2221 struct sockaddr_storage ss; 2221 struct sockaddr_storage ss;
2222 struct sockaddr *sa; 2222 struct sockaddr *sa;
2223 struct psref psref; 2223 struct psref psref;
2224 struct wg_peer *wgp; 2224 struct wg_peer *wgp;
2225 bool ok; 2225 bool ok;
2226 2226
2227 /* 2227 /*
2228 * II CRYPTOKEY ROUTING 2228 * II CRYPTOKEY ROUTING
2229 * "it will only accept it if its source IP resolves in the 2229 * "it will only accept it if its source IP resolves in the
2230 * table to the public key used in the secure session for 2230 * table to the public key used in the secure session for
2231 * decrypting it." 2231 * decrypting it."
2232 */ 2232 */
2233 2233
2234 if (af == AF_INET) { 2234 if (af == AF_INET) {
2235 const struct ip *ip = (const struct ip *)packet; 2235 const struct ip *ip = (const struct ip *)packet;
2236 struct sockaddr_in *sin = (struct sockaddr_in *)&ss; 2236 struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
2237 sockaddr_in_init(sin, &ip->ip_src, 0); 2237 sockaddr_in_init(sin, &ip->ip_src, 0);
2238 sa = sintosa(sin); 2238 sa = sintosa(sin);
2239#ifdef INET6 2239#ifdef INET6
2240 } else { 2240 } else {
2241 const struct ip6_hdr *ip6 = (const struct ip6_hdr *)packet; 2241 const struct ip6_hdr *ip6 = (const struct ip6_hdr *)packet;
2242 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss; 2242 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss;
2243 sockaddr_in6_init(sin6, &ip6->ip6_src, 0, 0, 0); 2243 sockaddr_in6_init(sin6, &ip6->ip6_src, 0, 0, 0);
2244 sa = sin6tosa(sin6); 2244 sa = sin6tosa(sin6);
2245#endif 2245#endif
2246 } 2246 }
2247 2247
2248 wgp = wg_pick_peer_by_sa(wg, sa, &psref); 2248 wgp = wg_pick_peer_by_sa(wg, sa, &psref);
2249 ok = (wgp == wgp_expected); 2249 ok = (wgp == wgp_expected);
2250 if (wgp != NULL) 2250 if (wgp != NULL)
2251 wg_put_peer(wgp, &psref); 2251 wg_put_peer(wgp, &psref);
2252 2252
2253 return ok; 2253 return ok;
2254} 2254}
2255 2255
2256static void 2256static void
2257wg_session_dtor_timer(void *arg) 2257wg_session_dtor_timer(void *arg)
2258{ 2258{
2259 struct wg_peer *wgp = arg; 2259 struct wg_peer *wgp = arg;
2260 2260
2261 WG_TRACE("enter"); 2261 WG_TRACE("enter");
2262 2262
2263 mutex_enter(wgp->wgp_lock); 2263 mutex_enter(wgp->wgp_lock);
2264 if (__predict_false(wgp->wgp_state == WGP_STATE_DESTROYING)) { 2264 if (__predict_false(wgp->wgp_state == WGP_STATE_DESTROYING)) {
2265 mutex_exit(wgp->wgp_lock); 2265 mutex_exit(wgp->wgp_lock);
2266 return; 2266 return;
2267 } 2267 }
2268 mutex_exit(wgp->wgp_lock); 2268 mutex_exit(wgp->wgp_lock);
2269 2269
2270 wg_schedule_peer_task(wgp, WGP_TASK_DESTROY_PREV_SESSION); 2270 wg_schedule_peer_task(wgp, WGP_TASK_DESTROY_PREV_SESSION);
2271} 2271}
2272 2272
2273static void 2273static void
2274wg_schedule_session_dtor_timer(struct wg_peer *wgp) 2274wg_schedule_session_dtor_timer(struct wg_peer *wgp)
2275{ 2275{
2276 2276
2277 /* 1 second grace period */ 2277 /* 1 second grace period */
2278 callout_schedule(&wgp->wgp_session_dtor_timer, hz); 2278 callout_schedule(&wgp->wgp_session_dtor_timer, hz);
2279} 2279}
2280 2280
2281static void 2281static void
2282wg_stop_session_dtor_timer(struct wg_peer *wgp) 2282wg_stop_session_dtor_timer(struct wg_peer *wgp)
2283{ 2283{
2284 2284
2285 callout_halt(&wgp->wgp_session_dtor_timer, NULL); 2285 callout_halt(&wgp->wgp_session_dtor_timer, NULL);
2286} 2286}
2287 2287
2288static bool 2288static bool
2289sockaddr_port_match(const struct sockaddr *sa1, const struct sockaddr *sa2) 2289sockaddr_port_match(const struct sockaddr *sa1, const struct sockaddr *sa2)
2290{ 2290{
2291 if (sa1->sa_family != sa2->sa_family) 2291 if (sa1->sa_family != sa2->sa_family)
2292 return false; 2292 return false;
2293 2293
2294 switch (sa1->sa_family) { 2294 switch (sa1->sa_family) {
2295 case AF_INET: 2295 case AF_INET:
2296 return satocsin(sa1)->sin_port == satocsin(sa2)->sin_port; 2296 return satocsin(sa1)->sin_port == satocsin(sa2)->sin_port;
2297 case AF_INET6: 2297 case AF_INET6:
2298 return satocsin6(sa1)->sin6_port == satocsin6(sa2)->sin6_port; 2298 return satocsin6(sa1)->sin6_port == satocsin6(sa2)->sin6_port;
2299 default: 2299 default:
2300 return true; 2300 return true;
2301 } 2301 }
2302} 2302}
2303 2303
2304static void 2304static void
2305wg_update_endpoint_if_necessary(struct wg_peer *wgp, 2305wg_update_endpoint_if_necessary(struct wg_peer *wgp,
2306 const struct sockaddr *src) 2306 const struct sockaddr *src)
2307{ 2307{
2308 2308
2309#ifdef WG_DEBUG_LOG 2309#ifdef WG_DEBUG_LOG
2310 char oldaddr[128], newaddr[128]; 2310 char oldaddr[128], newaddr[128];
2311 sockaddr_format(&wgp->wgp_sa, oldaddr, sizeof(oldaddr)); 2311 sockaddr_format(&wgp->wgp_sa, oldaddr, sizeof(oldaddr));
2312 sockaddr_format(src, newaddr, sizeof(newaddr)); 2312 sockaddr_format(src, newaddr, sizeof(newaddr));
2313 WG_DLOG("old=%s, new=%s\n", oldaddr, newaddr); 2313 WG_DLOG("old=%s, new=%s\n", oldaddr, newaddr);
2314#endif 2314#endif
2315 2315
2316 /* 2316 /*
2317 * III: "Since the packet has authenticated correctly, the source IP of 2317 * III: "Since the packet has authenticated correctly, the source IP of
2318 * the outer UDP/IP packet is used to update the endpoint for peer..." 2318 * the outer UDP/IP packet is used to update the endpoint for peer..."
2319 */ 2319 */
2320 if (__predict_false(sockaddr_cmp(src, &wgp->wgp_sa) != 0 || 2320 if (__predict_false(sockaddr_cmp(src, &wgp->wgp_sa) != 0 ||
2321 !sockaddr_port_match(src, &wgp->wgp_sa))) { 2321 !sockaddr_port_match(src, &wgp->wgp_sa))) {
2322 mutex_enter(wgp->wgp_lock); 2322 mutex_enter(wgp->wgp_lock);
2323 /* XXX We can't change the endpoint twice in a short period */ 2323 /* XXX We can't change the endpoint twice in a short period */
2324 if (!wgp->wgp_endpoint_changing) { 2324 if (!wgp->wgp_endpoint_changing) {
2325 wg_change_endpoint(wgp, src); 2325 wg_change_endpoint(wgp, src);
2326 } 2326 }
2327 mutex_exit(wgp->wgp_lock); 2327 mutex_exit(wgp->wgp_lock);
2328 } 2328 }
2329} 2329}
2330 2330
2331static void 2331static void
2332wg_handle_msg_data(struct wg_softc *wg, struct mbuf *m, 2332wg_handle_msg_data(struct wg_softc *wg, struct mbuf *m,
2333 const struct sockaddr *src) 2333 const struct sockaddr *src)
2334{ 2334{
2335 struct wg_msg_data *wgmd; 2335 struct wg_msg_data *wgmd;
2336 char *encrypted_buf = NULL, *decrypted_buf; 2336 char *encrypted_buf = NULL, *decrypted_buf;
2337 size_t encrypted_len, decrypted_len; 2337 size_t encrypted_len, decrypted_len;
2338 struct wg_session *wgs; 2338 struct wg_session *wgs;
2339 struct wg_peer *wgp; 2339 struct wg_peer *wgp;
2340 size_t mlen; 2340 size_t mlen;
2341 struct psref psref; 2341 struct psref psref;
2342 int error, af; 2342 int error, af;
2343 bool success, free_encrypted_buf = false, ok; 2343 bool success, free_encrypted_buf = false, ok;
2344 struct mbuf *n; 2344 struct mbuf *n;
2345 2345
2346 if (m->m_len < sizeof(struct wg_msg_data)) { 2346 if (m->m_len < sizeof(struct wg_msg_data)) {
2347 m = m_pullup(m, sizeof(struct wg_msg_data)); 2347 m = m_pullup(m, sizeof(struct wg_msg_data));
2348 if (m == NULL) 2348 if (m == NULL)
2349 return; 2349 return;
2350 } 2350 }
2351 wgmd = mtod(m, struct wg_msg_data *); 2351 wgmd = mtod(m, struct wg_msg_data *);
2352 2352
2353 KASSERT(wgmd->wgmd_type == WG_MSG_TYPE_DATA); 2353 KASSERT(wgmd->wgmd_type == WG_MSG_TYPE_DATA);
2354 WG_TRACE("data"); 2354 WG_TRACE("data");
2355 2355
2356 wgs = wg_lookup_session_by_index(wg, wgmd->wgmd_receiver, &psref); 2356 wgs = wg_lookup_session_by_index(wg, wgmd->wgmd_receiver, &psref);
2357 if (wgs == NULL) { 2357 if (wgs == NULL) {
2358 WG_TRACE("No session found"); 2358 WG_TRACE("No session found");
2359 m_freem(m); 2359 m_freem(m);
2360 return; 2360 return;
2361 } 2361 }
2362 wgp = wgs->wgs_peer; 2362 wgp = wgs->wgs_peer;
2363 2363
2364 error = sliwin_check_fast(&wgs->wgs_recvwin->window, 2364 error = sliwin_check_fast(&wgs->wgs_recvwin->window,
2365 wgmd->wgmd_counter); 2365 wgmd->wgmd_counter);
2366 if (error) { 2366 if (error) {
2367 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2367 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2368 "out-of-window packet: %"PRIu64"\n", 2368 "out-of-window packet: %"PRIu64"\n",
2369 wgmd->wgmd_counter); 2369 wgmd->wgmd_counter);
2370 goto out; 2370 goto out;
2371 } 2371 }
2372 2372
2373 mlen = m_length(m); 2373 mlen = m_length(m);
2374 encrypted_len = mlen - sizeof(*wgmd); 2374 encrypted_len = mlen - sizeof(*wgmd);
2375 2375
2376 if (encrypted_len < WG_AUTHTAG_LEN) { 2376 if (encrypted_len < WG_AUTHTAG_LEN) {
2377 WG_DLOG("Short encrypted_len: %lu\n", encrypted_len); 2377 WG_DLOG("Short encrypted_len: %lu\n", encrypted_len);
2378 goto out; 2378 goto out;
2379 } 2379 }
2380 2380
2381 success = m_ensure_contig(&m, sizeof(*wgmd) + encrypted_len); 2381 success = m_ensure_contig(&m, sizeof(*wgmd) + encrypted_len);
2382 if (success) { 2382 if (success) {
2383 encrypted_buf = mtod(m, char *) + sizeof(*wgmd); 2383 encrypted_buf = mtod(m, char *) + sizeof(*wgmd);
2384 } else { 2384 } else {
2385 encrypted_buf = kmem_intr_alloc(encrypted_len, KM_NOSLEEP); 2385 encrypted_buf = kmem_intr_alloc(encrypted_len, KM_NOSLEEP);
2386 if (encrypted_buf == NULL) { 2386 if (encrypted_buf == NULL) {
2387 WG_DLOG("failed to allocate encrypted_buf\n"); 2387 WG_DLOG("failed to allocate encrypted_buf\n");
2388 goto out; 2388 goto out;
2389 } 2389 }
2390 m_copydata(m, sizeof(*wgmd), encrypted_len, encrypted_buf); 2390 m_copydata(m, sizeof(*wgmd), encrypted_len, encrypted_buf);
2391 free_encrypted_buf = true; 2391 free_encrypted_buf = true;
2392 } 2392 }
2393 /* m_ensure_contig may change m regardless of its result */ 2393 /* m_ensure_contig may change m regardless of its result */
2394 wgmd = mtod(m, struct wg_msg_data *); 2394 wgmd = mtod(m, struct wg_msg_data *);
2395 2395
2396 decrypted_len = encrypted_len - WG_AUTHTAG_LEN; 2396 decrypted_len = encrypted_len - WG_AUTHTAG_LEN;
2397 if (decrypted_len > MCLBYTES) { 2397 if (decrypted_len > MCLBYTES) {
2398 /* FIXME handle larger data than MCLBYTES */ 2398 /* FIXME handle larger data than MCLBYTES */
2399 WG_DLOG("couldn't handle larger data than MCLBYTES\n"); 2399 WG_DLOG("couldn't handle larger data than MCLBYTES\n");
2400 goto out; 2400 goto out;
2401 } 2401 }
2402 2402
2403 /* To avoid zero length */ 2403 /* To avoid zero length */
2404 n = wg_get_mbuf(0, decrypted_len + WG_AUTHTAG_LEN); 2404 n = wg_get_mbuf(0, decrypted_len + WG_AUTHTAG_LEN);
2405 if (n == NULL) { 2405 if (n == NULL) {
2406 WG_DLOG("wg_get_mbuf failed\n"); 2406 WG_DLOG("wg_get_mbuf failed\n");
2407 goto out; 2407 goto out;
2408 } 2408 }
2409 decrypted_buf = mtod(n, char *); 2409 decrypted_buf = mtod(n, char *);
2410 2410
2411 WG_DLOG("mlen=%lu, encrypted_len=%lu\n", mlen, encrypted_len); 2411 WG_DLOG("mlen=%lu, encrypted_len=%lu\n", mlen, encrypted_len);
2412 error = wg_algo_aead_dec(decrypted_buf, 2412 error = wg_algo_aead_dec(decrypted_buf,
2413 encrypted_len - WG_AUTHTAG_LEN /* can be 0 */, 2413 encrypted_len - WG_AUTHTAG_LEN /* can be 0 */,
2414 wgs->wgs_tkey_recv, wgmd->wgmd_counter, encrypted_buf, 2414 wgs->wgs_tkey_recv, wgmd->wgmd_counter, encrypted_buf,
2415 encrypted_len, NULL, 0); 2415 encrypted_len, NULL, 0);
2416 if (error != 0) { 2416 if (error != 0) {
2417 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2417 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2418 "failed to wg_algo_aead_dec\n"); 2418 "failed to wg_algo_aead_dec\n");
2419 m_freem(n); 2419 m_freem(n);
2420 goto out; 2420 goto out;
2421 } 2421 }
2422 WG_DLOG("outsize=%u\n", (u_int)decrypted_len); 2422 WG_DLOG("outsize=%u\n", (u_int)decrypted_len);
2423 2423
2424 mutex_enter(&wgs->wgs_recvwin->lock); 2424 mutex_enter(&wgs->wgs_recvwin->lock);
2425 error = sliwin_update(&wgs->wgs_recvwin->window, 2425 error = sliwin_update(&wgs->wgs_recvwin->window,
2426 wgmd->wgmd_counter); 2426 wgmd->wgmd_counter);
2427 mutex_exit(&wgs->wgs_recvwin->lock); 2427 mutex_exit(&wgs->wgs_recvwin->lock);
2428 if (error) { 2428 if (error) {
2429 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2429 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2430 "replay or out-of-window packet: %"PRIu64"\n", 2430 "replay or out-of-window packet: %"PRIu64"\n",
2431 wgmd->wgmd_counter); 2431 wgmd->wgmd_counter);
2432 m_freem(n); 2432 m_freem(n);
2433 goto out; 2433 goto out;
2434 } 2434 }
2435 2435
2436 m_freem(m); 2436 m_freem(m);
2437 m = NULL; 2437 m = NULL;
2438 wgmd = NULL; 2438 wgmd = NULL;
2439 2439
2440 ok = wg_validate_inner_packet(decrypted_buf, decrypted_len, &af); 2440 ok = wg_validate_inner_packet(decrypted_buf, decrypted_len, &af);
2441 if (!ok) { 2441 if (!ok) {
2442 /* something wrong... */ 2442 /* something wrong... */
2443 m_freem(n); 2443 m_freem(n);
2444 goto out; 2444 goto out;
2445 } 2445 }
2446 2446
2447 wg_update_endpoint_if_necessary(wgp, src); 2447 wg_update_endpoint_if_necessary(wgp, src);
2448 2448
2449 ok = wg_validate_route(wg, wgp, af, decrypted_buf); 2449 ok = wg_validate_route(wg, wgp, af, decrypted_buf);
2450 if (ok) { 2450 if (ok) {
2451 wg->wg_ops->input(&wg->wg_if, n, af); 2451 wg->wg_ops->input(&wg->wg_if, n, af);
2452 } else { 2452 } else {
2453 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2453 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2454 "invalid source address\n"); 2454 "invalid source address\n");
2455 m_freem(n); 2455 m_freem(n);
2456 /* 2456 /*
2457 * The inner address is invalid however the session is valid 2457 * The inner address is invalid however the session is valid
2458 * so continue the session processing below. 2458 * so continue the session processing below.
2459 */ 2459 */
2460 } 2460 }
2461 n = NULL; 2461 n = NULL;
2462 2462
2463 if (wgs->wgs_state == WGS_STATE_INIT_PASSIVE) { 2463 if (wgs->wgs_state == WGS_STATE_INIT_PASSIVE) {
2464 struct wg_session *wgs_prev; 2464 struct wg_session *wgs_prev;
2465 2465
2466 KASSERT(wgs == wgp->wgp_session_unstable); 2466 KASSERT(wgs == wgp->wgp_session_unstable);
2467 wgs->wgs_state = WGS_STATE_ESTABLISHED; 2467 wgs->wgs_state = WGS_STATE_ESTABLISHED;
2468 wgs->wgs_time_established = time_uptime; 2468 wgs->wgs_time_established = time_uptime;
2469 wgs->wgs_time_last_data_sent = 0; 2469 wgs->wgs_time_last_data_sent = 0;
2470 wgs->wgs_is_initiator = false; 2470 wgs->wgs_is_initiator = false;
2471 WG_TRACE("WGS_STATE_ESTABLISHED"); 2471 WG_TRACE("WGS_STATE_ESTABLISHED");
2472 2472
2473 mutex_enter(wgp->wgp_lock); 2473 mutex_enter(wgp->wgp_lock);
2474 wg_swap_sessions(wgp); 2474 wg_swap_sessions(wgp);
2475 wgs_prev = wgp->wgp_session_unstable; 2475 wgs_prev = wgp->wgp_session_unstable;
2476 mutex_enter(wgs_prev->wgs_lock); 2476 mutex_enter(wgs_prev->wgs_lock);
2477 getnanotime(&wgp->wgp_last_handshake_time); 2477 getnanotime(&wgp->wgp_last_handshake_time);
2478 wgp->wgp_handshake_start_time = 0; 2478 wgp->wgp_handshake_start_time = 0;
2479 wgp->wgp_last_sent_mac1_valid = false; 2479 wgp->wgp_last_sent_mac1_valid = false;
2480 wgp->wgp_last_sent_cookie_valid = false; 2480 wgp->wgp_last_sent_cookie_valid = false;
2481 mutex_exit(wgp->wgp_lock); 2481 mutex_exit(wgp->wgp_lock);
2482 2482
2483 if (wgs_prev->wgs_state == WGS_STATE_ESTABLISHED) { 2483 if (wgs_prev->wgs_state == WGS_STATE_ESTABLISHED) {
2484 wgs_prev->wgs_state = WGS_STATE_DESTROYING; 2484 wgs_prev->wgs_state = WGS_STATE_DESTROYING;
2485 /* We can't destroy the old session immediately */ 2485 /* We can't destroy the old session immediately */
2486 wg_schedule_session_dtor_timer(wgp); 2486 wg_schedule_session_dtor_timer(wgp);
2487 } else { 2487 } else {
2488 wg_clear_states(wgs_prev); 2488 wg_clear_states(wgs_prev);
2489 wgs_prev->wgs_state = WGS_STATE_UNKNOWN; 2489 wgs_prev->wgs_state = WGS_STATE_UNKNOWN;
2490 } 2490 }
2491 mutex_exit(wgs_prev->wgs_lock); 2491 mutex_exit(wgs_prev->wgs_lock);
2492 2492
2493 /* Anyway run a softint to flush pending packets */ 2493 /* Anyway run a softint to flush pending packets */
2494 kpreempt_disable(); 2494 kpreempt_disable();
2495 softint_schedule(wgp->wgp_si); 2495 softint_schedule(wgp->wgp_si);
2496 kpreempt_enable(); 2496 kpreempt_enable();
2497 } else { 2497 } else {
2498 if (__predict_false(wg_need_to_send_init_message(wgs))) { 2498 if (__predict_false(wg_need_to_send_init_message(wgs))) {
2499 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 2499 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
2500 } 2500 }
2501 /* 2501 /*
2502 * [W] 6.5 Passive Keepalive 2502 * [W] 6.5 Passive Keepalive
2503 * "If a peer has received a validly-authenticated transport 2503 * "If a peer has received a validly-authenticated transport
2504 * data message (section 5.4.6), but does not have any packets 2504 * data message (section 5.4.6), but does not have any packets
2505 * itself to send back for KEEPALIVE-TIMEOUT seconds, it sends 2505 * itself to send back for KEEPALIVE-TIMEOUT seconds, it sends
2506 * a keepalive message." 2506 * a keepalive message."
2507 */ 2507 */
2508 WG_DLOG("time_uptime=%lu wgs_time_last_data_sent=%lu\n", 2508 WG_DLOG("time_uptime=%lu wgs_time_last_data_sent=%lu\n",
2509 time_uptime, wgs->wgs_time_last_data_sent); 2509 time_uptime, wgs->wgs_time_last_data_sent);
2510 if ((time_uptime - wgs->wgs_time_last_data_sent) >= 2510 if ((time_uptime - wgs->wgs_time_last_data_sent) >=
2511 wg_keepalive_timeout) { 2511 wg_keepalive_timeout) {
2512 WG_TRACE("Schedule sending keepalive message"); 2512 WG_TRACE("Schedule sending keepalive message");
2513 /* 2513 /*
2514 * We can't send a keepalive message here to avoid 2514 * We can't send a keepalive message here to avoid
2515 * a deadlock; we already hold the solock of a socket 2515 * a deadlock; we already hold the solock of a socket
2516 * that is used to send the message. 2516 * that is used to send the message.
2517 */ 2517 */
2518 wg_schedule_peer_task(wgp, 2518 wg_schedule_peer_task(wgp,
2519 WGP_TASK_SEND_KEEPALIVE_MESSAGE); 2519 WGP_TASK_SEND_KEEPALIVE_MESSAGE);
2520 } 2520 }
2521 } 2521 }
2522out: 2522out:
2523 wg_put_session(wgs, &psref); 2523 wg_put_session(wgs, &psref);
2524 if (m != NULL) 2524 if (m != NULL)
2525 m_freem(m); 2525 m_freem(m);
2526 if (free_encrypted_buf) 2526 if (free_encrypted_buf)
2527 kmem_intr_free(encrypted_buf, encrypted_len); 2527 kmem_intr_free(encrypted_buf, encrypted_len);
2528} 2528}
2529 2529
2530static void 2530static void
2531wg_handle_msg_cookie(struct wg_softc *wg, const struct wg_msg_cookie *wgmc) 2531wg_handle_msg_cookie(struct wg_softc *wg, const struct wg_msg_cookie *wgmc)
2532{ 2532{
2533 struct wg_session *wgs; 2533 struct wg_session *wgs;
2534 struct wg_peer *wgp; 2534 struct wg_peer *wgp;
2535 struct psref psref; 2535 struct psref psref;
2536 int error; 2536 int error;
2537 uint8_t key[WG_HASH_LEN]; 2537 uint8_t key[WG_HASH_LEN];
2538 uint8_t cookie[WG_COOKIE_LEN]; 2538 uint8_t cookie[WG_COOKIE_LEN];
2539 2539
2540 WG_TRACE("cookie msg received"); 2540 WG_TRACE("cookie msg received");
2541 wgs = wg_lookup_session_by_index(wg, wgmc->wgmc_receiver, &psref); 2541 wgs = wg_lookup_session_by_index(wg, wgmc->wgmc_receiver, &psref);
2542 if (wgs == NULL) { 2542 if (wgs == NULL) {
2543 WG_TRACE("No session found"); 2543 WG_TRACE("No session found");
2544 return; 2544 return;
2545 } 2545 }
2546 wgp = wgs->wgs_peer; 2546 wgp = wgs->wgs_peer;
2547 2547
2548 if (!wgp->wgp_last_sent_mac1_valid) { 2548 if (!wgp->wgp_last_sent_mac1_valid) {
2549 WG_TRACE("No valid mac1 sent (or expired)"); 2549 WG_TRACE("No valid mac1 sent (or expired)");
2550 goto out; 2550 goto out;
2551 } 2551 }
2552 2552
2553 wg_algo_mac_cookie(key, sizeof(key), wgp->wgp_pubkey, 2553 wg_algo_mac_cookie(key, sizeof(key), wgp->wgp_pubkey,
2554 sizeof(wgp->wgp_pubkey)); 2554 sizeof(wgp->wgp_pubkey));
2555 error = wg_algo_xaead_dec(cookie, sizeof(cookie), key, 0, 2555 error = wg_algo_xaead_dec(cookie, sizeof(cookie), key, 0,
2556 wgmc->wgmc_cookie, sizeof(wgmc->wgmc_cookie), 2556 wgmc->wgmc_cookie, sizeof(wgmc->wgmc_cookie),
2557 wgp->wgp_last_sent_mac1, sizeof(wgp->wgp_last_sent_mac1), 2557 wgp->wgp_last_sent_mac1, sizeof(wgp->wgp_last_sent_mac1),
2558 wgmc->wgmc_salt); 2558 wgmc->wgmc_salt);
2559 if (error != 0) { 2559 if (error != 0) {
2560 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG, 2560 WG_LOG_RATECHECK(&wgp->wgp_ppsratecheck, LOG_DEBUG,
2561 "wg_algo_aead_dec for cookie failed: error=%d\n", error); 2561 "wg_algo_aead_dec for cookie failed: error=%d\n", error);
2562 goto out; 2562 goto out;
2563 } 2563 }
2564 /* 2564 /*
2565 * [W] 6.6: Interaction with Cookie Reply System 2565 * [W] 6.6: Interaction with Cookie Reply System
2566 * "it should simply store the decrypted cookie value from the cookie 2566 * "it should simply store the decrypted cookie value from the cookie
2567 * reply message, and wait for the expiration of the REKEY-TIMEOUT 2567 * reply message, and wait for the expiration of the REKEY-TIMEOUT
2568 * timer for retrying a handshake initiation message." 2568 * timer for retrying a handshake initiation message."
2569 */ 2569 */
2570 wgp->wgp_latest_cookie_time = time_uptime; 2570 wgp->wgp_latest_cookie_time = time_uptime;
2571 memcpy(wgp->wgp_latest_cookie, cookie, sizeof(wgp->wgp_latest_cookie)); 2571 memcpy(wgp->wgp_latest_cookie, cookie, sizeof(wgp->wgp_latest_cookie));
2572out: 2572out:
2573 wg_put_session(wgs, &psref); 2573 wg_put_session(wgs, &psref);
2574} 2574}
2575 2575
2576static bool 2576static bool
2577wg_validate_msg_length(struct wg_softc *wg, const struct mbuf *m) 2577wg_validate_msg_length(struct wg_softc *wg, const struct mbuf *m)
2578{ 2578{
2579 struct wg_msg *wgm; 2579 struct wg_msg *wgm;
2580 size_t mlen; 2580 size_t mlen;
2581 2581
2582 mlen = m_length(m); 2582 mlen = m_length(m);
2583 if (__predict_false(mlen < sizeof(struct wg_msg))) 2583 if (__predict_false(mlen < sizeof(struct wg_msg)))
2584 return false; 2584 return false;
2585 2585
2586 wgm = mtod(m, struct wg_msg *); 2586 wgm = mtod(m, struct wg_msg *);
2587 switch (wgm->wgm_type) { 2587 switch (wgm->wgm_type) {
2588 case WG_MSG_TYPE_INIT: 2588 case WG_MSG_TYPE_INIT:
2589 if (__predict_true(mlen >= sizeof(struct wg_msg_init))) 2589 if (__predict_true(mlen >= sizeof(struct wg_msg_init)))
2590 return true; 2590 return true;
2591 break; 2591 break;
2592 case WG_MSG_TYPE_RESP: 2592 case WG_MSG_TYPE_RESP:
2593 if (__predict_true(mlen >= sizeof(struct wg_msg_resp))) 2593 if (__predict_true(mlen >= sizeof(struct wg_msg_resp)))
2594 return true; 2594 return true;
2595 break; 2595 break;
2596 case WG_MSG_TYPE_COOKIE: 2596 case WG_MSG_TYPE_COOKIE:
2597 if (__predict_true(mlen >= sizeof(struct wg_msg_cookie))) 2597 if (__predict_true(mlen >= sizeof(struct wg_msg_cookie)))
2598 return true; 2598 return true;
2599 break; 2599 break;
2600 case WG_MSG_TYPE_DATA: 2600 case WG_MSG_TYPE_DATA:
2601 if (__predict_true(mlen >= sizeof(struct wg_msg_data))) 2601 if (__predict_true(mlen >= sizeof(struct wg_msg_data)))
2602 return true; 2602 return true;
2603 break; 2603 break;
2604 default: 2604 default:
2605 WG_LOG_RATECHECK(&wg->wg_ppsratecheck, LOG_DEBUG, 2605 WG_LOG_RATECHECK(&wg->wg_ppsratecheck, LOG_DEBUG,
2606 "Unexpected msg type: %u\n", wgm->wgm_type); 2606 "Unexpected msg type: %u\n", wgm->wgm_type);
2607 return false; 2607 return false;
2608 } 2608 }
2609 WG_DLOG("Invalid msg size: mlen=%lu type=%u\n", mlen, wgm->wgm_type); 2609 WG_DLOG("Invalid msg size: mlen=%lu type=%u\n", mlen, wgm->wgm_type);
2610 2610
2611 return false; 2611 return false;
2612} 2612}
2613 2613
2614static void 2614static void
2615wg_handle_packet(struct wg_softc *wg, struct mbuf *m, 2615wg_handle_packet(struct wg_softc *wg, struct mbuf *m,
2616 const struct sockaddr *src) 2616 const struct sockaddr *src)
2617{ 2617{
2618 struct wg_msg *wgm; 2618 struct wg_msg *wgm;
2619 bool valid; 2619 bool valid;
2620 2620
2621 valid = wg_validate_msg_length(wg, m); 2621 valid = wg_validate_msg_length(wg, m);
2622 if (!valid) { 2622 if (!valid) {
2623 m_freem(m); 2623 m_freem(m);
2624 return; 2624 return;
2625 } 2625 }
2626 2626
2627 wgm = mtod(m, struct wg_msg *); 2627 wgm = mtod(m, struct wg_msg *);
2628 switch (wgm->wgm_type) { 2628 switch (wgm->wgm_type) {
2629 case WG_MSG_TYPE_INIT: 2629 case WG_MSG_TYPE_INIT:
2630 wg_handle_msg_init(wg, (struct wg_msg_init *)wgm, src); 2630 wg_handle_msg_init(wg, (struct wg_msg_init *)wgm, src);
2631 break; 2631 break;
2632 case WG_MSG_TYPE_RESP: 2632 case WG_MSG_TYPE_RESP:
2633 wg_handle_msg_resp(wg, (struct wg_msg_resp *)wgm, src); 2633 wg_handle_msg_resp(wg, (struct wg_msg_resp *)wgm, src);
2634 break; 2634 break;
2635 case WG_MSG_TYPE_COOKIE: 2635 case WG_MSG_TYPE_COOKIE:
2636 wg_handle_msg_cookie(wg, (struct wg_msg_cookie *)wgm); 2636 wg_handle_msg_cookie(wg, (struct wg_msg_cookie *)wgm);
2637 break; 2637 break;
2638 case WG_MSG_TYPE_DATA: 2638 case WG_MSG_TYPE_DATA:
2639 wg_handle_msg_data(wg, m, src); 2639 wg_handle_msg_data(wg, m, src);
2640 break; 2640 break;
2641 default: 2641 default:
2642 /* wg_validate_msg_length should already reject this case */ 2642 /* wg_validate_msg_length should already reject this case */
2643 break; 2643 break;
2644 } 2644 }
2645} 2645}
2646 2646
2647static void 2647static void
2648wg_receive_packets(struct wg_softc *wg, const int af) 2648wg_receive_packets(struct wg_softc *wg, const int af)
2649{ 2649{
2650 2650
2651 for (;;) { 2651 for (;;) {
2652 int error, flags; 2652 int error, flags;
2653 struct socket *so; 2653 struct socket *so;
2654 struct mbuf *m = NULL; 2654 struct mbuf *m = NULL;
2655 struct uio dummy_uio; 2655 struct uio dummy_uio;
2656 struct mbuf *paddr = NULL; 2656 struct mbuf *paddr = NULL;
2657 struct sockaddr *src; 2657 struct sockaddr *src;
2658 2658
2659 so = wg_get_so_by_af(wg->wg_worker, af); 2659 so = wg_get_so_by_af(wg->wg_worker, af);
2660 flags = MSG_DONTWAIT; 2660 flags = MSG_DONTWAIT;
2661 dummy_uio.uio_resid = 1000000000; 2661 dummy_uio.uio_resid = 1000000000;
2662 2662
2663 error = so->so_receive(so, &paddr, &dummy_uio, &m, NULL, 2663 error = so->so_receive(so, &paddr, &dummy_uio, &m, NULL,
2664 &flags); 2664 &flags);
2665 if (error || m == NULL) { 2665 if (error || m == NULL) {
2666 //if (error == EWOULDBLOCK) 2666 //if (error == EWOULDBLOCK)
2667 return; 2667 return;
2668 } 2668 }
2669 2669
2670 KASSERT(paddr != NULL); 2670 KASSERT(paddr != NULL);
2671 src = mtod(paddr, struct sockaddr *); 2671 src = mtod(paddr, struct sockaddr *);
2672 2672
2673 wg_handle_packet(wg, m, src); 2673 wg_handle_packet(wg, m, src);
2674 } 2674 }
2675} 2675}
2676 2676
2677static void 2677static void
2678wg_get_peer(struct wg_peer *wgp, struct psref *psref) 2678wg_get_peer(struct wg_peer *wgp, struct psref *psref)
2679{ 2679{
2680 2680
2681 psref_acquire(psref, &wgp->wgp_psref, wg_psref_class); 2681 psref_acquire(psref, &wgp->wgp_psref, wg_psref_class);
2682} 2682}
2683 2683
2684static void 2684static void
2685wg_put_peer(struct wg_peer *wgp, struct psref *psref) 2685wg_put_peer(struct wg_peer *wgp, struct psref *psref)
2686{ 2686{
2687 2687
2688 psref_release(psref, &wgp->wgp_psref, wg_psref_class); 2688 psref_release(psref, &wgp->wgp_psref, wg_psref_class);
2689} 2689}
2690 2690
2691static void 2691static void
2692wg_task_send_init_message(struct wg_softc *wg, struct wg_peer *wgp) 2692wg_task_send_init_message(struct wg_softc *wg, struct wg_peer *wgp)
2693{ 2693{
2694 struct psref psref; 2694 struct psref psref;
2695 struct wg_session *wgs; 2695 struct wg_session *wgs;
2696 2696
2697 WG_TRACE("WGP_TASK_SEND_INIT_MESSAGE"); 2697 WG_TRACE("WGP_TASK_SEND_INIT_MESSAGE");
2698 2698
2699 if (!wgp->wgp_endpoint_available) { 2699 if (!wgp->wgp_endpoint_available) {
2700 WGLOG(LOG_DEBUG, "No endpoint available\n"); 2700 WGLOG(LOG_DEBUG, "No endpoint available\n");
2701 /* XXX should do something? */ 2701 /* XXX should do something? */
2702 return; 2702 return;
2703 } 2703 }
2704 2704
2705 wgs = wg_get_stable_session(wgp, &psref); 2705 wgs = wg_get_stable_session(wgp, &psref);
2706 if (wgs->wgs_state == WGS_STATE_UNKNOWN) { 2706 if (wgs->wgs_state == WGS_STATE_UNKNOWN) {
2707 wg_put_session(wgs, &psref); 2707 wg_put_session(wgs, &psref);
2708 wg_send_handshake_msg_init(wg, wgp); 2708 wg_send_handshake_msg_init(wg, wgp);
2709 } else { 2709 } else {
2710 wg_put_session(wgs, &psref); 2710 wg_put_session(wgs, &psref);
2711 /* rekey */ 2711 /* rekey */
2712 wgs = wg_get_unstable_session(wgp, &psref); 2712 wgs = wg_get_unstable_session(wgp, &psref);
2713 if (wgs->wgs_state != WGS_STATE_INIT_ACTIVE) 2713 if (wgs->wgs_state != WGS_STATE_INIT_ACTIVE)
2714 wg_send_handshake_msg_init(wg, wgp); 2714 wg_send_handshake_msg_init(wg, wgp);
2715 wg_put_session(wgs, &psref); 2715 wg_put_session(wgs, &psref);
2716 } 2716 }
2717} 2717}
2718 2718
2719static void 2719static void
2720wg_task_endpoint_changed(struct wg_softc *wg, struct wg_peer *wgp) 2720wg_task_endpoint_changed(struct wg_softc *wg, struct wg_peer *wgp)
2721{ 2721{
2722 2722
2723 WG_TRACE("WGP_TASK_ENDPOINT_CHANGED"); 2723 WG_TRACE("WGP_TASK_ENDPOINT_CHANGED");
2724 2724
2725 mutex_enter(wgp->wgp_lock); 2725 mutex_enter(wgp->wgp_lock);
2726 if (wgp->wgp_endpoint_changing) { 2726 if (wgp->wgp_endpoint_changing) {
2727 pserialize_perform(wgp->wgp_psz); 2727 pserialize_perform(wgp->wgp_psz);
2728 psref_target_destroy(&wgp->wgp_endpoint0->wgsa_psref, 2728 psref_target_destroy(&wgp->wgp_endpoint0->wgsa_psref,
2729 wg_psref_class); 2729 wg_psref_class);
2730 psref_target_init(&wgp->wgp_endpoint0->wgsa_psref, 2730 psref_target_init(&wgp->wgp_endpoint0->wgsa_psref,
2731 wg_psref_class); 2731 wg_psref_class);
2732 wgp->wgp_endpoint_changing = false; 2732 wgp->wgp_endpoint_changing = false;
2733 } 2733 }
2734 mutex_exit(wgp->wgp_lock); 2734 mutex_exit(wgp->wgp_lock);
2735} 2735}
2736 2736
2737static void 2737static void
2738wg_task_send_keepalive_message(struct wg_softc *wg, struct wg_peer *wgp) 2738wg_task_send_keepalive_message(struct wg_softc *wg, struct wg_peer *wgp)
2739{ 2739{
2740 struct psref psref; 2740 struct psref psref;
2741 struct wg_session *wgs; 2741 struct wg_session *wgs;
2742 2742
2743 WG_TRACE("WGP_TASK_SEND_KEEPALIVE_MESSAGE"); 2743 WG_TRACE("WGP_TASK_SEND_KEEPALIVE_MESSAGE");
2744 2744
2745 wgs = wg_get_stable_session(wgp, &psref); 2745 wgs = wg_get_stable_session(wgp, &psref);
2746 wg_send_keepalive_msg(wgp, wgs); 2746 wg_send_keepalive_msg(wgp, wgs);
2747 wg_put_session(wgs, &psref); 2747 wg_put_session(wgs, &psref);
2748} 2748}
2749 2749
2750static void 2750static void
2751wg_task_destroy_prev_session(struct wg_softc *wg, struct wg_peer *wgp) 2751wg_task_destroy_prev_session(struct wg_softc *wg, struct wg_peer *wgp)
2752{ 2752{
2753 struct wg_session *wgs; 2753 struct wg_session *wgs;
2754 2754
2755 WG_TRACE("WGP_TASK_DESTROY_PREV_SESSION"); 2755 WG_TRACE("WGP_TASK_DESTROY_PREV_SESSION");
2756 2756
2757 mutex_enter(wgp->wgp_lock); 2757 mutex_enter(wgp->wgp_lock);
2758 wgs = wgp->wgp_session_unstable; 2758 wgs = wgp->wgp_session_unstable;
2759 mutex_enter(wgs->wgs_lock); 2759 mutex_enter(wgs->wgs_lock);
2760 if (wgs->wgs_state == WGS_STATE_DESTROYING) { 2760 if (wgs->wgs_state == WGS_STATE_DESTROYING) {
2761 pserialize_perform(wgp->wgp_psz); 2761 pserialize_perform(wgp->wgp_psz);
2762 psref_target_destroy(&wgs->wgs_psref, wg_psref_class); 2762 psref_target_destroy(&wgs->wgs_psref, wg_psref_class);
2763 psref_target_init(&wgs->wgs_psref, wg_psref_class); 2763 psref_target_init(&wgs->wgs_psref, wg_psref_class);
2764 wg_clear_states(wgs); 2764 wg_clear_states(wgs);
2765 wgs->wgs_state = WGS_STATE_UNKNOWN; 2765 wgs->wgs_state = WGS_STATE_UNKNOWN;
2766 } 2766 }
2767 mutex_exit(wgs->wgs_lock); 2767 mutex_exit(wgs->wgs_lock);
2768 mutex_exit(wgp->wgp_lock); 2768 mutex_exit(wgp->wgp_lock);
2769} 2769}
2770 2770
2771static void 2771static void
2772wg_process_peer_tasks(struct wg_softc *wg) 2772wg_process_peer_tasks(struct wg_softc *wg)
2773{ 2773{
2774 struct wg_peer *wgp; 2774 struct wg_peer *wgp;
2775 int s; 2775 int s;
2776 2776
2777 /* XXX should avoid checking all peers */ 2777 /* XXX should avoid checking all peers */
2778 s = pserialize_read_enter(); 2778 s = pserialize_read_enter();
2779 WG_PEER_READER_FOREACH(wgp, wg) { 2779 WG_PEER_READER_FOREACH(wgp, wg) {
2780 struct psref psref; 2780 struct psref psref;
2781 unsigned int tasks; 2781 unsigned int tasks;
2782 2782
2783 if (wgp->wgp_tasks == 0) 2783 if (wgp->wgp_tasks == 0)
2784 continue; 2784 continue;
2785 2785
2786 wg_get_peer(wgp, &psref); 2786 wg_get_peer(wgp, &psref);
2787 pserialize_read_exit(s); 2787 pserialize_read_exit(s);
2788 2788
2789 restart: 2789 restart:
2790 tasks = atomic_swap_uint(&wgp->wgp_tasks, 0); 2790 tasks = atomic_swap_uint(&wgp->wgp_tasks, 0);
2791 KASSERT(tasks != 0); 2791 KASSERT(tasks != 0);
2792 2792
2793 WG_DLOG("tasks=%x\n", tasks); 2793 WG_DLOG("tasks=%x\n", tasks);
2794 2794
2795 if (ISSET(tasks, WGP_TASK_SEND_INIT_MESSAGE)) 2795 if (ISSET(tasks, WGP_TASK_SEND_INIT_MESSAGE))
2796 wg_task_send_init_message(wg, wgp); 2796 wg_task_send_init_message(wg, wgp);
2797 if (ISSET(tasks, WGP_TASK_ENDPOINT_CHANGED)) 2797 if (ISSET(tasks, WGP_TASK_ENDPOINT_CHANGED))
2798 wg_task_endpoint_changed(wg, wgp); 2798 wg_task_endpoint_changed(wg, wgp);
2799 if (ISSET(tasks, WGP_TASK_SEND_KEEPALIVE_MESSAGE)) 2799 if (ISSET(tasks, WGP_TASK_SEND_KEEPALIVE_MESSAGE))
2800 wg_task_send_keepalive_message(wg, wgp); 2800 wg_task_send_keepalive_message(wg, wgp);
2801 if (ISSET(tasks, WGP_TASK_DESTROY_PREV_SESSION)) 2801 if (ISSET(tasks, WGP_TASK_DESTROY_PREV_SESSION))
2802 wg_task_destroy_prev_session(wg, wgp); 2802 wg_task_destroy_prev_session(wg, wgp);
2803 2803
2804 /* New tasks may be scheduled during processing tasks */ 2804 /* New tasks may be scheduled during processing tasks */
2805 WG_DLOG("wgp_tasks=%d\n", wgp->wgp_tasks); 2805 WG_DLOG("wgp_tasks=%d\n", wgp->wgp_tasks);
2806 if (wgp->wgp_tasks != 0) 2806 if (wgp->wgp_tasks != 0)
2807 goto restart; 2807 goto restart;
2808 2808
2809 s = pserialize_read_enter(); 2809 s = pserialize_read_enter();
2810 wg_put_peer(wgp, &psref); 2810 wg_put_peer(wgp, &psref);
2811 } 2811 }
2812 pserialize_read_exit(s); 2812 pserialize_read_exit(s);
2813} 2813}
2814 2814
2815static void 2815static void
2816wg_worker(void *arg) 2816wg_worker(void *arg)
2817{ 2817{
2818 struct wg_softc *wg = arg; 2818 struct wg_softc *wg = arg;
2819 struct wg_worker *wgw = wg->wg_worker; 2819 struct wg_worker *wgw = wg->wg_worker;
2820 bool todie = false; 2820 bool todie = false;
2821 2821
2822 KASSERT(wg != NULL); 2822 KASSERT(wg != NULL);
2823 KASSERT(wgw != NULL); 2823 KASSERT(wgw != NULL);
2824 2824
2825 while (!todie) { 2825 while (!todie) {
2826 int reasons; 2826 int reasons;
2827 int bound; 2827 int bound;
2828 2828
2829 mutex_enter(&wgw->wgw_lock); 2829 mutex_enter(&wgw->wgw_lock);
2830 /* New tasks may come during task handling */ 2830 /* New tasks may come during task handling */
2831 while ((reasons = wgw->wgw_wakeup_reasons) == 0 && 2831 while ((reasons = wgw->wgw_wakeup_reasons) == 0 &&
2832 !(todie = wgw->wgw_todie)) 2832 !(todie = wgw->wgw_todie))
2833 cv_wait(&wgw->wgw_cv, &wgw->wgw_lock); 2833 cv_wait(&wgw->wgw_cv, &wgw->wgw_lock);
2834 wgw->wgw_wakeup_reasons = 0; 2834 wgw->wgw_wakeup_reasons = 0;
2835 mutex_exit(&wgw->wgw_lock); 2835 mutex_exit(&wgw->wgw_lock);
2836 2836
2837 bound = curlwp_bind(); 2837 bound = curlwp_bind();
2838 if (ISSET(reasons, WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4)) 2838 if (ISSET(reasons, WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4))
2839 wg_receive_packets(wg, AF_INET); 2839 wg_receive_packets(wg, AF_INET);
2840 if (ISSET(reasons, WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6)) 2840 if (ISSET(reasons, WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6))
2841 wg_receive_packets(wg, AF_INET6); 2841 wg_receive_packets(wg, AF_INET6);
2842 if (ISSET(reasons, WG_WAKEUP_REASON_PEER)) 2842 if (ISSET(reasons, WG_WAKEUP_REASON_PEER))
2843 wg_process_peer_tasks(wg); 2843 wg_process_peer_tasks(wg);
2844 curlwp_bindx(bound); 2844 curlwp_bindx(bound);
2845 } 2845 }
2846 kthread_exit(0); 2846 kthread_exit(0);
2847} 2847}
2848 2848
2849static void 2849static void
2850wg_wakeup_worker(struct wg_worker *wgw, const int reason) 2850wg_wakeup_worker(struct wg_worker *wgw, const int reason)
2851{ 2851{
2852 2852
2853 mutex_enter(&wgw->wgw_lock); 2853 mutex_enter(&wgw->wgw_lock);
2854 wgw->wgw_wakeup_reasons |= reason; 2854 wgw->wgw_wakeup_reasons |= reason;
2855 cv_broadcast(&wgw->wgw_cv); 2855 cv_broadcast(&wgw->wgw_cv);
2856 mutex_exit(&wgw->wgw_lock); 2856 mutex_exit(&wgw->wgw_lock);
2857} 2857}
2858 2858
2859static int 2859static int
2860wg_bind_port(struct wg_softc *wg, const uint16_t port) 2860wg_bind_port(struct wg_softc *wg, const uint16_t port)
2861{ 2861{
2862 int error; 2862 int error;
2863 struct wg_worker *wgw = wg->wg_worker; 2863 struct wg_worker *wgw = wg->wg_worker;
2864 uint16_t old_port = wg->wg_listen_port; 2864 uint16_t old_port = wg->wg_listen_port;
2865 2865
2866 if (port != 0 && old_port == port) 2866 if (port != 0 && old_port == port)
2867 return 0; 2867 return 0;
2868 2868
2869 struct sockaddr_in _sin, *sin = &_sin; 2869 struct sockaddr_in _sin, *sin = &_sin;
2870 sin->sin_len = sizeof(*sin); 2870 sin->sin_len = sizeof(*sin);
2871 sin->sin_family = AF_INET; 2871 sin->sin_family = AF_INET;
2872 sin->sin_addr.s_addr = INADDR_ANY; 2872 sin->sin_addr.s_addr = INADDR_ANY;
2873 sin->sin_port = htons(port); 2873 sin->sin_port = htons(port);
2874 2874
2875 error = sobind(wgw->wgw_so4, sintosa(sin), curlwp); 2875 error = sobind(wgw->wgw_so4, sintosa(sin), curlwp);
2876 if (error != 0) 2876 if (error != 0)
2877 return error; 2877 return error;
2878 2878
2879#ifdef INET6 2879#ifdef INET6
2880 struct sockaddr_in6 _sin6, *sin6 = &_sin6; 2880 struct sockaddr_in6 _sin6, *sin6 = &_sin6;
2881 sin6->sin6_len = sizeof(*sin6); 2881 sin6->sin6_len = sizeof(*sin6);
2882 sin6->sin6_family = AF_INET6; 2882 sin6->sin6_family = AF_INET6;
2883 sin6->sin6_addr = in6addr_any; 2883 sin6->sin6_addr = in6addr_any;
2884 sin6->sin6_port = htons(port); 2884 sin6->sin6_port = htons(port);
2885 2885
2886 error = sobind(wgw->wgw_so6, sin6tosa(sin6), curlwp); 2886 error = sobind(wgw->wgw_so6, sin6tosa(sin6), curlwp);
2887 if (error != 0) 2887 if (error != 0)
2888 return error; 2888 return error;
2889#endif 2889#endif
2890 2890
2891 wg->wg_listen_port = port; 2891 wg->wg_listen_port = port;
2892 2892
2893 return 0; 2893 return 0;
2894} 2894}
2895 2895
2896static void 2896static void
2897wg_so_upcall(struct socket *so, void *arg, int events, int waitflag) 2897wg_so_upcall(struct socket *so, void *arg, int events, int waitflag)
2898{ 2898{
2899 struct wg_worker *wgw = arg; 2899 struct wg_worker *wgw = arg;
2900 int reason; 2900 int reason;
2901 2901
2902 reason = (so->so_proto->pr_domain->dom_family == AF_INET) ? 2902 reason = (so->so_proto->pr_domain->dom_family == AF_INET) ?
2903 WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4 : 2903 WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV4 :
2904 WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6; 2904 WG_WAKEUP_REASON_RECEIVE_PACKETS_IPV6;
2905 wg_wakeup_worker(wgw, reason); 2905 wg_wakeup_worker(wgw, reason);
2906} 2906}
2907 2907
2908static int 2908static int
2909wg_overudp_cb(struct mbuf **mp, int offset, struct socket *so, 2909wg_overudp_cb(struct mbuf **mp, int offset, struct socket *so,
2910 struct sockaddr *src, void *arg) 2910 struct sockaddr *src, void *arg)
2911{ 2911{
2912 struct wg_softc *wg = arg; 2912 struct wg_softc *wg = arg;
2913 struct wg_msg wgm; 2913 struct wg_msg wgm;
2914 struct mbuf *m = *mp; 2914 struct mbuf *m = *mp;
2915 2915
2916 WG_TRACE("enter"); 2916 WG_TRACE("enter");
2917 2917
 2918 /* Verify the mbuf chain is long enough to have a wg msg header. */
 2919 KASSERT(offset <= m_length(m));
 2920 if (__predict_false(m_length(m) - offset < sizeof(struct wg_msg))) {
 2921 m_freem(m);
 2922 return -1;
 2923 }
 2924
 2925 /*
 2926 * Copy the message header (32-bit message type) out -- we'll
 2927 * worry about contiguity and alignment later.
 2928 */
2918 m_copydata(m, offset, sizeof(struct wg_msg), &wgm); 2929 m_copydata(m, offset, sizeof(struct wg_msg), &wgm);
2919 WG_DLOG("type=%d\n", wgm.wgm_type); 2930 WG_DLOG("type=%d\n", wgm.wgm_type);
2920 2931
 2932 /*
 2933 * Handle DATA packets promptly as they arrive. Other packets
 2934 * may require expensive public-key crypto and are not as
 2935 * sensitive to latency, so defer them to the worker thread.
 2936 */
2921 switch (wgm.wgm_type) { 2937 switch (wgm.wgm_type) {
2922 case WG_MSG_TYPE_DATA: 2938 case WG_MSG_TYPE_DATA:
2923 m_adj(m, offset); 2939 m_adj(m, offset);
2924 wg_handle_msg_data(wg, m, src); 2940 wg_handle_msg_data(wg, m, src);
2925 *mp = NULL; 2941 *mp = NULL;
2926 return 1; 2942 return 1;
2927 default: 2943 default:
2928 break; 2944 break;
2929 } 2945 }
2930 2946
2931 return 0; 2947 return 0;
2932} 2948}
2933 2949
2934static int 2950static int
2935wg_worker_socreate(struct wg_softc *wg, struct wg_worker *wgw, const int af, 2951wg_worker_socreate(struct wg_softc *wg, struct wg_worker *wgw, const int af,
2936 struct socket **sop) 2952 struct socket **sop)
2937{ 2953{
2938 int error; 2954 int error;
2939 struct socket *so; 2955 struct socket *so;
2940 2956
2941 error = socreate(af, &so, SOCK_DGRAM, 0, curlwp, NULL); 2957 error = socreate(af, &so, SOCK_DGRAM, 0, curlwp, NULL);
2942 if (error != 0) 2958 if (error != 0)
2943 return error; 2959 return error;
2944 2960
2945 solock(so); 2961 solock(so);
2946 so->so_upcallarg = wgw; 2962 so->so_upcallarg = wgw;
2947 so->so_upcall = wg_so_upcall; 2963 so->so_upcall = wg_so_upcall;
2948 so->so_rcv.sb_flags |= SB_UPCALL; 2964 so->so_rcv.sb_flags |= SB_UPCALL;
2949 if (af == AF_INET) 2965 if (af == AF_INET)
2950 in_pcb_register_overudp_cb(sotoinpcb(so), wg_overudp_cb, wg); 2966 in_pcb_register_overudp_cb(sotoinpcb(so), wg_overudp_cb, wg);
2951#if INET6 2967#if INET6
2952 else 2968 else
2953 in6_pcb_register_overudp_cb(sotoin6pcb(so), wg_overudp_cb, wg); 2969 in6_pcb_register_overudp_cb(sotoin6pcb(so), wg_overudp_cb, wg);
2954#endif 2970#endif
2955 sounlock(so); 2971 sounlock(so);
2956 2972
2957 *sop = so; 2973 *sop = so;
2958 2974
2959 return 0; 2975 return 0;
2960} 2976}
2961 2977
2962static int 2978static int
2963wg_worker_init(struct wg_softc *wg) 2979wg_worker_init(struct wg_softc *wg)
2964{ 2980{
2965 int error; 2981 int error;
2966 struct wg_worker *wgw; 2982 struct wg_worker *wgw;
2967 const char *ifname = wg->wg_if.if_xname; 2983 const char *ifname = wg->wg_if.if_xname;
2968 struct socket *so; 2984 struct socket *so;
2969 2985
2970 wgw = kmem_zalloc(sizeof(struct wg_worker), KM_SLEEP); 2986 wgw = kmem_zalloc(sizeof(struct wg_worker), KM_SLEEP);
2971 2987
2972 mutex_init(&wgw->wgw_lock, MUTEX_DEFAULT, IPL_NONE); 2988 mutex_init(&wgw->wgw_lock, MUTEX_DEFAULT, IPL_NONE);
2973 cv_init(&wgw->wgw_cv, ifname); 2989 cv_init(&wgw->wgw_cv, ifname);
2974 wgw->wgw_todie = false; 2990 wgw->wgw_todie = false;
2975 wgw->wgw_wakeup_reasons = 0; 2991 wgw->wgw_wakeup_reasons = 0;
2976 2992
2977 error = wg_worker_socreate(wg, wgw, AF_INET, &so); 2993 error = wg_worker_socreate(wg, wgw, AF_INET, &so);
2978 if (error != 0) 2994 if (error != 0)
2979 goto error; 2995 goto error;
2980 wgw->wgw_so4 = so; 2996 wgw->wgw_so4 = so;
2981#ifdef INET6 2997#ifdef INET6
2982 error = wg_worker_socreate(wg, wgw, AF_INET6, &so); 2998 error = wg_worker_socreate(wg, wgw, AF_INET6, &so);
2983 if (error != 0) 2999 if (error != 0)
2984 goto error; 3000 goto error;
2985 wgw->wgw_so6 = so; 3001 wgw->wgw_so6 = so;
2986#endif 3002#endif
2987 3003
2988 wg->wg_worker = wgw; 3004 wg->wg_worker = wgw;
2989 3005
2990 error = kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, 3006 error = kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN,
2991 NULL, wg_worker, wg, &wg->wg_worker_lwp, "%s", ifname); 3007 NULL, wg_worker, wg, &wg->wg_worker_lwp, "%s", ifname);
2992 if (error != 0) 3008 if (error != 0)
2993 goto error; 3009 goto error;
2994 3010
2995 return 0; 3011 return 0;
2996 3012
2997error: 3013error:
2998#ifdef INET6 3014#ifdef INET6
2999 if (wgw->wgw_so6 != NULL) 3015 if (wgw->wgw_so6 != NULL)
3000 soclose(wgw->wgw_so6); 3016 soclose(wgw->wgw_so6);
3001#endif 3017#endif
3002 if (wgw->wgw_so4 != NULL) 3018 if (wgw->wgw_so4 != NULL)
3003 soclose(wgw->wgw_so4); 3019 soclose(wgw->wgw_so4);
3004 cv_destroy(&wgw->wgw_cv); 3020 cv_destroy(&wgw->wgw_cv);
3005 mutex_destroy(&wgw->wgw_lock); 3021 mutex_destroy(&wgw->wgw_lock);
3006 3022
3007 return error; 3023 return error;
3008} 3024}
3009 3025
3010static void 3026static void
3011wg_worker_destroy(struct wg_softc *wg) 3027wg_worker_destroy(struct wg_softc *wg)
3012{ 3028{
3013 struct wg_worker *wgw = wg->wg_worker; 3029 struct wg_worker *wgw = wg->wg_worker;
3014 3030
3015 mutex_enter(&wgw->wgw_lock); 3031 mutex_enter(&wgw->wgw_lock);
3016 wgw->wgw_todie = true; 3032 wgw->wgw_todie = true;
3017 wgw->wgw_wakeup_reasons = 0; 3033 wgw->wgw_wakeup_reasons = 0;
3018 cv_broadcast(&wgw->wgw_cv); 3034 cv_broadcast(&wgw->wgw_cv);
3019 mutex_exit(&wgw->wgw_lock); 3035 mutex_exit(&wgw->wgw_lock);
3020 3036
3021 kthread_join(wg->wg_worker_lwp); 3037 kthread_join(wg->wg_worker_lwp);
3022 3038
3023#ifdef INET6 3039#ifdef INET6
3024 soclose(wgw->wgw_so6); 3040 soclose(wgw->wgw_so6);
3025#endif 3041#endif
3026 soclose(wgw->wgw_so4); 3042 soclose(wgw->wgw_so4);
3027 cv_destroy(&wgw->wgw_cv); 3043 cv_destroy(&wgw->wgw_cv);
3028 mutex_destroy(&wgw->wgw_lock); 3044 mutex_destroy(&wgw->wgw_lock);
3029 kmem_free(wg->wg_worker, sizeof(struct wg_worker)); 3045 kmem_free(wg->wg_worker, sizeof(struct wg_worker));
3030 wg->wg_worker = NULL; 3046 wg->wg_worker = NULL;
3031} 3047}
3032 3048
3033static bool 3049static bool
3034wg_session_hit_limits(struct wg_session *wgs) 3050wg_session_hit_limits(struct wg_session *wgs)
3035{ 3051{
3036 3052
3037 /* 3053 /*
3038 * [W] 6.2: Transport Message Limits 3054 * [W] 6.2: Transport Message Limits
3039 * "After REJECT-AFTER-MESSAGES transport data messages or after the 3055 * "After REJECT-AFTER-MESSAGES transport data messages or after the
3040 * current secure session is REJECT-AFTER-TIME seconds old, whichever 3056 * current secure session is REJECT-AFTER-TIME seconds old, whichever
3041 * comes first, WireGuard will refuse to send any more transport data 3057 * comes first, WireGuard will refuse to send any more transport data
3042 * messages using the current secure session, ..." 3058 * messages using the current secure session, ..."
3043 */ 3059 */
3044 KASSERT(wgs->wgs_time_established != 0); 3060 KASSERT(wgs->wgs_time_established != 0);
3045 if ((time_uptime - wgs->wgs_time_established) > wg_reject_after_time) { 3061 if ((time_uptime - wgs->wgs_time_established) > wg_reject_after_time) {
3046 WG_DLOG("The session hits REJECT_AFTER_TIME\n"); 3062 WG_DLOG("The session hits REJECT_AFTER_TIME\n");
3047 return true; 3063 return true;
3048 } else if (wg_session_get_send_counter(wgs) > 3064 } else if (wg_session_get_send_counter(wgs) >
3049 wg_reject_after_messages) { 3065 wg_reject_after_messages) {
3050 WG_DLOG("The session hits REJECT_AFTER_MESSAGES\n"); 3066 WG_DLOG("The session hits REJECT_AFTER_MESSAGES\n");
3051 return true; 3067 return true;
3052 } 3068 }
3053 3069
3054 return false; 3070 return false;
3055} 3071}
3056 3072
3057static void 3073static void
3058wg_peer_softint(void *arg) 3074wg_peer_softint(void *arg)
3059{ 3075{
3060 struct wg_peer *wgp = arg; 3076 struct wg_peer *wgp = arg;
3061 struct wg_session *wgs; 3077 struct wg_session *wgs;
3062 struct mbuf *m; 3078 struct mbuf *m;
3063 struct psref psref; 3079 struct psref psref;
3064 3080
3065 wgs = wg_get_stable_session(wgp, &psref); 3081 wgs = wg_get_stable_session(wgp, &psref);
3066 if (wgs->wgs_state != WGS_STATE_ESTABLISHED) { 3082 if (wgs->wgs_state != WGS_STATE_ESTABLISHED) {
3067 /* XXX how to treat? */ 3083 /* XXX how to treat? */
3068 WG_TRACE("skipped"); 3084 WG_TRACE("skipped");
3069 goto out; 3085 goto out;
3070 } 3086 }
3071 if (wg_session_hit_limits(wgs)) { 3087 if (wg_session_hit_limits(wgs)) {
3072 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3088 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3073 goto out; 3089 goto out;
3074 } 3090 }
3075 WG_TRACE("running"); 3091 WG_TRACE("running");
3076 3092
3077 while ((m = pcq_get(wgp->wgp_q)) != NULL) { 3093 while ((m = pcq_get(wgp->wgp_q)) != NULL) {
3078 wg_send_data_msg(wgp, wgs, m); 3094 wg_send_data_msg(wgp, wgs, m);
3079 } 3095 }
3080out: 3096out:
3081 wg_put_session(wgs, &psref); 3097 wg_put_session(wgs, &psref);
3082} 3098}
3083 3099
3084static void 3100static void
3085wg_rekey_timer(void *arg) 3101wg_rekey_timer(void *arg)
3086{ 3102{
3087 struct wg_peer *wgp = arg; 3103 struct wg_peer *wgp = arg;
3088 3104
3089 mutex_enter(wgp->wgp_lock); 3105 mutex_enter(wgp->wgp_lock);
3090 if (__predict_true(wgp->wgp_state != WGP_STATE_DESTROYING)) { 3106 if (__predict_true(wgp->wgp_state != WGP_STATE_DESTROYING)) {
3091 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3107 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3092 } 3108 }
3093 mutex_exit(wgp->wgp_lock); 3109 mutex_exit(wgp->wgp_lock);
3094} 3110}
3095 3111
3096static void 3112static void
3097wg_purge_pending_packets(struct wg_peer *wgp) 3113wg_purge_pending_packets(struct wg_peer *wgp)
3098{ 3114{
3099 struct mbuf *m; 3115 struct mbuf *m;
3100 3116
3101 while ((m = pcq_get(wgp->wgp_q)) != NULL) { 3117 while ((m = pcq_get(wgp->wgp_q)) != NULL) {
3102 m_freem(m); 3118 m_freem(m);
3103 } 3119 }
3104} 3120}
3105 3121
3106static void 3122static void
3107wg_handshake_timeout_timer(void *arg) 3123wg_handshake_timeout_timer(void *arg)
3108{ 3124{
3109 struct wg_peer *wgp = arg; 3125 struct wg_peer *wgp = arg;
3110 struct wg_session *wgs; 3126 struct wg_session *wgs;
3111 struct psref psref; 3127 struct psref psref;
3112 3128
3113 WG_TRACE("enter"); 3129 WG_TRACE("enter");
3114 3130
3115 mutex_enter(wgp->wgp_lock); 3131 mutex_enter(wgp->wgp_lock);
3116 if (__predict_false(wgp->wgp_state == WGP_STATE_DESTROYING)) { 3132 if (__predict_false(wgp->wgp_state == WGP_STATE_DESTROYING)) {
3117 mutex_exit(wgp->wgp_lock); 3133 mutex_exit(wgp->wgp_lock);
3118 return; 3134 return;
3119 } 3135 }
3120 mutex_exit(wgp->wgp_lock); 3136 mutex_exit(wgp->wgp_lock);
3121 3137
3122 KASSERT(wgp->wgp_handshake_start_time != 0); 3138 KASSERT(wgp->wgp_handshake_start_time != 0);
3123 wgs = wg_get_unstable_session(wgp, &psref); 3139 wgs = wg_get_unstable_session(wgp, &psref);
3124 KASSERT(wgs->wgs_state == WGS_STATE_INIT_ACTIVE); 3140 KASSERT(wgs->wgs_state == WGS_STATE_INIT_ACTIVE);
3125 3141
3126 /* [W] 6.4 Handshake Initiation Retransmission */ 3142 /* [W] 6.4 Handshake Initiation Retransmission */
3127 if ((time_uptime - wgp->wgp_handshake_start_time) > 3143 if ((time_uptime - wgp->wgp_handshake_start_time) >
3128 wg_rekey_attempt_time) { 3144 wg_rekey_attempt_time) {
3129 /* Give up handshaking */ 3145 /* Give up handshaking */
3130 wgs->wgs_state = WGS_STATE_UNKNOWN; 3146 wgs->wgs_state = WGS_STATE_UNKNOWN;
3131 wg_clear_states(wgs); 3147 wg_clear_states(wgs);
3132 wgp->wgp_state = WGP_STATE_GIVEUP; 3148 wgp->wgp_state = WGP_STATE_GIVEUP;
3133 wgp->wgp_handshake_start_time = 0; 3149 wgp->wgp_handshake_start_time = 0;
3134 wg_put_session(wgs, &psref); 3150 wg_put_session(wgs, &psref);
3135 WG_TRACE("give up"); 3151 WG_TRACE("give up");
3136 /* 3152 /*
3137 * If a new data packet comes, handshaking will be retried 3153 * If a new data packet comes, handshaking will be retried
3138 * and a new session would be established at that time, 3154 * and a new session would be established at that time,
3139 * however we don't want to send pending packets then. 3155 * however we don't want to send pending packets then.
3140 */ 3156 */
3141 wg_purge_pending_packets(wgp); 3157 wg_purge_pending_packets(wgp);
3142 return; 3158 return;
3143 } 3159 }
3144 3160
3145 /* No response for an initiation message sent, retry handshaking */ 3161 /* No response for an initiation message sent, retry handshaking */
3146 wgs->wgs_state = WGS_STATE_UNKNOWN; 3162 wgs->wgs_state = WGS_STATE_UNKNOWN;
3147 wg_clear_states(wgs); 3163 wg_clear_states(wgs);
3148 wg_put_session(wgs, &psref); 3164 wg_put_session(wgs, &psref);
3149 3165
3150 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3166 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3151} 3167}
3152 3168
3153static struct wg_peer * 3169static struct wg_peer *
3154wg_alloc_peer(struct wg_softc *wg) 3170wg_alloc_peer(struct wg_softc *wg)
3155{ 3171{
3156 struct wg_peer *wgp; 3172 struct wg_peer *wgp;
3157 3173
3158 wgp = kmem_zalloc(sizeof(*wgp), KM_SLEEP); 3174 wgp = kmem_zalloc(sizeof(*wgp), KM_SLEEP);
3159 3175
3160 wgp->wgp_sc = wg; 3176 wgp->wgp_sc = wg;
3161 wgp->wgp_state = WGP_STATE_INIT; 3177 wgp->wgp_state = WGP_STATE_INIT;
3162 wgp->wgp_q = pcq_create(1024, KM_SLEEP); 3178 wgp->wgp_q = pcq_create(1024, KM_SLEEP);
3163 wgp->wgp_si = softint_establish(SOFTINT_NET, wg_peer_softint, wgp); 3179 wgp->wgp_si = softint_establish(SOFTINT_NET, wg_peer_softint, wgp);
3164 callout_init(&wgp->wgp_rekey_timer, CALLOUT_MPSAFE); 3180 callout_init(&wgp->wgp_rekey_timer, CALLOUT_MPSAFE);
3165 callout_setfunc(&wgp->wgp_rekey_timer, wg_rekey_timer, wgp); 3181 callout_setfunc(&wgp->wgp_rekey_timer, wg_rekey_timer, wgp);
3166 callout_init(&wgp->wgp_handshake_timeout_timer, CALLOUT_MPSAFE); 3182 callout_init(&wgp->wgp_handshake_timeout_timer, CALLOUT_MPSAFE);
3167 callout_setfunc(&wgp->wgp_handshake_timeout_timer, 3183 callout_setfunc(&wgp->wgp_handshake_timeout_timer,
3168 wg_handshake_timeout_timer, wgp); 3184 wg_handshake_timeout_timer, wgp);
3169 callout_init(&wgp->wgp_session_dtor_timer, CALLOUT_MPSAFE); 3185 callout_init(&wgp->wgp_session_dtor_timer, CALLOUT_MPSAFE);
3170 callout_setfunc(&wgp->wgp_session_dtor_timer, 3186 callout_setfunc(&wgp->wgp_session_dtor_timer,
3171 wg_session_dtor_timer, wgp); 3187 wg_session_dtor_timer, wgp);
3172 PSLIST_ENTRY_INIT(wgp, wgp_peerlist_entry); 3188 PSLIST_ENTRY_INIT(wgp, wgp_peerlist_entry);
3173 wgp->wgp_endpoint_changing = false; 3189 wgp->wgp_endpoint_changing = false;
3174 wgp->wgp_endpoint_available = false; 3190 wgp->wgp_endpoint_available = false;
3175 wgp->wgp_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 3191 wgp->wgp_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
3176 wgp->wgp_psz = pserialize_create(); 3192 wgp->wgp_psz = pserialize_create();
3177 psref_target_init(&wgp->wgp_psref, wg_psref_class); 3193 psref_target_init(&wgp->wgp_psref, wg_psref_class);
3178 3194
3179 wgp->wgp_endpoint = kmem_zalloc(sizeof(*wgp->wgp_endpoint), KM_SLEEP); 3195 wgp->wgp_endpoint = kmem_zalloc(sizeof(*wgp->wgp_endpoint), KM_SLEEP);
3180 wgp->wgp_endpoint0 = kmem_zalloc(sizeof(*wgp->wgp_endpoint0), KM_SLEEP); 3196 wgp->wgp_endpoint0 = kmem_zalloc(sizeof(*wgp->wgp_endpoint0), KM_SLEEP);
3181 psref_target_init(&wgp->wgp_endpoint->wgsa_psref, wg_psref_class); 3197 psref_target_init(&wgp->wgp_endpoint->wgsa_psref, wg_psref_class);
3182 psref_target_init(&wgp->wgp_endpoint0->wgsa_psref, wg_psref_class); 3198 psref_target_init(&wgp->wgp_endpoint0->wgsa_psref, wg_psref_class);
3183 3199
3184 struct wg_session *wgs; 3200 struct wg_session *wgs;
3185 wgp->wgp_session_stable = 3201 wgp->wgp_session_stable =
3186 kmem_zalloc(sizeof(*wgp->wgp_session_stable), KM_SLEEP); 3202 kmem_zalloc(sizeof(*wgp->wgp_session_stable), KM_SLEEP);
3187 wgp->wgp_session_unstable = 3203 wgp->wgp_session_unstable =
3188 kmem_zalloc(sizeof(*wgp->wgp_session_unstable), KM_SLEEP); 3204 kmem_zalloc(sizeof(*wgp->wgp_session_unstable), KM_SLEEP);
3189 wgs = wgp->wgp_session_stable; 3205 wgs = wgp->wgp_session_stable;
3190 wgs->wgs_peer = wgp; 3206 wgs->wgs_peer = wgp;
3191 wgs->wgs_state = WGS_STATE_UNKNOWN; 3207 wgs->wgs_state = WGS_STATE_UNKNOWN;
3192 psref_target_init(&wgs->wgs_psref, wg_psref_class); 3208 psref_target_init(&wgs->wgs_psref, wg_psref_class);
3193 wgs->wgs_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 3209 wgs->wgs_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
3194#ifndef __HAVE_ATOMIC64_LOADSTORE 3210#ifndef __HAVE_ATOMIC64_LOADSTORE
3195 mutex_init(&wgs->wgs_send_counter_lock, MUTEX_DEFAULT, IPL_SOFTNET); 3211 mutex_init(&wgs->wgs_send_counter_lock, MUTEX_DEFAULT, IPL_SOFTNET);
3196#endif 3212#endif
3197 wgs->wgs_recvwin = kmem_zalloc(sizeof(*wgs->wgs_recvwin), KM_SLEEP); 3213 wgs->wgs_recvwin = kmem_zalloc(sizeof(*wgs->wgs_recvwin), KM_SLEEP);
3198 mutex_init(&wgs->wgs_recvwin->lock, MUTEX_DEFAULT, IPL_NONE); 3214 mutex_init(&wgs->wgs_recvwin->lock, MUTEX_DEFAULT, IPL_NONE);
3199 3215
3200 wgs = wgp->wgp_session_unstable; 3216 wgs = wgp->wgp_session_unstable;
3201 wgs->wgs_peer = wgp; 3217 wgs->wgs_peer = wgp;
3202 wgs->wgs_state = WGS_STATE_UNKNOWN; 3218 wgs->wgs_state = WGS_STATE_UNKNOWN;
3203 psref_target_init(&wgs->wgs_psref, wg_psref_class); 3219 psref_target_init(&wgs->wgs_psref, wg_psref_class);
3204 wgs->wgs_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 3220 wgs->wgs_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
3205#ifndef __HAVE_ATOMIC64_LOADSTORE 3221#ifndef __HAVE_ATOMIC64_LOADSTORE
3206 mutex_init(&wgs->wgs_send_counter_lock, MUTEX_DEFAULT, IPL_SOFTNET); 3222 mutex_init(&wgs->wgs_send_counter_lock, MUTEX_DEFAULT, IPL_SOFTNET);
3207#endif 3223#endif
3208 wgs->wgs_recvwin = kmem_zalloc(sizeof(*wgs->wgs_recvwin), KM_SLEEP); 3224 wgs->wgs_recvwin = kmem_zalloc(sizeof(*wgs->wgs_recvwin), KM_SLEEP);
3209 mutex_init(&wgs->wgs_recvwin->lock, MUTEX_DEFAULT, IPL_NONE); 3225 mutex_init(&wgs->wgs_recvwin->lock, MUTEX_DEFAULT, IPL_NONE);
3210 3226
3211 return wgp; 3227 return wgp;
3212} 3228}
3213 3229
3214static void 3230static void
3215wg_destroy_peer(struct wg_peer *wgp) 3231wg_destroy_peer(struct wg_peer *wgp)
3216{ 3232{
3217 struct wg_session *wgs; 3233 struct wg_session *wgs;
3218 struct wg_softc *wg = wgp->wgp_sc; 3234 struct wg_softc *wg = wgp->wgp_sc;
3219 3235
3220 rw_enter(wg->wg_rwlock, RW_WRITER); 3236 rw_enter(wg->wg_rwlock, RW_WRITER);
3221 for (int i = 0; i < wgp->wgp_n_allowedips; i++) { 3237 for (int i = 0; i < wgp->wgp_n_allowedips; i++) {
3222 struct wg_allowedip *wga = &wgp->wgp_allowedips[i]; 3238 struct wg_allowedip *wga = &wgp->wgp_allowedips[i];
3223 struct radix_node_head *rnh = wg_rnh(wg, wga->wga_family); 3239 struct radix_node_head *rnh = wg_rnh(wg, wga->wga_family);
3224 struct radix_node *rn; 3240 struct radix_node *rn;
3225 3241
3226 KASSERT(rnh != NULL); 3242 KASSERT(rnh != NULL);
3227 rn = rnh->rnh_deladdr(&wga->wga_sa_addr, 3243 rn = rnh->rnh_deladdr(&wga->wga_sa_addr,
3228 &wga->wga_sa_mask, rnh); 3244 &wga->wga_sa_mask, rnh);
3229 if (rn == NULL) { 3245 if (rn == NULL) {
3230 char addrstr[128]; 3246 char addrstr[128];
3231 sockaddr_format(&wga->wga_sa_addr, addrstr, 3247 sockaddr_format(&wga->wga_sa_addr, addrstr,
3232 sizeof(addrstr)); 3248 sizeof(addrstr));
3233 WGLOG(LOG_WARNING, "Couldn't delete %s", addrstr); 3249 WGLOG(LOG_WARNING, "Couldn't delete %s", addrstr);
3234 } 3250 }
3235 } 3251 }
3236 rw_exit(wg->wg_rwlock); 3252 rw_exit(wg->wg_rwlock);
3237 3253
3238 softint_disestablish(wgp->wgp_si); 3254 softint_disestablish(wgp->wgp_si);
3239 callout_halt(&wgp->wgp_rekey_timer, NULL); 3255 callout_halt(&wgp->wgp_rekey_timer, NULL);
3240 callout_halt(&wgp->wgp_handshake_timeout_timer, NULL); 3256 callout_halt(&wgp->wgp_handshake_timeout_timer, NULL);
3241 callout_halt(&wgp->wgp_session_dtor_timer, NULL); 3257 callout_halt(&wgp->wgp_session_dtor_timer, NULL);
3242 3258
3243 wgs = wgp->wgp_session_unstable; 3259 wgs = wgp->wgp_session_unstable;
3244 psref_target_destroy(&wgs->wgs_psref, wg_psref_class); 3260 psref_target_destroy(&wgs->wgs_psref, wg_psref_class);
3245 mutex_obj_free(wgs->wgs_lock); 3261 mutex_obj_free(wgs->wgs_lock);
3246 mutex_destroy(&wgs->wgs_recvwin->lock); 3262 mutex_destroy(&wgs->wgs_recvwin->lock);
3247 kmem_free(wgs->wgs_recvwin, sizeof(*wgs->wgs_recvwin)); 3263 kmem_free(wgs->wgs_recvwin, sizeof(*wgs->wgs_recvwin));
3248#ifndef __HAVE_ATOMIC64_LOADSTORE 3264#ifndef __HAVE_ATOMIC64_LOADSTORE
3249 mutex_destroy(&wgs->wgs_send_counter_lock); 3265 mutex_destroy(&wgs->wgs_send_counter_lock);
3250#endif 3266#endif
3251 kmem_free(wgs, sizeof(*wgs)); 3267 kmem_free(wgs, sizeof(*wgs));
3252 wgs = wgp->wgp_session_stable; 3268 wgs = wgp->wgp_session_stable;
3253 psref_target_destroy(&wgs->wgs_psref, wg_psref_class); 3269 psref_target_destroy(&wgs->wgs_psref, wg_psref_class);
3254 mutex_obj_free(wgs->wgs_lock); 3270 mutex_obj_free(wgs->wgs_lock);
3255 mutex_destroy(&wgs->wgs_recvwin->lock); 3271 mutex_destroy(&wgs->wgs_recvwin->lock);
3256 kmem_free(wgs->wgs_recvwin, sizeof(*wgs->wgs_recvwin)); 3272 kmem_free(wgs->wgs_recvwin, sizeof(*wgs->wgs_recvwin));
3257#ifndef __HAVE_ATOMIC64_LOADSTORE 3273#ifndef __HAVE_ATOMIC64_LOADSTORE
3258 mutex_destroy(&wgs->wgs_send_counter_lock); 3274 mutex_destroy(&wgs->wgs_send_counter_lock);
3259#endif 3275#endif
3260 kmem_free(wgs, sizeof(*wgs)); 3276 kmem_free(wgs, sizeof(*wgs));
3261 3277
3262 psref_target_destroy(&wgp->wgp_endpoint->wgsa_psref, wg_psref_class); 3278 psref_target_destroy(&wgp->wgp_endpoint->wgsa_psref, wg_psref_class);
3263 psref_target_destroy(&wgp->wgp_endpoint0->wgsa_psref, wg_psref_class); 3279 psref_target_destroy(&wgp->wgp_endpoint0->wgsa_psref, wg_psref_class);
3264 kmem_free(wgp->wgp_endpoint, sizeof(*wgp->wgp_endpoint)); 3280 kmem_free(wgp->wgp_endpoint, sizeof(*wgp->wgp_endpoint));
3265 kmem_free(wgp->wgp_endpoint0, sizeof(*wgp->wgp_endpoint0)); 3281 kmem_free(wgp->wgp_endpoint0, sizeof(*wgp->wgp_endpoint0));
3266 3282
3267 pserialize_destroy(wgp->wgp_psz); 3283 pserialize_destroy(wgp->wgp_psz);
3268 pcq_destroy(wgp->wgp_q); 3284 pcq_destroy(wgp->wgp_q);
3269 mutex_obj_free(wgp->wgp_lock); 3285 mutex_obj_free(wgp->wgp_lock);
3270 3286
3271 kmem_free(wgp, sizeof(*wgp)); 3287 kmem_free(wgp, sizeof(*wgp));
3272} 3288}
3273 3289
3274static void 3290static void
3275wg_destroy_all_peers(struct wg_softc *wg) 3291wg_destroy_all_peers(struct wg_softc *wg)
3276{ 3292{
3277 struct wg_peer *wgp; 3293 struct wg_peer *wgp;
3278 3294
3279restart: 3295restart:
3280 mutex_enter(wg->wg_lock); 3296 mutex_enter(wg->wg_lock);
3281 WG_PEER_WRITER_FOREACH(wgp, wg) { 3297 WG_PEER_WRITER_FOREACH(wgp, wg) {
3282 WG_PEER_WRITER_REMOVE(wgp); 3298 WG_PEER_WRITER_REMOVE(wgp);
3283 mutex_enter(wgp->wgp_lock); 3299 mutex_enter(wgp->wgp_lock);
3284 wgp->wgp_state = WGP_STATE_DESTROYING; 3300 wgp->wgp_state = WGP_STATE_DESTROYING;
3285 pserialize_perform(wgp->wgp_psz); 3301 pserialize_perform(wgp->wgp_psz);
3286 mutex_exit(wgp->wgp_lock); 3302 mutex_exit(wgp->wgp_lock);
3287 PSLIST_ENTRY_DESTROY(wgp, wgp_peerlist_entry); 3303 PSLIST_ENTRY_DESTROY(wgp, wgp_peerlist_entry);
3288 break; 3304 break;
3289 } 3305 }
3290 mutex_exit(wg->wg_lock); 3306 mutex_exit(wg->wg_lock);
3291 3307
3292 if (wgp == NULL) 3308 if (wgp == NULL)
3293 return; 3309 return;
3294 3310
3295 psref_target_destroy(&wgp->wgp_psref, wg_psref_class); 3311 psref_target_destroy(&wgp->wgp_psref, wg_psref_class);
3296 3312
3297 wg_destroy_peer(wgp); 3313 wg_destroy_peer(wgp);
3298 3314
3299 goto restart; 3315 goto restart;
3300} 3316}
3301 3317
3302static int 3318static int
3303wg_destroy_peer_name(struct wg_softc *wg, const char *name) 3319wg_destroy_peer_name(struct wg_softc *wg, const char *name)
3304{ 3320{
3305 struct wg_peer *wgp; 3321 struct wg_peer *wgp;
3306 3322
3307 mutex_enter(wg->wg_lock); 3323 mutex_enter(wg->wg_lock);
3308 WG_PEER_WRITER_FOREACH(wgp, wg) { 3324 WG_PEER_WRITER_FOREACH(wgp, wg) {
3309 if (strcmp(wgp->wgp_name, name) == 0) 3325 if (strcmp(wgp->wgp_name, name) == 0)
3310 break; 3326 break;
3311 } 3327 }
3312 if (wgp != NULL) { 3328 if (wgp != NULL) {
3313 WG_PEER_WRITER_REMOVE(wgp); 3329 WG_PEER_WRITER_REMOVE(wgp);
3314 wg->wg_npeers--; 3330 wg->wg_npeers--;
3315 mutex_enter(wgp->wgp_lock); 3331 mutex_enter(wgp->wgp_lock);
3316 wgp->wgp_state = WGP_STATE_DESTROYING; 3332 wgp->wgp_state = WGP_STATE_DESTROYING;
3317 pserialize_perform(wgp->wgp_psz); 3333 pserialize_perform(wgp->wgp_psz);
3318 mutex_exit(wgp->wgp_lock); 3334 mutex_exit(wgp->wgp_lock);
3319 PSLIST_ENTRY_DESTROY(wgp, wgp_peerlist_entry); 3335 PSLIST_ENTRY_DESTROY(wgp, wgp_peerlist_entry);
3320 } 3336 }
3321 mutex_exit(wg->wg_lock); 3337 mutex_exit(wg->wg_lock);
3322 3338
3323 if (wgp == NULL) 3339 if (wgp == NULL)
3324 return ENOENT; 3340 return ENOENT;
3325 3341
3326 psref_target_destroy(&wgp->wgp_psref, wg_psref_class); 3342 psref_target_destroy(&wgp->wgp_psref, wg_psref_class);
3327 3343
3328 wg_destroy_peer(wgp); 3344 wg_destroy_peer(wgp);
3329 3345
3330 return 0; 3346 return 0;
3331} 3347}
3332 3348
3333static int 3349static int
3334wg_if_attach(struct wg_softc *wg) 3350wg_if_attach(struct wg_softc *wg)
3335{ 3351{
3336 int error; 3352 int error;
3337 3353
3338 wg->wg_if.if_addrlen = 0; 3354 wg->wg_if.if_addrlen = 0;
3339 wg->wg_if.if_mtu = WG_MTU; 3355 wg->wg_if.if_mtu = WG_MTU;
3340 wg->wg_if.if_flags = IFF_POINTOPOINT; 3356 wg->wg_if.if_flags = IFF_POINTOPOINT;
3341 wg->wg_if.if_extflags = IFEF_NO_LINK_STATE_CHANGE; 3357 wg->wg_if.if_extflags = IFEF_NO_LINK_STATE_CHANGE;
3342 wg->wg_if.if_extflags |= IFEF_MPSAFE; 3358 wg->wg_if.if_extflags |= IFEF_MPSAFE;
3343 wg->wg_if.if_ioctl = wg_ioctl; 3359 wg->wg_if.if_ioctl = wg_ioctl;
3344 wg->wg_if.if_output = wg_output; 3360 wg->wg_if.if_output = wg_output;
3345 wg->wg_if.if_init = wg_init; 3361 wg->wg_if.if_init = wg_init;
3346 wg->wg_if.if_stop = wg_stop; 3362 wg->wg_if.if_stop = wg_stop;
3347 wg->wg_if.if_type = IFT_OTHER; 3363 wg->wg_if.if_type = IFT_OTHER;
3348 wg->wg_if.if_dlt = DLT_NULL; 3364 wg->wg_if.if_dlt = DLT_NULL;
3349 wg->wg_if.if_softc = wg; 3365 wg->wg_if.if_softc = wg;
3350 IFQ_SET_READY(&wg->wg_if.if_snd); 3366 IFQ_SET_READY(&wg->wg_if.if_snd);
3351 3367
3352 error = if_initialize(&wg->wg_if); 3368 error = if_initialize(&wg->wg_if);
3353 if (error != 0) 3369 if (error != 0)
3354 return error; 3370 return error;
3355 3371
3356 if_alloc_sadl(&wg->wg_if); 3372 if_alloc_sadl(&wg->wg_if);
3357 if_register(&wg->wg_if); 3373 if_register(&wg->wg_if);
3358 3374
3359 bpf_attach(&wg->wg_if, DLT_NULL, sizeof(uint32_t)); 3375 bpf_attach(&wg->wg_if, DLT_NULL, sizeof(uint32_t));
3360 3376
3361 return 0; 3377 return 0;
3362} 3378}
3363 3379
3364static int 3380static int
3365wg_clone_create(struct if_clone *ifc, int unit) 3381wg_clone_create(struct if_clone *ifc, int unit)
3366{ 3382{
3367 struct wg_softc *wg; 3383 struct wg_softc *wg;
3368 int error; 3384 int error;
3369 3385
3370 wg = kmem_zalloc(sizeof(struct wg_softc), KM_SLEEP); 3386 wg = kmem_zalloc(sizeof(struct wg_softc), KM_SLEEP);
3371 3387
3372 if_initname(&wg->wg_if, ifc->ifc_name, unit); 3388 if_initname(&wg->wg_if, ifc->ifc_name, unit);
3373 3389
3374 error = wg_worker_init(wg); 3390 error = wg_worker_init(wg);
3375 if (error != 0) { 3391 if (error != 0) {
3376 kmem_free(wg, sizeof(struct wg_softc)); 3392 kmem_free(wg, sizeof(struct wg_softc));
3377 return error; 3393 return error;
3378 } 3394 }
3379 3395
3380 rn_inithead((void **)&wg->wg_rtable_ipv4, 3396 rn_inithead((void **)&wg->wg_rtable_ipv4,
3381 offsetof(struct sockaddr_in, sin_addr) * NBBY); 3397 offsetof(struct sockaddr_in, sin_addr) * NBBY);
3382#ifdef INET6 3398#ifdef INET6
3383 rn_inithead((void **)&wg->wg_rtable_ipv6, 3399 rn_inithead((void **)&wg->wg_rtable_ipv6,
3384 offsetof(struct sockaddr_in6, sin6_addr) * NBBY); 3400 offsetof(struct sockaddr_in6, sin6_addr) * NBBY);
3385#endif 3401#endif
3386 3402
3387 PSLIST_INIT(&wg->wg_peers); 3403 PSLIST_INIT(&wg->wg_peers);
3388 wg->wg_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); 3404 wg->wg_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
3389 wg->wg_rwlock = rw_obj_alloc(); 3405 wg->wg_rwlock = rw_obj_alloc();
3390 wg->wg_ops = &wg_ops_rumpkernel; 3406 wg->wg_ops = &wg_ops_rumpkernel;
3391 3407
3392 error = wg_if_attach(wg); 3408 error = wg_if_attach(wg);
3393 if (error != 0) { 3409 if (error != 0) {
3394 wg_worker_destroy(wg); 3410 wg_worker_destroy(wg);
3395 if (wg->wg_rtable_ipv4 != NULL) 3411 if (wg->wg_rtable_ipv4 != NULL)
3396 free(wg->wg_rtable_ipv4, M_RTABLE); 3412 free(wg->wg_rtable_ipv4, M_RTABLE);
3397 if (wg->wg_rtable_ipv6 != NULL) 3413 if (wg->wg_rtable_ipv6 != NULL)
3398 free(wg->wg_rtable_ipv6, M_RTABLE); 3414 free(wg->wg_rtable_ipv6, M_RTABLE);
3399 PSLIST_DESTROY(&wg->wg_peers); 3415 PSLIST_DESTROY(&wg->wg_peers);
3400 mutex_obj_free(wg->wg_lock); 3416 mutex_obj_free(wg->wg_lock);
3401 kmem_free(wg, sizeof(struct wg_softc)); 3417 kmem_free(wg, sizeof(struct wg_softc));
3402 return error; 3418 return error;
3403 } 3419 }
3404 3420
3405 mutex_enter(&wg_softcs.lock); 3421 mutex_enter(&wg_softcs.lock);
3406 LIST_INSERT_HEAD(&wg_softcs.list, wg, wg_list); 3422 LIST_INSERT_HEAD(&wg_softcs.list, wg, wg_list);
3407 mutex_exit(&wg_softcs.lock); 3423 mutex_exit(&wg_softcs.lock);
3408 3424
3409 return 0; 3425 return 0;
3410} 3426}
3411 3427
3412static int 3428static int
3413wg_clone_destroy(struct ifnet *ifp) 3429wg_clone_destroy(struct ifnet *ifp)
3414{ 3430{
3415 struct wg_softc *wg = container_of(ifp, struct wg_softc, wg_if); 3431 struct wg_softc *wg = container_of(ifp, struct wg_softc, wg_if);
3416 3432
3417 mutex_enter(&wg_softcs.lock); 3433 mutex_enter(&wg_softcs.lock);
3418 LIST_REMOVE(wg, wg_list); 3434 LIST_REMOVE(wg, wg_list);
3419 mutex_exit(&wg_softcs.lock); 3435 mutex_exit(&wg_softcs.lock);
3420 3436
3421#ifdef WG_RUMPKERNEL 3437#ifdef WG_RUMPKERNEL
3422 if (wg_user_mode(wg)) { 3438 if (wg_user_mode(wg)) {
3423 rumpuser_wg_destroy(wg->wg_user); 3439 rumpuser_wg_destroy(wg->wg_user);
3424 wg->wg_user = NULL; 3440 wg->wg_user = NULL;
3425 } 3441 }
3426#endif 3442#endif
3427 3443
3428 bpf_detach(ifp); 3444 bpf_detach(ifp);
3429 if_detach(ifp); 3445 if_detach(ifp);
3430 wg_worker_destroy(wg); 3446 wg_worker_destroy(wg);
3431 wg_destroy_all_peers(wg); 3447 wg_destroy_all_peers(wg);
3432 if (wg->wg_rtable_ipv4 != NULL) 3448 if (wg->wg_rtable_ipv4 != NULL)
3433 free(wg->wg_rtable_ipv4, M_RTABLE); 3449 free(wg->wg_rtable_ipv4, M_RTABLE);
3434 if (wg->wg_rtable_ipv6 != NULL) 3450 if (wg->wg_rtable_ipv6 != NULL)
3435 free(wg->wg_rtable_ipv6, M_RTABLE); 3451 free(wg->wg_rtable_ipv6, M_RTABLE);
3436 3452
3437 PSLIST_DESTROY(&wg->wg_peers); 3453 PSLIST_DESTROY(&wg->wg_peers);
3438 mutex_obj_free(wg->wg_lock); 3454 mutex_obj_free(wg->wg_lock);
3439 rw_obj_free(wg->wg_rwlock); 3455 rw_obj_free(wg->wg_rwlock);
3440 3456
3441 kmem_free(wg, sizeof(struct wg_softc)); 3457 kmem_free(wg, sizeof(struct wg_softc));
3442 3458
3443 return 0; 3459 return 0;
3444} 3460}
3445 3461
3446static struct wg_peer * 3462static struct wg_peer *
3447wg_pick_peer_by_sa(struct wg_softc *wg, const struct sockaddr *sa, 3463wg_pick_peer_by_sa(struct wg_softc *wg, const struct sockaddr *sa,
3448 struct psref *psref) 3464 struct psref *psref)
3449{ 3465{
3450 struct radix_node_head *rnh; 3466 struct radix_node_head *rnh;
3451 struct radix_node *rn; 3467 struct radix_node *rn;
3452 struct wg_peer *wgp = NULL; 3468 struct wg_peer *wgp = NULL;
3453 struct wg_allowedip *wga; 3469 struct wg_allowedip *wga;
3454 3470
3455#ifdef WG_DEBUG_LOG 3471#ifdef WG_DEBUG_LOG
3456 char addrstr[128]; 3472 char addrstr[128];
3457 sockaddr_format(sa, addrstr, sizeof(addrstr)); 3473 sockaddr_format(sa, addrstr, sizeof(addrstr));
3458 WG_DLOG("sa=%s\n", addrstr); 3474 WG_DLOG("sa=%s\n", addrstr);
3459#endif 3475#endif
3460 3476
3461 rw_enter(wg->wg_rwlock, RW_READER); 3477 rw_enter(wg->wg_rwlock, RW_READER);
3462 3478
3463 rnh = wg_rnh(wg, sa->sa_family); 3479 rnh = wg_rnh(wg, sa->sa_family);
3464 if (rnh == NULL) 3480 if (rnh == NULL)
3465 goto out; 3481 goto out;
3466 3482
3467 rn = rnh->rnh_matchaddr(sa, rnh); 3483 rn = rnh->rnh_matchaddr(sa, rnh);
3468 if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0) 3484 if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0)
3469 goto out; 3485 goto out;
3470 3486
3471 WG_TRACE("success"); 3487 WG_TRACE("success");
3472 3488
3473 wga = container_of(rn, struct wg_allowedip, wga_nodes[0]); 3489 wga = container_of(rn, struct wg_allowedip, wga_nodes[0]);
3474 wgp = wga->wga_peer; 3490 wgp = wga->wga_peer;
3475 wg_get_peer(wgp, psref); 3491 wg_get_peer(wgp, psref);
3476 3492
3477out: 3493out:
3478 rw_exit(wg->wg_rwlock); 3494 rw_exit(wg->wg_rwlock);
3479 return wgp; 3495 return wgp;
3480} 3496}
3481 3497
3482static void 3498static void
3483wg_fill_msg_data(struct wg_softc *wg, struct wg_peer *wgp, 3499wg_fill_msg_data(struct wg_softc *wg, struct wg_peer *wgp,
3484 struct wg_session *wgs, struct wg_msg_data *wgmd) 3500 struct wg_session *wgs, struct wg_msg_data *wgmd)
3485{ 3501{
3486 3502
3487 memset(wgmd, 0, sizeof(*wgmd)); 3503 memset(wgmd, 0, sizeof(*wgmd));
3488 wgmd->wgmd_type = WG_MSG_TYPE_DATA; 3504 wgmd->wgmd_type = WG_MSG_TYPE_DATA;
3489 wgmd->wgmd_receiver = wgs->wgs_receiver_index; 3505 wgmd->wgmd_receiver = wgs->wgs_receiver_index;
3490 /* [W] 5.4.6: msg.counter := Nm^send */ 3506 /* [W] 5.4.6: msg.counter := Nm^send */
3491 /* [W] 5.4.6: Nm^send := Nm^send + 1 */ 3507 /* [W] 5.4.6: Nm^send := Nm^send + 1 */
3492 wgmd->wgmd_counter = wg_session_inc_send_counter(wgs); 3508 wgmd->wgmd_counter = wg_session_inc_send_counter(wgs);
3493 WG_DLOG("counter=%"PRIu64"\n", wgmd->wgmd_counter); 3509 WG_DLOG("counter=%"PRIu64"\n", wgmd->wgmd_counter);
3494} 3510}
3495 3511
3496static int 3512static int
3497wg_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 3513wg_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
3498 const struct rtentry *rt) 3514 const struct rtentry *rt)
3499{ 3515{
3500 struct wg_softc *wg = ifp->if_softc; 3516 struct wg_softc *wg = ifp->if_softc;
3501 int error = 0; 3517 int error = 0;
3502 int bound; 3518 int bound;
3503 struct psref psref; 3519 struct psref psref;
3504 3520
3505 /* TODO make the nest limit configurable via sysctl */ 3521 /* TODO make the nest limit configurable via sysctl */
3506 error = if_tunnel_check_nesting(ifp, m, 1); 3522 error = if_tunnel_check_nesting(ifp, m, 1);
3507 if (error != 0) { 3523 if (error != 0) {
3508 m_freem(m); 3524 m_freem(m);
3509 WGLOG(LOG_ERR, "tunneling loop detected and packet dropped\n"); 3525 WGLOG(LOG_ERR, "tunneling loop detected and packet dropped\n");
3510 return error; 3526 return error;
3511 } 3527 }
3512 3528
3513 bound = curlwp_bind(); 3529 bound = curlwp_bind();
3514 3530
3515 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family); 3531 IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family);
3516 3532
3517 bpf_mtap_af(ifp, dst->sa_family, m, BPF_D_OUT); 3533 bpf_mtap_af(ifp, dst->sa_family, m, BPF_D_OUT);
3518 3534
3519 m->m_flags &= ~(M_BCAST|M_MCAST); 3535 m->m_flags &= ~(M_BCAST|M_MCAST);
3520 3536
3521 struct wg_peer *wgp = wg_pick_peer_by_sa(wg, dst, &psref); 3537 struct wg_peer *wgp = wg_pick_peer_by_sa(wg, dst, &psref);
3522 if (wgp == NULL) { 3538 if (wgp == NULL) {
3523 WG_TRACE("peer not found"); 3539 WG_TRACE("peer not found");
3524 error = EHOSTUNREACH; 3540 error = EHOSTUNREACH;
3525 goto error; 3541 goto error;
3526 } 3542 }
3527 3543
3528 /* Clear checksum-offload flags. */ 3544 /* Clear checksum-offload flags. */
3529 m->m_pkthdr.csum_flags = 0; 3545 m->m_pkthdr.csum_flags = 0;
3530 m->m_pkthdr.csum_data = 0; 3546 m->m_pkthdr.csum_data = 0;
3531 3547
3532 if (!pcq_put(wgp->wgp_q, m)) { 3548 if (!pcq_put(wgp->wgp_q, m)) {
3533 error = ENOBUFS; 3549 error = ENOBUFS;
3534 goto error; 3550 goto error;
3535 } 3551 }
3536 3552
3537 struct psref psref_wgs; 3553 struct psref psref_wgs;
3538 struct wg_session *wgs; 3554 struct wg_session *wgs;
3539 wgs = wg_get_stable_session(wgp, &psref_wgs); 3555 wgs = wg_get_stable_session(wgp, &psref_wgs);
3540 if (wgs->wgs_state == WGS_STATE_ESTABLISHED && 3556 if (wgs->wgs_state == WGS_STATE_ESTABLISHED &&
3541 !wg_session_hit_limits(wgs)) { 3557 !wg_session_hit_limits(wgs)) {
3542 kpreempt_disable(); 3558 kpreempt_disable();
3543 softint_schedule(wgp->wgp_si); 3559 softint_schedule(wgp->wgp_si);
3544 kpreempt_enable(); 3560 kpreempt_enable();
3545 WG_TRACE("softint scheduled"); 3561 WG_TRACE("softint scheduled");
3546 } else { 3562 } else {
3547 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3563 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3548 WG_TRACE("softint NOT scheduled"); 3564 WG_TRACE("softint NOT scheduled");
3549 } 3565 }
3550 wg_put_session(wgs, &psref_wgs); 3566 wg_put_session(wgs, &psref_wgs);
3551 wg_put_peer(wgp, &psref); 3567 wg_put_peer(wgp, &psref);
3552 3568
3553 return 0; 3569 return 0;
3554 3570
3555error: 3571error:
3556 if (wgp != NULL) 3572 if (wgp != NULL)
3557 wg_put_peer(wgp, &psref); 3573 wg_put_peer(wgp, &psref);
3558 if (m != NULL) 3574 if (m != NULL)
3559 m_freem(m); 3575 m_freem(m);
3560 curlwp_bindx(bound); 3576 curlwp_bindx(bound);
3561 return error; 3577 return error;
3562} 3578}
3563 3579
3564static int 3580static int
3565wg_send_udp(struct wg_peer *wgp, struct mbuf *m) 3581wg_send_udp(struct wg_peer *wgp, struct mbuf *m)
3566{ 3582{
3567 struct psref psref; 3583 struct psref psref;
3568 struct wg_sockaddr *wgsa; 3584 struct wg_sockaddr *wgsa;
3569 int error; 3585 int error;
3570 struct socket *so = wg_get_so_by_peer(wgp); 3586 struct socket *so = wg_get_so_by_peer(wgp);
3571 3587
3572 solock(so); 3588 solock(so);
3573 wgsa = wg_get_endpoint_sa(wgp, &psref); 3589 wgsa = wg_get_endpoint_sa(wgp, &psref);
3574 if (wgsatosa(wgsa)->sa_family == AF_INET) { 3590 if (wgsatosa(wgsa)->sa_family == AF_INET) {
3575 error = udp_send(so, m, wgsatosa(wgsa), NULL, curlwp); 3591 error = udp_send(so, m, wgsatosa(wgsa), NULL, curlwp);
3576 } else { 3592 } else {
3577#ifdef INET6 3593#ifdef INET6
3578 error = udp6_output(sotoin6pcb(so), m, wgsatosin6(wgsa), 3594 error = udp6_output(sotoin6pcb(so), m, wgsatosin6(wgsa),
3579 NULL, curlwp); 3595 NULL, curlwp);
3580#else 3596#else
3581 error = EPROTONOSUPPORT; 3597 error = EPROTONOSUPPORT;
3582#endif 3598#endif
3583 } 3599 }
3584 wg_put_sa(wgp, wgsa, &psref); 3600 wg_put_sa(wgp, wgsa, &psref);
3585 sounlock(so); 3601 sounlock(so);
3586 3602
3587 return error; 3603 return error;
3588} 3604}
3589 3605
3590/* Inspired by pppoe_get_mbuf */ 3606/* Inspired by pppoe_get_mbuf */
3591static struct mbuf * 3607static struct mbuf *
3592wg_get_mbuf(size_t leading_len, size_t len) 3608wg_get_mbuf(size_t leading_len, size_t len)
3593{ 3609{
3594 struct mbuf *m; 3610 struct mbuf *m;
3595 3611
3596 m = m_gethdr(M_DONTWAIT, MT_DATA); 3612 m = m_gethdr(M_DONTWAIT, MT_DATA);
3597 if (m == NULL) 3613 if (m == NULL)
3598 return NULL; 3614 return NULL;
3599 if (len + leading_len > MHLEN) { 3615 if (len + leading_len > MHLEN) {
3600 m_clget(m, M_DONTWAIT); 3616 m_clget(m, M_DONTWAIT);
3601 if ((m->m_flags & M_EXT) == 0) { 3617 if ((m->m_flags & M_EXT) == 0) {
3602 m_free(m); 3618 m_free(m);
3603 return NULL; 3619 return NULL;
3604 } 3620 }
3605 } 3621 }
3606 m->m_data += leading_len; 3622 m->m_data += leading_len;
3607 m->m_pkthdr.len = m->m_len = len; 3623 m->m_pkthdr.len = m->m_len = len;
3608 3624
3609 return m; 3625 return m;
3610} 3626}
3611 3627
3612static int 3628static int
3613wg_send_data_msg(struct wg_peer *wgp, struct wg_session *wgs, 3629wg_send_data_msg(struct wg_peer *wgp, struct wg_session *wgs,
3614 struct mbuf *m) 3630 struct mbuf *m)
3615{ 3631{
3616 struct wg_softc *wg = wgp->wgp_sc; 3632 struct wg_softc *wg = wgp->wgp_sc;
3617 int error; 3633 int error;
3618 size_t inner_len, padded_len, encrypted_len; 3634 size_t inner_len, padded_len, encrypted_len;
3619 char *padded_buf = NULL; 3635 char *padded_buf = NULL;
3620 size_t mlen; 3636 size_t mlen;
3621 struct wg_msg_data *wgmd; 3637 struct wg_msg_data *wgmd;
3622 bool free_padded_buf = false; 3638 bool free_padded_buf = false;
3623 struct mbuf *n; 3639 struct mbuf *n;
3624 size_t leading_len = max_linkhdr + sizeof(struct ip6_hdr) + 3640 size_t leading_len = max_linkhdr + sizeof(struct ip6_hdr) +
3625 sizeof(struct udphdr); 3641 sizeof(struct udphdr);
3626 3642
3627 mlen = m_length(m); 3643 mlen = m_length(m);
3628 inner_len = mlen; 3644 inner_len = mlen;
3629 padded_len = roundup(mlen, 16); 3645 padded_len = roundup(mlen, 16);
3630 encrypted_len = padded_len + WG_AUTHTAG_LEN; 3646 encrypted_len = padded_len + WG_AUTHTAG_LEN;
3631 WG_DLOG("inner=%lu, padded=%lu, encrypted_len=%lu\n", 3647 WG_DLOG("inner=%lu, padded=%lu, encrypted_len=%lu\n",
3632 inner_len, padded_len, encrypted_len); 3648 inner_len, padded_len, encrypted_len);
3633 if (mlen != 0) { 3649 if (mlen != 0) {
3634 bool success; 3650 bool success;
3635 success = m_ensure_contig(&m, padded_len); 3651 success = m_ensure_contig(&m, padded_len);
3636 if (success) { 3652 if (success) {
3637 padded_buf = mtod(m, char *); 3653 padded_buf = mtod(m, char *);
3638 } else { 3654 } else {
3639 padded_buf = kmem_intr_alloc(padded_len, KM_NOSLEEP); 3655 padded_buf = kmem_intr_alloc(padded_len, KM_NOSLEEP);
3640 if (padded_buf == NULL) { 3656 if (padded_buf == NULL) {
3641 error = ENOBUFS; 3657 error = ENOBUFS;
3642 goto end; 3658 goto end;
3643 } 3659 }
3644 free_padded_buf = true; 3660 free_padded_buf = true;
3645 m_copydata(m, 0, mlen, padded_buf); 3661 m_copydata(m, 0, mlen, padded_buf);
3646 } 3662 }
3647 memset(padded_buf + mlen, 0, padded_len - inner_len); 3663 memset(padded_buf + mlen, 0, padded_len - inner_len);
3648 } 3664 }
3649 3665
3650 n = wg_get_mbuf(leading_len, sizeof(*wgmd) + encrypted_len); 3666 n = wg_get_mbuf(leading_len, sizeof(*wgmd) + encrypted_len);
3651 if (n == NULL) { 3667 if (n == NULL) {
3652 error = ENOBUFS; 3668 error = ENOBUFS;
3653 goto end; 3669 goto end;
3654 } 3670 }
3655 wgmd = mtod(n, struct wg_msg_data *); 3671 wgmd = mtod(n, struct wg_msg_data *);
3656 wg_fill_msg_data(wg, wgp, wgs, wgmd); 3672 wg_fill_msg_data(wg, wgp, wgs, wgmd);
3657 /* [W] 5.4.6: AEAD(Tm^send, Nm^send, P, e) */ 3673 /* [W] 5.4.6: AEAD(Tm^send, Nm^send, P, e) */
3658 wg_algo_aead_enc((char *)wgmd + sizeof(*wgmd), encrypted_len, 3674 wg_algo_aead_enc((char *)wgmd + sizeof(*wgmd), encrypted_len,
3659 wgs->wgs_tkey_send, wgmd->wgmd_counter, padded_buf, padded_len, 3675 wgs->wgs_tkey_send, wgmd->wgmd_counter, padded_buf, padded_len,
3660 NULL, 0); 3676 NULL, 0);
3661 3677
3662 error = wg->wg_ops->send_data_msg(wgp, n); 3678 error = wg->wg_ops->send_data_msg(wgp, n);
3663 if (error == 0) { 3679 if (error == 0) {
3664 struct ifnet *ifp = &wg->wg_if; 3680 struct ifnet *ifp = &wg->wg_if;
3665 if_statadd(ifp, if_obytes, mlen); 3681 if_statadd(ifp, if_obytes, mlen);
3666 if_statinc(ifp, if_opackets); 3682 if_statinc(ifp, if_opackets);
3667 if (wgs->wgs_is_initiator && 3683 if (wgs->wgs_is_initiator &&
3668 wgs->wgs_time_last_data_sent == 0) { 3684 wgs->wgs_time_last_data_sent == 0) {
3669 /* 3685 /*
3670 * [W] 6.2 Transport Message Limits 3686 * [W] 6.2 Transport Message Limits
3671 * "if a peer is the initiator of a current secure 3687 * "if a peer is the initiator of a current secure
3672 * session, WireGuard will send a handshake initiation 3688 * session, WireGuard will send a handshake initiation
3673 * message to begin a new secure session if, after 3689 * message to begin a new secure session if, after
3674 * transmitting a transport data message, the current 3690 * transmitting a transport data message, the current
3675 * secure session is REKEY-AFTER-TIME seconds old," 3691 * secure session is REKEY-AFTER-TIME seconds old,"
3676 */ 3692 */
3677 wg_schedule_rekey_timer(wgp); 3693 wg_schedule_rekey_timer(wgp);
3678 } 3694 }
3679 wgs->wgs_time_last_data_sent = time_uptime; 3695 wgs->wgs_time_last_data_sent = time_uptime;
3680 if (wg_session_get_send_counter(wgs) >= 3696 if (wg_session_get_send_counter(wgs) >=
3681 wg_rekey_after_messages) { 3697 wg_rekey_after_messages) {
3682 /* 3698 /*
3683 * [W] 6.2 Transport Message Limits 3699 * [W] 6.2 Transport Message Limits
3684 * "WireGuard will try to create a new session, by 3700 * "WireGuard will try to create a new session, by
3685 * sending a handshake initiation message (section 3701 * sending a handshake initiation message (section
3686 * 5.4.2), after it has sent REKEY-AFTER-MESSAGES 3702 * 5.4.2), after it has sent REKEY-AFTER-MESSAGES
3687 * transport data messages..." 3703 * transport data messages..."
3688 */ 3704 */
3689 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE); 3705 wg_schedule_peer_task(wgp, WGP_TASK_SEND_INIT_MESSAGE);
3690 } 3706 }
3691 } 3707 }
3692end: 3708end:
3693 m_freem(m); 3709 m_freem(m);
3694 if (free_padded_buf) 3710 if (free_padded_buf)
3695 kmem_intr_free(padded_buf, padded_len); 3711 kmem_intr_free(padded_buf, padded_len);
3696 return error; 3712 return error;
3697} 3713}
3698 3714
3699static void 3715static void
3700wg_input(struct ifnet *ifp, struct mbuf *m, const int af) 3716wg_input(struct ifnet *ifp, struct mbuf *m, const int af)
3701{ 3717{
3702 pktqueue_t *pktq; 3718 pktqueue_t *pktq;
3703 size_t pktlen; 3719 size_t pktlen;
3704 3720
3705 KASSERT(af == AF_INET || af == AF_INET6); 3721 KASSERT(af == AF_INET || af == AF_INET6);
3706 3722
3707 WG_TRACE(""); 3723 WG_TRACE("");
3708 3724
3709 m_set_rcvif(m, ifp); 3725 m_set_rcvif(m, ifp);
3710 pktlen = m->m_pkthdr.len; 3726 pktlen = m->m_pkthdr.len;
3711 3727
3712 bpf_mtap_af(ifp, af, m, BPF_D_IN); 3728 bpf_mtap_af(ifp, af, m, BPF_D_IN);
3713 3729
3714 switch (af) { 3730 switch (af) {
3715 case AF_INET: 3731 case AF_INET:
3716 pktq = ip_pktq; 3732 pktq = ip_pktq;
3717 break; 3733 break;
3718#ifdef INET6 3734#ifdef INET6
3719 case AF_INET6: 3735 case AF_INET6:
3720 pktq = ip6_pktq; 3736 pktq = ip6_pktq;
3721 break; 3737 break;
3722#endif 3738#endif
3723 default: 3739 default:
3724 panic("invalid af=%d", af); 3740 panic("invalid af=%d", af);
3725 } 3741 }
3726 3742
3727 const u_int h = curcpu()->ci_index; 3743 const u_int h = curcpu()->ci_index;
3728 if (__predict_true(pktq_enqueue(pktq, m, h))) { 3744 if (__predict_true(pktq_enqueue(pktq, m, h))) {
3729 if_statadd(ifp, if_ibytes, pktlen); 3745 if_statadd(ifp, if_ibytes, pktlen);
3730 if_statinc(ifp, if_ipackets); 3746 if_statinc(ifp, if_ipackets);
3731 } else { 3747 } else {
3732 m_freem(m); 3748 m_freem(m);
3733 } 3749 }
3734} 3750}
3735 3751
3736static void 3752static void
3737wg_calc_pubkey(uint8_t pubkey[WG_STATIC_KEY_LEN], 3753wg_calc_pubkey(uint8_t pubkey[WG_STATIC_KEY_LEN],
3738 const uint8_t privkey[WG_STATIC_KEY_LEN]) 3754 const uint8_t privkey[WG_STATIC_KEY_LEN])
3739{ 3755{
3740 3756
3741 crypto_scalarmult_base(pubkey, privkey); 3757 crypto_scalarmult_base(pubkey, privkey);
3742} 3758}
3743 3759
3744static int 3760static int
3745wg_rtable_add_route(struct wg_softc *wg, struct wg_allowedip *wga) 3761wg_rtable_add_route(struct wg_softc *wg, struct wg_allowedip *wga)
3746{ 3762{
3747 struct radix_node_head *rnh; 3763 struct radix_node_head *rnh;
3748 struct radix_node *rn; 3764 struct radix_node *rn;
3749 int error = 0; 3765 int error = 0;
3750 3766
3751 rw_enter(wg->wg_rwlock, RW_WRITER); 3767 rw_enter(wg->wg_rwlock, RW_WRITER);
3752 rnh = wg_rnh(wg, wga->wga_family); 3768 rnh = wg_rnh(wg, wga->wga_family);
3753 KASSERT(rnh != NULL); 3769 KASSERT(rnh != NULL);
3754 rn = rnh->rnh_addaddr(&wga->wga_sa_addr, &wga->wga_sa_mask, rnh, 3770 rn = rnh->rnh_addaddr(&wga->wga_sa_addr, &wga->wga_sa_mask, rnh,
3755 wga->wga_nodes); 3771 wga->wga_nodes);
3756 rw_exit(wg->wg_rwlock); 3772 rw_exit(wg->wg_rwlock);
3757 3773
3758 if (rn == NULL) 3774 if (rn == NULL)
3759 error = EEXIST; 3775 error = EEXIST;
3760 3776
3761 return error; 3777 return error;
3762} 3778}
3763 3779
3764static int 3780static int
3765wg_handle_prop_peer(struct wg_softc *wg, prop_dictionary_t peer, 3781wg_handle_prop_peer(struct wg_softc *wg, prop_dictionary_t peer,
3766 struct wg_peer **wgpp) 3782 struct wg_peer **wgpp)
3767{ 3783{
3768 int error = 0; 3784 int error = 0;
3769 const void *pubkey; 3785 const void *pubkey;
3770 size_t pubkey_len; 3786 size_t pubkey_len;
3771 const void *psk; 3787 const void *psk;
3772 size_t psk_len; 3788 size_t psk_len;
3773 const char *name = NULL; 3789 const char *name = NULL;
3774 3790
3775 if (prop_dictionary_get_string(peer, "name", &name)) { 3791 if (prop_dictionary_get_string(peer, "name", &name)) {
3776 if (strlen(name) > WG_PEER_NAME_MAXLEN) { 3792 if (strlen(name) > WG_PEER_NAME_MAXLEN) {
3777 error = EINVAL; 3793 error = EINVAL;
3778 goto out; 3794 goto out;
3779 } 3795 }
3780 } 3796 }
3781 3797
3782 if (!prop_dictionary_get_data(peer, "public_key", 3798 if (!prop_dictionary_get_data(peer, "public_key",
3783 &pubkey, &pubkey_len)) { 3799 &pubkey, &pubkey_len)) {
3784 error = EINVAL; 3800 error = EINVAL;
3785 goto out; 3801 goto out;
3786 } 3802 }
3787#ifdef WG_DEBUG_DUMP 3803#ifdef WG_DEBUG_DUMP
3788 log(LOG_DEBUG, "pubkey=%p, pubkey_len=%lu\n", pubkey, pubkey_len); 3804 log(LOG_DEBUG, "pubkey=%p, pubkey_len=%lu\n", pubkey, pubkey_len);
3789 for (int _i = 0; _i < pubkey_len; _i++) 3805 for (int _i = 0; _i < pubkey_len; _i++)
3790 log(LOG_DEBUG, "%c", ((const char *)pubkey)[_i]); 3806 log(LOG_DEBUG, "%c", ((const char *)pubkey)[_i]);
3791 log(LOG_DEBUG, "\n"); 3807 log(LOG_DEBUG, "\n");
3792#endif 3808#endif
3793 3809
3794 struct wg_peer *wgp = wg_alloc_peer(wg); 3810 struct wg_peer *wgp = wg_alloc_peer(wg);
3795 memcpy(wgp->wgp_pubkey, pubkey, sizeof(wgp->wgp_pubkey)); 3811 memcpy(wgp->wgp_pubkey, pubkey, sizeof(wgp->wgp_pubkey));
3796 if (name != NULL) 3812 if (name != NULL)
3797 strncpy(wgp->wgp_name, name, sizeof(wgp->wgp_name)); 3813 strncpy(wgp->wgp_name, name, sizeof(wgp->wgp_name));
3798 3814
3799 if (prop_dictionary_get_data(peer, "preshared_key", &psk, &psk_len)) { 3815 if (prop_dictionary_get_data(peer, "preshared_key", &psk, &psk_len)) {
3800 if (psk_len != sizeof(wgp->wgp_psk)) { 3816 if (psk_len != sizeof(wgp->wgp_psk)) {
3801 error = EINVAL; 3817 error = EINVAL;
3802 goto out; 3818 goto out;
3803 } 3819 }
3804 memcpy(wgp->wgp_psk, psk, sizeof(wgp->wgp_psk)); 3820 memcpy(wgp->wgp_psk, psk, sizeof(wgp->wgp_psk));
3805 } 3821 }
3806 3822
3807 struct sockaddr_storage sockaddr; 3823 struct sockaddr_storage sockaddr;
3808 const void *addr; 3824 const void *addr;
3809 size_t addr_len; 3825 size_t addr_len;
3810 3826
3811 if (!prop_dictionary_get_data(peer, "endpoint", &addr, &addr_len)) 3827 if (!prop_dictionary_get_data(peer, "endpoint", &addr, &addr_len))
3812 goto skip_endpoint; 3828 goto skip_endpoint;
3813 memcpy(&sockaddr, addr, addr_len); 3829 memcpy(&sockaddr, addr, addr_len);
3814 switch (sockaddr.ss_family) { 3830 switch (sockaddr.ss_family) {
3815 case AF_INET: { 3831 case AF_INET: {
3816 struct sockaddr_in sin; 3832 struct sockaddr_in sin;
3817 sockaddr_copy(sintosa(&sin), sizeof(sin), 3833 sockaddr_copy(sintosa(&sin), sizeof(sin),
3818 (const struct sockaddr *)&sockaddr); 3834 (const struct sockaddr *)&sockaddr);
3819 sockaddr_copy(sintosa(&wgp->wgp_sin), 3835 sockaddr_copy(sintosa(&wgp->wgp_sin),
3820 sizeof(wgp->wgp_sin), (const struct sockaddr *)&sockaddr); 3836 sizeof(wgp->wgp_sin), (const struct sockaddr *)&sockaddr);
3821 char addrstr[128]; 3837 char addrstr[128];
3822 sockaddr_format(sintosa(&sin), addrstr, sizeof(addrstr)); 3838 sockaddr_format(sintosa(&sin), addrstr, sizeof(addrstr));
3823 WG_DLOG("addr=%s\n", addrstr); 3839 WG_DLOG("addr=%s\n", addrstr);
3824 break; 3840 break;
3825 } 3841 }
3826#ifdef INET6 3842#ifdef INET6
3827 case AF_INET6: { 3843 case AF_INET6: {
3828 struct sockaddr_in6 sin6; 3844 struct sockaddr_in6 sin6;
3829 char addrstr[128]; 3845 char addrstr[128];
3830 sockaddr_copy(sintosa(&sin6), sizeof(sin6), 3846 sockaddr_copy(sintosa(&sin6), sizeof(sin6),
3831 (const struct sockaddr *)&sockaddr); 3847 (const struct sockaddr *)&sockaddr);
3832 sockaddr_format(sintosa(&sin6), addrstr, sizeof(addrstr)); 3848 sockaddr_format(sintosa(&sin6), addrstr, sizeof(addrstr));
3833 WG_DLOG("addr=%s\n", addrstr); 3849 WG_DLOG("addr=%s\n", addrstr);
3834 sockaddr_copy(sin6tosa(&wgp->wgp_sin6), 3850 sockaddr_copy(sin6tosa(&wgp->wgp_sin6),
3835 sizeof(wgp->wgp_sin6), (const struct sockaddr *)&sockaddr); 3851 sizeof(wgp->wgp_sin6), (const struct sockaddr *)&sockaddr);
3836 break; 3852 break;
3837 } 3853 }
3838#endif 3854#endif
3839 default: 3855 default:
3840 break; 3856 break;
3841 } 3857 }
3842 wgp->wgp_endpoint_available = true; 3858 wgp->wgp_endpoint_available = true;
3843 3859
3844 prop_array_t allowedips; 3860 prop_array_t allowedips;
3845skip_endpoint: 3861skip_endpoint:
3846 allowedips = prop_dictionary_get(peer, "allowedips"); 3862 allowedips = prop_dictionary_get(peer, "allowedips");
3847 if (allowedips == NULL) 3863 if (allowedips == NULL)
3848 goto skip; 3864 goto skip;
3849 3865
3850 prop_object_iterator_t _it = prop_array_iterator(allowedips); 3866 prop_object_iterator_t _it = prop_array_iterator(allowedips);
3851 prop_dictionary_t prop_allowedip; 3867 prop_dictionary_t prop_allowedip;
3852 int j = 0; 3868 int j = 0;
3853 while ((prop_allowedip = prop_object_iterator_next(_it)) != NULL) { 3869 while ((prop_allowedip = prop_object_iterator_next(_it)) != NULL) {
3854 struct wg_allowedip *wga = &wgp->wgp_allowedips[j]; 3870 struct wg_allowedip *wga = &wgp->wgp_allowedips[j];
3855 3871
3856 if (!prop_dictionary_get_int(prop_allowedip, "family", 3872 if (!prop_dictionary_get_int(prop_allowedip, "family",
3857 &wga->wga_family)) 3873 &wga->wga_family))
3858 continue; 3874 continue;
3859 if (!prop_dictionary_get_data(prop_allowedip, "ip", 3875 if (!prop_dictionary_get_data(prop_allowedip, "ip",
3860 &addr, &addr_len)) 3876 &addr, &addr_len))
3861 continue; 3877 continue;
3862 if (!prop_dictionary_get_uint8(prop_allowedip, "cidr", 3878 if (!prop_dictionary_get_uint8(prop_allowedip, "cidr",
3863 &wga->wga_cidr)) 3879 &wga->wga_cidr))
3864 continue; 3880 continue;
3865 3881
3866 switch (wga->wga_family) { 3882 switch (wga->wga_family) {
3867 case AF_INET: { 3883 case AF_INET: {
3868 struct sockaddr_in sin; 3884 struct sockaddr_in sin;
3869 char addrstr[128]; 3885 char addrstr[128];
3870 struct in_addr mask; 3886 struct in_addr mask;
3871 struct sockaddr_in sin_mask; 3887 struct sockaddr_in sin_mask;
3872 3888
3873 if (addr_len != sizeof(struct in_addr)) 3889 if (addr_len != sizeof(struct in_addr))
3874 return EINVAL; 3890 return EINVAL;
3875 memcpy(&wga->wga_addr4, addr, addr_len); 3891 memcpy(&wga->wga_addr4, addr, addr_len);
3876 3892
3877 sockaddr_in_init(&sin, (const struct in_addr *)addr, 3893 sockaddr_in_init(&sin, (const struct in_addr *)addr,
3878 0); 3894 0);
3879 sockaddr_copy(&wga->wga_sa_addr, 3895 sockaddr_copy(&wga->wga_sa_addr,
3880 sizeof(sin), sintosa(&sin)); 3896 sizeof(sin), sintosa(&sin));
3881 3897
3882 sockaddr_format(sintosa(&sin), 3898 sockaddr_format(sintosa(&sin),
3883 addrstr, sizeof(addrstr)); 3899 addrstr, sizeof(addrstr));
3884 WG_DLOG("addr=%s/%d\n", addrstr, wga->wga_cidr); 3900 WG_DLOG("addr=%s/%d\n", addrstr, wga->wga_cidr);
3885 3901
3886 in_len2mask(&mask, wga->wga_cidr); 3902 in_len2mask(&mask, wga->wga_cidr);
3887 sockaddr_in_init(&sin_mask, &mask, 0); 3903 sockaddr_in_init(&sin_mask, &mask, 0);
3888 sockaddr_copy(&wga->wga_sa_mask, 3904 sockaddr_copy(&wga->wga_sa_mask,
3889 sizeof(sin_mask), sintosa(&sin_mask)); 3905 sizeof(sin_mask), sintosa(&sin_mask));
3890 3906
3891 break; 3907 break;
3892 } 3908 }
3893#ifdef INET6 3909#ifdef INET6
3894 case AF_INET6: { 3910 case AF_INET6: {
3895 struct sockaddr_in6 sin6; 3911 struct sockaddr_in6 sin6;
3896 char addrstr[128]; 3912 char addrstr[128];
3897 struct in6_addr mask; 3913 struct in6_addr mask;
3898 struct sockaddr_in6 sin6_mask; 3914 struct sockaddr_in6 sin6_mask;
3899 3915
3900 if (addr_len != sizeof(struct in6_addr)) 3916 if (addr_len != sizeof(struct in6_addr))
3901 return EINVAL; 3917 return EINVAL;
3902 memcpy(&wga->wga_addr6, addr, addr_len); 3918 memcpy(&wga->wga_addr6, addr, addr_len);
3903 3919
3904 sockaddr_in6_init(&sin6, (const struct in6_addr *)addr, 3920 sockaddr_in6_init(&sin6, (const struct in6_addr *)addr,
3905 0, 0, 0); 3921 0, 0, 0);
3906 sockaddr_copy(&wga->wga_sa_addr, 3922 sockaddr_copy(&wga->wga_sa_addr,
3907 sizeof(sin6), sin6tosa(&sin6)); 3923 sizeof(sin6), sin6tosa(&sin6));
3908 3924
3909 sockaddr_format(sin6tosa(&sin6), 3925 sockaddr_format(sin6tosa(&sin6),
3910 addrstr, sizeof(addrstr)); 3926 addrstr, sizeof(addrstr));
3911 WG_DLOG("addr=%s/%d\n", addrstr, wga->wga_cidr); 3927 WG_DLOG("addr=%s/%d\n", addrstr, wga->wga_cidr);
3912 3928
3913 in6_prefixlen2mask(&mask, wga->wga_cidr); 3929 in6_prefixlen2mask(&mask, wga->wga_cidr);
3914 sockaddr_in6_init(&sin6_mask, &mask, 0, 0, 0); 3930 sockaddr_in6_init(&sin6_mask, &mask, 0, 0, 0);
3915 sockaddr_copy(&wga->wga_sa_mask, 3931 sockaddr_copy(&wga->wga_sa_mask,
3916 sizeof(sin6_mask), sin6tosa(&sin6_mask)); 3932 sizeof(sin6_mask), sin6tosa(&sin6_mask));
3917 3933
3918 break; 3934 break;
3919 } 3935 }

cvs diff -r1.2 -r1.3 src/tests/net/if_wg/t_misc.sh (switch to unified diff)

--- src/tests/net/if_wg/t_misc.sh 2020/08/27 02:51:49 1.2
+++ src/tests/net/if_wg/t_misc.sh 2020/08/27 02:52:33 1.3
@@ -1,600 +1,673 @@ @@ -1,600 +1,673 @@
1# $NetBSD: t_misc.sh,v 1.2 2020/08/27 02:51:49 riastradh Exp $ 1# $NetBSD: t_misc.sh,v 1.3 2020/08/27 02:52:33 riastradh Exp $
2# 2#
3# Copyright (c) 2018 Ryota Ozaki <ozaki.ryota@gmail.com> 3# Copyright (c) 2018 Ryota Ozaki <ozaki.ryota@gmail.com>
4# All rights reserved. 4# All rights reserved.
5# 5#
6# Redistribution and use in source and binary forms, with or without 6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions 7# modification, are permitted provided that the following conditions
8# are met: 8# are met:
9# 1. Redistributions of source code must retain the above copyright 9# 1. Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer. 10# notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright 11# 2. Redistributions in binary form must reproduce the above copyright
12# notice, this list of conditions and the following disclaimer in the 12# notice, this list of conditions and the following disclaimer in the
13# documentation and/or other materials provided with the distribution. 13# documentation and/or other materials provided with the distribution.
14# 14#
15# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 15# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
16# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 16# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 18# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
19# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25# POSSIBILITY OF SUCH DAMAGE. 25# POSSIBILITY OF SUCH DAMAGE.
26# 26#
27 27
28BUS=bus 28BUS=bus
29SOCK_LOCAL=unix://wg_local 29SOCK_LOCAL=unix://wg_local
30SOCK_PEER=unix://wg_peer 30SOCK_PEER=unix://wg_peer
31 31
32 32
33atf_test_case wg_rekey cleanup 33atf_test_case wg_rekey cleanup
34wg_rekey_head() 34wg_rekey_head()
35{ 35{
36 36
37 atf_set "descr" "tests of rekeying of wg(4)" 37 atf_set "descr" "tests of rekeying of wg(4)"
38 atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen" 38 atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
39} 39}
40 40
41wg_rekey_body() 41wg_rekey_body()
42{ 42{
43 local ifconfig="atf_check -s exit:0 rump.ifconfig" 43 local ifconfig="atf_check -s exit:0 rump.ifconfig"
44 local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 1 -w 1" 44 local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 1 -w 1"
45 local ip_local=192.168.1.1 45 local ip_local=192.168.1.1
46 local ip_peer=192.168.1.2 46 local ip_peer=192.168.1.2
47 local ip_wg_local=10.0.0.1 47 local ip_wg_local=10.0.0.1
48 local ip_wg_peer=10.0.0.2 48 local ip_wg_peer=10.0.0.2
49 local port=51820 49 local port=51820
50 local rekey_after_time=3 50 local rekey_after_time=3
51 local latest_handshake= 51 local latest_handshake=
52 52
53 setup_servers 53 setup_servers
54 54
55 export RUMP_SERVER=$SOCK_LOCAL 55 export RUMP_SERVER=$SOCK_LOCAL
56 atf_check -s exit:0 -o ignore \ 56 atf_check -s exit:0 -o ignore \
57 rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time 57 rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time
58 export RUMP_SERVER=$SOCK_PEER 58 export RUMP_SERVER=$SOCK_PEER
59 atf_check -s exit:0 -o ignore \ 59 atf_check -s exit:0 -o ignore \
60 rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time 60 rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time
61 61
62 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer 62 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
63 generate_keys 63 generate_keys
64 64
65 export RUMP_SERVER=$SOCK_LOCAL 65 export RUMP_SERVER=$SOCK_LOCAL
66 setup_common shmif0 inet $ip_local 24 66 setup_common shmif0 inet $ip_local 24
67 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" 67 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
68 68
69 export RUMP_SERVER=$SOCK_PEER 69 export RUMP_SERVER=$SOCK_PEER
70 setup_common shmif0 inet $ip_peer 24 70 setup_common shmif0 inet $ip_peer 24
71 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" 71 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
72 72
73 export RUMP_SERVER=$SOCK_LOCAL 73 export RUMP_SERVER=$SOCK_LOCAL
74 add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 74 add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
75 75
76 export RUMP_SERVER=$SOCK_PEER 76 export RUMP_SERVER=$SOCK_PEER
77 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 77 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
78 78
79 export RUMP_SERVER=$SOCK_LOCAL 79 export RUMP_SERVER=$SOCK_LOCAL
80 80
81 $ping $ip_wg_peer 81 $ping $ip_wg_peer
82 82
83 latest_handshake=$($HIJACKING wgconfig wg0 show peer peer0 \ 83 latest_handshake=$($HIJACKING wgconfig wg0 show peer peer0 \
84 | awk -F : '/latest-handshake/ {print $2;}') 84 | awk -F : '/latest-handshake/ {print $2;}')
85 $DEBUG && echo $latest_handshake 85 $DEBUG && echo $latest_handshake
86 86
87 sleep 1 87 sleep 1
88 88
89 $ping $ip_wg_peer 89 $ping $ip_wg_peer
90 90
91 # No reinitiation is performed 91 # No reinitiation is performed
92 atf_check -s exit:0 -o match:"$latest_handshake" \ 92 atf_check -s exit:0 -o match:"$latest_handshake" \
93 $HIJACKING wgconfig wg0 show peer peer0 93 $HIJACKING wgconfig wg0 show peer peer0
94 94
95 # Wait for a reinitiation to be performed 95 # Wait for a reinitiation to be performed
96 sleep $rekey_after_time 96 sleep $rekey_after_time
97 97
98 $ping $ip_wg_peer 98 $ping $ip_wg_peer
99 99
100 # A reinitiation should be performed 100 # A reinitiation should be performed
101 atf_check -s exit:0 -o not-match:"$latest_handshake" \ 101 atf_check -s exit:0 -o not-match:"$latest_handshake" \
102 $HIJACKING wgconfig wg0 show peer peer0 102 $HIJACKING wgconfig wg0 show peer peer0
103 103
104 latest_handshake=$($HIJACKING wgconfig wg0 show peer peer0 \ 104 latest_handshake=$($HIJACKING wgconfig wg0 show peer peer0 \
105 | awk -F : '/latest-handshake/ {print $2;}') 105 | awk -F : '/latest-handshake/ {print $2;}')
106 $DEBUG && echo $latest_handshake 106 $DEBUG && echo $latest_handshake
107 107
108 # Wait for a reinitiation to be performed again 108 # Wait for a reinitiation to be performed again
109 sleep $rekey_after_time 109 sleep $rekey_after_time
110 110
111 $ping $ip_wg_peer 111 $ping $ip_wg_peer
112 112
113 # A reinitiation should be performed 113 # A reinitiation should be performed
114 atf_check -s exit:0 -o not-match:"$latest_handshake" \ 114 atf_check -s exit:0 -o not-match:"$latest_handshake" \
115 $HIJACKING wgconfig wg0 show peer peer0 115 $HIJACKING wgconfig wg0 show peer peer0
116 116
117 destroy_wg_interfaces 117 destroy_wg_interfaces
118} 118}
119 119
120wg_rekey_cleanup() 120wg_rekey_cleanup()
121{ 121{
122 122
123 $DEBUG && dump 123 $DEBUG && dump
124 cleanup 124 cleanup
125} 125}
126 126
127atf_test_case wg_handshake_timeout cleanup 127atf_test_case wg_handshake_timeout cleanup
128wg_handshake_timeout_head() 128wg_handshake_timeout_head()
129{ 129{
130 130
131 atf_set "descr" "tests of handshake timeout of wg(4)" 131 atf_set "descr" "tests of handshake timeout of wg(4)"
132 atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen" 132 atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
133} 133}
134 134
135wg_handshake_timeout_body() 135wg_handshake_timeout_body()
136{ 136{
137 local ifconfig="atf_check -s exit:0 rump.ifconfig" 137 local ifconfig="atf_check -s exit:0 rump.ifconfig"
138 local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 1 -w 1" 138 local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 1 -w 1"
139 local ip_local=192.168.1.1 139 local ip_local=192.168.1.1
140 local ip_peer=192.168.1.2 140 local ip_peer=192.168.1.2
141 local ip_wg_local=10.0.0.1 141 local ip_wg_local=10.0.0.1
142 local ip_wg_peer=10.0.0.2 142 local ip_wg_peer=10.0.0.2
143 local port=51820 143 local port=51820
144 local rekey_after_time=3 144 local rekey_after_time=3
145 local latest_handshake= 145 local latest_handshake=
146 local outfile=./out 146 local outfile=./out
147 local rekey_timeout=3 147 local rekey_timeout=3
148 local rekey_attempt_time=8 148 local rekey_attempt_time=8
149 local n= 149 local n=
150 150
151 setup_servers 151 setup_servers
152 152
153 export RUMP_SERVER=$SOCK_LOCAL 153 export RUMP_SERVER=$SOCK_LOCAL
154 atf_check -s exit:0 -o ignore \ 154 atf_check -s exit:0 -o ignore \
155 rump.sysctl -w net.wg.rekey_timeout=$rekey_timeout 155 rump.sysctl -w net.wg.rekey_timeout=$rekey_timeout
156 atf_check -s exit:0 -o ignore \ 156 atf_check -s exit:0 -o ignore \
157 rump.sysctl -w net.wg.rekey_attempt_time=$rekey_attempt_time 157 rump.sysctl -w net.wg.rekey_attempt_time=$rekey_attempt_time
158 export RUMP_SERVER=$SOCK_PEER 158 export RUMP_SERVER=$SOCK_PEER
159 atf_check -s exit:0 -o ignore \ 159 atf_check -s exit:0 -o ignore \
160 rump.sysctl -w net.wg.rekey_timeout=$rekey_timeout 160 rump.sysctl -w net.wg.rekey_timeout=$rekey_timeout
161 atf_check -s exit:0 -o ignore \ 161 atf_check -s exit:0 -o ignore \
162 rump.sysctl -w net.wg.rekey_attempt_time=$rekey_attempt_time 162 rump.sysctl -w net.wg.rekey_attempt_time=$rekey_attempt_time
163 163
164 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer 164 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
165 generate_keys 165 generate_keys
166 166
167 export RUMP_SERVER=$SOCK_LOCAL 167 export RUMP_SERVER=$SOCK_LOCAL
168 setup_common shmif0 inet $ip_local 24 168 setup_common shmif0 inet $ip_local 24
169 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" 169 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
170 170
171 export RUMP_SERVER=$SOCK_PEER 171 export RUMP_SERVER=$SOCK_PEER
172 setup_common shmif0 inet $ip_peer 24 172 setup_common shmif0 inet $ip_peer 24
173 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" 173 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
174 174
175 export RUMP_SERVER=$SOCK_LOCAL 175 export RUMP_SERVER=$SOCK_LOCAL
176 add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 176 add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
177 177
178 export RUMP_SERVER=$SOCK_PEER 178 export RUMP_SERVER=$SOCK_PEER
179 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 179 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
180 180
181 # Resolve arp 181 # Resolve arp
182 export RUMP_SERVER=$SOCK_LOCAL 182 export RUMP_SERVER=$SOCK_LOCAL
183 $ping $ip_peer 183 $ping $ip_peer
184 184
185 export RUMP_SERVER=$SOCK_PEER 185 export RUMP_SERVER=$SOCK_PEER
186 $ifconfig shmif0 down 186 $ifconfig shmif0 down
187 export RUMP_SERVER=$SOCK_LOCAL 187 export RUMP_SERVER=$SOCK_LOCAL
188 188
189 extract_new_packets $BUS > $outfile 189 extract_new_packets $BUS > $outfile
190 190
191 # Should fail 191 # Should fail
192 atf_check -s not-exit:0 -o match:'100.0% packet loss' \ 192 atf_check -s not-exit:0 -o match:'100.0% packet loss' \
193 rump.ping -n -c 1 -w 1 $ip_wg_peer 193 rump.ping -n -c 1 -w 1 $ip_wg_peer
194 194
195 sleep $((rekey_attempt_time + rekey_timeout)) 195 sleep $((rekey_attempt_time + rekey_timeout))
196 196
197 extract_new_packets $BUS > $outfile 197 extract_new_packets $BUS > $outfile
198 $DEBUG && cat $outfile 198 $DEBUG && cat $outfile
199 199
200 n=$(grep "$ip_local.$port > $ip_peer.$port" $outfile |wc -l) 200 n=$(grep "$ip_local.$port > $ip_peer.$port" $outfile |wc -l)
201 201
202 # Give up handshaking after three attempts 202 # Give up handshaking after three attempts
203 atf_check_equal $n 3 203 atf_check_equal $n 3
204 204
205 export RUMP_SERVER=$SOCK_PEER 205 export RUMP_SERVER=$SOCK_PEER
206 $ifconfig shmif0 up 206 $ifconfig shmif0 up
207 export RUMP_SERVER=$SOCK_LOCAL 207 export RUMP_SERVER=$SOCK_LOCAL
208 208
209 destroy_wg_interfaces 209 destroy_wg_interfaces
210} 210}
211 211
212wg_handshake_timeout_cleanup() 212wg_handshake_timeout_cleanup()
213{ 213{
214 214
215 $DEBUG && dump 215 $DEBUG && dump
216 cleanup 216 cleanup
217} 217}
218 218
219atf_test_case wg_cookie cleanup 219atf_test_case wg_cookie cleanup
220wg_cookie_head() 220wg_cookie_head()
221{ 221{
222 222
223 atf_set "descr" "tests of cookie messages of the wg(4) protocol" 223 atf_set "descr" "tests of cookie messages of the wg(4) protocol"
224 atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen" 224 atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
225} 225}
226 226
227wg_cookie_body() 227wg_cookie_body()
228{ 228{
229 local ifconfig="atf_check -s exit:0 rump.ifconfig" 229 local ifconfig="atf_check -s exit:0 rump.ifconfig"
230 local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1" 230 local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1"
231 local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1" 231 local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1"
232 local ip_local=192.168.1.1 232 local ip_local=192.168.1.1
233 local ip_peer=192.168.1.2 233 local ip_peer=192.168.1.2
234 local ip_wg_local=10.0.0.1 234 local ip_wg_local=10.0.0.1
235 local ip_wg_peer=10.0.0.2 235 local ip_wg_peer=10.0.0.2
236 local port=51820 236 local port=51820
237 local outfile=./out 237 local outfile=./out
238 local rekey_timeout=5 238 local rekey_timeout=5
239 239
240 setup_servers 240 setup_servers
241 241
242 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer 242 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
243 generate_keys 243 generate_keys
244 244
245 export RUMP_SERVER=$SOCK_LOCAL 245 export RUMP_SERVER=$SOCK_LOCAL
246 setup_common shmif0 inet $ip_local 24 246 setup_common shmif0 inet $ip_local 24
247 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" 247 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
248 248
249 export RUMP_SERVER=$SOCK_PEER 249 export RUMP_SERVER=$SOCK_PEER
250 setup_common shmif0 inet $ip_peer 24 250 setup_common shmif0 inet $ip_peer 24
251 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" 251 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
252 252
253 export RUMP_SERVER=$SOCK_LOCAL 253 export RUMP_SERVER=$SOCK_LOCAL
254 add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 254 add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
255 255
256 export RUMP_SERVER=$SOCK_PEER 256 export RUMP_SERVER=$SOCK_PEER
257 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 257 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
258 258
259 export RUMP_SERVER=$SOCK_PEER 259 export RUMP_SERVER=$SOCK_PEER
260 # Emulate load on the peer 260 # Emulate load on the peer
261 atf_check -s exit:0 -o ignore \ 261 atf_check -s exit:0 -o ignore \
262 rump.sysctl -w net.wg.force_underload=1 262 rump.sysctl -w net.wg.force_underload=1
263 263
264 export RUMP_SERVER=$SOCK_LOCAL 264 export RUMP_SERVER=$SOCK_LOCAL
265 265
266 extract_new_packets $BUS > $outfile 266 extract_new_packets $BUS > $outfile
267 $DEBUG && cat $outfile 267 $DEBUG && cat $outfile
268 268
269 # The peer doesn't return a response message but a cookie message 269 # The peer doesn't return a response message but a cookie message
270 # and a session doesn't start 270 # and a session doesn't start
271 $ping_fail $ip_wg_peer 271 $ping_fail $ip_wg_peer
272 272
273 extract_new_packets $BUS > $outfile 273 extract_new_packets $BUS > $outfile
274 $DEBUG && cat $outfile 274 $DEBUG && cat $outfile
275 # XXX length 64 indicates the message is a cookie message 275 # XXX length 64 indicates the message is a cookie message
276 atf_check -s exit:0 \ 276 atf_check -s exit:0 \
277 -o match:"$ip_peer.$port > $ip_local.$port: UDP, length 64" \ 277 -o match:"$ip_peer.$port > $ip_local.$port: UDP, length 64" \
278 cat $outfile 278 cat $outfile
279 279
280 $DEBUG && $HIJACKING wgconfig wg0 show all 280 $DEBUG && $HIJACKING wgconfig wg0 show all
281 atf_check -s exit:0 -o match:"latest-handshake: 0" \ 281 atf_check -s exit:0 -o match:"latest-handshake: 0" \
282 $HIJACKING wgconfig wg0 282 $HIJACKING wgconfig wg0
283 283
284 # Wait for restarting a session 284 # Wait for restarting a session
285 sleep $rekey_timeout 285 sleep $rekey_timeout
286 286
287 # The second attempt should be success because the init message has 287 # The second attempt should be success because the init message has
288 # a valid cookie. 288 # a valid cookie.
289 $ping $ip_wg_peer 289 $ping $ip_wg_peer
290 290
291 $DEBUG && $HIJACKING wgconfig wg0 show all 291 $DEBUG && $HIJACKING wgconfig wg0 show all
292 atf_check -s exit:0 -o not-match:"latest-handshake: 0" \ 292 atf_check -s exit:0 -o not-match:"latest-handshake: 0" \
293 $HIJACKING wgconfig wg0 293 $HIJACKING wgconfig wg0
294 294
295 destroy_wg_interfaces 295 destroy_wg_interfaces
296} 296}
297 297
298wg_cookie_cleanup() 298wg_cookie_cleanup()
299{ 299{
300 300
301 $DEBUG && dump 301 $DEBUG && dump
302 cleanup 302 cleanup
303} 303}
304 304
305atf_test_case wg_mobility cleanup 305atf_test_case wg_mobility cleanup
306wg_mobility_head() 306wg_mobility_head()
307{ 307{
308 308
309 atf_set "descr" "tests of the mobility of wg(4)" 309 atf_set "descr" "tests of the mobility of wg(4)"
310 atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen" 310 atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
311} 311}
312 312
313wg_mobility_body() 313wg_mobility_body()
314{ 314{
315 local ifconfig="atf_check -s exit:0 rump.ifconfig" 315 local ifconfig="atf_check -s exit:0 rump.ifconfig"
316 local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1" 316 local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1"
317 local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1" 317 local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1"
318 local ip_local=192.168.1.1 318 local ip_local=192.168.1.1
319 local ip_peer=192.168.1.2 319 local ip_peer=192.168.1.2
320 local ip_peer_new=192.168.1.3 320 local ip_peer_new=192.168.1.3
321 local ip_wg_local=10.0.0.1 321 local ip_wg_local=10.0.0.1
322 local ip_wg_peer=10.0.0.2 322 local ip_wg_peer=10.0.0.2
323 local port=51820 323 local port=51820
324 local outfile=./out 324 local outfile=./out
325 325
326 setup_servers 326 setup_servers
327 327
328 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer 328 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
329 generate_keys 329 generate_keys
330 330
331 export RUMP_SERVER=$SOCK_LOCAL 331 export RUMP_SERVER=$SOCK_LOCAL
332 setup_common shmif0 inet $ip_local 24 332 setup_common shmif0 inet $ip_local 24
333 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" 333 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
334 334
335 export RUMP_SERVER=$SOCK_PEER 335 export RUMP_SERVER=$SOCK_PEER
336 setup_common shmif0 inet $ip_peer 24 336 setup_common shmif0 inet $ip_peer 24
337 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" 337 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
338 338
339 export RUMP_SERVER=$SOCK_LOCAL 339 export RUMP_SERVER=$SOCK_LOCAL
340 # Initially, the local doesn't know the endpoint of the peer 340 # Initially, the local doesn't know the endpoint of the peer
341 add_peer wg0 peer0 $key_pub_peer "" $ip_wg_peer/32 341 add_peer wg0 peer0 $key_pub_peer "" $ip_wg_peer/32
342 342
343 export RUMP_SERVER=$SOCK_PEER 343 export RUMP_SERVER=$SOCK_PEER
344 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 344 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
345 345
346 extract_new_packets $BUS > $outfile 346 extract_new_packets $BUS > $outfile
347 $DEBUG && cat $outfile 347 $DEBUG && cat $outfile
348 348
349 # Ping from the local to the peer doesn't work because the local 349 # Ping from the local to the peer doesn't work because the local
350 # doesn't know the endpoint of the peer 350 # doesn't know the endpoint of the peer
351 export RUMP_SERVER=$SOCK_LOCAL 351 export RUMP_SERVER=$SOCK_LOCAL
352 $ping_fail $ip_wg_peer 352 $ping_fail $ip_wg_peer
353 353
354 extract_new_packets $BUS > $outfile 354 extract_new_packets $BUS > $outfile
355 $DEBUG && cat $outfile 355 $DEBUG && cat $outfile
356 356
357 export RUMP_SERVER=$SOCK_PEER 357 export RUMP_SERVER=$SOCK_PEER
358 $ping $ip_wg_local 358 $ping $ip_wg_local
359 359
360 extract_new_packets $BUS > $outfile 360 extract_new_packets $BUS > $outfile
361 $DEBUG && cat $outfile 361 $DEBUG && cat $outfile
362 362
363 atf_check -s exit:0 -o match:"$ip_local.$port > $ip_peer.$port" cat $outfile 363 atf_check -s exit:0 -o match:"$ip_local.$port > $ip_peer.$port" cat $outfile
364 364
365 # Change the IP address of the peer 365 # Change the IP address of the peer
366 setup_common shmif0 inet $ip_peer_new 24 366 setup_common shmif0 inet $ip_peer_new 24
367 atf_check -s exit:0 rump.ifconfig -w 10 367 atf_check -s exit:0 rump.ifconfig -w 10
368 368
369 # Ping from the local to the peer doesn't work because the local 369 # Ping from the local to the peer doesn't work because the local
370 # doesn't know the change of the IP address of the peer 370 # doesn't know the change of the IP address of the peer
371 export RUMP_SERVER=$SOCK_LOCAL 371 export RUMP_SERVER=$SOCK_LOCAL
372 $ping_fail $ip_wg_peer 372 $ping_fail $ip_wg_peer
373 373
374 extract_new_packets $BUS > $outfile 374 extract_new_packets $BUS > $outfile
375 $DEBUG && cat $outfile 375 $DEBUG && cat $outfile
376 376
377 atf_check -s exit:0 -o match:"$ip_local.$port > $ip_peer.$port" cat $outfile 377 atf_check -s exit:0 -o match:"$ip_local.$port > $ip_peer.$port" cat $outfile
378 378
379 # Ping from the peer to the local works because the local notices 379 # Ping from the peer to the local works because the local notices
380 # the change and updates the IP address of the peer 380 # the change and updates the IP address of the peer
381 export RUMP_SERVER=$SOCK_PEER 381 export RUMP_SERVER=$SOCK_PEER
382 $ping $ip_wg_local 382 $ping $ip_wg_local
383 383
384 extract_new_packets $BUS > $outfile 384 extract_new_packets $BUS > $outfile
385 $DEBUG && cat $outfile 385 $DEBUG && cat $outfile
386 386
387 atf_check -s exit:0 -o match:"$ip_local.$port > $ip_peer_new.$port" cat $outfile 387 atf_check -s exit:0 -o match:"$ip_local.$port > $ip_peer_new.$port" cat $outfile
388 atf_check -s exit:0 -o match:"$ip_peer_new.$port > $ip_local.$port" cat $outfile 388 atf_check -s exit:0 -o match:"$ip_peer_new.$port > $ip_local.$port" cat $outfile
389 atf_check -s exit:0 -o not-match:"$ip_local.$port > $ip_peer.$port" cat $outfile 389 atf_check -s exit:0 -o not-match:"$ip_local.$port > $ip_peer.$port" cat $outfile
390 390
391 destroy_wg_interfaces 391 destroy_wg_interfaces
392} 392}
393 393
394wg_mobility_cleanup() 394wg_mobility_cleanup()
395{ 395{
396 396
397 $DEBUG && dump 397 $DEBUG && dump
398 cleanup 398 cleanup
399} 399}
400 400
401atf_test_case wg_keepalive cleanup 401atf_test_case wg_keepalive cleanup
402wg_keepalive_head() 402wg_keepalive_head()
403{ 403{
404 404
405 atf_set "descr" "tests keepalive messages" 405 atf_set "descr" "tests keepalive messages"
406 atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen" 406 atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
407} 407}
408 408
409wg_keepalive_body() 409wg_keepalive_body()
410{ 410{
411 local ifconfig="atf_check -s exit:0 rump.ifconfig" 411 local ifconfig="atf_check -s exit:0 rump.ifconfig"
412 local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1" 412 local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1"
413 local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1" 413 local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1"
414 local ip_local=192.168.1.1 414 local ip_local=192.168.1.1
415 local ip_peer=192.168.1.2 415 local ip_peer=192.168.1.2
416 local ip_peer_new=192.168.1.3 416 local ip_peer_new=192.168.1.3
417 local ip_wg_local=10.0.0.1 417 local ip_wg_local=10.0.0.1
418 local ip_wg_peer=10.0.0.2 418 local ip_wg_peer=10.0.0.2
419 local port=51820 419 local port=51820
420 local outfile=./out 420 local outfile=./out
421 local keepalive_timeout=3 421 local keepalive_timeout=3
422 422
423 setup_servers 423 setup_servers
424 424
425 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer 425 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
426 generate_keys 426 generate_keys
427 427
428 export RUMP_SERVER=$SOCK_LOCAL 428 export RUMP_SERVER=$SOCK_LOCAL
429 setup_common shmif0 inet $ip_local 24 429 setup_common shmif0 inet $ip_local 24
430 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" 430 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
431 431
432 export RUMP_SERVER=$SOCK_PEER 432 export RUMP_SERVER=$SOCK_PEER
433 setup_common shmif0 inet $ip_peer 24 433 setup_common shmif0 inet $ip_peer 24
434 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" 434 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
435 435
436 export RUMP_SERVER=$SOCK_LOCAL 436 export RUMP_SERVER=$SOCK_LOCAL
437 add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 437 add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
438 438
439 export RUMP_SERVER=$SOCK_PEER 439 export RUMP_SERVER=$SOCK_PEER
440 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 440 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
441 441
442 # Shorten keepalive_timeout of the peer 442 # Shorten keepalive_timeout of the peer
443 atf_check -s exit:0 -o ignore \ 443 atf_check -s exit:0 -o ignore \
444 rump.sysctl -w net.wg.keepalive_timeout=$keepalive_timeout 444 rump.sysctl -w net.wg.keepalive_timeout=$keepalive_timeout
445 445
446 export RUMP_SERVER=$SOCK_LOCAL 446 export RUMP_SERVER=$SOCK_LOCAL
447 447
448 extract_new_packets $BUS > $outfile 448 extract_new_packets $BUS > $outfile
449 $DEBUG && cat $outfile 449 $DEBUG && cat $outfile
450 450
451 $ping $ip_wg_peer 451 $ping $ip_wg_peer
452 452
453 extract_new_packets $BUS > $outfile 453 extract_new_packets $BUS > $outfile
454 $DEBUG && cat $outfile 454 $DEBUG && cat $outfile
455 455
456 sleep $((keepalive_timeout + 1)) 456 sleep $((keepalive_timeout + 1))
457 457
458 $ping $ip_wg_peer 458 $ping $ip_wg_peer
459 459
460 extract_new_packets $BUS > $outfile 460 extract_new_packets $BUS > $outfile
461 $DEBUG && cat $outfile 461 $DEBUG && cat $outfile
462 462
463 # XXX length 32 indicates the message is a keepalive (empty) message 463 # XXX length 32 indicates the message is a keepalive (empty) message
464 atf_check -s exit:0 -o match:"$ip_peer.$port > $ip_local.$port: UDP, length 32" \ 464 atf_check -s exit:0 -o match:"$ip_peer.$port > $ip_local.$port: UDP, length 32" \
465 cat $outfile 465 cat $outfile
466 466
467 destroy_wg_interfaces 467 destroy_wg_interfaces
468} 468}
469 469
470wg_keepalive_cleanup() 470wg_keepalive_cleanup()
471{ 471{
472 472
473 $DEBUG && dump 473 $DEBUG && dump
474 cleanup 474 cleanup
475} 475}
476 476
477atf_test_case wg_psk cleanup 477atf_test_case wg_psk cleanup
478wg_psk_head() 478wg_psk_head()
479{ 479{
480 480
481 atf_set "descr" "tests preshared-key" 481 atf_set "descr" "tests preshared-key"
482 atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen" 482 atf_set "require.progs" "rump_server" "wgconfig" "wg-keygen"
483} 483}
484 484
485test_psk_common() 485test_psk_common()
486{ 486{
487} 487}
488 488
489wg_psk_body() 489wg_psk_body()
490{ 490{
491 local ifconfig="atf_check -s exit:0 rump.ifconfig" 491 local ifconfig="atf_check -s exit:0 rump.ifconfig"
492 local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1" 492 local ping="atf_check -s exit:0 -o ignore rump.ping -n -i 0.1 -c 3 -w 1"
493 local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1" 493 local ping_fail="atf_check -s not-exit:0 -o ignore rump.ping -n -c 1 -w 1"
494 local ip_local=192.168.1.1 494 local ip_local=192.168.1.1
495 local ip_peer=192.168.1.2 495 local ip_peer=192.168.1.2
496 local ip_peer_new=192.168.1.3 496 local ip_peer_new=192.168.1.3
497 local ip_wg_local=10.0.0.1 497 local ip_wg_local=10.0.0.1
498 local ip_wg_peer=10.0.0.2 498 local ip_wg_peer=10.0.0.2
499 local port=51820 499 local port=51820
500 local outfile=./out 500 local outfile=./out
501 local pskfile=./psk 501 local pskfile=./psk
502 local rekey_after_time=3 502 local rekey_after_time=3
503 503
504 setup_servers 504 setup_servers
505 505
506 export RUMP_SERVER=$SOCK_LOCAL 506 export RUMP_SERVER=$SOCK_LOCAL
507 atf_check -s exit:0 -o ignore \ 507 atf_check -s exit:0 -o ignore \
508 rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time 508 rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time
509 export RUMP_SERVER=$SOCK_PEER 509 export RUMP_SERVER=$SOCK_PEER
510 atf_check -s exit:0 -o ignore \ 510 atf_check -s exit:0 -o ignore \
511 rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time 511 rump.sysctl -w net.wg.rekey_after_time=$rekey_after_time
512 512
513 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer 513 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
514 generate_keys 514 generate_keys
515 key_psk=$(wg-keygen --psk) 515 key_psk=$(wg-keygen --psk)
516 $DEBUG && echo $key_psk 516 $DEBUG && echo $key_psk
517 517
518 export RUMP_SERVER=$SOCK_LOCAL 518 export RUMP_SERVER=$SOCK_LOCAL
519 setup_common shmif0 inet $ip_local 24 519 setup_common shmif0 inet $ip_local 24
520 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local" 520 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
521 521
522 export RUMP_SERVER=$SOCK_PEER 522 export RUMP_SERVER=$SOCK_PEER
523 setup_common shmif0 inet $ip_peer 24 523 setup_common shmif0 inet $ip_peer 24
524 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer" 524 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
525 525
526 echo "$key_psk" > $pskfile 526 echo "$key_psk" > $pskfile
527 527
528 export RUMP_SERVER=$SOCK_LOCAL 528 export RUMP_SERVER=$SOCK_LOCAL
529 529
530 # The local always has the preshared key 530 # The local always has the preshared key
531 add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 \ 531 add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32 \
532 $pskfile "$key_psk" 532 $pskfile "$key_psk"
533 533
534 export RUMP_SERVER=$SOCK_PEER 534 export RUMP_SERVER=$SOCK_PEER
535 535
536 # First, try the peer without the preshared key 536 # First, try the peer without the preshared key
537 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 537 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
538 538
539 export RUMP_SERVER=$SOCK_LOCAL 539 export RUMP_SERVER=$SOCK_LOCAL
540 540
541 extract_new_packets $BUS > $outfile 541 extract_new_packets $BUS > $outfile
542 $DEBUG && cat $outfile 542 $DEBUG && cat $outfile
543 543
544 $ping_fail $ip_wg_peer 544 $ping_fail $ip_wg_peer
545 545
546 extract_new_packets $BUS > $outfile 546 extract_new_packets $BUS > $outfile
547 $DEBUG && cat $outfile 547 $DEBUG && cat $outfile
548 548
549 # Next, try with the preshared key 549 # Next, try with the preshared key
550 export RUMP_SERVER=$SOCK_PEER 550 export RUMP_SERVER=$SOCK_PEER
551 delete_peer wg0 peer0 551 delete_peer wg0 peer0
552 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 \ 552 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 \
553 $pskfile "$key_psk" 553 $pskfile "$key_psk"
554 554
555 # Need a rekey 555 # Need a rekey
556 atf_check -s exit:0 sleep $((rekey_after_time + 1)) 556 atf_check -s exit:0 sleep $((rekey_after_time + 1))
557 557
558 export RUMP_SERVER=$SOCK_LOCAL 558 export RUMP_SERVER=$SOCK_LOCAL
559 559
560 extract_new_packets $BUS > $outfile 560 extract_new_packets $BUS > $outfile
561 $DEBUG && cat $outfile 561 $DEBUG && cat $outfile
562 562
563 $ping $ip_wg_peer 563 $ping $ip_wg_peer
564 564
565 extract_new_packets $BUS > $outfile 565 extract_new_packets $BUS > $outfile
566 $DEBUG && cat $outfile 566 $DEBUG && cat $outfile
567 567
568 # Then, try again without the preshared key just in case 568 # Then, try again without the preshared key just in case
569 export RUMP_SERVER=$SOCK_PEER 569 export RUMP_SERVER=$SOCK_PEER
570 delete_peer wg0 peer0 570 delete_peer wg0 peer0
571 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32 571 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
572 572
573 # Need a rekey 573 # Need a rekey
574 atf_check -s exit:0 sleep $((rekey_after_time + 1)) 574 atf_check -s exit:0 sleep $((rekey_after_time + 1))
575 575
576 export RUMP_SERVER=$SOCK_LOCAL 576 export RUMP_SERVER=$SOCK_LOCAL
577 $ping_fail $ip_wg_peer 577 $ping_fail $ip_wg_peer
578 578
579 rm -f $pskfile 579 rm -f $pskfile
580 580
581 destroy_wg_interfaces 581 destroy_wg_interfaces
582} 582}
583 583
584wg_psk_cleanup() 584wg_psk_cleanup()
585{ 585{
586 586
587 $DEBUG && dump 587 $DEBUG && dump
588 cleanup 588 cleanup
589} 589}
590 590
 591atf_test_case wg_malformed cleanup
 592wg_malformed_head()
 593{
 594
 595 atf_set "descr" "tests malformed packet headers"
 596 atf_set "require.progs" "nc" "rump_server" "wgconfig" "wg-keygen"
 597 atf_set "timeout" "10"
 598}
 599
 600wg_malformed_body()
 601{
 602 local ifconfig="atf_check -s exit:0 rump.ifconfig"
 603 local ping="atf_check -s exit:0 -o ignore rump.ping -n -c 1 -w 1"
 604 local ip_local=192.168.1.1
 605 local ip_peer=192.168.1.2
 606 local ip_wg_local=10.0.0.1
 607 local ip_wg_peer=10.0.0.2
 608 local port=51820
 609 setup_servers
 610
 611 # It sets key_priv_local key_pub_local key_priv_peer key_pub_peer
 612 generate_keys
 613
 614 export RUMP_SERVER=$SOCK_LOCAL
 615 setup_common shmif0 inet $ip_local 24
 616 setup_wg_common wg0 inet $ip_wg_local 24 $port "$key_priv_local"
 617
 618 export RUMP_SERVER=$SOCK_PEER
 619 setup_common shmif0 inet $ip_peer 24
 620 setup_wg_common wg0 inet $ip_wg_peer 24 $port "$key_priv_peer"
 621
 622 export RUMP_SERVER=$SOCK_LOCAL
 623 add_peer wg0 peer0 $key_pub_peer $ip_peer:$port $ip_wg_peer/32
 624
 625 export RUMP_SERVER=$SOCK_PEER
 626 add_peer wg0 peer0 $key_pub_local $ip_local:$port $ip_wg_local/32
 627
 628 export RUMP_SERVER=$SOCK_LOCAL
 629
 630 $ping $ip_wg_peer
 631
 632 printf 'send malformed packets\n'
 633
 634 $HIJACKING ping -c 1 -n $ip_peer
 635
 636 printf 'x' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 637 printf 'xy' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 638 printf 'xyz' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 639 printf 'xyzw' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 640 printf '\x00\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 641 printf '\x00\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 642 printf '\x01\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 643 printf '\x01\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 644 printf '\x02\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 645 printf '\x02\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 646 printf '\x03\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 647 printf '\x03\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 648 printf '\x04\x00\x00\x00' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 649 printf '\x04\x00\x00\x00z' | $HIJACKING nc -Nu -w 0 $ip_peer $port
 650
 651 printf 'done sending malformed packets\n'
 652
 653 $ping $ip_wg_peer
 654}
 655
 656wg_malformed_cleanup()
 657{
 658
 659 $DEBUG && dump
 660 cleanup
 661}
 662
591atf_init_test_cases() 663atf_init_test_cases()
592{ 664{
593 665
594 atf_add_test_case wg_rekey 666 atf_add_test_case wg_rekey
595 atf_add_test_case wg_handshake_timeout 667 atf_add_test_case wg_handshake_timeout
596 atf_add_test_case wg_cookie 668 atf_add_test_case wg_cookie
597 atf_add_test_case wg_mobility 669 atf_add_test_case wg_mobility
598 atf_add_test_case wg_keepalive 670 atf_add_test_case wg_keepalive
599 atf_add_test_case wg_psk 671 atf_add_test_case wg_psk
 672 atf_add_test_case wg_malformed
600} 673}