Merge pull request #7312 from valeriosetti/issue7254

driver-only ECDH: enable TLS 1.3 key exchanges
diff --git a/ChangeLog.d/driver-only-ecdh.txt b/ChangeLog.d/driver-only-ecdh.txt
new file mode 100644
index 0000000..1aeed64
--- /dev/null
+++ b/ChangeLog.d/driver-only-ecdh.txt
@@ -0,0 +1,7 @@
+Features
+   * When a PSA driver for ECDH is present, it is now possible to disable
+     MBEDTLS_ECDH_C in the build in order to save code size. For TLS 1.2
+     key exchanges based on ECDH(E) to work, this requires
+     MBEDTLS_USE_PSA_CRYPTO. Restartable/interruptible ECDHE operations in
+     TLS 1.2 (ECDHE-ECDSA key exchange) are not supported in those builds yet,
+     as PSA does not have an API for restartable ECDH yet.
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 1293f43..ff4eef7 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -802,14 +802,14 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
-#if !( defined(MBEDTLS_ECDH_C) && defined(MBEDTLS_X509_CRT_PARSE_C) && \
+#if !( defined(MBEDTLS_PK_HAVE_ECDH) && defined(MBEDTLS_X509_CRT_PARSE_C) && \
        ( defined(MBEDTLS_PK_HAVE_ECDSA) || defined(MBEDTLS_PKCS1_V21) ) )
 #error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED defined, but not all prerequisites"
 #endif
 #endif
 
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
-#if !( defined(MBEDTLS_ECDH_C) )
+#if !( defined(MBEDTLS_PK_HAVE_ECDH) )
 #error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED defined, but not all prerequisites"
 #endif
 #endif
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index f029265..3de7a8f 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -193,12 +193,6 @@
 #endif /* PSA_WANT_ALG_ECDSA */
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-/* Symbol for ECDH capabilities, no matter how it is provided */
-#if (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_HAVE_FULL_ECDH)) || \
-    (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C))
-#define MBEDTLS_PK_CAN_ECDH
-#endif
-
 #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) || defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
 #define MBEDTLS_PK_CAN_ECDSA_SOME
 #endif
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index f53e9ec..9dc4021 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -760,16 +760,18 @@
 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
     mbedtls_ecdh_context ecdh_ctx;              /*!<  ECDH key exchange       */
 #endif /* !MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
+#if defined(PSA_WANT_ALG_ECDH) && \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
     psa_key_type_t ecdh_psa_type;
     size_t ecdh_bits;
     mbedtls_svc_key_id_t ecdh_psa_privkey;
     uint8_t ecdh_psa_privkey_is_external;
     unsigned char ecdh_psa_peerkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
     size_t ecdh_psa_peerkey_len;
-#endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
+#endif /* PSA_WANT_ALG_ECDH &&
+          (MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3) */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
@@ -2089,7 +2091,7 @@
 MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl);
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
 MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
     mbedtls_ssl_context *ssl,
@@ -2097,7 +2099,7 @@
     unsigned char *buf,
     unsigned char *end,
     size_t *out_len);
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
 int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl,
@@ -2215,7 +2217,7 @@
 
 static inline int mbedtls_ssl_named_group_is_supported(uint16_t named_group)
 {
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
     if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group)) {
         if (mbedtls_ssl_get_ecp_group_id_from_tls_id(named_group) !=
             MBEDTLS_ECP_DP_NONE) {
@@ -2224,7 +2226,7 @@
     }
 #else
     ((void) named_group);
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
     return 0;
 }
 
@@ -2617,14 +2619,14 @@
     const mbedtls_ssl_ciphersuite_t *suite);
 #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
 
 MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_read_public_ecdhe_share(mbedtls_ssl_context *ssl,
                                               const unsigned char *buf,
                                               size_t buf_len);
 
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
 
 static inline int mbedtls_ssl_tls13_cipher_suite_is_offered(
     mbedtls_ssl_context *ssl, int cipher_suite)
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index a9c7005..ad019b1 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -4219,12 +4219,12 @@
     mbedtls_ssl_buffering_free(ssl);
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-#if defined(MBEDTLS_PK_CAN_ECDH) && \
+#if defined(PSA_WANT_ALG_ECDH) && \
     (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
     if (handshake->ecdh_psa_privkey_is_external == 0) {
         psa_destroy_key(handshake->ecdh_psa_privkey);
     }
-#endif /* MBEDTLS_ECDH_C && MBEDTLS_USE_PSA_CRYPTO */
+#endif /* PSA_WANT_ALG_ECDH && (MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3) */
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     mbedtls_ssl_transform_free(handshake->transform_handshake);
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index a7feced..d10fbeb 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -184,7 +184,7 @@
         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
     if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id)) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
