Blob Blame History Raw
diff --git a/epan/dissectors/packet-ssl-utils.h b/epan/dissectors/packet-ssl-utils.h
index aaadbe7..ccac6ae 100644
--- a/epan/dissectors/packet-ssl-utils.h
+++ b/epan/dissectors/packet-ssl-utils.h
@@ -151,6 +151,7 @@
 #define SSL_HND_HELLO_EXT_SERVER_NAME        0x0
 #define SSL_HND_HELLO_EXT_ELLIPTIC_CURVES    0x000a
 #define SSL_HND_HELLO_EXT_EC_POINT_FORMATS   0x000b
+#define SSL_HND_HELLO_EXT_SIG_HASH_ALGS      0x000d
 #define SSL_HND_HELLO_EXT_HEARTBEAT          0x000f
 #define SSL_HND_HELLO_EXT_RENEG_INFO         0xff01
 #define SSL_HND_HELLO_EXT_NPN                0x3374
diff --git a/epan/dissectors/packet-ssl.c b/epan/dissectors/packet-ssl.c
index d75a3cc..b50ca22 100644
--- a/epan/dissectors/packet-ssl.c
+++ b/epan/dissectors/packet-ssl.c
@@ -542,6 +542,9 @@ static gint dissect_ssl3_hnd_hello_ext_elliptic_curves(tvbuff_t *tvb,
 static gint dissect_ssl3_hnd_hello_ext_ec_point_formats(tvbuff_t *tvb,
                                                         proto_tree *tree, guint32 offset);
 
+static gint dissect_ssl3_hnd_hello_ext_sig_hash_algs(tvbuff_t *tvb,
+                                                     proto_tree *tree, guint32 offset, guint32 ext_len);
+
 static gint dissect_ssl3_hnd_hello_ext_npn(tvbuff_t *tvb,
                                            proto_tree *tree, guint32 offset, guint32 ext_len);
 
@@ -674,6 +677,10 @@ static gint  ssl_looks_like_valid_v2_handshake(tvbuff_t *tvb,
 static gint  ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb,
                                                 const guint32 offset,
                                                 const guint32 record_length);
+
+static gint  dissect_ssl_hash_alg_list(tvbuff_t *tvb, proto_tree *tree,
+                                       guint32 offset, guint16 len);
+
 /*********************************************************************
  *
  * Main dissector
@@ -2439,6 +2446,9 @@ dissect_ssl3_hnd_hello_ext(tvbuff_t *tvb,
         case SSL_HND_HELLO_EXT_EC_POINT_FORMATS:
             offset = dissect_ssl3_hnd_hello_ext_ec_point_formats(tvb, ext_tree, offset);
             break;
+        case SSL_HND_HELLO_EXT_SIG_HASH_ALGS:
+            offset = dissect_ssl3_hnd_hello_ext_sig_hash_algs(tvb, ext_tree, offset, ext_len);
+            break;
         case SSL_HND_HELLO_EXT_NPN:
             offset = dissect_ssl3_hnd_hello_ext_npn(tvb, ext_tree, offset, ext_len);
             break;
@@ -2502,6 +2512,29 @@ dissect_ssl3_hnd_hello_ext_npn(tvbuff_t *tvb,
 }
 
 static gint
+dissect_ssl3_hnd_hello_ext_sig_hash_algs(tvbuff_t *tvb,
+        proto_tree *tree, guint32 offset, guint32 ext_len)
+{
+    guint16  sh_alg_length;
+    gint     ret;
+
+    sh_alg_length = tvb_get_ntohs(tvb, offset);
+    proto_tree_add_uint(tree, hf_ssl_handshake_sig_hash_alg_len,
+                        tvb, offset, 2, sh_alg_length);
+    offset += 2;
+    if (ext_len<2 || sh_alg_length!=ext_len-2) {
+        /* ERROR: sh_alg_length must be 2 less than ext_len */
+        return offset;
+    }
+
+    ret = dissect_ssl_hash_alg_list(tvb, tree, offset, sh_alg_length);
+    if (ret >=0)
+        offset += ret;
+
+    return offset;
+}
+
+static gint
 dissect_ssl3_hnd_hello_ext_reneg_info(tvbuff_t *tvb,
                                proto_tree *tree, guint32 offset, guint32 ext_len)
 {
@@ -4957,6 +4990,51 @@ ssl_looks_like_valid_pct_handshake(tvbuff_t *tvb, const guint32 offset,
     return ret;
 }
 
+/* dissect a list of hash algorithms, return the number of bytes dissected
+ * this is used for the signature algorithms extension and for the
+ * TLS1.2 certificate request */
+static gint
+dissect_ssl_hash_alg_list(tvbuff_t *tvb, proto_tree *tree,
+                          guint32 offset, guint16 len)
+{
+    guint32     offset_start;
+    proto_tree *subtree, *alg_tree;
+    proto_tree *ti;
+
+    offset_start = offset;
+    if (len==0)
+        return 0;
+
+    ti = proto_tree_add_none_format(tree,
+            hf_ssl_handshake_sig_hash_algs,
+            tvb, offset, len,
+            "Signature Hash Algorithms (%u algorithm%s)",
+            len/2,
+            plurality(len/2, "", "s"));
+    subtree = proto_item_add_subtree(ti, ett_ssl_sig_hash_algs);
+
+    if (len % 2) {
+        proto_tree_add_text(tree, tvb, offset, 2,
+                "Invalid Signature Hash Algorithm length: %d", len);
+        return offset-offset_start;
+    }
+
+    while (len > 0) {
+        ti = proto_tree_add_item(subtree, hf_ssl_handshake_sig_hash_alg,
+                tvb, offset, 2, ENC_BIG_ENDIAN);
+        alg_tree = proto_item_add_subtree(ti, ett_ssl_sig_hash_alg);
+
+        proto_tree_add_item(alg_tree, hf_ssl_handshake_sig_hash_hash,
+                tvb, offset, 1, ENC_BIG_ENDIAN);
+        proto_tree_add_item(alg_tree, hf_ssl_handshake_sig_hash_sig,
+                tvb, offset+1, 1, ENC_BIG_ENDIAN);
+
+        offset += 2;
+        len -= 2;
+    }
+    return offset-offset_start;
+}
+
 /* UAT */
 
 #ifdef HAVE_LIBGNUTLS