summaryrefslogtreecommitdiffstats
path: root/ui/ssl_key_export.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /ui/ssl_key_export.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ui/ssl_key_export.c')
-rw-r--r--ui/ssl_key_export.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/ui/ssl_key_export.c b/ui/ssl_key_export.c
new file mode 100644
index 00000000..fe72a75d
--- /dev/null
+++ b/ui/ssl_key_export.c
@@ -0,0 +1,173 @@
+/* export_sslkeys.c
+ *
+ * Export SSL Session Keys dialog
+ * by Sake Blok <sake@euronet.nl> (20110526)
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <glib.h>
+
+#include <epan/address.h>
+#include <epan/dissectors/packet-tls-utils.h>
+
+#include <wiretap/secrets-types.h>
+
+#include "ui/ssl_key_export.h"
+
+int
+ssl_session_key_count(void)
+{
+ int count = 0;
+ ssl_master_key_map_t *mk_map = tls_get_master_key_map(FALSE);
+ if (!mk_map)
+ return count;
+
+ GHashTableIter iter;
+ gpointer key;
+
+ g_hash_table_iter_init(&iter, mk_map->used_crandom);
+ while (g_hash_table_iter_next(&iter, &key, NULL)) {
+ if (g_hash_table_contains(mk_map->crandom, key)) {
+ count++;
+ }
+ if (g_hash_table_contains(mk_map->tls13_client_early, key)) {
+ count++;
+ }
+ if (g_hash_table_contains(mk_map->tls13_client_handshake, key)) {
+ count++;
+ }
+ if (g_hash_table_contains(mk_map->tls13_server_handshake, key)) {
+ count++;
+ }
+ if (g_hash_table_contains(mk_map->tls13_client_appdata, key)) {
+ count++;
+ }
+ if (g_hash_table_contains(mk_map->tls13_server_appdata, key)) {
+ count++;
+ }
+ }
+ return count;
+}
+
+static void
+tls_export_client_randoms_func(gpointer key, gpointer value, gpointer user_data, const char* label)
+{
+ guint i;
+ StringInfo *client_random = (StringInfo *)key;
+ StringInfo *master_secret = (StringInfo *)value;
+ GString *keylist = (GString *)user_data;
+
+ g_string_append(keylist, label);
+
+ for (i = 0; i < client_random->data_len; i++) {
+ g_string_append_printf(keylist, "%.2x", client_random->data[i]);
+ }
+
+ g_string_append_c(keylist, ' ');
+
+ for (i = 0; i < master_secret->data_len; i++) {
+ g_string_append_printf(keylist, "%.2x", master_secret->data[i]);
+ }
+
+ g_string_append_c(keylist, '\n');
+}
+
+gchar*
+ssl_export_sessions(gsize *length)
+{
+ /* Output format is:
+ * "CLIENT_RANDOM zzzz yyyy\n"
+ * Where zzzz is the client random (always 64 chars)
+ * Where yyyy is same as above
+ * So length will always be 13+1+64+1+96+2 = 177 chars
+ *
+ * Wireshark can read CLIENT_RANDOM since v1.8.0.
+ * Both values are exported in case you use the Session-ID for resuming a
+ * session in a different capture.
+ *
+ * TLS 1.3 derived secrets are similar to the CLIENT_RANDOM master secret
+ * export, but with a (longer) label indicating the type of derived secret
+ * to which the client random maps, e.g.
+ * "CLIENT_HANDSHAKE_TRAFFIC_SECRET zzzz yyyy\n"
+ *
+ * The TLS 1.3 values are obtained from an existing key log, but exporting
+ * them is useful in order to filter actually used secrets or add a DSB.
+ */
+ ssl_master_key_map_t *mk_map = tls_get_master_key_map(FALSE);
+
+ if (!mk_map) {
+ *length = 0;
+ return g_strdup("");
+ }
+
+ gsize len = 177 * (gsize)ssl_session_key_count();
+ GString *keylist = g_string_sized_new(len);
+
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init(&iter, mk_map->used_crandom);
+ while (g_hash_table_iter_next(&iter, &key, NULL)) {
+ if ((value = g_hash_table_lookup(mk_map->crandom, key))) {
+ tls_export_client_randoms_func(key, value, (gpointer)keylist, "CLIENT_RANDOM ");
+ }
+ if ((value = g_hash_table_lookup(mk_map->tls13_client_early, key))) {
+ tls_export_client_randoms_func(key, value, (gpointer)keylist, "CLIENT_EARLY_TRAFFIC_SECRET ");
+ }
+ if ((value = g_hash_table_lookup(mk_map->tls13_client_handshake, key))) {
+ tls_export_client_randoms_func(key, value, (gpointer)keylist, "CLIENT_HANDSHAKE_TRAFFIC_SECRET ");
+ }
+ if ((value = g_hash_table_lookup(mk_map->tls13_server_handshake, key))) {
+ tls_export_client_randoms_func(key, value, (gpointer)keylist, "SERVER_HANDSHAKE_TRAFFIC_SECRET ");
+ }
+ if ((value = g_hash_table_lookup(mk_map->tls13_server_appdata, key))) {
+ tls_export_client_randoms_func(key, value, (gpointer)keylist, "SERVER_TRAFFIC_SECRET_0 ");
+ }
+ if ((value = g_hash_table_lookup(mk_map->tls13_client_appdata, key))) {
+ tls_export_client_randoms_func(key, value, (gpointer)keylist, "CLIENT_TRAFFIC_SECRET_0 ");
+ }
+#if 0
+ /* We don't use the EARLY_EXPORT_SECRET or EXPORTER_SECRET now so don't
+ export, but we may in the future. */
+ if ((value = g_hash_table_lookup(mk_map->tls13_early_exporter, key))) {
+ tls_export_client_randoms_func(key, value, (gpointer)keylist, "EARLY_EXPORTER_SECRET ");
+ }
+ if ((value = g_hash_table_lookup(mk_map->tls13_exporter, key))) {
+ tls_export_client_randoms_func(key, value, (gpointer)keylist, "EXPORTER_SECRET ");
+ }
+#endif
+ }
+
+ *length = keylist->len;
+ return g_string_free(keylist, FALSE);
+}
+
+void
+tls_export_dsb(capture_file *cf)
+{
+ wtap_block_t block;
+ wtapng_dsb_mandatory_t *dsb;
+ size_t secrets_len;
+ char* secrets = ssl_export_sessions(&secrets_len);
+
+ block = wtap_block_create(WTAP_BLOCK_DECRYPTION_SECRETS);
+ dsb = (wtapng_dsb_mandatory_t *)wtap_block_get_mandatory_data(block);
+
+ dsb->secrets_type = SECRETS_TYPE_TLS;
+ dsb->secrets_data = g_memdup2(secrets, secrets_len);
+ dsb->secrets_len = (guint)secrets_len;
+
+ /* XXX - support replacing the DSB of the same type instead of adding? */
+ wtap_file_add_decryption_secrets(cf->provider.wth, block);
+ /* Mark the file as having unsaved changes */
+ cf->unsaved_changes = TRUE;
+
+ return;
+}