diff options
-rw-r--r-- | contrib/examples/nat-hole-punching/README | 4 | ||||
-rw-r--r-- | src/compat/compat.h | 8 | ||||
-rw-r--r-- | src/crypto/zinc/poly1305/poly1305-x86_64.pl | 2 | ||||
-rw-r--r-- | src/crypto/zinc/selftest/chacha20poly1305.c | 67 | ||||
-rw-r--r-- | src/dkms.conf | 2 | ||||
-rw-r--r-- | src/main.c | 1 | ||||
-rw-r--r-- | src/receive.c | 2 | ||||
-rw-r--r-- | src/socket.c | 7 | ||||
-rw-r--r-- | src/tools/man/wg.8 | 2 | ||||
-rw-r--r-- | src/tools/wg-quick/android.c | 4 | ||||
-rwxr-xr-x | src/tools/wg-quick/linux.bash | 78 | ||||
-rw-r--r-- | src/uapi/wireguard.h | 8 | ||||
-rw-r--r-- | src/version.h | 2 |
13 files changed, 131 insertions, 56 deletions
diff --git a/contrib/examples/nat-hole-punching/README b/contrib/examples/nat-hole-punching/README index 46e6201..99c20e5 100644 --- a/contrib/examples/nat-hole-punching/README +++ b/contrib/examples/nat-hole-punching/README @@ -9,8 +9,8 @@ Compile with: Server is 1.2.3.4 and is on the public internet accepting UDP:49918. -Client A is NAT'd and doesnt't know its IP address. -Client B is NAT'd and doesnt't know its IP address. +Client A is NAT'd and doesn't know its IP address. +Client B is NAT'd and doesn't know its IP address. Server runs: diff --git a/src/compat/compat.h b/src/compat/compat.h index ab22fa4..824f57c 100644 --- a/src/compat/compat.h +++ b/src/compat/compat.h @@ -326,7 +326,7 @@ static inline int wait_for_random_bytes(void) } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 19, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) && !defined(ISRHEL8) #include <linux/random.h> #include <linux/slab.h> struct rng_is_initialized_callback { @@ -831,7 +831,7 @@ static inline void skb_mark_not_on_list(struct sk_buff *skb) } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0) && !defined(ISRHEL8) #define NLA_EXACT_LEN NLA_UNSPEC #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 2, 0) @@ -861,6 +861,10 @@ static inline void skb_mark_not_on_list(struct sk_buff *skb) }) #endif +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 5) && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)) || LINUX_VERSION_CODE < KERNEL_VERSION(5, 3, 18) +#define ipv6_dst_lookup_flow(a, b, c, d) ipv6_dst_lookup(a, b, &dst, c) + (void *)0 ?: dst +#endif + #if defined(ISUBUNTU1604) #include <linux/siphash.h> #ifndef _WG_LINUX_SIPHASH_H diff --git a/src/crypto/zinc/poly1305/poly1305-x86_64.pl b/src/crypto/zinc/poly1305/poly1305-x86_64.pl index 94c3c42..f994855 100644 --- a/src/crypto/zinc/poly1305/poly1305-x86_64.pl +++ b/src/crypto/zinc/poly1305/poly1305-x86_64.pl @@ -35,7 +35,7 @@ # Skylake-X system performance. Since we are likely to suppress # AVX512F capability flag [at least on Skylake-X], conversion serves # as kind of "investment protection". Note that next *lake processor, -# Cannolake, has AVX512IFMA code path to execute... +# Cannonlake, has AVX512IFMA code path to execute... # # Numbers are cycles per processed byte with poly1305_blocks alone, # measured with rdtsc at fixed clock frequency. diff --git a/src/crypto/zinc/selftest/chacha20poly1305.c b/src/crypto/zinc/selftest/chacha20poly1305.c index d3b928d..c58ac6e 100644 --- a/src/crypto/zinc/selftest/chacha20poly1305.c +++ b/src/crypto/zinc/selftest/chacha20poly1305.c @@ -8879,14 +8879,15 @@ decryption_success(bool func_ret, bool expect_failure, int memcmp_result) static bool __init chacha20poly1305_selftest(void) { enum { MAXIMUM_TEST_BUFFER_LEN = 1UL << 12 }; - size_t i; - u8 *computed_output = NULL; + size_t i, j, k, total_len; + u8 *computed_output = NULL, *input = NULL; bool success = true, ret; simd_context_t simd_context; - struct scatterlist sg_src; + struct scatterlist sg_src[3]; computed_output = kmalloc(MAXIMUM_TEST_BUFFER_LEN, GFP_KERNEL); - if (!computed_output) { + input = kmalloc(MAXIMUM_TEST_BUFFER_LEN, GFP_KERNEL); + if (!computed_output || !input) { pr_err("chacha20poly1305 self-test malloc: FAIL\n"); success = false; goto out; @@ -8917,10 +8918,10 @@ static bool __init chacha20poly1305_selftest(void) continue; memcpy(computed_output, chacha20poly1305_enc_vectors[i].input, chacha20poly1305_enc_vectors[i].ilen); - sg_init_one(&sg_src, computed_output, + sg_init_one(sg_src, computed_output, chacha20poly1305_enc_vectors[i].ilen + POLY1305_MAC_SIZE); - ret = chacha20poly1305_encrypt_sg_inplace(&sg_src, + ret = chacha20poly1305_encrypt_sg_inplace(sg_src, chacha20poly1305_enc_vectors[i].ilen, chacha20poly1305_enc_vectors[i].assoc, chacha20poly1305_enc_vectors[i].alen, @@ -8961,9 +8962,9 @@ static bool __init chacha20poly1305_selftest(void) for (i = 0; i < ARRAY_SIZE(chacha20poly1305_dec_vectors); ++i) { memcpy(computed_output, chacha20poly1305_dec_vectors[i].input, chacha20poly1305_dec_vectors[i].ilen); - sg_init_one(&sg_src, computed_output, + sg_init_one(sg_src, computed_output, chacha20poly1305_dec_vectors[i].ilen); - ret = chacha20poly1305_decrypt_sg_inplace(&sg_src, + ret = chacha20poly1305_decrypt_sg_inplace(sg_src, chacha20poly1305_dec_vectors[i].ilen, chacha20poly1305_dec_vectors[i].assoc, chacha20poly1305_dec_vectors[i].alen, @@ -9019,7 +9020,57 @@ static bool __init chacha20poly1305_selftest(void) } } + simd_get(&simd_context); + for (total_len = POLY1305_MAC_SIZE; IS_ENABLED(DEBUG_CHACHA20POLY1305_SLOW_CHUNK_TEST) + && total_len <= 1 << 10; ++total_len) { + for (i = 0; i <= total_len; ++i) { + for (j = i; j <= total_len; ++j) { + sg_init_table(sg_src, 3); + sg_set_buf(&sg_src[0], input, i); + sg_set_buf(&sg_src[1], input + i, j - i); + sg_set_buf(&sg_src[2], input + j, total_len - j); + memset(computed_output, 0, total_len); + memset(input, 0, total_len); + + if (!chacha20poly1305_encrypt_sg_inplace(sg_src, + total_len - POLY1305_MAC_SIZE, NULL, 0, + 0, enc_key001, &simd_context)) + goto chunkfail; + chacha20poly1305_encrypt(computed_output, + computed_output, + total_len - POLY1305_MAC_SIZE, NULL, 0, 0, + enc_key001); + if (memcmp(computed_output, input, total_len)) + goto chunkfail;; + if (!chacha20poly1305_decrypt(computed_output, + input, total_len, NULL, 0, 0, enc_key001)) + goto chunkfail; + for (k = 0; k < total_len - POLY1305_MAC_SIZE; ++k) { + if (computed_output[k]) + goto chunkfail; + } + if (!chacha20poly1305_decrypt_sg_inplace(sg_src, + total_len, NULL, 0, 0, enc_key001, + &simd_context)) + goto chunkfail; + for (k = 0; k < total_len - POLY1305_MAC_SIZE; ++k) { + if (input[k]) + goto chunkfail; + } + continue; + + chunkfail: + pr_err("chacha20poly1305 chunked self-test %zu/%zu/%zu: FAIL\n", + total_len, i, j); + success = false; + } + + } + } + simd_put(&simd_context); + out: kfree(computed_output); + kfree(input); return success; } diff --git a/src/dkms.conf b/src/dkms.conf index 194f27b..cdcd2e7 100644 --- a/src/dkms.conf +++ b/src/dkms.conf @@ -1,5 +1,5 @@ PACKAGE_NAME="wireguard" -PACKAGE_VERSION="0.0.20191205" +PACKAGE_VERSION="0.0.20191219" AUTOINSTALL=yes BUILT_MODULE_NAME="wireguard" @@ -12,7 +12,6 @@ #include "uapi/wireguard.h" #include "crypto/zinc.h" -#include <linux/version.h> #include <linux/init.h> #include <linux/module.h> #include <linux/genetlink.h> diff --git a/src/receive.c b/src/receive.c index dfd6e40..e00f0f4 100644 --- a/src/receive.c +++ b/src/receive.c @@ -382,7 +382,7 @@ static void wg_packet_consume_data_done(struct wg_peer *peer, /* We've already verified the Poly1305 auth tag, which means this packet * was not modified in transit. We can therefore tell the networking * stack that all checksums of every layer of encapsulation have already - * been checked "by the hardware" and therefore is unneccessary to check + * been checked "by the hardware" and therefore is unnecessary to check * again in software. */ skb->ip_summed = CHECKSUM_UNNECESSARY; diff --git a/src/socket.c b/src/socket.c index a90dadd..c46256d 100644 --- a/src/socket.c +++ b/src/socket.c @@ -142,9 +142,10 @@ static int send6(struct wg_device *wg, struct sk_buff *skb, if (cache) dst_cache_reset(cache); } - ret = ipv6_stub->ipv6_dst_lookup(sock_net(sock), sock, &dst, - &fl); - if (unlikely(ret)) { + dst = ipv6_stub->ipv6_dst_lookup_flow(sock_net(sock), sock, &fl, + NULL); + if (unlikely(IS_ERR(dst))) { + ret = PTR_ERR(dst); net_dbg_ratelimited("%s: No route to %pISpfsc, error %d\n", wg->dev->name, &endpoint->addr, ret); goto err; diff --git a/src/tools/man/wg.8 b/src/tools/man/wg.8 index 043ffb0..ac281bc 100644 --- a/src/tools/man/wg.8 +++ b/src/tools/man/wg.8 @@ -122,7 +122,7 @@ A private key and a corresponding public key may be generated at once by calling $ wg genkey | tee private.key | wg pubkey > public.key .TP \fBhelp\fP -Show usage message. +Shows usage message. .SH CONFIGURATION FILE FORMAT The configuration file format is based on \fIINI\fP. There are two top level sections diff --git a/src/tools/wg-quick/android.c b/src/tools/wg-quick/android.c index 144d462..ad05895 100644 --- a/src/tools/wg-quick/android.c +++ b/src/tools/wg-quick/android.c @@ -390,10 +390,10 @@ static int32_t string_array_size(char *const *array) return size; } -static const char *string_array_getter(const void *array_data, size_t index, int32_t *outlength) +static const char *string_array_getter(const void *array_data, size_t index, int32_t *out_length) { const char **array = (const char **)array_data; - *outlength = array[index] ? strlen(array[index]) : -1; + *out_length = array[index] ? strlen(array[index]) : -1; return array[index]; } diff --git a/src/tools/wg-quick/linux.bash b/src/tools/wg-quick/linux.bash index fc90e55..e9c9052 100755 --- a/src/tools/wg-quick/linux.bash +++ b/src/tools/wg-quick/linux.bash @@ -95,18 +95,18 @@ add_if() { del_if() { local table [[ $HAVE_SET_DNS -eq 0 ]] || unset_dns - [[ $HAVE_SET_IPTABLES -eq 0 ]] || remove_iptables + [[ $HAVE_SET_FIREWALL -eq 0 ]] || remove_firewall if [[ -z $TABLE || $TABLE == auto ]] && get_fwmark table && [[ $(wg show "$INTERFACE" allowed-ips) =~ /0(\ |$'\n'|$) ]]; then - while [[ $(ip -4 rule show) == *"lookup $table"* ]]; do + while [[ $(ip -4 rule show 2>/dev/null) == *"lookup $table"* ]]; do cmd ip -4 rule delete table $table done - while [[ $(ip -4 rule show) == *"from all lookup main suppress_prefixlength 0"* ]]; do + while [[ $(ip -4 rule show 2>/dev/null) == *"from all lookup main suppress_prefixlength 0"* ]]; do cmd ip -4 rule delete table main suppress_prefixlength 0 done - while [[ $(ip -6 rule show) == *"lookup $table"* ]]; do + while [[ $(ip -6 rule show 2>/dev/null) == *"lookup $table"* ]]; do cmd ip -6 rule delete table $table done - while [[ $(ip -6 rule show) == *"from all lookup main suppress_prefixlength 0"* ]]; do + while [[ $(ip -6 rule show 2>/dev/null) == *"from all lookup main suppress_prefixlength 0"* ]]; do cmd ip -6 rule delete table main suppress_prefixlength 0 done fi @@ -181,22 +181,31 @@ get_fwmark() { return 0 } -remove_iptables() { - local line iptables found restore - for iptables in iptables ip6tables; do - restore="" found=0 - while read -r line; do - [[ $line == "*"* || $line == COMMIT || $line == "-A "*"-m comment --comment \"wg-quick(8) rule for $INTERFACE\""* ]] || continue - [[ $line == "-A"* ]] && found=1 - printf -v restore '%s\n%s' "$restore" "${line/#-A/-D}" - done < <($iptables-save) - [[ $found -ne 1 ]] || echo "$restore" | cmd $iptables-restore -n - done +remove_firewall() { + if type -p nft >/dev/null; then + local table nftcmd + while read -r table; do + [[ $table == *" wg-quick-$INTERFACE" ]] && printf -v nftcmd '%sdelete %s\n' "$nftcmd" "$table" + done < <(nft list tables 2>/dev/null) + [[ -z $nftcmd ]] || cmd nft -f <(echo -n "$nftcmd") + fi + if type -p iptables >/dev/null; then + local line iptables found restore + for iptables in iptables ip6tables; do + restore="" found=0 + while read -r line; do + [[ $line == "*"* || $line == COMMIT || $line == "-A "*"-m comment --comment \"wg-quick(8) rule for $INTERFACE\""* ]] || continue + [[ $line == "-A"* ]] && found=1 + printf -v restore '%s%s\n' "$restore" "${line/#-A/-D}" + done < <($iptables-save 2>/dev/null) + [[ $found -ne 1 ]] || echo -n "$restore" | cmd $iptables-restore -n + done + fi } -HAVE_SET_IPTABLES=0 +HAVE_SET_FIREWALL=0 add_default() { - local table proto i iptables + local table line if ! get_fwmark table; then table=51820 while [[ -n $(ip -4 route show table $table 2>/dev/null) || -n $(ip -6 route show table $table 2>/dev/null) ]]; do @@ -204,21 +213,32 @@ add_default() { done cmd wg set "$INTERFACE" fwmark $table fi - proto=-4 iptables=iptables - [[ $1 == *:* ]] && proto=-6 iptables=ip6tables + local proto=-4 iptables=iptables pf=ip + [[ $1 == *:* ]] && proto=-6 iptables=ip6tables pf=ip6 cmd ip $proto route add "$1" dev "$INTERFACE" table $table cmd ip $proto rule add not fwmark $table table $table cmd ip $proto rule add table main suppress_prefixlength 0 - local marker="-m comment --comment \"wg-quick(8) rule for $INTERFACE\"" restore="*raw" - for i in "${ADDRESSES[@]}"; do - [[ ( $proto == -4 && $i != *:* ) || ( $proto == -6 && $i == *:* ) ]] || continue - printf -v restore '%s\n-I PREROUTING ! -i %s -d %s -m addrtype ! --src-type LOCAL -j DROP %s\n' "$restore" "$INTERFACE" "${i%/*}" "$marker" - done - printf -v restore '%s\nCOMMIT\n*mangle\n-I POSTROUTING -m mark --mark %d -p udp -j CONNMARK --save-mark %s\n-I PREROUTING -p udp -j CONNMARK --restore-mark %s\nCOMMIT\n' "$restore" $table "$marker" "$marker" + local marker="-m comment --comment \"wg-quick(8) rule for $INTERFACE\"" restore=$'*raw\n' nftable="wg-quick-$INTERFACE" nftcmd + printf -v nftcmd '%sadd table %s %s\n' "$nftcmd" "$pf" "$nftable" + printf -v nftcmd '%sadd chain %s %s preraw { type filter hook prerouting priority -300; }\n' "$nftcmd" "$pf" "$nftable" + printf -v nftcmd '%sadd chain %s %s premangle { type filter hook prerouting priority -150; }\n' "$nftcmd" "$pf" "$nftable" + printf -v nftcmd '%sadd chain %s %s postmangle { type filter hook postrouting priority -150; }\n' "$nftcmd" "$pf" "$nftable" + while read -r line; do + [[ $line =~ .*inet6?\ ([0-9a-f:.]+)/[0-9]+.* ]] || continue + printf -v restore '%s-I PREROUTING ! -i %s -d %s -m addrtype ! --src-type LOCAL -j DROP %s\n' "$restore" "$INTERFACE" "${BASH_REMATCH[1]}" "$marker" + printf -v nftcmd '%sadd rule %s %s preraw iifname != %s %s daddr %s fib saddr type != local drop\n' "$nftcmd" "$pf" "$nftable" "$INTERFACE" "$pf" "${BASH_REMATCH[1]}" + done < <(ip -o $proto addr show dev "$INTERFACE" 2>/dev/null) + printf -v restore '%sCOMMIT\n*mangle\n-I POSTROUTING -m mark --mark %d -p udp -j CONNMARK --save-mark %s\n-I PREROUTING -p udp -j CONNMARK --restore-mark %s\nCOMMIT\n' "$restore" $table "$marker" "$marker" + printf -v nftcmd '%sadd rule %s %s postmangle meta l4proto udp mark %d ct mark set mark \n' "$nftcmd" "$pf" "$nftable" $table + printf -v nftcmd '%sadd rule %s %s premangle meta l4proto udp meta mark set ct mark \n' "$nftcmd" "$pf" "$nftable" [[ $proto == -4 ]] && cmd sysctl -q net.ipv4.conf.all.src_valid_mark=1 - echo "$restore" | cmd $iptables-restore -n - HAVE_SET_IPTABLES=1 + if type -p nft >/dev/null; then + cmd nft -f <(echo -n "$nftcmd") + else + echo -n "$restore" | cmd $iptables-restore -n + fi + HAVE_SET_FIREWALL=1 return 0 } @@ -323,7 +343,7 @@ cmd_down() { [[ $SAVE_CONFIG -eq 0 ]] || save_config del_if unset_dns || true - remove_iptables || true + remove_firewall || true execute_hooks "${POST_DOWN[@]}" } diff --git a/src/uapi/wireguard.h b/src/uapi/wireguard.h index dd8a47c..ae88be1 100644 --- a/src/uapi/wireguard.h +++ b/src/uapi/wireguard.h @@ -18,13 +18,13 @@ * one but not both of: * * WGDEVICE_A_IFINDEX: NLA_U32 - * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 + * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMSIZ - 1 * * The kernel will then return several messages (NLM_F_MULTI) containing the * following tree of nested items: * * WGDEVICE_A_IFINDEX: NLA_U32 - * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 + * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMSIZ - 1 * WGDEVICE_A_PRIVATE_KEY: NLA_EXACT_LEN, len WG_KEY_LEN * WGDEVICE_A_PUBLIC_KEY: NLA_EXACT_LEN, len WG_KEY_LEN * WGDEVICE_A_LISTEN_PORT: NLA_U16 @@ -77,7 +77,7 @@ * WGDEVICE_A_IFINDEX and WGDEVICE_A_IFNAME: * * WGDEVICE_A_IFINDEX: NLA_U32 - * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMESIZ - 1 + * WGDEVICE_A_IFNAME: NLA_NUL_STRING, maxlen IFNAMSIZ - 1 * WGDEVICE_A_FLAGS: NLA_U32, 0 or WGDEVICE_F_REPLACE_PEERS if all current * peers should be removed prior to adding the list below. * WGDEVICE_A_PRIVATE_KEY: len WG_KEY_LEN, all zeros to remove @@ -121,7 +121,7 @@ * filling in information not contained in the prior. Note that if * WGDEVICE_F_REPLACE_PEERS is specified in the first message, it probably * should not be specified in fragments that come after, so that the list - * of peers is only cleared the first time but appened after. Likewise for + * of peers is only cleared the first time but appended after. Likewise for * peers, if WGPEER_F_REPLACE_ALLOWEDIPS is specified in the first message * of a peer, it likely should not be specified in subsequent fragments. * diff --git a/src/version.h b/src/version.h index 4e2bb40..ddba103 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define WIREGUARD_VERSION "0.0.20191205" +#define WIREGUARD_VERSION "0.0.20191219" |