@@ -200,7 +200,7 @@
         ssl->handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
         return 0;
     } else
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
     if (0 /* other KEMs? */) {
         /* Do something */
     }
@@ -219,7 +219,7 @@
     int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
 
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
     const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);
     /* Pick first available ECDHE group compatible with TLS 1.3 */
     if (group_list == NULL) {
@@ -237,7 +237,7 @@
 #else
     ((void) ssl);
     ((void) group_id);
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
 
     /*
      * Add DHE named groups here.
@@ -301,7 +301,7 @@
      * only one key share entry is allowed.
      */
     client_shares = p;
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
     if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id)) {
         /* Pointer to group */
         unsigned char *group = p;
@@ -326,7 +326,7 @@
         /* Write key_exchange_length */
         MBEDTLS_PUT_UINT16_BE(key_exchange_len, group, 2);
     } else
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
     if (0 /* other KEMs? */) {
         /* Do something */
     } else {
@@ -375,7 +375,7 @@
                                              const unsigned char *buf,
                                              const unsigned char *end)
 {
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
     const unsigned char *p = buf;
     int selected_group;
     int found = 0;
@@ -480,7 +480,7 @@
         return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
     }
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
     if (mbedtls_ssl_tls13_named_group_is_ecdhe(group)) {
         if (mbedtls_ssl_get_psa_curve_info_from_tls_id(group, NULL, NULL)
             == PSA_ERROR_NOT_SUPPORTED) {
@@ -496,7 +496,7 @@
             return ret;
         }
     } else
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
     if (0 /* other KEMs? */) {
         /* Do something */
     } else {
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index 669a90a..38077dd 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -1428,7 +1428,7 @@
     return ret;
 }
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
 
 int mbedtls_ssl_tls13_read_public_ecdhe_share(mbedtls_ssl_context *ssl,
                                               const unsigned char *buf,
@@ -1510,7 +1510,7 @@
 
     return 0;
 }
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
 
 /* RFC 8446 section 4.2
  *
diff --git a/library/ssl_tls13_keys.c b/library/ssl_tls13_keys.c
index 6edce50..8ec3570 100644
--- a/library/ssl_tls13_keys.c
+++ b/library/ssl_tls13_keys.c
@@ -1463,7 +1463,7 @@
      */
     if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) {
         if (mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id)) {
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
             /* Compute ECDH shared secret. */
             psa_status_t status = PSA_ERROR_GENERIC_ERROR;
             psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -1499,7 +1499,7 @@
             }
 
             handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
         } else {
             MBEDTLS_SSL_DEBUG_MSG(1, ("Group not supported."));
             return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index bccf9ab..4cfb20b 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -762,7 +762,7 @@
     return 0;
 }
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
 /*
  *
  * From RFC 8446:
@@ -818,11 +818,11 @@
     return 0;
 
 }
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
 
 #define SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH 1
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
 /*
  *  ssl_tls13_parse_key_shares_ext() verifies whether the information in the
  *  extension is correct and stores the first acceptable key share and its associated group.
@@ -923,7 +923,7 @@
     }
     return 0;
 }
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
 
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_client_hello_has_exts(mbedtls_ssl_context *ssl,
@@ -1462,7 +1462,7 @@
                 break;
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
             case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS:
                 MBEDTLS_SSL_DEBUG_MSG(3, ("found supported group extension"));
 
@@ -1481,9 +1481,9 @@
                 }
 
                 break;
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
             case MBEDTLS_TLS_EXT_KEY_SHARE:
                 MBEDTLS_SSL_DEBUG_MSG(3, ("found key share extension"));
 
@@ -1508,7 +1508,7 @@
                 }
 
                 break;
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
 
             case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS:
                 MBEDTLS_SSL_DEBUG_MSG(3, ("found supported versions extension"));
@@ -1826,7 +1826,7 @@
 
     *out_len = 0;
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
     if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group)) {
         ret = mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
             ssl, named_group, buf, end, out_len);
@@ -1837,7 +1837,7 @@
             return ret;
         }
     } else
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH */
     if (0 /* Other kinds of KEMs */) {
     } else {
         ((void) ssl);
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 2801214..0973216 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -2258,14 +2258,6 @@
         scripts/config.py unset MBEDTLS_ECDH_C
     fi
 
-    scripts/config.py unset MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
-    scripts/config.py unset MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-    # Note: the above two lines should be enough, but currently there's a bug
-    # that prevents tests from passing TLS 1.3 with only PSK (no ephemeral)
-    # when TLS 1.2 is also enabled, see #6848.
-    # So, as a temporary measure disable all of TLS 1.3.
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-
     # Restartable feature is not yet supported by PSA. Once it will in
     # the future, the following line could be removed (see issues
     # 6061, 6332 and following ones)