Create configuration option to bypass the mbedtls_ssl_set_hostname check

Update generated files.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 84af7f7..9590dd3 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -1713,6 +1713,46 @@
  */
 //#define MBEDTLS_SSL_ASYNC_PRIVATE
 
+/** \def MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME
+ *
+ * In TLS clients, when a client authenticates a server through its
+ * certificate, the client normally checks three things:
+ * - the certificate chain must be valid;
+ * - the chain must start from a trusted CA;
+ * - the certificate must cover the server name that is expected by the client.
+ *
+ * Omitting any of these checks is generally insecure, and can allow a
+ * malicious server to impersonate a legitimate server.
+ *
+ * The third check may be safely skipped in some unusual scenarios,
+ * such as networks where eavesdropping is a risk but not active attacks,
+ * or a private PKI where the client equally trusts all servers that are
+ * accredited by the root CA.
+ *
+ * You should call mbedtls_ssl_set_hostname() with the expected server name
+ * before starting a TLS handshake on a client (unless the client is
+ * set up to only use PSK-based authentication, which does not rely on the
+ * host name). This configuration option controls what happens if a TLS client
+ * is configured with the authentication mode #MBEDTLS_SSL_VERIFY_REQUIRED
+ * (default), certificate authentication is enabled and the client does not
+ * call mbedtls_ssl_set_hostname():
+ *
+ * - If this option is unset (default), the connection attempt is aborted
+ *   with the error #MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME.
+ * - If this option is set, the TLS library does not check the server name
+ *   that the certificate is valid for. This is the historical behavior
+ *   of Mbed TLS, but may be insecure as explained above.
+ *
+ * Enable this option for strict backward compatibility if you have
+ * determined that it is secure in the scenario where you are using
+ * Mbed TLS.
+ *
+ * \deprecated This option exists only for backward compatibility and will
+ *             be removed in the next major version of Mbed TLS.
+ *
+ */
+//#define MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME
+
 /**
  * \def MBEDTLS_SSL_CONTEXT_SERIALIZATION
  *
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 4b3a67c..541b879 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -213,6 +213,9 @@
  *   #MBEDTLS_SSL_VERIFY_REQUIRED (default).
  * - Certificate authentication is enabled.
  * - The client does not call mbedtls_ssl_set_hostname().
+ * - The configuration option
+ *   #MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME
+ *   is not enabled.
  */
 #define MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME  -0x5D80
 
diff --git a/library/error.c b/library/error.c
index dc75904..a0667e1 100644
--- a/library/error.c
+++ b/library/error.c
@@ -509,7 +509,7 @@
         case -(MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND):
             return( "SSL - Cache entry not found" );
         case -(MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME):
-            return( "SSL - Attempt to verify a certificate without an expected hostname. This is usually insecure.  In TLS clients, when a client authenticates a server through its certificate, the client normally checks three things: - the certificate chain must be valid; - the chain must start from a trusted CA; - the certificate must cover the server name that is expected by the client.  Omitting any of these checks is generally insecure, and can allow a malicious server to impersonate a legitimate server.  The third check may be safely skipped in some unusual scenarios, such as networks where eavesdropping is a risk but not active attacks, or a private PKI where the client equally trusts all servers that are accredited by the root CA.  You should call mbedtls_ssl_set_hostname() with the expected server name before starting a TLS handshake on a client (unless the client is set up to only use PSK-based authentication, which does not rely on the host name). If you have determined that server name verification is not required for security in your scenario, call mbedtls_ssl_set_hostname() with \\p NULL as the server name.  This error is raised if all of the following conditions are met:  - A TLS client is configured with the authentication mode #MBEDTLS_SSL_VERIFY_REQUIRED (default). - Certificate authentication is enabled. - The client does not call mbedtls_ssl_set_hostname()" );
+            return( "SSL - Attempt to verify a certificate without an expected hostname. This is usually insecure.  In TLS clients, when a client authenticates a server through its certificate, the client normally checks three things: - the certificate chain must be valid; - the chain must start from a trusted CA; - the certificate must cover the server name that is expected by the client.  Omitting any of these checks is generally insecure, and can allow a malicious server to impersonate a legitimate server.  The third check may be safely skipped in some unusual scenarios, such as networks where eavesdropping is a risk but not active attacks, or a private PKI where the client equally trusts all servers that are accredited by the root CA.  You should call mbedtls_ssl_set_hostname() with the expected server name before starting a TLS handshake on a client (unless the client is set up to only use PSK-based authentication, which does not rely on the host name). If you have determined that server name verification is not required for security in your scenario, call mbedtls_ssl_set_hostname() with \\p NULL as the server name.  This error is raised if all of the following conditions are met:  - A TLS client is configured with the authentication mode #MBEDTLS_SSL_VERIFY_REQUIRED (default). - Certificate authentication is enabled. - The client does not call mbedtls_ssl_set_hostname(). - The configuration option #MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME is not enabled" );
 #endif /* MBEDTLS_SSL_TLS_C */
 
 #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
diff --git a/library/version_features.c b/library/version_features.c
index 6f663b1..f5734c4 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -486,6 +486,9 @@
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
     "MBEDTLS_SSL_ASYNC_PRIVATE",
 #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+#if defined(MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME)
+    "MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME",
+#endif /* MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME */
 #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
     "MBEDTLS_SSL_CONTEXT_SERIALIZATION",
 #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
diff --git a/programs/test/query_config.c b/programs/test/query_config.c
index 5d9886b..d09b7f6 100644
--- a/programs/test/query_config.c
+++ b/programs/test/query_config.c
@@ -1376,6 +1376,14 @@
     }
 #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
 
+#if defined(MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME)
+    if( strcmp( "MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME */
+
 #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
     if( strcmp( "MBEDTLS_SSL_CONTEXT_SERIALIZATION", config ) == 0 )
     {
@@ -3506,6 +3514,10 @@
     OUTPUT_MACRO_NAME_VALUE(MBEDTLS_SSL_ASYNC_PRIVATE);
 #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
 
+#if defined(MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME)
+    OUTPUT_MACRO_NAME_VALUE(MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME);
+#endif /* MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME */
+
 #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
     OUTPUT_MACRO_NAME_VALUE(MBEDTLS_SSL_CONTEXT_SERIALIZATION);
 #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
diff --git a/scripts/config.py b/scripts/config.py
index 766b5af..ef72db3 100755
--- a/scripts/config.py
+++ b/scripts/config.py
@@ -326,6 +326,7 @@
 
 DEPRECATED = frozenset([
     'MBEDTLS_SSL_PROTO_SSL3',
+    'MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME',
     'MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO',
 ])
 
diff --git a/tests/suites/test_suite_config.mbedtls_boolean.data b/tests/suites/test_suite_config.mbedtls_boolean.data
index 1a1d13f..718bd28 100644
--- a/tests/suites/test_suite_config.mbedtls_boolean.data
+++ b/tests/suites/test_suite_config.mbedtls_boolean.data
@@ -1264,6 +1264,14 @@
 depends_on:!MBEDTLS_SSL_CBC_RECORD_SPLITTING:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C
 pass:
 
+Config: MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME
+depends_on:MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C
+pass:
+
+Config: !MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME
+depends_on:!MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C
+pass:
+
 Config: MBEDTLS_SSL_CLI_C
 depends_on:MBEDTLS_SSL_CLI_C
 pass: