Fix ECDSA hash selection bug with TLS 1.0 and 1.1
This commit is contained in:
parent
9c9812a299
commit
4bd1284f59
@ -1185,7 +1185,6 @@ static int ssl_parse_signature_algorithm( ssl_context *ssl,
|
||||
unsigned char **p,
|
||||
unsigned char *end,
|
||||
md_type_t *md_alg,
|
||||
size_t *hash_len,
|
||||
pk_type_t *pk_alg )
|
||||
{
|
||||
((void) ssl);
|
||||
@ -1195,16 +1194,12 @@ static int ssl_parse_signature_algorithm( ssl_context *ssl,
|
||||
/* Only in TLS 1.2 */
|
||||
if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
|
||||
{
|
||||
*hash_len = 36;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if( (*p) + 2 > end )
|
||||
return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
|
||||
|
||||
/* Info from md_alg will be used instead */
|
||||
*hash_len = 0;
|
||||
|
||||
/*
|
||||
* Get hash algorithm
|
||||
*/
|
||||
@ -1361,7 +1356,7 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
|
||||
* Handle the digitally-signed structure
|
||||
*/
|
||||
if( ssl_parse_signature_algorithm( ssl, &p, end,
|
||||
&md_alg, &hashlen, &pk_alg ) != 0 )
|
||||
&md_alg, &pk_alg ) != 0 )
|
||||
{
|
||||
SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
|
||||
return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
|
||||
@ -1380,6 +1375,13 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
|
||||
pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
|
||||
}
|
||||
|
||||
/* Default hash for ECDSA is SHA-1 */
|
||||
if( pk_alg == POLARSSL_PK_ECDSA && md_alg == POLARSSL_MD_NONE )
|
||||
md_alg = POLARSSL_MD_SHA1;
|
||||
|
||||
/*
|
||||
* Read signature
|
||||
*/
|
||||
sig_len = ( p[0] << 8 ) | p[1];
|
||||
p += 2;
|
||||
|
||||
@ -1389,14 +1391,18 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
|
||||
return( POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
|
||||
}
|
||||
|
||||
SSL_DEBUG_BUF( 3, "signature", p, sig_len );
|
||||
|
||||
/*
|
||||
* Compute the hash that has been signed
|
||||
*/
|
||||
if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
|
||||
if( md_alg == POLARSSL_MD_NONE )
|
||||
{
|
||||
md5_context md5;
|
||||
sha1_context sha1;
|
||||
|
||||
hashlen = 36;
|
||||
|
||||
/*
|
||||
* digitally-signed struct {
|
||||
* opaque md5_hash[16];
|
||||
@ -1424,6 +1430,9 @@ static int ssl_parse_server_key_exchange( ssl_context *ssl )
|
||||
{
|
||||
md_context_t ctx;
|
||||
|
||||
/* Info from md_alg will be used instead */
|
||||
hashlen = 0;
|
||||
|
||||
/*
|
||||
* digitally-signed struct {
|
||||
* opaque client_random[32];
|
||||
@ -1918,6 +1927,7 @@ static int ssl_write_certificate_verify( ssl_context *ssl )
|
||||
const ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info;
|
||||
size_t n = 0, offset = 0;
|
||||
unsigned char hash[48];
|
||||
unsigned char *hash_start = hash;
|
||||
md_type_t md_alg = POLARSSL_MD_NONE;
|
||||
unsigned int hashlen;
|
||||
|
||||
@ -1965,6 +1975,16 @@ static int ssl_write_certificate_verify( ssl_context *ssl )
|
||||
*/
|
||||
hashlen = 36;
|
||||
md_alg = POLARSSL_MD_NONE;
|
||||
|
||||
/*
|
||||
* For ECDSA, default hash is SHA-1 only
|
||||
*/
|
||||
if( pk_can_do( ssl->pk_key, POLARSSL_PK_ECDSA ) )
|
||||
{
|
||||
hash_start += 16;
|
||||
hashlen -= 16;
|
||||
md_alg = POLARSSL_MD_SHA1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2002,7 +2022,7 @@ static int ssl_write_certificate_verify( ssl_context *ssl )
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
if( ( ret = pk_sign( ssl->pk_key, md_alg, hash, hashlen,
|
||||
if( ( ret = pk_sign( ssl->pk_key, md_alg, hash_start, hashlen,
|
||||
ssl->out_msg + 6 + offset, &n,
|
||||
ssl->f_rng, ssl->p_rng ) ) != 0 )
|
||||
{
|
||||
|
@ -1950,10 +1950,34 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
|
||||
{
|
||||
size_t signature_len = 0;
|
||||
|
||||
/*
|
||||
* Choose hash algorithm. NONE means MD5 + SHA1 here.
|
||||
*/
|
||||
if( ssl->minor_ver == SSL_MINOR_VERSION_3 )
|
||||
{
|
||||
md_alg = ssl_md_alg_from_hash( ssl->handshake->sig_alg );
|
||||
|
||||
if( md_alg == POLARSSL_MD_NONE )
|
||||
{
|
||||
SSL_DEBUG_MSG( 1, ( "should never happen" ) );
|
||||
return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
|
||||
}
|
||||
}
|
||||
else if ( ciphersuite_info->key_exchange ==
|
||||
POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA )
|
||||
{
|
||||
md_alg = POLARSSL_MD_SHA1;
|
||||
}
|
||||
else
|
||||
{
|
||||
md_alg = POLARSSL_MD_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compute the hash to be signed
|
||||
*/
|
||||
if( ssl->minor_ver != SSL_MINOR_VERSION_3 )
|
||||
if( md_alg == POLARSSL_MD_NONE )
|
||||
{
|
||||
md5_context md5;
|
||||
sha1_context sha1;
|
||||
@ -1982,7 +2006,6 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
|
||||
sha1_finish( &sha1, hash + 16 );
|
||||
|
||||
hashlen = 36;
|
||||
md_alg = POLARSSL_MD_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1998,13 +2021,6 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
|
||||
* ServerDHParams params;
|
||||
* };
|
||||
*/
|
||||
if( ( md_alg = ssl_md_alg_from_hash( ssl->handshake->sig_alg ) )
|
||||
== POLARSSL_MD_NONE )
|
||||
{
|
||||
SSL_DEBUG_MSG( 1, ( "should never happen" ) );
|
||||
return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
|
||||
}
|
||||
|
||||
if( ( ret = md_init_ctx( &ctx, md_info_from_type(md_alg) ) ) != 0 )
|
||||
{
|
||||
SSL_DEBUG_RET( 1, "md_init_ctx", ret );
|
||||
@ -2498,6 +2514,7 @@ static int ssl_parse_certificate_verify( ssl_context *ssl )
|
||||
int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
|
||||
size_t sa_len, sig_len;
|
||||
unsigned char hash[48];
|
||||
unsigned char *hash_start = hash;
|
||||
size_t hashlen;
|
||||
pk_type_t pk_alg;
|
||||
md_type_t md_alg;
|
||||
@ -2556,6 +2573,15 @@ static int ssl_parse_certificate_verify( ssl_context *ssl )
|
||||
|
||||
md_alg = POLARSSL_MD_NONE;
|
||||
hashlen = 36;
|
||||
|
||||
/* For ECDSA, use SHA-1, not MD-5 + SHA-1 */
|
||||
if( pk_can_do( &ssl->session_negotiate->peer_cert->pk,
|
||||
POLARSSL_PK_ECDSA ) )
|
||||
{
|
||||
hash_start += 16;
|
||||
hashlen -= 16;
|
||||
md_alg = POLARSSL_MD_SHA1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2607,7 +2633,7 @@ static int ssl_parse_certificate_verify( ssl_context *ssl )
|
||||
}
|
||||
|
||||
if( ( ret = pk_verify( &ssl->session_negotiate->peer_cert->pk,
|
||||
md_alg, hash, hashlen,
|
||||
md_alg, hash_start, hashlen,
|
||||
ssl->in_msg + 6 + sa_len, sig_len ) ) != 0 )
|
||||
{
|
||||
SSL_DEBUG_RET( 1, "pk_verify", ret );
|
||||
|
Loading…
Reference in New Issue
Block a user