Abort handshake if signature algorithm used not supported by peer.
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 11ffabb..e9c1518 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1750,25 +1750,12 @@
 		{
 		if (TLS1_get_version(s) >= TLS1_2_VERSION)
 			{
-			int sigalg = tls12_get_sigid(pkey);
-			/* Should never happen */
-			if (sigalg == -1)
-				{
-				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR);
+			int rv = tls12_check_peer_sigalg(&md, s, p, pkey);
+			if (rv == -1)
 				goto err;
-				}
-			/* Check key type is consistent with signature */
-			if (sigalg != (int)p[1])
+			else if (rv == 0)
 				{
-				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_WRONG_SIGNATURE_TYPE);
-				al=SSL_AD_DECODE_ERROR;
-				goto f_err;
-				}
-			md = tls12_get_hash(p[0]);
-			if (md == NULL)
-				{
-				SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNKNOWN_DIGEST);
-				al=SSL_AD_DECODE_ERROR;
+				al = SSL_AD_DECODE_ERROR;
 				goto f_err;
 				}
 #ifdef SSL_DEBUG
@@ -3161,13 +3148,17 @@
 	}
 
 /* Check a certificate can be used for client authentication. Currently
- * just check cert exists and if static DH client certificates can be used.
+ * check cert exists, if we have a suitable digest for TLS 1.2  and if
+ * static DH client certificates can be used.
  */
 static int ssl3_check_client_certificate(SSL *s)
 	{
 	unsigned long alg_k;
 	if (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey)
 		return 0;
+	/* If no suitable signature algorithm can't use certificate */
+	if (TLS1_get_version(s) >= TLS1_2_VERSION && !s->cert->key->digest)
+		return 0;
 	alg_k=s->s3->tmp.new_cipher->algorithm_mkey;
 	/* See if we can use client certificate for fixed DH */
 	if (alg_k & (SSL_kDHr|SSL_kDHd))
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 28f3bdd..2f23f21 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -3051,26 +3051,15 @@
 		{	
 		if (TLS1_get_version(s) >= TLS1_2_VERSION)
 			{
-			int sigalg = tls12_get_sigid(pkey);
-			/* Should never happen */
-			if (sigalg == -1)
+			int rv = tls12_check_peer_sigalg(&md, s, p, pkey);
+			if (rv == -1)
 				{
-				SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
-				al=SSL_AD_INTERNAL_ERROR;
+				al = SSL_AD_INTERNAL_ERROR;
 				goto f_err;
 				}
-			/* Check key type is consistent with signature */
-			if (sigalg != (int)p[1])
+			else if (rv == 0)
 				{
-				SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_TYPE);
-				al=SSL_AD_DECODE_ERROR;
-				goto f_err;
-				}
-			md = tls12_get_hash(p[0]);
-			if (md == NULL)
-				{
-				SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_UNKNOWN_DIGEST);
-				al=SSL_AD_DECODE_ERROR;
+				al = SSL_AD_DECODE_ERROR;
 				goto f_err;
 				}
 #ifdef SSL_DEBUG
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 09085a2..b8b1ba1 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2452,6 +2452,7 @@
 #define SSL_F_SSL_USE_RSAPRIVATEKEY_FILE		 206
 #define SSL_F_SSL_VERIFY_CERT_CHAIN			 207
 #define SSL_F_SSL_WRITE					 208
+#define SSL_F_TLS12_CHECK_PEER_SIGALG			 333
 #define SSL_F_TLS1_CERT_VERIFY_MAC			 286
 #define SSL_F_TLS1_CHANGE_CIPHER_STATE			 209
 #define SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT		 274
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 665d74f..14e8488 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -288,6 +288,7 @@
 {ERR_FUNC(SSL_F_SSL_USE_RSAPRIVATEKEY_FILE),	"SSL_use_RSAPrivateKey_file"},
 {ERR_FUNC(SSL_F_SSL_VERIFY_CERT_CHAIN),	"ssl_verify_cert_chain"},
 {ERR_FUNC(SSL_F_SSL_WRITE),	"SSL_write"},
+{ERR_FUNC(SSL_F_TLS12_CHECK_PEER_SIGALG),	"tls12_check_peer_sigalg"},
 {ERR_FUNC(SSL_F_TLS1_CERT_VERIFY_MAC),	"tls1_cert_verify_mac"},
 {ERR_FUNC(SSL_F_TLS1_CHANGE_CIPHER_STATE),	"tls1_change_cipher_state"},
 {ERR_FUNC(SSL_F_TLS1_CHECK_SERVERHELLO_TLSEXT),	"TLS1_CHECK_SERVERHELLO_TLSEXT"},
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 8b0ea0e..d8d1b79 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1252,6 +1252,8 @@
 long ssl_get_algorithm2(SSL *s);
 int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
 size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs);
+int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
+				const unsigned char *sig, EVP_PKEY *pkey);
 void ssl_set_client_disabled(SSL *s);
 
 int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len, int maxlen);
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 06db730..8b3c213 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -680,6 +680,45 @@
 			return sizeof(tls12_sigalgs);
 		}
 	}
+/* Check signature algorithm is consistent with sent supported signature
+ * algorithms and if so return relevant digest.
+ */
+int tls12_check_peer_sigalg(const EVP_MD **pmd, SSL *s,
+				const unsigned char *sig, EVP_PKEY *pkey)
+	{
+	const unsigned char *sent_sigs;
+	size_t sent_sigslen, i;
+	int sigalg = tls12_get_sigid(pkey);
+	/* Should never happen */
+	if (sigalg == -1)
+		return -1;
+	/* Check key type is consistent with signature */
+	if (sigalg != (int)sig[1])
+		{
+		SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE);
+		return 0;
+		}
+	/* Check signature matches a type we sent */
+	sent_sigslen = tls12_get_psigalgs(s, &sent_sigs);
+	for (i = 0; i < sent_sigslen; i+=2, sent_sigs+=2)
+		{
+		if (sig[0] == sent_sigs[0] && sig[1] == sent_sigs[1])
+			break;
+		}
+	/* Allow fallback to SHA1 if not strict mode */
+	if (i == sent_sigslen && (sig[0] != TLSEXT_hash_sha1 || s->cert->cert_flags & SSL_CERT_FLAG_TLS_STRICT))
+		{
+		SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_WRONG_SIGNATURE_TYPE);
+		return 0;
+		}
+	*pmd = tls12_get_hash(sig[0]);
+	if (*pmd == NULL)
+		{
+		SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG,SSL_R_UNKNOWN_DIGEST);
+		return 0;
+		}
+	return 1;
+	}
 /* Get a mask of disabled algorithms: an algorithm is disabled
  * if it isn't supported or doesn't appear in supported signature
  * algorithms. Unlike ssl_cipher_get_disabled this applies to a specific