From Eric Wustrow:

TLS Diffie-Hellman key exchange dissection support.
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=6277

svn path=/trunk/; revision=38858
This commit is contained in:
Anders Broman 2011-09-02 05:48:29 +00:00
parent 3cc9cabaa0
commit af65dc50ab
1 changed files with 197 additions and 7 deletions

View File

@ -191,6 +191,16 @@ static gint hf_ssl_handshake_certificate_len = -1;
static gint hf_ssl_handshake_cert_types_count = -1;
static gint hf_ssl_handshake_cert_types = -1;
static gint hf_ssl_handshake_cert_type = -1;
static gint hf_ssl_handshake_server_keyex_p_len = -1;
static gint hf_ssl_handshake_server_keyex_g_len = -1;
static gint hf_ssl_handshake_server_keyex_ys_len = -1;
static gint hf_ssl_handshake_client_keyex_yc_len = -1;
static gint hf_ssl_handshake_server_keyex_sig_len = -1;
static gint hf_ssl_handshake_server_keyex_p = -1;
static gint hf_ssl_handshake_server_keyex_g = -1;
static gint hf_ssl_handshake_server_keyex_ys = -1;
static gint hf_ssl_handshake_client_keyex_yc = -1;
static gint hf_ssl_handshake_server_keyex_sig = -1;
static gint hf_ssl_handshake_sig_hash_alg_len = -1;
static gint hf_ssl_handshake_sig_hash_algs = -1;
static gint hf_ssl_handshake_sig_hash_alg = -1;
@ -260,6 +270,7 @@ static gint ett_ssl_sig_hash_algs = -1;
static gint ett_ssl_sig_hash_alg = -1;
static gint ett_ssl_dnames = -1;
static gint ett_ssl_random = -1;
static gint ett_ssl_keyex_params = -1;
static gint ett_ssl_cert_status = -1;
static gint ett_ssl_ocsp_resp = -1;
static gint ett_pct_cipher_suites = -1;
@ -411,7 +422,7 @@ ssl_parse(void)
/* record layer dissector */
static gint dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
guint *conv_version,
guint *conv_version, guint conv_cipher,
gboolean *need_desegmentation,
SslDecryptSession *conv_data,
const gboolean first_record_in_frame);
@ -431,7 +442,7 @@ static void dissect_ssl3_alert(tvbuff_t *tvb, packet_info *pinfo,
static void dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
guint32 record_length,
guint *conv_version,
guint *conv_version, guint conv_cipher,
SslDecryptSession *conv_data, const guint8 content_type);
/* hello extension dissector */
@ -459,6 +470,14 @@ static void dissect_ssl3_hnd_cert_req(tvbuff_t *tvb,
guint32 offset, packet_info *pinfo,
const guint* conv_version);
static void dissect_ssl3_hnd_srv_keyex_dh(tvbuff_t *tvb,
proto_tree *tree,
guint32 offset, guint32 length);
static void dissect_ssl3_hnd_cli_keyex_dh(tvbuff_t *tvb,
proto_tree *tree,
guint32 offset, guint32 length);
static void dissect_ssl3_hnd_finished(tvbuff_t *tvb,
proto_tree *tree,
const guint32 offset,
@ -555,6 +574,7 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
gboolean need_desegmentation;
SslDecryptSession* ssl_session;
guint* conv_version;
guint conv_cipher;
ti = NULL;
ssl_tree = NULL;
@ -592,6 +612,7 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
conversation_add_proto_data(conversation, proto_ssl, ssl_session);
}
conv_version =& ssl_session->version;
conv_cipher = ssl_session->cipher;
/* try decryption only the first time we see this packet
* (to keep cipher synchronized) */
@ -670,6 +691,7 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
offset = dissect_ssl3_record(tvb, pinfo, ssl_tree,
offset, conv_version,
conv_cipher,
&need_desegmentation,
ssl_session,
first_record_in_frame);
@ -694,6 +716,7 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* looks like sslv3 or tls */
offset = dissect_ssl3_record(tvb, pinfo, ssl_tree,
offset, conv_version,
conv_cipher,
&need_desegmentation,
ssl_session,
first_record_in_frame);
@ -1279,7 +1302,8 @@ dissect_ssl_payload(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *t
static gint
dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
guint *conv_version, gboolean *need_desegmentation,
guint *conv_version, guint conv_cipher,
gboolean *need_desegmentation,
SslDecryptSession* ssl, const gboolean first_record_in_frame)
{
@ -1561,10 +1585,10 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
/* add desegmented data to the data source list */
add_new_data_source(pinfo, decrypted, "Decrypted SSL record");
dissect_ssl3_handshake(decrypted, pinfo, ssl_record_tree, 0,
tvb_length(decrypted), conv_version, ssl, content_type);
tvb_length(decrypted), conv_version, conv_cipher, ssl, content_type);
} else {
dissect_ssl3_handshake(tvb, pinfo, ssl_record_tree, offset,
record_length, conv_version, ssl, content_type);
record_length, conv_version, conv_cipher, ssl, content_type);
}
break;
}
@ -1711,7 +1735,7 @@ dissect_ssl3_alert(tvbuff_t *tvb, packet_info *pinfo,
static void
dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, guint32 offset,
guint32 record_length, guint *conv_version,
guint32 record_length, guint *conv_version, guint conv_cipher,
SslDecryptSession* ssl, const guint8 content_type)
{
/* struct {
@ -1859,7 +1883,15 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
break;
case SSL_HND_SERVER_KEY_EXCHG:
/* unimplemented */
/* Only supports (a couple) Diffie-Hellman key exchanges.
Have to keep some state if you want to also support RSA
(server key exchange is optional and appears to be rare for RSA)
*/
{
if (conv_cipher == 0x39 || conv_cipher == 0x33) {
dissect_ssl3_hnd_srv_keyex_dh(tvb, ssl_hand_tree, offset, length);
}
}
break;
case SSL_HND_CERT_REQUEST:
@ -1875,6 +1907,9 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
break;
case SSL_HND_CLIENT_KEY_EXCHG:
if (conv_cipher == 0x39 || conv_cipher == 0x33) {
dissect_ssl3_hnd_cli_keyex_dh(tvb, ssl_hand_tree, offset, length);
}
{
/* PAOLO: here we can have all the data to build session key*/
@ -2696,6 +2731,110 @@ dissect_ssl3_hnd_cert_req(tvbuff_t *tvb,
}
static void
dissect_ssl3_hnd_srv_keyex_dh(tvbuff_t *tvb, proto_tree *tree,
guint32 offset, guint32 length)
{
gint p_len, p_len_offset;
gint g_len, g_len_offset;
gint ys_len, ys_len_offset;
gint sig_len, sig_len_offset;
proto_item *ti_dh;
proto_tree *ssl_dh_tree;
guint32 orig_offset;
orig_offset = offset;
p_len_offset = offset;
p_len = tvb_get_ntohs(tvb, offset);
offset += 2 + p_len;
if ((offset - orig_offset) > length) {
return;
}
g_len_offset = offset;
g_len = tvb_get_ntohs(tvb, offset);
offset += 2 + g_len;
if ((offset - orig_offset) > length) {
return;
}
ys_len_offset = offset;
ys_len = tvb_get_ntohs(tvb, offset);
offset += 2 + ys_len;
if ((offset - orig_offset) > length) {
return;
}
sig_len_offset = offset;
sig_len = tvb_get_ntohs(tvb, offset);
offset += 2 + sig_len;
if ((offset - orig_offset) != length) {
/* Lengths don't line up (wasn't what we expected?) */
return;
}
ti_dh = proto_tree_add_text(tree, tvb, orig_offset,
(offset - orig_offset), "Diffie-Hellman Server Params");
ssl_dh_tree = proto_item_add_subtree(ti_dh, ett_ssl_keyex_params);
/* p */
proto_tree_add_uint(ssl_dh_tree, hf_ssl_handshake_server_keyex_p_len,
tvb, p_len_offset, 2, p_len);
proto_tree_add_item(ssl_dh_tree, hf_ssl_handshake_server_keyex_p,
tvb, p_len_offset + 2, p_len, FALSE);
/* g */
proto_tree_add_uint(ssl_dh_tree, hf_ssl_handshake_server_keyex_g_len,
tvb, g_len_offset, 2, g_len);
proto_tree_add_item(ssl_dh_tree, hf_ssl_handshake_server_keyex_g,
tvb, g_len_offset + 2, g_len, FALSE);
/* Ys */
proto_tree_add_uint(ssl_dh_tree, hf_ssl_handshake_server_keyex_ys_len,
tvb, ys_len_offset, 2, ys_len);
proto_tree_add_item(ssl_dh_tree, hf_ssl_handshake_server_keyex_ys,
tvb, ys_len_offset + 2, ys_len, FALSE);
/* Sig */
proto_tree_add_uint(ssl_dh_tree, hf_ssl_handshake_server_keyex_sig_len,
tvb, sig_len_offset, 2, sig_len);
proto_tree_add_item(ssl_dh_tree, hf_ssl_handshake_server_keyex_sig,
tvb, sig_len_offset + 2, sig_len, FALSE);
}
static void
dissect_ssl3_hnd_cli_keyex_dh(tvbuff_t *tvb, proto_tree *tree,
guint32 offset, guint32 length)
{
gint yc_len, yc_len_offset;
proto_item *ti_dh;
proto_tree *ssl_dh_tree;
guint32 orig_offset;
orig_offset = offset;
yc_len_offset = offset;
yc_len = tvb_get_ntohs(tvb, offset);
offset += 2 + yc_len;
if ((offset - orig_offset) != length) {
return;
}
ti_dh = proto_tree_add_text(tree, tvb, orig_offset,
(offset - orig_offset), "Diffie-Hellman Client Params");
ssl_dh_tree = proto_item_add_subtree(ti_dh, ett_ssl_keyex_params);
/* Yc */
proto_tree_add_uint(ssl_dh_tree, hf_ssl_handshake_client_keyex_yc_len,
tvb, yc_len_offset, 2, yc_len);
proto_tree_add_item(ssl_dh_tree, hf_ssl_handshake_client_keyex_yc,
tvb, yc_len_offset + 2, yc_len, FALSE);
}
static void
dissect_ssl3_hnd_finished(tvbuff_t *tvb,
proto_tree *tree, const guint32 offset,
@ -4492,6 +4631,56 @@ proto_register_ssl(void)
FT_UINT8, BASE_DEC, VALS(ssl_31_client_certificate_type), 0x0,
NULL, HFILL }
},
{ &hf_ssl_handshake_server_keyex_p_len,
{ "p Length", "ssl.handshake.p_len",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Length of p", HFILL }
},
{ &hf_ssl_handshake_server_keyex_g_len,
{ "g Length", "ssl.handshake.g_len",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Length of g", HFILL }
},
{ &hf_ssl_handshake_server_keyex_ys_len,
{ "Pubkey Length", "ssl.handshake.ys_len",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Length of server's Diffie-Hellman public key", HFILL }
},
{ &hf_ssl_handshake_client_keyex_yc_len,
{ "Pubkey Length", "ssl.handshake.yc_len",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Length of client's Diffie-Hellman public key", HFILL }
},
{ &hf_ssl_handshake_server_keyex_sig_len,
{ "Signature Length", "ssl.handshake.sig_len",
FT_UINT16, BASE_DEC, NULL, 0x0,
"Length of Signature", HFILL }
},
{ &hf_ssl_handshake_server_keyex_p,
{ "p", "ssl.handshake.p",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Diffie-Hellman p", HFILL }
},
{ &hf_ssl_handshake_server_keyex_g,
{ "g", "ssl.handshake.g",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Diffie-Hellman g", HFILL }
},
{ &hf_ssl_handshake_server_keyex_ys,
{ "pubkey", "ssl.handshake.ys",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Diffie-Hellman server pubkey", HFILL }
},
{ &hf_ssl_handshake_client_keyex_yc,
{ "pubkey", "ssl.handshake.yc",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Diffie-Hellman client pubkey", HFILL }
},
{ &hf_ssl_handshake_server_keyex_sig,
{ "signature", "ssl.handshake.sig",
FT_BYTES, BASE_NONE, NULL, 0x0,
"Diffie-Hellman server signature", HFILL }
},
{ &hf_ssl_handshake_sig_hash_alg_len,
{ "Signature Hash Algorithms Length", "ssl.handshake.sig_hash_alg_len",
FT_UINT16, BASE_DEC, NULL, 0x0,
@ -4765,6 +4954,7 @@ proto_register_ssl(void)
&ett_ssl_sig_hash_alg,
&ett_ssl_dnames,
&ett_ssl_random,
&ett_ssl_keyex_params,
&ett_ssl_cert_status,
&ett_ssl_ocsp_resp,
&ett_pct_cipher_suites,