Call psa_crypto_init in the library when required for TLS 1.3

For backward compatibility with Mbed TLS <=3.5.x, applications must be able
to make a TLS connection with a peer that supports both TLS 1.2 and TLS 1.3,
regardless of whether they call psa_crypto_init(). Since Mbed TLS 3.6.0,
we enable TLS 1.3 in the default configuration, so we must take care of
calling psa_crypto_init() if needed. This is a change from TLS 1.3 in
previous versions, where enabling MBEDTLS_SSL_PROTO_TLS1_3 was a user
choice and could have additional requirement.

This commit makes the library call psa_crypto_init() when it needs PSA
crypto in a situation where the application might not have called it,
namely, when starting a TLS 1.3 connection.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 8402fe8..082bc9b 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -1891,6 +1891,26 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_TLS1_3 */
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+
+/** \brief Initialize the PSA crypto subsystem if necessary.
+ *
+ * Call this function before doing any cryptography in a TLS 1.3 handshake.
+ *
+ * This is necessary in Mbed TLS 3.x for backward compatibility.
+ * Up to Mbed TLS 3.5, in the default configuration, you could perform
+ * a TLS connection with default parameters without having called
+ * psa_crypto_init(), since the TLS layer only supported TLS 1.2 and
+ * did not use PSA crypto. (TLS 1.2 only uses PSA crypto if
+ * MBEDTLS_USE_PSA_CRYPTO is enabled, which is not the case in the default
+ * configuration.) Starting with Mbed TLS 3.6.0, TLS 1.3 is enabled
+ * by default, and the TLS 1.3 layer uses PSA crypto. This means that
+ * applications that are not otherwise using PSA crypto and that worked
+ * with Mbed TLS 3.5 started failing in TLS 3.6.0 if they connected to
+ * a peer that supports TLS 1.3. See
+ * https://github.com/Mbed-TLS/mbedtls/issues/9072
+ */
+int mbedtls_ssl_tls13_crypto_init(mbedtls_ssl_context *ssl);
+
 extern const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[
     MBEDTLS_SERVER_HELLO_RANDOM_LEN];
 MBEDTLS_CHECK_RETURN_CRITICAL
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 162e3a3..b63b5e6 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -1141,6 +1141,11 @@
 
     *out_len = 0;
 
+    ret = mbedtls_ssl_tls13_crypto_init(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
     /* Write supported_versions extension
      *
      * Supported Versions Extension is mandatory with TLS 1.3.
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index 8ac6579..631e763 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -39,6 +39,16 @@
 #define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
 #endif
 
+int mbedtls_ssl_tls13_crypto_init(mbedtls_ssl_context *ssl)
+{
+    psa_status_t status = psa_crypto_init();
+    if (status != PSA_SUCCESS) {
+        (void) ssl; // unused when debugging is disabled
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_crypto_init", status);
+    }
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+
 const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[
     MBEDTLS_SERVER_HELLO_RANDOM_LEN] =
 { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 9c949bd..616d2ee 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -1948,6 +1948,11 @@
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse client hello"));
 
+    ret = mbedtls_ssl_tls13_crypto_init(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(
                              ssl, MBEDTLS_SSL_HS_CLIENT_HELLO,
                              &buf, &buflen));