Added the possibility to define the allowed curves for ECDHE handshake. It also defines the preference of the curves.
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index 1bda2b3..2b50304 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -83,6 +83,12 @@
#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED
#endif
+#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
+ defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
+ defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED
+#endif
+
#if defined(_MSC_VER) && !defined(inline)
#define inline _inline
#else
@@ -721,6 +727,9 @@
int disable_renegotiation; /*!< enable/disable renegotiation */
int allow_legacy_renegotiation; /*!< allow legacy renegotiation */
const int *ciphersuite_list[4]; /*!< allowed ciphersuites / version */
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED)
+ const ecp_group_id *ecdh_curve_list;/*!< allowed curves for ECDH */
+#endif
#if defined(POLARSSL_SSL_TRUNCATED_HMAC)
int trunc_hmac; /*!< negotiate truncated hmac? */
#endif
@@ -1149,6 +1158,19 @@
int ssl_set_dh_param_ctx( ssl_context *ssl, dhm_context *dhm_ctx );
#endif
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED)
+/**
+ * \brief Set the allowed ECDH curves.
+ *
+ * The sequence of the curves in the list also determines the
+ * handshake curve preference.
+ *
+ * \param ssl SSL context
+ * \param ecdh_curve_list Zero terminated list of the allowed ECDH curves
+ */
+void ssl_set_ecdh_curves( ssl_context *ssl, const ecp_group_id *ecdh_curve_list );
+#endif
+
#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION)
/**
* \brief Set hostname for ServerName TLS extension
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 0abded1..dfae8c5 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -2092,10 +2092,7 @@
#endif /* POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED ||
POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED */
-#if defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
- defined(POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
- defined(POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
-
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED)
if( ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_RSA ||
ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA ||
ciphersuite_info->key_exchange == POLARSSL_KEY_EXCHANGE_ECDHE_PSK )
@@ -2108,8 +2105,41 @@
* ECPoint public;
* } ServerECDHParams;
*/
+
+ unsigned int pref_idx, curv_idx, found;
+
+ /* Match our preference list against the agreed curves */
+ for( pref_idx = 0, found = 0;
+ ssl->ecdh_curve_list[pref_idx] != POLARSSL_ECP_DP_NONE;
+ pref_idx++ )
+ {
+ /* Look through the agreed curve list */
+ for( curv_idx = 0;
+ ssl->handshake->curves[curv_idx] != NULL;
+ curv_idx++ )
+ {
+ if (ssl->handshake->curves[curv_idx]->grp_id ==
+ ssl->ecdh_curve_list[pref_idx] )
+ {
+ /* We found our most preferred curve */
+ found = 1;
+ break;
+ }
+ }
+
+ /* Exit the search if we have found our curve */
+ if( found == 1 )
+ {
+ break;
+ }
+ }
+ /* If we haven't found any allowed / preferred curve,
+ * ssl->ecdh_curve_list[pref_idx] will contain POLARSSL_ECP_DP_NONE and
+ * ecp_use_known_dp() will fail.
+ */
+
if( ( ret = ecp_use_known_dp( &ssl->handshake->ecdh_ctx.grp,
- ssl->handshake->curves[0]->grp_id ) ) != 0 )
+ ssl->ecdh_curve_list[pref_idx] ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ecp_use_known_dp", ret );
return( ret );
@@ -2134,9 +2164,7 @@
SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q );
}
-#endif /* POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
- POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ||
- POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+#endif /* POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED */
#if defined(POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
defined(POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 36378ef..02f24a1 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -3325,6 +3325,46 @@
*/
int ssl_init( ssl_context *ssl )
{
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED)
+ /*
+ * ECDHE allowed curves and preference list
+ *
+ * We start with the most secure curves. From the same size curves, we prefer
+ * the SECP ones because they are much faster.
+ *
+ * TODO: Add the Montgomery curves
+ */
+ static const ecp_group_id ecdh_default_curve_list[] =
+ {
+#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
+ POLARSSL_ECP_DP_SECP521R1,
+#endif
+#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
+ POLARSSL_ECP_DP_BP512R1,
+#endif
+#if defined(POLARSSL_ECP_DP_SECP384R1_ENABLED)
+ POLARSSL_ECP_DP_SECP384R1,
+#endif
+#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
+ POLARSSL_ECP_DP_BP384R1,
+#endif
+#if defined(POLARSSL_ECP_DP_SECP256R1_ENABLED)
+ POLARSSL_ECP_DP_SECP256R1,
+#endif
+#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
+ POLARSSL_ECP_DP_BP256R1,
+#endif
+#if defined(POLARSSL_ECP_DP_SECP224R1_ENABLED)
+ POLARSSL_ECP_DP_SECP224R1,
+#endif
+#if defined(POLARSSL_ECP_DP_SECP192R1_ENABLED)
+ POLARSSL_ECP_DP_SECP192R1,
+#endif
+ POLARSSL_ECP_DP_NONE
+ };
+#endif
+
int ret;
int len = SSL_BUFFER_LEN;
@@ -3384,6 +3424,10 @@
ssl->ticket_lifetime = SSL_DEFAULT_TICKET_LIFETIME;
#endif
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED)
+ ssl->ecdh_curve_list = ecdh_default_curve_list;
+#endif
+
if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
return( ret );
@@ -4610,3 +4654,13 @@
}
#endif
+
+#if defined(POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED)
+/*
+ * Set the allowed ECDH curves.
+ */
+void ssl_set_ecdh_curves( ssl_context *ssl, const ecp_group_id *ecdh_curve_list )
+{
+ ssl->ecdh_curve_list = ecdh_curve_list;
+}
+#endif