Add compile-time option to hardcode choice of single ciphersuite
diff --git a/configs/baremetal.h b/configs/baremetal.h
index ee514b4..99d5410 100644
--- a/configs/baremetal.h
+++ b/configs/baremetal.h
@@ -60,6 +60,7 @@
 /* Key exchanges */
 #define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 #define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+//#define MBEDTLS_SSL_SINGLE_CIPHERSUITE MBEDTLS_SUITE_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
 
 /* Digests - just SHA-256 */
 #define MBEDTLS_MD_C
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 91d2550..2b7e9da 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -3641,6 +3641,17 @@
 //#define MBEDTLS_SSL_CONF_EXTENDED_MASTER_SECRET MBEDTLS_SSL_EXTENDED_MS_ENABLED
 //#define MBEDTLS_SSL_CONF_ENFORCE_EXTENDED_MASTER_SECRET MBEDTLS_SSL_EXTENDED_MS_ENFORCE_DISABLED
 
+/* Set this to MBEDTLS_SUITE_{OFFICIAL_SUITE_NAME} to hardcode
+ * the choice of a fixed ciphersuite at compile-time.
+ *
+ * You need to make sure that the corresponding ciphersuite attributes
+ * are defined through macros in ssl_ciphersuites.h. See the definitions
+ * of MBEDTLS_SUITE_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8_XXX for an example.
+ *
+ * If this option is set, the API mbedtls_ssl_conf_ciphersuites() is removed.
+ */
+//#define MBEDTLS_SSL_SINGLE_CIPHERSUITE MBEDTLS_SUITE_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8
+
 /* \} SECTION: Compile-time SSL configuration */
 
 /* Target and application specific configurations
diff --git a/include/mbedtls/ssl_ciphersuites.h b/include/mbedtls/ssl_ciphersuites.h
index 3d3805c..2f31cee 100644
--- a/include/mbedtls/ssl_ciphersuites.h
+++ b/include/mbedtls/ssl_ciphersuites.h
@@ -364,6 +364,7 @@
 #define MBEDTLS_SSL_SUITE_MAX_MINOR_VER( SUITE ) MBEDTLS_SSL_SUITE_MAX_MINOR_VER_T( SUITE )
 #define MBEDTLS_SSL_SUITE_FLAGS(         SUITE ) MBEDTLS_SSL_SUITE_FLAGS_T(         SUITE )
 
+#if !defined(MBEDTLS_SSL_SINGLE_CIPHERSUITE)
 /**
  * \brief   This structure is used for storing ciphersuite information
  */
@@ -402,6 +403,15 @@
       MBEDTLS_SSL_SUITE_MAX_MAJOR_VER( SUITE ),   \
       MBEDTLS_SSL_SUITE_MAX_MINOR_VER( SUITE ),   \
       MBEDTLS_SSL_SUITE_FLAGS( SUITE ) }
+
+#else /* !MBEDTLS_SSL_SINGLE_CIPHERSUITE */
+
+typedef unsigned char mbedtls_ssl_ciphersuite_handle_t;
+#define MBEDTLS_SSL_CIPHERSUITE_INVALID_HANDLE      ( (mbedtls_ssl_ciphersuite_handle_t) 0 )
+#define MBEDTLS_SSL_CIPHERSUITE_UNIQUE_VALID_HANDLE ( (mbedtls_ssl_ciphersuite_handle_t) 1 )
+
+#endif /* MBEDTLS_SSL_SINGLE_CIPHERSUITE */
+
 /*
  * Getter functions for the extraction of ciphersuite attributes
  * from a ciphersuite handle.
@@ -411,6 +421,7 @@
  * is passed.
  */
 
