aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2017-05-13 19:21:45 +0200
committerAlexis La Goutte <alexis.lagoutte@gmail.com>2017-05-14 21:18:24 +0000
commit6b289a8b76e7a6fec1d5f2d856995bb549907c4f (patch)
tree00ca6591ff1e1ebb21a154670184b5795f440c24 /epan
parentaf13668831df07f36a4cf8e2bc242d57a267a367 (diff)
ssl,dtls: fix message hash for extended_master_secret
The handshake_messages for extended master secret start at Client Hello and end at ClientKeyExchange. Previously all handshake messages in a record would be hashed, possibly covering those after CKE. Now it will hash each handshake message separately. For DTLS, the CH and HVR messages must also be ignored. Additionally, DTLS needs special treatment to merge multiple fragments. Bug: 13704 Change-Id: I0c8f19b4c352c0195848ded319b6991d76542720 Reviewed-on: https://code.wireshark.org/review/21625 Reviewed-by: Peter Wu <peter@lekensteyn.nl> Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Diffstat (limited to 'epan')
-rw-r--r--epan/dissectors/packet-dtls.c38
-rw-r--r--epan/dissectors/packet-ssl-utils.c6
-rw-r--r--epan/dissectors/packet-ssl.c9
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: