diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 38b402954d..29e9316351 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -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 ) { diff --git a/library/ssl_srv.c b/library/ssl_srv.c index ce45898d0b..8efd57e82f 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -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 );