+#if !defined(MBEDTLS_SSL_SINGLE_CIPHERSUITE)
 /*
  * Implementation of getter functions when the ciphersuite handle
  * is a pointer to the ciphersuite information structure.
@@ -468,6 +479,77 @@
 {
     return( info->flags );
 }
+#else /* !MBEDTLS_SSL_SINGLE_CIPHERSUITE */
+/*
+ * Implementations of getter functions in the case of only
+ * a single possible ciphersuite. In this case, the handle
+ * is logically a boolean (either the invalid handle or the
+ * unique valid handle representing the single enabled
+ * ciphersuite), and the precondition that the handle is valid
+ * means that we can statically return the hardcoded attribute
+ * of the enabled ciphersuite.
+ */
+static inline int mbedtls_ssl_suite_get_id(
+    mbedtls_ssl_ciphersuite_handle_t const info )
+{
+    ((void) info);
+    return( MBEDTLS_SSL_SUITE_ID( MBEDTLS_SSL_SINGLE_CIPHERSUITE ) );
+}
+static inline const char* mbedtls_ssl_suite_get_name(
+    mbedtls_ssl_ciphersuite_handle_t const info )
+{
+    ((void) info);
+    return( MBEDTLS_SSL_SUITE_NAME( MBEDTLS_SSL_SINGLE_CIPHERSUITE ) );
+}
+static inline mbedtls_cipher_type_t mbedtls_ssl_suite_get_cipher(
+    mbedtls_ssl_ciphersuite_handle_t const info )
+{
+    ((void) info);
+    return( MBEDTLS_SSL_SUITE_CIPHER( MBEDTLS_SSL_SINGLE_CIPHERSUITE ) );
+}
+static inline mbedtls_md_type_t mbedtls_ssl_suite_get_mac(
+    mbedtls_ssl_ciphersuite_handle_t const info )
+{
+    ((void) info);
+    return( MBEDTLS_SSL_SUITE_MAC( MBEDTLS_SSL_SINGLE_CIPHERSUITE ) );
+}
+static inline mbedtls_key_exchange_type_t mbedtls_ssl_suite_get_key_exchange(
+    mbedtls_ssl_ciphersuite_handle_t const info )
+{
+    ((void) info);
+    return( MBEDTLS_SSL_SUITE_KEY_EXCHANGE( MBEDTLS_SSL_SINGLE_CIPHERSUITE ) );
+}
+static inline int mbedtls_ssl_suite_get_min_major_ver(
+    mbedtls_ssl_ciphersuite_handle_t const info )
+{
+    ((void) info);
+    return( MBEDTLS_SSL_SUITE_MIN_MAJOR_VER( MBEDTLS_SSL_SINGLE_CIPHERSUITE ) );
+}
+static inline int mbedtls_ssl_suite_get_min_minor_ver(
+    mbedtls_ssl_ciphersuite_handle_t const info )
+{
+    ((void) info);
+    return( MBEDTLS_SSL_SUITE_MIN_MINOR_VER( MBEDTLS_SSL_SINGLE_CIPHERSUITE ) );
+}
+static inline int mbedtls_ssl_suite_get_max_major_ver(
+    mbedtls_ssl_ciphersuite_handle_t const info )
+{
+    ((void) info);
+    return( MBEDTLS_SSL_SUITE_MAX_MAJOR_VER( MBEDTLS_SSL_SINGLE_CIPHERSUITE ) );
+}
+static inline int mbedtls_ssl_suite_get_max_minor_ver(
+    mbedtls_ssl_ciphersuite_handle_t const info )
+{
+    ((void) info);
+    return( MBEDTLS_SSL_SUITE_MAX_MINOR_VER( MBEDTLS_SSL_SINGLE_CIPHERSUITE ) );
+}
+static inline unsigned char mbedtls_ssl_suite_get_flags(
+    mbedtls_ssl_ciphersuite_handle_t const info )
+{
+    ((void) info);
+    return( MBEDTLS_SSL_SUITE_FLAGS( MBEDTLS_SSL_SINGLE_CIPHERSUITE ) );
+}
+#endif /* MBEDTLS_SSL_SINGLE_CIPHERSUITE */
 
 static inline int mbedtls_ssl_ciphersuite_has_pfs(
     mbedtls_ssl_ciphersuite_handle_t info )
diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c
index ffe0341..d37d7a2 100644
--- a/library/ssl_ciphersuites.c
+++ b/library/ssl_ciphersuites.c
@@ -54,6 +54,7 @@
  */
 static const int ciphersuite_preference[] =
 {
+#if !defined(MBEDTLS_SSL_SINGLE_CIPHERSUITE)
 #if defined(MBEDTLS_SSL_CIPHERSUITES)
     MBEDTLS_SSL_CIPHERSUITES,
 #else
@@ -311,9 +312,13 @@
     MBEDTLS_TLS_PSK_WITH_NULL_SHA,
 
 #endif /* MBEDTLS_SSL_CIPHERSUITES */
+#else /* !MBEDTLS_SSL_SINGLE_CIPHERSUITE */
+    MBEDTLS_SSL_SUITE_ID( MBEDTLS_SSL_SINGLE_CIPHERSUITE ),
+#endif /* MBEDTLS_SSL_SINGLE_CIPHERSUITE */
     0
 };
 
