ssl,dtls: move ServerHello to ssl-utils

Changes to ServerHello:

 - Get rid of session parameter as the SslDecryptSession already
   provides a reference to SslSession. Done for the new
   ssl_dissect_hnd_srv_hello and ssl_dissect_hnd_hello_ext functions.
 - No need to generate the keyring here, decryption is only needed after
   ChangeCipherSpec and the keyring will be generated there provided
   that there are enough params (cipher, version, master-secret, etc.)
 - Get rid of labels and goto in favor of if/else.
 - DTLS: SSL_HAVE_SESSION_KEY is implicitly set when
   ssl_generate_keyring_material succeeds, no need to set it. Remove it.
 - Remove `if (tree || ssl)` since expert info seems not to apply
   otherwise (this also needs changes in common and handshake
   dissection). (Expert info from the TLS extensions, not the
   ServerHello itself.)

Other changes:

 - ClientHello: renamed some fields shared with ServerHello.

Change-Id: I466b905d990489e03250bac97bf9d862ff82ce6c
Reviewed-on: https://code.wireshark.org/review/3020
Reviewed-by: Evan Huus <eapache@gmail.com>
This commit is contained in:
Peter Wu 2014-07-19 11:12:49 +02:00 committed by Evan Huus
parent fbcfe6eccb
commit aa09feaf52
4 changed files with 99 additions and 222 deletions

View File

