aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
Diffstat (limited to 'epan')
-rw-r--r--epan/dissectors/packet-ssl-utils.c34
-rw-r--r--epan/dissectors/packet-ssl-utils.h16
-rw-r--r--epan/dissectors/packet-ssl.c136
3 files changed, 129 insertions, 57 deletions
diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c
index ee3b2bdeb0..e9fb2730e4 100644
--- a/epan/dissectors/packet-ssl-utils.c
+++ b/epan/dissectors/packet-ssl-utils.c
@@ -179,6 +179,13 @@ ssl_get_cipher_by_name(const char* name)
return gcry_cipher_map_name(name);
}
+static inline void
+ssl_cipher_cleanup(gcry_cipher_hd_t *cipher)
+{
+ gcry_cipher_close(*cipher);
+ *cipher = NULL;
+}
+
/* private key abstraction layer */
static inline int
ssl_get_key_len(SSL_PRIVATE_KEY* pk) {return gcry_pk_get_nbits (pk); }
@@ -355,8 +362,8 @@ static SslCipherSuite cipher_suites[]={
{5,KEX_RSA,SIG_RSA,ENC_RC4,1,128,128,DIG_SHA,20,0, SSL_CIPHER_MODE_STREAM},
{6,KEX_RSA,SIG_RSA,ENC_RC2,8,128,40,DIG_SHA,20,1, SSL_CIPHER_MODE_STREAM},
{7,KEX_RSA,SIG_RSA,ENC_IDEA,8,128,128,DIG_SHA,20,0, SSL_CIPHER_MODE_STREAM},
- {8,KEX_RSA,SIG_RSA,ENC_DES,8,64,40,DIG_SHA,20,1, SSL_CIPHER_MODE_STREAM},
- {9,KEX_RSA,SIG_RSA,ENC_DES,8,64,64,DIG_SHA,20,0, SSL_CIPHER_MODE_STREAM},
+ {8,KEX_RSA,SIG_RSA,ENC_DES,8,64,40,DIG_SHA,20,1, SSL_CIPHER_MODE_CBC},
+ {9,KEX_RSA,SIG_RSA,ENC_DES,8,64,64,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC},
{10,KEX_RSA,SIG_RSA,ENC_3DES,8,192,192,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC},
{11,KEX_DH,SIG_DSS,ENC_DES,8,64,40,DIG_SHA,20,1, SSL_CIPHER_MODE_STREAM},
{12,KEX_DH,SIG_DSS,ENC_DES,8,64,64,DIG_SHA,20,0, SSL_CIPHER_MODE_STREAM},
@@ -591,7 +598,7 @@ ssl_create_decoder(SslDecoder *dec, SslCipherSuite *cipher_suite,
}
if (ciph == 0) {
ssl_debug_printf("ssl_create_decoder can't find cipher %s\n",
- ciphers[(cipher_suite->enc-0x30) > 7 ? 7 : (cipher_suite->enc-0x30)]);
+ ciphers[(cipher_suite->enc-0x30) > 7 ? 7 : (cipher_suite->enc-0x30)]);
return -1;
}
@@ -600,6 +607,10 @@ ssl_create_decoder(SslDecoder *dec, SslCipherSuite *cipher_suite,
dec->cipher_suite=cipher_suite;
dec->mac_key.data = dec->_mac_key;
ssl_data_set(&dec->mac_key, mk, cipher_suite->dig_len);
+ dec->seq = 0;
+
+ if (dec->evp)
+ ssl_cipher_cleanup(&dec->evp);
if (ssl_cipher_init(&dec->evp,ciph,sk,iv,cipher_suite->mode) < 0) {
ssl_debug_printf("ssl_create_decoder: can't create cipher id:%d mode:%d\n",
@@ -812,7 +823,9 @@ ssl_generate_keyring_material(SslDecryptSession*ssl_session)
ssl_debug_printf("ssl_generate_keyring_material can't init client decoder\n");
goto fail;
}
-
+
+ ssl_debug_printf("ssl_generate_keyring_material client seq %d server seq %d\n",
+ ssl_session->client.seq, ssl_session->server.seq);
g_free(key_block.data);
return 0;
@@ -853,7 +866,7 @@ ssl_decrypt_pre_master_secret(SslDecryptSession*ssl_session,
/* Remove the master secret if it was there.
This force keying material regeneration in
case we're renegotiating */
- ssl_session->state &= ~SSL_MASTER_SECRET;
+ ssl_session->state &= ~(SSL_MASTER_SECRET|SSL_HAVE_SESSION_KEY);
return 0;
}
@@ -926,10 +939,7 @@ ssl3_check_mac(SslDecoder*decoder,int ct,guint8* data,
/* get cipher used for digest comptuation */
md=ssl_get_digest_by_name(digests[decoder->cipher_suite->dig-0x40]);
- ssl_debug_printf("ssl3_check_mac digest%s md %d\n",
- digests[decoder->cipher_suite->dig-0x40], md);
ssl_md_init(&mc,md);
- ssl_debug_printf("ssl3_check_mac memory digest %p\n",mc);
/* do hash computation on data && padding */
ssl_md_update(&mc,decoder->mac_key.data,decoder->mac_key.data_len);
@@ -1009,19 +1019,19 @@ ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, int ct,
return -1;
}
mac=out+worklen;
- /*ssl_print_data("Record data",out,*outl);*/
/* Now check the MAC */
- ssl_debug_printf("checking mac (len %d, version %X, ct %d)\n", worklen,ssl->version_netorder, ct);
+ ssl_debug_printf("checking mac (len %d, version %X, ct %d seq %d)\n",
+ worklen, ssl->version_netorder, ct, decoder->seq);
if(ssl->version_netorder==0x300){
if(ssl3_check_mac(decoder,ct,out,worklen,mac) < 0) {
- ssl_debug_printf("ssl_decrypt_record: mac falied\n");
+ ssl_debug_printf("ssl_decrypt_record: mac failed\n");
return -1;
}
}
else{
if(tls_check_mac(decoder,ct,ssl->version_netorder,out,worklen,mac)< 0) {
- ssl_debug_printf("ssl_decrypt_record: mac falied\n");
+ ssl_debug_printf("ssl_decrypt_record: mac failed\n");
return -1;
}
}
diff --git a/epan/dissectors/packet-ssl-utils.h b/epan/dissectors/packet-ssl-utils.h
index f852e5c4c3..4a4f71aeba 100644
--- a/epan/dissectors/packet-ssl-utils.h
+++ b/epan/dissectors/packet-ssl-utils.h
@@ -113,10 +113,18 @@ typedef struct _SslDecoder {
#define DIG_MD5 0x40
#define DIG_SHA 0x41
-/*typedef struct _SslService {
- address addr;
- guint port;
-} SslService;*/
+struct tvbuff;
+
+typedef struct _SslRecordInfo {
+ struct tvbuff* tvb;
+ int id;
+ struct _SslRecordInfo* next;
+} SslRecordInfo;
+
+typedef struct {
+ StringInfo app_data;
+ SslRecordInfo* handshake_data;
+} SslPacketInfo;
typedef struct _SslDecryptSession {
unsigned char _master_secret[48];
diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c
index 6fc2d7c9d8..b43a13dab3 100644
--- a/epan/dissectors/packet-ssl.c
+++ b/epan/dissectors/packet-ssl.c
@@ -231,6 +231,7 @@ static GHashTable *ssl_key_hash = NULL;
static GTree* ssl_associations = NULL;
static dissector_handle_t ssl_handle = NULL;
static StringInfo ssl_decrypted_data = {NULL, 0};
+static int ssl_decrypted_data_avail = 0;
/* Hash Functions for ssl sessions table and private keys table*/
static gint
@@ -349,6 +350,44 @@ ssl_packet_from_server(unsigned int port)
return ret;
}
+/* add to packet data a newly allocated tvb with the specified real data*/
+static void
+ssl_add_record_info(packet_info *pinfo, unsigned char* data, int data_len, int record_id)
+{
+ unsigned char* real_data = se_alloc(data_len);
+ SslRecordInfo* rec = se_alloc(sizeof(SslRecordInfo));
+ SslPacketInfo* pi = p_get_proto_data(pinfo->fd, proto_ssl);
+ if (!pi)
+ {
+ pi = se_alloc0(sizeof(SslPacketInfo));
+ p_add_proto_data(pinfo->fd, proto_ssl,pi);
+ }
+
+ rec->id = record_id;
+ rec->tvb = tvb_new_real_data(real_data, data_len, data_len);
+ memcpy(real_data, data, data_len);
+
+ /* head insertion */
+ rec->next= pi->handshake_data;
+ pi->handshake_data = rec;
+}
+
+/* search in packet data the tvbuff associated to the specified id */
+static tvbuff_t*
+ssl_get_record_info(packet_info *pinfo, int record_id)
+{
+ SslRecordInfo* rec;
+ SslPacketInfo* pi = p_get_proto_data(pinfo->fd, proto_ssl);
+ if (!pi)
+ return NULL;
+
+ for (rec = pi->handshake_data; rec; rec = rec->next)
+ if (rec->id == record_id)
+ return rec->tvb;
+
+ return NULL;
+}
+
/* initialize/reset per capture state data (ssl sessions cache) */
static void
ssl_init(void)
@@ -1379,12 +1418,13 @@ dissect_ssl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tap_queue_packet(ssl_tap, pinfo, (gpointer)proto_ssl);
}
-static void
+static int
decrypt_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
guint32 record_length, guint8 content_type, SslDecryptSession* ssl,
gboolean save_plaintext)
{
- int len, direction;
+ int ret = 0;
+ int direction;
SslDecoder* decoder;
/* if we can decrypt and decryption have success
@@ -1393,7 +1433,7 @@ decrypt_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
record_length, ssl->state);
if (!(ssl->state & SSL_HAVE_SESSION_KEY)) {
ssl_debug_printf("decrypt_ssl3_record: no session key\n");
- return ;
+ return ret;
}
/* retrive decoder for this packet direction*/
@@ -1419,46 +1459,48 @@ decrypt_ssl3_record(tvbuff_t *tvb, packet_info *pinfo, guint32 offset,
/* run decryption and add decrypted payload to protocol data, if decryption
* is successful*/
- len = ssl_decrypted_data.data_len;
- if ((ssl_decrypt_record(ssl, decoder,
- content_type, tvb_get_ptr(tvb, offset, record_length),
- record_length, ssl_decrypted_data.data, &len) == 0) &&
- save_plaintext)
+ ssl_decrypted_data_avail = ssl_decrypted_data.data_len;
+ if (ssl_decrypt_record(ssl, decoder,
+ content_type, tvb_get_ptr(tvb, offset, record_length),
+ record_length, ssl_decrypted_data.data, &ssl_decrypted_data_avail) == 0)
+ ret = 1;
+ if (ret && save_plaintext)
{
- StringInfo* data = p_get_proto_data(pinfo->fd, proto_ssl);
- if (!data)
+ SslPacketInfo* pi = p_get_proto_data(pinfo->fd, proto_ssl);
+ if (!pi)
{
ssl_debug_printf("decrypt_ssl3_record: allocating app_data %d "
- "bytes for app data\n", len);
+ "bytes for app data\n", ssl_decrypted_data_avail);
/* first app data record: allocate and put packet data*/
- data = se_alloc(sizeof(StringInfo));
- data->data = se_alloc(len);
- data->data_len = len;
- memcpy(data->data, ssl_decrypted_data.data, len);
+ pi = se_alloc0(sizeof(SslPacketInfo));
+ pi->app_data.data = se_alloc(ssl_decrypted_data_avail);
+ pi->app_data.data_len = ssl_decrypted_data_avail;
+ memcpy(pi->app_data.data, ssl_decrypted_data.data, ssl_decrypted_data_avail);
}
else {
unsigned char* store;
/* update previus record*/
ssl_debug_printf("decrypt_ssl3_record: reallocating app_data "
"%d bytes for app data (total %d appdata bytes)\n",
- len, data->data_len + len);
- store = se_alloc(data->data_len + len);
- memcpy(store, data->data, data->data_len);
- memcpy(&store[data->data_len], ssl_decrypted_data.data, len);
- data->data_len += len;
+ ssl_decrypted_data_avail, pi->app_data.data_len + ssl_decrypted_data_avail);
+ store = se_alloc(pi->app_data.data_len + ssl_decrypted_data_avail);
+ memcpy(store, pi->app_data.data, pi->app_data.data_len);
+ memcpy(&store[pi->app_data.data_len], ssl_decrypted_data.data, ssl_decrypted_data_avail);
+ pi->app_data.data_len += ssl_decrypted_data_avail;
/* old decrypted data ptr here appare to be leaked, but it's
* collected by emem allocator */
- data->data = store;
+ pi->app_data.data = store;
/* data ptr is changed, so remove old one and re-add the new one*/
ssl_debug_printf("decrypt_ssl3_record: removing old app_data ptr\n");
p_remove_proto_data(pinfo->fd, proto_ssl);
}
- ssl_debug_printf("decrypt_ssl3_record: setting decrypted app_data ptr %p\n",data);
- p_add_proto_data(pinfo->fd, proto_ssl, data);
+ ssl_debug_printf("decrypt_ssl3_record: setting decrypted app_data ptr %p\n",pi);
+ p_add_proto_data(pinfo->fd, proto_ssl, pi);
}
+ return ret;
}
@@ -1500,7 +1542,7 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *ti = NULL;
proto_tree *ssl_record_tree = NULL;
guint32 available_bytes = 0;
- StringInfo* decrypted;
+ SslPacketInfo* pi;
SslAssociation* association;
available_bytes = tvb_length_remaining(tvb, offset);
@@ -1671,6 +1713,7 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
col_append_str(pinfo->cinfo, COL_INFO, "Change Cipher Spec");
dissect_ssl3_change_cipher_spec(tvb, ssl_record_tree,
offset, conv_version, content_type);
+ ssl_debug_printf("dissect_ssl3_change_cipher_spec\n");
break;
case SSL_ID_ALERT:
if (ssl)
@@ -1680,12 +1723,27 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
conv_version);
break;
case SSL_ID_HANDSHAKE:
- if (ssl)
- decrypt_ssl3_record(tvb, pinfo, offset,
- record_length, content_type, ssl, FALSE);
- dissect_ssl3_handshake(tvb, pinfo, ssl_record_tree, offset,
+ {
+ tvbuff_t* decrypted=0;
+ /* try to decrypt handshake record, if possible. Store decrypted
+ * record for later usage. The offset is used as 'key' to itentify
+ * this record into the packet (we can have multiple handshake records
+ * in the same frame) */
+ if (ssl && decrypt_ssl3_record(tvb, pinfo, offset,
+ record_length, content_type, ssl, FALSE))
+ ssl_add_record_info(pinfo, ssl_decrypted_data.data,
+ ssl_decrypted_data_avail, offset);
+
+ /* try to retrive and use decrypted handshake record, if any. */
+ decrypted = ssl_get_record_info(pinfo, offset);
+ if (decrypted)
+ dissect_ssl3_handshake(decrypted, pinfo, ssl_record_tree, 0,
+ decrypted->length, conv_version, ssl, content_type);
+ else
+ dissect_ssl3_handshake(tvb, pinfo, ssl_record_tree, offset,
record_length, conv_version, ssl, content_type);
break;
+ }
case SSL_ID_APP_DATA:
if (ssl)
decrypt_ssl3_record(tvb, pinfo, offset,
@@ -1711,32 +1769,33 @@ dissect_ssl3_record(tvbuff_t *tvb, packet_info *pinfo,
association?association->info:"Application Data");
/* show decrypted data info, if available */
- decrypted = p_get_proto_data(pinfo->fd, proto_ssl);
- if (decrypted)
+ pi = p_get_proto_data(pinfo->fd, proto_ssl);
+ if (pi && pi->app_data.data)
{
tvbuff_t* new_tvb;
/* try to dissect decrypted data*/
- ssl_debug_printf("dissect_ssl3_record decrypted len %d\n", decrypted->data_len);
+ ssl_debug_printf("dissect_ssl3_record decrypted len %d\n",
+ pi->app_data.data_len);
/* create new tvbuff for the decrypted data */
- new_tvb = tvb_new_real_data(decrypted->data,
- decrypted->data_len, decrypted->data_len);
+ new_tvb = tvb_new_real_data(pi->app_data.data,
+ pi->app_data.data_len, pi->app_data.data_len);
tvb_set_free_cb(new_tvb, g_free);
/* tvb_set_child_real_data_tvbuff(tvb, new_tvb); */
/* find out a dissector using server port*/
if (association && association->handle) {
ssl_debug_printf("dissect_ssl3_record found association %p\n", association);
- ssl_print_text_data("decrypted app data",decrypted->data,
- decrypted->data_len);
+ ssl_print_text_data("decrypted app data",pi->app_data.data,
+ pi->app_data.data_len);
call_dissector(association->handle, new_tvb, pinfo, ssl_record_tree);
}
/* add raw decrypted data only if a decoder is not found*/
else
proto_tree_add_string(ssl_record_tree, hf_ssl_record_appdata_decrypted, tvb,
- offset, decrypted->data_len, (char*) decrypted->data);
+ offset, pi->app_data.data_len, (char*) pi->app_data.data);
}
else {
tvb_ensure_bytes_exist(tvb, offset, record_length);
@@ -2121,11 +2180,6 @@ dissect_ssl3_hnd_hello_common(tvbuff_t *tvb, proto_tree *tree,
ssl_restore_session(ssl);
}
else {
- /* reset state on renegotiation*/
- if (!from_server)
- ssl->state &= ~(SSL_HAVE_SESSION_KEY|SSL_MASTER_SECRET|
- SSL_CIPHER|SSL_SERVER_RANDOM);
-
tvb_memcpy(tvb,ssl->session_id.data, offset+33, session_id_length);
ssl->session_id.data_len = session_id_length;
}