+#if !defined(MBEDTLS_SSL_SINGLE_CIPHERSUITE)
 static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 {
 #if defined(MBEDTLS_CHACHAPOLY_C) && \
@@ -2166,8 +2171,9 @@
       MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE,
       0, 0, 0, 0, 0 }
 };
+#endif /* !MBEDTLS_SSL_SINGLE_CIPHERSUITE */
 
-#if defined(MBEDTLS_SSL_CIPHERSUITES)
+#if defined(MBEDTLS_SSL_CIPHERSUITES) || defined(MBEDTLS_SSL_SINGLE_CIPHERSUITE)
 const int *mbedtls_ssl_list_ciphersuites( void )
 {
     return( ciphersuite_preference );
@@ -2226,8 +2232,9 @@
 
     return( supported_ciphersuites );
 }
-#endif /* MBEDTLS_SSL_CIPHERSUITES */
+#endif /* !( MBEDTLS_SSL_CIPHERSUITES || MBEDTLS_SSL_SINGLE_CIPHERSUITE ) */
 
+#if !defined(MBEDTLS_SSL_SINGLE_CIPHERSUITE)
 mbedtls_ssl_ciphersuite_handle_t mbedtls_ssl_ciphersuite_from_string(
                                                 const char *ciphersuite_name )
 {
@@ -2286,6 +2293,55 @@
     return( cur->id );
 }
 
+#else /* !MBEDTLS_SSL_SINGLE_CIPHERSUITE */
+
+mbedtls_ssl_ciphersuite_handle_t mbedtls_ssl_ciphersuite_from_string(
+                                                const char *ciphersuite_name )
+{
+    static const char * const single_suite_name =
+        MBEDTLS_SSL_SUITE_NAME( MBEDTLS_SSL_SINGLE_CIPHERSUITE );
+
+    if( strcmp( ciphersuite_name, single_suite_name ) == 0 )
+        return( MBEDTLS_SSL_CIPHERSUITE_UNIQUE_VALID_HANDLE );
+
+    return( MBEDTLS_SSL_CIPHERSUITE_INVALID_HANDLE );
+}
+
+mbedtls_ssl_ciphersuite_handle_t mbedtls_ssl_ciphersuite_from_id( int ciphersuite )
+{
+    static const int single_suite_id =
+        MBEDTLS_SSL_SUITE_ID( MBEDTLS_SSL_SINGLE_CIPHERSUITE );
+
+    if( ciphersuite == single_suite_id )
+        return( MBEDTLS_SSL_CIPHERSUITE_UNIQUE_VALID_HANDLE );
+
+    return( MBEDTLS_SSL_CIPHERSUITE_INVALID_HANDLE );
+}
+
+const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id )
+{
+    static const int single_suite_id =
+        MBEDTLS_SSL_SUITE_ID( MBEDTLS_SSL_SINGLE_CIPHERSUITE );
+
+    if( ciphersuite_id == single_suite_id )
+        return( MBEDTLS_SSL_SUITE_NAME( MBEDTLS_SSL_SINGLE_CIPHERSUITE ) );
+
+    return( NULL );
+}
+
+int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name )
+{
+    static const char * const single_suite_name =
+        MBEDTLS_SSL_SUITE_NAME( MBEDTLS_SSL_SINGLE_CIPHERSUITE );
+
+    if( strcmp( ciphersuite_name, single_suite_name ) == 0 )
+        return( MBEDTLS_SSL_SUITE_ID( MBEDTLS_SSL_SINGLE_CIPHERSUITE ) );
+
+    return( 0 );
+}
+
+#endif /* MBEDTLS_SSL_SINGLE_CIPHERSUITE */
+
 #if defined(MBEDTLS_PK_C)
 mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( mbedtls_ssl_ciphersuite_handle_t info )
 {