@ -105,15 +105,12 @@ static gint hf_dtls_handshake_message_seq = -1;
static gint hf_dtls_handshake_fragment_offset = -1;
static gint hf_dtls_handshake_fragment_length = -1;
static gint hf_dtls_handshake_client_version = -1;
static gint hf_dtls_handshake_server_version = -1;
static gint hf_dtls_handshake_cookie_len = -1;
static gint hf_dtls_handshake_cookie = -1;
static gint hf_dtls_handshake_cipher_suites_len = -1;
static gint hf_dtls_handshake_cipher_suites = -1;
static gint hf_dtls_handshake_cipher_suite = -1;
static gint hf_dtls_handshake_comp_methods_len = -1;
static gint hf_dtls_handshake_comp_methods = -1;
static gint hf_dtls_handshake_comp_method = -1;
static gint hf_dtls_handshake_session_ticket_lifetime_hint = -1;
static gint hf_dtls_handshake_session_ticket_len = -1;
static gint hf_dtls_handshake_session_ticket = -1;
@ -325,12 +322,6 @@ static void dissect_dtls_hnd_cli_hello(tvbuff_t *tvb,
SslSession *session,
SslDecryptSession* ssl);
static int dissect_dtls_hnd_srv_hello(tvbuff_t *tvb,
proto_tree *tree,
guint32 offset, guint32 length,
SslSession *session,
SslDecryptSession* ssl);
static int dissect_dtls_hnd_hello_verify_request(tvbuff_t *tvb,
proto_tree *tree,
guint32 offset,
@ -1357,7 +1348,8 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
break;
case SSL_HND_SERVER_HELLO:
dissect_dtls_hnd_srv_hello(sub_tvb, ssl_hand_tree, 0, length, session, ssl);
ssl_dissect_hnd_srv_hello(&dissect_dtls_hf, sub_tvb, ssl_hand_tree,
0, length, session, ssl);
break;
case SSL_HND_HELLO_VERIFY_REQUEST:
@ -1583,7 +1575,7 @@ dissect_dtls_hnd_cli_hello(tvbuff_t *tvb, packet_info *pinfo,
while (cipher_suite_length > 0)
{
proto_tree_add_item(cs_tree, hf_dtls_handshake_cipher_suite,
proto_tree_add_item(cs_tree, dissect_dtls_hf.hf.hs_cipher_suite,
tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
cipher_suite_length -= 2;
@ -1613,7 +1605,7 @@ dissect_dtls_hnd_cli_hello(tvbuff_t *tvb, packet_info *pinfo,
{
compression_method = tvb_get_guint8(tvb, offset);
if (compression_method < 64)
proto_tree_add_uint(cs_tree, hf_dtls_handshake_comp_method,
proto_tree_add_uint(cs_tree, dissect_dtls_hf.hf.hs_comp_method,
tvb, offset, 1, compression_method);
else if (compression_method > 63 && compression_method < 193)
proto_tree_add_text(cs_tree, tvb, offset, 1,
@ -1637,93 +1629,6 @@ dissect_dtls_hnd_cli_hello(tvbuff_t *tvb, packet_info *pinfo,
}
}
static int
dissect_dtls_hnd_srv_hello(tvbuff_t *tvb,
proto_tree *tree, guint32 offset, guint32 length,
SslSession *session, SslDecryptSession *ssl)
{
/* struct {
* ProtocolVersion server_version;
* Random random;
* SessionID session_id;
* CipherSuite cipher_suite;
* CompressionMethod compression_method;
* Extension server_hello_extension_list<0..2^16-1>;
* } ServerHello;
*/
guint16 start_offset;
start_offset = offset;
if (tree || ssl)
{
/* show the server version */
proto_tree_add_item(tree, hf_dtls_handshake_server_version, tvb,
offset, 2, ENC_BIG_ENDIAN);
offset += 2;
/* first display the elements conveniently in
* common with client hello
*/
offset = ssl_dissect_hnd_hello_common(&dissect_dtls_hf, tvb, tree, offset, ssl, TRUE);
/* PAOLO: handle session cipher suite */
if (ssl) {
/* store selected cipher suite for decryption */
ssl->session.cipher = tvb_get_ntohs(tvb, offset);
if (ssl_find_cipher(ssl->session.cipher,&ssl->cipher_suite) < 0) {
ssl_debug_printf("dissect_dtls_hnd_srv_hello can't find cipher suite %X\n", ssl->session.cipher);
goto no_cipher;
}
ssl->state |= SSL_CIPHER;
ssl_debug_printf("dissect_dtls_hnd_srv_hello found cipher %X, state %X\n",
ssl->session.cipher, ssl->state);
/* if we have restored a session now we can have enough material
* to build session key, check it out*/
if ((ssl->state &
(SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION|SSL_MASTER_SECRET)) !=
(SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION|SSL_MASTER_SECRET)) {
ssl_debug_printf("dissect_dtls_hnd_srv_hello not enough data to generate key (required state %X)\n",
(SSL_CIPHER|SSL_CLIENT_RANDOM|SSL_SERVER_RANDOM|SSL_VERSION|SSL_MASTER_SECRET));
goto no_cipher;
}
ssl_debug_printf("dissect_dtls_hnd_srv_hello trying to generate keys\n");
if (ssl_generate_keyring_material(ssl)<0) {
ssl_debug_printf("dissect_dtls_hnd_srv_hello can't generate keyring material\n");
goto no_cipher;
}
ssl->state |= SSL_HAVE_SESSION_KEY;
}
no_cipher:
if (ssl) {
/* store selected compression method for decompression */
ssl->session.compression = tvb_get_guint8(tvb, offset+2);
}
/* now the server-selected cipher suite */
proto_tree_add_item(tree, hf_dtls_handshake_cipher_suite,
tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
/* and the server-selected compression method */
proto_tree_add_item(tree, hf_dtls_handshake_comp_method,
tvb, offset, 1, ENC_BIG_ENDIAN);
offset++;
if (length > offset - start_offset)
{
offset = ssl_dissect_hnd_hello_ext(&dissect_dtls_hf, tvb, tree, offset,
length - (offset - start_offset),
FALSE, session, ssl);
}
}
return offset;
}
static int
dissect_dtls_hnd_hello_verify_request(tvbuff_t *tvb, proto_tree *tree,
guint32 offset, SslDecryptSession* ssl _U_)
@ -1738,7 +1643,7 @@ dissect_dtls_hnd_hello_verify_request(tvbuff_t *tvb, proto_tree *tree,
guint8 cookie_length;
/* show the client version */
proto_tree_add_item(tree, hf_dtls_handshake_server_version, tvb,
proto_tree_add_item(tree, dissect_dtls_hf.hf.hs_server_version, tvb,
offset, 2, ENC_BIG_ENDIAN);
offset += 2;
@ -2040,11 +1945,6 @@ proto_register_dtls(void)
FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
"Maximum version supported by client", HFILL }
},
{ &hf_dtls_handshake_server_version,
{ "Version", "dtls.handshake.server_version",
FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
"Version selected by server", HFILL }
},
{ &hf_dtls_handshake_cipher_suites_len,
{ "Cipher Suites Length", "dtls.handshake.cipher_suites_length",
FT_UINT16, BASE_DEC, NULL, 0x0,
@ -2055,11 +1955,6 @@ proto_register_dtls(void)
FT_NONE, BASE_NONE, NULL, 0x0,
"List of cipher suites supported by client", HFILL }
},
{ &hf_dtls_handshake_cipher_suite,
{ "Cipher Suite", "dtls.handshake.ciphersuite",
FT_UINT16, BASE_HEX|BASE_EXT_STRING, &ssl_31_ciphersuite_ext, 0x0,
NULL, HFILL }
},
{ &hf_dtls_handshake_cookie_len,
{ "Cookie Length", "dtls.handshake.cookie_length",
FT_UINT8, BASE_DEC, NULL, 0x0,
@ -2080,11 +1975,6 @@ proto_register_dtls(void)
FT_NONE, BASE_NONE, NULL, 0x0,
"List of compression methods supported by client", HFILL }
},
{ &hf_dtls_handshake_comp_method,
{ "Compression Method", "dtls.handshake.comp_method",
FT_UINT8, BASE_DEC, VALS(ssl_31_compression_method), 0x0,
NULL, HFILL }
},
{ &hf_dtls_handshake_session_ticket_lifetime_hint,
{ "Session Ticket Lifetime Hint", "dtls.handshake.session_ticket_lifetime_hint",
FT_UINT32, BASE_DEC, NULL, 0x0,

View File

@ -5236,6 +5236,67 @@ ssl_dissect_hnd_hello_common(ssl_common_dissect_t *hf, tvbuff_t *tvb,
return offset;
}
void
ssl_dissect_hnd_srv_hello(ssl_common_dissect_t *hf, tvbuff_t *tvb,
proto_tree *tree, guint32 offset, guint32 length,
SslSession *session, SslDecryptSession *ssl)
{
/* struct {
* ProtocolVersion server_version;
* Random random;
* SessionID session_id;
* CipherSuite cipher_suite;
* CompressionMethod compression_method;
* Extension server_hello_extension_list<0..2^16-1>;
* } ServerHello;
*/
guint16 start_offset = offset;
/* show the server version */
proto_tree_add_item(tree, hf->hf.hs_server_version, tvb,
offset, 2, ENC_BIG_ENDIAN);
offset += 2;
/* dissect fields that are also present in ClientHello */
offset = ssl_dissect_hnd_hello_common(hf, tvb, tree, offset, ssl, TRUE);
if (ssl) {
/* store selected cipher suite for decryption */
ssl->session.cipher = tvb_get_ntohs(tvb, offset);
if (ssl_find_cipher(ssl->session.cipher, &ssl->cipher_suite) < 0) {
ssl_debug_printf("%s can't find cipher suite 0x%04X\n",
G_STRFUNC, ssl->session.cipher);
} else {
/* Cipher found, save this for the delayed decoder init */
ssl->state |= SSL_CIPHER;
ssl_debug_printf("%s found CIPHER 0x%04X -> state 0x%02X\n",
G_STRFUNC, ssl->session.cipher, ssl->state);
}
}
/* now the server-selected cipher suite */
proto_tree_add_item(tree, hf->hf.hs_cipher_suite,
tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
if (ssl) {
/* store selected compression method for decryption */
ssl->session.compression = tvb_get_guint8(tvb, offset);
}
/* and the server-selected compression method */
proto_tree_add_item(tree, hf->hf.hs_comp_method,
tvb, offset, 1, ENC_BIG_ENDIAN);
offset++;
/* remaining data are extensions */
if (length > offset - start_offset) {
ssl_dissect_hnd_hello_ext(hf, tvb, tree, offset,
length - (offset - start_offset), FALSE,
session, ssl);
}
}
void
ssl_dissect_hnd_cert(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
guint32 offset, packet_info *pinfo,
@ -5726,7 +5787,10 @@ ssl_dissect_hnd_hello_ext(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *t
case SSL_HND_HELLO_EXT_CERT_TYPE:
case SSL_HND_HELLO_EXT_SERVER_CERT_TYPE:
case SSL_HND_HELLO_EXT_CLIENT_CERT_TYPE:
offset = ssl_dissect_hnd_hello_ext_cert_type(hf, tvb, ext_tree, offset, ext_len, is_client, ext_type, session);
offset = ssl_dissect_hnd_hello_ext_cert_type(hf, tvb, ext_tree,
offset, ext_len,
is_client, ext_type,
session);
break;
default:
proto_tree_add_bytes_format(ext_tree, hf->hf.hs_ext_data,

View File

@ -692,6 +692,9 @@ typedef struct ssl_common_dissect {
gint hs_random_bytes;
gint hs_session_id;
gint hs_session_id_len;
gint hs_server_version;
gint hs_cipher_suite;
gint hs_comp_method;
/* do not forget to update SSL_COMMON_LIST_T and SSL_COMMON_HF_LIST! */
} hf;
@ -734,6 +737,11 @@ ssl_dissect_hnd_hello_common(ssl_common_dissect_t *hf, tvbuff_t *tvb,
proto_tree *tree, guint32 offset,
SslDecryptSession *ssl, gboolean from_server);
extern void
ssl_dissect_hnd_srv_hello(ssl_common_dissect_t *hf, tvbuff_t *tvb,
proto_tree *tree, guint32 offset, guint32 length,
SslSession *session, SslDecryptSession *ssl);
extern gint
ssl_dissect_hash_alg_list(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
guint32 offset, guint16 len);
@ -770,7 +778,7 @@ ssl_common_dissect_t name = { \
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, \
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, \
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, \
-1, -1, -1, -1, \
-1, -1, -1, -1, -1, -1, -1, \
}, \
/* ett */ { \
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, \
@ -1203,6 +1211,21 @@ ssl_common_dissect_t name = { \
{ "Session ID Length", prefix ".handshake.session_id_length", \
FT_UINT8, BASE_DEC, NULL, 0x0, \
"Length of Session ID field", HFILL } \
}, \
{ & name .hf.hs_server_version, \
{ "Version", prefix ".handshake.version", \
FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0, \
"Version selected by server", HFILL } \
}, \
{ & name .hf.hs_cipher_suite, \
{ "Cipher Suite", prefix ".handshake.ciphersuite", \
FT_UINT16, BASE_HEX|BASE_EXT_STRING, &ssl_31_ciphersuite_ext, 0x0, \
NULL, HFILL } \
}, \
{ & name .hf.hs_comp_method, \
{ "Compression Method", prefix ".handshake.comp_method", \
FT_UINT8, BASE_DEC, VALS(ssl_31_compression_method), 0x0, \
NULL, HFILL } \
}
/* }}} */

View File

@ -148,13 +148,10 @@ static gint hf_ssl_handshake_protocol = -1;
static gint hf_ssl_handshake_type = -1;
static gint hf_ssl_handshake_length = -1;
static gint hf_ssl_handshake_client_version = -1;
static gint hf_ssl_handshake_server_version = -1;
static gint hf_ssl_handshake_cipher_suites_len = -1;
static gint hf_ssl_handshake_cipher_suites = -1;
static gint hf_ssl_handshake_cipher_suite = -1;
static gint hf_ssl_handshake_comp_methods_len = -1;
static gint hf_ssl_handshake_comp_methods = -1;
static gint hf_ssl_handshake_comp_method = -1;
static gint hf_ssl_handshake_session_ticket_lifetime_hint = -1;
static gint hf_ssl_handshake_session_ticket_len = -1;
static gint hf_ssl_handshake_session_ticket = -1;
@ -480,12 +477,6 @@ static void dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb, packet_info *pinfo,
SslSession *session,
SslDecryptSession *ssl);
static void dissect_ssl3_hnd_srv_hello(tvbuff_t *tvb,
proto_tree *tree,
guint32 offset, guint32 length,
SslSession *session,
SslDecryptSession *ssl);
static void dissect_ssl3_hnd_new_ses_ticket(tvbuff_t *tvb,
proto_tree *tree,
guint32 offset, guint32 length,
@ -1959,7 +1950,8 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
break;
case SSL_HND_SERVER_HELLO:
dissect_ssl3_hnd_srv_hello(tvb, ssl_hand_tree, offset, length, session, ssl);
ssl_dissect_hnd_srv_hello(&dissect_ssl3_hf, tvb, ssl_hand_tree,
offset, length, session, ssl);
break;
case SSL_HND_HELLO_VERIFY_REQUEST:
@ -2195,7 +2187,7 @@ dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb, packet_info *pinfo,
while (cipher_suite_length > 0)
{
proto_tree_add_item(cs_tree, hf_ssl_handshake_cipher_suite,
proto_tree_add_item(cs_tree, dissect_ssl3_hf.hf.hs_cipher_suite,
tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
cipher_suite_length -= 2;
@ -2228,7 +2220,7 @@ dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb, packet_info *pinfo,
{
compression_method = tvb_get_guint8(tvb, offset);
if (compression_method < 64)
proto_tree_add_uint(cs_tree, hf_ssl_handshake_comp_method,
proto_tree_add_uint(cs_tree, dissect_ssl3_hf.hf.hs_comp_method,
tvb, offset, 1, compression_method);
else if (compression_method > 63 && compression_method < 193)
proto_tree_add_text(cs_tree, tvb, offset, 1,
@ -2251,83 +2243,6 @@ dissect_ssl3_hnd_cli_hello(tvbuff_t *tvb, packet_info *pinfo,
}
}
static void
dissect_ssl3_hnd_srv_hello(tvbuff_t *tvb,
proto_tree *tree, guint32 offset, guint32 length,
SslSession *session, SslDecryptSession *ssl)
{
/* struct {
* ProtocolVersion server_version;
* Random random;
* SessionID session_id;
* CipherSuite cipher_suite;
* CompressionMethod compression_method;
* Extension server_hello_extension_list<0..2^16-1>;
* } ServerHello;
*/
guint16 start_offset;
start_offset = offset;
if (tree || ssl)
{
/* show the server version */
if (tree)
proto_tree_add_item(tree, hf_ssl_handshake_server_version, tvb,
offset, 2, ENC_BIG_ENDIAN);
offset += 2;
/* first display the elements conveniently in
* common with client hello
*/
offset = ssl_dissect_hnd_hello_common(&dissect_ssl3_hf, tvb, tree, offset, ssl, TRUE);
/* PAOLO: handle session cipher suite */
if (ssl) {
/* store selected cipher suite for decryption */
ssl->session.cipher = tvb_get_ntohs(tvb, offset);
if (ssl_find_cipher(ssl->session.cipher,&ssl->cipher_suite) < 0) {
ssl_debug_printf("dissect_ssl3_hnd_srv_hello can't find cipher suite 0x%X\n", ssl->session.cipher);
goto no_cipher;
}
ssl->state |= SSL_CIPHER;
ssl_debug_printf("dissect_ssl3_hnd_srv_hello found CIPHER 0x%04X -> state 0x%02X\n",
ssl->session.cipher, ssl->state);
/* if we have restored a session now we can have enough material
* to build session key, check it out*/
ssl_debug_printf("dissect_ssl3_hnd_srv_hello trying to generate keys\n");
if (ssl_generate_keyring_material(ssl)<0) {
ssl_debug_printf("dissect_ssl3_hnd_srv_hello can't generate keyring material\n");
goto no_cipher;
}
}
no_cipher:
/* now the server-selected cipher suite */
proto_tree_add_item(tree, hf_ssl_handshake_cipher_suite,
tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
if (ssl) {
/* store selected compression method for decryption */
ssl->session.compression = tvb_get_guint8(tvb, offset);
}
/* and the server-selected compression method */
proto_tree_add_item(tree, hf_ssl_handshake_comp_method,
tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
if (length > offset - start_offset)
{
ssl_dissect_hnd_hello_ext(&dissect_ssl3_hf, tvb, tree, offset,
length - (offset - start_offset), FALSE,
session, ssl);
}
}
}
static void
dissect_ssl3_hnd_new_ses_ticket(tvbuff_t *tvb, proto_tree *tree,
guint32 offset, guint32 length, SslDecryptSession *ssl)
@ -3468,7 +3383,7 @@ dissect_ssl2_hnd_server_hello(tvbuff_t *tvb,
offset += 1;
/* now the server version */
proto_tree_add_item(tree, hf_ssl_handshake_server_version,
proto_tree_add_item(tree, dissect_ssl3_hf.hf.hs_server_version,
tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
@ -4087,11 +4002,6 @@ proto_register_ssl(void)
FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
"Maximum version supported by client", HFILL }
},
{ &hf_ssl_handshake_server_version,
{ "Version", "ssl.handshake.version",
FT_UINT16, BASE_HEX, VALS(ssl_versions), 0x0,
"Version selected by server", HFILL }
},
{ &hf_ssl_handshake_cipher_suites_len,
{ "Cipher Suites Length", "ssl.handshake.cipher_suites_length",
FT_UINT16, BASE_DEC, NULL, 0x0,
@ -4102,11 +4012,6 @@ proto_register_ssl(void)
FT_NONE, BASE_NONE, NULL, 0x0,
"List of cipher suites supported by client", HFILL }
},
{ &hf_ssl_handshake_cipher_suite,
{ "Cipher Suite", "ssl.handshake.ciphersuite",
FT_UINT16, BASE_HEX|BASE_EXT_STRING, &ssl_31_ciphersuite_ext, 0x0,
NULL, HFILL }
},
{ &hf_ssl2_handshake_cipher_spec,
{ "Cipher Spec", "ssl.handshake.cipherspec",
FT_UINT24, BASE_HEX|BASE_EXT_STRING, &ssl_20_cipher_suites_ext, 0x0,
@ -4122,11 +4027,6 @@ proto_register_ssl(void)
FT_NONE, BASE_NONE, NULL, 0x0,
"List of compression methods supported by client", HFILL }
},
{ &hf_ssl_handshake_comp_method,
{ "Compression Method", "ssl.handshake.comp_method",
FT_UINT8, BASE_DEC, VALS(ssl_31_compression_method), 0x0,
NULL, HFILL }
},
{ &hf_ssl_handshake_session_ticket_lifetime_hint,
{ "Session Ticket Lifetime Hint", "ssl.handshake.session_ticket_lifetime_hint",
FT_UINT32, BASE_DEC, NULL, 0x0,