Add support for embedding WireGuard keys in a pcapng file
pcapng spec update is here: https://github.com/pcapng/pcapng/pull/62 Bug: 15571 Change-Id: I2f1921b1da70ac0bab8c38dd5138a9dfe7843fea Reviewed-on: https://code.wireshark.org/review/33300 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
parent
662ad82d60
commit
94b211977a
|
@ -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>.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Binary file not shown.
|
@ -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, [
|
||||
|
|
|
@ -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__ */
|
||||
|
|
Loading…
Reference in New Issue