Merge pull request #9731 from gilles-peskine-arm/coverity-20241004-3.6

Backport 3.6: Fix edge cases of mbedtls_psa_raw_to_der and mbedtls_psa_der_to_raw
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fc85ae7..46ca440 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -235,9 +235,15 @@
     # test_suite_pkwrite taking >3h on the CI. Observed with GCC 5.4 on
     # Ubuntu 16.04 x86_64 and GCC 6.5 on Ubuntu 18.04 x86_64.
     # GCC 7.5 and above on Ubuntu 18.04 appear fine.
-    # To avoid the performance problem, we use -O2 here. It doesn't slow
-    # down much even with modern compiler versions.
-    set(CMAKE_C_FLAGS_ASAN        "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O2")
+    # To avoid the performance problem, we use -O2 when GCC version is lower than 7.0.
+    # It doesn't slow down much even with modern compiler versions.
+    if (GCC_VERSION VERSION_LESS 7.0)
+        message(STATUS "USING O2")
+        set(CMAKE_C_FLAGS_ASAN        "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O2")
+    else()
+        message(STATUS "USING O3")
+        set(CMAKE_C_FLAGS_ASAN        "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O3")
+    endif()
     set(CMAKE_C_FLAGS_ASANDBG     "-fsanitize=address -fno-common -fsanitize=undefined -fno-sanitize-recover=all -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
     set(CMAKE_C_FLAGS_TSAN        "-fsanitize=thread -O3")
     set(CMAKE_C_FLAGS_TSANDBG     "-fsanitize=thread -O1 -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls")
@@ -309,7 +315,11 @@
 endif()
 
 if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/framework/CMakeLists.txt")
-    message(FATAL_ERROR "${CMAKE_CURRENT_SOURCE_DIR}/framework/CMakeLists.txt not found. Run `git submodule update --init` from the source tree to fetch the submodule contents.")
+    if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git/")
+        message(FATAL_ERROR "${CMAKE_CURRENT_SOURCE_DIR}CMakeLists.txt not found (and does appear to be a git checkout). Run `git submodule update --init` from the source tree to fetch the submodule contents.")
+    else ()
+        message(FATAL_ERROR "${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt not found (and does not appear to be a git checkout). Please ensure you have downloaded the right archive from the release page on GitHub.")
+    endif()
 endif()
 add_subdirectory(framework)
 
diff --git a/ChangeLog.d/mbedtls_psa_ecp_generate_key-no_public_key.txt b/ChangeLog.d/mbedtls_psa_ecp_generate_key-no_public_key.txt
new file mode 100644
index 0000000..69c00e1
--- /dev/null
+++ b/ChangeLog.d/mbedtls_psa_ecp_generate_key-no_public_key.txt
@@ -0,0 +1,3 @@
+Changes
+   * Improve performance of PSA key generation with ECC keys: it no longer
+     computes the public key (which was immediately discarded). Fixes #9732.
diff --git a/Makefile b/Makefile
index e4d98c9..09c829a 100644
--- a/Makefile
+++ b/Makefile
@@ -6,11 +6,16 @@
     ifeq (,$(wildcard framework/exported.make))
         # Use the define keyword to get a multi-line message.
         # GNU make appends ".  Stop.", so tweak the ending of our message accordingly.
-        define error_message
-$(MBEDTLS_PATH)/framework/exported.make not found.
-Run `git submodule update --init` to fetch the submodule contents.
+        ifeq (,$(wildcard .git))
+            define error_message
+${MBEDTLS_PATH}/framework/exported.make not found (and does appear to be a git checkout). Run `git submodule update --init` from the source tree to fetch the submodule contents.
 This is a fatal error
-        endef
+            endef
+        else
+            define error_message
+${MBEDTLS_PATH}/framework/exported.make not found (and does not appear to be a git checkout). Please ensure you have downloaded the right archive from the release page on GitHub.
+            endef
+        endif
         $(error $(error_message))
     endif
     include framework/exported.make
diff --git a/framework b/framework
index d68446c..5560984 160000
--- a/framework
+++ b/framework
@@ -1 +1 @@
-Subproject commit d68446c9da02e536279a7aaa5a3c9850742ba30c
+Subproject commit 55609845504ce77f3714795785282456444967c8
diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c
index 95baff6..48b90ef 100644
--- a/library/psa_crypto_ecp.c
+++ b/library/psa_crypto_ecp.c
@@ -321,38 +321,36 @@
     const psa_key_attributes_t *attributes,
     uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
 {
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
     psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
         attributes->type);
     mbedtls_ecp_group_id grp_id =
         mbedtls_ecc_group_from_psa(curve, attributes->bits);
-
-    const mbedtls_ecp_curve_info *curve_info =
-        mbedtls_ecp_curve_info_from_grp_id(grp_id);
-    mbedtls_ecp_keypair ecp;
-
-    if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) {
+    if (grp_id == MBEDTLS_ECP_DP_NONE) {
         return PSA_ERROR_NOT_SUPPORTED;
     }
 
+    mbedtls_ecp_keypair ecp;
     mbedtls_ecp_keypair_init(&ecp);
-    ret = mbedtls_ecp_gen_key(grp_id, &ecp,
-                              mbedtls_psa_get_random,
-                              MBEDTLS_PSA_RANDOM_STATE);
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    ret = mbedtls_ecp_group_load(&ecp.grp, grp_id);
     if (ret != 0) {
-        mbedtls_ecp_keypair_free(&ecp);
-        return mbedtls_to_psa_error(ret);
+        goto exit;
     }
 
-    status = mbedtls_to_psa_error(
-        mbedtls_ecp_write_key_ext(&ecp, key_buffer_length,
-                                  key_buffer, key_buffer_size));
+    ret = mbedtls_ecp_gen_privkey(&ecp.grp, &ecp.d,
+                                  mbedtls_psa_get_random,
+                                  MBEDTLS_PSA_RANDOM_STATE);
+    if (ret != 0) {
+        goto exit;
+    }
 
+    ret = mbedtls_ecp_write_key_ext(&ecp, key_buffer_length,
+                                    key_buffer, key_buffer_size);
+
+exit:
     mbedtls_ecp_keypair_free(&ecp);
-
-    return status;
+    return mbedtls_to_psa_error(ret);
 }
 #endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
 
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 929f83d..ec68730 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -109,7 +109,7 @@
 #define DFL_SRTP_MKI            ""
 #define DFL_KEY_OPAQUE_ALG      "none"
 
-#define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: "
+#define GET_REQUEST "GET %s HTTP/1.0\r\nHost: %s\r\nExtra-header: "
 #define GET_REQUEST_END "\r\n\r\n"
 
 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
@@ -727,7 +727,7 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len, tail_len, request_size;
 
-    ret = mbedtls_snprintf((char *) buf, buf_size, GET_REQUEST, opt.request_page);
+    ret = mbedtls_snprintf((char *) buf, buf_size, GET_REQUEST, opt.request_page, opt.server_name);
     if (ret < 0) {
         return ret;
     }
diff --git a/scripts/output_env.sh b/scripts/output_env.sh
index b056ffd..32f1f86 100755
--- a/scripts/output_env.sh
+++ b/scripts/output_env.sh
@@ -78,10 +78,6 @@
 echo
 
 if [ "${RUN_ARMCC:-1}" -ne 0 ]; then
-    : "${ARMC5_CC:=armcc}"
-    print_version "$ARMC5_CC" "--vsn" "" "head -n 2"
-    echo
-
     : "${ARMC6_CC:=armclang}"
     print_version "$ARMC6_CC" "--vsn" "" "head -n 2"
     echo
diff --git a/tests/include/test/drivers/crypto_config_test_driver_extension.h b/tests/include/test/drivers/crypto_config_test_driver_extension.h
index dac07ac..66378e7 100644
--- a/tests/include/test/drivers/crypto_config_test_driver_extension.h
+++ b/tests/include/test/drivers/crypto_config_test_driver_extension.h
@@ -1,9 +1,24 @@
 /**
- * This file is intended to be used to build PSA test driver libraries. It is
- * intended to be appended by the test build system to the crypto_config.h file
- * of the Mbed TLS library the test library will be linked to. It mirrors the
- * PSA_ACCEL_* macros defining the cryptographic operations the test library
- * supports.
+ * This file is intended to be used to build PSA external test driver
+ * libraries (libtestdriver1).
+ *
+ * It is intended to be appended by the test build system to the
+ * crypto_config.h file of the Mbed TLS library the test library will be
+ * linked to (see `tests/Makefile` libtestdriver1 target). This is done in
+ * order to insert it at the right time: after the main configuration
+ * (PSA_WANT) but before the logic that determines what built-ins to enable
+ * based on PSA_WANT and MBEDTLS_PSA_ACCEL macros.
+ *
+ * It reverses the PSA_ACCEL_* macros defining the cryptographic operations
+ * that will be accelerated in the main library:
+ * - When something is accelerated in the main library, we need it supported
+ *   in libtestdriver1, so we disable the accel macro in order to the built-in
+ *   to be enabled.
+ * - When something is NOT accelerated in the main library, we don't need it
+ *   in libtestdriver1, so we enable its accel macro in order to the built-in
+ *   to be disabled, to keep libtestdriver1 minimal. (We can't adjust the
+ *   PSA_WANT macros as they need to be the same between libtestdriver1 and
+ *   the main library, since they determine the ABI between the two.)
  */
 
 #include "psa/crypto_legacy.h"
diff --git a/tests/include/test/psa_crypto_helpers.h b/tests/include/test/psa_crypto_helpers.h
index bf0707d..82f333c 100644
--- a/tests/include/test/psa_crypto_helpers.h
+++ b/tests/include/test/psa_crypto_helpers.h
@@ -11,7 +11,8 @@
 
 #include "test/helpers.h"
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if (MBEDTLS_VERSION_MAJOR < 4 && defined(MBEDTLS_PSA_CRYPTO_C)) || \
+    (MBEDTLS_VERSION_MAJOR >= 4 && defined(MBEDTLS_PSA_CRYPTO_CLIENT))
 #include "test/psa_helpers.h"
 #include <psa/crypto.h>
 #endif
@@ -40,12 +41,16 @@
         mbedtls_psa_crypto_free();                                      \
     }                                                                   \
     while (0)
