Allow hardcoding single supported elliptic curve

This commit introduces the option MBEDTLS_SSL_CONF_SINGLE_EC
which can be used to register a single supported elliptic curve
at compile time. It replaces the runtime configuration API
mbedtls_ssl_conf_curves() which allows to register a _list_
of supported elliptic curves.

In contrast to other options used to hardcode configuration options,
MBEDTLS_SSL_CONF_SINGLE_EC isn't a numeric option, but instead it's
only relevant if it's defined or not. To actually set the single
elliptic curve that should be supported, numeric options

MBEDTLS_SSL_CONF_SINGLE_EC_TLS_ID
MBEDTLS_SSL_CONF_SINGLE_EC_GRP_ID

must both be defined and provide the TLS ID and the Mbed TLS internal
ID and the chosen curve, respectively.
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 735a1e4..509cfa4 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -87,6 +87,12 @@
 #error "MBEDTLS_CMAC_C defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_SSL_CONF_SINGLE_EC) &&           \
+    ( !defined(MBEDTLS_SSL_CONF_SINGLE_EC_TLS_ID) || \
+      !defined(MBEDTLS_SSL_CONF_SINGLE_EC_GRP_ID) )
+#error "MBEDTLS_SSL_CONF_SINGLE_EC defined, but not all prerequesites"
+#endif
+
 #if defined(MBEDTLS_USE_TINYCRYPT) && defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
 #error "MBEDTLS_USE_TINYCRYPT defined, but it cannot be defined with MBEDTLS_NO_64BIT_MULTIPLICATION"
 #endif
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 8290c51..9443c92 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -3652,6 +3652,33 @@
  */
 //#define MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE MBEDTLS_SUITE_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
 
+/* Enable support a single elliptic curve fixed
+ * at compile-time, at the benefit of code-size.
+ *
+ * On highly constrained systems which large control
+ * over the configuration of the connection endpoints,
+ * this option can be used to hardcode the choice of
+ * a single elliptic curve to use for all elliptic
+ * curve operations during the handshake.
+ *
+ * If this is set, you must also define the following:
+ * - MBEDTLS_SSL_CONF_SINGLE_EC_GRP_ID
+ *   This must resolve to the Mbed TLS group ID for the elliptic
+ *   curve to use (e.g. MBEDTLS_ECP_DP_SECP256R1_ENABLED); see
+ *   ::mbedtls_ecp_group_id in mbedtls/ecp.h for a complete list
+ *   of curve identifiers.
+ * - MBEDTLS_SSL_CONF_SINGLE_EC_TLS_ID
+ *   This must resolve to the identifier for the elliptic curve
+ *   to use according to the IANA NamedCurve registry:
+ *     https://tools.ietf.org/html/rfc4492#section-5.1
+ *
+ * If defined, this option overwrites the effect of the
+ * runtime configuration API mbedtls_ssl_conf_curves().
+ */
+//#define MBEDTLS_SSL_CONF_SINGLE_EC
+//#define MBEDTLS_SSL_CONF_SINGLE_EC_TLS_ID
+//#define MBEDTLS_SSL_CONF_SINGLE_EC_GRP_ID
+
 /* \} SECTION: Compile-time SSL configuration */
 
 /* Target and application specific configurations
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 169e054..9937b30 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1070,7 +1070,9 @@
 #endif
 
 #if defined(MBEDTLS_ECP_C)
+#if !defined(MBEDTLS_SSL_CONF_SINGLE_EC)
     const mbedtls_ecp_group_id *curve_list; /*!< allowed curves             */
+#endif /* MBEDTLS_SSL_CONF_SINGLE_EC */
 #endif
 
 #if defined(MBEDTLS_DHM_C)
@@ -2785,6 +2787,7 @@
 #endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */
 
 #if defined(MBEDTLS_ECP_C)
+#if !defined(MBEDTLS_SSL_CONF_SINGLE_EC)
 /**
  * \brief          Set the allowed curves in order of preference.
  *                 (Default: all defined curves.)
@@ -2808,12 +2811,17 @@
  * \note           This list should be ordered by decreasing preference
  *                 (preferred curve first).
  *
+ * \note           On highly constrained systems, the support for a single
+ *                 fixed elliptic curve can be configured at compile time
+ *                 through the option MBEDTLS_SSL_CONF_SINGLE_EC.
+ *
  * \param conf     SSL configuration
  * \param curves   Ordered list of allowed curves,
  *                 terminated by MBEDTLS_ECP_DP_NONE.
  */
 void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf,
                               const mbedtls_ecp_group_id *curves );
+#endif /* !MBEDTLS_SSL_CONF_SINGLE_EC */
 #endif /* MBEDTLS_ECP_C */
 
 #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index f7ae625..9259955 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -1484,6 +1484,8 @@
 
 #endif /* MBEDTLS_SSL_CONF_SINGLE_CIPHERSUITE */
 
+#if !defined(MBEDTLS_SSL_CONF_SINGLE_EC)
+
 #define MBEDTLS_SSL_BEGIN_FOR_EACH_SUPPORTED_EC_TLS_ID( TLS_ID_VAR )    \
     {                                                                   \
         mbedtls_ecp_group_id const *__gid;                              \
@@ -1513,4 +1515,24 @@
         }                                                               \
     }
 
+#else /* !MBEDTLS_SSL_CONF_SINGLE_EC */
+
+#define MBEDTLS_SSL_BEGIN_FOR_EACH_SUPPORTED_EC_TLS_ID( TLS_ID_VAR )    \
+    {                                                                   \
+        uint16_t TLS_ID_VAR = MBEDTLS_SSL_CONF_SINGLE_EC_TLS_ID;        \
+        ((void) ssl);
+
+#define MBEDTLS_SSL_END_FOR_EACH_SUPPORTED_EC_TLS_ID                    \
+    }
+
+#define MBEDTLS_SSL_BEGIN_FOR_EACH_SUPPORTED_EC_GRP_ID( EC_ID_VAR )         \
+    {                                                                       \
+        mbedtls_ecp_group_id EC_ID_VAR = MBEDTLS_SSL_CONF_SINGLE_EC_GRP_ID; \
+        ((void) ssl);
+
+#define MBEDTLS_SSL_END_FOR_EACH_SUPPORTED_EC_GRP_ID                    \
+    }
+
+#endif /* MBEDTLS_SSL_CONF_SINGLE_EC */
+
 #endif /* ssl_internal.h */