aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--contrib/examples/extract-handshakes/.gitignore3
-rw-r--r--contrib/examples/extract-handshakes/Makefile28
-rw-r--r--contrib/examples/extract-handshakes/README20
-rwxr-xr-xcontrib/examples/extract-handshakes/extract-handshakes.sh80
-rw-r--r--contrib/examples/extract-handshakes/offset-finder.c44
6 files changed, 176 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 83768f6..4f9e9fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,4 @@ src/tests/qemu/distfiles/
*.nam
*.til
*.pro.user
+.cache.mk
diff --git a/contrib/examples/extract-handshakes/.gitignore b/contrib/examples/extract-handshakes/.gitignore
new file mode 100644
index 0000000..4196119
--- /dev/null
+++ b/contrib/examples/extract-handshakes/.gitignore
@@ -0,0 +1,3 @@
+offset-finder.o
+offset-finder
+offsets.include
diff --git a/contrib/examples/extract-handshakes/Makefile b/contrib/examples/extract-handshakes/Makefile
new file mode 100644
index 0000000..36e951e
--- /dev/null
+++ b/contrib/examples/extract-handshakes/Makefile
@@ -0,0 +1,28 @@
+ifeq ($(KERNELRELEASE),)
+KERNELDIR ?= /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+CFLAGS ?= -O3 -march=native
+CFLAGS += -Wall -pedantic -std=gnu11
+
+offsets.include: offset-finder
+ ./$^ > $@
+
+offset-finder: offset-finder.c offset-finder.o
+ $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $^
+
+offset-finder.o: offset-finder.c
+ $(MAKE) -C $(KERNELDIR) M=$(PWD) $@
+ objcopy -j '.rodata*' $@ $@
+
+clean:
+ rm -f offset-finder offsets.include
+ $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
+
+.PHONY: clean
+else
+offset-finder-m := offset-finder.o
+oldsrc := $(src)
+src := $(src)/../../../src
+include $(src)/compat/Kbuild.include
+src := $(oldsrc)
+endif
diff --git a/contrib/examples/extract-handshakes/README b/contrib/examples/extract-handshakes/README
new file mode 100644
index 0000000..1d030fa
--- /dev/null
+++ b/contrib/examples/extract-handshakes/README
@@ -0,0 +1,20 @@
+Handshake Extractor
+===================
+
+This will extract private keys from outgoing handshake sessions, prior
+to them being sent, via kprobes. It exports the bare minimum to be
+able to then decrypt all packets in the handshake and in the subsequent
+transport data session.
+
+Build:
+
+ $ make
+
+Run (as root):
+
+ # ./extract-handshakes.sh
+ New handshake session:
+ LOCAL_STATIC_PRIVATE_KEY = QChaGDXeH3eQsbFAhueUNWFdq9KfpF3yl+eITjZbXEk=
+ REMOTE_STATIC_PUBLIC_KEY = HzgTY6aWXtuSyW/PUquZtg8LB/DyMwEXGkPiEmdSsUU=
+ LOCAL_EPHEMERAL_PRIVATE_KEY = UNGdRHuKDeqbFvmiV5FD4wP7a8PqI6v3Xnnz6Jc6NXQ=
+ PRESHARED_KEY = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/contrib/examples/extract-handshakes/extract-handshakes.sh b/contrib/examples/extract-handshakes/extract-handshakes.sh
new file mode 100755
index 0000000..16ed630
--- /dev/null
+++ b/contrib/examples/extract-handshakes/extract-handshakes.sh
@@ -0,0 +1,80 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+# Copyright (C) 2017-2018 Peter Wu <peter@lekensteyn.nl>. All Rights Reserved.
+
+set -e
+
+ME_DIR="${BASH_SOURCE[0]}"
+ME_DIR="${ME_DIR%/*}"
+source "$ME_DIR/offsets.include" || { echo "Did you forget to run make?" >&2; exit 1; }
+
+case "$(uname -m)" in
+ x86_64) ARGUMENT_REGISTER="%si" ;;
+ i386|i686) ARGUMENT_REGISTER="%dx" ;;
+ aarch64) ARGUMENT_REGISTER="%x1" ;;
+ arm) ARGUMENT_REGISTER="%r1" ;;
+ *) echo "ERROR: Unknown architecture" >&2; exit 1 ;;
+esac
+
+ARGS=( )
+REGEX=".*: idxadd: .*"
+for key in "${!OFFSETS[@]}"; do
+ values="${OFFSETS[$key]}"
+ values=( ${values//,/ } )
+ for i in {0..3}; do
+ value="$ARGUMENT_REGISTER"
+ for indirection in "${values[@]:1}"; do
+ value="+$indirection($value)"
+ done
+ value="+$((i * 8 + values[0]))($value)"
+ ARGS+=( "${key,,}$i=$value:x64" )
+ REGEX="$REGEX ${key,,}$i=0x([0-9a-f]+)"
+ done
+done
+
+turn_off() {
+ set +e
+ [[ -f /sys/kernel/debug/tracing/events/wireguard/idxadd/enable ]] || exit
+ echo 0 > /sys/kernel/debug/tracing/events/wireguard/idxadd/enable
+ echo "-:wireguard/idxadd" >> /sys/kernel/debug/tracing/kprobe_events
+ exit
+}
+
+trap turn_off INT TERM EXIT
+echo "p:wireguard/idxadd index_hashtable_insert ${ARGS[*]}" >> /sys/kernel/debug/tracing/kprobe_events
+echo 1 > /sys/kernel/debug/tracing/events/wireguard/idxadd/enable
+
+unpack_u64() {
+ local i expanded="$1"
+ if [[ $ENDIAN == big ]]; then
+ printf -v expanded "%.*s$expanded" $((16 - ${#expanded})) 0000000000000000
+ for i in {0..7}; do
+ echo -n "\\x${expanded:(i * 2):2}"
+ done
+ elif [[ $ENDIAN == little ]]; then
+ (( ${#expanded} % 2 == 1 )) && expanded="0$expanded"
+ expanded="${expanded}0000000000000000"
+ for i in {0..7}; do
+ echo -n "\\x${expanded:((7 - i) * 2):2}"
+ done
+ else
+ echo "ERROR: Unable to determine endian" >&2
+ exit 1
+ fi
+}
+
+while read -r line; do
+ [[ $line =~ $REGEX ]] || continue
+ echo "New handshake session:"
+ j=1
+ for key in "${!OFFSETS[@]}"; do
+ bytes=""
+ for i in {0..3}; do
+ bytes="$bytes$(unpack_u64 "${BASH_REMATCH[j]}")"
+ ((++j))
+ done
+ echo " $key = $(printf "$bytes" | base64)"
+ done
+done < /sys/kernel/debug/tracing/trace_pipe
diff --git a/contrib/examples/extract-handshakes/offset-finder.c b/contrib/examples/extract-handshakes/offset-finder.c
new file mode 100644
index 0000000..d0bc69c
--- /dev/null
+++ b/contrib/examples/extract-handshakes/offset-finder.c
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ */
+
+struct def {
+ const char *name;
+ unsigned long offset;
+ unsigned long indirection_offset;
+};
+extern const struct def defs[];
+
+#ifdef __KERNEL__
+#include "../../../src/noise.h"
+
+const struct def defs[] = {
+ { "LOCAL_STATIC_PRIVATE_KEY", offsetof(struct noise_static_identity, static_private), offsetof(struct noise_handshake, static_identity) },
+ { "LOCAL_EPHEMERAL_PRIVATE_KEY", offsetof(struct noise_handshake, ephemeral_private), -1 },
+ { "REMOTE_STATIC_PUBLIC_KEY", offsetof(struct noise_handshake, remote_static), -1 },
+ { "PRESHARED_KEY", offsetof(struct noise_handshake, preshared_key), -1 },
+ { NULL, 0 }
+};
+#else
+#include <stdio.h>
+int main(int argc, char *argv[])
+{
+ puts("declare -A OFFSETS=(");
+ for (const struct def *def = defs; def->name; ++def) {
+ printf("\t[%s]=%ld", def->name, def->offset);
+ if (def->indirection_offset != -1)
+ printf(",%ld", def->indirection_offset);
+ putchar('\n');
+ }
+ puts(")");
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ puts("ENDIAN=big");
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ puts("ENDIAN=little");
+#else
+#error "Unsupported endianness"
+#endif
+ return 0;
+}
+#endif