summaryrefslogtreecommitdiff
path: root/epan
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2017-01-30 14:29:12 +0100
committerAnders Broman <a.broman58@gmail.com>2017-01-31 04:47:15 +0000
commit93e71032418045884280c7d081da2d6c0030985c (patch)
tree127971bfbf4b2ce280a161a44969bde9474bedf8 /epan
parent17b98fe759be92019af9b870b0f1bc00f0337972 (diff)
downloadwireshark-93e71032418045884280c7d081da2d6c0030985c.tar.gz
TLS: add bare essentials for TLS 1.3 decryption support
The bare essentials are now in place to perform decryption (HKDF-Expand-Label, calculation of traffic secrets, AEAD integration). Can successfully decrypt the initial handshake message. Only AES ciphers are supported, ChaCha20-Poly1305 still needs to be added. Note: "decryption" indeed works, but dissection needs to be updated. The padding must be stripped and the content type extracted. Ping-Bug: 12779 Change-Id: I3869c9ae5131e57519be99c5f439c4fa68841bae Reviewed-on: https://code.wireshark.org/review/19858 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'epan')
-rw-r--r--epan/dissectors/packet-ssl-utils.c285
-rw-r--r--epan/dissectors/packet-ssl-utils.h19
-rw-r--r--epan/dissectors/packet-ssl.c12
3 files changed, 310 insertions, 6 deletions
diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c
index 525878f6c4..2a2b07086b 100644
--- a/epan/dissectors/packet-ssl-utils.c
+++ b/epan/dissectors/packet-ssl-utils.c
@@ -2185,6 +2185,14 @@ static const SslCipherSuite cipher_suites[]={
{0x00C3,KEX_DHE_DSS, ENC_CAMELLIA256,DIG_SHA256, MODE_CBC }, /* TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 */
{0x00C4,KEX_DHE_RSA, ENC_CAMELLIA256,DIG_SHA256, MODE_CBC }, /* TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 */
{0x00C5,KEX_DH_ANON, ENC_CAMELLIA256,DIG_SHA256, MODE_CBC }, /* TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 */
+
+ /* NOTE: TLS 1.3 cipher suites are incompatible with TLS 1.2. */
+ {0x1301,KEX_TLS13, ENC_AES, DIG_SHA256, MODE_GCM }, /* TLS_AES_128_GCM_SHA256 */
+ {0x1302,KEX_TLS13, ENC_AES256, DIG_SHA384, MODE_GCM }, /* TLS_AES_256_GCM_SHA384 */
+ /* TODO TLS_CHACHA20_POLY1305_SHA256 */
+ {0x1304,KEX_TLS13, ENC_AES, DIG_SHA256, MODE_CCM }, /* TLS_AES_128_CCM_SHA256 */
+ {0x1305,KEX_TLS13, ENC_AES, DIG_SHA256, MODE_CCM_8 }, /* TLS_AES_128_CCM_8_SHA256 */
+
{0xC001,KEX_ECDH_ECDSA, ENC_NULL, DIG_SHA, MODE_STREAM}, /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
{0xC002,KEX_ECDH_ECDSA, ENC_RC4, DIG_SHA, MODE_STREAM}, /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
{0xC003,KEX_ECDH_ECDSA, ENC_3DES, DIG_SHA, MODE_CBC }, /* TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA */
@@ -2673,6 +2681,70 @@ static gint tls12_handshake_hash(SslDecryptSession* ssl, gint md, StringInfo* ou
memcpy(out->data, tmp, len);
return 0;
}
+
+static gboolean
+tls13_hkdf_expand_label(int md, const StringInfo *secret, const char *label, const char *hash_value,
+ guint16 out_len, guchar **out)
+{
+ /* draft-ietf-tls-tls13-18:
+ * HKDF-Expand-Label(Secret, Label, HashValue, Length) =
+ * HKDF-Expand(Secret, HkdfLabel, Length)
+ * struct {
+ * uint16 length = Length;
+ * opaque label<9..255> = "TLS 1.3, " + Label;
+ * opaque hash_value<0..255> = HashValue;
+ * } HkdfLabel;
+ *
+ * RFC 5869 HMAC-based Extract-and-Expand Key Derivation Function (HKDF):
+ * HKDF-Expand(PRK, info, L) -> OKM
+ */
+ guchar lastoutput[DIGEST_MAX_SIZE];
+ gcry_md_hd_t h;
+ gcry_error_t err;
+ const guint label_length = (guint) strlen(label);
+ const guint hash_value_length = (guint) strlen(hash_value);
+ const guint hash_len = gcry_md_get_algo_dlen(md);
+
+ /* Some sanity checks */
+ DISSECTOR_ASSERT(out_len > 0 && out_len <= 255 * hash_len);
+ DISSECTOR_ASSERT(label_length <= 255 - 9);
+ DISSECTOR_ASSERT(hash_value_length <= 255);
+ DISSECTOR_ASSERT(hash_len > 0 && hash_len <= DIGEST_MAX_SIZE);
+
+ err = gcry_md_open(&h, md, GCRY_MD_FLAG_HMAC);
+ if (err) {
+ ssl_debug_printf("%s failed to invoke hash func %d: %s\n", G_STRFUNC, md, gcry_strerror(err));
+ return FALSE;
+ }
+
+ *out = (guchar *)wmem_alloc(NULL, out_len);
+
+ for (guint offset = 0; offset < out_len; offset += hash_len) {
+ gcry_md_reset(h);
+ gcry_md_setkey(h, secret->data, secret->data_len); /* Set PRK */
+
+ if (offset > 0) {
+ gcry_md_write(h, lastoutput, hash_len); /* T(1..N) */
+ }
+
+ /* info = HkdfLabel { length, label, hash_value } */
+ gcry_md_putc(h, out_len >> 8); /* length */
+ gcry_md_putc(h, (guint8) out_len);
+ gcry_md_putc(h, 9 + label_length); /* label */
+ gcry_md_write(h, "TLS 1.3, ", 9);
+ gcry_md_write(h, label, label_length);
+ gcry_md_putc(h, hash_value_length); /* hash_value */
+ gcry_md_write(h, hash_value, hash_value_length);
+
+ gcry_md_putc(h, (guint8) (offset / hash_len + 1)); /* constant 0x01..N */
+
+ memcpy(lastoutput, gcry_md_read(h, md), hash_len);
+ memcpy(*out + offset, lastoutput, MIN(hash_len, out_len - offset));
+ }
+
+ gcry_md_close(h);
+ return TRUE;
+}
/* HMAC and the Pseudorandom function }}} */
#else /* ! HAVE_LIBGCRYPT */
@@ -2846,7 +2918,7 @@ ssl_decoder_destroy_cb(wmem_allocator_t *, wmem_cb_event_t, void *);
static SslDecoder*
ssl_create_decoder(const SslCipherSuite *cipher_suite, gint cipher_algo,
- gint compression, guint8 *mk, guint8 *sk, guint8 *iv)
+ gint compression, guint8 *mk, guint8 *sk, guint8 *iv, guint iv_length)
{
SslDecoder *dec;
ssl_cipher_mode_t mode = cipher_suite->mode;
@@ -2864,9 +2936,10 @@ ssl_create_decoder(const SslCipherSuite *cipher_suite, gint cipher_algo,
dec->mac_key.data = dec->_mac_key_or_write_iv;
ssl_data_set(&dec->mac_key, mk, ssl_cipher_suite_dig(cipher_suite)->len);
} else if (mode == MODE_GCM || mode == MODE_CCM || mode == MODE_CCM_8) {
- /* So far all AEAD ciphers derive the 4-byte implicit nonce part from the write IV */
+ // Input for the nonce, to be used with AEAD ciphers.
+ DISSECTOR_ASSERT(iv_length <= sizeof(dec->_mac_key_or_write_iv));
dec->write_iv.data = dec->_mac_key_or_write_iv;
- ssl_data_set(&dec->write_iv, iv, 4);
+ ssl_data_set(&dec->write_iv, iv, iv_length);
}
dec->seq = 0;
dec->decomp = ssl_create_decompressor(compression);
@@ -2927,6 +3000,11 @@ ssl_generate_pre_master_secret(SslDecryptSession *ssl_session,
return FALSE;
}
+ if (ssl_session->session.version == TLSV1DOT3_VERSION) {
+ ssl_debug_printf("%s: detected TLS 1.3 which has no pre-master secrets\n", G_STRFUNC);
+ return FALSE;
+ }
+
/* check to see if the PMS was provided to us*/
if (ssl_restore_master_key(ssl_session, "Unencrypted pre-master secret", TRUE,
mk_map->pms, &ssl_session->client_random)) {
@@ -3046,6 +3124,7 @@ ssl_generate_pre_master_secret(SslDecryptSession *ssl_session,
return FALSE;
}
+/* Used for (D)TLS 1.2 and earlier versions (not with TLS 1.3). */
int
ssl_generate_keyring_material(SslDecryptSession*ssl_session)
{
@@ -3060,6 +3139,12 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session)
guint8 *c_wk = NULL, *s_wk = NULL, *c_mk = NULL, *s_mk = NULL;
const SslCipherSuite *cipher_suite = ssl_session->cipher_suite;
+ /* TLS 1.3 is handled directly in tls13_change_key. */
+ if (ssl_session->session.version == TLSV1DOT3_VERSION) {
+ ssl_debug_printf("%s: detected TLS 1.3. Should not have been called!\n", G_STRFUNC);
+ return -1;
+ }
+
/* check for enough info to proced */
guint need_all = SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION;
guint need_any = SSL_MASTER_SECRET | SSL_PRE_MASTER_SECRET;
@@ -3329,13 +3414,13 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session)
create_decoders:
/* create both client and server ciphers*/
ssl_debug_printf("%s ssl_create_decoder(client)\n", G_STRFUNC);
- ssl_session->client_new = ssl_create_decoder(cipher_suite, cipher_algo, ssl_session->session.compression, c_mk, c_wk, c_iv);
+ ssl_session->client_new = ssl_create_decoder(cipher_suite, cipher_algo, ssl_session->session.compression, c_mk, c_wk, c_iv, write_iv_len);
if (!ssl_session->client_new) {
ssl_debug_printf("%s can't init client decoder\n", G_STRFUNC);
goto fail;
}
ssl_debug_printf("%s ssl_create_decoder(server)\n", G_STRFUNC);
- ssl_session->server_new = ssl_create_decoder(cipher_suite, cipher_algo, ssl_session->session.compression, s_mk, s_wk, s_iv);
+ ssl_session->server_new = ssl_create_decoder(cipher_suite, cipher_algo, ssl_session->session.compression, s_mk, s_wk, s_iv, write_iv_len);
if (!ssl_session->server_new) {
ssl_debug_printf("%s can't init client decoder\n", G_STRFUNC);
goto fail;
@@ -3355,6 +3440,93 @@ fail:
g_free(key_block.data);
return -1;
}
+
+/* Generated the key material based on the given secret. */
+static gboolean
+tls13_generate_keys(SslDecryptSession *ssl_session, const StringInfo *secret, gboolean is_from_server)
+{
+ gboolean success = FALSE;
+ guchar *write_key = NULL, *write_iv = NULL;
+ SslDecoder *decoder;
+ guint key_length, iv_length;
+ int hash_algo;
+ const SslCipherSuite *cipher_suite = ssl_session->cipher_suite;
+ int cipher_algo;
+
+ if (ssl_session->session.version != TLSV1DOT3_VERSION) {
+ ssl_debug_printf("%s only usable for TLS 1.3, not %#x!\n", G_STRFUNC,
+ ssl_session->session.version);
+ return FALSE;
+ }
+
+ if (cipher_suite == NULL) {
+ ssl_debug_printf("%s Unknown cipher\n", G_STRFUNC);
+ return FALSE;
+ }
+
+ if (cipher_suite->kex != KEX_TLS13) {
+ ssl_debug_printf("%s Invalid cipher suite 0x%04x spotted!\n", G_STRFUNC, cipher_suite->number);
+ return FALSE;
+ }
+
+ /* Find the Libgcrypt cipher algorithm for the given SSL cipher suite ID */
+ const char *cipher_name = ciphers[cipher_suite->enc-0x30];
+ ssl_debug_printf("%s CIPHER: %s\n", G_STRFUNC, cipher_name);
+ cipher_algo = ssl_get_cipher_by_name(cipher_name);
+ if (cipher_algo == 0) {
+ ssl_debug_printf("%s can't find cipher %s\n", G_STRFUNC, cipher_name);
+ return FALSE;
+ }
+
+ const char *hash_name = ssl_cipher_suite_dig(cipher_suite)->name;
+ hash_algo = ssl_get_digest_by_name(hash_name);
+ if (!hash_algo) {
+ ssl_debug_printf("%s can't find hash function %s\n", G_STRFUNC, hash_name);
+ return FALSE;
+ }
+
+ key_length = (guint) gcry_cipher_get_algo_blklen(cipher_algo);
+ /* AES-GCM/AES-CCM/Poly1305-ChaCha20 all have N_MIN=N_MAX = 12. */
+ iv_length = 12;
+ ssl_debug_printf("%s key_length %u iv_length %u\n", G_STRFUNC, key_length, iv_length);
+
+ if (!tls13_hkdf_expand_label(hash_algo, secret, "key", "", key_length, &write_key)) {
+ ssl_debug_printf("%s write_key expansion failed\n", G_STRFUNC);
+ return FALSE;
+ }
+ if (!tls13_hkdf_expand_label(hash_algo, secret, "iv", "", iv_length, &write_iv)) {
+ ssl_debug_printf("%s write_iv expansion failed\n", G_STRFUNC);
+ goto end;
+ }
+
+ ssl_print_data(is_from_server ? "Server Write Key" : "Client Write Key", write_key, key_length);
+ ssl_print_data(is_from_server ? "Server Write IV" : "Client Write IV", write_iv, iv_length);
+
+ ssl_debug_printf("%s ssl_create_decoder(%s)\n", G_STRFUNC, is_from_server ? "server" : "client");
+ decoder = ssl_create_decoder(cipher_suite, cipher_algo, 0, NULL, write_key, write_iv, iv_length);
+ if (!decoder) {
+ ssl_debug_printf("%s can't init %s decoder\n", G_STRFUNC, is_from_server ? "server" : "client");
+ goto end;
+ }
+
+ /* Continue the TLS session with new keys, but reuse old flow to keep things
+ * like "Follow SSL" working (by linking application data records). */
+ if (is_from_server) {
+ decoder->flow = ssl_session->server ? ssl_session->server->flow : ssl_create_flow();
+ ssl_session->server = decoder;
+ } else {
+ decoder->flow = ssl_session->client ? ssl_session->client->flow : ssl_create_flow();
+ ssl_session->client = decoder;
+ }
+ ssl_debug_printf("%s %s ready using cipher suite 0x%04x (cipher %s hash %s)\n", G_STRFUNC,
+ is_from_server ? "Server" : "Client", cipher_suite->number, cipher_name, hash_name);
+ success = TRUE;
+
+end:
+ wmem_free(NULL, write_key);
+ wmem_free(NULL, write_iv);
+ return success;
+}
/* (Pre-)master secrets calculations }}} */
#ifdef HAVE_LIBGNUTLS
@@ -3626,6 +3798,13 @@ tls_decrypt_aead_record(SslDecryptSession *ssl, SslDecoder *decoder,
explicit_nonce = in;
ciphertext = explicit_nonce + EXPLICIT_NONCE_LEN;
ciphertext_len = inl - EXPLICIT_NONCE_LEN - auth_tag_len;
+ } else if (version == TLSV1DOT3_VERSION) {
+ if (inl < auth_tag_len) {
+ ssl_debug_printf("%s input %d has no space for auth tag %d\n", G_STRFUNC, inl, auth_tag_len);
+ return FALSE;
+ }
+ ciphertext = in;
+ ciphertext_len = inl - auth_tag_len;
} else {
ssl_debug_printf("%s Unexpected TLS version %#x\n", G_STRFUNC, version);
return FALSE;
@@ -3658,6 +3837,18 @@ tls_decrypt_aead_record(SslDecryptSession *ssl, SslDecoder *decoder,
nonce_with_counter[IMPLICIT_NONCE_LEN + EXPLICIT_NONCE_LEN + 3] = 1;
}
#endif
+ } else if (version == TLSV1DOT3_VERSION) {
+ /*
+ * Technically the nonce length must be at least 8 bytes, but for
+ * AES-GCM, AES-CCM and Poly1305-ChaCha20 the nonce length is exact 12.
+ */
+ const guint nonce_len = 12;
+ DISSECTOR_ASSERT(decoder->write_iv.data_len == nonce_len);
+ memcpy(nonce, decoder->write_iv.data, decoder->write_iv.data_len);
+ /* Sequence number is left-padded with zeroes and XORed with write_iv */
+ phton64(nonce + nonce_len - 8, pntoh64(nonce + nonce_len - 8) ^ decoder->seq);
+ ssl_debug_printf("%s seq %" G_GUINT64_FORMAT "\n", G_STRFUNC, decoder->seq);
+ decoder->seq++; /* Implicit sequence number for TLS 1.3. */
}
/* Set nonce and additional authentication data */
@@ -3751,6 +3942,11 @@ ssl_decrypt_record(SslDecryptSession *ssl, SslDecoder *decoder, guint8 ct, guint
ssl_debug_printf("ssl_decrypt_record ciphertext len %d\n", inl);
ssl_print_data("Ciphertext",in, inl);
+ if ((ssl->session.version == TLSV1DOT3_VERSION) != (decoder->cipher_suite->kex == KEX_TLS13)) {
+ ssl_debug_printf("%s Invalid cipher suite for the protocol version!\n", G_STRFUNC);
+ return -1;
+ }
+
/* ensure we have enough storage space for decrypted data */
if (inl > out_str->data_len)
{
@@ -4846,6 +5042,12 @@ ssl_restore_master_key(SslDecryptSession *ssl, const char *label,
void
ssl_finalize_decryption(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map)
{
+ if (ssl->session.version == TLSV1DOT3_VERSION) {
+ /* TLS 1.3 implementations only provide secrets derived from the master
+ * secret which are loaded in tls13_change_key. No master secrets can be
+ * loaded here, so just return. */
+ return;
+ }
ssl_debug_printf("%s state = 0x%02X\n", G_STRFUNC, ssl->state);
if (ssl->state & SSL_HAVE_SESSION_KEY) {
ssl_debug_printf(" session key already available, nothing to do.\n");
@@ -4893,6 +5095,77 @@ ssl_finalize_decryption(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map)
&ssl->session_ticket, &ssl->master_secret);
}
} /* }}} */
+
+/* Load the new key. */
+void
+tls13_change_key(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map,
+ gboolean is_from_server, TLSRecordType type)
+{
+ GHashTable *key_map;
+ const char *label;
+
+ if (ssl->session.version != TLSV1DOT3_VERSION) {
+ ssl_debug_printf("%s TLS version %#x is not 1.3\n", G_STRFUNC, ssl->session.version);
+ return;
+ }
+
+ if (ssl->client_random.data_len == 0) {
+ /* May happen if Hello message is missing and Finished is found. */
+ ssl_debug_printf("%s missing Client Random\n", G_STRFUNC);
+ return;
+ }
+
+ switch (type) {
+ case TLS_SECRET_0RTT_APP:
+ /* TODO 0-RTT decryption is not implemented yet */
+ return;
+ case TLS_SECRET_HANDSHAKE:
+ if (is_from_server) {
+ label = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
+ key_map = mk_map->tls13_server_handshake;
+ } else {
+ label = "CLIENT_HANDSHAKE_TRAFFIC_SECRET";
+ key_map = mk_map->tls13_client_handshake;
+ }
+ break;
+ case TLS_SECRET_APP:
+ if (is_from_server) {
+ label = "SERVER_TRAFFIC_SECRET_0";
+ key_map = mk_map->tls13_server_appdata;
+ } else {
+ label = "CLIENT_TRAFFIC_SECRET_0";
+ key_map = mk_map->tls13_client_appdata;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ /* Transitioning to new keys, mark old ones as unusable. */
+ ssl_debug_printf("%s transitioning to new key, old state 0x%02x\n", G_STRFUNC, ssl->state);
+ ssl->state &= ~(SSL_MASTER_SECRET | SSL_PRE_MASTER_SECRET | SSL_HAVE_SESSION_KEY);
+
+ StringInfo *secret = (StringInfo *)g_hash_table_lookup(key_map, &ssl->client_random);
+ if (!secret) {
+ ssl_debug_printf("%s Cannot find %s, decryption impossible\n", G_STRFUNC, label);
+ /* Disable decryption, the keys are invalid. */
+ if (is_from_server) {
+ ssl->server = NULL;
+ } else {
+ ssl->client = NULL;
+ }
+ return;
+ }
+
+ /* TLS 1.3 secret found, set new keys. */
+ ssl->traffic_secret.data = (guchar *) wmem_realloc(wmem_file_scope(),
+ ssl->traffic_secret.data, secret->data_len);
+ ssl_data_set(&ssl->traffic_secret, secret->data, secret->data_len);
+ ssl_debug_printf("%s Retrieved TLS 1.3 traffic secret.\n", G_STRFUNC);
+ ssl_print_string("Client Random", &ssl->client_random);
+ ssl_print_string(label, secret);
+ tls13_generate_keys(ssl, secret, is_from_server);
+}
#endif /* HAVE_LIBGCRYPT */
/** SSL keylog file handling. {{{ */
@@ -7552,7 +7825,7 @@ ssl_common_register_options(module_t *module _U_, ssl_common_options_t *options
void
ssl_calculate_handshake_hash(SslDecryptSession *ssl_session, tvbuff_t *tvb, guint32 offset, guint32 length)
{
- if (ssl_session && !(ssl_session->state & SSL_MASTER_SECRET)) {
+ if (ssl_session && ssl_session->session.version != TLSV1DOT3_VERSION && !(ssl_session->state & SSL_MASTER_SECRET)) {
guint32 old_length = ssl_session->handshake_data.data_len;
ssl_debug_printf("Calculating hash with offset %d %d\n", offset, length);
ssl_session->handshake_data.data = (guchar *)wmem_realloc(wmem_file_scope(), ssl_session->handshake_data.data, old_length + length);
diff --git a/epan/dissectors/packet-ssl-utils.h b/epan/dissectors/packet-ssl-utils.h
index 8da1458a03..322f9634c3 100644
--- a/epan/dissectors/packet-ssl-utils.h
+++ b/epan/dissectors/packet-ssl-utils.h
@@ -272,6 +272,13 @@ typedef enum {
#define IMPLICIT_NONCE_LEN 4
#define EXPLICIT_NONCE_LEN 8
+/* TLS 1.3 Record type for selecting the appropriate secret. */
+typedef enum {
+ TLS_SECRET_0RTT_APP,
+ TLS_SECRET_HANDSHAKE,
+ TLS_SECRET_APP,
+} TLSRecordType;
+
#define SSL_DEBUG_USE_STDERR "-"
#define SSLV2_MAX_SESSION_ID_LENGTH_IN_BYTES 16
@@ -328,6 +335,7 @@ typedef struct _SslDecoder {
#define KEX_SRP_SHA_DSS 0x21
#define KEX_SRP_SHA_RSA 0x22
#define KEX_IS_DH(n) ((n) >= KEX_DHE_DSS && (n) <= KEX_ECDH_RSA)
+#define KEX_TLS13 0x23
#define ENC_DES 0x30
#define ENC_3DES 0x31
@@ -401,6 +409,7 @@ typedef struct _SslDecryptSession {
StringInfo server_random;
StringInfo client_random;
StringInfo master_secret;
+ StringInfo traffic_secret; /**< TLS 1.3 traffic secret, wmem file scope. */
StringInfo handshake_data;
/* the data store for this StringInfo must be allocated explicitly with a capture lifetime scope */
StringInfo pre_master_secret;
@@ -614,11 +623,21 @@ ssl_save_session(SslDecryptSession* ssl, GHashTable *session_hash);
#ifdef HAVE_LIBGCRYPT
extern void
ssl_finalize_decryption(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map);
+
+extern void
+tls13_change_key(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map,
+ gboolean is_from_server, TLSRecordType type);
#else /* ! HAVE_LIBGCRYPT */
static inline void
ssl_finalize_decryption(SslDecryptSession *ssl _U_, ssl_master_key_map_t *mk_map _U_)
{
}
+
+static inline void
+tls13_change_key(SslDecryptSession *ssl _U_, ssl_master_key_map_t *mk_map _U_,
+ gboolean is_from_server _U_, TLSRecordType type _U_)
+{
+}
#endif /* ! HAVE_LIBGCRYPT */
extern gboolean
diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c
index f73bcd45e8..b146f2ed8e 100644
--- a/epan/dissectors/packet-ssl.c
+++ b/epan/dissectors/packet-ssl.c
@@ -2032,11 +2032,19 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
ssl_dissect_hnd_cli_hello(&dissect_ssl3_hf, tvb, pinfo,
ssl_hand_tree, offset, length, session, ssl,
NULL);
+ /* Cannot call tls13_change_key here since it is not yet known
+ * whether the server will agree on TLS 1.3 or not. */
break;
case SSL_HND_SERVER_HELLO:
ssl_dissect_hnd_srv_hello(&dissect_ssl3_hf, tvb, pinfo, ssl_hand_tree,
offset, length, session, ssl, FALSE);
+ if (ssl) {
+ ssl_load_keyfile(ssl_options.keylog_filename, &ssl_keylog_file, &ssl_master_key_map);
+ /* Create client and server decoders for TLS 1.3. */
+ tls13_change_key(ssl, &ssl_master_key_map, FALSE, TLS_SECRET_HANDSHAKE);
+ tls13_change_key(ssl, &ssl_master_key_map, TRUE, TLS_SECRET_HANDSHAKE);
+ }
break;
case SSL_HND_HELLO_VERIFY_REQUEST:
@@ -2097,6 +2105,10 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
case SSL_HND_FINISHED:
ssl_dissect_hnd_finished(&dissect_ssl3_hf, tvb, ssl_hand_tree,
offset, session, &ssl_hfs);
+ if (ssl) {
+ ssl_load_keyfile(ssl_options.keylog_filename, &ssl_keylog_file, &ssl_master_key_map);
+ tls13_change_key(ssl, &ssl_master_key_map, is_from_server, TLS_SECRET_APP);
+ }
break;
case SSL_HND_CERT_URL: