Allow compile-time configuration of legacy renegotiation

Introduces MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION
allowing to configure enforcing secure renegotiation at
compile-time.

Impact on code-size:

|  | GCC | ARMC5 | ARMC6 |
| --- | --- | --- | --- |
| `libmbedtls.a` after  | 23379 | 23929 | 27727 |
| `libmbedtls.a` before | 23307 | 23865 | 27615 |
| gain in Bytes | 72 | 64 | 112 |
diff --git a/configs/baremetal.h b/configs/baremetal.h
index fad3992..a836d4a 100644
--- a/configs/baremetal.h
+++ b/configs/baremetal.h
@@ -80,6 +80,8 @@
 #define MBEDTLS_SSL_DTLS_CONNECTION_ID
 
 /* Compile-time fixed parts of the SSL configuration */
+#define MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION \
+    MBEDTLS_SSL_SECURE_RENEGOTIATION
 #define MBEDTLS_SSL_CONF_AUTHMODE MBEDTLS_SSL_VERIFY_REQUIRED
 #define MBEDTLS_SSL_CONF_BADMAC_LIMIT 0
 #define MBEDTLS_SSL_CONF_ANTI_REPLAY MBEDTLS_SSL_ANTI_REPLAY_ENABLED
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 3381b79..d45d887 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -3450,6 +3450,8 @@
  * \{
  */
 
+//#define MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION
+
 //#define MBEDTLS_SSL_CONF_AUTHMODE MBEDTLS_SSL_VERIFY_REQUIRED
 
 /* DTLS-specific settings */
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 492a324..d783d07 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1052,8 +1052,10 @@
 #if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
     unsigned int authmode : 2;      /*!< MBEDTLS_SSL_VERIFY_XXX             */
 #endif /* !MBEDTLS_SSL_CONF_AUTHMODE */
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
     /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE          */
     unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX   */
+#endif /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
 #if defined(MBEDTLS_ARC4_C)
     unsigned int arc4_disabled : 1; /*!< blacklist RC4 ciphersuites?        */
 #endif
@@ -3047,6 +3049,7 @@
 void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation );
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
 /**
  * \brief          Prevent or allow legacy renegotiation.
  *                 (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION)
@@ -3073,8 +3076,14 @@
  * \param allow_legacy  Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION,
  *                                        SSL_ALLOW_LEGACY_RENEGOTIATION or
  *                                        MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE)
+ *
+ *
+ * \note            On constrained systems, this option can also be
+ *                  fixed at compile-time by defining the constant
+ *                  MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION.
  */
 void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy );
+#endif /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
 /**
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index 378db24..20d2006 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -1085,6 +1085,21 @@
  * be fixed at compile time via one of MBEDTLS_SSL_SSL_CONF_XXX.
  */
 
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
+static inline unsigned int mbedtls_ssl_conf_get_allow_legacy_renegotiation(
+    mbedtls_ssl_config  const *conf )
+{
+    return( conf->allow_legacy_renegotiation );
+}
+#else /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
+static inline unsigned int mbedtls_ssl_conf_get_allow_legacy_renegotiation(
+    mbedtls_ssl_config  const *conf )
+{
+    ((void) conf);
+    return( MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION );
+}
+#endif /* MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
+
 #if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
 static inline int mbedtls_ssl_conf_get_authmode(
     mbedtls_ssl_config  const *conf )
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 17611d6..92c7c73 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -2059,7 +2059,8 @@
      * Renegotiation security checks
      */
     if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-        ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
+        mbedtls_ssl_conf_get_allow_legacy_renegotiation( ssl->conf ) ==
+          MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
         handshake_failure = 1;
@@ -2074,7 +2075,8 @@
     }
     else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
              ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-             ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
+             mbedtls_ssl_conf_get_allow_legacy_renegotiation( ssl->conf ) ==
+               MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
         handshake_failure = 1;
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 9cc8be7..0009f8b 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -1227,7 +1227,8 @@
      * SSLv2 Client Hello relevant renegotiation security checks
      */
     if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-        ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
+        mbedtls_ssl_conf_get_allow_legacy_renegotiation( ssl->conf ) ==
+          MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@@ -2004,7 +2005,8 @@
      * Renegotiation security checks
      */
     if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION &&
-        ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
+        mbedtls_ssl_conf_get_allow_legacy_renegotiation( ssl->conf ) ==
+          MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) );
         handshake_failure = 1;
@@ -2019,7 +2021,8 @@
     }
     else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
              ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-             ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
+             mbedtls_ssl_conf_get_allow_legacy_renegotiation( ssl->conf )
+               == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) );
         handshake_failure = 1;
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 0c05b50..65cdd49 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -8675,10 +8675,12 @@
 }
 #endif
 
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
 void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy )
 {
     conf->allow_legacy_renegotiation = allow_legacy;
 }
+#endif /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
 void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation )
@@ -9999,7 +10001,7 @@
             /* Determine whether renegotiation attempt should be accepted */
             if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
                     ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
-                      ssl->conf->allow_legacy_renegotiation ==
+                      mbedtls_ssl_conf_get_allow_legacy_renegotiation( ssl->conf ) ==
                                                    MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) )
             {
                 /*
diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c
index 2557675..2871fd7 100644
--- a/programs/ssl/query_config.c
+++ b/programs/ssl/query_config.c
@@ -2578,6 +2578,14 @@
     }
 #endif /* MBEDTLS_PLATFORM_GMTIME_R_ALT */
 
+#if defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
+    if( strcmp( "MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
+
 #if defined(MBEDTLS_SSL_CONF_AUTHMODE)
     if( strcmp( "MBEDTLS_SSL_CONF_AUTHMODE", config ) == 0 )
     {
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index dc5542e..879fcf4 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -301,6 +301,12 @@
 #define USAGE_AUTH_MODE ""
 #endif
 
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
+#define USAGE_ALLOW_LEGACY_RENEGO    "    allow_legacy=%%d     default: (library default: no)\n"
+#else
+#define USAGE_ALLOW_LEGACY_RENEGO ""
+#endif
+
 #define USAGE \
     "\n usage: ssl_client2 param=<>...\n"                   \
     "\n acceptable parameters:\n"                           \
@@ -332,7 +338,7 @@
     USAGE_ECJPAKE                                           \
     USAGE_ECRESTART                                         \
     "\n"                                                    \
-    "    allow_legacy=%%d     default: (library default: no)\n"   \
+    USAGE_ALLOW_LEGACY_RENEGO                               \
     USAGE_RENEGO                                            \
     "    exchanges=%%d        default: 1\n"                 \
     "    reconnect=%%d        number of reconnections using session resumption\n" \
@@ -987,6 +993,7 @@
                 MBEDTLS_SSL_RENEGOTIATION_ENABLED :
                 MBEDTLS_SSL_RENEGOTIATION_DISABLED;
         }
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
         else if( strcmp( p, "allow_legacy" ) == 0 )
         {
             switch( atoi( q ) )
@@ -1003,6 +1010,7 @@
                 default: goto usage;
             }
         }
+#endif /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
         else if( strcmp( p, "renegotiate" ) == 0 )
         {
             opt.renegotiate = atoi( q );
@@ -1771,8 +1779,10 @@
         mbedtls_ssl_conf_arc4_support( &conf, opt.arc4 );
 #endif
 
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
     if( opt.allow_legacy != DFL_ALLOW_LEGACY )
         mbedtls_ssl_conf_legacy_renegotiation( &conf, opt.allow_legacy );
+#endif /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
     mbedtls_ssl_conf_renegotiation( &conf, opt.renegotiation );
 #endif
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 89bd4f4..2196dd1 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -408,6 +408,13 @@
 #define USAGE_AUTH_MODE ""
 #endif
 
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
+#define USAGE_ALLOW_LEGACY_RENEGO  \
+    "    allow_legacy=%%d     default: (library default: no)\n"
+#else
+#define USAGE_ALLOW_LEGACY_RENEGO ""
+#endif
+
 #define USAGE \
     "\n usage: ssl_server2 param=<>...\n"                   \
     "\n acceptable parameters:\n"                           \
@@ -440,7 +447,7 @@
     USAGE_PSK                                               \
     USAGE_ECJPAKE                                           \
     "\n"                                                    \
-    "    allow_legacy=%%d     default: (library default: no)\n"      \
+    USAGE_ALLOW_LEGACY_RENEGO                               \
     USAGE_RENEGO                                            \
     "    exchanges=%%d        default: 1\n"                 \
     "\n"                                                    \
@@ -1668,6 +1675,7 @@
                 MBEDTLS_SSL_RENEGOTIATION_ENABLED :
                 MBEDTLS_SSL_RENEGOTIATION_DISABLED;
         }
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
         else if( strcmp( p, "allow_legacy" ) == 0 )
         {
             switch( atoi( q ) )
@@ -1684,6 +1692,7 @@
                 default: goto usage;
             }
         }
+#endif /* !MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION */
         else if( strcmp( p, "renegotiate" ) == 0 )
         {
             opt.renegotiate = atoi( q );
@@ -2637,8 +2646,10 @@
                                           MBEDTLS_SSL_MINOR_VERSION_3 );
     }
 
+#if !defined(MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION)
     if( opt.allow_legacy != DFL_ALLOW_LEGACY )
         mbedtls_ssl_conf_legacy_renegotiation( &conf, opt.allow_legacy );
+#endif
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
     mbedtls_ssl_conf_renegotiation( &conf, opt.renegotiation );
 
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 4c3fc15..c5ff97e 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -543,6 +543,20 @@
     fi
 }
 
+check_cmdline_legacy_renego_compat() {
+    __VAL="$( get_config_value_or_default "MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION" )"
+    if [ ! -z "$__VAL" ]; then
+        extract_cmdline_argument "allow_legacy"
+        if [ "$__ARG" = "-1" ] && [ "$__VAL" != "2" ]; then
+            SKIP_NEXT="YES";
+        elif [ "$__ARG" = "0" ] && [ "$__VAL" != "0" ]; then
+            SKIP_NEXT="YES"
+        elif [ "$__ARG" = "1" ] && [ "$__VAL" != "1" ]; then
+            SKIP_NEXT="YES"
+        fi
+    fi
+}
+
 # Go through all options that can be hardcoded at compile-time and
 # detect whether the command line configures them in a conflicting
 # way. If so, skip the test. Otherwise, remove the corresponding
@@ -569,6 +583,9 @@
 
     # Authentication mode
     check_cmdline_authmode_compat
+
+    # Legacy renegotiation
+    check_cmdline_legacy_renego_compat
 }
 
 # Usage: run_test name [-p proxy_cmd] srv_cmd cli_cmd cli_exit [option [...]]