Check our ECDSA cert(s) against supported curves
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index f357b46..144c852 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -490,7 +490,7 @@
ecdh_context ecdh_ctx; /*!< ECDH key exchange */
#endif
#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
- int ec_curve; /*!< Selected elliptic curve */
+ const ecp_curve_info **curves; /*!< Supported elliptic curves */
#endif
#if defined(POLARSSL_X509_CRT_PARSE_C)
ssl_key_cert *key_cert; /*!< Own key/cert in use */
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 9c90268..df7709b 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -501,9 +501,9 @@
const unsigned char *buf,
size_t len )
{
- size_t list_size;
+ size_t list_size, our_size;
const unsigned char *p;
- const ecp_curve_info *curve_info;
+ const ecp_curve_info *curve_info, **curves;
list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( list_size + 2 != len ||
@@ -513,15 +513,27 @@
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;
- while( list_size > 0 )
+ while( list_size > 0 && our_size > 1 )
{
curve_info = ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] );
if( curve_info != NULL )
{
- ssl->handshake->ec_curve = curve_info->grp_id;
- return( 0 );
+ *curves++ = curve_info;
+ our_size--;
}
list_size -= 2;
@@ -875,6 +887,62 @@
}
#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 )
{
int ret;
@@ -888,9 +956,6 @@
int handshake_failure = 0;
const int *ciphersuites;
const ssl_ciphersuite_t *ciphersuite_info;
-#if defined(POLARSSL_PK_C)
- pk_type_t pk_alg;
-#endif
SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) );
@@ -1298,7 +1363,7 @@
#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
if( ssl_ciphersuite_uses_ec( ciphersuite_info ) &&
- ssl->handshake->ec_curve == 0 )
+ ssl->handshake->curves[0] == NULL )
continue;
#endif
@@ -1310,24 +1375,8 @@
* - try the next ciphersuite if we don't
* This must be done last since we modify the key_cert list.
*/
- pk_alg = ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info );
- if( pk_alg != POLARSSL_PK_NONE )
- {
- 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;
- }
+ if( ssl_pick_cert( ssl, ciphersuite_info ) != 0 )
+ continue;
#endif
goto have_ciphersuite;
@@ -1928,7 +1977,7 @@
* } ServerECDHParams;
*/
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 );
return( ret );
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 5ab4a5c..cafdcf0 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -4145,6 +4145,10 @@
ecdh_free( &handshake->ecdh_ctx );
#endif
+#if defined(POLARSSL_ECDH_C) || defined(POLARSSL_ECDSA_C)
+ polarssl_free( handshake->curves );
+#endif
+
memset( handshake, 0, sizeof( ssl_handshake_params ) );
}