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