aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/editcap.pod3
-rw-r--r--docbook/release-notes.adoc2
-rw-r--r--editcap.c3
-rw-r--r--epan/dissectors/file-pcapng.c3
-rw-r--r--epan/dissectors/packet-wireguard.c84
-rw-r--r--test/captures/wireguard-ping-tcp-dsb.pcapngbin0 -> 5912 bytes
-rw-r--r--test/suite_decryption.py25
-rw-r--r--wiretap/secrets-types.h1
8 files changed, 91 insertions, 30 deletions
diff --git a/doc/editcap.pod b/doc/editcap.pod
index 5c6c7ac8e0..3cb705ccb4 100644
--- a/doc/editcap.pod
+++ b/doc/editcap.pod
@@ -345,7 +345,8 @@ additional configuration in protocol preferences.
The file format is described by E<lt>secrets typeE<gt> which can be one of:
-I<tls> TLS Key Log as described at L<https://developer.mozilla.org/NSS_Key_Log_Format>
+I<tls> TLS Key Log as described at L<https://developer.mozilla.org/NSS_Key_Log_Format>
+I<wg> WireGuard Key Log, see L<https://wiki.wireshark.org/WireGuard#Key_Log_Format>
This option may be specified multiple times. The available options for
E<lt>secrets typeE<gt> can be listed with B<--inject-secrets help>.
diff --git a/docbook/release-notes.adoc b/docbook/release-notes.adoc
index a72a796fc5..870899835b 100644
--- a/docbook/release-notes.adoc
+++ b/docbook/release-notes.adoc
@@ -39,6 +39,8 @@ since version 3.0.0:
* Brotli decompression support in HTTP/HTTP2 (requires the brotli library).
* The build system now checks for a SpeexDSP system library installation. The
bundled Speex resampler code is still provided as a fallback.
+* WireGuard decryption can now be enabled through keys embedded in a pcapng in
+ addition to the existing key log preference (wsbuglink:15571[]).
// === Removed Features and Support
diff --git a/editcap.c b/editcap.c
index eb8c20bd9c..948bb4ac7d 100644
--- a/editcap.c
+++ b/editcap.c
@@ -180,7 +180,8 @@ static const struct {
const char *str;
guint32 id;
} secrets_types[] = {
- { "tls", SECRETS_TYPE_TLS },
+ { "tls", SECRETS_TYPE_TLS },
+ { "wg", SECRETS_TYPE_WIREGUARD },
};
static int find_dct2000_real_data(guint8 *buf);
diff --git a/epan/dissectors/file-pcapng.c b/epan/dissectors/file-pcapng.c
index c5a2e608fe..64700940e1 100644
--- a/epan/dissectors/file-pcapng.c
+++ b/epan/dissectors/file-pcapng.c
@@ -537,7 +537,8 @@ static const value_string flags_reception_type_vals[] = {
};
static const value_string dsb_secrets_types_vals[] = {
- { SECRETS_TYPE_TLS, "TLS Key Log" },
+ { SECRETS_TYPE_TLS, "TLS Key Log" },
+ { SECRETS_TYPE_WIREGUARD, "WireGuard Key Log" },
{ 0, NULL }
};
diff --git a/epan/dissectors/packet-wireguard.c b/epan/dissectors/packet-wireguard.c
index 6d60573cd6..bc236c2e9a 100644
--- a/epan/dissectors/packet-wireguard.c
+++ b/epan/dissectors/packet-wireguard.c
@@ -28,6 +28,8 @@
#include <wsutil/file_util.h>
#include <wsutil/wsgcrypt.h>
#include <wsutil/curve25519.h>
+#include <epan/secrets.h>
+#include <wiretap/secrets-types.h>
#if GCRYPT_VERSION_NUMBER >= 0x010800 /* 1.8.0 */
/* Decryption requires Curve25519, ChaCha20-Poly1305 (1.7) and Blake2s (1.8). */
@@ -649,6 +651,8 @@ wg_keylog_reset(void)
}
}
+static void wg_keylog_process_lines(const void *data, guint datalen);
+
static void
wg_keylog_read(void)
{
@@ -695,43 +699,67 @@ wg_keylog_read(void)
break;
}
- gsize bytes_read = strlen(buf);
- /* fgets includes the \n at the end of the line. */
- if (bytes_read > 0 && buf[bytes_read - 1] == '\n') {
- buf[bytes_read - 1] = 0;
- bytes_read--;
+ wg_keylog_process_lines((const guint8 *)buf, (guint)strlen(buf));
+ }
+}
+
+static void
+wg_keylog_process_lines(const void *data, guint datalen)
+{
+ const char *next_line = (const char *)data;
+ const char *line_end = next_line + datalen;
+ while (next_line && next_line < line_end) {
+ /* Note: line is NOT nul-terminated. */
+ const char *line = next_line;
+ next_line = (const char *)memchr(line, '\n', line_end - line);
+ gssize linelen;
+
+ if (next_line) {
+ linelen = next_line - line;
+ next_line++; /* drop LF */
+ } else {
+ linelen = (gssize)(line_end - line);
}
- if (bytes_read > 0 && buf[bytes_read - 1] == '\r') {
- buf[bytes_read - 1] = 0;
- bytes_read--;
+ if (linelen > 0 && line[linelen - 1] == '\r') {
+ linelen--; /* drop CR */
}
- g_debug("Read key log line: %s", buf);
+ g_debug("Read WG key log line: %.*s", (int)linelen, line);
/* Strip leading spaces. */
- char *p = buf;
- while (*p == ' ') {
+ const char *p = line;
+ while (p < line_end && *p == ' ') {
++p;
}
- const char *key_type = p;
- const char *key_value = NULL;
- p = strchr(p, '=');
- if (p && key_type != p) {
- key_value = p + 1;
- /* Strip '=' and spaces before it (after key type). */
- do {
- *p = '\0';
- --p;
- } while (*p == ' ');
- /* Strip spaces after '=' (before key value) */
- while (*key_value == ' ') {
- ++key_value;
+ char key_type[sizeof("LOCAL_EPHEMERAL_PRIVATE_KEY")];
+ char key_value[45] = { 0 };
+ const char *p0 = p;
+ p = (const char *)memchr(p0, '=', line_end - p);
+ if (p && p0 != p) {
+ /* Extract "key-type" from "key-type = key-value" */
+ gsize key_type_len = p - p0;
+ while (key_type_len && p0[key_type_len - 1] == ' ') {
+ --key_type_len;
+ }
+ if (key_type_len && key_type_len < sizeof(key_type)) {
+ memcpy(key_type, p0, key_type_len);
+ key_type[key_type_len] = '\0';
+
+ /* Skip '=' and any spaces. */
+ p = p + 1;
+ while (p < line_end && *p == ' ') {
+ ++p;
+ }
+ gsize key_value_len = (line + linelen) - p;
+ if (key_value_len && key_value_len < sizeof(key_value)) {
+ memcpy(key_value, p, key_value_len);
+ }
}
}
wg_qqword key;
- if (!key_value || !decode_base64_key(&key, key_value)) {
- g_debug("Unrecognized key log line: %s", buf);
+ if (!key_value[0] || !decode_base64_key(&key, key_value)) {
+ g_debug("Unrecognized key log line: %.*s", (int)linelen, line);
continue;
}
@@ -750,7 +778,7 @@ wg_keylog_read(void)
g_debug("Ignored PSK as no new ephemeral key was found");
}
} else {
- g_debug("Unrecognized key log line: %s", buf);
+ g_debug("Unrecognized key log line: %.*s", (int)linelen, line);
}
}
}
@@ -1857,6 +1885,8 @@ proto_register_wg(void)
g_warning("%s: decryption will not be possible due to lack of algorithms support", G_STRFUNC);
}
+ secrets_register_type(SECRETS_TYPE_WIREGUARD, wg_keylog_process_lines);
+
wg_ephemeral_keys = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_int_hash, wg_pubkey_equal);
#endif /* WG_DECRYPTION_SUPPORTED */
diff --git a/test/captures/wireguard-ping-tcp-dsb.pcapng b/test/captures/wireguard-ping-tcp-dsb.pcapng
new file mode 100644
index 0000000000..d15790f395
--- /dev/null
+++ b/test/captures/wireguard-ping-tcp-dsb.pcapng
Binary files differ
diff --git a/test/suite_decryption.py b/test/suite_decryption.py
index 68f189588a..06cca6367e 100644
--- a/test/suite_decryption.py
+++ b/test/suite_decryption.py
@@ -723,6 +723,31 @@ class case_decrypt_wireguard(subprocesstest.SubprocessTestCase):
self.assertIn('17\t\t\t\t\t\t443', lines)
self.assertIn('18\t\t\t\t\t\t49472', lines)
+ def test_decrypt_wg_full_initiator_dsb(self, run_wireguard_test):
+ """
+ Similar to test_decrypt_full_initiator, but using decryption keys
+ embedded in the pcapng file. The embedded secrets do not contain leading
+ spaces nor spaces around the '=' character.
+ """
+ lines = run_wireguard_test(self, [
+ '-Tfields',
+ '-e', 'frame.number',
+ '-e', 'wg.ephemeral.known_privkey',
+ '-e', 'wg.static',
+ '-e', 'wg.timestamp.nanoseconds',
+ '-e', 'wg.handshake_ok',
+ '-e', 'icmp.type',
+ '-e', 'tcp.dstport',
+ ], pcap_file='wireguard-ping-tcp-dsb.pcapng')
+ self.assertIn('1\t1\t%s\t%s\t\t\t' % (self.key_Spub_i, '356537872'), lines)
+ self.assertIn('2\t0\t\t\t1\t\t', lines)
+ self.assertIn('3\t\t\t\t\t8\t', lines)
+ self.assertIn('4\t\t\t\t\t0\t', lines)
+ self.assertIn('13\t1\t%s\t%s\t\t\t' % (self.key_Spub_i, '490514356'), lines)
+ self.assertIn('14\t0\t\t\t1\t\t', lines)
+ self.assertIn('17\t\t\t\t\t\t443', lines)
+ self.assertIn('18\t\t\t\t\t\t49472', lines)
+
def test_decrypt_full_responder(self, run_wireguard_test):
"""Check for full handshake decryption using responder secrets."""
lines = run_wireguard_test(self, [
diff --git a/wiretap/secrets-types.h b/wiretap/secrets-types.h
index 513b901286..5b1b774f90 100644
--- a/wiretap/secrets-types.h
+++ b/wiretap/secrets-types.h
@@ -15,5 +15,6 @@
* Type describing the format of the opaque secrets value in a pcapng DSB.
*/
#define SECRETS_TYPE_TLS 0x544c534b /* TLS Key Log */
+#define SECRETS_TYPE_WIREGUARD 0x57474b4c /* WireGuard Key Log */
#endif /* __SECRETS_TYPES_H__ */