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,