You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			412 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Diff
		
	
			
		
		
	
	
			412 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Diff
		
	
| From 3a8c7b1a08b2766a7f8a388eee14442281b4e295 Mon Sep 17 00:00:00 2001
 | |
| From: Adam Langley <agl@chromium.org>
 | |
| Date: Thu, 24 Jan 2013 16:27:14 -0500
 | |
| Subject: [PATCH 19/36] tls12_digests
 | |
| 
 | |
| Fixes a bug with handling TLS 1.2 and digest functions for DSA and ECDSA
 | |
| keys.
 | |
| ---
 | |
|  ssl/s3_clnt.c  |  26 +++++++++++++--
 | |
|  ssl/ssl3.h     |  11 +++++-
 | |
|  ssl/ssl_cert.c |  20 -----------
 | |
|  ssl/ssl_lib.c  |  35 +++++++++++--------
 | |
|  ssl/ssl_locl.h |   4 +--
 | |
|  ssl/t1_lib.c   | 104 ++++++++++++++++++++-------------------------------------
 | |
|  6 files changed, 94 insertions(+), 106 deletions(-)
 | |
| 
 | |
| diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
 | |
| index c9196b3..1f3b376 100644
 | |
| --- a/ssl/s3_clnt.c
 | |
| +++ b/ssl/s3_clnt.c
 | |
| @@ -1990,12 +1990,13 @@ int ssl3_get_certificate_request(SSL *s)
 | |
|  			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_DATA_LENGTH_TOO_LONG);
 | |
|  			goto err;
 | |
|  			}
 | |
| -		if ((llen & 1) || !tls1_process_sigalgs(s, p, llen))
 | |
| +		if (llen & 1)
 | |
|  			{
 | |
|  			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECODE_ERROR);
 | |
|  			SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST,SSL_R_SIGNATURE_ALGORITHMS_ERROR);
 | |
|  			goto err;
 | |
|  			}
 | |
| +		tls1_process_sigalgs(s, p, llen);
 | |
|  		p += llen;
 | |
|  		}
 | |
|  
 | |
| @@ -3017,7 +3018,28 @@ int ssl3_send_client_verify(SSL *s)
 | |
|  			{
 | |
|  			long hdatalen = 0;
 | |
|  			void *hdata;
 | |
| -			const EVP_MD *md = s->cert->key->digest;
 | |
| +			const EVP_MD *md;
 | |
| +			switch (ssl_cert_type(NULL, pkey))
 | |
| +				{
 | |
| +			case SSL_PKEY_RSA_ENC:
 | |
| +				md = s->s3->digest_rsa;
 | |
| +				break;
 | |
| +			case SSL_PKEY_DSA_SIGN:
 | |
| +				md = s->s3->digest_dsa;
 | |
| +				break;
 | |
| +			case SSL_PKEY_ECC:
 | |
| +				md = s->s3->digest_ecdsa;
 | |
| +				break;
 | |
| +			default:
 | |
| +				md = NULL;
 | |
| +				}
 | |
| +			if (!md)
 | |
| +				/* Unlike with the SignatureAlgorithm extension (sent by clients),
 | |
| +				 * there are no default algorithms for the CertificateRequest message
 | |
| +				 * (sent by servers). However, now that we've sent a certificate
 | |
| +				 * for which we don't really know what hash to use for signing, the
 | |
| +				 * best we can do is try a default algorithm. */
 | |
| +				md = EVP_sha1();
 | |
|  			hdatalen = BIO_get_mem_data(s->s3->handshake_buffer,
 | |
|  								&hdata);
 | |
|  			if (hdatalen <= 0 || !tls12_get_sigandhash(p, pkey, md))
 | |
| diff --git a/ssl/ssl3.h b/ssl/ssl3.h
 | |
| index 29098e4..3229995 100644
 | |
| --- a/ssl/ssl3.h
 | |
| +++ b/ssl/ssl3.h
 | |
| @@ -550,6 +550,16 @@ typedef struct ssl3_state_st
 | |
|  	 *     verified Channel ID from the client: a P256 point, (x,y), where
 | |
|  	 *     each are big-endian values. */
 | |
|  	unsigned char tlsext_channel_id[64];
 | |
| +
 | |
| +	/* These point to the digest function to use for signatures made with
 | |
| +	 * each type of public key. A NULL value indicates that the default
 | |
| +	 * digest should be used, which is SHA1 as of TLS 1.2.
 | |
| +	 *
 | |
| +	 * (These should be in the tmp member, but we have to put them here to
 | |
| +	 * ensure binary compatibility with earlier OpenSSL 1.0.* releases.) */
 | |
| +	const EVP_MD *digest_rsa;
 | |
| +	const EVP_MD *digest_dsa;
 | |
| +	const EVP_MD *digest_ecdsa;
 | |
|  	} SSL3_STATE;
 | |
|  
 | |
|  #endif
 | |
| @@ -700,4 +710,3 @@ typedef struct ssl3_state_st
 | |
|  }
 | |
|  #endif
 | |
|  #endif
 | |
| -
 | |
| diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
 | |
| index 5123a89..bc4150b 100644
 | |
| --- a/ssl/ssl_cert.c
 | |
| +++ b/ssl/ssl_cert.c
 | |
| @@ -160,21 +160,6 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void)
 | |
|  	return ssl_x509_store_ctx_idx;
 | |
|  	}
 | |
|  
 | |
| -static void ssl_cert_set_default_md(CERT *cert)
 | |
| -	{
 | |
| -	/* Set digest values to defaults */
 | |
| -#ifndef OPENSSL_NO_DSA
 | |
| -	cert->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
 | |
| -#endif
 | |
| -#ifndef OPENSSL_NO_RSA
 | |
| -	cert->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
 | |
| -	cert->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
 | |
| -#endif
 | |
| -#ifndef OPENSSL_NO_ECDSA
 | |
| -	cert->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
 | |
| -#endif
 | |
| -	}
 | |
| -
 | |
|  CERT *ssl_cert_new(void)
 | |
|  	{
 | |
|  	CERT *ret;
 | |
| @@ -189,7 +174,6 @@ CERT *ssl_cert_new(void)
 | |
|  
 | |
|  	ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
 | |
|  	ret->references=1;
 | |
| -	ssl_cert_set_default_md(ret);
 | |
|  	return(ret);
 | |
|  	}
 | |
|  
 | |
| @@ -322,10 +306,6 @@ CERT *ssl_cert_dup(CERT *cert)
 | |
|  	 * chain is held inside SSL_CTX */
 | |
|  
 | |
|  	ret->references=1;
 | |
| -	/* Set digests to defaults. NB: we don't copy existing values as they
 | |
| -	 * will be set during handshake.
 | |
| -	 */
 | |
| -	ssl_cert_set_default_md(ret);
 | |
|  
 | |
|  	return(ret);
 | |
|  	
 | |
| diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
 | |
| index 5f8b0b0..e360550 100644
 | |
| --- a/ssl/ssl_lib.c
 | |
| +++ b/ssl/ssl_lib.c
 | |
| @@ -2345,32 +2345,41 @@ EVP_PKEY *ssl_get_sign_pkey(SSL *s,const SSL_CIPHER *cipher, const EVP_MD **pmd)
 | |
|  	{
 | |
|  	unsigned long alg_a;
 | |
|  	CERT *c;
 | |
| -	int idx = -1;
 | |
|  
 | |
|  	alg_a = cipher->algorithm_auth;
 | |
|  	c=s->cert;
 | |
|  
 | |
| +	/* SHA1 is the default for all signature algorithms up to TLS 1.2,
 | |
| +	 * except RSA which is handled specially in s3_srvr.c */
 | |
| +	if (pmd)
 | |
| +		*pmd = EVP_sha1();
 | |
| +
 | |
|  	if ((alg_a & SSL_aDSS) &&
 | |
| -		(c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
 | |
| -		idx = SSL_PKEY_DSA_SIGN;
 | |
| +	    (c->pkeys[SSL_PKEY_DSA_SIGN].privatekey != NULL))
 | |
| +		{
 | |
| +		if (pmd && s->s3 && s->s3->digest_dsa)
 | |
| +			*pmd = s->s3->digest_dsa;
 | |
| +		return c->pkeys[SSL_PKEY_DSA_SIGN].privatekey;
 | |
| +		}
 | |
|  	else if (alg_a & SSL_aRSA)
 | |
|  		{
 | |
| +		if (pmd && s->s3 && s->s3->digest_rsa)
 | |
| +			*pmd = s->s3->digest_rsa;
 | |
|  		if (c->pkeys[SSL_PKEY_RSA_SIGN].privatekey != NULL)
 | |
| -			idx = SSL_PKEY_RSA_SIGN;
 | |
| -		else if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
 | |
| -			idx = SSL_PKEY_RSA_ENC;
 | |
| +			return c->pkeys[SSL_PKEY_RSA_SIGN].privatekey;
 | |
| +		if (c->pkeys[SSL_PKEY_RSA_ENC].privatekey != NULL)
 | |
| +			return c->pkeys[SSL_PKEY_RSA_ENC].privatekey;
 | |
|  		}
 | |
|  	else if ((alg_a & SSL_aECDSA) &&
 | |
|  	         (c->pkeys[SSL_PKEY_ECC].privatekey != NULL))
 | |
| -		idx = SSL_PKEY_ECC;
 | |
| -	if (idx == -1)
 | |
|  		{
 | |
| -		SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
 | |
| -		return(NULL);
 | |
| +		if (pmd && s->s3 && s->s3->digest_ecdsa)
 | |
| +			*pmd = s->s3->digest_ecdsa;
 | |
| +		return c->pkeys[SSL_PKEY_ECC].privatekey;
 | |
|  		}
 | |
| -	if (pmd)
 | |
| -		*pmd = c->pkeys[idx].digest;
 | |
| -	return c->pkeys[idx].privatekey;
 | |
| +
 | |
| +	SSLerr(SSL_F_SSL_GET_SIGN_PKEY,ERR_R_INTERNAL_ERROR);
 | |
| +	return(NULL);
 | |
|  	}
 | |
|  
 | |
|  void ssl_update_cache(SSL *s,int mode)
 | |
| diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
 | |
| index 6d38f0f..3e89fcb 100644
 | |
| --- a/ssl/ssl_locl.h
 | |
| +++ b/ssl/ssl_locl.h
 | |
| @@ -485,8 +485,6 @@ typedef struct cert_pkey_st
 | |
|  	{
 | |
|  	X509 *x509;
 | |
|  	EVP_PKEY *privatekey;
 | |
| -	/* Digest to use when signing */
 | |
| -	const EVP_MD *digest;
 | |
|  	} CERT_PKEY;
 | |
|  
 | |
|  typedef struct cert_st
 | |
| @@ -1142,7 +1140,7 @@ int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
 | |
|  int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
 | |
|  					  int *al);
 | |
|  long ssl_get_algorithm2(SSL *s);
 | |
| -int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
 | |
| +void tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
 | |
|  int tls12_get_req_sig_algs(SSL *s, unsigned char *p);
 | |
|  
 | |
|  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 26805e4..6af51a9 100644
 | |
| --- a/ssl/t1_lib.c
 | |
| +++ b/ssl/t1_lib.c
 | |
| @@ -897,6 +897,13 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
 | |
|  
 | |
|  	s->servername_done = 0;
 | |
|  	s->tlsext_status_type = -1;
 | |
| +
 | |
| +	/* Reset TLS 1.2 digest functions to defaults because they don't carry
 | |
| +	 * over to a renegotiation. */
 | |
| +	s->s3->digest_rsa = NULL;
 | |
| +	s->s3->digest_dsa = NULL;
 | |
| +	s->s3->digest_ecdsa = NULL;
 | |
| +
 | |
|  #ifndef OPENSSL_NO_NEXTPROTONEG
 | |
|  	s->s3->next_proto_neg_seen = 0;
 | |
|  #endif
 | |