-#else /*MBEDTLS_PSA_CRYPTO_C */
+#elif MBEDTLS_VERSION_MAJOR >= 4 && defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+#define PSA_INIT() PSA_ASSERT(psa_crypto_init())
+#define PSA_DONE() mbedtls_psa_crypto_free();
+#else  /* MBEDTLS_PSA_CRYPTO_CLIENT && !MBEDTLS_PSA_CRYPTO_C */
 #define PSA_INIT() ((void) 0)
 #define PSA_DONE() ((void) 0)
 #endif /* MBEDTLS_PSA_CRYPTO_C */
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if (MBEDTLS_VERSION_MAJOR < 4 && defined(MBEDTLS_PSA_CRYPTO_C)) || \
+    (MBEDTLS_VERSION_MAJOR >= 4 && defined(MBEDTLS_PSA_CRYPTO_CLIENT))
 
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
 
@@ -253,15 +258,15 @@
 #if defined(MBEDTLS_AES_ALT) || \
     defined(MBEDTLS_AES_SETKEY_ENC_ALT) || \
     defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES)
-#define MBEDTLS_TEST_HAVE_ALT_AES 1
+#define MBEDTLS_TEST_HAVE_ACCEL_AES 1
 #else
-#define MBEDTLS_TEST_HAVE_ALT_AES 0
+#define MBEDTLS_TEST_HAVE_ACCEL_AES 0
 #endif
 
 #define MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192(key_type, key_bits)        \
     do                                                                    \
     {                                                                     \
-        if ((MBEDTLS_TEST_HAVE_ALT_AES) &&                              \
+        if ((MBEDTLS_TEST_HAVE_ACCEL_AES) &&                              \
             ((key_type) == PSA_KEY_TYPE_AES) &&                       \
             (key_bits == 192))                                         \
         {                                                                 \
@@ -293,18 +298,19 @@
  *  \param  alg             The AEAD algorithm.
  *  \param  nonce_length    The nonce length in number of bytes.
  */
+
 #if defined(MBEDTLS_GCM_ALT) || \
     defined(MBEDTLS_PSA_ACCEL_ALG_GCM)
-#define MBEDTLS_TEST_HAVE_ALT_GCM  1
+#define MBEDTLS_TEST_HAVE_ACCEL_GCM  1
 #else
-#define MBEDTLS_TEST_HAVE_ALT_GCM  0
+#define MBEDTLS_TEST_HAVE_ACCEL_GCM  0
 #endif
 
 #define MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE(alg,           \
                                                            nonce_length) \
     do                                                                     \
     {                                                                      \
-        if ((MBEDTLS_TEST_HAVE_ALT_GCM) &&                               \
+        if ((MBEDTLS_TEST_HAVE_ACCEL_GCM) &&                               \
             (PSA_ALG_AEAD_WITH_SHORTENED_TAG((alg), 0) ==            \
              PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0)) &&       \
             ((nonce_length) != 12))                                   \
@@ -315,7 +321,22 @@
     }                                                                      \
     while (0)
 
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT || MBEDTLS_PSA_CRYPTO_C */
+
+#if MBEDTLS_VERSION_MAJOR >= 4
+/* Legacy PSA_INIT() / PSA_DONE() variants from 3.6 */
+#define USE_PSA_INIT()          PSA_INIT()
+#define USE_PSA_DONE()          PSA_DONE()
+#define MD_PSA_INIT()           PSA_INIT()
+#define MD_PSA_DONE()           PSA_DONE()
+#define BLOCK_CIPHER_PSA_INIT() PSA_INIT()
+#define BLOCK_CIPHER_PSA_DONE() PSA_DONE()
+#define MD_OR_USE_PSA_INIT()    PSA_INIT()
+#define MD_OR_USE_PSA_DONE()    PSA_DONE()
+#define AES_PSA_INIT()          PSA_INIT()
+#define AES_PSA_DONE()          PSA_DONE()
+
+#else /* MBEDTLS_VERSION_MAJOR < 4 */
 
 /** \def USE_PSA_INIT
  *
@@ -448,6 +469,8 @@
 #define AES_PSA_DONE() ((void) 0)
 #endif /* MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO */
 
+#endif /* MBEDTLS_VERSION_MAJOR >= 4 */
+
 #if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) &&                        \
     defined(MBEDTLS_CTR_DRBG_C) &&                                      \
     defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
diff --git a/tests/scripts/all-core.sh b/tests/scripts/all-core.sh
index ccd7e59..926ee45 100644
--- a/tests/scripts/all-core.sh
+++ b/tests/scripts/all-core.sh
@@ -51,7 +51,7 @@
 #   * GCC and Clang (recent enough for using ASan with gcc and MemSan with clang, or valgrind)
 #   * G++
 #   * arm-gcc and mingw-gcc
-#   * ArmCC 5 and ArmCC 6, unless invoked with --no-armcc
+#   * ArmCC 6 (aka armclang), unless invoked with --no-armcc
 #   * OpenSSL and GnuTLS command line tools, in suitable versions for the
 #     interoperability tests. The following are the official versions at the
 #     time of writing:
@@ -223,10 +223,11 @@
     : ${GNUTLS_CLI:="gnutls-cli"}
     : ${GNUTLS_SERV:="gnutls-serv"}
     : ${OUT_OF_SOURCE_DIR:=./mbedtls_out_of_source_build}
-    : ${ARMC5_BIN_DIR:=/usr/bin}
     : ${ARMC6_BIN_DIR:=/usr/bin}
     : ${ARM_NONE_EABI_GCC_PREFIX:=arm-none-eabi-}
     : ${ARM_LINUX_GNUEABI_GCC_PREFIX:=arm-linux-gnueabi-}
+    : ${ARM_LINUX_GNUEABIHF_GCC_PREFIX:=arm-linux-gnueabihf-}
+    : ${AARCH64_LINUX_GNU_GCC_PREFIX:=aarch64-linux-gnu-}
     : ${CLANG_LATEST:="clang-latest"}
     : ${CLANG_EARLIEST:="clang-earliest"}
     : ${GCC_LATEST:="gcc-latest"}
@@ -323,6 +324,12 @@
      --arm-linux-gnueabi-gcc-prefix=<string>
                         Prefix for a cross-compiler for arm-linux-gnueabi
                         (default: "${ARM_LINUX_GNUEABI_GCC_PREFIX}")
+     --arm-linux-gnueabihf-gcc-prefix=<string>
+                        Prefix for a cross-compiler for arm-linux-gnueabihf
+                        (default: "${ARM_LINUX_GNUEABIHF_GCC_PREFIX}")
+     --aarch64-linux-gnu-gcc-prefix=<string>
+                        Prefix for a cross-compiler for aarch64-linux-gnu
+                        (default: "${AARCH64_LINUX_GNU_GCC_PREFIX}")
      --armcc            Run ARM Compiler builds (on by default).
      --restore          First clean up the build tree, restoring backed up
                         files. Do not run any components unless they are
@@ -345,7 +352,6 @@
   -s|--seed             Integer seed value to use for this test run.
 
 Tool path options:
-     --armc5-bin-dir=<ARMC5_bin_dir_path>       ARM Compiler 5 bin directory.
      --armc6-bin-dir=<ARMC6_bin_dir_path>       ARM Compiler 6 bin directory.
      --clang-earliest=<Clang_earliest_path>     Earliest version of clang available
      --clang-latest=<Clang_latest_path>         Latest version of clang available
@@ -505,8 +511,9 @@
             --append-outcome) append_outcome=1;;
             --arm-none-eabi-gcc-prefix) shift; ARM_NONE_EABI_GCC_PREFIX="$1";;
             --arm-linux-gnueabi-gcc-prefix) shift; ARM_LINUX_GNUEABI_GCC_PREFIX="$1";;
+            --arm-linux-gnueabihf-gcc-prefix) shift; ARM_LINUX_GNUEABIHF_GCC_PREFIX="$1";;
+            --aarch64-linux-gnu-gcc-prefix) shift; AARCH64_LINUX_GNU_GCC_PREFIX="$1";;
             --armcc) no_armcc=;;
-            --armc5-bin-dir) shift; ARMC5_BIN_DIR="$1";;
             --armc6-bin-dir) shift; ARMC6_BIN_DIR="$1";;
             --clang-earliest) shift; CLANG_EARLIEST="$1";;
             --clang-latest) shift; CLANG_LATEST="$1";;
@@ -795,7 +802,6 @@
     echo "OPENSSL_NEXT: $OPENSSL_NEXT"
     echo "GNUTLS_CLI: $GNUTLS_CLI"
     echo "GNUTLS_SERV: $GNUTLS_SERV"
-    echo "ARMC5_BIN_DIR: $ARMC5_BIN_DIR"
     echo "ARMC6_BIN_DIR: $ARMC6_BIN_DIR"
 }
 
@@ -843,14 +849,10 @@
 
     case " $RUN_COMPONENTS " in
         *_armcc*)
-            ARMC5_CC="$ARMC5_BIN_DIR/armcc"
-            ARMC5_AR="$ARMC5_BIN_DIR/armar"
-            ARMC5_FROMELF="$ARMC5_BIN_DIR/fromelf"
             ARMC6_CC="$ARMC6_BIN_DIR/armclang"
             ARMC6_AR="$ARMC6_BIN_DIR/armar"
             ARMC6_FROMELF="$ARMC6_BIN_DIR/fromelf"
-            check_tools "$ARMC5_CC" "$ARMC5_AR" "$ARMC5_FROMELF" \
-                        "$ARMC6_CC" "$ARMC6_AR" "$ARMC6_FROMELF";;
+            check_tools "$ARMC6_CC" "$ARMC6_AR" "$ARMC6_FROMELF";;
     esac
 
     # past this point, no call to check_tool, only printing output
@@ -861,7 +863,7 @@
     msg "info: output_env.sh"
     case $RUN_COMPONENTS in
         *_armcc*)
-            set "$@" ARMC5_CC="$ARMC5_CC" ARMC6_CC="$ARMC6_CC" RUN_ARMCC=1;;
+            set "$@" ARMC6_CC="$ARMC6_CC" RUN_ARMCC=1;;
         *) set "$@" RUN_ARMCC=0;;
     esac
     "$@" scripts/output_env.sh
