aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/contrib
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2016-08-24 17:44:41 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2016-08-26 04:52:50 +0200
commit7234d7339f570be46b3d916fd7d2561b970b68e8 (patch)
treec9edbcceaf07da2718923c8c9ca48c8cd1f3ef22 /contrib
parentexamples: add nat-hole-punching (diff)
downloadwireguard-monolithic-historical-7234d7339f570be46b3d916fd7d2561b970b68e8.tar.xz
wireguard-monolithic-historical-7234d7339f570be46b3d916fd7d2561b970b68e8.zip
examples: add key extractor
Diffstat (limited to 'contrib')
-rw-r--r--contrib/examples/extract-keys/Makefile27
-rw-r--r--contrib/examples/extract-keys/README23
-rw-r--r--contrib/examples/extract-keys/config.c32
-rw-r--r--contrib/examples/extract-keys/extract-keys.c139
4 files changed, 221 insertions, 0 deletions
diff --git a/contrib/examples/extract-keys/Makefile b/contrib/examples/extract-keys/Makefile
new file mode 100644
index 0000000..a1dd7a2
--- /dev/null
+++ b/contrib/examples/extract-keys/Makefile
@@ -0,0 +1,27 @@
+ifeq ($(KERNELRELEASE),)
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+CFLAGS ?= -O3 -march=native
+CFLAGS += -Wall -pedantic -std=gnu11
+
+extract-keys: extract-keys.c config.h
+ $(CC) $(CFLAGS) $(CPPFLAGS) -D_FILE_OFFSET_BITS=64 -o $@ -lresolv $<
+
+config.o: config.c
+ $(MAKE) -C $(KERNELDIR) M=$(PWD) $@
+ objcopy -j '.rodata*' $@ $@
+
+config: config.c config.o
+ $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $^
+
+config.h: config
+ ./$< > $@
+
+clean:
+ rm -f extract-keys config config.h
+ $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
+
+.PHONY: clean
+else
+config-m := config.o
+endif
diff --git a/contrib/examples/extract-keys/README b/contrib/examples/extract-keys/README
new file mode 100644
index 0000000..a91363d
--- /dev/null
+++ b/contrib/examples/extract-keys/README
@@ -0,0 +1,23 @@
+Key Extractor
+=============
+
+This will extract the symmetric ChaCha20Poly1305 session keys from the kernel
+for a WireGuard interface, for use in making packet dissectors.
+
+
+Build:
+ $ make
+
+Run (as root):
+ # ./extract-keys INTERFACE
+
+Output:
+ REMOTE_KEY_ID SENDING_KEY
+ LOCAL_KEY_ID RECEIVING_KEY
+
+Example:
+ # ./extract-keys wg0
+ 0x57b56068 tMTSEOJpEYFAQV2UviDiYooX0A1AD/ONqrzoQVHa1rQ=
+ 0xa182fd19 xvQSkQ5HTX5RUeJ74eAAb/xfNhdrDThxG91GXZIPKmY=
+ 0x01662508 LbMc84JULzXJiHotSkdSOPZ0bHh6IDwOrbxWLfwosTs=
+ 0xbd819021 4VA8lZ3I1HjnJcWTmhEzBdC92W1Aag9Lnyy2GkroOYI=
diff --git a/contrib/examples/extract-keys/config.c b/contrib/examples/extract-keys/config.c
new file mode 100644
index 0000000..0dc4841
--- /dev/null
+++ b/contrib/examples/extract-keys/config.c
@@ -0,0 +1,32 @@
+struct def {
+ const char *name;
+ long long value;
+};
+extern const struct def defs[];
+
+#ifdef __KERNEL__
+#include "../../../src/wireguard.h"
+const struct def defs[] = {
+ { "SOCK_DEVICE_OFFSET", offsetof(struct sock, sk_user_data) },
+ { "DEVICE_NAME_OFFSET", -ALIGN(sizeof(struct net_device), NETDEV_ALIGN) + offsetof(struct net_device, name) },
+ { "IFNAMSIZ", IFNAMSIZ },
+ { "DEVICE_PEERS_OFFSET", offsetof(struct wireguard_device, peer_list) },
+ { "PEERS_PEER_OFFSET", -offsetof(struct wireguard_peer, peer_list) },
+ { "PEER_CURRENTKEY_OFFSET", offsetof(struct wireguard_peer, keypairs.current_keypair) },
+ { "PEER_PREVIOUSKEY_OFFSET", offsetof(struct wireguard_peer, keypairs.previous_keypair) },
+ { "PEER_NEXTKEY_OFFSET", offsetof(struct wireguard_peer, keypairs.next_keypair) },
+ { "KEY_LOCALID_OFFSET", offsetof(struct noise_keypair, entry.index) },
+ { "KEY_REMOTEID_OFFSET", offsetof(struct noise_keypair, remote_index) },
+ { "KEY_SENDING_OFFSET", offsetof(struct noise_keypair, sending.key) },
+ { "KEY_RECEIVING_OFFSET", offsetof(struct noise_keypair, receiving.key) },
+ { NULL, 0 }
+};
+#else
+#include <stdio.h>
+int main(int argc, char *argv[])
+{
+ for (const struct def *def = defs; def->name; ++def)
+ printf("#define %s %lld\n", def->name, def->value);
+ return 0;
+}
+#endif
diff --git a/contrib/examples/extract-keys/extract-keys.c b/contrib/examples/extract-keys/extract-keys.c
new file mode 100644
index 0000000..5d7de32
--- /dev/null
+++ b/contrib/examples/extract-keys/extract-keys.c
@@ -0,0 +1,139 @@
+#include <endian.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <resolv.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "config.h"
+
+static int fd;
+
+static void open_kmem(void)
+{
+ fd = open("/dev/kmem", O_RDONLY);
+ if (fd < 0) {
+ perror("open(/dev/kmem)");
+ exit(errno);
+ }
+}
+
+static void read_kmem(void *buffer, size_t len, unsigned long addr)
+{
+ if (lseek(fd, addr, SEEK_SET) == (off_t)-1) {
+ perror("lseek");
+ exit(errno);
+ }
+ if (read(fd, buffer, len) != len) {
+ perror("read");
+ exit(errno);
+ }
+}
+
+static inline unsigned int read_int(unsigned long addr)
+{
+ unsigned int ret;
+ read_kmem(&ret, sizeof(ret), addr);
+ return ret;
+}
+
+static inline unsigned long read_long(unsigned long addr)
+{
+ unsigned long ret;
+ read_kmem(&ret, sizeof(ret), addr);
+ return ret;
+}
+
+static unsigned long find_interface(const char *interface)
+{
+ FILE *f = fopen("/proc/net/udp", "r");
+ char line[256], *ptr;
+ unsigned long addr = 0;
+ char name[IFNAMSIZ + 1] = { 0 };
+
+ if (!f) {
+ perror("fopen(/proc/net/udp)");
+ exit(errno);
+ }
+ if (!fgets(line, 256, f))
+ goto out;
+ while (fgets(line, 256, f)) {
+ ptr = line + strlen(line) - 1;
+ while (*--ptr == ' ');
+ while (*--ptr != ' ');
+ while (*(--ptr - 1) != ' ');
+ addr = strtoul(ptr, NULL, 16);
+ if (!addr)
+ continue;
+ addr = read_long(addr + SOCK_DEVICE_OFFSET);
+ if (!addr)
+ continue;
+ read_kmem(name, IFNAMSIZ, addr + DEVICE_NAME_OFFSET);
+ if (!strcmp(name, interface))
+ goto out;
+ }
+ addr = 0;
+out:
+ fclose(f);
+ return addr;
+}
+
+static bool print_key(unsigned long key)
+{
+ unsigned char sending[32], receiving[32];
+ char sending_b64[45], receiving_b64[45];
+ unsigned int local_index, remote_index;
+
+ if (!key)
+ return false;
+
+ local_index = le32toh(read_int(key + KEY_LOCALID_OFFSET));
+ remote_index = le32toh(read_int(key + KEY_REMOTEID_OFFSET));
+ read_kmem(sending, 32, key + KEY_SENDING_OFFSET);
+ read_kmem(receiving, 32, key + KEY_RECEIVING_OFFSET);
+
+ b64_ntop(sending, 32, sending_b64, 45);
+ b64_ntop(receiving, 32, receiving_b64, 45);
+
+ printf("0x%08x %s\n", local_index, receiving_b64);
+ printf("0x%08x %s\n", remote_index, sending_b64);
+ return true;
+}
+
+static bool walk_peers(unsigned long peer_head)
+{
+ unsigned long peer, peer_entry;
+ bool found = false;
+ for (peer_entry = read_long(peer_head); peer_entry != peer_head; peer_entry = read_long(peer_entry)) {
+ peer = peer_entry + PEERS_PEER_OFFSET;
+ if (print_key(read_long(peer + PEER_CURRENTKEY_OFFSET)))
+ found = true;
+ if (print_key(read_long(peer + PEER_PREVIOUSKEY_OFFSET)))
+ found = true;
+ if (print_key(read_long(peer + PEER_NEXTKEY_OFFSET)))
+ found = true;
+ }
+ return found;
+}
+
+int main(int argc, char *argv[])
+{
+ unsigned long wireguard_device;
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s WIREGUARD_INTERFACE\n", argv[0]);
+ return EINVAL;
+ }
+ open_kmem();
+ wireguard_device = find_interface(argv[1]);
+ if (!wireguard_device) {
+ fprintf(stderr, "Could not find interface %s\n", argv[1]);
+ return EBADSLT;
+ }
+ if (!walk_peers(wireguard_device + DEVICE_PEERS_OFFSET)) {
+ fprintf(stderr, "No active sessions\n");
+ return ENOKEY;
+ }
+ return 0;
+}