summaryrefslogtreecommitdiff
path: root/sysdep/linux
diff options
context:
space:
mode:
authorMikael Magnusson <mikma@users.sourceforge.net>2018-12-15 23:56:07 +0100
committerMikael Magnusson <mikma@users.sourceforge.net>2019-02-28 00:46:04 +0100
commitc9ed80d46ef714dd15626a4a4e98468e154e473f (patch)
tree0139fbec82d255a48539823f912a1d30df863896 /sysdep/linux
parent62763c769f59569de7d6e53968f1170b2bd0c239 (diff)
wireguard: update library
Diffstat (limited to 'sysdep/linux')
-rw-r--r--sysdep/linux/wireguard.c55
-rw-r--r--sysdep/linux/wireguard.h4
2 files changed, 32 insertions, 27 deletions
diff --git a/sysdep/linux/wireguard.c b/sysdep/linux/wireguard.c
index a7135678..b8368e9f 100644
--- a/sysdep/linux/wireguard.c
+++ b/sysdep/linux/wireguard.c
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: LGPL-2.1+
- *
+// SPDX-License-Identifier: LGPL-2.1+
+/*
* Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
* Copyright (C) 2008-2012 Pablo Neira Ayuso <pablo@netfilter.org>.
*/
@@ -358,11 +358,15 @@ static void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len,
{
struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
+ int pad;
attr->nla_type = type;
attr->nla_len = payload_len;
memcpy(mnl_attr_get_payload(attr), data, len);
nlh->nlmsg_len += MNL_ALIGN(payload_len);
+ pad = MNL_ALIGN(len) - len;
+ if (pad > 0)
+ memset(mnl_attr_get_payload(attr) + len, 0, pad);
}
static void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data)
@@ -994,8 +998,15 @@ another:
goto cleanup;
}
if ((len = mnl_cb_run(rtnl_buffer, len, seq, portid, read_devices_cb, buffer)) < 0) {
- ret = -errno;
- goto cleanup;
+ /* Netlink returns NLM_F_DUMP_INTR if the set of all tunnels changed
+ * during the dump. That's unfortunate, but is pretty common on busy
+ * systems that are adding and removing tunnels all the time. Rather
+ * than retrying, potentially indefinitely, we just work with the
+ * partial results. */
+ if (errno != EINTR) {
+ ret = -errno;
+ goto cleanup;
+ }
}
if (len == MNL_CB_OK + 1)
goto another;
@@ -1070,7 +1081,6 @@ cleanup:
int wg_set_device(wg_device *dev)
{
int ret = 0;
- size_t i, j;
wg_peer *peer = NULL;
wg_allowedip *allowedip = NULL;
struct nlattr *peers_nest, *peer_nest, *allowedips_nest, *allowedip_nest;
@@ -1103,10 +1113,10 @@ again:
goto send;
peers_nest = peer_nest = allowedips_nest = allowedip_nest = NULL;
peers_nest = mnl_attr_nest_start(nlh, WGDEVICE_A_PEERS);
- for (i = 0, peer = peer ? peer : dev->first_peer; peer; peer = peer->next_peer) {
+ for (peer = peer ? peer : dev->first_peer; peer; peer = peer->next_peer) {
uint32_t flags = 0;
- peer_nest = mnl_attr_nest_start_check(nlh, MNL_SOCKET_BUFFER_SIZE, i++);
+ peer_nest = mnl_attr_nest_start_check(nlh, MNL_SOCKET_BUFFER_SIZE, 0);
if (!peer_nest)
goto toobig_peers;
if (!mnl_attr_put_check(nlh, MNL_SOCKET_BUFFER_SIZE, WGPEER_A_PUBLIC_KEY, sizeof(peer->public_key), peer->public_key))
@@ -1142,8 +1152,8 @@ again:
allowedips_nest = mnl_attr_nest_start_check(nlh, MNL_SOCKET_BUFFER_SIZE, WGPEER_A_ALLOWEDIPS);
if (!allowedips_nest)
goto toobig_allowedips;
- for (j = 0; allowedip; allowedip = allowedip->next_allowedip) {
- allowedip_nest = mnl_attr_nest_start_check(nlh, MNL_SOCKET_BUFFER_SIZE, j++);
+ for (; allowedip; allowedip = allowedip->next_allowedip) {
+ allowedip_nest = mnl_attr_nest_start_check(nlh, MNL_SOCKET_BUFFER_SIZE, 0);
if (!allowedip_nest)
goto toobig_allowedips;
if (!mnl_attr_put_u16_check(nlh, MNL_SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_FAMILY, allowedip->family))
@@ -1510,7 +1520,7 @@ void wg_free_device(wg_device *dev)
free(dev);
}
-static void encode_base64(char dest[4], const uint8_t src[3])
+static void encode_base64(char dest[static 4], const uint8_t src[static 3])
{
const uint8_t input[] = { (src[0] >> 2) & 63, ((src[0] << 4) | (src[1] >> 4)) & 63, ((src[1] << 2) | (src[2] >> 6)) & 63, src[2] & 63 };
unsigned int i;
@@ -1535,7 +1545,7 @@ void wg_key_to_base64(wg_key_b64_string base64, const wg_key key)
base64[sizeof(wg_key_b64_string) - 1] = '\0';
}
-static int decode_base64(const char src[4])
+static int decode_base64(const char src[static 4])
{
int val = 0;
unsigned int i;
@@ -1555,25 +1565,25 @@ int wg_key_from_base64(wg_key key, const wg_key_b64_string base64)
{
unsigned int i;
int val;
+ volatile uint8_t ret = 0;
- errno = EINVAL;
- if (strlen(base64) != sizeof(wg_key_b64_string) - 1 || base64[sizeof(wg_key_b64_string) - 2] != '=')
+ if (strlen(base64) != sizeof(wg_key_b64_string) - 1 || base64[sizeof(wg_key_b64_string) - 2] != '=') {
+ errno = EINVAL;
goto out;
+ }
for (i = 0; i < 32 / 3; ++i) {
val = decode_base64(&base64[i * 4]);
- if (val < 0)
- goto out;
+ ret |= (uint32_t)val >> 31;
key[i * 3 + 0] = (val >> 16) & 0xff;
key[i * 3 + 1] = (val >> 8) & 0xff;
key[i * 3 + 2] = val & 0xff;
}
val = decode_base64((const char[]){ base64[i * 4 + 0], base64[i * 4 + 1], base64[i * 4 + 2], 'A' });
- if (val < 0 || val & 0xff)
- goto out;
+ ret |= ((uint32_t)val >> 31) | (val & 0xff);
key[i * 3 + 0] = (val >> 16) & 0xff;
key[i * 3 + 1] = (val >> 8) & 0xff;
- errno = 0;
+ errno = EINVAL & ~((ret - 1) >> 8);
out:
return -errno;
}
@@ -1589,16 +1599,11 @@ static __attribute__((noinline)) void memzero_explicit(void *s, size_t count)
static void carry(fe o)
{
int i;
- int64_t c;
for (i = 0; i < 16; ++i) {
- o[i] += (1LL << 16);
- c = o[i] >> 16;
- o[(i + 1) * (i < 15)] += c - 1 + 37 * (c - 1) * (i == 15);
- o[i] -= c << 16;
+ o[(i + 1) % 16] += (i == 15 ? 38 : 1) * (o[i] >> 16);
+ o[i] &= 0xffff;
}
-
- memzero_explicit(&c, sizeof(c));
}
static void cswap(fe p, fe q, int b)
diff --git a/sysdep/linux/wireguard.h b/sysdep/linux/wireguard.h
index 53d9d5d7..e9210a41 100644
--- a/sysdep/linux/wireguard.h
+++ b/sysdep/linux/wireguard.h
@@ -1,5 +1,5 @@
-/* SPDX-License-Identifier: LGPL-2.1+
- *
+/* SPDX-License-Identifier: LGPL-2.1+ */
+/*
* Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*/