diff --git a/tests/scripts/all-helpers.sh b/tests/scripts/all-helpers.sh
index 0e97f39..cdb3f4e 100644
--- a/tests/scripts/all-helpers.sh
+++ b/tests/scripts/all-helpers.sh
@@ -265,3 +265,63 @@
         echo 0  # report version 0 for "no clang"
     fi
 }
+
+gcc_version() {
+    gcc="$1"
+    if command -v "$gcc" > /dev/null ; then
+        "$gcc" --version | sed -En '1s/^[^ ]* \([^)]*\) ([0-9]+).*/\1/p'
+    else
+        echo 0  # report version 0 for "no gcc"
+    fi
+}
+
+can_run_cc_output() {
+    cc="$1"
+    result=false
+    if type "$cc" >/dev/null 2>&1; then
+        testbin=$(mktemp)
+        if echo 'int main(void){return 0;}' | "$cc" -o "$testbin" -x c -; then
+            if "$testbin" 2>/dev/null; then
+                result=true
+            fi
+        fi
+        rm -f "$testbin"
+    fi
+    $result
+}
+
+can_run_arm_linux_gnueabi=
+can_run_arm_linux_gnueabi () {
+    if [ -z "$can_run_arm_linux_gnueabi" ]; then
+        if can_run_cc_output "${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc"; then
+            can_run_arm_linux_gnueabi=true
+        else
+            can_run_arm_linux_gnueabi=false
+        fi
+    fi
+    $can_run_arm_linux_gnueabi
+}
+
+can_run_arm_linux_gnueabihf=
+can_run_arm_linux_gnueabihf () {
+    if [ -z "$can_run_arm_linux_gnueabihf" ]; then
+        if can_run_cc_output "${ARM_LINUX_GNUEABIHF_GCC_PREFIX}gcc"; then
+            can_run_arm_linux_gnueabihf=true
+        else
+            can_run_arm_linux_gnueabihf=false
+        fi
+    fi
+    $can_run_arm_linux_gnueabihf
+}
+
+can_run_aarch64_linux_gnu=
+can_run_aarch64_linux_gnu () {
+    if [ -z "$can_run_aarch64_linux_gnu" ]; then
+        if can_run_cc_output "${AARCH64_LINUX_GNU_GCC_PREFIX}gcc"; then
+            can_run_aarch64_linux_gnu=true
+        else
+            can_run_aarch64_linux_gnu=false
+        fi
+    fi
+    $can_run_aarch64_linux_gnu
+}
diff --git a/tests/scripts/analyze_outcomes.py b/tests/scripts/analyze_outcomes.py
index 1f7e98c..18c8bde 100755
--- a/tests/scripts/analyze_outcomes.py
+++ b/tests/scripts/analyze_outcomes.py
@@ -428,6 +428,8 @@
     IGNORED_SUITES = [
         # Modules replaced by drivers
         'ecdsa', 'ecdh', 'ecjpake',
+        # Unit tests for the built-in implementation
+        'psa_crypto_ecp',
     ]
     IGNORED_TESTS = {
         'test_suite_config': [
@@ -468,6 +470,8 @@
     IGNORED_SUITES = [
         # Modules replaced by drivers
         'ecp', 'ecdsa', 'ecdh', 'ecjpake',
+        # Unit tests for the built-in implementation
+        'psa_crypto_ecp',
     ]
     IGNORED_TESTS = {
         'test_suite_config': [
@@ -508,6 +512,8 @@
         'ecp', 'ecdsa', 'ecdh', 'ecjpake',
         'bignum_core', 'bignum_random', 'bignum_mod', 'bignum_mod_raw',
         'bignum.generated', 'bignum.misc',
+        # Unit tests for the built-in implementation
+        'psa_crypto_ecp',
     ]
     IGNORED_TESTS = {
         'test_suite_config': [
@@ -553,6 +559,8 @@
         'ecp', 'ecdsa', 'ecdh', 'ecjpake', 'dhm',
         'bignum_core', 'bignum_random', 'bignum_mod', 'bignum_mod_raw',
         'bignum.generated', 'bignum.misc',
+        # Unit tests for the built-in implementation
+        'psa_crypto_ecp',
     ]
     IGNORED_TESTS = {
         'ssl-opt': [
@@ -623,6 +631,8 @@
         'ecp', 'ecdsa', 'ecdh', 'ecjpake',
         'bignum_core', 'bignum_random', 'bignum_mod', 'bignum_mod_raw',
         'bignum.generated', 'bignum.misc',
+        # Unit tests for the built-in implementation
+        'psa_crypto_ecp',
     ]
     IGNORED_TESTS = {
         'test_suite_config': [
diff --git a/tests/scripts/components-platform.sh b/tests/scripts/components-platform.sh
index 5f26ba4..a9f108f 100644
--- a/tests/scripts/components-platform.sh
+++ b/tests/scripts/components-platform.sh
@@ -341,6 +341,118 @@
     esac
 }
 
+component_test_arm_linux_gnueabi_gcc_arm5vte () {
+    # Mimic Debian armel port
+    msg "test: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -march=arm5vte, default config" # ~4m
+    make CC="${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc" AR="${ARM_LINUX_GNUEABI_GCC_PREFIX}ar" CFLAGS='-Werror -Wall -Wextra -march=armv5te -O1'
+
+    msg "test: main suites make, default config (out-of-box)" # ~7m 40s
+    make test
+
+    msg "selftest: make, default config (out-of-box)" # ~0s
+    programs/test/selftest
+
+    msg "program demos: make, default config (out-of-box)" # ~0s
+    tests/scripts/run_demos.py
+}
+
+support_test_arm_linux_gnueabi_gcc_arm5vte () {
+    can_run_arm_linux_gnueabi
+}
+
+# The hard float ABI is not implemented for Thumb 1, so use gnueabi
+# Some Thumb 1 asm is sensitive to optimisation level, so test both -O0 and -Os
+component_test_arm_linux_gnueabi_gcc_thumb_1_opt_0 () {
+    msg "test: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -O0, thumb 1, default config" # ~2m 10s
+    make CC="${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc" CFLAGS='-std=c99 -Werror -Wextra -O0 -mcpu=arm1136j-s -mthumb'
+
+    msg "test: main suites make, default config (out-of-box)" # ~36m
+    make test
+
+    msg "selftest: make, default config (out-of-box)" # ~10s
+    programs/test/selftest
+
+    msg "program demos: make, default config (out-of-box)" # ~0s
+    tests/scripts/run_demos.py
+}
+
+support_test_arm_linux_gnueabi_gcc_thumb_1_opt_0 () {
+    can_run_arm_linux_gnueabi
+}
+
+component_test_arm_linux_gnueabi_gcc_thumb_1_opt_s () {
+    msg "test: ${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc -Os, thumb 1, default config" # ~3m 10s
+    make CC="${ARM_LINUX_GNUEABI_GCC_PREFIX}gcc" CFLAGS='-std=c99 -Werror -Wextra -Os -mcpu=arm1136j-s -mthumb'
+
+    msg "test: main suites make, default config (out-of-box)" # ~21m 10s
+    make test
+
+    msg "selftest: make, default config (out-of-box)" # ~2s
+    programs/test/selftest
+
+    msg "program demos: make, default config (out-of-box)" # ~0s
+    tests/scripts/run_demos.py
+}
+
+support_test_arm_linux_gnueabi_gcc_thumb_1_opt_s () {
+    can_run_arm_linux_gnueabi
+}
+
+component_test_arm_linux_gnueabihf_gcc_armv7 () {
+    msg "test: ${ARM_LINUX_GNUEABIHF_GCC_PREFIX}gcc -O2, A32, default config" # ~4m 30s
+    make CC="${ARM_LINUX_GNUEABIHF_GCC_PREFIX}gcc" CFLAGS='-std=c99 -Werror -Wextra -O2 -march=armv7-a -marm'
+
+    msg "test: main suites make, default config (out-of-box)" # ~3m 30s
+    make test
+
+    msg "selftest: make, default config (out-of-box)" # ~0s
+    programs/test/selftest
+
+    msg "program demos: make, default config (out-of-box)" # ~0s
+    tests/scripts/run_demos.py
+}
+
+support_test_arm_linux_gnueabihf_gcc_armv7 () {
+    can_run_arm_linux_gnueabihf
+}
+
+component_test_arm_linux_gnueabihf_gcc_thumb_2 () {
+    msg "test: ${ARM_LINUX_GNUEABIHF_GCC_PREFIX}gcc -Os, thumb 2, default config" # ~4m
+    make CC="${ARM_LINUX_GNUEABIHF_GCC_PREFIX}gcc" CFLAGS='-std=c99 -Werror -Wextra -Os -march=armv7-a -mthumb'
+
+    msg "test: main suites make, default config (out-of-box)" # ~3m 40s
+    make test
+
+    msg "selftest: make, default config (out-of-box)" # ~0s
+    programs/test/selftest
+
+    msg "program demos: make, default config (out-of-box)" # ~0s
+    tests/scripts/run_demos.py
+}
+
+support_test_arm_linux_gnueabihf_gcc_thumb_2 () {
+    can_run_arm_linux_gnueabihf
+}
+
+component_test_aarch64_linux_gnu_gcc () {
+    msg "test: ${AARCH64_LINUX_GNU_GCC_PREFIX}gcc -O2, default config" # ~3m 50s
+    make CC="${AARCH64_LINUX_GNU_GCC_PREFIX}gcc" CFLAGS='-std=c99 -Werror -Wextra -O2'
+
+    msg "test: main suites make, default config (out-of-box)" # ~1m 50s
+    make test
+
+    msg "selftest: make, default config (out-of-box)" # ~0s
+    programs/test/selftest
+
+    msg "program demos: make, default config (out-of-box)" # ~0s
+    tests/scripts/run_demos.py
+}
+
+support_test_aarch64_linux_gnu_gcc () {
+    # Minimum version of GCC for MBEDTLS_AESCE_C is 6.0
+    [ "$(gcc_version "${AARCH64_LINUX_GNU_GCC_PREFIX}gcc")" -ge 6 ] && can_run_aarch64_linux_gnu
+}
+
 component_build_arm_none_eabi_gcc () {
     msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1, baremetal+debug" # ~ 10s
     scripts/config.py baremetal
@@ -431,8 +543,9 @@
 }
 
 component_build_armcc () {
-    msg "build: ARM Compiler 5"
+    # Common configuration for all the builds below
     scripts/config.py baremetal
+
     # armc[56] don't support SHA-512 intrinsics
     scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
 
@@ -449,11 +562,6 @@
 
     scripts/config.py set MBEDTLS_HAVE_ASM
 
-    make CC="$ARMC5_CC" AR="$ARMC5_AR" WARNING_CFLAGS='--strict --c99' lib
-
-    msg "size: ARM Compiler 5"
-    "$ARMC5_FROMELF" -z library/*.o
-
     # Compile mostly with -O1 since some Arm inline assembly is disabled for -O0.
 
     # ARM Compiler 6 - Target ARMv7-A
@@ -486,9 +594,8 @@
 }
 
 support_build_armcc () {
-    armc5_cc="$ARMC5_BIN_DIR/armcc"
     armc6_cc="$ARMC6_BIN_DIR/armclang"
-    (check_tools "$armc5_cc" "$armc6_cc" > /dev/null 2>&1)
+    (check_tools "$armc6_cc" > /dev/null 2>&1)
 }
 
 # For timebeing, no VIA Padlock platform available.
diff --git a/tests/src/bignum_codepath_check.c b/tests/src/bignum_codepath_check.c
index b752d13..9c6bbc7 100644
--- a/tests/src/bignum_codepath_check.c
+++ b/tests/src/bignum_codepath_check.c
@@ -11,14 +11,14 @@
 #if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
 int mbedtls_codepath_check = MBEDTLS_MPI_IS_TEST;
 
-void mbedtls_codepath_take_safe(void)
+static void mbedtls_codepath_take_safe(void)
 {
     if (mbedtls_codepath_check == MBEDTLS_MPI_IS_TEST) {
         mbedtls_codepath_check = MBEDTLS_MPI_IS_SECRET;
     }
 }
 
-void mbedtls_codepath_take_unsafe(void)
+static void mbedtls_codepath_take_unsafe(void)
 {
     mbedtls_codepath_check = MBEDTLS_MPI_IS_PUBLIC;
 }
diff --git a/tests/src/drivers/hash.c b/tests/src/drivers/hash.c
index 76ec12a..54aec93 100644
--- a/tests/src/drivers/hash.c
+++ b/tests/src/drivers/hash.c
@@ -13,7 +13,11 @@
 #include "test/drivers/hash.h"
 
 #if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#if MBEDTLS_VERSION_MAJOR < 4
 #include "libtestdriver1/library/psa_crypto_hash.h"
+#else
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_hash.h"
+#endif
 #endif
 
 mbedtls_test_driver_hash_hooks_t
diff --git a/tests/src/drivers/test_driver_aead.c b/tests/src/drivers/test_driver_aead.c
index 314ce83..6992a06 100644
--- a/tests/src/drivers/test_driver_aead.c
+++ b/tests/src/drivers/test_driver_aead.c
@@ -16,7 +16,11 @@
 #include "mbedtls/constant_time.h"
 
 #if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#if MBEDTLS_VERSION_MAJOR < 4
 #include "libtestdriver1/library/psa_crypto_aead.h"
+#else
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_aead.h"
+#endif
 #endif
 
 mbedtls_test_driver_aead_hooks_t
diff --git a/tests/src/drivers/test_driver_asymmetric_encryption.c b/tests/src/drivers/test_driver_asymmetric_encryption.c
index 4fc8c9d..6fdbe43 100644
--- a/tests/src/drivers/test_driver_asymmetric_encryption.c
+++ b/tests/src/drivers/test_driver_asymmetric_encryption.c
@@ -16,7 +16,11 @@
 #include "test/drivers/key_management.h"
 
 #if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#if MBEDTLS_VERSION_MAJOR < 4
 #include "libtestdriver1/library/psa_crypto_rsa.h"
+#else
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.h"
+#endif
 #endif
 
 #define PSA_RSA_KEY_PAIR_MAX_SIZE \
diff --git a/tests/src/drivers/test_driver_cipher.c b/tests/src/drivers/test_driver_cipher.c
index 2bc751a..90256fc 100644
--- a/tests/src/drivers/test_driver_cipher.c
+++ b/tests/src/drivers/test_driver_cipher.c
@@ -19,7 +19,11 @@
 #include "test/random.h"
 
 #if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#if MBEDTLS_VERSION_MAJOR < 4
 #include "libtestdriver1/library/psa_crypto_cipher.h"
+#else
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_cipher.h"
+#endif
 #endif
 
 #include <string.h>
diff --git a/tests/src/drivers/test_driver_key_agreement.c b/tests/src/drivers/test_driver_key_agreement.c
index 8471959..8a7a9ea 100644
--- a/tests/src/drivers/test_driver_key_agreement.c
+++ b/tests/src/drivers/test_driver_key_agreement.c
@@ -20,9 +20,15 @@
 #include <string.h>
 
 #if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#if MBEDTLS_VERSION_MAJOR < 4
 #include "libtestdriver1/include/psa/crypto.h"
 #include "libtestdriver1/library/psa_crypto_ecp.h"
 #include "libtestdriver1/library/psa_crypto_ffdh.h"
+#else
+#include "libtestdriver1/tf-psa-crypto/include/psa/crypto.h"
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ecp.h"
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ffdh.h"
+#endif
 #endif
 
 mbedtls_test_driver_key_agreement_hooks_t
diff --git a/tests/src/drivers/test_driver_key_management.c b/tests/src/drivers/test_driver_key_management.c
index 2a87899..d2ca157 100644
--- a/tests/src/drivers/test_driver_key_management.c
+++ b/tests/src/drivers/test_driver_key_management.c
@@ -23,9 +23,15 @@
 #include "test/random.h"
 
 #if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#if MBEDTLS_VERSION_MAJOR < 4
 #include "libtestdriver1/library/psa_crypto_ecp.h"
 #include "libtestdriver1/library/psa_crypto_rsa.h"
 #include "libtestdriver1/library/psa_crypto_ffdh.h"
+#else
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ecp.h"
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.h"
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ffdh.h"
+#endif
 #endif
 
 #include <string.h>
diff --git a/tests/src/drivers/test_driver_mac.c b/tests/src/drivers/test_driver_mac.c
index 9f8120b..f1cf504 100644
--- a/tests/src/drivers/test_driver_mac.c
+++ b/tests/src/drivers/test_driver_mac.c
@@ -13,7 +13,11 @@
 #include "test/drivers/mac.h"
 
 #if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#if MBEDTLS_VERSION_MAJOR < 4
 #include "libtestdriver1/library/psa_crypto_mac.h"
+#else
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_mac.h"
+#endif
 #endif
 
 mbedtls_test_driver_mac_hooks_t mbedtls_test_driver_mac_hooks =
diff --git a/tests/src/drivers/test_driver_pake.c b/tests/src/drivers/test_driver_pake.c
index a0b6c1c..c3ce326 100644
--- a/tests/src/drivers/test_driver_pake.c
+++ b/tests/src/drivers/test_driver_pake.c
@@ -1,5 +1,5 @@
 /*
- * Test driver for MAC entry points.
+ * Test driver for PAKE entry points.
  */
 /*  Copyright The Mbed TLS Contributors
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
@@ -14,7 +14,11 @@
 #include "string.h"
 
 #if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#if MBEDTLS_VERSION_MAJOR < 4
 #include "libtestdriver1/library/psa_crypto_pake.h"
+#else
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_pake.h"
+#endif
 #endif
 
 mbedtls_test_driver_pake_hooks_t mbedtls_test_driver_pake_hooks =
diff --git a/tests/src/drivers/test_driver_signature.c b/tests/src/drivers/test_driver_signature.c
index 4fca5d1..a6eef57 100644
--- a/tests/src/drivers/test_driver_signature.c
+++ b/tests/src/drivers/test_driver_signature.c
@@ -26,9 +26,15 @@
 #include "test/random.h"
 
 #if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#if MBEDTLS_VERSION_MAJOR < 4
 #include "libtestdriver1/library/psa_crypto_ecp.h"
 #include "libtestdriver1/library/psa_crypto_hash.h"
 #include "libtestdriver1/library/psa_crypto_rsa.h"
+#else
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_ecp.h"
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_hash.h"
+#include "libtestdriver1/tf-psa-crypto/drivers/builtin/src/psa_crypto_rsa.h"
+#endif
 #endif
 
 #include <string.h>
diff --git a/tests/src/psa_exercise_key.c b/tests/src/psa_exercise_key.c
index 937bd45..032c489 100644
--- a/tests/src/psa_exercise_key.c
+++ b/tests/src/psa_exercise_key.c
@@ -11,7 +11,8 @@
 #include <test/macros.h>
 #include <test/psa_exercise_key.h>
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if (MBEDTLS_VERSION_MAJOR < 4 && defined(MBEDTLS_PSA_CRYPTO_C)) || \
+    (MBEDTLS_VERSION_MAJOR >= 4 && defined(MBEDTLS_PSA_CRYPTO_CLIENT))
 
 #include <mbedtls/asn1.h>
 #include <psa/crypto.h>
@@ -1284,7 +1285,7 @@
             break;
 #endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
 
-#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
         case MBEDTLS_PK_ECKEY:
         case MBEDTLS_PK_ECKEY_DH:
         case MBEDTLS_PK_ECDSA:
@@ -1295,7 +1296,7 @@
                            pk_public_buffer, sizeof(pk_public_buffer)), 0);
             pk_public = pk_public_buffer;
             break;
-#endif /* MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_PK_USE_PSA_EC_DATA */
+#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY && !MBEDTLS_PK_USE_PSA_EC_DATA */
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
         case MBEDTLS_PK_OPAQUE:
@@ -1332,4 +1333,4 @@
 }
 #endif /* MBEDTLS_PK_C */
 
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+#endif /* MBEDTLS_PSA_CRYPTO_C || MBEDTLS_PSA_CRYPTO_CLIENT */
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 3315ba2..2750fa9 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -989,6 +989,14 @@
     fi
 }
 
+# Skip the next test if called by all.sh in a component with MSan
+# (which we also call MemSan) or Valgrind.
+not_with_msan_or_valgrind() {
+    case "_${MBEDTLS_TEST_CONFIGURATION:-}_" in
+        *_msan_*|*_memsan_*|*_valgrind_*) SKIP_NEXT="YES";;
+    esac
+}
+
 # skip the next test if valgrind is in use
 not_with_valgrind() {
     if [ "$MEMCHECK" -gt 0 ]; then
@@ -14339,6 +14347,14 @@
 requires_gnutls_tls1_3
 requires_gnutls_next_no_ticket
 requires_gnutls_next_disable_tls13_compat
+# Tests using FFDH with a large prime take a long time to run with a memory
+# sanitizer. GnuTLS <=3.8.1 has a hard-coded timeout and gives up after
+# 30s (since 3.8.1, it can be configured with --timeout). We've observed
+# 8192-bit FFDH test cases failing intermittently on heavily loaded CI
+# executors (https://github.com/Mbed-TLS/mbedtls/issues/9742),
+# when using MSan. As a workaround, skip them.
+# Also skip 6144-bit FFDH to have a bit of safety margin.
+not_with_msan_or_valgrind
 run_test "TLS 1.3 G->m: AES_128_GCM_SHA256,ffdhe6144,rsa_pss_rsae_sha256" \
          "$P_SRV crt_file=$DATA_FILES_PATH/server2-sha256.crt key_file=$DATA_FILES_PATH/server2.key debug_level=4 force_ciphersuite=TLS1-3-AES-128-GCM-SHA256 sig_algs=rsa_pss_rsae_sha256 groups=ffdhe6144 tls13_kex_modes=ephemeral cookies=0 tickets=0" \
          "$G_NEXT_CLI_NO_CERT --debug=4 --single-key-share --x509cafile $DATA_FILES_PATH/test-ca_cat12.crt --priority=NONE:+AES-128-GCM:+SHA256:+AEAD:+SIGN-RSA-PSS-RSAE-SHA256:+GROUP-FFDHE6144:+VERS-TLS1.3:%NO_TICKETS" \
@@ -14359,6 +14375,7 @@
 requires_config_enabled MBEDTLS_X509_RSASSA_PSS_SUPPORT
 requires_config_enabled PSA_WANT_ALG_FFDH
 requires_config_enabled PSA_WANT_DH_RFC7919_6144
+not_with_msan_or_valgrind
 run_test "TLS 1.3 m->G: AES_128_GCM_SHA256,ffdhe6144,rsa_pss_rsae_sha256" \
          "$G_NEXT_SRV_NO_CERT --http --disable-client-cert --debug=4 --x509certfile $DATA_FILES_PATH/server2-sha256.crt --x509keyfile $DATA_FILES_PATH/server2.key --priority=NONE:+AES-128-GCM:+SHA256:+AEAD:+SIGN-RSA-PSS-RSAE-SHA256:+GROUP-FFDHE6144:+VERS-TLS1.3:%NO_TICKETS" \
          "$P_CLI ca_file=$DATA_FILES_PATH/test-ca_cat12.crt debug_level=4 force_ciphersuite=TLS1-3-AES-128-GCM-SHA256 sig_algs=rsa_pss_rsae_sha256 groups=ffdhe6144" \
@@ -14380,6 +14397,7 @@
 requires_gnutls_tls1_3
 requires_gnutls_next_no_ticket
 requires_gnutls_next_disable_tls13_compat
+not_with_msan_or_valgrind
 client_needs_more_time 4
 run_test "TLS 1.3 G->m: AES_128_GCM_SHA256,ffdhe8192,rsa_pss_rsae_sha256" \
          "$P_SRV crt_file=$DATA_FILES_PATH/server2-sha256.crt key_file=$DATA_FILES_PATH/server2.key debug_level=4 force_ciphersuite=TLS1-3-AES-128-GCM-SHA256 sig_algs=rsa_pss_rsae_sha256 groups=ffdhe8192 tls13_kex_modes=ephemeral cookies=0 tickets=0" \
@@ -14401,6 +14419,7 @@
 requires_config_enabled MBEDTLS_X509_RSASSA_PSS_SUPPORT
 requires_config_enabled PSA_WANT_ALG_FFDH
 requires_config_enabled PSA_WANT_DH_RFC7919_8192
+not_with_msan_or_valgrind
 client_needs_more_time 4
 run_test "TLS 1.3 m->G: AES_128_GCM_SHA256,ffdhe8192,rsa_pss_rsae_sha256" \
          "$G_NEXT_SRV_NO_CERT --http --disable-client-cert --debug=4 --x509certfile $DATA_FILES_PATH/server2-sha256.crt --x509keyfile $DATA_FILES_PATH/server2.key --priority=NONE:+AES-128-GCM:+SHA256:+AEAD:+SIGN-RSA-PSS-RSAE-SHA256:+GROUP-FFDHE8192:+VERS-TLS1.3:%NO_TICKETS" \
diff --git a/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function
index 9fa55a7..78a63ea 100644
--- a/tests/suites/test_suite_ctr_drbg.function
+++ b/tests/suites/test_suite_ctr_drbg.function
@@ -363,14 +363,14 @@
      * as this was the value used when the expected answers were calculated. */
     const size_t entropy_len = 48;
 
+    mbedtls_ctr_drbg_context ctx;
+    mbedtls_ctr_drbg_init(&ctx);
+
     AES_PSA_INIT();
 
     TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count);
     memset(out, 0, sizeof(out));
 
-    mbedtls_ctr_drbg_context ctx;
-    mbedtls_ctr_drbg_init(&ctx);
-
     test_offset_idx = 0;
 
     /* Need to set a non-default fixed entropy len, to ensure same output across
diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function
index f16a6d4..d9ff802 100644
--- a/tests/suites/test_suite_ecdsa.function
+++ b/tests/suites/test_suite_ecdsa.function
@@ -196,13 +196,12 @@
 {
     mbedtls_ecp_group grp;
     mbedtls_mpi d, r, s, r_check, s_check;
-
-    MD_PSA_INIT();
-
     mbedtls_ecp_group_init(&grp);
     mbedtls_mpi_init(&d); mbedtls_mpi_init(&r); mbedtls_mpi_init(&s);
     mbedtls_mpi_init(&r_check); mbedtls_mpi_init(&s_check);
 
+    MD_PSA_INIT();
+
     TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0);
     TEST_ASSERT(mbedtls_test_read_mpi(&d, d_str) == 0);
     TEST_ASSERT(mbedtls_test_read_mpi(&r_check, r_str) == 0);
@@ -235,13 +234,13 @@
     unsigned char sig[200];
     size_t sig_len, i;
 
-    MD_PSA_INIT();
-
     mbedtls_ecdsa_init(&ctx);
     memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
     memset(hash, 0, sizeof(hash));
     memset(sig, 0x2a, sizeof(sig));
 
+    MD_PSA_INIT();
+
     /* generate signing key */
     TEST_ASSERT(mbedtls_ecdsa_genkey(&ctx, id,
                                      &mbedtls_test_rnd_pseudo_rand,
@@ -300,13 +299,13 @@
     unsigned char sig[200];
     size_t sig_len, i;
 
-    MD_PSA_INIT();
-
     mbedtls_ecdsa_init(&ctx);
     memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info));
     memset(hash, 0, sizeof(hash));
     memset(sig, 0x2a, sizeof(sig));
 
+    MD_PSA_INIT();
+
     /* prepare material for signature */
     TEST_ASSERT(mbedtls_test_rnd_pseudo_rand(&rnd_info,
                                              hash, sizeof(hash)) == 0);
@@ -436,12 +435,12 @@
     unsigned char sig[MBEDTLS_ECDSA_MAX_LEN];
     size_t slen;
 
-    MD_PSA_INIT();
-
     mbedtls_ecdsa_restart_init(&rs_ctx);
     mbedtls_ecdsa_init(&ctx);
     memset(sig, 0, sizeof(sig));
 
+    MD_PSA_INIT();
+
     TEST_ASSERT(mbedtls_ecp_group_load(&ctx.grp, id) == 0);
     TEST_ASSERT(mbedtls_test_read_mpi(&ctx.d, d_str) == 0);
 
diff --git a/tests/suites/test_suite_ecjpake.function b/tests/suites/test_suite_ecjpake.function
index 177e09a..7f73195 100644
--- a/tests/suites/test_suite_ecjpake.function
+++ b/tests/suites/test_suite_ecjpake.function
@@ -102,6 +102,7 @@
 void ecjpake_invalid_param()
 {
     mbedtls_ecjpake_context ctx;
+    mbedtls_ecjpake_init(&ctx);
     unsigned char buf[42] = { 0 };
     size_t const len = sizeof(buf);
     mbedtls_ecjpake_role invalid_role = (mbedtls_ecjpake_role) 42;
@@ -110,8 +111,6 @@
 
     MD_PSA_INIT();
 
-    mbedtls_ecjpake_init(&ctx);
-
     TEST_EQUAL(MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
                mbedtls_ecjpake_setup(&ctx,
                                      invalid_role,
@@ -139,13 +138,13 @@
 void read_bad_md(data_t *msg)
 {
     mbedtls_ecjpake_context corrupt_ctx;
+    mbedtls_ecjpake_init(&corrupt_ctx);
     const unsigned char *pw = NULL;
     const size_t pw_len = 0;
     int any_role = MBEDTLS_ECJPAKE_CLIENT;
 
     MD_PSA_INIT();
 
-    mbedtls_ecjpake_init(&corrupt_ctx);
     TEST_ASSERT(mbedtls_ecjpake_setup(&corrupt_ctx, any_role,
                                       MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, pw,
                                       pw_len) == 0);
@@ -164,13 +163,12 @@
 void read_round_one(int role, data_t *msg, int ref_ret)
 {
     mbedtls_ecjpake_context ctx;
+    mbedtls_ecjpake_init(&ctx);
     const unsigned char *pw = NULL;
     const size_t pw_len = 0;
 
     MD_PSA_INIT();
 
-    mbedtls_ecjpake_init(&ctx);
-
     TEST_ASSERT(mbedtls_ecjpake_setup(&ctx, role,
                                       MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, pw,
                                       pw_len) == 0);
@@ -187,13 +185,12 @@
 void read_round_two_cli(data_t *msg, int ref_ret)
 {
     mbedtls_ecjpake_context ctx;
+    mbedtls_ecjpake_init(&ctx);
     const unsigned char *pw = NULL;
     const size_t pw_len = 0;
 
     MD_PSA_INIT();
 
-    mbedtls_ecjpake_init(&ctx);
-
     TEST_ASSERT(mbedtls_ecjpake_setup(&ctx, MBEDTLS_ECJPAKE_CLIENT,
                                       MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, pw,
                                       pw_len) == 0);
@@ -216,13 +213,12 @@
 void read_round_two_srv(data_t *msg, int ref_ret)
 {
     mbedtls_ecjpake_context ctx;
+    mbedtls_ecjpake_init(&ctx);
     const unsigned char *pw = NULL;
     const size_t pw_len = 0;
 
     MD_PSA_INIT();
 
-    mbedtls_ecjpake_init(&ctx);
-
     TEST_ASSERT(mbedtls_ecjpake_setup(&ctx, MBEDTLS_ECJPAKE_SERVER,
                                       MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, pw,
                                       pw_len) == 0);
diff --git a/tests/suites/test_suite_hmac_drbg.function b/tests/suites/test_suite_hmac_drbg.function
index 0a50c6c..fbe1b03 100644
--- a/tests/suites/test_suite_hmac_drbg.function
+++ b/tests/suites/test_suite_hmac_drbg.function
@@ -41,8 +41,6 @@
     size_t default_entropy_len;
     size_t expected_consumed_entropy = 0;
 
-    MD_PSA_INIT();
-
     mbedtls_hmac_drbg_init(&ctx);
     memset(buf, 0, sizeof(buf));
     memset(out, 0, sizeof(out));
@@ -50,6 +48,8 @@
     entropy.len = sizeof(buf);
     entropy.p = buf;
 
+    MD_PSA_INIT();
+
     md_info = mbedtls_md_info_from_type(md_alg);
     TEST_ASSERT(md_info != NULL);
     if (mbedtls_md_get_size(md_info) <= 20) {
@@ -129,11 +129,10 @@
 {
     const mbedtls_md_info_t *md_info;
     mbedtls_hmac_drbg_context ctx;
+    mbedtls_hmac_drbg_init(&ctx);
 
     MD_PSA_INIT();
 
-    mbedtls_hmac_drbg_init(&ctx);
-
     md_info = mbedtls_md_info_from_type(md_alg);
     TEST_ASSERT(md_info != NULL);
 
@@ -159,12 +158,12 @@
     mbedtls_hmac_drbg_context ctx;
     size_t i;
 
-    MD_PSA_INIT();
-
     mbedtls_hmac_drbg_init(&ctx);
     memset(buf, 0, sizeof(buf));
     memset(out, 0, sizeof(out));
 
+    MD_PSA_INIT();
+
     md_info = mbedtls_md_info_from_type(md_alg);
     TEST_ASSERT(md_info != NULL);
     TEST_ASSERT(mbedtls_hmac_drbg_seed_buf(&ctx, md_info, buf, sizeof(buf)) == 0);
@@ -194,13 +193,13 @@
     const mbedtls_md_info_t *md_info;
     mbedtls_hmac_drbg_context ctx;
 
-    MD_PSA_INIT();
-
     mbedtls_hmac_drbg_init(&ctx);
 
     p_entropy.p = entropy->x;
     p_entropy.len = entropy->len;
 
+    MD_PSA_INIT();
+
     md_info = mbedtls_md_info_from_type(md_alg);
     TEST_ASSERT(md_info != NULL);
 
@@ -244,13 +243,13 @@
     const mbedtls_md_info_t *md_info;
     mbedtls_hmac_drbg_context ctx;
 
-    MD_PSA_INIT();
-
     mbedtls_hmac_drbg_init(&ctx);
 
     p_entropy.p = entropy->x;
     p_entropy.len = entropy->len;
 
+    MD_PSA_INIT();
+
     md_info = mbedtls_md_info_from_type(md_alg);
     TEST_ASSERT(md_info != NULL);
 
@@ -279,13 +278,13 @@
     const mbedtls_md_info_t *md_info;
     mbedtls_hmac_drbg_context ctx;
 
-    MD_PSA_INIT();
-
     mbedtls_hmac_drbg_init(&ctx);
 
     p_entropy.p = entropy->x;
     p_entropy.len = entropy->len;
 
+    MD_PSA_INIT();
+
     md_info = mbedtls_md_info_from_type(md_alg);
     TEST_ASSERT(md_info != NULL);
 
diff --git a/tests/suites/test_suite_md.function b/tests/suites/test_suite_md.function
index 2a885e2..4e62154 100644
--- a/tests/suites/test_suite_md.function
+++ b/tests/suites/test_suite_md.function
@@ -21,10 +21,10 @@
     const int *md_type_ptr;
     const mbedtls_md_info_t *info;
     mbedtls_md_context_t ctx;
+    mbedtls_md_init(&ctx);
     unsigned char out[MBEDTLS_MD_MAX_SIZE] = { 0 };
 
     MD_PSA_INIT();
-    mbedtls_md_init(&ctx);
 
     /*
      * Test that mbedtls_md_list() only returns valid MDs.
@@ -87,13 +87,13 @@
 void md_null_args()
 {
     mbedtls_md_context_t ctx;
+    mbedtls_md_init(&ctx);
 #if defined(MBEDTLS_MD_C)
     const mbedtls_md_info_t *info = mbedtls_md_info_from_type(*(mbedtls_md_list()));
 #endif
     unsigned char buf[1] = { 0 };
 
     MD_PSA_INIT();
-    mbedtls_md_init(&ctx);
 
     TEST_EQUAL(0, mbedtls_md_get_size(NULL));
 #if defined(MBEDTLS_MD_C)
@@ -245,12 +245,11 @@
 
     const mbedtls_md_info_t *md_info = NULL;
     mbedtls_md_context_t ctx, ctx_copy;
-
-    MD_PSA_INIT();
-
     mbedtls_md_init(&ctx);
     mbedtls_md_init(&ctx_copy);
 
+    MD_PSA_INIT();
+
     halfway = src_len / 2;
 
     md_info = mbedtls_md_info_from_type(md_type);
@@ -291,13 +290,12 @@
     unsigned char output[MBEDTLS_MD_MAX_SIZE] = { 0 };
     const mbedtls_md_info_t *md_info = NULL;
     mbedtls_md_context_t ctx, ctx_copy;
+    mbedtls_md_init(&ctx);
+    mbedtls_md_init(&ctx_copy);
     int halfway;
 
     MD_PSA_INIT();
 
-    mbedtls_md_init(&ctx);
-    mbedtls_md_init(&ctx_copy);
-
     md_info = mbedtls_md_info_from_type(md_type);
     TEST_ASSERT(md_info != NULL);
     TEST_EQUAL(0, mbedtls_md_setup(&ctx, md_info, 0));
@@ -363,12 +361,11 @@
     unsigned char output[MBEDTLS_MD_MAX_SIZE] = { 0 };
     const mbedtls_md_info_t *md_info = NULL;
     mbedtls_md_context_t ctx;
+    mbedtls_md_init(&ctx);
     int halfway;
 
     MD_PSA_INIT();
 
-    mbedtls_md_init(&ctx);
-
     md_info = mbedtls_md_info_from_type(md_type);
     TEST_ASSERT(md_info != NULL);
     TEST_EQUAL(0, mbedtls_md_setup(&ctx, md_info, 1));
diff --git a/tests/suites/test_suite_pem.function b/tests/suites/test_suite_pem.function
index 413dc55..091cbd1 100644
--- a/tests/suites/test_suite_pem.function
+++ b/tests/suites/test_suite_pem.function
@@ -66,6 +66,7 @@
                              char *pwd, int res, data_t *out)
 {
     mbedtls_pem_context ctx;
+    mbedtls_pem_init(&ctx);
     int ret;
     size_t use_len = 0;
     size_t pwd_len = strlen(pwd);
@@ -73,8 +74,6 @@
 
     MD_PSA_INIT();
 
-    mbedtls_pem_init(&ctx);
-
     ret = mbedtls_pem_read_buffer(&ctx, header, footer, (unsigned char *) data,
                                   (unsigned char *) pwd, pwd_len, &use_len);
     TEST_ASSERT(ret == res);
diff --git a/tests/suites/test_suite_pkcs1_v21.function b/tests/suites/test_suite_pkcs1_v21.function
index 6261979..a15d5d7 100644
--- a/tests/suites/test_suite_pkcs1_v21.function
+++ b/tests/suites/test_suite_pkcs1_v21.function
@@ -14,18 +14,18 @@
 {
     unsigned char output[256];
     mbedtls_rsa_context ctx;
+    mbedtls_rsa_init(&ctx);
     mbedtls_test_rnd_buf_info info;
     mbedtls_mpi N, E;
-
-    MD_PSA_INIT();
+    mbedtls_mpi_init(&N); mbedtls_mpi_init(&E);
 
     info.fallback_f_rng = mbedtls_test_rnd_std_rand;
     info.fallback_p_rng = NULL;
     info.buf = rnd_buf->x;
     info.length = rnd_buf->len;
 
-    mbedtls_mpi_init(&N); mbedtls_mpi_init(&E);
-    mbedtls_rsa_init(&ctx);
+    MD_PSA_INIT();
+
     TEST_ASSERT(mbedtls_rsa_set_padding(&ctx,
                                         MBEDTLS_RSA_PKCS_V21, hash) == 0);
     memset(output, 0x00, sizeof(output));
@@ -66,17 +66,16 @@
 {
     unsigned char output[64];
     mbedtls_rsa_context ctx;
+    mbedtls_rsa_init(&ctx);
     size_t output_len;
     mbedtls_test_rnd_pseudo_info rnd_info;
     mbedtls_mpi N, P, Q, E;
+    mbedtls_mpi_init(&N); mbedtls_mpi_init(&P);
+    mbedtls_mpi_init(&Q); mbedtls_mpi_init(&E);
     ((void) seed);
 
     MD_PSA_INIT();
 
-    mbedtls_mpi_init(&N); mbedtls_mpi_init(&P);
-    mbedtls_mpi_init(&Q); mbedtls_mpi_init(&E);
-
-    mbedtls_rsa_init(&ctx);
     TEST_ASSERT(mbedtls_rsa_set_padding(&ctx,
                                         MBEDTLS_RSA_PKCS_V21, hash) == 0);
 
@@ -131,19 +130,19 @@
 {
     unsigned char output[512];
     mbedtls_rsa_context ctx;
+    mbedtls_rsa_init(&ctx);
     mbedtls_test_rnd_buf_info info;
     mbedtls_mpi N, P, Q, E;
-
-    MD_PSA_INIT();
+    mbedtls_mpi_init(&N); mbedtls_mpi_init(&P);
+    mbedtls_mpi_init(&Q); mbedtls_mpi_init(&E);
 
     info.fallback_f_rng = mbedtls_test_rnd_std_rand;
     info.fallback_p_rng = NULL;
     info.buf = rnd_buf->x;
     info.length = rnd_buf->len;
 
-    mbedtls_mpi_init(&N); mbedtls_mpi_init(&P);
-    mbedtls_mpi_init(&Q); mbedtls_mpi_init(&E);
-    mbedtls_rsa_init(&ctx);
+    MD_PSA_INIT();
+
     TEST_ASSERT(mbedtls_rsa_set_padding(&ctx,
                                         MBEDTLS_RSA_PKCS_V21, hash) == 0);
 
@@ -196,13 +195,13 @@
                              char *salt, data_t *result_str, int result)
 {
     mbedtls_rsa_context ctx;
+    mbedtls_rsa_init(&ctx);
     mbedtls_mpi N, E;
+    mbedtls_mpi_init(&N); mbedtls_mpi_init(&E);
     ((void) salt);
 
     MD_PSA_INIT();
 
-    mbedtls_mpi_init(&N); mbedtls_mpi_init(&E);
-    mbedtls_rsa_init(&ctx);
     TEST_ASSERT(mbedtls_rsa_set_padding(&ctx,
                                         MBEDTLS_RSA_PKCS_V21, hash) == 0);
 
@@ -236,12 +235,12 @@
                                  int result_full)
 {
     mbedtls_rsa_context ctx;
+    mbedtls_rsa_init(&ctx);
     mbedtls_mpi N, E;
+    mbedtls_mpi_init(&N); mbedtls_mpi_init(&E);
 
     MD_PSA_INIT();
 
-    mbedtls_mpi_init(&N); mbedtls_mpi_init(&E);
-    mbedtls_rsa_init(&ctx);
     TEST_ASSERT(mbedtls_rsa_set_padding(&ctx,
                                         MBEDTLS_RSA_PKCS_V21, ctx_hash) == 0);
 
diff --git a/tests/suites/test_suite_pkparse.function b/tests/suites/test_suite_pkparse.function
index 63ff092..942dae3 100644
--- a/tests/suites/test_suite_pkparse.function
+++ b/tests/suites/test_suite_pkparse.function
@@ -114,10 +114,10 @@
 void pk_parse_keyfile_rsa(char *key_file, char *password, int result)
 {
     mbedtls_pk_context ctx;
+    mbedtls_pk_init(&ctx);
     int res;
     char *pwd = password;
 
-    mbedtls_pk_init(&ctx);
     MD_PSA_INIT();
 
     if (strcmp(pwd, "NULL") == 0) {
@@ -161,9 +161,9 @@
 void pk_parse_public_keyfile_rsa(char *key_file, int result)
 {
     mbedtls_pk_context ctx;
+    mbedtls_pk_init(&ctx);
     int res;
 
-    mbedtls_pk_init(&ctx);
     MD_PSA_INIT();
 
     res = mbedtls_pk_parse_public_keyfile(&ctx, key_file);
diff --git a/tests/suites/test_suite_pkwrite.data b/tests/suites/test_suite_pkwrite.data
index d333ddd..62c3e8d 100644
--- a/tests/suites/test_suite_pkwrite.data
+++ b/tests/suites/test_suite_pkwrite.data
@@ -30,16 +30,13 @@
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_ECP_HAVE_SECP521R1
 pk_write_pubkey_check:"../framework/data_files/ec_521_pub.der":TEST_DER
 
-## The pk_write_pubkey_check sometimes take ~3 hours to run with
-## GCC+Asan on the CI in the full config. Comment out the slowest
-## ones while we investigate and release 3.6.2.
-# Public key write check EC Brainpool 512 bits
-# depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_PEM_PARSE_C:MBEDTLS_PEM_WRITE_C:MBEDTLS_ECP_HAVE_BP512R1
-# pk_write_pubkey_check:"../framework/data_files/ec_bp512_pub.pem":TEST_PEM
+Public key write check EC Brainpool 512 bits
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_PEM_PARSE_C:MBEDTLS_PEM_WRITE_C:MBEDTLS_ECP_HAVE_BP512R1
+pk_write_pubkey_check:"../framework/data_files/ec_bp512_pub.pem":TEST_PEM
 
-# Public key write check EC Brainpool 512 bits (DER)
-# depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_ECP_HAVE_BP512R1
-# pk_write_pubkey_check:"../framework/data_files/ec_bp512_pub.der":TEST_DER
+Public key write check EC Brainpool 512 bits (DER)
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_ECP_HAVE_BP512R1
+pk_write_pubkey_check:"../framework/data_files/ec_bp512_pub.der":TEST_DER
 
 Public key write check EC X25519
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_PEM_PARSE_C:MBEDTLS_PEM_WRITE_C:MBEDTLS_ECP_HAVE_CURVE25519
diff --git a/tests/suites/test_suite_psa_crypto_ecp.data b/tests/suites/test_suite_psa_crypto_ecp.data
new file mode 100644
index 0000000..ffb7a7b
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_ecp.data
@@ -0,0 +1,82 @@
+ECC generate: unknown family (0)
+generate_key:0:256:64:PSA_ERROR_NOT_SUPPORTED
+
+ECC generate: unknown family (0xff)
+generate_key:0xff:256:64:PSA_ERROR_NOT_SUPPORTED
+
+ECC generate: SECP_R1 bad bit-size (0)
+generate_key:PSA_ECC_FAMILY_SECP_R1:0:64:PSA_ERROR_NOT_SUPPORTED
+
+ECC generate: SECP_R1 bad bit-size (512)
+generate_key:PSA_ECC_FAMILY_SECP_R1:512:64:PSA_ERROR_NOT_SUPPORTED
+
+ECC generate: SECP_R1 bad bit-size (528)
+generate_key:PSA_ECC_FAMILY_SECP_R1:528:64:PSA_ERROR_NOT_SUPPORTED
+
+ECC generate: SECP_R1 256-bit not supported
+depends_on:!MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256
+generate_key:PSA_ECC_FAMILY_SECP_R1:256:32:PSA_ERROR_NOT_SUPPORTED
+
+ECC generate: SECP_R1 384-bit not supported
+depends_on:!MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384
+generate_key:PSA_ECC_FAMILY_SECP_R1:384:48:PSA_ERROR_NOT_SUPPORTED
+
+ECC generate: SECP_R1 521-bit not supported
+depends_on:!MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521
+generate_key:PSA_ECC_FAMILY_SECP_R1:521:66:PSA_ERROR_NOT_SUPPORTED
+
+ECC generate: SECP_K1 256-bit not supported
+depends_on:!MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256
+generate_key:PSA_ECC_FAMILY_SECP_K1:256:32:PSA_ERROR_NOT_SUPPORTED
+
+ECC generate: Curve25519 not supported
+depends_on:!MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255
+generate_key:PSA_ECC_FAMILY_MONTGOMERY:255:32:PSA_ERROR_NOT_SUPPORTED
+
+ECC generate: Curve448 not supported
+depends_on:!MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448
+generate_key:PSA_ECC_FAMILY_MONTGOMERY:448:56:PSA_ERROR_NOT_SUPPORTED
+
+ECC generate: SECP_R1 256-bit, size=31, too small
+depends_on:MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256
+generate_key:PSA_ECC_FAMILY_SECP_R1:256:31:PSA_ERROR_BUFFER_TOO_SMALL
+
+ECC generate: SECP_R1 256-bit, size=32, ok
+depends_on:MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256
+generate_key:PSA_ECC_FAMILY_SECP_R1:256:32:PSA_SUCCESS
+
+ECC generate: SECP_R1 256-bit, size=33, ok
+depends_on:MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256
+generate_key:PSA_ECC_FAMILY_SECP_R1:256:33:PSA_SUCCESS
+
+ECC generate: SECP_R1 521-bit, size=65, too small
+depends_on:MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521
+generate_key:PSA_ECC_FAMILY_SECP_R1:521:65:PSA_ERROR_BUFFER_TOO_SMALL
+
+ECC generate: SECP_R1 521-bit, size=66, ok
+depends_on:MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521
+generate_key:PSA_ECC_FAMILY_SECP_R1:521:66:PSA_SUCCESS
+
+ECC generate: Curve25519, size=31, too small
+depends_on:MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255
+generate_key:PSA_ECC_FAMILY_MONTGOMERY:255:31:PSA_ERROR_BUFFER_TOO_SMALL
+
+ECC generate: Curve25519, size=32, ok
+depends_on:MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255
+generate_key:PSA_ECC_FAMILY_MONTGOMERY:255:32:PSA_SUCCESS
+
+ECC generate: Curve25519, size=33, ok
+depends_on:MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255
+generate_key:PSA_ECC_FAMILY_MONTGOMERY:255:33:PSA_SUCCESS
+
+ECC generate: Curve448, size=55, too small
+depends_on:MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448
+generate_key:PSA_ECC_FAMILY_MONTGOMERY:448:55:PSA_ERROR_BUFFER_TOO_SMALL
+
+ECC generate: Curve448, size=56, ok
+depends_on:MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448
+generate_key:PSA_ECC_FAMILY_MONTGOMERY:448:56:PSA_SUCCESS
+
+ECC generate: Curve448, size=57, ok
+depends_on:MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448
+generate_key:PSA_ECC_FAMILY_MONTGOMERY:448:57:PSA_SUCCESS
diff --git a/tests/suites/test_suite_psa_crypto_ecp.function b/tests/suites/test_suite_psa_crypto_ecp.function
new file mode 100644
index 0000000..5be7a2c
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_ecp.function
@@ -0,0 +1,165 @@
+/* BEGIN_HEADER */
+/* Unit tests for internal functions for built-in ECC mechanisms. */
+#include <psa/crypto.h>
+
+#include "psa_crypto_ecp.h"
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
+/*
+ * Check if a buffer is all-0 bytes:
+ * return   1 if it is,
+ *          0 if it isn't.
+ *
+ * TODO: we use this in multiple test suites. Move it to tests/src.
+ */
+static int buffer_is_all_zero(const uint8_t *buf, size_t size)
+{
+    for (size_t i = 0; i < size; i++) {
+        if (buf[i] != 0) {
+            return 0;
+        }
+    }
+    return 1;
+}
+
+typedef struct {
+    unsigned bit_bot;           /* lowest non-forced bit */
+    unsigned bit_top;           /* highest non-forced bit */
+} ecc_private_key_stats_t;
+
+/* Do some sanity checks on an ECC private key. This is not intended to be
+ * a full validity check, just to catch some potential mistakes. */
+static int check_ecc_private_key(psa_ecc_family_t family, size_t bits,
+                                 const uint8_t *key, size_t key_length,
+                                 ecc_private_key_stats_t *stats)
+{
+    int ok = 0;
+
+    /* Check the expected length (same calculation for all curves). */
+    TEST_EQUAL(PSA_BITS_TO_BYTES(bits), key_length);
+
+    /* All-bits zero is invalid and means no key material was copied to the
+     * output buffer, or a grave RNG pluming failure. */
+    TEST_ASSERT(!buffer_is_all_zero(key, key_length));
+
+    /* Check the top byte of the value for non-byte-aligned curve sizes.
+     * This is a partial endianness check. */
+    if (bits % 8 != 0) {
+        /* All supported non-byte-aligned curve sizes are for Weierstrass
+         * curves with a big-endian representation. */
+        uint8_t top_byte = key[0];
+        uint8_t mask = 0xff << (bits & 8);
+        TEST_EQUAL(top_byte & mask, 0);
+    }
+
+    /* Check masked bits on Curve25519 and Curve448 scalars.
+     * See RFC 7748 \S4.1 (we expect the "decoded" form here). */
+#if defined(MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255)
+    if (family == PSA_ECC_FAMILY_MONTGOMERY && bits == 255) {
+        TEST_EQUAL(key[0] & 0xf8, key[0]);
+        TEST_EQUAL(key[31] & 0xc0, 0x40);
+    }
+#endif /* MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 */
+#if defined(MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448)
+    if (family == PSA_ECC_FAMILY_MONTGOMERY && bits == 448) {
+        TEST_EQUAL(key[0] & 0xfc, key[0]);
+        TEST_EQUAL(key[55] & 0x80, 0x80);
+    }
+#endif /* MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 */
+
+    /* Don't bother to check that the value is in the exact permitted range
+     * (1 to p-1 for Weierstrass curves, 2^{n-1} to p-1 for Montgomery curves).
+     * We would need to bring in bignum machinery, and on most curves
+     * the probability of a number being out of range is negligible.
+     */
+
+    /* Collect statistics on random-valued bits */
+    /* Defaults for big-endian numbers */
+    uint8_t bit_bot_mask = 0x01;
+    size_t bit_bot_index = key_length - 1;
+    uint8_t bit_top_mask = (bits % 8 == 0 ? 0x80 : 1 << (bits % 8 - 1));
+    size_t bit_top_index = 0;
+    if (family == PSA_ECC_FAMILY_MONTGOMERY) {
+        bit_bot_index = 0;
+        bit_top_index = key_length - 1;
+        if (bits == 255) {
+            bit_bot_mask = 0x08;
+            bit_top_mask = 0x20;
+        } else {
+            bit_bot_mask = 0x04;
+            bit_top_mask = 0x40;
+        }
+    }
+    if (key[bit_bot_index] & bit_bot_mask) {
+        ++stats->bit_bot;
+    }
+    if (key[bit_top_index] & bit_top_mask) {
+        ++stats->bit_top;
+    }
+
+    ok = 1;
+exit:
+    return ok;
+}
+#endif
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
+void generate_key(int family_arg, int bits_arg,
+                  int output_size_arg,
+                  psa_status_t expected_status)
+{
+    psa_ecc_family_t family = family_arg;
+    size_t bits = bits_arg;
+    size_t output_size = output_size_arg;
+
+    uint8_t *output = NULL;
+    size_t output_length = SIZE_MAX;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(family));
+    psa_set_key_bits(&attributes, bits);
+    ecc_private_key_stats_t stats = { 0, 0 };
+
+    PSA_INIT();
+    TEST_CALLOC(output, output_size);
+
+    /* In success cases, run multiple iterations so that we can make
+     * statistical observations. */
+    unsigned iteration_count = expected_status == PSA_SUCCESS ? 256 : 1;
+    for (unsigned i = 0; i < iteration_count; i++) {
+        mbedtls_test_set_step(i);
+        TEST_EQUAL(mbedtls_psa_ecp_generate_key(&attributes,
+                                                output, output_size,
+                                                &output_length),
+                   expected_status);
+        if (expected_status == PSA_SUCCESS) {
+            TEST_LE_U(output_length, output_size);
+            TEST_ASSERT(check_ecc_private_key(family, bits,
+                                              output, output_length,
+                                              &stats));
+        }
+    }
+
+    if (expected_status == PSA_SUCCESS) {
+        /* For selected bits, check that we saw the values 0 and 1 each
+         * at least some minimum number of times. The iteration count and
+         * the minimum are chosen so that a random failure is unlikely
+         * to more than cryptographic levels. */
+        unsigned const min_times = 10;
+        TEST_LE_U(min_times, stats.bit_bot);
+        TEST_LE_U(stats.bit_bot, iteration_count - min_times);
+        TEST_LE_U(min_times, stats.bit_top);
+        TEST_LE_U(stats.bit_top, iteration_count - min_times);
+    }
+
+exit:
+    PSA_DONE();
+    mbedtls_free(output);
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_psa_crypto_memory.function b/tests/suites/test_suite_psa_crypto_memory.function
index 55c0092..50539e8 100644
--- a/tests/suites/test_suite_psa_crypto_memory.function
+++ b/tests/suites/test_suite_psa_crypto_memory.function
@@ -107,7 +107,10 @@
 
 exit:
     mbedtls_free(local_input.buffer);
-    mbedtls_free(input);
+
+    if (local_input.buffer != input) {
+        mbedtls_free(input);
+    }
 }
 /* END_CASE */
 
@@ -243,7 +246,7 @@
     TEST_CALLOC(buffer_copy_for_comparison, local_output.length);
     memcpy(buffer_copy_for_comparison, local_output.buffer, local_output.length);
 
-    psa_crypto_local_output_free(&local_output);
+    TEST_EQUAL(psa_crypto_local_output_free(&local_output), PSA_SUCCESS);
     TEST_ASSERT(local_output.buffer == NULL);
     TEST_EQUAL(local_output.length, 0);
 
diff --git a/tests/suites/test_suite_random.function b/tests/suites/test_suite_random.function
index 155b8e7..b58b22f 100644
--- a/tests/suites/test_suite_random.function
+++ b/tests/suites/test_suite_random.function
@@ -22,7 +22,9 @@
 void random_twice_with_ctr_drbg()
 {
     mbedtls_entropy_context entropy;
+    mbedtls_entropy_init(&entropy);
     mbedtls_ctr_drbg_context drbg;
+    mbedtls_ctr_drbg_init(&drbg);
     unsigned char output1[OUTPUT_SIZE];
     unsigned char output2[OUTPUT_SIZE];
 
@@ -34,8 +36,6 @@
 
 
     /* First round */
-    mbedtls_entropy_init(&entropy);
-    mbedtls_ctr_drbg_init(&drbg);
     TEST_EQUAL(0, mbedtls_ctr_drbg_seed(&drbg,
                                         mbedtls_entropy_func, &entropy,
                                         NULL, 0));
@@ -73,7 +73,9 @@
 void random_twice_with_hmac_drbg(int md_type)
 {
     mbedtls_entropy_context entropy;
+    mbedtls_entropy_init(&entropy);
     mbedtls_hmac_drbg_context drbg;
+    mbedtls_hmac_drbg_init(&drbg);
     unsigned char output1[OUTPUT_SIZE];
     unsigned char output2[OUTPUT_SIZE];
     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
@@ -81,8 +83,6 @@
     MD_PSA_INIT();
 
     /* First round */
-    mbedtls_entropy_init(&entropy);
-    mbedtls_hmac_drbg_init(&drbg);
     TEST_EQUAL(0, mbedtls_hmac_drbg_seed(&drbg, md_info,
                                          mbedtls_entropy_func, &entropy,
                                          NULL, 0));
diff --git a/tests/suites/test_suite_x509write.function b/tests/suites/test_suite_x509write.function
index 2762b0f..81816fe 100644
--- a/tests/suites/test_suite_x509write.function
+++ b/tests/suites/test_suite_x509write.function
@@ -287,21 +287,24 @@
                            int cert_type)
 {
     mbedtls_pk_context key;
+    mbedtls_pk_init(&key);
+
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+
     mbedtls_x509write_csr req;
+    mbedtls_x509write_csr_init(&req);
+
     unsigned char buf[4096];
     int ret;
     size_t pem_len = 0;
     const char *subject_name = "C=NL,O=PolarSSL,CN=PolarSSL Server 1";
     mbedtls_test_rnd_pseudo_info rnd_info;
 
-    mbedtls_x509write_csr_init(&req);
     MD_OR_USE_PSA_INIT();
 
     memset(&rnd_info, 0x2a, sizeof(mbedtls_test_rnd_pseudo_info));
 
-    mbedtls_pk_init(&key);
     TEST_ASSERT(mbedtls_pk_parse_keyfile(&key, key_file, NULL,
                                          mbedtls_test_rnd_std_rand, NULL) == 0);