diff options
Diffstat (limited to 'ui/ssl_key_export.c')
-rw-r--r-- | ui/ssl_key_export.c | 173 |
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 0000000..fe72a75 --- /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; +} |