Check our ECDSA cert(s) against supported curves

This commit is contained in:
Manuel Pégourié-Gonnard 2013-09-23 19:11:32 +02:00
parent f24b4a7316
commit d09453c88c
3 changed files with 82 additions and 29 deletions

View File

@ -490,7 +490,7 @@ struct _ssl_handshake_params
ecdh_context ecdh_ctx; /*!< ECDH key exchange */ ecdh_context ecdh_ctx; /*!< ECDH key exchange */
#endif #endif
#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) #if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
int ec_curve; /*!< Selected elliptic curve */ const ecp_curve_info **curves; /*!< Supported elliptic curves */
#endif #endif
#if defined(POLARSSL_X509_CRT_PARSE_C) #if defined(POLARSSL_X509_CRT_PARSE_C)
ssl_key_cert *key_cert; /*!< Own key/cert in use */ ssl_key_cert *key_cert; /*!< Own key/cert in use */

View File

@ -501,9 +501,9 @@ static int ssl_parse_supported_elliptic_curves( ssl_context *ssl,
const unsigned char *buf, const unsigned char *buf,
size_t len ) size_t len )
{ {
size_t list_size; size_t list_size, our_size;
const unsigned char *p; const unsigned char *p;
const ecp_curve_info *curve_info; const ecp_curve_info *curve_info, **curves;
list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( list_size + 2 != len || if( list_size + 2 != len ||
@ -513,15 +513,27 @@ static int ssl_parse_supported_elliptic_curves( ssl_context *ssl,
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
} }
/* Don't allow our peer to make use allocated too much memory,
* and leave room for a final 0 */
our_size = list_size / 2 + 1;
if( our_size > POLARSSL_ECP_DP_MAX )
our_size = POLARSSL_ECP_DP_MAX;
if( ( curves = polarssl_malloc( our_size * sizeof( *curves ) ) ) == NULL )
return( POLARSSL_ERR_SSL_MALLOC_FAILED );
memset( curves, 0, our_size * sizeof( *curves ) );
ssl->handshake->curves = curves;
p = buf + 2; p = buf + 2;
while( list_size > 0 ) while( list_size > 0 && our_size > 1 )
{ {
curve_info = ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] ); curve_info = ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] );
if( curve_info != NULL ) if( curve_info != NULL )
{ {
ssl->handshake->ec_curve = curve_info->grp_id; *curves++ = curve_info;
return( 0 ); our_size--;
} }
list_size -= 2; list_size -= 2;
@ -875,6 +887,62 @@ have_ciphersuite_v2:
} }
#endif /* POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ #endif /* POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
#if defined(POLARSSL_X509_CRT_PARSE_C)
#if defined(POLARSSL_ECDSA_C)
static int ssl_key_matches_curves( pk_context *pk,
const ecp_curve_info **curves )
{
const ecp_curve_info **crv = curves;
ecp_group_id grp_id = pk_ec( *pk )->grp.id;
while( *crv != NULL )
{
if( (*crv)->grp_id == grp_id )
return( 1 );
crv++;
}
return( 0 );
}
#endif /* POLARSSL_ECDSA_C */
/*
* Try picking a certificate for this ciphersuite,
* return 0 on success and -1 on failure.
*/
static int ssl_pick_cert( ssl_context *ssl,
const ssl_ciphersuite_t * ciphersuite_info )
{
ssl_key_cert *cur;
pk_type_t pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
if( pk_alg == POLARSSL_PK_NONE )
return( 0 );
for( cur = ssl->key_cert; cur != NULL; cur = cur->next )
{
if( ! pk_can_do( cur->key, pk_alg ) )
continue;
#if defined(POLARSSL_ECDSA_C)
if( pk_alg == POLARSSL_PK_ECDSA )
{
if( ssl_key_matches_curves( cur->key, ssl->handshake->curves ) )
break;
}
else
#endif
break;
}
if( cur == NULL )
return( -1 );
ssl->handshake->key_cert = cur;
return( 0 );
}
#endif /* POLARSSL_X509_CRT_PARSE_C */
static int ssl_parse_client_hello( ssl_context *ssl ) static int ssl_parse_client_hello( ssl_context *ssl )
{ {
int ret; int ret;
@ -888,9 +956,6 @@ static int ssl_parse_client_hello( ssl_context *ssl )
int handshake_failure = 0; int handshake_failure = 0;
const int *ciphersuites; const int *ciphersuites;
const ssl_ciphersuite_t *ciphersuite_info; const ssl_ciphersuite_t *ciphersuite_info;
#if defined(POLARSSL_PK_C)
pk_type_t pk_alg;
#endif
SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
@ -1298,7 +1363,7 @@ static int ssl_parse_client_hello( ssl_context *ssl )
#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C) #if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
if( ssl_ciphersuite_uses_ec( ciphersuite_info ) && if( ssl_ciphersuite_uses_ec( ciphersuite_info ) &&
ssl->handshake->ec_curve == 0 ) ssl->handshake->curves[0] == NULL )
continue; continue;
#endif #endif
@ -1310,24 +1375,8 @@ static int ssl_parse_client_hello( ssl_context *ssl )
* - try the next ciphersuite if we don't * - try the next ciphersuite if we don't
* This must be done last since we modify the key_cert list. * This must be done last since we modify the key_cert list.
*/ */
pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); if( ssl_pick_cert( ssl, ciphersuite_info ) != 0 )
if( pk_alg != POLARSSL_PK_NONE ) continue;
{
ssl_key_cert *good = NULL;
ssl_key_cert *cur = ssl->key_cert;
while( cur != NULL && good == NULL )
{
if( pk_can_do( cur->key, pk_alg ) )
good = cur;
cur = cur->next;
}
if( good == NULL )
continue;
else
ssl->handshake->key_cert = good;
}
#endif #endif
goto have_ciphersuite; goto have_ciphersuite;
@ -1928,7 +1977,7 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
* } ServerECDHParams; * } ServerECDHParams;
*/ */
if( ( ret = ecp_use_known_dp( &ssl->handshake->ecdh_ctx.grp, if( ( ret = ecp_use_known_dp( &ssl->handshake->ecdh_ctx.grp,
ssl->handshake->ec_curve ) ) != 0 ) ssl->handshake->curves[0]->grp_id ) ) != 0 )
{ {
SSL_DEBUG_RET( 1, "ecp_use_known_dp", ret ); SSL_DEBUG_RET( 1, "ecp_use_known_dp", ret );
return( ret ); return( ret );

View File

@ -4145,6 +4145,10 @@ void ssl_handshake_free( ssl_handshake_params *handshake )
ecdh_free( &handshake->ecdh_ctx ); ecdh_free( &handshake->ecdh_ctx );
#endif #endif
#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
polarssl_free( handshake->curves );
#endif
memset( handshake, 0, sizeof( ssl_handshake_params ) ); memset( handshake, 0, sizeof( ssl_handshake_params ) );
} }