| @@ -1198,11 +1205,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
 | |
|  				*al = SSL_AD_DECODE_ERROR;
 | |
|  				return 0;
 | |
|  				}
 | |
| -			if (!tls1_process_sigalgs(s, data, dsize))
 | |
| -				{
 | |
| -				*al = SSL_AD_DECODE_ERROR;
 | |
| -				return 0;
 | |
| -				}
 | |
| +			tls1_process_sigalgs(s, data, dsize);
 | |
|  			}
 | |
|  		else if (type == TLSEXT_TYPE_status_request &&
 | |
|  		         s->version != DTLS1_VERSION && s->ctx->tlsext_status_cb)
 | |
| @@ -2354,18 +2357,6 @@ static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen)
 | |
|  		}
 | |
|  	return -1;
 | |
|  	}
 | |
| -#if 0
 | |
| -static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
 | |
| -	{
 | |
| -	size_t i;
 | |
| -	for (i = 0; i < tlen; i++)
 | |
| -		{
 | |
| -		if (table[i].id == id)
 | |
| -			return table[i].nid;
 | |
| -		}
 | |
| -	return -1;
 | |
| -	}
 | |
| -#endif
 | |
|  
 | |
|  int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
 | |
|  	{
 | |
| @@ -2384,6 +2375,8 @@ int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
 | |
|  	return 1;
 | |
|  	}
 | |
|  
 | |
| +/* tls12_get_sigid returns the TLS 1.2 SignatureAlgorithm value corresponding
 | |
| + * to the given public key, or -1 if not known. */
 | |
|  int tls12_get_sigid(const EVP_PKEY *pk)
 | |
|  	{
 | |
|  	return tls12_find_id(pk->type, tls12_sig,
 | |
| @@ -2403,47 +2396,49 @@ const EVP_MD *tls12_get_hash(unsigned char hash_alg)
 | |
|  		return EVP_md5();
 | |
|  #endif
 | |
|  #ifndef OPENSSL_NO_SHA
 | |
| -		case TLSEXT_hash_sha1:
 | |
| +	case TLSEXT_hash_sha1:
 | |
|  		return EVP_sha1();
 | |
|  #endif
 | |
|  #ifndef OPENSSL_NO_SHA256
 | |
| -		case TLSEXT_hash_sha224:
 | |
| +	case TLSEXT_hash_sha224:
 | |
|  		return EVP_sha224();
 | |
|  
 | |
| -		case TLSEXT_hash_sha256:
 | |
| +	case TLSEXT_hash_sha256:
 | |
|  		return EVP_sha256();
 | |
|  #endif
 | |
|  #ifndef OPENSSL_NO_SHA512
 | |
| -		case TLSEXT_hash_sha384:
 | |
| +	case TLSEXT_hash_sha384:
 | |
|  		return EVP_sha384();
 | |
|  
 | |
| -		case TLSEXT_hash_sha512:
 | |
| +	case TLSEXT_hash_sha512:
 | |
|  		return EVP_sha512();
 | |
|  #endif
 | |
| -		default:
 | |
| +	default:
 | |
|  		return NULL;
 | |
|  
 | |
|  		}
 | |
|  	}
 | |
|  
 | |
| -/* Set preferred digest for each key type */
 | |
| -
 | |
| -int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
 | |
| +/* tls1_process_sigalgs processes a signature_algorithms extension and sets the
 | |
| + * digest functions accordingly for each key type.
 | |
| + *
 | |
| + * See RFC 5246, section 7.4.1.4.1.
 | |
| + *
 | |
| + * data: points to the content of the extension, not including type and length
 | |
| + *     headers.
 | |
| + * dsize: the number of bytes of |data|. Must be even.
 | |
| + */
 | |
| +void tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
 | |
|  	{
 | |
| -	int i, idx;
 | |
| -	const EVP_MD *md;
 | |
| -	CERT *c = s->cert;
 | |
| +	int i;
 | |
| +	const EVP_MD *md, **digest_ptr;
 | |
|  	/* Extension ignored for TLS versions below 1.2 */
 | |
|  	if (TLS1_get_version(s) < TLS1_2_VERSION)
 | |
| -		return 1;
 | |
| -	/* Should never happen */
 | |
| -	if (!c)
 | |
| -		return 0;
 | |
| +		return;
 | |
|  
 | |
| -	c->pkeys[SSL_PKEY_DSA_SIGN].digest = NULL;
 | |
| -	c->pkeys[SSL_PKEY_RSA_SIGN].digest = NULL;
 | |
| -	c->pkeys[SSL_PKEY_RSA_ENC].digest = NULL;
 | |
| -	c->pkeys[SSL_PKEY_ECC].digest = NULL;
 | |
| +	s->s3->digest_rsa = NULL;
 | |
| +	s->s3->digest_dsa = NULL;
 | |
| +	s->s3->digest_ecdsa = NULL;
 | |
|  
 | |
|  	for (i = 0; i < dsize; i += 2)
 | |
|  		{
 | |
| @@ -2453,56 +2448,31 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
 | |
|  			{
 | |
|  #ifndef OPENSSL_NO_RSA
 | |
|  			case TLSEXT_signature_rsa:
 | |
| -			idx = SSL_PKEY_RSA_SIGN;
 | |
| +			digest_ptr = &s->s3->digest_rsa;
 | |
|  			break;
 | |
|  #endif
 | |
|  #ifndef OPENSSL_NO_DSA
 | |
|  			case TLSEXT_signature_dsa:
 | |
| -			idx = SSL_PKEY_DSA_SIGN;
 | |
| +			digest_ptr = &s->s3->digest_dsa;
 | |
|  			break;
 | |
|  #endif
 | |
|  #ifndef OPENSSL_NO_ECDSA
 | |
|  			case TLSEXT_signature_ecdsa:
 | |
| -			idx = SSL_PKEY_ECC;
 | |
| +			digest_ptr = &s->s3->digest_ecdsa;
 | |
|  			break;
 | |
|  #endif
 | |
|  			default:
 | |
|  			continue;
 | |
|  			}
 | |
|  
 | |
| -		if (c->pkeys[idx].digest == NULL)
 | |
| +		if (*digest_ptr == NULL)
 | |
|  			{
 | |
|  			md = tls12_get_hash(hash_alg);
 | |
|  			if (md)
 | |
| -				{
 | |
| -				c->pkeys[idx].digest = md;
 | |
| -				if (idx == SSL_PKEY_RSA_SIGN)
 | |
| -					c->pkeys[SSL_PKEY_RSA_ENC].digest = md;
 | |
| -				}
 | |
| +				*digest_ptr = md;
 | |
|  			}
 | |
|  
 | |
|  		}
 | |
| -
 | |
| -
 | |
| -	/* Set any remaining keys to default values. NOTE: if alg is not
 | |
| -	 * supported it stays as NULL.
 | |
| -	 */
 | |
| -#ifndef OPENSSL_NO_DSA
 | |
| -	if (!c->pkeys[SSL_PKEY_DSA_SIGN].digest)
 | |
| -		c->pkeys[SSL_PKEY_DSA_SIGN].digest = EVP_sha1();
 | |
| -#endif
 | |
| -#ifndef OPENSSL_NO_RSA
 | |
| -	if (!c->pkeys[SSL_PKEY_RSA_SIGN].digest)
 | |
| -		{
 | |
| -		c->pkeys[SSL_PKEY_RSA_SIGN].digest = EVP_sha1();
 | |
| -		c->pkeys[SSL_PKEY_RSA_ENC].digest = EVP_sha1();
 | |
| -		}
 | |
| -#endif
 | |
| -#ifndef OPENSSL_NO_ECDSA
 | |
| -	if (!c->pkeys[SSL_PKEY_ECC].digest)
 | |
| -		c->pkeys[SSL_PKEY_ECC].digest = EVP_sha1();
 | |
| -#endif
 | |
| -	return 1;
 | |
|  	}
 | |
|  
 | |
|  #endif
 | |
| -- 
 | |
| 1.8.2.1
 | |
| 
 |