The branch stable/13 has been updated by kevans:

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

commit 919fc568b68f4f68fe897eacdce7fc34bc646fe5
Author:     Kyle Evans <[email protected]>
AuthorDate: 2022-10-29 03:05:14 +0000
Commit:     Kyle Evans <[email protected]>
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 <[email protected]>. 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 <[email protected]>. 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 <[email protected]>. 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 <[email protected]>. 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 <[email protected]>. 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 ***

Reply via email to