aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2019-01-17 17:52:52 +0100
committerPeter Wu <peter@lekensteyn.nl>2019-01-17 21:33:25 +0000
commitcbe7f26a86c2d24e3525bdea9faa3b2b307d8c95 (patch)
treeae40757d75a0e9a86246bbc6cea73fbd406c1525
parentcda1a591e9a835f626aacc0843a71bc6f25ce13b (diff)
DTLS: add DSB support, use the key log file from the TLS dissector
The DTLS and TLS dissectors already share code for parsing the key log file contents but the actual key material was stored separately. As implementations (like GnuTLS) write the TLS and DTLS secrets to the same file (specified by the SSLKEYLOGFILE environment variable), it seems reasonable to combine them. This also enables use of the pcapng Decryption Secrets Block for decryption of DTLS traces. The dtls.keylog_file preference has become obsolete and can no longer be used (this was not tested anyway). A new test was added based on dtls12-aes128ccm8.pcap, the master secret was extracted using the tls.debug_file preference. Bug: 15252 Change-Id: Idfd52c251da966fe111dea37bc3fb143d968f744 Reviewed-on: https://code.wireshark.org/review/31577 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot Reviewed-by: Stig Bjørlykke <stig@bjorlykke.org> Reviewed-by: Peter Wu <peter@lekensteyn.nl>
-rw-r--r--docbook/release-notes.asciidoc2
-rw-r--r--epan/dissectors/packet-dtls.c22
-rw-r--r--epan/dissectors/packet-tls-utils.c10
-rw-r--r--epan/dissectors/packet-tls-utils.h10
-rw-r--r--epan/dissectors/packet-tls.c12
-rw-r--r--test/captures/dtls12-aes128ccm8-dsb.pcapngbin0 -> 2044 bytes
-rw-r--r--test/suite_decryption.py10
7 files changed, 48 insertions, 18 deletions
diff --git a/docbook/release-notes.asciidoc b/docbook/release-notes.asciidoc
index e66cde25f7..4b5460cf67 100644
--- a/docbook/release-notes.asciidoc
+++ b/docbook/release-notes.asciidoc
@@ -74,7 +74,7 @@ since version 2.6.0:
* The build system now supports AppImage packages.
* The Windows installers now ship with Qt 5.12.0. Previously they
shipped with Qt 5.9.7.
-* Support for decrypting TLS streams in pcapng files that embedded a Decryption
+* Support for DTLS and TLS decryption using pcapng files that embed a Decryption
Secrets Block (DSB) containing a TLS Key Log (wsbuglink:15252[]).
* The editcap utility gained a new `--inject-secrets` option to inject an
existing TLS Key Log file into a pcapng file.
diff --git a/epan/dissectors/packet-dtls.c b/epan/dissectors/packet-dtls.c
index 9c3154ec5f..e7f6c117a6 100644
--- a/epan/dissectors/packet-dtls.c
+++ b/epan/dissectors/packet-dtls.c
@@ -147,7 +147,6 @@ static expert_field ei_dtls_handshake_fragment_past_end_msg = EI_INIT;
static expert_field ei_dtls_msg_len_diff_fragment = EI_INIT;
static expert_field ei_dtls_heartbeat_payload_length = EI_INIT;
-static ssl_master_key_map_t dtls_master_key_map;
#ifdef HAVE_LIBGNUTLS
static GHashTable *dtls_key_hash = NULL;
static wmem_stack_t *key_list_stack = NULL;
@@ -160,7 +159,6 @@ static dissector_handle_t dtls_handle = NULL;
static StringInfo dtls_compressed_data = {NULL, 0};
static StringInfo dtls_decrypted_data = {NULL, 0};
static gint dtls_decrypted_data_avail = 0;
-static FILE *dtls_keylog_file = NULL;
static ssl_common_options_t dtls_options = { NULL, NULL};
static const gchar *dtls_debug_file_name = NULL;
@@ -199,8 +197,8 @@ dtls_init(void)
module_t *dtls_module = prefs_find_module("dtls");
pref_t *keys_list_pref;
- ssl_common_init(&dtls_master_key_map,
- &dtls_decrypted_data, &dtls_compressed_data);
+ ssl_data_alloc(&dtls_decrypted_data, 32);
+ ssl_data_alloc(&dtls_compressed_data, 32);
/* We should have loaded "keys_list" by now. Mark it obsolete */
if (dtls_module) {
@@ -220,8 +218,8 @@ dtls_cleanup(void)
key_list_stack = NULL;
}
#endif
- ssl_common_cleanup(&dtls_master_key_map, &dtls_keylog_file,
- &dtls_decrypted_data, &dtls_compressed_data);
+ g_free(dtls_decrypted_data.data);
+ g_free(dtls_compressed_data.data);
}
#ifdef HAVE_LIBGNUTLS
@@ -787,9 +785,7 @@ dissect_dtls_record(tvbuff_t *tvb, packet_info *pinfo,
dtls_record_tree, offset, session,
is_from_server, ssl);
if (ssl) {
- ssl_load_keyfile(dtls_options.keylog_filename, &dtls_keylog_file,
- &dtls_master_key_map);
- ssl_finalize_decryption(ssl, &dtls_master_key_map);
+ ssl_finalize_decryption(ssl, tls_get_master_key_map(TRUE));
ssl_change_cipher(ssl, ssl_packet_from_server(session, dtls_associations, pinfo));
}
/* Heuristic: any later ChangeCipherSpec is not a resumption of this
@@ -1301,7 +1297,7 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
* master key with this Session Ticket */
ssl_dissect_hnd_new_ses_ticket(&dissect_dtls_hf, sub_tvb, pinfo,
ssl_hand_tree, 0, length, session, ssl, TRUE,
- dtls_master_key_map.tickets);
+ tls_get_master_key_map(FALSE)->tickets);
break;
case SSL_HND_HELLO_RETRY_REQUEST:
@@ -1336,15 +1332,13 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
if (!ssl)
break;
- ssl_load_keyfile(dtls_options.keylog_filename, &dtls_keylog_file,
- &dtls_master_key_map);
/* try to find master key from pre-master key */
if (!ssl_generate_pre_master_secret(ssl, length, sub_tvb, 0,
dtls_options.psk,
#ifdef HAVE_LIBGNUTLS
dtls_key_hash,
#endif
- &dtls_master_key_map)) {
+ tls_get_master_key_map(TRUE))) {
ssl_debug_printf("dissect_dtls_handshake can't generate pre master secret\n");
}
break;
@@ -2000,7 +1994,7 @@ proto_register_dtls(void)
"redirect dtls debug to file name; leave empty to disable debug, "
"use \"" SSL_DEBUG_USE_STDERR "\" to redirect output to stderr\n",
&dtls_debug_file_name, TRUE);
- ssl_common_register_options(dtls_module, &dtls_options);
+ ssl_common_register_options(dtls_module, &dtls_options, TRUE);
}
dtls_handle = register_dissector("dtls", dissect_dtls, proto_dtls);
diff --git a/epan/dissectors/packet-tls-utils.c b/epan/dissectors/packet-tls-utils.c
index ccccb57864..9ce8db407b 100644
--- a/epan/dissectors/packet-tls-utils.c
+++ b/epan/dissectors/packet-tls-utils.c
@@ -9002,12 +9002,20 @@ ssl_common_register_dtls_alpn_dissector_table(const char *name,
}
void
-ssl_common_register_options(module_t *module, ssl_common_options_t *options)
+ssl_common_register_options(module_t *module, ssl_common_options_t *options, gboolean is_dtls)
{
prefs_register_string_preference(module, "psk", "Pre-Shared-Key",
"Pre-Shared-Key as HEX string. Should be 0 to 16 bytes.",
&(options->psk));
+ if (is_dtls) {
+ prefs_register_obsolete_preference(module, "keylog_file");
+ prefs_register_static_text_preference(module, "keylog_file_removed",
+ "The (Pre)-Master-Secret log filename preference can be configured in the TLS protocol preferences.",
+ "Use the TLS protocol preference to configure the keylog file for both DTLS and TLS.");
+ return;
+ }
+
prefs_register_filename_preference(module, "keylog_file", "(Pre)-Master-Secret log filename",
"The name of a file which contains a list of \n"
"(pre-)master secrets in one of the following formats:\n"
diff --git a/epan/dissectors/packet-tls-utils.h b/epan/dissectors/packet-tls-utils.h
index 4a77099c77..e08da9f67e 100644
--- a/epan/dissectors/packet-tls-utils.h
+++ b/epan/dissectors/packet-tls-utils.h
@@ -640,6 +640,14 @@ extern void
ssl_common_cleanup(ssl_master_key_map_t *master_key_map, FILE **ssl_keylog_file,
StringInfo *decrypted_data, StringInfo *compressed_data);
+/**
+ * Access to the keys in the TLS dissector, for use by the DTLS dissector.
+ * (This is a transition function, it would be nice if the static keylog file
+ * contents was separated from keys derived at runtime.)
+ */
+extern ssl_master_key_map_t *
+tls_get_master_key_map(gboolean load_secrets);
+
/* Process lines from the TLS key log and populate the secrets map. */
extern void
tls_keylog_process_lines(const ssl_master_key_map_t *mk_map, const guint8 *data, guint len);
@@ -2110,7 +2118,7 @@ ssl_common_register_dtls_alpn_dissector_table(const char *name,
const char *ui_name, const int proto);
extern void
-ssl_common_register_options(module_t *module, ssl_common_options_t *options);
+ssl_common_register_options(module_t *module, ssl_common_options_t *options, gboolean is_dtls);
#ifdef SSL_DECRYPT_DEBUG
extern void
diff --git a/epan/dissectors/packet-tls.c b/epan/dissectors/packet-tls.c
index ae71fac802..36e82ea51b 100644
--- a/epan/dissectors/packet-tls.c
+++ b/epan/dissectors/packet-tls.c
@@ -310,6 +310,16 @@ ssl_cleanup(void)
ssl_crandom_hash = NULL;
}
+ssl_master_key_map_t *
+tls_get_master_key_map(gboolean load_secrets)
+{
+ // Try to load new keys.
+ if (load_secrets) {
+ ssl_load_keyfile(ssl_options.keylog_filename, &ssl_keylog_file, &ssl_master_key_map);
+ }
+ return &ssl_master_key_map;
+}
+
#ifdef HAVE_LIBGNUTLS
/* parse ssl related preferences (private keys and ports association strings) */
static void
@@ -4160,7 +4170,7 @@ proto_register_tls(void)
"Message Authentication Code (MAC), ignore \"mac failed\"",
"For troubleshooting ignore the mac check result and decrypt also if the Message Authentication Code (MAC) fails.",
&tls_ignore_mac_failed);
- ssl_common_register_options(ssl_module, &ssl_options);
+ ssl_common_register_options(ssl_module, &ssl_options, FALSE);
}
/* heuristic dissectors for any premable e.g. CredSSP before RDP */
diff --git a/test/captures/dtls12-aes128ccm8-dsb.pcapng b/test/captures/dtls12-aes128ccm8-dsb.pcapng
new file mode 100644
index 0000000000..9a9bf4e519
--- /dev/null
+++ b/test/captures/dtls12-aes128ccm8-dsb.pcapng
Binary files differ
diff --git a/test/suite_decryption.py b/test/suite_decryption.py
index 1cbdaf33bb..a282069d7e 100644
--- a/test/suite_decryption.py
+++ b/test/suite_decryption.py
@@ -107,6 +107,16 @@ class case_decrypt_dtls(subprocesstest.SubprocessTestCase):
wfm_count = self.countOutput('Works for me!.')
self.assertTrue(dt_count == 7 and wfm_count == 2)
+ def test_dtls_dsb_aes128ccm8(self, cmd_tshark, capture_file):
+ '''DTLS 1.2 with master secrets in a pcapng Decryption Secrets Block.'''
+ self.assertRun((cmd_tshark,
+ '-r', capture_file('dtls12-aes128ccm8-dsb.pcapng'),
+ '-x'
+ ))
+ dt_count = self.countOutput('Decrypted DTLS')
+ wfm_count = self.countOutput('Works for me!.')
+ self.assertTrue(dt_count == 7 and wfm_count == 2)
+
def test_dtls_udt(self, cmd_tshark, dirs, capture_file, features):
'''UDT over DTLS 1.2 with RSA key'''
if not features.have_gnutls: