git: 919fc568b68f - stable/13 - Add 'contrib/wireguard-tools/' from commit '7e00bf8773b93a2a3ee28dba2710d2ae443989f1'

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Sun, 13 Nov 2022 05:38:02 UTC
The branch stable/13 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=919fc568b68f4f68fe897eacdce7fc34bc646fe5

commit 919fc568b68f4f68fe897eacdce7fc34bc646fe5
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2022-10-29 03:05:14 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2022-11-13 05:37:05 +0000

    Add 'contrib/wireguard-tools/' from commit '7e00bf8773b93a2a3ee28dba2710d2ae443989f1'
    
    git-subtree-dir: contrib/wireguard-tools
    git-subtree-mainline: 9142a2a37b2fe65d46ace08a098ad26b8ff81541
    git-subtree-split: 7e00bf8773b93a2a3ee28dba2710d2ae443989f1
    (cherry picked from commit adf376485712c8fffbf3be330d505a969647f479)
---
 contrib/wireguard-tools/.gitignore          |  16 +
 contrib/wireguard-tools/config.c            | 650 +++++++++++++++++++++
 contrib/wireguard-tools/config.h            |  27 +
 contrib/wireguard-tools/containers.h        | 107 ++++
 contrib/wireguard-tools/ctype.h             |  29 +
 contrib/wireguard-tools/curve25519-fiat32.h | 860 ++++++++++++++++++++++++++++
 contrib/wireguard-tools/curve25519-hacl64.h | 784 +++++++++++++++++++++++++
 contrib/wireguard-tools/curve25519.c        |  98 ++++
 contrib/wireguard-tools/curve25519.h        |  24 +
 contrib/wireguard-tools/encoding.c          | 125 ++++
 contrib/wireguard-tools/encoding.h          |  24 +
 contrib/wireguard-tools/genkey.c            |  99 ++++
 contrib/wireguard-tools/ipc-freebsd.h       | 350 +++++++++++
 contrib/wireguard-tools/ipc-uapi-unix.h     | 119 ++++
 contrib/wireguard-tools/ipc-uapi.h          | 297 ++++++++++
 contrib/wireguard-tools/ipc.c               |  98 ++++
 contrib/wireguard-tools/ipc.h               |  17 +
 contrib/wireguard-tools/man/wg.8            | 258 +++++++++
 contrib/wireguard-tools/pubkey.c            |  50 ++
 contrib/wireguard-tools/set.c               |  41 ++
 contrib/wireguard-tools/setconf.c           | 156 +++++
 contrib/wireguard-tools/show.c              | 454 +++++++++++++++
 contrib/wireguard-tools/showconf.c          | 103 ++++
 contrib/wireguard-tools/subcommands.h       |  17 +
 contrib/wireguard-tools/terminal.c          |  76 +++
 contrib/wireguard-tools/terminal.h          |  51 ++
 contrib/wireguard-tools/version.h           |   3 +
 contrib/wireguard-tools/wg.c                |  66 +++
 28 files changed, 4999 insertions(+)

