aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-ssl-utils.c
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2014-01-20 20:26:04 +0000
committerAnders Broman <anders.broman@ericsson.com>2014-01-20 20:26:04 +0000
commitf0fb43a6215f0845face2b5dd0df568012321ae1 (patch)
treef524a884c4a06a6ce2102c6126631861f6c59f30 /epan/dissectors/packet-ssl-utils.c
parent6402d8590ea0fe7bfb6fbc8d530cce64a0080183 (diff)
From alexeyv:
Add decryption for resumed TLS sessions with a session ticket. https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=5963 svn path=/trunk/; revision=54860
Diffstat (limited to 'epan/dissectors/packet-ssl-utils.c')
-rw-r--r--epan/dissectors/packet-ssl-utils.c80
1 files changed, 77 insertions, 3 deletions
diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c
index 240839c529..4dc89c8d83 100644
--- a/epan/dissectors/packet-ssl-utils.c
+++ b/epan/dissectors/packet-ssl-utils.c
@@ -1043,7 +1043,7 @@ const value_string tls_hello_extension_types[] = {
{ SSL_HND_HELLO_EXT_HEARTBEAT, "Heartbeat" }, /* RFC 6520 */
{ SSL_HND_HELLO_EXT_ALPN, "Application Layer Protocol Negotiation" }, /* draft-ietf-tls-applayerprotoneg-01 */
{ SSL_HND_HELLO_EXT_STATUS_REQUEST_V2, "status_request_v2" }, /* RFC 6961 */
- { 35, "SessionTicket TLS" }, /* RFC 4507 */
+ { SSL_HND_HELLO_EXT_SESSION_TICKET, "SessionTicket TLS" }, /* RFC 4507 */
{ SSL_HND_HELLO_EXT_NPN, "next_protocol_negotiation"}, /* http://technotes.googlecode.com/git/nextprotoneg.html */
{ SSL_HND_HELLO_EXT_RENEG_INFO, "renegotiation_info" }, /* RFC 5746 */
{ 0, NULL }
@@ -3668,6 +3668,8 @@ ssl_session_init(SslDecryptSession* ssl_session)
ssl_session->session_id.data = ssl_session->_session_id;
ssl_session->client_random.data = ssl_session->_client_random;
ssl_session->server_random.data = ssl_session->_server_random;
+ ssl_session->session_ticket.data = ssl_session->_session_ticket;
+ ssl_session->session_ticket.data_len = 0;
ssl_session->master_secret.data_len = 48;
ssl_session->server_data_for_iv.data_len = 0;
ssl_session->server_data_for_iv.data = ssl_session->_server_data_for_iv;
@@ -4126,6 +4128,58 @@ ssl_restore_session(SslDecryptSession* ssl, GHashTable *session_hash)
return TRUE;
}
+/* store master secret into session data cache */
+void
+ssl_save_session_ticket(SslDecryptSession* ssl, GHashTable *session_hash)
+{
+ /* allocate stringinfo chunks for session id and master secret data*/
+ StringInfo* session_ticket;
+ StringInfo* master_secret;
+
+ if (ssl->session_ticket.data_len == 0) {
+ ssl_debug_printf("ssl_save_session_ticket - session ticket is empty!\n");
+ return;
+ }
+
+ session_ticket = (StringInfo *)wmem_alloc0(wmem_file_scope(), sizeof(StringInfo) + ssl->session_ticket.data_len);
+ master_secret = (StringInfo *)wmem_alloc0(wmem_file_scope(), 48 + sizeof(StringInfo));
+
+ master_secret->data = ((guchar*)master_secret+sizeof(StringInfo));
+
+ /* ssl_hash() depends on session_id->data being aligned for guint access
+ * so be careful in changing how it is allocated.
+ */
+ session_ticket->data = ((guchar*)session_ticket+sizeof(StringInfo));
+
+ ssl_data_set(session_ticket, ssl->session_ticket.data, ssl->session_ticket.data_len);
+ ssl_data_set(master_secret, ssl->master_secret.data, ssl->master_secret.data_len);
+ g_hash_table_insert(session_hash, session_ticket, master_secret);
+ ssl_print_string("ssl_save_session_ticket stored session_ticket", session_ticket);
+ ssl_print_string("ssl_save_session_ticket stored master secret", master_secret);
+}
+
+gboolean
+ssl_restore_session_ticket(SslDecryptSession* ssl, GHashTable *session_hash)
+{
+ StringInfo* ms;
+
+ if (ssl->session_ticket.data_len == 0) {
+ ssl_debug_printf("ssl_restore_session_ticket Cannot restore using an empty session ticket\n");
+ return FALSE;
+ }
+
+ ms = (StringInfo *)g_hash_table_lookup(session_hash, &ssl->session_ticket);
+
+ if (!ms) {
+ ssl_debug_printf("ssl_restore_session_ticket can't find stored session ticket\n");
+ return FALSE;
+ }
+ ssl_data_set(&ssl->master_secret, ms->data, ms->data_len);
+ ssl->state |= SSL_MASTER_SECRET;
+ ssl_debug_printf("ssl_restore_session_ticket master key retrieved\n");
+ return TRUE;
+}
+
int
ssl_is_valid_content_type(guint8 type)
{
@@ -4747,6 +4801,23 @@ ssl_dissect_hnd_hello_ext_server_name(ssl_common_dissect_t *hf, tvbuff_t *tvb,
return offset;
}
+static gint
+ssl_dissect_hnd_hello_ext_session_ticket(ssl_common_dissect_t *hf, tvbuff_t *tvb,
+ proto_tree *tree, guint32 offset, guint32 ext_len, gboolean is_client, SslDecryptSession *ssl)
+{
+ if(is_client && ssl && ext_len != 0)
+ {
+ /*save the ticket on the ssl opaque so that we can use it as key on server hello */
+ tvb_memcpy(tvb,ssl->session_ticket.data, offset, ext_len);
+ ssl->session_ticket.data_len = ext_len;
+ }
+ proto_tree_add_bytes_format(tree, hf->hf.hs_ext_data,
+ tvb, offset, ext_len, NULL,
+ "Data (%u byte%s)",
+ ext_len, plurality(ext_len, "", "s"));
+ return offset + ext_len;
+}
+
void
ssl_dissect_hnd_cert_url(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree, guint32 offset)
{
@@ -4950,14 +5021,14 @@ ssl_dissect_hnd_hello_ext_ec_point_formats(ssl_common_dissect_t *hf, tvbuff_t *t
gint
ssl_dissect_hnd_hello_ext(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
- guint32 offset, guint32 left, gboolean is_client)
+ guint32 offset, guint32 left, gboolean is_client, SslDecryptSession *ssl)
{
guint16 extension_length;
guint16 ext_type;
guint16 ext_len;
proto_item *pi;
proto_tree *ext_tree;
-
+
if (left < 2)
return offset;
@@ -5027,6 +5098,9 @@ ssl_dissect_hnd_hello_ext(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *t
tvb, offset, 1, ENC_BIG_ENDIAN);
offset += ext_len;
break;
+ case SSL_HND_HELLO_EXT_SESSION_TICKET:
+ offset = ssl_dissect_hnd_hello_ext_session_ticket(hf, tvb, ext_tree, offset, ext_len, is_client, ssl);
+ break;
default:
proto_tree_add_bytes_format(ext_tree, hf->hf.hs_ext_data,
tvb, offset, ext_len, NULL,