diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 1bda2b3959..2b50304aa4 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 @@ struct _ssl_context 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( ssl_context *ssl, const char *dhm_P, const char *dhm_G ); 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 0abded139b..dfae8c5a18 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -2092,10 +2092,7 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) #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 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) * 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 @@ static int ssl_write_server_key_exchange( ssl_context *ssl ) 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 36378ef1bd..02f24a18ff 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -3325,6 +3325,46 @@ static int ssl_handshake_init( ssl_context *ssl ) */ 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 @@ int ssl_init( ssl_context *ssl ) 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 @@ md_type_t ssl_md_alg_from_hash( unsigned char hash ) } #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