aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2018-09-13 10:29:29 +0200
committerPeter Wu <peter@lekensteyn.nl>2018-09-16 20:22:18 +0000
commit624d136f37ecd78dbd47011045c0093f1bb61619 (patch)
tree81860fdf594681b57496eb8cadc446c3f6047ff7
parente22faab56d6b1421df26c7aa2025d41af03a9f55 (diff)
QUIC: wire up CRYPTO frames with TLS 1.3 Handshake (draft -13)
This recognizes the Client/Server Hello message in the Initial Packets. Full (handshake) decryption remains a task for later. Prevent STREAM 0 from being treated as TLS while at it. Change-Id: I27193a15be777c568b6b009141cbc59bcf3e8ad6 Ping-Bug: 13881 Reviewed-on: https://code.wireshark.org/review/29646 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot Reviewed-by: Peter Wu <peter@lekensteyn.nl>
-rw-r--r--epan/dissectors/packet-quic.c23
-rw-r--r--epan/dissectors/packet-ssl-utils.c8
-rw-r--r--epan/dissectors/packet-ssl-utils.h1
-rw-r--r--epan/dissectors/packet-ssl.c47
4 files changed, 76 insertions, 3 deletions
diff --git a/epan/dissectors/packet-quic.c b/epan/dissectors/packet-quic.c
index 2a32c65382..95127d5e08 100644
--- a/epan/dissectors/packet-quic.c
+++ b/epan/dissectors/packet-quic.c
@@ -125,6 +125,7 @@ static gint ett_quic_ftflags = -1;
static dissector_handle_t quic_handle;
static dissector_handle_t tls_handle;
+static dissector_handle_t tls13_handshake_handle;
/*
* PROTECTED PAYLOAD DECRYPTION (done in first pass)
@@ -781,7 +782,7 @@ quic_connection_destroy(gpointer data, gpointer user_data _U_)
#ifdef HAVE_LIBGCRYPT_AEAD
static int
-dissect_quic_frame_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tree, guint offset, quic_packet_info_t *quic_packet _U_)
+dissect_quic_frame_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tree, guint offset, guint32 version)
{
proto_item *ti_ft, *ti_ftflags, *ti;
proto_tree *ft_tree, *ftflags_tree;
@@ -1085,7 +1086,7 @@ dissect_quic_frame_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tree
proto_tree_add_item(ft_tree, hf_quic_stream_data, tvb, offset, (int)length, ENC_NA);
- if (stream_id == 0) { /* Special Stream */
+ if (is_quic_draft_max(version, 12) && stream_id == 0) { /* Special Stream */
tvbuff_t *next_tvb;
proto_item_append_text(ti_stream, " (Cryptographic handshake)");
@@ -1108,6 +1109,20 @@ dissect_quic_frame_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tree
proto_tree_add_item_ret_varint(ft_tree, hf_quic_frame_type_crypt_length, tvb, offset, -1, ENC_VARINT_QUIC, &crypto_length, &lenvar);
offset += lenvar;
proto_tree_add_item(ft_tree, hf_quic_frame_type_crypt_crypto_data, tvb, offset, (guint32)crypto_length, ENC_NA);
+ {
+ tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, (int)crypto_length);
+ col_set_writable(pinfo->cinfo, -1, FALSE);
+ /*
+ * Dissect TLS handshake record. The Client/Server Hello (CH/SH)
+ * are contained in the Initial Packet. 0-RTT keys are ready
+ * after CH. HS + 1-RTT keys are ready after SH.
+ * (Note: keys captured from the client might become available
+ * after capturing the packets due to processing delay.)
+ * These keys will be loaded in the first HS/0-RTT/1-RTT msg.
+ */
+ call_dissector(tls13_handshake_handle, next_tvb, pinfo, ft_tree);
+ col_set_writable(pinfo->cinfo, -1, TRUE);
+ }
offset += (guint32)crypto_length;
}
break;
@@ -1577,6 +1592,7 @@ quic_process_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_
quic_info_data_t *quic_info, quic_packet_info_t *quic_packet, quic_cipher *cipher, guint pkn_len)
{
quic_decrypt_result_t *decryption = &quic_packet->decryption;
+ guint32 version = quic_info ? quic_info->version : 0;
/*
* If no decryption error has occurred yet, try decryption on the first
@@ -1598,7 +1614,7 @@ quic_process_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_
guint decrypted_offset = 0;
while (tvb_reported_length_remaining(decrypted_tvb, decrypted_offset) > 0) {
- decrypted_offset = dissect_quic_frame_type(decrypted_tvb, pinfo, tree, decrypted_offset, quic_packet);
+ decrypted_offset = dissect_quic_frame_type(decrypted_tvb, pinfo, tree, decrypted_offset, version);
}
} else if (quic_info->skip_decryption) {
expert_add_info_format(pinfo, ti, &ei_quic_decryption_failed,
@@ -2566,6 +2582,7 @@ void
proto_reg_handoff_quic(void)
{
tls_handle = find_dissector("tls");
+ tls13_handshake_handle = find_dissector("tls13-handshake");
dissector_add_uint_with_preference("udp.port", 0, quic_handle);
heur_dissector_add("udp", dissect_quic_heur, "QUIC", "quic", proto_quic, HEURISTIC_ENABLE);
}
diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c
index 866073738e..3cce6609e7 100644
--- a/epan/dissectors/packet-ssl-utils.c
+++ b/epan/dissectors/packet-ssl-utils.c
@@ -4997,6 +4997,14 @@ void
tls13_change_key(SslDecryptSession *ssl, ssl_master_key_map_t *mk_map,
gboolean is_from_server, TLSRecordType type)
{
+ if (ssl->state & SSL_QUIC_RECORD_LAYER) {
+ /*
+ * QUIC does not use the TLS record layer for message protection.
+ * The required keys will be extracted later by QUIC.
+ */
+ return;
+ }
+
StringInfo *secret = tls13_load_secret(ssl, mk_map, is_from_server, type);
if (!secret) {
return;
diff --git a/epan/dissectors/packet-ssl-utils.h b/epan/dissectors/packet-ssl-utils.h
index e32911e4a1..23638ff014 100644
--- a/epan/dissectors/packet-ssl-utils.h
+++ b/epan/dissectors/packet-ssl-utils.h
@@ -237,6 +237,7 @@ static inline guint8 extract_tls13_draft_version(guint32 version) {
#define SSL_NEW_SESSION_TICKET (1<<10)
#define SSL_ENCRYPT_THEN_MAC (1<<11)
#define SSL_SEEN_0RTT_APPDATA (1<<12)
+#define SSL_QUIC_RECORD_LAYER (1<<13) /* For QUIC (draft >= -13) */
#define SSL_EXTENDED_MASTER_SECRET_MASK (SSL_CLIENT_EXTENDED_MASTER_SECRET|SSL_SERVER_EXTENDED_MASTER_SECRET)
diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c
index 65402f3d58..912d83b40f 100644
--- a/epan/dissectors/packet-ssl.c
+++ b/epan/dissectors/packet-ssl.c
@@ -770,6 +770,52 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
return tvb_captured_length(tvb);
}
+/*
+ * Dissect TLS 1.3 handshake messages (without the record layer).
+ * For use by QUIC (draft -13).
+ */
+static int
+dissect_tls13_handshake(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+
+ conversation_t *conversation;
+ SslDecryptSession *ssl_session;
+ SslSession *session;
+ gint is_from_server;
+
+ ssl_debug_printf("\n%s enter frame #%u (%s)\n", G_STRFUNC, pinfo->num, (pinfo->fd->flags.visited)?"already visited":"first time");
+
+ conversation = find_or_create_conversation(pinfo);
+ ssl_session = ssl_get_session(conversation, tls_handle);
+ session = &ssl_session->session;
+ is_from_server = ssl_packet_from_server(session, ssl_associations, pinfo);
+ if (session->version == SSL_VER_UNKNOWN) {
+ session->version = TLSV1DOT3_VERSION;
+ ssl_session->state |= SSL_VERSION;
+ ssl_session->state |= SSL_QUIC_RECORD_LAYER;
+ }
+
+ /*
+ * First pass: collect state (including Client Random for key matching).
+ * Second pass: dissection only, no need to collect state.
+ */
+ if (PINFO_FD_VISITED(pinfo)) {
+ ssl_session = NULL;
+ }
+
+ ssl_debug_printf(" conversation = %p, ssl_session = %p, from_server = %d\n",
+ (void *)conversation, (void *)ssl_session, is_from_server);
+
+ /* Directly add handshake message to the tree (without proto_tls item). */
+ dissect_ssl3_handshake(tvb, pinfo, tree, 0,
+ tvb_reported_length(tvb), FALSE, session,
+ is_from_server, ssl_session, SSL_ID_HANDSHAKE, TLSV1DOT3_VERSION);
+
+ ssl_debug_flush();
+
+ return tvb_captured_length(tvb);
+}
+
static gboolean
is_sslv3_or_tls(tvbuff_t *tvb)
{
@@ -4010,6 +4056,7 @@ proto_register_tls(void)
proto_tls);
tls_handle = register_dissector("tls", dissect_ssl, proto_tls);
+ register_dissector("tls13-handshake", dissect_tls13_handshake, proto_tls);
register_init_routine(ssl_init);
register_cleanup_routine(ssl_cleanup);