diff --git a/contrib/wireguard-tools/.gitignore b/contrib/wireguard-tools/.gitignore
new file mode 100644
index 000000000000..4343ea95a0a2
--- /dev/null
+++ b/contrib/wireguard-tools/.gitignore
@@ -0,0 +1,16 @@
+# GPL-2.0, not used on FreeBSD:
+Makefile
+completion
+fuzz/
+ipc-uapi-windows.h
+ipc-windows.h
+netlink.h
+uapi/
+wg-quick/
+wincompat/
+
+# License OK, but not needed for FreeBSD
+ipc-linux.h
+ipc-openbsd.h
+man/wg-quick.8
+systemd/
diff --git a/contrib/wireguard-tools/config.c b/contrib/wireguard-tools/config.c
new file mode 100644
index 000000000000..81ccb479c367
--- /dev/null
+++ b/contrib/wireguard-tools/config.c
@@ -0,0 +1,650 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ */
+
+#include <arpa/inet.h>
+#include <limits.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include "config.h"
+#include "containers.h"
+#include "ipc.h"
+#include "encoding.h"
+#include "ctype.h"
+
+#define COMMENT_CHAR '#'
+
+static const char *get_value(const char *line, const char *key)
+{
+	size_t linelen = strlen(line);
+	size_t keylen = strlen(key);
+
+	if (keylen >= linelen)
+		return NULL;
+
+	if (strncasecmp(line, key, keylen))
+		return NULL;
+
+	return line + keylen;
+}
+
+static inline bool parse_port(uint16_t *port, uint32_t *flags, const char *value)
+{
+	int ret;
+	struct addrinfo *resolved;
+	struct addrinfo hints = {
+		.ai_family = AF_UNSPEC,
+		.ai_socktype = SOCK_DGRAM,
+		.ai_protocol = IPPROTO_UDP,
+		.ai_flags = AI_PASSIVE
+	};
+
+	if (!strlen(value)) {
+		fprintf(stderr, "Unable to parse empty port\n");
+		return false;
+	}
+
+	ret = getaddrinfo(NULL, value, &hints, &resolved);
+	if (ret) {
+		fprintf(stderr, "%s: `%s'\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), value);
+		return false;
+	}
+
+	ret = -1;
+	if (resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(struct sockaddr_in)) {
+		*port = ntohs(((struct sockaddr_in *)resolved->ai_addr)->sin_port);
+		ret = 0;
+	} else if (resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(struct sockaddr_in6)) {
+		*port = ntohs(((struct sockaddr_in6 *)resolved->ai_addr)->sin6_port);
+		ret = 0;
+	} else
+		fprintf(stderr, "Neither IPv4 nor IPv6 address found: `%s'\n", value);
+
+	freeaddrinfo(resolved);
+	if (!ret)
+		*flags |= WGDEVICE_HAS_LISTEN_PORT;
+	return ret == 0;
+}
+
+static inline bool parse_fwmark(uint32_t *fwmark, uint32_t *flags, const char *value)
+{
+	unsigned long ret;
+	char *end;
+	int base = 10;
+
+	if (!strcasecmp(value, "off")) {
+		*fwmark = 0;
+		*flags |= WGDEVICE_HAS_FWMARK;
+		return true;
+	}
+
+	if (!char_is_digit(value[0]))
+		goto err;
+
+	if (strlen(value) > 2 && value[0] == '0' && value[1] == 'x')
+		base = 16;
+
+	ret = strtoul(value, &end, base);
+	if (*end || ret > UINT32_MAX)
+		goto err;
+
+	*fwmark = ret;
+	*flags |= WGDEVICE_HAS_FWMARK;
+	return true;
+err:
+	fprintf(stderr, "Fwmark is neither 0/off nor 0-0xffffffff: `%s'\n", value);
+	return false;
+}
+
+static inline bool parse_key(uint8_t key[static WG_KEY_LEN], const char *value)
+{
+	if (!key_from_base64(key, value)) {
+		fprintf(stderr, "Key is not the correct length or format: `%s'\n", value);
+		memset(key, 0, WG_KEY_LEN);
+		return false;
+	}
+	return true;
+}
+
+static bool parse_keyfile(uint8_t key[static WG_KEY_LEN], const char *path)
+{
+	FILE *f;
+	int c;
+	char dst[WG_KEY_LEN_BASE64];
+	bool ret = false;
+
+	f = fopen(path, "r");
+	if (!f) {
+		perror("fopen");
+		return false;
+	}
+
+	if (fread(dst, WG_KEY_LEN_BASE64 - 1, 1, f) != 1) {
+		/* If we're at the end and we didn't read anything, we're /dev/null or an empty file. */
+		if (!ferror(f) && feof(f) && !ftell(f)) {
+			memset(key, 0, WG_KEY_LEN);
+			ret = true;
+			goto out;
+		}
+
+		fprintf(stderr, "Invalid length key in key file\n");
+		goto out;
+	}
+	dst[WG_KEY_LEN_BASE64 - 1] = '\0';
+
+	while ((c = getc(f)) != EOF) {
+		if (!char_is_space(c)) {
+			fprintf(stderr, "Found trailing character in key file: `%c'\n", c);
+			goto out;
+		}
+	}
+	if (ferror(f) && errno) {
+		perror("getc");
+		goto out;
+	}
+	ret = parse_key(key, dst);
+
+out:
+	fclose(f);
+	return ret;
+}
+
+static inline bool parse_ip(struct wgallowedip *allowedip, const char *value)
+{
+	allowedip->family = AF_UNSPEC;
+	if (strchr(value, ':')) {
+		if (inet_pton(AF_INET6, value, &allowedip->ip6) == 1)
+			allowedip->family = AF_INET6;
+	} else {
+		if (inet_pton(AF_INET, value, &allowedip->ip4) == 1)
+			allowedip->family = AF_INET;
+	}
+	if (allowedip->family == AF_UNSPEC) {
+		fprintf(stderr, "Unable to parse IP address: `%s'\n", value);
+		return false;
+	}
+	return true;
+}
+
+static inline int parse_dns_retries(void)
+{
+	unsigned long ret;
+	char *retries = getenv("WG_ENDPOINT_RESOLUTION_RETRIES"), *end;
+
+	if (!retries)
+		return 15;
+	if (!strcmp(retries, "infinity"))
+		return -1;
+
+	ret = strtoul(retries, &end, 10);
+	if (*end || ret > INT_MAX) {
+		fprintf(stderr, "Unable to parse WG_ENDPOINT_RESOLUTION_RETRIES: `%s'\n", retries);
+		exit(1);
+	}
+	return (int)ret;
+}
+
+static inline bool parse_endpoint(struct sockaddr *endpoint, const char *value)
+{
+	char *mutable = strdup(value);
+	char *begin, *end;
+	int ret, retries = parse_dns_retries();
+	struct addrinfo *resolved;
+	struct addrinfo hints = {
+		.ai_family = AF_UNSPEC,
+		.ai_socktype = SOCK_DGRAM,
+		.ai_protocol = IPPROTO_UDP
+	};
+	if (!mutable) {
+		perror("strdup");
+		return false;
+	}
+	if (!strlen(value)) {
+		free(mutable);
+		fprintf(stderr, "Unable to parse empty endpoint\n");
+		return false;
+	}
+	if (mutable[0] == '[') {
+		begin = &mutable[1];
+		end = strchr(mutable, ']');
+		if (!end) {
+			free(mutable);
+			fprintf(stderr, "Unable to find matching brace of endpoint: `%s'\n", value);
+			return false;
+		}
+		*end++ = '\0';
+		if (*end++ != ':' || !*end) {
+			free(mutable);
+			fprintf(stderr, "Unable to find port of endpoint: `%s'\n", value);
+			return false;
+		}
+	} else {
+		begin = mutable;
+		end = strrchr(mutable, ':');
+		if (!end || !*(end + 1)) {
+			free(mutable);
+			fprintf(stderr, "Unable to find port of endpoint: `%s'\n", value);
+			return false;
+		}
+		*end++ = '\0';
+	}
+
+	#define min(a, b) ((a) < (b) ? (a) : (b))
+	for (unsigned int timeout = 1000000;; timeout = min(20000000, timeout * 6 / 5)) {
+		ret = getaddrinfo(begin, end, &hints, &resolved);
+		if (!ret)
+			break;
+		/* The set of return codes that are "permanent failures". All other possibilities are potentially transient.
+		 *
+		 * This is according to https://sourceware.org/glibc/wiki/NameResolver which states:
+		 *	"From the perspective of the application that calls getaddrinfo() it perhaps
+		 *	 doesn't matter that much since EAI_FAIL, EAI_NONAME and EAI_NODATA are all
+		 *	 permanent failure codes and the causes are all permanent failures in the
+		 *	 sense that there is no point in retrying later."
+		 *
+		 * So this is what we do, except FreeBSD removed EAI_NODATA some time ago, so that's conditional.
+		 */
+		if (ret == EAI_NONAME || ret == EAI_FAIL ||
+			#ifdef EAI_NODATA
+				ret == EAI_NODATA ||
+			#endif
+				(retries >= 0 && !retries--)) {
+			free(mutable);
+			fprintf(stderr, "%s: `%s'\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), value);
+			return false;
+		}
+		fprintf(stderr, "%s: `%s'. Trying again in %.2f seconds...\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), value, timeout / 1000000.0);
+		usleep(timeout);
+	}
+
+	if ((resolved->ai_family == AF_INET && resolved->ai_addrlen == sizeof(struct sockaddr_in)) ||
+	    (resolved->ai_family == AF_INET6 && resolved->ai_addrlen == sizeof(struct sockaddr_in6)))
+		memcpy(endpoint, resolved->ai_addr, resolved->ai_addrlen);
+	else {
+		freeaddrinfo(resolved);
+		free(mutable);
+		fprintf(stderr, "Neither IPv4 nor IPv6 address found: `%s'\n", value);
+		return false;
+	}
+	freeaddrinfo(resolved);
+	free(mutable);
+	return true;
+}
+
+static inline bool parse_persistent_keepalive(uint16_t *interval, uint32_t *flags, const char *value)
+{
+	unsigned long ret;
+	char *end;
+
+	if (!strcasecmp(value, "off")) {
+		*interval = 0;
+		*flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
+		return true;
+	}
+
+	if (!char_is_digit(value[0]))
+		goto err;
+
+	ret = strtoul(value, &end, 10);
+	if (*end || ret > 65535)
+		goto err;
+
+	*interval = (uint16_t)ret;
+	*flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL;
+	return true;
+err:
+	fprintf(stderr, "Persistent keepalive interval is neither 0/off nor 1-65535: `%s'\n", value);
+	return false;
+}
+
+static bool validate_netmask(struct wgallowedip *allowedip)
+{
+	uint32_t *ip;
+	int last;
+
+	switch (allowedip->family) {
+		case AF_INET:
+			last = 0;
+			ip = (uint32_t *)&allowedip->ip4;
+			break;
+		case AF_INET6:
+			last = 3;
+			ip = (uint32_t *)&allowedip->ip6;
+			break;
+		default:
+			return true; /* We don't know how to validate it, so say 'okay'. */
+	}
+
+	for (int i = last; i >= 0; --i) {
+		uint32_t mask = ~0;
+
+		if (allowedip->cidr >= 32 * (i + 1))
+			break;
+		if (allowedip->cidr > 32 * i)
+			mask >>= (allowedip->cidr - 32 * i);
+		if (ntohl(ip[i]) & mask)
+			return false;
+	}
+
+	return true;
+}
+
+static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **last_allowedip, const char *value)
+{
+	struct wgallowedip *allowedip = *last_allowedip, *new_allowedip;
+	char *mask, *mutable = strdup(value), *sep, *saved_entry;
+
+	if (!mutable) {
+		perror("strdup");
+		return false;
+	}
+	peer->flags |= WGPEER_REPLACE_ALLOWEDIPS;
+	if (!strlen(value)) {
+		free(mutable);
+		return true;
+	}
+	sep = mutable;
+	while ((mask = strsep(&sep, ","))) {
+		unsigned long cidr;
+		char *end, *ip;
+
+		saved_entry = strdup(mask);
+		ip = strsep(&mask, "/");
+
+		new_allowedip = calloc(1, sizeof(*new_allowedip));
+		if (!new_allowedip) {
+			perror("calloc");
+			free(saved_entry);
+			free(mutable);
+			return false;
+		}
+
+		if (!parse_ip(new_allowedip, ip)) {
+			free(new_allowedip);
+			free(saved_entry);
+			free(mutable);
+			return false;
+		}
+
+		if (mask) {
+			if (!char_is_digit(mask[0]))
+				goto err;
+			cidr = strtoul(mask, &end, 10);
+			if (*end || (cidr > 32 && new_allowedip->family == AF_INET) || (cidr > 128 && new_allowedip->family == AF_INET6))
+				goto err;
+		} else if (new_allowedip->family == AF_INET)
+			cidr = 32;
+		else if (new_allowedip->family == AF_INET6)
+			cidr = 128;
+		else
+			goto err;
+		new_allowedip->cidr = cidr;
+
+		if (!validate_netmask(new_allowedip))
+			fprintf(stderr, "Warning: AllowedIP has nonzero host part: %s/%s\n", ip, mask);
+
+		if (allowedip)
+			allowedip->next_allowedip = new_allowedip;
+		else
+			peer->first_allowedip = new_allowedip;
+		allowedip = new_allowedip;
+		free(saved_entry);
+	}
+	free(mutable);
+	*last_allowedip = allowedip;
+	return true;
+
+err:
+	free(new_allowedip);
+	free(mutable);
+	fprintf(stderr, "AllowedIP is not in the correct format: `%s'\n", saved_entry);
+	free(saved_entry);
+	return false;
+}
+
+static bool process_line(struct config_ctx *ctx, const char *line)
+{
+	const char *value;
+	bool ret = true;
+
+	if (!strcasecmp(line, "[Interface]")) {
+		ctx->is_peer_section = false;
+		ctx->is_device_section = true;
+		return true;
+	}
+	if (!strcasecmp(line, "[Peer]")) {
+		struct wgpeer *new_peer = calloc(1, sizeof(struct wgpeer));
+
+		if (!new_peer) {
+			perror("calloc");
+			return false;
+		}
+		ctx->last_allowedip = NULL;
+		if (ctx->last_peer)
+			ctx->last_peer->next_peer = new_peer;
+		else
+			ctx->device->first_peer = new_peer;
+		ctx->last_peer = new_peer;
+		ctx->is_peer_section = true;
+		ctx->is_device_section = false;
+		ctx->last_peer->flags |= WGPEER_REPLACE_ALLOWEDIPS;
+		return true;
+	}
+
+#define key_match(key) (value = get_value(line, key "="))
+
+	if (ctx->is_device_section) {
+		if (key_match("ListenPort"))
+			ret = parse_port(&ctx->device->listen_port, &ctx->device->flags, value);
+		else if (key_match("FwMark"))
+			ret = parse_fwmark(&ctx->device->fwmark, &ctx->device->flags, value);
+		else if (key_match("PrivateKey")) {
+			ret = parse_key(ctx->device->private_key, value);
+			if (ret)
+				ctx->device->flags |= WGDEVICE_HAS_PRIVATE_KEY;
+		} else
+			goto error;
+	} else if (ctx->is_peer_section) {
+		if (key_match("Endpoint"))
+			ret = parse_endpoint(&ctx->last_peer->endpoint.addr, value);
+		else if (key_match("PublicKey")) {
+			ret = parse_key(ctx->last_peer->public_key, value);
+			if (ret)
+				ctx->last_peer->flags |= WGPEER_HAS_PUBLIC_KEY;
+		} else if (key_match("AllowedIPs"))
+			ret = parse_allowedips(ctx->last_peer, &ctx->last_allowedip, value);
+		else if (key_match("PersistentKeepalive"))
+			ret = parse_persistent_keepalive(&ctx->last_peer->persistent_keepalive_interval, &ctx->last_peer->flags, value);
+		else if (key_match("PresharedKey")) {
+			ret = parse_key(ctx->last_peer->preshared_key, value);
+			if (ret)
+				ctx->last_peer->flags |= WGPEER_HAS_PRESHARED_KEY;
+		} else
+			goto error;
+	} else
+		goto error;
+	return ret;
+
+#undef key_match
+
+error:
+	fprintf(stderr, "Line unrecognized: `%s'\n", line);
+	return false;
+}
+
+bool config_read_line(struct config_ctx *ctx, const char *input)
+{
+	size_t len, cleaned_len = 0;
+	char *line, *comment;
+	bool ret = true;
+
+	/* This is what strchrnul is for, but that isn't portable. */
+	comment = strchr(input, COMMENT_CHAR);
+	if (comment)
+		len = comment - input;
+	else
+		len = strlen(input);
+
+	line = calloc(len + 1, sizeof(char));
+	if (!line) {
+		perror("calloc");
+		ret = false;
+		goto out;
+	}
+
+	for (size_t i = 0; i < len; ++i) {
+		if (!char_is_space(input[i]))
+			line[cleaned_len++] = input[i];
+	}
+	if (!cleaned_len)
+		goto out;
+	ret = process_line(ctx, line);
+out:
+	free(line);
+	if (!ret)
+		free_wgdevice(ctx->device);
+	return ret;
+}
+
+bool config_read_init(struct config_ctx *ctx, bool append)
+{
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->device = calloc(1, sizeof(*ctx->device));
+	if (!ctx->device) {
+		perror("calloc");
+		return false;
+	}
+	if (!append)
+		ctx->device->flags |= WGDEVICE_REPLACE_PEERS | WGDEVICE_HAS_PRIVATE_KEY | WGDEVICE_HAS_FWMARK | WGDEVICE_HAS_LISTEN_PORT;
+	return true;
+}
+
+struct wgdevice *config_read_finish(struct config_ctx *ctx)
+{
+	struct wgpeer *peer;
+
+	for_each_wgpeer(ctx->device, peer) {
+		if (!(peer->flags & WGPEER_HAS_PUBLIC_KEY)) {
+			fprintf(stderr, "A peer is missing a public key\n");
+			goto err;
+		}
+	}
+	return ctx->device;
+err:
+	free_wgdevice(ctx->device);
+	return NULL;
+}
+
+static char *strip_spaces(const char *in)
+{
+	char *out;
+	size_t t, l, i;
+
+	t = strlen(in);
+	out = calloc(t + 1, sizeof(char));
+	if (!out) {
+		perror("calloc");
+		return NULL;
+	}
+	for (i = 0, l = 0; i < t; ++i) {
+		if (!char_is_space(in[i]))
+			out[l++] = in[i];
+	}
+	return out;
+}
+
+struct wgdevice *config_read_cmd(const char *argv[], int argc)
+{
+	struct wgdevice *device = calloc(1, sizeof(*device));
+	struct wgpeer *peer = NULL;
+	struct wgallowedip *allowedip = NULL;
+
+	if (!device) {
+		perror("calloc");
+		return false;
+	}
+	while (argc > 0) {
+		if (!strcmp(argv[0], "listen-port") && argc >= 2 && !peer) {
+			if (!parse_port(&device->listen_port, &device->flags, argv[1]))
+				goto error;
+			argv += 2;
+			argc -= 2;
+		} else if (!strcmp(argv[0], "fwmark") && argc >= 2 && !peer) {
+			if (!parse_fwmark(&device->fwmark, &device->flags, argv[1]))
+				goto error;
+			argv += 2;
+			argc -= 2;
+		} else if (!strcmp(argv[0], "private-key") && argc >= 2 && !peer) {
+			if (!parse_keyfile(device->private_key, argv[1]))
+				goto error;
+			device->flags |= WGDEVICE_HAS_PRIVATE_KEY;
+			argv += 2;
+			argc -= 2;
+		} else if (!strcmp(argv[0], "peer") && argc >= 2) {
+			struct wgpeer *new_peer = calloc(1, sizeof(*new_peer));
+
+			allowedip = NULL;
+			if (!new_peer) {
+				perror("calloc");
+				goto error;
+			}
+			if (peer)
+				peer->next_peer = new_peer;
+			else
+				device->first_peer = new_peer;
+			peer = new_peer;
+			if (!parse_key(peer->public_key, argv[1]))
+				goto error;
+			peer->flags |= WGPEER_HAS_PUBLIC_KEY;
+			argv += 2;
+			argc -= 2;
+		} else if (!strcmp(argv[0], "remove") && argc >= 1 && peer) {
+			peer->flags |= WGPEER_REMOVE_ME;
+			argv += 1;
+			argc -= 1;
+		} else if (!strcmp(argv[0], "endpoint") && argc >= 2 && peer) {
+			if (!parse_endpoint(&peer->endpoint.addr, argv[1]))
+				goto error;
+			argv += 2;
+			argc -= 2;
+		} else if (!strcmp(argv[0], "allowed-ips") && argc >= 2 && peer) {
+			char *line = strip_spaces(argv[1]);
+
+			if (!line)
+				goto error;
+			if (!parse_allowedips(peer, &allowedip, line)) {
+				free(line);
+				goto error;
+			}
+			free(line);
+			argv += 2;
+			argc -= 2;
+		} else if (!strcmp(argv[0], "persistent-keepalive") && argc >= 2 && peer) {
+			if (!parse_persistent_keepalive(&peer->persistent_keepalive_interval, &peer->flags, argv[1]))
+				goto error;
+			argv += 2;
+			argc -= 2;
+		} else if (!strcmp(argv[0], "preshared-key") && argc >= 2 && peer) {
+			if (!parse_keyfile(peer->preshared_key, argv[1]))
+				goto error;
+			peer->flags |= WGPEER_HAS_PRESHARED_KEY;
+			argv += 2;
+			argc -= 2;
+		} else {
+			fprintf(stderr, "Invalid argument: %s\n", argv[0]);
+			goto error;
+		}
+	}
+	return device;
+error:
+	free_wgdevice(device);
+	return false;
+}
diff --git a/contrib/wireguard-tools/config.h b/contrib/wireguard-tools/config.h
new file mode 100644
index 000000000000..443cf2147446
--- /dev/null
+++ b/contrib/wireguard-tools/config.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ */
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <stdbool.h>
+
+struct wgdevice;
+struct wgpeer;
+struct wgallowedip;
+
+struct config_ctx {
+	struct wgdevice *device;
+	struct wgpeer *last_peer;
+	struct wgallowedip *last_allowedip;
+	bool is_peer_section, is_device_section;
+};
+
+struct wgdevice *config_read_cmd(const char *argv[], int argc);
+bool config_read_init(struct config_ctx *ctx, bool append);
+bool config_read_line(struct config_ctx *ctx, const char *line);
+struct wgdevice *config_read_finish(struct config_ctx *ctx);
+
+#endif
diff --git a/contrib/wireguard-tools/containers.h b/contrib/wireguard-tools/containers.h
new file mode 100644
index 000000000000..a82e8ddee46a
--- /dev/null
+++ b/contrib/wireguard-tools/containers.h
@@ -0,0 +1,107 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ */
+
+#ifndef CONTAINERS_H
+#define CONTAINERS_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#if defined(__linux__)
+#include <linux/wireguard.h>
+#elif defined(__OpenBSD__)
+#include <net/if_wg.h>
+#endif
+
+#ifndef WG_KEY_LEN
+#define WG_KEY_LEN 32
+#endif
+
+/* Cross platform __kernel_timespec */
+struct timespec64 {
+	int64_t tv_sec;
+	int64_t tv_nsec;
+};
+
+struct wgallowedip {
+	uint16_t family;
+	union {
+		struct in_addr ip4;
+		struct in6_addr ip6;
+	};
+	uint8_t cidr;
+	struct wgallowedip *next_allowedip;
+};
+
+enum {
+	WGPEER_REMOVE_ME = 1U << 0,
+	WGPEER_REPLACE_ALLOWEDIPS = 1U << 1,
+	WGPEER_HAS_PUBLIC_KEY = 1U << 2,
+	WGPEER_HAS_PRESHARED_KEY = 1U << 3,
+	WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL = 1U << 4
+};
+
+struct wgpeer {
+	uint32_t flags;
+
+	uint8_t public_key[WG_KEY_LEN];
+	uint8_t preshared_key[WG_KEY_LEN];
+
+	union {
+		struct sockaddr addr;
+		struct sockaddr_in addr4;
+		struct sockaddr_in6 addr6;
+	} endpoint;
+
+	struct timespec64 last_handshake_time;
+	uint64_t rx_bytes, tx_bytes;
+	uint16_t persistent_keepalive_interval;
+
+	struct wgallowedip *first_allowedip, *last_allowedip;
+	struct wgpeer *next_peer;
+};
+
+enum {
+	WGDEVICE_REPLACE_PEERS = 1U << 0,
+	WGDEVICE_HAS_PRIVATE_KEY = 1U << 1,
+	WGDEVICE_HAS_PUBLIC_KEY = 1U << 2,
+	WGDEVICE_HAS_LISTEN_PORT = 1U << 3,
+	WGDEVICE_HAS_FWMARK = 1U << 4
+};
+
+struct wgdevice {
+	char name[IFNAMSIZ];
+	uint32_t ifindex;
+
+	uint32_t flags;
+
+	uint8_t public_key[WG_KEY_LEN];
+	uint8_t private_key[WG_KEY_LEN];
+
+	uint32_t fwmark;
+	uint16_t listen_port;
+
+	struct wgpeer *first_peer, *last_peer;
+};
+
+#define for_each_wgpeer(__dev, __peer) for ((__peer) = (__dev)->first_peer; (__peer); (__peer) = (__peer)->next_peer)
+#define for_each_wgallowedip(__peer, __allowedip) for ((__allowedip) = (__peer)->first_allowedip; (__allowedip); (__allowedip) = (__allowedip)->next_allowedip)
+
+static inline void free_wgdevice(struct wgdevice *dev)
+{
+	if (!dev)
+		return;
+	for (struct wgpeer *peer = dev->first_peer, *np = peer ? peer->next_peer : NULL; peer; peer = np, np = peer ? peer->next_peer : NULL) {
+		for (struct wgallowedip *allowedip = peer->first_allowedip, *na = allowedip ? allowedip->next_allowedip : NULL; allowedip; allowedip = na, na = allowedip ? allowedip->next_allowedip : NULL)
+			free(allowedip);
+		free(peer);
+	}
+	free(dev);
+}
+
+#endif
diff --git a/contrib/wireguard-tools/ctype.h b/contrib/wireguard-tools/ctype.h
new file mode 100644
index 000000000000..7c9942c29265
--- /dev/null
+++ b/contrib/wireguard-tools/ctype.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ *
+ * Specialized constant-time ctype.h reimplementations that aren't locale-specific.
+ */
+
+#ifndef CTYPE_H
+#define CTYPE_H
+
+#include <stdbool.h>
+
+static inline bool char_is_space(int c)
+{
+	unsigned char d = c - 9;
+	return (0x80001FU >> (d & 31)) & (1U >> (d >> 5));
+}
+
+static inline bool char_is_digit(int c)
+{
+	return (unsigned int)(('0' - 1 - c) & (c - ('9' + 1))) >> (sizeof(c) * 8 - 1);
+}
+
+static inline bool char_is_alpha(int c)
+{
+	return (unsigned int)(('a' - 1 - (c | 32)) & ((c | 32) - ('z' + 1))) >> (sizeof(c) * 8 - 1);
+}
+
+#endif
diff --git a/contrib/wireguard-tools/curve25519-fiat32.h b/contrib/wireguard-tools/curve25519-fiat32.h
new file mode 100644
index 000000000000..66f3309c8d88
--- /dev/null
+++ b/contrib/wireguard-tools/curve25519-fiat32.h
@@ -0,0 +1,860 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2015-2016 The fiat-crypto Authors.
+ * Copyright (C) 2018-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ *
+ * This is a machine-generated formally verified implementation of Curve25519
+ * ECDH from: <https://github.com/mit-plv/fiat-crypto>. Though originally
+ * machine generated, it has been tweaked to be suitable for use in the kernel.
+ * It is optimized for 32-bit machines and machines that cannot work efficiently
+ * with 128-bit integer types.
+ */
+
+/* fe means field element. Here the field is \Z/(2^255-19). An element t,
+ * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+ * t[3]+2^102 t[4]+...+2^230 t[9].
+ * fe limbs are bounded by 1.125*2^26,1.125*2^25,1.125*2^26,1.125*2^25,etc.
+ * Multiplication and carrying produce fe from fe_loose.
+ */
+typedef struct fe { u32 v[10]; } fe;
+
+/* fe_loose limbs are bounded by 3.375*2^26,3.375*2^25,3.375*2^26,3.375*2^25,etc
+ * Addition and subtraction produce fe_loose from (fe, fe).
+ */
+typedef struct fe_loose { u32 v[10]; } fe_loose;
+
+static __always_inline void fe_frombytes_impl(u32 h[10], const u8 *s)
+{
+	/* Ignores top bit of s. */
+	u32 a0 = get_unaligned_le32(s);
+	u32 a1 = get_unaligned_le32(s+4);
+	u32 a2 = get_unaligned_le32(s+8);
+	u32 a3 = get_unaligned_le32(s+12);
+	u32 a4 = get_unaligned_le32(s+16);
+	u32 a5 = get_unaligned_le32(s+20);
+	u32 a6 = get_unaligned_le32(s+24);
+	u32 a7 = get_unaligned_le32(s+28);
+	h[0] = a0&((1<<26)-1);                    /* 26 used, 32-26 left.   26 */
+	h[1] = (a0>>26) | ((a1&((1<<19)-1))<< 6); /* (32-26) + 19 =  6+19 = 25 */
+	h[2] = (a1>>19) | ((a2&((1<<13)-1))<<13); /* (32-19) + 13 = 13+13 = 26 */
+	h[3] = (a2>>13) | ((a3&((1<< 6)-1))<<19); /* (32-13) +  6 = 19+ 6 = 25 */
+	h[4] = (a3>> 6);                          /* (32- 6)              = 26 */
+	h[5] = a4&((1<<25)-1);                    /*                        25 */
+	h[6] = (a4>>25) | ((a5&((1<<19)-1))<< 7); /* (32-25) + 19 =  7+19 = 26 */
+	h[7] = (a5>>19) | ((a6&((1<<12)-1))<<13); /* (32-19) + 12 = 13+12 = 25 */
+	h[8] = (a6>>12) | ((a7&((1<< 6)-1))<<20); /* (32-12) +  6 = 20+ 6 = 26 */
+	h[9] = (a7>> 6)&((1<<25)-1); /*                                     25 */
+}
+
+static __always_inline void fe_frombytes(fe *h, const u8 *s)
+{
+	fe_frombytes_impl(h->v, s);
+}
+
+static __always_inline u8 /*bool*/
+addcarryx_u25(u8 /*bool*/ c, u32 a, u32 b, u32 *low)
+{
+	/* This function extracts 25 bits of result and 1 bit of carry
+	 * (26 total), so a 32-bit intermediate is sufficient.
+	 */
+	u32 x = a + b + c;
+	*low = x & ((1 << 25) - 1);
+	return (x >> 25) & 1;
+}
+
+static __always_inline u8 /*bool*/
+addcarryx_u26(u8 /*bool*/ c, u32 a, u32 b, u32 *low)
+{
+	/* This function extracts 26 bits of result and 1 bit of carry
+	 * (27 total), so a 32-bit intermediate is sufficient.
+	 */
+	u32 x = a + b + c;
+	*low = x & ((1 << 26) - 1);
+	return (x >> 26) & 1;
+}
+
*** 4227 LINES SKIPPED ***