Blob Blame History Raw
diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c
index e97e46e..f70919b 100644
--- a/epan/dissectors/packet-ssl.c
+++ b/epan/dissectors/packet-ssl.c
@@ -202,6 +202,8 @@ static gint hf_ssl_handshake_server_keyex_named_curve = -1;
 static gint hf_ssl_handshake_server_keyex_point     = -1;
 static gint hf_ssl_handshake_client_keyex_epms      = -1;
 static gint hf_ssl_handshake_client_keyex_point     = -1;
+static gint hf_ssl_handshake_client_vrfy_sig_len    = -1;
+static gint hf_ssl_handshake_client_vrfy_sig        = -1;
 static gint hf_ssl_handshake_server_keyex_modulus   = -1;
 static gint hf_ssl_handshake_server_keyex_exponent  = -1;
 static gint hf_ssl_handshake_server_keyex_sig       = -1;
@@ -682,6 +684,10 @@ static gint  ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb,
 static gint  dissect_ssl_hash_alg_list(tvbuff_t *tvb, proto_tree *tree,
                                        guint32 offset, guint16 len);
 
+static void  dissect_ssl3_hnd_cli_cert_verify(tvbuff_t *tvb, proto_tree *tree,
+                                              guint32 offset,
+                                              const SslSession *session);
+
 /*********************************************************************
  *
  * Main dissector
@@ -2070,7 +2076,7 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
                 break;
 
             case SSL_HND_CERT_VERIFY:
-                /* unimplemented */
+                dissect_ssl3_hnd_cli_cert_verify(tvb, ssl_hand_tree, offset, session);
                 break;
 
             case SSL_HND_CLIENT_KEY_EXCHG:
@@ -3174,8 +3180,9 @@ dissect_ssl3_hnd_cert_req(tvbuff_t *tvb,
 }
 
 static void
-dissect_ssl3_hnd_srv_keyex_sig(tvbuff_t *tvb, proto_tree *tree,
-                               guint32 offset, SslSession *session)
+dissect_ssl3_digitally_signed(tvbuff_t *tvb, proto_tree *tree, guint32 offset,
+                              const SslSession *session, gint hf_sig_len,
+                              gint hf_sig)
 {
     gint        sig_len;
     proto_item *ti_algo;
@@ -3202,10 +3209,40 @@ dissect_ssl3_hnd_srv_keyex_sig(tvbuff_t *tvb, proto_tree *tree,
 
     /* Sig */
     sig_len = tvb_get_ntohs(tvb, offset);
-    proto_tree_add_item(tree, hf_ssl_handshake_server_keyex_sig_len, tvb,
-                        offset, 2, ENC_BIG_ENDIAN);
-    proto_tree_add_item(tree, hf_ssl_handshake_server_keyex_sig, tvb,
-                        offset + 2, sig_len, ENC_NA);
+    proto_tree_add_item(tree, hf_sig_len, tvb, offset, 2, ENC_BIG_ENDIAN);
+    proto_tree_add_item(tree, hf_sig, tvb, offset + 2, sig_len, ENC_NA);
+}
+
+static void
+dissect_ssl3_hnd_cli_cert_verify(tvbuff_t *tvb, proto_tree *tree,
+                                 guint32 offset, const SslSession *session)
+{
+    dissect_ssl3_digitally_signed(tvb, tree, offset, session,
+                                  hf_ssl_handshake_client_vrfy_sig_len,
+                                  hf_ssl_handshake_client_vrfy_sig);
+}
+
+static void
+dissect_ssl3_hnd_srv_keyex_sig(tvbuff_t *tvb, proto_tree *tree,
+                               guint32 offset, SslSession *session)
+{
+    /*
+     * TLSv1.2 (RFC 5246 sec 7.4.8)
+     *  struct {
+     *      digitally-signed struct {
+     *          opaque handshake_messages[handshake_messages_length];
+     *      }
+     *  } CertificateVerify;
+     *
+     * TLSv1.0/TLSv1.1 (RFC 5436 sec 7.4.8 and 7.4.3) works essentially the same
+     * as TLSv1.2, but the hash algorithms are not explicit in digitally-signed.
+     *
+     * SSLv3 (RFC 6101 sec 5.6.8) esseentially works the same as TLSv1.0 but it
+     * does more hashing including the master secret and padding.
+     */
+    dissect_ssl3_digitally_signed(tvb, tree, offset, session,
+                                  hf_ssl_handshake_server_keyex_sig_len,
+                                  hf_ssl_handshake_server_keyex_sig);
 }
 
 static void
@@ -5410,6 +5447,16 @@ proto_register_ssl(void)
             FT_BYTES, BASE_NONE, NULL, 0x0,
             "EC Diffie-Hellman client pubkey", HFILL }
         },
+        { &hf_ssl_handshake_client_vrfy_sig_len,
+          { "signature length", "ssl.handshake.client_cert_vrfy.sig_len",
+            FT_UINT16, BASE_DEC, NULL, 0x0,
+            "Length of CertificateVerify's signature", HFILL }
+        },
+        { &hf_ssl_handshake_client_vrfy_sig,
+          { "signature", "ssl.handshake.client_cert_vrfy.sig",
+            FT_BYTES, BASE_NONE, NULL, 0x0,
+            "CertificateVerify's signature", HFILL }
+        },
         { &hf_ssl_handshake_server_keyex_modulus,
           { "modulus", "ssl.handshake.modulus",
             FT_BYTES, BASE_NONE, NULL, 0x0,