diff options
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-dtls.c | 38 | ||||
-rw-r--r-- | epan/dissectors/packet-ssl-utils.c | 6 | ||||
-rw-r--r-- | epan/dissectors/packet-ssl.c | 9 |
3 files changed, 49 insertions, 4 deletions
diff --git a/epan/dissectors/packet-dtls.c b/epan/dissectors/packet-dtls.c index f9e2539ebd..63caaa7b8c 100644 --- a/epan/dissectors/packet-dtls.c +++ b/epan/dissectors/packet-dtls.c @@ -825,8 +825,6 @@ dissect_dtls_record(tvbuff_t *tvb, packet_info *pinfo, } case SSL_ID_HANDSHAKE: { - ssl_calculate_handshake_hash(ssl, tvb, offset, record_length); - /* try to retrieve and use decrypted handshake record, if any. */ if (decrypted) { dissect_dtls_handshake(decrypted, pinfo, dtls_record_tree, 0, @@ -1055,6 +1053,7 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo, tvbuff_t *new_tvb = NULL; const gchar *frag_str = NULL; gboolean fragmented; + guint32 hs_offset = offset; /* add a subtree for the handshake protocol */ ti = proto_tree_add_item(tree, hf_dtls_handshake_protocol, tvb, offset, -1, ENC_NA); @@ -1246,6 +1245,29 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo, sub_tvb = tvb_new_subset_length(tvb, offset, fragment_length); } + /* + * Add handshake message (including type, length, etc.) to hash (for + * Extended Master Secret). The computation must however happen as if + * the message was sent in a single fragment (RFC 6347, section 4.2.6). + */ + if (fragment_offset == 0) { + /* Unfragmented packet. */ + ssl_calculate_handshake_hash(ssl, tvb, hs_offset, 12 + fragment_length); + } else { + /* + * Handshake message was fragmented over multiple messages, fake a + * single fragment and add reassembled data. + */ + /* msg_type (1), length (3), message_seq (2) */ + ssl_calculate_handshake_hash(ssl, tvb, hs_offset, 6); + /* fragment_offset (3) equals to zero. */ + ssl_calculate_handshake_hash(ssl, NULL, 0, 3); + /* fragment_length (3) equals to length. */ + ssl_calculate_handshake_hash(ssl, tvb, hs_offset + 1, 3); + /* actual handshake data */ + ssl_calculate_handshake_hash(ssl, sub_tvb, 0, length); + } + /* now dissect the handshake message, if necessary */ switch ((HandshakeType) msg_type) { case SSL_HND_HELLO_REQUEST: @@ -1268,6 +1290,18 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo, break; case SSL_HND_HELLO_VERIFY_REQUEST: + /* + * The initial ClientHello and HelloVerifyRequest are not included + * in the calculation of the handshake_messages + * (https://tools.ietf.org/html/rfc6347#page-18). This is also + * important for correct calculation of Extended Master Secret. + */ + if (ssl && ssl->handshake_data.data_len) { + ssl_debug_printf("%s erasing previous handshake_messages: %d\n", G_STRFUNC, ssl->handshake_data.data_len); + wmem_free(wmem_file_scope(), ssl->handshake_data.data); + ssl->handshake_data.data = NULL; + ssl->handshake_data.data_len = 0; + } dissect_dtls_hnd_hello_verify_request(&dissect_dtls_hf, sub_tvb, pinfo, ssl_hand_tree, 0, length); break; diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c index f3edf9a683..e26926d12e 100644 --- a/epan/dissectors/packet-ssl-utils.c +++ b/epan/dissectors/packet-ssl-utils.c @@ -8496,7 +8496,11 @@ ssl_calculate_handshake_hash(SslDecryptSession *ssl_session, tvbuff_t *tvb, guin 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); - tvb_memcpy(tvb, ssl_session->handshake_data.data + old_length, offset, length); + if (tvb) { + tvb_memcpy(tvb, ssl_session->handshake_data.data + old_length, offset, length); + } else { + memset(ssl_session->handshake_data.data + old_length, 0, length); + } ssl_session->handshake_data.data_len += length; } } diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c index 60fa0a803f..44dcdaba2a 100644 --- a/epan/dissectors/packet-ssl.c +++ b/epan/dissectors/packet-ssl.c @@ -1728,7 +1728,6 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, } break; case SSL_ID_HANDSHAKE: - ssl_calculate_handshake_hash(ssl, tvb, offset, record_length); if (decrypted) { dissect_ssl3_handshake(decrypted, pinfo, ssl_record_tree, 0, tvb_reported_length(decrypted), FALSE, session, @@ -1941,6 +1940,8 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo, record_length += offset; while (offset < record_length) { + guint32 hs_offset = offset; + msg_type = tvb_get_guint8(tvb, offset); length = tvb_get_ntoh24(tvb, offset + 1); @@ -2011,6 +2012,12 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo, tvb, offset, 3, length); offset += 3; + /* + * Add handshake message (including type, length, etc.) to hash (for + * Extended Master Secret). + */ + ssl_calculate_handshake_hash(ssl, tvb, hs_offset, 4 + length); + /* now dissect the handshake message, if necessary */ switch ((HandshakeType) msg_type) { case SSL_HND_HELLO_REQUEST: |