Abort handshake if signature algorithm used not supported by peer.
(backport from HEAD)
This commit is contained in:
		
							
								
								
									
										6
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								CHANGES
									
									
									
									
									
								
							| @@ -8,6 +8,12 @@ | ||||
|      OID NID. | ||||
|      [Steve Henson] | ||||
|  | ||||
|   *) If an attempt is made to use a signature algorithm not in the peer | ||||
|      preference list abort the handshake. If client has no suitable | ||||
|      signature algorithms in response to a certificate request do not | ||||
|      use the certificate. | ||||
|      [Steve Henson] | ||||
|  | ||||
|   *) If server EC tmp key is not in client preference list abort handshake. | ||||
|      [Steve Henson] | ||||
|  | ||||
|   | ||||
| @@ -1751,25 +1751,12 @@ int ssl3_get_key_exchange(SSL *s) | ||||
| 		{ | ||||
| 		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 | ||||
| @@ -3162,13 +3149,17 @@ err: | ||||
| 	} | ||||
|  | ||||
| /* 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)) | ||||
|   | ||||
| @@ -3054,26 +3054,15 @@ int ssl3_get_cert_verify(SSL *s) | ||||
| 		{	 | ||||
| 		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 | ||||
|   | ||||
| @@ -2433,6 +2433,7 @@ void ERR_load_SSL_strings(void); | ||||
| #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 | ||||
|   | ||||
| @@ -289,6 +289,7 @@ static ERR_STRING_DATA SSL_str_functs[]= | ||||
| {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"}, | ||||
|   | ||||
| @@ -1255,6 +1255,8 @@ int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len, | ||||
| 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); | ||||
|   | ||||
							
								
								
									
										39
									
								
								ssl/t1_lib.c
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								ssl/t1_lib.c
									
									
									
									
									
								
							| @@ -680,6 +680,45 @@ size_t tls12_get_psigalgs(SSL *s, const unsigned char **psigs) | ||||
| 			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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Dr. Stephen Henson
					Dr. Stephen Henson