Merge pull request #6172 from gilles-peskine-arm/doc-tls13-psa_crypto_init

Document the need to call psa_crypto_init for TLS 1.3
diff --git a/ChangeLog.d/platform-zeroization.txt b/ChangeLog.d/platform-zeroization.txt
new file mode 100644
index 0000000..f17fbbb
--- /dev/null
+++ b/ChangeLog.d/platform-zeroization.txt
@@ -0,0 +1,3 @@
+Security
+  * Use platform-provided secure zeroization function where possible, such as
+    explicit_bzero().
diff --git a/ChangeLog.d/psa-alt-headers.txt b/ChangeLog.d/psa-alt-headers.txt
new file mode 100644
index 0000000..9555629
--- /dev/null
+++ b/ChangeLog.d/psa-alt-headers.txt
@@ -0,0 +1,4 @@
+Features
+   * The configuration macros MBEDTLS_PSA_CRYPTO_PLATFORM_FILE and
+     MBEDTLS_PSA_CRYPTO_STRUCT_FILE specify alternative locations for
+     the headers "psa/crypto_platform.h" and "psa/crypto_struct.h".
diff --git a/ChangeLog.d/tls13-only-renegotiation.txt b/ChangeLog.d/tls13-only-renegotiation.txt
new file mode 100644
index 0000000..f463de1
--- /dev/null
+++ b/ChangeLog.d/tls13-only-renegotiation.txt
@@ -0,0 +1,5 @@
+Bugfix
+   * Fix the handling of renegotiation attempts in TLS 1.3. They are now
+     systematically rejected.
+   * Fix an unused-variable warning in TLS 1.3-only builds if
+     MBEDTLS_SSL_RENEGOTIATION was enabled. Fixes #6200.
diff --git a/include/mbedtls/build_info.h b/include/mbedtls/build_info.h
index b10b1ad..4835beb 100644
--- a/include/mbedtls/build_info.h
+++ b/include/mbedtls/build_info.h
@@ -80,6 +80,20 @@
 #include MBEDTLS_USER_CONFIG_FILE
 #endif
 
+/* Auto-enable MBEDTLS_MD_LIGHT based on MBEDTLS_MD_C.
+ * This allows checking for MD_LIGHT rather than MD_LIGHT || MD_C.
+ */
+#if defined(MBEDTLS_MD_C)
+#define MBEDTLS_MD_LIGHT
+#endif
+
+/* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT
+ * is defined as well to include all PSA code.
+ */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+#define MBEDTLS_PSA_CRYPTO_CLIENT
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
 /* The PK wrappers need pk_write functions to format RSA key objects
  * when they are dispatching to the PSA API. This happens under USE_PSA_CRYPTO,
  * and also even without USE_PSA_CRYPTO for mbedtls_pk_sign_ext(). */
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index ac374d2..3065df5 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -712,41 +712,6 @@
 #if defined(MBEDTLS_SHA512_ALT) || defined(MBEDTLS_SHA512_PROCESS_ALT)
 #error "MBEDTLS_SHA512_*ALT can't be used with MBEDTLS_SHA512_USE_A64_CRYPTO_*"
 #endif
-/*
- * Best performance comes from most recent compilers, with intrinsics and -O3.
- * Must compile with -march=armv8.2-a+sha3, but we can't detect armv8.2-a, and
- * can't always detect __ARM_FEATURE_SHA512 (notably clang 7-12).
- *
- * GCC < 8 won't work at all (lacks the sha512 instructions)
- * GCC >= 8 uses intrinsics, sets __ARM_FEATURE_SHA512
- *
- * Clang < 7 won't work at all (lacks the sha512 instructions)
- * Clang 7-12 don't have intrinsics (but we work around that with inline
- *            assembler) or __ARM_FEATURE_SHA512
- * Clang == 13.0.0 same as clang 12 (only seen on macOS)
- * Clang >= 13.0.1 has __ARM_FEATURE_SHA512 and intrinsics
- */
-#if defined(__aarch64__) && !defined(__ARM_FEATURE_SHA512)
-   /* Test Clang first, as it defines __GNUC__ */
-#  if defined(__clang__)
-#    if __clang_major__ < 7
-#      error "A more recent Clang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
-#    elif __clang_major__ < 13 || \
-         (__clang_major__ == 13 && __clang_minor__ == 0 && __clang_patchlevel__ == 0)
-       /* We implement the intrinsics with inline assembler, so don't error */
-#    else
-#      error "Must use minimum -march=armv8.2-a+sha3 for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
-#    endif
-#  elif defined(__GNUC__)
-#    if __GNUC__ < 8
-#      error "A more recent GCC is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
-#    else
-#      error "Must use minimum -march=armv8.2-a+sha3 for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
-#    endif
-#  else
-#    error "Only GCC and Clang supported for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
-#  endif
-#endif
 
 #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
 
@@ -767,9 +732,7 @@
 #if defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA256_PROCESS_ALT)
 #error "MBEDTLS_SHA256_*ALT can't be used with MBEDTLS_SHA256_USE_A64_CRYPTO_*"
 #endif
-#if defined(__aarch64__) && !defined(__ARM_FEATURE_CRYPTO)
-#error "Must use minimum -march=armv8-a+crypto for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
-#endif
+
 #endif
 
 #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) && \
@@ -936,6 +899,11 @@
 #error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_SSL_RENEGOTIATION) && \
+    !defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#error "MBEDTLS_SSL_RENEGOTIATION defined, but not all prerequisites"
+#endif
+
 #if defined(MBEDTLS_SSL_TICKET_C) && ( !defined(MBEDTLS_CIPHER_C) && \
                                        !defined(MBEDTLS_USE_PSA_CRYPTO) )
 #error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites"
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index 677670a..05f9d9d 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -2635,7 +2635,7 @@
 /**
  * \def MBEDTLS_MD_C
  *
- * Enable the generic message digest layer.
+ * Enable the generic layer for message digest (hashing) and HMAC.
  *
  * Requires: one of: MBEDTLS_MD5_C, MBEDTLS_RIPEMD160_C, MBEDTLS_SHA1_C,
  *                   MBEDTLS_SHA224_C, MBEDTLS_SHA256_C, MBEDTLS_SHA384_C,
@@ -3079,9 +3079,6 @@
  * \note If MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT is defined when building
  * for a non-Aarch64 build it will be silently ignored.
  *
- * \note The code uses Neon intrinsics, so \c CFLAGS must be set to a minimum
- * of \c -march=armv8-a+crypto.
- *
  * \warning MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT cannot be defined at the
  * same time as MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY.
  *
@@ -3104,9 +3101,6 @@
  * \note This allows builds with a smaller code size than with
  * MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
  *
- * \note The code uses Neon intrinsics, so \c CFLAGS must be set to a minimum
- * of \c -march=armv8-a+crypto.
- *
  * \warning MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY cannot be defined at the same
  * time as MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT.
  *
@@ -3161,9 +3155,7 @@
  * for a non-Aarch64 build it will be silently ignored.
  *
  * \note The code uses the SHA-512 Neon intrinsics, so requires GCC >= 8 or
- * Clang >= 7, and \c CFLAGS must be set to a minimum of
- * \c -march=armv8.2-a+sha3. An optimisation level of \c -O3 generates the
- * fastest code.
+ * Clang >= 7.
  *
  * \warning MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT cannot be defined at the
  * same time as MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY.
@@ -3188,9 +3180,7 @@
  * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
  *
  * \note The code uses the SHA-512 Neon intrinsics, so requires GCC >= 8 or
- * Clang >= 7, and \c CFLAGS must be set to a minimum of
- * \c -march=armv8.2-a+sha3. An optimisation level of \c -O3 generates the
- * fastest code.
+ * Clang >= 7.
  *
  * \warning MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY cannot be defined at the same
  * time as MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT.
@@ -3529,6 +3519,53 @@
  */
 //#define MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE "/dev/null"
 
+/**
+ * \def MBEDTLS_PSA_CRYPTO_PLATFORM_FILE
+ *
+ * If defined, this is a header which will be included instead of
+ * `"psa/crypto_platform.h"`. This file should declare the same identifiers
+ * as the one in Mbed TLS, but with definitions adapted to the platform on
+ * which the library code will run.
+ *
+ * \note The required content of this header can vary from one version of
+ *       Mbed TLS to the next. Integrators who provide an alternative file
+ *       should review the changes in the original file whenever they
+ *       upgrade Mbed TLS.
+ *
+ * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an <tt>\#include</tt> line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_PSA_CRYPTO_PLATFORM_FILE "psa/crypto_platform_alt.h"
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_STRUCT_FILE
+ *
+ * If defined, this is a header which will be included instead of
+ * `"psa/crypto_struct.h"`. This file should declare the same identifiers
+ * as the one in Mbed TLS, but with definitions adapted to the environment
+ * in which the library code will run. The typical use for this feature
+ * is to provide alternative type definitions on the client side in
+ * client-server integrations of PSA crypto, where operation structures
+ * contain handles instead of cryptographic data.
+ *
+ * \note The required content of this header can vary from one version of
+ *       Mbed TLS to the next. Integrators who provide an alternative file
+ *       should review the changes in the original file whenever they
+ *       upgrade Mbed TLS.
+ *
+ * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an <tt>\#include</tt> line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_PSA_CRYPTO_STRUCT_FILE "psa/crypto_struct_alt.h"
+
 /** \} name SECTION: General configuration options */
 
 /**
diff --git a/include/mbedtls/md.h b/include/mbedtls/md.h
index 1a92c57..3341d1c 100644
--- a/include/mbedtls/md.h
+++ b/include/mbedtls/md.h
@@ -1,7 +1,8 @@
 /**
  * \file md.h
  *
- * \brief This file contains the generic message-digest wrapper.
+ * \brief   This file contains the generic functions for message-digest
+ *          (hashing) and HMAC.
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  */
@@ -108,30 +109,6 @@
 } mbedtls_md_context_t;
 
 /**
- * \brief           This function returns the list of digests supported by the
- *                  generic digest module.
- *
- * \note            The list starts with the strongest available hashes.
- *
- * \return          A statically allocated array of digests. Each element
- *                  in the returned list is an integer belonging to the
- *                  message-digest enumeration #mbedtls_md_type_t.
- *                  The last entry is 0.
- */
-const int *mbedtls_md_list(void);
-
-/**
- * \brief           This function returns the message-digest information
- *                  associated with the given digest name.
- *
- * \param md_name   The name of the digest to search for.
- *
- * \return          The message-digest information associated with \p md_name.
- * \return          NULL if the associated message-digest information is not found.
- */
-const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name);
-
-/**
  * \brief           This function returns the message-digest information
  *                  associated with the given digest type.
  *
@@ -143,19 +120,6 @@
 const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type);
 
 /**
- * \brief           This function returns the message-digest information
- *                  from the given context.
- *
- * \param ctx       The context from which to extract the information.
- *                  This must be initialized (or \c NULL).
- *
- * \return          The message-digest information associated with \p ctx.
- * \return          \c NULL if \p ctx is \c NULL.
- */
-const mbedtls_md_info_t *mbedtls_md_info_from_ctx(
-    const mbedtls_md_context_t *ctx);
-
-/**
  * \brief           This function initializes a message-digest context without
  *                  binding it to a particular message-digest algorithm.
  *
@@ -249,17 +213,6 @@
 mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info);
 
 /**
- * \brief           This function extracts the message-digest name from the
- *                  message-digest information structure.
- *
- * \param md_info   The information structure of the message-digest algorithm
- *                  to use.
- *
- * \return          The name of the message digest.
- */
-const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info);
-
-/**
  * \brief           This function starts a message-digest computation.
  *
  *                  You must call this function after setting up the context
@@ -337,6 +290,54 @@
 int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
                unsigned char *output);
 
+/**
+ * \brief           This function returns the list of digests supported by the
+ *                  generic digest module.
+ *
+ * \note            The list starts with the strongest available hashes.
+ *
+ * \return          A statically allocated array of digests. Each element
+ *                  in the returned list is an integer belonging to the
+ *                  message-digest enumeration #mbedtls_md_type_t.
+ *                  The last entry is 0.
+ */
+const int *mbedtls_md_list(void);
+
+/**
+ * \brief           This function returns the message-digest information
+ *                  associated with the given digest name.
+ *
+ * \param md_name   The name of the digest to search for.
+ *
+ * \return          The message-digest information associated with \p md_name.
+ * \return          NULL if the associated message-digest information is not found.
+ */
+const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name);
+
+/**
+ * \brief           This function extracts the message-digest name from the
+ *                  message-digest information structure.
+ *
+ * \param md_info   The information structure of the message-digest algorithm
+ *                  to use.
+ *
+ * \return          The name of the message digest.
+ */
+const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info);
+
+/**
+ * \brief           This function returns the message-digest information
+ *                  from the given context.
+ *
+ * \param ctx       The context from which to extract the information.
+ *                  This must be initialized (or \c NULL).
+ *
+ * \return          The message-digest information associated with \p ctx.
+ * \return          \c NULL if \p ctx is \c NULL.
+ */
+const mbedtls_md_info_t *mbedtls_md_info_from_ctx(
+    const mbedtls_md_context_t *ctx);
+
 #if defined(MBEDTLS_FS_IO)
 /**
  * \brief          This function calculates the message-digest checksum
@@ -471,10 +472,6 @@
                     const unsigned char *input, size_t ilen,
                     unsigned char *output);
 
-/* Internal use */
-MBEDTLS_CHECK_RETURN_TYPICAL
-int mbedtls_md_process(mbedtls_md_context_t *ctx, const unsigned char *data);
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h
index f6070dc..6d5843d 100644
--- a/include/mbedtls/psa_util.h
+++ b/include/mbedtls/psa_util.h
@@ -344,6 +344,52 @@
 
 #endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
 
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+typedef struct {
+    psa_status_t psa_status;
+    int16_t mbedtls_error;
+} mbedtls_error_pair_t;
 
+#if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_MD5_C) || defined(MBEDTLS_USE_PSA_CRYPTO)
+extern const mbedtls_error_pair_t psa_to_md_errors[4];
+#endif
+
+#if defined(MBEDTLS_LMS_C)
+extern const mbedtls_error_pair_t psa_to_lms_errors[3];
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
+extern const mbedtls_error_pair_t psa_to_ssl_errors[7];
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
+extern const mbedtls_error_pair_t psa_to_pk_rsa_errors[8];
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+extern const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[7];
+#endif
+
+/* Generic fallback function for error translation,
+ * when the received state was not module-specific. */
+int psa_generic_status_to_mbedtls(psa_status_t status);
+
+/* This function iterates over provided local error translations,
+ * and if no match was found - calls the fallback error translation function. */
+int psa_status_to_mbedtls(psa_status_t status,
+                          const mbedtls_error_pair_t *local_translations,
+                          size_t local_errors_num,
+                          int (*fallback_f)(psa_status_t));
+
+/* The second out of three-stage error handling functions of the pk module,
+ * acts as a fallback after RSA / ECDSA error translation, and if no match
+ * is found, it itself calls psa_generic_status_to_mbedtls. */
+int psa_pk_status_to_mbedtls(psa_status_t status);
+
+/* Utility macro to shorten the defines of error translator in modules. */
+#define PSA_TO_MBEDTLS_ERR_LIST(status, error_list, fallback_f) \
+    psa_status_to_mbedtls(status, error_list, sizeof(error_list), fallback_f)
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
 #endif /* MBEDTLS_PSA_UTIL_H */
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 5b448a5..8a05efd 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -22,7 +22,11 @@
 #ifndef PSA_CRYPTO_H
 #define PSA_CRYPTO_H
 
+#if defined(MBEDTLS_PSA_CRYPTO_PLATFORM_FILE)
+#include MBEDTLS_PSA_CRYPTO_PLATFORM_FILE
+#else
 #include "crypto_platform.h"
+#endif
 
 #include <stddef.h>
 
@@ -4680,7 +4684,11 @@
 
 /* The file "crypto_struct.h" contains definitions for
  * implementation-specific structs that are declared above. */
+#if defined(MBEDTLS_PSA_CRYPTO_STRUCT_FILE)
+#include MBEDTLS_PSA_CRYPTO_STRUCT_FILE
+#else
 #include "crypto_struct.h"
+#endif
 
 /* The file "crypto_extra.h" contains vendor-specific definitions. This
  * can include vendor-defined algorithms, extra functions, etc. */
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index 95bf32f..a5154fc 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -32,16 +32,17 @@
 
 #ifndef PSA_CRYPTO_TYPES_H
 #define PSA_CRYPTO_TYPES_H
+
+/* Make sure the Mbed TLS configuration is visible. */
+#include "mbedtls/build_info.h"
+/* Define the MBEDTLS_PRIVATE macro. */
 #include "mbedtls/private_access.h"
 
+#if defined(MBEDTLS_PSA_CRYPTO_PLATFORM_FILE)
+#include MBEDTLS_PSA_CRYPTO_PLATFORM_FILE
+#else
 #include "crypto_platform.h"
-
-/* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT
- * is defined as well to include all PSA code.
- */
-#if defined(MBEDTLS_PSA_CRYPTO_C)
-#define MBEDTLS_PSA_CRYPTO_CLIENT
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+#endif
 
 #include <stdint.h>
 
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index bef2e1c..06b0131 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -77,6 +77,7 @@
     psa_crypto_slot_management.c
     psa_crypto_storage.c
     psa_its_file.c
+    psa_util.c
     ripemd160.c
     rsa.c
     rsa_alt_helpers.c
diff --git a/library/Makefile b/library/Makefile
index ed5e1e1..ceb9c0d 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -142,6 +142,7 @@
 	     psa_crypto_slot_management.o \
 	     psa_crypto_storage.o \
 	     psa_its_file.o \
+	     psa_util.o \
 	     ripemd160.o \
 	     rsa.o \
 	     rsa_alt_helpers.o \
diff --git a/library/constant_time.c b/library/constant_time.c
index b3bf874..552a918 100644
--- a/library/constant_time.c
+++ b/library/constant_time.c
@@ -46,6 +46,11 @@
 #endif
 
 #include <string.h>
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,    \
+                                                           psa_to_ssl_errors,              \
+                                                           psa_generic_status_to_mbedtls)
+#endif
 
 /*
  * Define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS where assembly is present to
@@ -620,7 +625,7 @@
 
     psa_hash_abort(&operation);
     psa_hash_abort(&aux_operation);
-    return psa_ssl_status_to_mbedtls(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 }
 
 #undef MAX_HASH_BLOCK_LENGTH
diff --git a/library/ecjpake.c b/library/ecjpake.c
index 1a683d5..36c1327 100644
--- a/library/ecjpake.c
+++ b/library/ecjpake.c
@@ -35,6 +35,11 @@
 #if !defined(MBEDTLS_MD_C)
 #include "psa/crypto.h"
 #include "mbedtls/psa_util.h"
+#if !defined(MBEDTLS_ECJPAKE_ALT)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_md_errors,              \
+                                                           psa_generic_status_to_mbedtls)
+#endif /* !MBEDTLS_ECJPAKE_ALT */
 #endif /* !MBEDTLS_MD_C */
 
 #include "hash_info.h"
@@ -72,7 +77,7 @@
 
     status = psa_hash_compute(alg, input, ilen, output, out_size, &out_len);
 
-    return mbedtls_md_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 #endif /* !MBEDTLS_MD_C */
 }
 
diff --git a/library/ecp_curves.c b/library/ecp_curves.c
index b352e76..81ad73a 100644
--- a/library/ecp_curves.c
+++ b/library/ecp_curves.c
@@ -4575,6 +4575,8 @@
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
 static int ecp_mod_p224(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
 static int ecp_mod_p256(mbedtls_mpi *);
@@ -4951,6 +4953,173 @@
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+
+/*
+ * The reader is advised to first understand ecp_mod_p192() since the same
+ * general structure is used here, but with additional complications:
+ * (1) chunks of 32 bits, and (2) subtractions.
+ */
+
+/*
+ * For these primes, we need to handle data in chunks of 32 bits.
+ * This makes it more complicated if we use 64 bits limbs in MPI,
+ * which prevents us from using a uniform access method as for p192.
+ *
+ * So, we define a mini abstraction layer to access 32 bit chunks,
+ * load them in 'cur' for work, and store them back from 'cur' when done.
+ *
+ * While at it, also define the size of N in terms of 32-bit chunks.
+ */
+#define LOAD32      cur = A(i);
+
+#if defined(MBEDTLS_HAVE_INT32)  /* 32 bit */
+
+#define MAX32       X_limbs
+#define A(j)        X[j]
+#define STORE32     X[i] = (mbedtls_mpi_uint) cur;
+#define STORE0      X[i] = 0;
+
+#else /* 64 bit */
+
+#define MAX32   X_limbs * 2
+#define A(j)                                                \
+    (j) % 2 ?                                               \
+    (uint32_t) (X[(j) / 2] >> 32) :                         \
+    (uint32_t) (X[(j) / 2])
+#define STORE32                                             \
+    if (i % 2) {                                            \
+        X[i/2] &= 0x00000000FFFFFFFF;                       \
+        X[i/2] |= (uint64_t) (cur) << 32;                   \
+    } else {                                                \
+        X[i/2] &= 0xFFFFFFFF00000000;                       \
+        X[i/2] |= (uint32_t) cur;                           \
+    }
+
+#define STORE0                                              \
+    if (i % 2) {                                            \
+        X[i/2] &= 0x00000000FFFFFFFF;                       \
+    } else {                                                \
+        X[i/2] &= 0xFFFFFFFF00000000;                       \
+    }
+
+#endif
+
+static inline int8_t extract_carry(int64_t cur)
+{
+    return (int8_t) (cur >> 32);
+}
+
+#define ADD(j)    cur += A(j)
+#define SUB(j)    cur -= A(j)
+
+#define ADD_CARRY(cc) cur += (cc)
+#define SUB_CARRY(cc) cur -= (cc)
+
+#define ADD_LAST ADD_CARRY(last_c)
+#define SUB_LAST SUB_CARRY(last_c)
+
+/*
+ * Helpers for the main 'loop'
+ */
+#define INIT(b)                                         \
+    int8_t c = 0, last_c;                               \
+    int64_t cur;                                        \
+    size_t i = 0;                                       \
+    LOAD32;
+
+#define NEXT                                            \
+    c = extract_carry(cur);                             \
+    STORE32; i++; LOAD32;                               \
+    ADD_CARRY(c);
+
+#define RESET                                           \
+    c = extract_carry(cur);                             \
+    last_c = c;                                         \
+    STORE32; i = 0; LOAD32;                             \
+    c = 0;                                              \
+
+#define LAST                                            \
+    c = extract_carry(cur);                             \
+    STORE32; i++;                                       \
+    if (c != 0)                                         \
+    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;              \
+    while (i < MAX32) { STORE0; i++; }
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+
+/*
+ * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
+ */
+static int ecp_mod_p224(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width =  2 * 224 / biL;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p224_raw(N->p, expected_width);
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs)
+{
+    if (X_limbs != 2 * 224 / biL) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    INIT(224);
+
+    SUB(7);  SUB(11);           NEXT;   // A0 += -A7  - A11
+    SUB(8);  SUB(12);           NEXT;   // A1 += -A8  - A12
+    SUB(9);  SUB(13);           NEXT;   // A2 += -A9  - A13
+    SUB(10); ADD(7);  ADD(11);  NEXT;   // A3 += -A10 + A7 + A11
+    SUB(11); ADD(8);  ADD(12);  NEXT;   // A4 += -A11 + A8 + A12
+    SUB(12); ADD(9);  ADD(13);  NEXT;   // A5 += -A12 + A9 + A13
+    SUB(13); ADD(10);                   // A6 += -A13 + A10
+
+    RESET;
+
+    /* Use 2^224 = P + 2^96 - 1 to modulo reduce the final carry */
+    SUB_LAST; NEXT;                     // A0 -= last_c
+    ;         NEXT;                     // A1
+    ;         NEXT;                     // A2
+    ADD_LAST; NEXT;                     // A3 += last_c
+    ;         NEXT;                     // A4
+    ;         NEXT;                     // A5
+                                        // A6
+
+    /* The carry reduction cannot generate a carry
+     * (see commit 73e8553 for details)*/
+
+    LAST;
+
+    return 0;
+}
+
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+
+#undef LOAD32
+#undef MAX32
+#undef A
+#undef STORE32
+#undef STORE0
+#undef ADD
+#undef SUB
+#undef ADD_CARRY
+#undef SUB_CARRY
+#undef ADD_LAST
+#undef SUB_LAST
+#undef INIT
+#undef NEXT
+#undef RESET
+#undef LAST
+
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED ||
+          MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
+          MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
 /*
  * The reader is advised to first understand ecp_mod_p192() since the same
  * general structure is used here, but with additional complications:
@@ -5071,27 +5240,6 @@
     N->p[bits / 8 / sizeof(mbedtls_mpi_uint)] += msw;
 }
 
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
-/*
- * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
- */
-static int ecp_mod_p224(mbedtls_mpi *N)
-{
-    INIT(224);
-
-    SUB(7); SUB(11);               NEXT;      // A0 += -A7 - A11
-    SUB(8); SUB(12);               NEXT;      // A1 += -A8 - A12
-    SUB(9); SUB(13);               NEXT;      // A2 += -A9 - A13
-    SUB(10); ADD(7); ADD(11);    NEXT;        // A3 += -A10 + A7 + A11
-    SUB(11); ADD(8); ADD(12);    NEXT;        // A4 += -A11 + A8 + A12
-    SUB(12); ADD(9); ADD(13);    NEXT;        // A5 += -A12 + A9 + A13
-    SUB(13); ADD(10);               LAST;     // A6 += -A13 + A10
-
-cleanup:
-    return ret;
-}
-#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
-
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
 /*
  * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
@@ -5186,8 +5334,7 @@
 #undef NEXT
 #undef LAST
 
-#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED ||
-          MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
           MBEDTLS_ECP_DP_SECP384R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
diff --git a/library/ecp_invasive.h b/library/ecp_invasive.h
index aba7cca..1972f8c 100644
--- a/library/ecp_invasive.h
+++ b/library/ecp_invasive.h
@@ -33,8 +33,7 @@
 
 #if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_C)
 
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
-    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
 /* Preconditions:
  *   - bits is a multiple of 64 or is 224
@@ -96,6 +95,28 @@
 
 #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
 
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+
+/** Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
+ *
+ * \param[in,out]   X       The address of the MPI to be converted.
+ *                          Must have exact limb size that stores a 448-bit MPI
+ *                          (double the bitlength of the modulus).
+ *                          Upon return holds the reduced value which is
+ *                          in range `0 <= X < 2 * N` (where N is the modulus).
+ *                          The bitlength of the reduced value is the same as
+ *                          that of the modulus (224 bits).
+ * \param[in]       X_limbs The length of \p X in limbs.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the
+ *                  limb size that sores a 448-bit MPI.
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+
 #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
 
 /** Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5)
diff --git a/library/hash_info.c b/library/hash_info.c
index f8b41a5..0e445b6 100644
--- a/library/hash_info.c
+++ b/library/hash_info.c
@@ -104,6 +104,7 @@
     return entry->md_type;
 }
 
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 int mbedtls_md_error_from_psa(psa_status_t status)
 {
     switch (status) {
@@ -119,3 +120,4 @@
             return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
     }
 }
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
diff --git a/library/hash_info.h b/library/hash_info.h
index 47da934..f984c82 100644
--- a/library/hash_info.h
+++ b/library/hash_info.h
@@ -34,6 +34,7 @@
 
 #include "mbedtls/md.h"
 #include "psa/crypto.h"
+#include "mbedtls/platform_util.h"
 
 /** \def MBEDTLS_HASH_MAX_SIZE
  *
@@ -88,12 +89,13 @@
  */
 mbedtls_md_type_t mbedtls_hash_info_md_from_psa(psa_algorithm_t psa_alg);
 
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 /** Convert PSA status to MD error code.
  *
  * \param status    PSA status.
  *
  * \return          The corresponding MD error code,
  */
-int mbedtls_md_error_from_psa(psa_status_t status);
-
+int MBEDTLS_DEPRECATED mbedtls_md_error_from_psa(psa_status_t status);
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
 #endif /* MBEDTLS_HASH_INFO_H */
diff --git a/library/lmots.c b/library/lmots.c
index c6b45ed..4061edd 100644
--- a/library/lmots.c
+++ b/library/lmots.c
@@ -41,9 +41,14 @@
 #include "mbedtls/lms.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "mbedtls/psa_util.h"
 
 #include "psa/crypto.h"
 
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_lms_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+
 #define PUBLIC_KEY_TYPE_OFFSET     (0)
 #define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \
                                     MBEDTLS_LMOTS_TYPE_LEN)
@@ -198,7 +203,7 @@
 exit:
     psa_hash_abort(&op);
 
-    return mbedtls_lms_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 }
 
 /* Hash each element of the string of digits (+ checksum), producing a hash
@@ -321,7 +326,7 @@
     psa_hash_abort(&op);
     mbedtls_platform_zeroize(tmp_hash, sizeof(tmp_hash));
 
-    return mbedtls_lms_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 }
 
 /* Combine the hashes of the digit array into a public key. This is used in
@@ -386,9 +391,10 @@
         psa_hash_abort(&op);
     }
 
-    return mbedtls_lms_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 }
 
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 int mbedtls_lms_error_from_psa(psa_status_t status)
 {
     switch (status) {
@@ -406,6 +412,7 @@
             return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
     }
 }
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
 void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx)
 {
@@ -682,7 +689,7 @@
 exit:
     psa_hash_abort(&op);
 
-    return mbedtls_lms_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 }
 
 int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx,
diff --git a/library/lmots.h b/library/lmots.h
index deeeace..98d1941 100644
--- a/library/lmots.h
+++ b/library/lmots.h
@@ -79,6 +79,7 @@
 unsigned int mbedtls_lms_network_bytes_to_unsigned_int(size_t len,
                                                        const unsigned char *bytes);
 
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 /**
  * \brief                    This function converts a \ref psa_status_t to a
  *                           low-level LMS error code.
@@ -87,8 +88,8 @@
  *
  * \return                   The corresponding LMS error code.
  */
-int mbedtls_lms_error_from_psa(psa_status_t status);
-
+int MBEDTLS_DEPRECATED mbedtls_lms_error_from_psa(psa_status_t status);
+#endif
 
 /**
  * \brief                    This function initializes a public LMOTS context
diff --git a/library/lms.c b/library/lms.c
index 76bcc19..acc3523 100644
--- a/library/lms.c
+++ b/library/lms.c
@@ -39,13 +39,17 @@
 #include "lmots.h"
 
 #include "psa/crypto.h"
-
+#include "mbedtls/psa_util.h"
 #include "mbedtls/lms.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 
 #include "mbedtls/platform.h"
 
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_lms_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+
 #define SIG_Q_LEAF_ID_OFFSET     (0)
 #define SIG_OTS_SIG_OFFSET       (SIG_Q_LEAF_ID_OFFSET + \
                                   MBEDTLS_LMOTS_Q_LEAF_ID_LEN)
@@ -140,7 +144,7 @@
 exit:
     psa_hash_abort(&op);
 
-    return mbedtls_lms_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 }
 
 /* Calculate the value of an internal node of the Merkle tree (which is a hash
@@ -220,7 +224,7 @@
 exit:
     psa_hash_abort(&op);
 
-    return mbedtls_lms_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 }
 
 void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx)
diff --git a/library/md.c b/library/md.c
index a729878..6681f9a 100644
--- a/library/md.c
+++ b/library/md.c
@@ -23,7 +23,23 @@
 
 #include "common.h"
 
-#if defined(MBEDTLS_MD_C)
+/*
+ * Availability of functions in this module is controlled by two
+ * feature macros:
+ * - MBEDTLS_MD_C enables the whole module;
+ * - MBEDTLS_MD_LIGHT enables only functions for hashing and accessing
+ * most hash metadata (everything except string names); is it
+ * automatically set whenever MBEDTLS_MD_C is defined.
+ *
+ * In this file, functions from MD_LIGHT are at the top, MD_C at the end.
+ *
+ * In the future we may want to change the contract of some functions
+ * (behaviour with NULL arguments) depending on whether MD_C is defined or
+ * only MD_LIGHT. Also, the exact scope of MD_LIGHT might vary.
+ *
+ * For these reasons, we're keeping MD_LIGHT internal for now.
+ */
+#if defined(MBEDTLS_MD_LIGHT)
 
 #include "mbedtls/md.h"
 #include "md_wrap.h"
@@ -107,91 +123,6 @@
 };
 #endif
 
-/*
- * Reminder: update profiles in x509_crt.c when adding a new hash!
- */
-static const int supported_digests[] = {
-
-#if defined(MBEDTLS_SHA512_C)
-    MBEDTLS_MD_SHA512,
-#endif
-
-#if defined(MBEDTLS_SHA384_C)
-    MBEDTLS_MD_SHA384,
-#endif
-
-#if defined(MBEDTLS_SHA256_C)
-    MBEDTLS_MD_SHA256,
-#endif
-#if defined(MBEDTLS_SHA224_C)
-    MBEDTLS_MD_SHA224,
-#endif
-
-#if defined(MBEDTLS_SHA1_C)
-    MBEDTLS_MD_SHA1,
-#endif
-
-#if defined(MBEDTLS_RIPEMD160_C)
-    MBEDTLS_MD_RIPEMD160,
-#endif
-
-#if defined(MBEDTLS_MD5_C)
-    MBEDTLS_MD_MD5,
-#endif
-
-    MBEDTLS_MD_NONE
-};
-
-const int *mbedtls_md_list(void)
-{
-    return supported_digests;
-}
-
-const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name)
-{
-    if (NULL == md_name) {
-        return NULL;
-    }
-
-    /* Get the appropriate digest information */
-#if defined(MBEDTLS_MD5_C)
-    if (!strcmp("MD5", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
-    }
-#endif
-#if defined(MBEDTLS_RIPEMD160_C)
-    if (!strcmp("RIPEMD160", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_RIPEMD160);
-    }
-#endif
-#if defined(MBEDTLS_SHA1_C)
-    if (!strcmp("SHA1", md_name) || !strcmp("SHA", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
-    }
-#endif
-#if defined(MBEDTLS_SHA224_C)
-    if (!strcmp("SHA224", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA224);
-    }
-#endif
-#if defined(MBEDTLS_SHA256_C)
-    if (!strcmp("SHA256", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
-    }
-#endif
-#if defined(MBEDTLS_SHA384_C)
-    if (!strcmp("SHA384", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
-    }
-#endif
-#if defined(MBEDTLS_SHA512_C)
-    if (!strcmp("SHA512", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
-    }
-#endif
-    return NULL;
-}
-
 const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type)
 {
     switch (md_type) {
@@ -228,16 +159,6 @@
     }
 }
 
-const mbedtls_md_info_t *mbedtls_md_info_from_ctx(
-    const mbedtls_md_context_t *ctx)
-{
-    if (ctx == NULL) {
-        return NULL;
-    }
-
-    return ctx->MBEDTLS_PRIVATE(md_info);
-}
-
 void mbedtls_md_init(mbedtls_md_context_t *ctx)
 {
     memset(ctx, 0, sizeof(mbedtls_md_context_t));
@@ -586,6 +507,125 @@
     }
 }
 
+unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info)
+{
+    if (md_info == NULL) {
+        return 0;
+    }
+
+    return md_info->size;
+}
+
+mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info)
+{
+    if (md_info == NULL) {
+        return MBEDTLS_MD_NONE;
+    }
+
+    return md_info->type;
+}
+
+/************************************************************************
+ * Functions above this separator are part of MBEDTLS_MD_LIGHT,         *
+ * functions below are only available when MBEDTLS_MD_C is set.         *
+ ************************************************************************/
+#if defined(MBEDTLS_MD_C)
+
+/*
+ * Reminder: update profiles in x509_crt.c when adding a new hash!
+ */
+static const int supported_digests[] = {
+
+#if defined(MBEDTLS_SHA512_C)
+    MBEDTLS_MD_SHA512,
+#endif
+
+#if defined(MBEDTLS_SHA384_C)
+    MBEDTLS_MD_SHA384,
+#endif
+
+#if defined(MBEDTLS_SHA256_C)
+    MBEDTLS_MD_SHA256,
+#endif
+#if defined(MBEDTLS_SHA224_C)
+    MBEDTLS_MD_SHA224,
+#endif
+
+#if defined(MBEDTLS_SHA1_C)
+    MBEDTLS_MD_SHA1,
+#endif
+
+#if defined(MBEDTLS_RIPEMD160_C)
+    MBEDTLS_MD_RIPEMD160,
+#endif
+
+#if defined(MBEDTLS_MD5_C)
+    MBEDTLS_MD_MD5,
+#endif
+
+    MBEDTLS_MD_NONE
+};
+
+const int *mbedtls_md_list(void)
+{
+    return supported_digests;
+}
+
+const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name)
+{
+    if (NULL == md_name) {
+        return NULL;
+    }
+
+    /* Get the appropriate digest information */
+#if defined(MBEDTLS_MD5_C)
+    if (!strcmp("MD5", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
+    }
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+    if (!strcmp("RIPEMD160", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_RIPEMD160);
+    }
+#endif
+#if defined(MBEDTLS_SHA1_C)
+    if (!strcmp("SHA1", md_name) || !strcmp("SHA", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
+    }
+#endif
+#if defined(MBEDTLS_SHA224_C)
+    if (!strcmp("SHA224", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA224);
+    }
+#endif
+#if defined(MBEDTLS_SHA256_C)
+    if (!strcmp("SHA256", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+    }
+#endif
+#if defined(MBEDTLS_SHA384_C)
+    if (!strcmp("SHA384", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
+    }
+#endif
+#if defined(MBEDTLS_SHA512_C)
+    if (!strcmp("SHA512", md_name)) {
+        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
+    }
+#endif
+    return NULL;
+}
+
+const mbedtls_md_info_t *mbedtls_md_info_from_ctx(
+    const mbedtls_md_context_t *ctx)
+{
+    if (ctx == NULL) {
+        return NULL;
+    }
+
+    return ctx->MBEDTLS_PRIVATE(md_info);
+}
+
 #if defined(MBEDTLS_FS_IO)
 int mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path, unsigned char *output)
 {
@@ -774,64 +814,6 @@
     return ret;
 }
 
-int mbedtls_md_process(mbedtls_md_context_t *ctx, const unsigned char *data)
-{
-    if (ctx == NULL || ctx->md_info == NULL) {
-        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
-    }
-
-    switch (ctx->md_info->type) {
-#if defined(MBEDTLS_MD5_C)
-        case MBEDTLS_MD_MD5:
-            return mbedtls_internal_md5_process(ctx->md_ctx, data);
-#endif
-#if defined(MBEDTLS_RIPEMD160_C)
-        case MBEDTLS_MD_RIPEMD160:
-            return mbedtls_internal_ripemd160_process(ctx->md_ctx, data);
-#endif
-#if defined(MBEDTLS_SHA1_C)
-        case MBEDTLS_MD_SHA1:
-            return mbedtls_internal_sha1_process(ctx->md_ctx, data);
-#endif
-#if defined(MBEDTLS_SHA224_C)
-        case MBEDTLS_MD_SHA224:
-            return mbedtls_internal_sha256_process(ctx->md_ctx, data);
-#endif
-#if defined(MBEDTLS_SHA256_C)
-        case MBEDTLS_MD_SHA256:
-            return mbedtls_internal_sha256_process(ctx->md_ctx, data);
-#endif
-#if defined(MBEDTLS_SHA384_C)
-        case MBEDTLS_MD_SHA384:
-            return mbedtls_internal_sha512_process(ctx->md_ctx, data);
-#endif
-#if defined(MBEDTLS_SHA512_C)
-        case MBEDTLS_MD_SHA512:
-            return mbedtls_internal_sha512_process(ctx->md_ctx, data);
-#endif
-        default:
-            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
-    }
-}
-
-unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info)
-{
-    if (md_info == NULL) {
-        return 0;
-    }
-
-    return md_info->size;
-}
-
-mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info)
-{
-    if (md_info == NULL) {
-        return MBEDTLS_MD_NONE;
-    }
-
-    return md_info->type;
-}
-
 const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info)
 {
     if (md_info == NULL) {
@@ -842,3 +824,5 @@
 }
 
 #endif /* MBEDTLS_MD_C */
+
+#endif /* MBEDTLS_MD_LIGHT */
diff --git a/library/pem.c b/library/pem.c
index 8044ed6..9f14052 100644
--- a/library/pem.c
+++ b/library/pem.c
@@ -39,6 +39,13 @@
 #include "psa/crypto.h"
 #endif
 
+#if !defined(MBEDTLS_MD5_C)
+#include "mbedtls/psa_util.h"
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,          \
+                                                           psa_to_md_errors,                     \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
 #include "mbedtls/legacy_or_psa.h"
 
 #if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA) &&  \
@@ -236,7 +243,7 @@
 exit:
     mbedtls_platform_zeroize(md5sum, 16);
 
-    return mbedtls_md_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 }
 #endif /* MBEDTLS_MD5_C */
 
diff --git a/library/pk.c b/library/pk.c
index 05afdbc..5e18ad2 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -41,6 +41,13 @@
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
 #include "mbedtls/psa_util.h"
+#define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status)
+#define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,     \
+                                                                  psa_to_pk_rsa_errors,            \
+                                                                  psa_pk_status_to_mbedtls)
+#define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                                    psa_to_pk_ecdsa_errors,        \
+                                                                    psa_pk_status_to_mbedtls)
 #endif
 
 #include <limits.h>
@@ -540,7 +547,7 @@
                                 &key_id);
         if (status != PSA_SUCCESS) {
             psa_destroy_key(key_id);
-            return mbedtls_pk_error_from_psa(status);
+            return PSA_PK_TO_MBEDTLS_ERR(status);
         }
 
         /* This function requires returning MBEDTLS_ERR_PK_SIG_LEN_MISMATCH
@@ -562,7 +569,7 @@
             status = destruction_status;
         }
 
-        return mbedtls_pk_error_from_psa_rsa(status);
+        return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
     } else
 #endif
     {
@@ -700,7 +707,7 @@
         status = psa_sign_hash(*key, PSA_ALG_RSA_PSS(psa_md_alg),
                                hash, hash_len,
                                sig, sig_size, sig_len);
-        return mbedtls_pk_error_from_psa_rsa(status);
+        return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
     }
 
     return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg),
@@ -896,7 +903,7 @@
         /* import private key into PSA */
         status = psa_import_key(&attributes, d, d_len, key);
         if (status != PSA_SUCCESS) {
-            return mbedtls_pk_error_from_psa(status);
+            return PSA_PK_TO_MBEDTLS_ERR(status);
         }
 
         /* make PK context wrap the key slot */
@@ -936,7 +943,7 @@
         mbedtls_platform_zeroize(buf, sizeof(buf));
 
         if (status != PSA_SUCCESS) {
-            return mbedtls_pk_error_from_psa(status);
+            return PSA_PK_TO_MBEDTLS_ERR(status);
         }
 
         /* make PK context wrap the key slot */
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 45cf807..4d91f22 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -40,9 +40,19 @@
 #include "pkwrite.h"
 #endif
 
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+#include "mbedtls/psa_util.h"
+#define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status)
+#define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,     \
+                                                                  psa_to_pk_rsa_errors,            \
+                                                                  psa_pk_status_to_mbedtls)
+#define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                                    psa_to_pk_ecdsa_errors,        \
+                                                                    psa_pk_status_to_mbedtls)
+#endif
+
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
 #include "hash_info.h"
 
 #if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
@@ -57,6 +67,7 @@
 #include <stdint.h>
 #include <string.h>
 
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 #if defined(MBEDTLS_PSA_CRYPTO_C)
 int mbedtls_pk_error_from_psa(psa_status_t status)
 {
@@ -108,16 +119,31 @@
             return MBEDTLS_ERR_RSA_VERIFY_FAILED;
         case PSA_ERROR_INVALID_PADDING:
             return MBEDTLS_ERR_RSA_INVALID_PADDING;
+        case PSA_SUCCESS:
+            return 0;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+        case PSA_ERROR_INSUFFICIENT_MEMORY:
+            return MBEDTLS_ERR_PK_ALLOC_FAILED;
+        case PSA_ERROR_BAD_STATE:
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        case PSA_ERROR_COMMUNICATION_FAILURE:
+        case PSA_ERROR_HARDWARE_FAILURE:
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        case PSA_ERROR_DATA_CORRUPT:
+        case PSA_ERROR_DATA_INVALID:
+        case PSA_ERROR_STORAGE_FAILURE:
+            return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+        case PSA_ERROR_CORRUPTION_DETECTED:
+            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         default:
-            return mbedtls_pk_error_from_psa(status);
+            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
     }
 }
 #endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
-
 #endif /* MBEDTLS_PSA_CRYPTO_C */
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-
 #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
 int mbedtls_pk_error_from_psa_ecdsa(psa_status_t status)
 {
@@ -133,13 +159,30 @@
             return MBEDTLS_ERR_ECP_RANDOM_FAILED;
         case PSA_ERROR_INVALID_SIGNATURE:
             return MBEDTLS_ERR_ECP_VERIFY_FAILED;
+        case PSA_SUCCESS:
+            return 0;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+        case PSA_ERROR_INSUFFICIENT_MEMORY:
+            return MBEDTLS_ERR_PK_ALLOC_FAILED;
+        case PSA_ERROR_BAD_STATE:
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        case PSA_ERROR_COMMUNICATION_FAILURE:
+        case PSA_ERROR_HARDWARE_FAILURE:
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        case PSA_ERROR_DATA_CORRUPT:
+        case PSA_ERROR_DATA_INVALID:
+        case PSA_ERROR_STORAGE_FAILURE:
+            return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+        case PSA_ERROR_CORRUPTION_DETECTED:
+            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         default:
-            return mbedtls_pk_error_from_psa(status);
+            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
     }
 }
 #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
-
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
 #if defined(MBEDTLS_RSA_C)
 static int rsa_can_do(mbedtls_pk_type_t type)
@@ -196,14 +239,14 @@
                             buf + sizeof(buf) - key_len, key_len,
                             &key_id);
     if (status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa(status);
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
     status = psa_verify_hash(key_id, psa_alg_md, hash, hash_len,
                              sig, sig_len);
     if (status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa_rsa(status);
+        ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
     ret = 0;
@@ -211,7 +254,7 @@
 cleanup:
     status = psa_destroy_key(key_id);
     if (ret == 0 && status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa(status);
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
     }
 
     return ret;
@@ -289,13 +332,13 @@
                             buf + sizeof(buf) - key_len, key_len,
                             &key_id);
     if (status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa(status);
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
     status = psa_sign_hash(key_id, alg, hash, hash_len,
                            sig, sig_size, sig_len);
     if (status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa_rsa(status);
+        ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
@@ -304,7 +347,7 @@
 cleanup:
     status = psa_destroy_key(key_id);
     if (ret == 0 && status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa(status);
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
     }
     return ret;
 }
@@ -398,7 +441,7 @@
                             buf + sizeof(buf) - key_len, key_len,
                             &key_id);
     if (status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa(status);
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
@@ -407,7 +450,7 @@
                                     NULL, 0,
                                     output, osize, olen);
     if (status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa_rsa(status);
+        ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
@@ -417,7 +460,7 @@
     mbedtls_platform_zeroize(buf, sizeof(buf));
     status = psa_destroy_key(key_id);
     if (ret == 0 && status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa(status);
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
     }
 
     return ret;
@@ -484,7 +527,7 @@
                             buf + sizeof(buf) - key_len, key_len,
                             &key_id);
     if (status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa(status);
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
@@ -493,7 +536,7 @@
                                     NULL, 0,
                                     output, osize, olen);
     if (status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa_rsa(status);
+        ret = PSA_PK_RSA_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
@@ -502,7 +545,7 @@
 cleanup:
     status = psa_destroy_key(key_id);
     if (ret == 0 && status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa(status);
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
     }
 
     return ret;
@@ -716,7 +759,7 @@
                             buf, key_len,
                             &key_id);
     if (status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa(status);
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
@@ -737,7 +780,7 @@
                              hash, hash_len,
                              buf, 2 * signature_part_size);
     if (status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa_ecdsa(status);
+        ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
@@ -750,7 +793,7 @@
 cleanup:
     status = psa_destroy_key(key_id);
     if (ret == 0 && status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa(status);
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
     }
 
     return ret;
@@ -908,14 +951,14 @@
                             buf, key_len,
                             &key_id);
     if (status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa(status);
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
     status = psa_sign_hash(key_id, psa_sig_md, hash, hash_len,
                            sig, sig_size, sig_len);
     if (status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa_ecdsa(status);
+        ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
@@ -925,7 +968,7 @@
     mbedtls_platform_zeroize(buf, sizeof(buf));
     status = psa_destroy_key(key_id);
     if (ret == 0 && status != PSA_SUCCESS) {
-        ret = mbedtls_pk_error_from_psa(status);
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
     }
 
     return ret;
@@ -1448,7 +1491,7 @@
 
     status = psa_get_key_attributes(*key, &attributes);
     if (status != PSA_SUCCESS) {
-        return mbedtls_pk_error_from_psa(status);
+        return PSA_PK_TO_MBEDTLS_ERR(status);
     }
 
     type = psa_get_key_type(&attributes);
@@ -1472,15 +1515,15 @@
     if (status != PSA_SUCCESS) {
 #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
         if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
-            return mbedtls_pk_error_from_psa_ecdsa(status);
+            return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
         } else
 #endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
 #if defined(MBEDTLS_RSA_C)
         if (PSA_KEY_TYPE_IS_RSA(type)) {
-            return mbedtls_pk_error_from_psa_rsa(status);
+            return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
         } else
 #endif /* MBEDTLS_RSA_C */
-        return mbedtls_pk_error_from_psa(status);
+        return PSA_PK_TO_MBEDTLS_ERR(status);
     }
 
 #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
@@ -1535,7 +1578,7 @@
                                     NULL, 0,
                                     output, osize, olen);
     if (status != PSA_SUCCESS) {
-        return mbedtls_pk_error_from_psa_rsa(status);
+        return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
     }
 
     return 0;
diff --git a/library/pk_wrap.h b/library/pk_wrap.h
index 7df9608..c5cd4df 100644
--- a/library/pk_wrap.h
+++ b/library/pk_wrap.h
@@ -137,26 +137,30 @@
 extern const mbedtls_pk_info_t mbedtls_pk_ecdsa_opaque_info;
 extern const mbedtls_pk_info_t mbedtls_pk_rsa_opaque_info;
 
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 #if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
-int mbedtls_pk_error_from_psa_ecdsa(psa_status_t status);
+int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa_ecdsa(psa_status_t status);
+#endif
 #endif
 
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
-int mbedtls_pk_error_from_psa(psa_status_t status);
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa(psa_status_t status);
 
 #if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \
     defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
-int mbedtls_pk_error_from_psa_rsa(psa_status_t status);
+int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa_rsa(psa_status_t status);
 #endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
 
 #if defined(MBEDTLS_RSA_C)
-int  mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md,
-                                 mbedtls_rsa_context *rsa_ctx,
-                                 const unsigned char *hash, size_t hash_len,
-                                 unsigned char *sig, size_t sig_size,
-                                 size_t *sig_len);
+int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md,
+                                mbedtls_rsa_context *rsa_ctx,
+                                const unsigned char *hash, size_t hash_len,
+                                unsigned char *sig, size_t sig_size,
+                                size_t *sig_len);
 #endif /* MBEDTLS_RSA_C */
 
 #endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/library/pkcs12.c b/library/pkcs12.c
index f5ab742..8521483 100644
--- a/library/pkcs12.c
+++ b/library/pkcs12.c
@@ -35,6 +35,13 @@
 
 #include <string.h>
 
+#if !defined(MBEDTLS_MD_C)
+#include "mbedtls/psa_util.h"
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_md_errors,              \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
 #if defined(MBEDTLS_DES_C)
 #include "mbedtls/des.h"
 #endif
@@ -328,7 +335,7 @@
     if (status == PSA_SUCCESS) {
         status = status_abort;
     }
-    return mbedtls_md_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 #endif /* !MBEDTLS_MD_C */
 }
 
diff --git a/library/pkcs5.c b/library/pkcs5.c
index 4e71dd3..f471b63 100644
--- a/library/pkcs5.c
+++ b/library/pkcs5.c
@@ -47,6 +47,12 @@
 #include "hash_info.h"
 #include "mbedtls/psa_util.h"
 
+#if !defined(MBEDTLS_MD_C)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_md_errors,              \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
 #if defined(MBEDTLS_ASN1_PARSE_C)
 static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
                                      mbedtls_asn1_buf *salt, int *iterations,
@@ -452,7 +458,7 @@
         status = status_destruction;
     }
 
-    return mbedtls_md_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 #endif /* !MBEDTLS_MD_C */
 }
 
diff --git a/library/platform_util.c b/library/platform_util.c
index f935b90..6d4759c 100644
--- a/library/platform_util.c
+++ b/library/platform_util.c
@@ -20,12 +20,18 @@
 
 /*
  * Ensure gmtime_r is available even with -std=c99; must be defined before
- * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms.
+ * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms
+ * except OpenBSD, where it stops us accessing explicit_bzero.
  */
-#if !defined(_POSIX_C_SOURCE)
+#if !defined(_POSIX_C_SOURCE) && !defined(__OpenBSD__)
 #define _POSIX_C_SOURCE 200112L
 #endif
 
+#if !defined(_GNU_SOURCE)
+/* Clang requires this to get support for explicit_bzero */
+#define _GNU_SOURCE
+#endif
+
 #include "common.h"
 
 #include "mbedtls/platform_util.h"
@@ -33,11 +39,31 @@
 #include "mbedtls/threading.h"
 
 #include <stddef.h>
+
+#ifndef __STDC_WANT_LIB_EXT1__
+#define __STDC_WANT_LIB_EXT1__ 1 /* Ask for the C11 gmtime_s() and memset_s() if available */
+#endif
 #include <string.h>
 
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
+// Detect platforms known to support explicit_bzero()
+#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
+#define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1
+#elif (defined(__FreeBSD__) && (__FreeBSD_version >= 1100037)) || defined(__OpenBSD__)
+#define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1
+#endif
+
 #if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT)
 /*
- * This implementation should never be optimized out by the compiler
+ * Where possible, we try to detect the presence of a platform-provided
+ * secure memset, such as explicit_bzero(), that is safe against being optimized
+ * out, and use that.
+ *
+ * For other platforms, we provide an implementation that aims not to be
+ * optimized out by the compiler.
  *
  * This implementation for mbedtls_platform_zeroize() was inspired from Colin
  * Percival's blog article at:
@@ -52,30 +78,40 @@
  * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for
  * details), optimizations of the following form are still possible:
  *
- * if( memset_func != memset )
- *     memset_func( buf, 0, len );
+ * if (memset_func != memset)
+ *     memset_func(buf, 0, len);
  *
  * Note that it is extremely difficult to guarantee that
- * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers
+ * the memset() call will not be optimized out by aggressive compilers
  * in a portable way. For this reason, Mbed TLS also provides the configuration
  * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure
  * mbedtls_platform_zeroize() to use a suitable implementation for their
  * platform and needs.
  */
+#if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !defined(__STDC_LIB_EXT1__) \
+    && !defined(_WIN32)
 static void *(*const volatile memset_func)(void *, int, size_t) = memset;
+#endif
 
 void mbedtls_platform_zeroize(void *buf, size_t len)
 {
     MBEDTLS_INTERNAL_VALIDATE(len == 0 || buf != NULL);
 
     if (len > 0) {
+#if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO)
+        explicit_bzero(buf, len);
+#elif defined(__STDC_LIB_EXT1__)
+        memset_s(buf, len, 0, len);
+#elif defined(_WIN32)
+        SecureZeroMemory(buf, len);
+#else
         memset_func(buf, 0, len);
+#endif
     }
 }
 #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
 
 #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
-#define __STDC_WANT_LIB_EXT1__ 1  /* Ask for the C11 gmtime_s() if it's available */
 #include <time.h>
 #if !defined(_WIN32) && (defined(unix) || \
     defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
diff --git a/library/psa_util.c b/library/psa_util.c
new file mode 100644
index 0000000..fefeea5
--- /dev/null
+++ b/library/psa_util.c
@@ -0,0 +1,150 @@
+/*
+ *  PSA hashing layer on top of Mbed TLS software crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <psa/crypto.h>
+
+#include "psa_crypto_core.h"
+#include <mbedtls/psa_util.h>
+#include <mbedtls/error.h>
+#include <mbedtls/lms.h>
+#include <mbedtls/ssl.h>
+#include <mbedtls/rsa.h>
+
+/* PSA_SUCCESS is kept at the top of each error table since
+ * it's the most common status when everything functions properly. */
+#if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_MD5_C) || defined(MBEDTLS_USE_PSA_CRYPTO)
+const mbedtls_error_pair_t psa_to_md_errors[] =
+{
+    { PSA_SUCCESS,                     0 },
+    { PSA_ERROR_NOT_SUPPORTED,         MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE },
+    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_MD_BAD_INPUT_DATA },
+    { PSA_ERROR_INSUFFICIENT_MEMORY,   MBEDTLS_ERR_MD_ALLOC_FAILED }
+};
+#endif
+#if defined(MBEDTLS_LMS_C)
+const mbedtls_error_pair_t psa_to_lms_errors[] =
+{
+    { PSA_SUCCESS,                     0 },
+    { PSA_ERROR_BUFFER_TOO_SMALL,      MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL },
+    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_LMS_BAD_INPUT_DATA }
+};
+#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
+const mbedtls_error_pair_t psa_to_ssl_errors[] =
+{
+    { PSA_SUCCESS,                     0 },
+    { PSA_ERROR_INSUFFICIENT_MEMORY,   MBEDTLS_ERR_SSL_ALLOC_FAILED },
+    { PSA_ERROR_NOT_SUPPORTED,         MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE },
+    { PSA_ERROR_INVALID_SIGNATURE,     MBEDTLS_ERR_SSL_INVALID_MAC },
+    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_SSL_BAD_INPUT_DATA },
+    { PSA_ERROR_BAD_STATE,             MBEDTLS_ERR_SSL_INTERNAL_ERROR },
+    { PSA_ERROR_BUFFER_TOO_SMALL,      MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL }
+};
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
+const mbedtls_error_pair_t psa_to_pk_rsa_errors[] =
+{
+    { PSA_SUCCESS,                     0 },
+    { PSA_ERROR_NOT_PERMITTED,         MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
+    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
+    { PSA_ERROR_INVALID_HANDLE,        MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
+    { PSA_ERROR_BUFFER_TOO_SMALL,      MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE },
+    { PSA_ERROR_INSUFFICIENT_ENTROPY,  MBEDTLS_ERR_RSA_RNG_FAILED },
+    { PSA_ERROR_INVALID_SIGNATURE,     MBEDTLS_ERR_RSA_VERIFY_FAILED },
+    { PSA_ERROR_INVALID_PADDING,       MBEDTLS_ERR_RSA_INVALID_PADDING }
+};
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[] =
+{
+    { PSA_SUCCESS,                     0 },
+    { PSA_ERROR_NOT_PERMITTED,         MBEDTLS_ERR_ECP_BAD_INPUT_DATA },
+    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_ECP_BAD_INPUT_DATA },
+    { PSA_ERROR_INVALID_HANDLE,        MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE },
+    { PSA_ERROR_BUFFER_TOO_SMALL,      MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL },
+    { PSA_ERROR_INSUFFICIENT_ENTROPY,  MBEDTLS_ERR_ECP_RANDOM_FAILED },
+    { PSA_ERROR_INVALID_SIGNATURE,     MBEDTLS_ERR_ECP_VERIFY_FAILED }
+};
+#endif
+
+int psa_generic_status_to_mbedtls(psa_status_t status)
+{
+    switch (status) {
+        case PSA_SUCCESS:
+            return 0;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
+        case PSA_ERROR_CORRUPTION_DETECTED:
+            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        case PSA_ERROR_COMMUNICATION_FAILURE:
+        case PSA_ERROR_HARDWARE_FAILURE:
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        case PSA_ERROR_NOT_PERMITTED:
+        default:
+            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
+    }
+}
+
+int psa_status_to_mbedtls(psa_status_t status,
+                          const mbedtls_error_pair_t *local_translations,
+                          size_t local_errors_size,
+                          int (*fallback_f)(psa_status_t))
+{
+    size_t local_errors_num = (size_t) local_errors_size / 2;
+    for (size_t i = 0; i < local_errors_num; i++) {
+        if (status == local_translations[i].psa_status) {
+            return local_translations[i].mbedtls_error;
+        }
+    }
+    return fallback_f(status);
+}
+
+int psa_pk_status_to_mbedtls(psa_status_t status)
+{
+    switch (status) {
+        case PSA_ERROR_INVALID_HANDLE:
+            return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+        case PSA_ERROR_BUFFER_TOO_SMALL:
+            return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+        case PSA_ERROR_INVALID_ARGUMENT:
+            return MBEDTLS_ERR_PK_INVALID_ALG;
+        case PSA_ERROR_INSUFFICIENT_MEMORY:
+            return MBEDTLS_ERR_PK_ALLOC_FAILED;
+        case PSA_ERROR_BAD_STATE:
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        case PSA_ERROR_DATA_CORRUPT:
+        case PSA_ERROR_DATA_INVALID:
+        case PSA_ERROR_STORAGE_FAILURE:
+            return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+        default:
+            return psa_generic_status_to_mbedtls(status);
+    }
+}
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/library/rsa.c b/library/rsa.c
index df7d797..7159588 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -60,7 +60,10 @@
 #if !defined(MBEDTLS_MD_C)
 #include "psa/crypto.h"
 #include "mbedtls/psa_util.h"
-#endif /* MBEDTLS_MD_C */
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_md_errors,              \
+                                                           psa_generic_status_to_mbedtls)
+#endif /* !MBEDTLS_MD_C */
 #endif /* MBEDTLS_PKCS1_V21 */
 
 #include "mbedtls/platform.h"
@@ -1156,7 +1159,7 @@
 #else
     psa_hash_abort(&op);
 
-    return mbedtls_md_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 #endif
 }
 
@@ -1236,7 +1239,7 @@
 exit:
     psa_hash_abort(&op);
 
-    return mbedtls_md_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 #endif /* !MBEDTLS_MD_C */
 }
 
@@ -1269,7 +1272,7 @@
 
     status = psa_hash_compute(alg, input, ilen, output, out_size, &out_len);
 
-    return mbedtls_md_error_from_psa(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 #endif /* !MBEDTLS_MD_C */
 }
 #endif /* MBEDTLS_PKCS1_V21 */
diff --git a/library/sha256.c b/library/sha256.c
index cb09a71..23cd406 100644
--- a/library/sha256.c
+++ b/library/sha256.c
@@ -22,6 +22,23 @@
  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
  */
 
+#if defined(__aarch64__) && !defined(__ARM_FEATURE_CRYPTO) && \
+    defined(__clang__) &&  __clang_major__ < 18 && __clang_major__ > 3
+/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.
+ *
+ * The intrinsic declaration are guarded by predefined ACLE macros in clang:
+ * these are normally only enabled by the -march option on the command line.
+ * By defining the macros ourselves we gain access to those declarations without
+ * requiring -march on the command line.
+ *
+ * `arm_neon.h` could be included by any header file, so we put these defines
+ * at the top of this file, before any includes.
+ */
+#define __ARM_FEATURE_CRYPTO 1
+#define NEED_TARGET_OPTIONS
+#endif /* __aarch64__ && __clang__ &&
+          !__ARM_FEATURE_CRYPTO && __clang_major__ < 18 && __clang_major__ > 3 */
+
 #include "common.h"
 
 #if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C)
@@ -37,6 +54,30 @@
 #if defined(__aarch64__)
 #  if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
     defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+/* *INDENT-OFF* */
+#    if !defined(__ARM_FEATURE_CRYPTO) || defined(NEED_TARGET_OPTIONS)
+#      if defined(__clang__)
+#        if __clang_major__ < 4
+#          error "A more recent Clang is required for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
+#        endif
+#        pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function)
+#        define MBEDTLS_POP_TARGET_PRAGMA
+#      elif defined(__GNUC__)
+         /* FIXME: GCC-5 annouce crypto extension, but some intrinsic are missed.
+          *        Known miss intrinsic can be workaround.
+          */
+#        if __GNUC__ < 6
+#          error "A more recent GCC is required for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
+#        else
+#          pragma GCC push_options
+#          pragma GCC target ("arch=armv8-a+crypto")
+#          define MBEDTLS_POP_TARGET_PRAGMA
+#        endif
+#      else
+#        error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
+#      endif
+#    endif
+/* *INDENT-ON* */
 #    include <arm_neon.h>
 #  endif
 #  if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
@@ -353,8 +394,16 @@
             SHA256_BLOCK_SIZE) ? 0 : -1;
 }
 
-#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
+#if defined(MBEDTLS_POP_TARGET_PRAGMA)
+#if defined(__clang__)
+#pragma clang attribute pop
+#elif defined(__GNUC__)
+#pragma GCC pop_options
+#endif
+#undef MBEDTLS_POP_TARGET_PRAGMA
+#endif
 
+#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
 
 #if !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
 #define mbedtls_internal_sha256_process_many_c mbedtls_internal_sha256_process_many
diff --git a/library/sha512.c b/library/sha512.c
index efcbed4..bc92a8d 100644
--- a/library/sha512.c
+++ b/library/sha512.c
@@ -22,6 +22,26 @@
  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
  */
 
+#if defined(__aarch64__) && !defined(__ARM_FEATURE_SHA512) && \
+    defined(__clang__) &&  __clang_major__ < 18 && \
+    __clang_major__ >= 13 && __clang_minor__ > 0 && __clang_patchlevel__ > 0
+/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.
+ *
+ * The intrinsic declaration are guarded by predefined ACLE macros in clang:
+ * these are normally only enabled by the -march option on the command line.
+ * By defining the macros ourselves we gain access to those declarations without
+ * requiring -march on the command line.
+ *
+ * `arm_neon.h` could be included by any header file, so we put these defines
+ * at the top of this file, before any includes.
+ */
+#define __ARM_FEATURE_SHA512 1
+#define NEED_TARGET_OPTIONS
+#endif /* __aarch64__ && __clang__ &&
+          !__ARM_FEATURE_SHA512 && __clang_major__ < 18 &&
+          __clang_major__ >= 13 && __clang_minor__ > 0 &&
+          __clang_patchlevel__ > 0 */
+
 #include "common.h"
 
 #if defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA384_C)
@@ -43,6 +63,47 @@
 #if defined(__aarch64__)
 #  if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
     defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
+/* *INDENT-OFF* */
+/*
+ * Best performance comes from most recent compilers, with intrinsics and -O3.
+ * Must compile with -march=armv8.2-a+sha3, but we can't detect armv8.2-a, and
+ * can't always detect __ARM_FEATURE_SHA512 (notably clang 7-12).
+ *
+ * GCC < 8 won't work at all (lacks the sha512 instructions)
+ * GCC >= 8 uses intrinsics, sets __ARM_FEATURE_SHA512
+ *
+ * Clang < 7 won't work at all (lacks the sha512 instructions)
+ * Clang 7-12 don't have intrinsics (but we work around that with inline
+ *            assembler) or __ARM_FEATURE_SHA512
+ * Clang == 13.0.0 same as clang 12 (only seen on macOS)
+ * Clang >= 13.0.1 has __ARM_FEATURE_SHA512 and intrinsics
+ */
+#    if !defined(__ARM_FEATURE_SHA512) || defined(NEED_TARGET_OPTIONS)
+       /* Test Clang first, as it defines __GNUC__ */
+#      if defined(__clang__)
+#        if __clang_major__ < 7
+#          error "A more recent Clang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
+#        elif __clang_major__ < 13 || \
+              (__clang_major__ == 13 && __clang_minor__ == 0 && \
+               __clang_patchlevel__ == 0)
+           /* We implement the intrinsics with inline assembler, so don't error */
+#        else
+#          pragma clang attribute push (__attribute__((target("sha3"))), apply_to=function)
+#          define MBEDTLS_POP_TARGET_PRAGMA
+#        endif
+#      elif defined(__GNUC__)
+#        if __GNUC__ < 8
+#          error "A more recent GCC is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
+#        else
+#          pragma GCC push_options
+#          pragma GCC target ("arch=armv8.2-a+sha3")
+#          define MBEDTLS_POP_TARGET_PRAGMA
+#        endif
+#      else
+#        error "Only GCC and Clang supported for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
+#      endif
+#    endif
+/* *INDENT-ON* */
 #    include <arm_neon.h>
 #  endif
 #  if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
@@ -516,6 +577,15 @@
             SHA512_BLOCK_SIZE) ? 0 : -1;
 }
 
+#if defined(MBEDTLS_POP_TARGET_PRAGMA)
+#if defined(__clang__)
+#pragma clang attribute pop
+#elif defined(__GNUC__)
+#pragma GCC pop_options
+#endif
+#undef MBEDTLS_POP_TARGET_PRAGMA
+#endif
+
 #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
 
 
diff --git a/library/ssl_cookie.c b/library/ssl_cookie.c
index b7eead4..ef4d188 100644
--- a/library/ssl_cookie.c
+++ b/library/ssl_cookie.c
@@ -37,6 +37,12 @@
 
 #include <string.h>
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
 /*
  * If DTLS is in use, then at least one of SHA-256 or SHA-384 is
  * available. Try SHA-256 first as 384 wastes resources
@@ -126,7 +132,7 @@
 
     if ((status = psa_generate_key(&attributes,
                                    &ctx->psa_hmac_key)) != PSA_SUCCESS) {
-        return psa_ssl_status_to_mbedtls(status);
+        return PSA_TO_MBEDTLS_ERR(status);
     }
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -215,26 +221,26 @@
     status = psa_mac_sign_setup(&operation, ctx->psa_hmac_key,
                                 ctx->psa_hmac_alg);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         goto exit;
     }
 
     status = psa_mac_update(&operation, *p - 4, 4);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         goto exit;
     }
 
     status = psa_mac_update(&operation, cli_id, cli_id_len);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         goto exit;
     }
 
     status = psa_mac_sign_finish(&operation, *p, COOKIE_MD_OUTLEN,
                                  &sign_mac_length);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         goto exit;
     }
 
@@ -263,7 +269,7 @@
 exit:
     status = psa_mac_abort(&operation);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
     return ret;
@@ -299,27 +305,27 @@
     status = psa_mac_verify_setup(&operation, ctx->psa_hmac_key,
                                   ctx->psa_hmac_alg);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         goto exit;
     }
 
     status = psa_mac_update(&operation, cookie, 4);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         goto exit;
     }
 
     status = psa_mac_update(&operation, cli_id,
                             cli_id_len);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         goto exit;
     }
 
     status = psa_mac_verify_finish(&operation, cookie + 4,
                                    COOKIE_HMAC_LEN);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         goto exit;
     }
 
@@ -374,7 +380,7 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     status = psa_mac_abort(&operation);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
     }
 #else
     mbedtls_platform_zeroize(ref_hmac, sizeof(ref_hmac));
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 7385c6e..9f7ed15 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -905,14 +905,14 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_hash_operation_t fin_sha256_psa;
 #else
-    mbedtls_sha256_context fin_sha256;
+    mbedtls_md_context_t fin_sha256;
 #endif
 #endif
 #if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_hash_operation_t fin_sha384_psa;
 #else
-    mbedtls_sha512_context fin_sha384;
+    mbedtls_md_context_t fin_sha384;
 #endif
 #endif
 
@@ -2514,6 +2514,7 @@
                                        psa_key_type_t *key_type,
                                        size_t *key_size);
 
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 /**
  * \brief       Convert given PSA status to mbedtls error code.
  *
@@ -2521,7 +2522,7 @@
  *
  * \return             corresponding mbedtls error code
  */
-static inline int psa_ssl_status_to_mbedtls(psa_status_t status)
+static inline MBEDTLS_DEPRECATED int psa_ssl_status_to_mbedtls(psa_status_t status)
 {
     switch (status) {
         case PSA_SUCCESS:
@@ -2542,6 +2543,7 @@
             return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
     }
 }
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
 #endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index d26d950..1cad588 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -48,6 +48,12 @@
 #include "mbedtls/oid.h"
 #endif
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
 static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl);
 
 /*
@@ -879,10 +885,10 @@
 hmac_failed_etm_disabled:
         mbedtls_platform_zeroize(mac, transform->maclen);
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         status = psa_mac_abort(&operation);
         if (ret == 0 && status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
         }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
         if (ret != 0) {
@@ -979,7 +985,7 @@
                                   &rec->data_len);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_encrypt_buf", ret);
             return ret;
         }
@@ -1089,7 +1095,7 @@
                                           transform->psa_key_enc, transform->psa_alg);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_encrypt_setup", ret);
             return ret;
         }
@@ -1097,7 +1103,7 @@
         status = psa_cipher_set_iv(&cipher_op, transform->iv_enc, transform->ivlen);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_set_iv", ret);
             return ret;
 
@@ -1108,7 +1114,7 @@
                                    data, rec->data_len, &olen);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_update", ret);
             return ret;
 
@@ -1119,7 +1125,7 @@
                                    &part_len);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_finish", ret);
             return ret;
 
@@ -1222,10 +1228,10 @@
 hmac_failed_etm_enabled:
             mbedtls_platform_zeroize(mac, transform->maclen);
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             status = psa_mac_abort(&operation);
             if (ret == 0 && status != PSA_SUCCESS) {
-                ret = psa_ssl_status_to_mbedtls(status);
+                ret = PSA_TO_MBEDTLS_ERR(status);
             }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
             if (ret != 0) {
@@ -1399,7 +1405,7 @@
                                   &olen);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_aead_decrypt", ret);
             return ret;
         }
@@ -1571,10 +1577,10 @@
 
 hmac_failed_etm_enabled:
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             status = psa_mac_abort(&operation);
             if (ret == 0 && status != PSA_SUCCESS) {
-                ret = psa_ssl_status_to_mbedtls(status);
+                ret = PSA_TO_MBEDTLS_ERR(status);
             }
 #else
             mbedtls_platform_zeroize(mac_expect, transform->maclen);
@@ -1621,7 +1627,7 @@
                                           transform->psa_key_dec, transform->psa_alg);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_decrypt_setup", ret);
             return ret;
         }
@@ -1629,7 +1635,7 @@
         status = psa_cipher_set_iv(&cipher_op, transform->iv_dec, transform->ivlen);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_set_iv", ret);
             return ret;
         }
@@ -1639,7 +1645,7 @@
                                    data, rec->data_len, &olen);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_update", ret);
             return ret;
         }
@@ -1649,7 +1655,7 @@
                                    &part_len);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_cipher_finish", ret);
             return ret;
         }
diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c
index ba9dbd5..7d07d19 100644
--- a/library/ssl_ticket.c
+++ b/library/ssl_ticket.c
@@ -30,6 +30,12 @@
 
 #include <string.h>
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
 /*
  * Initialize context
  */
@@ -91,7 +97,7 @@
     psa_set_key_type(&attributes, key->key_type);
     psa_set_key_bits(&attributes, key->key_bits);
 
-    ret = psa_ssl_status_to_mbedtls(
+    ret = PSA_TO_MBEDTLS_ERR(
         psa_import_key(&attributes, buf,
                        PSA_BITS_TO_BYTES(key->key_bits),
                        &key->key));
@@ -133,7 +139,7 @@
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
         if ((status = psa_destroy_key(ctx->keys[ctx->active].key)) != PSA_SUCCESS) {
-            return psa_ssl_status_to_mbedtls(status);
+            return PSA_TO_MBEDTLS_ERR(status);
         }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
@@ -169,7 +175,7 @@
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     if ((status = psa_destroy_key(key->key)) != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         return ret;
     }
 
@@ -182,7 +188,7 @@
     if ((status = psa_import_key(&attributes, k,
                                  PSA_BITS_TO_BYTES(key->key_bits),
                                  &key->key)) != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         return ret;
     }
 #else
@@ -355,7 +361,7 @@
                                    state, clear_len,
                                    state, end - state,
                                    &ciph_len)) != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 #else
@@ -465,7 +471,7 @@
                                    key_name, TICKET_ADD_DATA_LEN,
                                    ticket, enc_len + TICKET_AUTH_TAG_BYTES,
                                    ticket, enc_len, &clear_len)) != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 #else
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 441089f..19bd127 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -52,6 +52,15 @@
 #include "mbedtls/oid.h"
 #endif
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
+                                                           psa_to_ssl_errors, \
+                                                           psa_generic_status_to_mbedtls)
+#define PSA_TO_MD_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
+                                                      psa_to_md_errors, \
+                                                      psa_generic_status_to_mbedtls)
+#endif
+
 #if defined(MBEDTLS_TEST_HOOKS)
 static mbedtls_ssl_chk_buf_ptr_args chk_buf_ptr_fail_args;
 
@@ -832,14 +841,22 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     status = psa_hash_abort(&ssl->handshake->fin_sha256_psa);
     if (status != PSA_SUCCESS) {
-        return mbedtls_md_error_from_psa(status);
+        return PSA_TO_MD_ERR(status);
     }
     status = psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256);
     if (status != PSA_SUCCESS) {
-        return mbedtls_md_error_from_psa(status);
+        return PSA_TO_MD_ERR(status);
     }
 #else
-    ret = mbedtls_sha256_starts(&ssl->handshake->fin_sha256, 0);
+    mbedtls_md_free(&ssl->handshake->fin_sha256);
+    mbedtls_md_init(&ssl->handshake->fin_sha256);
+    ret = mbedtls_md_setup(&ssl->handshake->fin_sha256,
+                           mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
+                           0);
+    if (ret != 0) {
+        return ret;
+    }
+    ret = mbedtls_md_starts(&ssl->handshake->fin_sha256);
     if (ret != 0) {
         return ret;
     }
@@ -849,14 +866,21 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     status = psa_hash_abort(&ssl->handshake->fin_sha384_psa);
     if (status != PSA_SUCCESS) {
-        return mbedtls_md_error_from_psa(status);
+        return PSA_TO_MD_ERR(status);
     }
     status = psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384);
     if (status != PSA_SUCCESS) {
-        return mbedtls_md_error_from_psa(status);
+        return PSA_TO_MD_ERR(status);
     }
 #else
-    ret = mbedtls_sha512_starts(&ssl->handshake->fin_sha384, 1);
+    mbedtls_md_free(&ssl->handshake->fin_sha384);
+    mbedtls_md_init(&ssl->handshake->fin_sha384);
+    ret = mbedtls_md_setup(&ssl->handshake->fin_sha384,
+                           mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);
+    if (ret != 0) {
+        return ret;
+    }
+    ret = mbedtls_md_starts(&ssl->handshake->fin_sha384);
     if (ret != 0) {
         return ret;
     }
@@ -884,10 +908,10 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     status = psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len);
     if (status != PSA_SUCCESS) {
-        return mbedtls_md_error_from_psa(status);
+        return PSA_TO_MD_ERR(status);
     }
 #else
-    ret = mbedtls_sha256_update(&ssl->handshake->fin_sha256, buf, len);
+    ret = mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len);
     if (ret != 0) {
         return ret;
     }
@@ -897,10 +921,10 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     status = psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len);
     if (status != PSA_SUCCESS) {
-        return mbedtls_md_error_from_psa(status);
+        return PSA_TO_MD_ERR(status);
     }
 #else
-    ret = mbedtls_sha512_update(&ssl->handshake->fin_sha384, buf, len);
+    ret = mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len);
     if (ret != 0) {
         return ret;
     }
@@ -914,10 +938,10 @@
                                       const unsigned char *buf, size_t len)
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    return mbedtls_md_error_from_psa(psa_hash_update(
-                                         &ssl->handshake->fin_sha256_psa, buf, len));
+    return PSA_TO_MD_ERR(psa_hash_update(
+                             &ssl->handshake->fin_sha256_psa, buf, len));
 #else
-    return mbedtls_sha256_update(&ssl->handshake->fin_sha256, buf, len);
+    return mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len);
 #endif
 }
 #endif
@@ -927,10 +951,10 @@
                                       const unsigned char *buf, size_t len)
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    return mbedtls_md_error_from_psa(psa_hash_update(
-                                         &ssl->handshake->fin_sha384_psa, buf, len));
+    return PSA_TO_MD_ERR(psa_hash_update(
+                             &ssl->handshake->fin_sha384_psa, buf, len));
 #else
-    return mbedtls_sha512_update(&ssl->handshake->fin_sha384, buf, len);
+    return mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len);
 #endif
 }
 #endif
@@ -943,14 +967,14 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     handshake->fin_sha256_psa = psa_hash_operation_init();
 #else
-    mbedtls_sha256_init(&handshake->fin_sha256);
+    mbedtls_md_init(&handshake->fin_sha256);
 #endif
 #endif
 #if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     handshake->fin_sha384_psa = psa_hash_operation_init();
 #else
-    mbedtls_sha512_init(&handshake->fin_sha384);
+    mbedtls_md_init(&handshake->fin_sha384);
 #endif
 #endif
 
@@ -4081,14 +4105,14 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_hash_abort(&handshake->fin_sha256_psa);
 #else
-    mbedtls_sha256_free(&handshake->fin_sha256);
+    mbedtls_md_free(&handshake->fin_sha256);
 #endif
 #endif
 #if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_hash_abort(&handshake->fin_sha384_psa);
 #else
-    mbedtls_sha512_free(&handshake->fin_sha384);
+    mbedtls_md_free(&handshake->fin_sha384);
 #endif
 #endif
 
@@ -5759,7 +5783,7 @@
     !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
     (void) ssl;
 #endif
-    return psa_ssl_status_to_mbedtls(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 }
 #else /* MBEDTLS_USE_PSA_CRYPTO */
 
@@ -5771,17 +5795,24 @@
                                                size_t *olen)
 {
     int ret;
-    mbedtls_sha512_context sha512;
+    mbedtls_md_context_t sha384;
 
     if (dst_len < 48) {
         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    mbedtls_sha512_init(&sha512);
-    mbedtls_sha512_clone(&sha512, &ssl->handshake->fin_sha384);
+    mbedtls_md_init(&sha384);
+    ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384);
+    if (ret != 0) {
+        goto exit;
+    }
 
-    if ((ret = mbedtls_sha512_finish(&sha512, dst)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_sha512_finish", ret);
+    if ((ret = mbedtls_md_finish(&sha384, dst)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret);
         goto exit;
     }
 
@@ -5789,7 +5820,7 @@
 
 exit:
 
-    mbedtls_sha512_free(&sha512);
+    mbedtls_md_free(&sha384);
     return ret;
 }
 #endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
@@ -5802,17 +5833,24 @@
                                                size_t *olen)
 {
     int ret;
-    mbedtls_sha256_context sha256;
+    mbedtls_md_context_t sha256;
 
     if (dst_len < 32) {
         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    mbedtls_sha256_init(&sha256);
-    mbedtls_sha256_clone(&sha256, &ssl->handshake->fin_sha256);
+    mbedtls_md_init(&sha256);
+    ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256);
+    if (ret != 0) {
+        goto exit;
+    }
 
-    if ((ret = mbedtls_sha256_finish(&sha256, dst)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_sha256_finish", ret);
+    if ((ret = mbedtls_md_finish(&sha256, dst)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret);
         goto exit;
     }
 
@@ -5820,7 +5858,7 @@
 
 exit:
 
-    mbedtls_sha256_free(&sha256);
+    mbedtls_md_free(&sha256);
     return ret;
 }
 #endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
@@ -6600,18 +6638,25 @@
 
 exit:
     psa_hash_abort(&sha256_psa);
-    return mbedtls_md_error_from_psa(status);
+    return PSA_TO_MD_ERR(status);
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_sha256_context sha256;
+    mbedtls_md_context_t sha256;
 
-    mbedtls_sha256_init(&sha256);
+    mbedtls_md_init(&sha256);
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify sha256"));
 
-    mbedtls_sha256_clone(&sha256, &ssl->handshake->fin_sha256);
+    ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256);
+    if (ret != 0) {
+        goto exit;
+    }
 
-    ret = mbedtls_sha256_finish(&sha256, hash);
+    ret = mbedtls_md_finish(&sha256, hash);
     if (ret != 0) {
         goto exit;
     }
@@ -6622,7 +6667,7 @@
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify"));
 
 exit:
-    mbedtls_sha256_free(&sha256);
+    mbedtls_md_free(&sha256);
     return ret;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 }
@@ -6655,18 +6700,25 @@
 
 exit:
     psa_hash_abort(&sha384_psa);
-    return mbedtls_md_error_from_psa(status);
+    return PSA_TO_MD_ERR(status);
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_sha512_context sha512;
+    mbedtls_md_context_t sha384;
 
-    mbedtls_sha512_init(&sha512);
+    mbedtls_md_init(&sha384);
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify sha384"));
 
-    mbedtls_sha512_clone(&sha512, &ssl->handshake->fin_sha384);
+    ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384);
+    if (ret != 0) {
+        goto exit;
+    }
 
-    ret = mbedtls_sha512_finish(&sha512, hash);
+    ret = mbedtls_md_finish(&sha384, hash);
     if (ret != 0) {
         goto exit;
     }
@@ -6677,7 +6729,7 @@
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify"));
 
 exit:
-    mbedtls_sha512_free(&sha512);
+    mbedtls_md_free(&sha384);
     return ret;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 }
@@ -7634,7 +7686,7 @@
     psa_status_t status;
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_sha256_context sha256;
+    mbedtls_md_context_t sha256;
 #endif
 
     mbedtls_ssl_session *session = ssl->session_negotiate;
@@ -7663,11 +7715,18 @@
     MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, 32);
 #else
 
-    mbedtls_sha256_init(&sha256);
+    mbedtls_md_init(&sha256);
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc  finished tls sha256"));
 
-    mbedtls_sha256_clone(&sha256, &ssl->handshake->fin_sha256);
+    ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256);
+    if (ret != 0) {
+        goto exit;
+    }
 
     /*
      * TLSv1.2:
@@ -7675,17 +7734,14 @@
      *               Hash( handshake ) )[0.11]
      */
 
-#if !defined(MBEDTLS_SHA256_ALT)
-    MBEDTLS_SSL_DEBUG_BUF(4, "finished sha2 state", (unsigned char *)
-                          sha256.state, sizeof(sha256.state));
-#endif
-
-    ret = mbedtls_sha256_finish(&sha256, padbuf);
+    ret = mbedtls_md_finish(&sha256, padbuf);
     if (ret != 0) {
         goto exit;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
+    MBEDTLS_SSL_DEBUG_BUF(4, "finished sha256 output", padbuf, 32);
+
     ssl->handshake->tls_prf(session->master, 48, sender,
                             padbuf, 32, buf, len);
 
@@ -7698,9 +7754,9 @@
 exit:
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_hash_abort(&sha256_psa);
-    return mbedtls_md_error_from_psa(status);
+    return PSA_TO_MD_ERR(status);
 #else
-    mbedtls_sha256_free(&sha256);
+    mbedtls_md_free(&sha256);
     return ret;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 }
@@ -7720,7 +7776,7 @@
     psa_status_t status;
 #else
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_sha512_context sha512;
+    mbedtls_md_context_t sha384;
 #endif
 
     mbedtls_ssl_session *session = ssl->session_negotiate;
@@ -7748,11 +7804,18 @@
     }
     MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, 48);
 #else
-    mbedtls_sha512_init(&sha512);
+    mbedtls_md_init(&sha384);
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc  finished tls sha384"));
 
-    mbedtls_sha512_clone(&sha512, &ssl->handshake->fin_sha384);
+    ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384);
+    if (ret != 0) {
+        goto exit;
+    }
 
     /*
      * TLSv1.2:
@@ -7760,16 +7823,14 @@
      *               Hash( handshake ) )[0.11]
      */
 
-#if !defined(MBEDTLS_SHA512_ALT)
-    MBEDTLS_SSL_DEBUG_BUF(4, "finished sha512 state", (unsigned char *)
-                          sha512.state, sizeof(sha512.state));
-#endif
-    ret = mbedtls_sha512_finish(&sha512, padbuf);
+    ret = mbedtls_md_finish(&sha384, padbuf);
     if (ret != 0) {
         goto exit;
     }
 #endif
 
+    MBEDTLS_SSL_DEBUG_BUF(4, "finished sha384 output", padbuf, 48);
+
     ssl->handshake->tls_prf(session->master, 48, sender,
                             padbuf, 48, buf, len);
 
@@ -7782,9 +7843,9 @@
 exit:
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_hash_abort(&sha384_psa);
-    return mbedtls_md_error_from_psa(status);
+    return PSA_TO_MD_ERR(status);
 #else
-    mbedtls_sha512_free(&sha512);
+    mbedtls_md_free(&sha384);
     return ret;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 }
@@ -8230,7 +8291,7 @@
                                             &alg,
                                             &key_type,
                                             &key_bits)) != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", ret);
         goto end;
     }
@@ -8478,7 +8539,7 @@
                                      PSA_BITS_TO_BYTES(key_bits),
                                      &transform->psa_key_enc)) != PSA_SUCCESS) {
             MBEDTLS_SSL_DEBUG_RET(3, "psa_import_key", (int) status);
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret);
             goto end;
         }
@@ -8489,7 +8550,7 @@
                                      key2,
                                      PSA_BITS_TO_BYTES(key_bits),
                                      &transform->psa_key_dec)) != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret);
             goto end;
         }
@@ -8552,7 +8613,7 @@
         if ((status = psa_import_key(&attributes,
                                      mac_enc, mac_key_len,
                                      &transform->psa_mac_enc)) != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret);
             goto end;
         }
@@ -8573,7 +8634,7 @@
         if ((status = psa_import_key(&attributes,
                                      mac_dec, mac_key_len,
                                      &transform->psa_mac_dec)) != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret);
             goto end;
         }
@@ -8628,7 +8689,7 @@
             status = psa_pake_input(pake_ctx, step,
                                     buf + input_offset, length);
             if (status != PSA_SUCCESS) {
-                return psa_ssl_status_to_mbedtls(status);
+                return PSA_TO_MBEDTLS_ERR(status);
             }
 
             input_offset += length;
@@ -8670,7 +8731,7 @@
                                      len - output_offset - 1,
                                      &output_len);
             if (status != PSA_SUCCESS) {
-                return psa_ssl_status_to_mbedtls(status);
+                return PSA_TO_MBEDTLS_ERR(status);
             }
 
             *(buf + output_offset) = (uint8_t) output_len;
diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c
index fc99fde..890e9a9 100644
--- a/library/ssl_tls12_client.c
+++ b/library/ssl_tls12_client.c
@@ -33,6 +33,9 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "mbedtls/psa_util.h"
 #include "psa/crypto.h"
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #include <string.h>
@@ -2951,7 +2954,7 @@
         status = psa_generate_key(&key_attributes,
                                   &handshake->ecdh_psa_privkey);
         if (status != PSA_SUCCESS) {
-            return psa_ssl_status_to_mbedtls(status);
+            return PSA_TO_MBEDTLS_ERR(status);
         }
 
         /* Export the public part of the ECDH private key from PSA.
@@ -2968,7 +2971,7 @@
         if (status != PSA_SUCCESS) {
             psa_destroy_key(handshake->ecdh_psa_privkey);
             handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
-            return psa_ssl_status_to_mbedtls(status);
+            return PSA_TO_MBEDTLS_ERR(status);
         }
 
         *p = (unsigned char) own_pubkey_len;
@@ -3000,9 +3003,9 @@
         handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
 
         if (status != PSA_SUCCESS) {
-            return psa_ssl_status_to_mbedtls(status);
+            return PSA_TO_MBEDTLS_ERR(status);
         } else if (destruction_status != PSA_SUCCESS) {
-            return psa_ssl_status_to_mbedtls(destruction_status);
+            return PSA_TO_MBEDTLS_ERR(destruction_status);
         }
 
         /* Write the ECDH computation length before the ECDH computation */
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index d5c8b7c..0806f7f 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -34,6 +34,12 @@
 
 #include <string.h>
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
 #if defined(MBEDTLS_ECP_C)
 #include "mbedtls/ecp.h"
 #endif
@@ -2588,7 +2594,7 @@
                                             &key_attributes);
             if (status != PSA_SUCCESS) {
                 ssl->handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
-                return psa_ssl_status_to_mbedtls(status);
+                return PSA_TO_MBEDTLS_ERR(status);
             }
 
             ssl->handshake->ecdh_psa_type = psa_get_key_type(&key_attributes);
@@ -2635,7 +2641,7 @@
             status = psa_import_key(&key_attributes, buf, key_len,
                                     &ssl->handshake->ecdh_psa_privkey);
             if (status != PSA_SUCCESS) {
-                ret = psa_ssl_status_to_mbedtls(status);
+                ret = PSA_TO_MBEDTLS_ERR(status);
                 goto cleanup;
             }
 
@@ -2956,7 +2962,7 @@
         status = psa_generate_key(&key_attributes,
                                   &handshake->ecdh_psa_privkey);
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret);
             return ret;
         }
@@ -2980,7 +2986,7 @@
                                        own_pubkey, own_pubkey_max_len,
                                        &len);
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret);
             (void) psa_destroy_key(handshake->ecdh_psa_privkey);
             handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
@@ -3688,7 +3694,7 @@
             handshake->premaster, sizeof(handshake->premaster),
             &handshake->pmslen);
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret);
             if (handshake->ecdh_psa_privkey_is_external == 0) {
                 (void) psa_destroy_key(handshake->ecdh_psa_privkey);
@@ -3701,7 +3707,7 @@
             status = psa_destroy_key(handshake->ecdh_psa_privkey);
 
             if (status != PSA_SUCCESS) {
-                ret = psa_ssl_status_to_mbedtls(status);
+                ret = PSA_TO_MBEDTLS_ERR(status);
                 MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret);
                 return ret;
             }
@@ -3894,9 +3900,9 @@
         handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
 
         if (status != PSA_SUCCESS) {
-            return psa_ssl_status_to_mbedtls(status);
+            return PSA_TO_MBEDTLS_ERR(status);
         } else if (destruction_status != PSA_SUCCESS) {
-            return psa_ssl_status_to_mbedtls(destruction_status);
+            return PSA_TO_MBEDTLS_ERR(destruction_status);
         }
 
         /* Write the ECDH computation length before the ECDH computation */
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 0dd762e..05c7364 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -34,6 +34,10 @@
 #include "ssl_tls13_keys.h"
 #include "ssl_debug_helpers.h"
 
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+
 /* Write extensions */
 
 /*
@@ -188,7 +192,7 @@
         /* Destroy generated private key. */
         status = psa_destroy_key(ssl->handshake->ecdh_psa_privkey);
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret);
             return ret;
         }
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index f607e36..512656e 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -36,6 +36,13 @@
 #include "ssl_tls13_keys.h"
 #include "ssl_debug_helpers.h"
 
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+
 const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[
     MBEDTLS_SERVER_HELLO_RANDOM_LEN] =
 { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
@@ -1016,7 +1023,7 @@
                                   verify_hash, sizeof(verify_hash),
                                   &verify_hash_len);
         if (status != PSA_SUCCESS) {
-            return psa_ssl_status_to_mbedtls(status);
+            return PSA_TO_MBEDTLS_ERR(status);
         }
 
         MBEDTLS_SSL_DEBUG_BUF(3, "verify hash", verify_hash, verify_hash_len);
@@ -1482,7 +1489,7 @@
     status = psa_generate_key(&key_attributes,
                               &handshake->ecdh_psa_privkey);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret);
         return ret;
 
@@ -1493,7 +1500,7 @@
                                    buf, (size_t) (end - buf),
                                    &own_pubkey_len);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret);
         return ret;
 
diff --git a/library/ssl_tls13_keys.c b/library/ssl_tls13_keys.c
index a95d2fd..6edce50 100644
--- a/library/ssl_tls13_keys.c
+++ b/library/ssl_tls13_keys.c
@@ -35,6 +35,10 @@
 
 #include "psa/crypto.h"
 
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                           psa_to_ssl_errors,             \
+                                                           psa_generic_status_to_mbedtls)
+
 #define MBEDTLS_SSL_TLS1_3_LABEL(name, string)       \
     .name = string,
 
@@ -215,7 +219,7 @@
     abort_status = psa_key_derivation_abort(&operation);
     status = (status == PSA_SUCCESS ? abort_status : status);
     mbedtls_platform_zeroize(hkdf_label, hkdf_label_len);
-    return psa_ssl_status_to_mbedtls(status);
+    return PSA_TO_MBEDTLS_ERR(status);
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
@@ -309,7 +313,7 @@
         status = psa_hash_compute(hash_alg, ctx, ctx_len, hashed_context,
                                   PSA_HASH_LENGTH(hash_alg), &ctx_len);
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             return ret;
         }
     } else {
@@ -416,7 +420,7 @@
 cleanup:
     abort_status = psa_key_derivation_abort(&operation);
     status = (status == PSA_SUCCESS ? abort_status : status);
-    ret = (ret == 0 ? psa_ssl_status_to_mbedtls(status) : ret);
+    ret = (ret == 0 ? PSA_TO_MBEDTLS_ERR(status) : ret);
     mbedtls_platform_zeroize(tmp_secret, sizeof(tmp_secret));
     return ret;
 }
@@ -740,19 +744,19 @@
 
     status = psa_import_key(&attributes, finished_key, hash_len, &key);
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         goto exit;
     }
 
     status = psa_mac_compute(key, alg, transcript, hash_len,
                              dst, hash_len, dst_len);
-    ret = psa_ssl_status_to_mbedtls(status);
+    ret = PSA_TO_MBEDTLS_ERR(status);
 
 exit:
 
     status = psa_destroy_key(key);
     if (ret == 0) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
     }
 
     mbedtls_platform_zeroize(finished_key, sizeof(finished_key));
@@ -1040,8 +1044,8 @@
                                             &alg,
                                             &key_type,
                                             &key_bits)) != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", psa_ssl_status_to_mbedtls(status));
-        return psa_ssl_status_to_mbedtls(status);
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", PSA_TO_MBEDTLS_ERR(status));
+        return PSA_TO_MBEDTLS_ERR(status);
     }
 
     transform->psa_alg = alg;
@@ -1055,8 +1059,8 @@
                                      key_enc,
                                      PSA_BITS_TO_BYTES(key_bits),
                                      &transform->psa_key_enc)) != PSA_SUCCESS) {
-            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", psa_ssl_status_to_mbedtls(status));
-            return psa_ssl_status_to_mbedtls(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status));
+            return PSA_TO_MBEDTLS_ERR(status);
         }
 
         psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
@@ -1065,8 +1069,8 @@
                                      key_dec,
                                      PSA_BITS_TO_BYTES(key_bits),
                                      &transform->psa_key_dec)) != PSA_SUCCESS) {
-            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", psa_ssl_status_to_mbedtls(status));
-            return psa_ssl_status_to_mbedtls(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status));
+            return PSA_TO_MBEDTLS_ERR(status);
         }
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
@@ -1094,7 +1098,7 @@
     status = mbedtls_ssl_cipher_to_psa(ciphersuite_info->cipher, taglen,
                                        &alg, &key_type, &key_bits);
     if (status != PSA_SUCCESS) {
-        return psa_ssl_status_to_mbedtls(status);
+        return PSA_TO_MBEDTLS_ERR(status);
     }
 
     *key_len = PSA_BITS_TO_BYTES(key_bits);
@@ -1467,7 +1471,7 @@
             status = psa_get_key_attributes(handshake->ecdh_psa_privkey,
                                             &key_attributes);
             if (status != PSA_SUCCESS) {
-                ret = psa_ssl_status_to_mbedtls(status);
+                ret = PSA_TO_MBEDTLS_ERR(status);
             }
 
             shared_secret_len = PSA_BITS_TO_BYTES(
@@ -1482,14 +1486,14 @@
                 handshake->ecdh_psa_peerkey, handshake->ecdh_psa_peerkey_len,
                 shared_secret, shared_secret_len, &shared_secret_len);
             if (status != PSA_SUCCESS) {
-                ret = psa_ssl_status_to_mbedtls(status);
+                ret = PSA_TO_MBEDTLS_ERR(status);
                 MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret);
                 goto cleanup;
             }
 
             status = psa_destroy_key(handshake->ecdh_psa_privkey);
             if (status != PSA_SUCCESS) {
-                ret = psa_ssl_status_to_mbedtls(status);
+                ret = PSA_TO_MBEDTLS_ERR(status);
                 MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret);
                 goto cleanup;
             }
@@ -1826,7 +1830,7 @@
 
     status = psa_get_key_attributes(ssl->handshake->psk_opaque, &key_attributes);
     if (status != PSA_SUCCESS) {
-        return psa_ssl_status_to_mbedtls(status);
+        return PSA_TO_MBEDTLS_ERR(status);
     }
 
     *psk_len = PSA_BITS_TO_BYTES(psa_get_key_bits(&key_attributes));
@@ -1840,7 +1844,7 @@
     if (status != PSA_SUCCESS) {
         mbedtls_free((void *) *psk);
         *psk = NULL;
-        return psa_ssl_status_to_mbedtls(status);
+        return PSA_TO_MBEDTLS_ERR(status);
     }
     return 0;
 #else
diff --git a/library/x509write_crt.c b/library/x509write_crt.c
index 4f23395..f481155 100644
--- a/library/x509write_crt.c
+++ b/library/x509write_crt.c
@@ -32,7 +32,7 @@
 #include "mbedtls/error.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
-#include "mbedtls/sha1.h"
+#include "mbedtls/md.h"
 
 #include <string.h>
 
@@ -229,8 +229,9 @@
         return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
     }
 #else
-    ret = mbedtls_sha1(buf + sizeof(buf) - len, len,
-                       buf + sizeof(buf) - 20);
+    ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1),
+                     buf + sizeof(buf) - len, len,
+                     buf + sizeof(buf) - 20);
     if (ret != 0) {
         return ret;
     }
diff --git a/programs/.gitignore b/programs/.gitignore
index 44e904a..398152d 100644
--- a/programs/.gitignore
+++ b/programs/.gitignore
@@ -64,6 +64,7 @@
 test/dlopen
 test/ecp-bench
 test/query_compile_time_config
+test/query_included_headers
 test/selftest
 test/ssl_cert_test
 test/udp_proxy
diff --git a/programs/Makefile b/programs/Makefile
index fdfece7..3509fc3 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -123,6 +123,7 @@
 	ssl/ssl_server2 \
 	test/benchmark \
 	test/query_compile_time_config \
+	test/query_included_headers \
 	test/selftest \
 	test/udp_proxy \
 	test/zeroize \
@@ -403,6 +404,10 @@
 	echo "  CC    test/query_config.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c test/query_config.c -o $@
 
+test/query_included_headers$(EXEXT): test/query_included_headers.c $(DEP)
+	echo "  CC    test/query_included_headers.c"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/query_included_headers.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 test/selftest$(EXEXT): test/selftest.c $(DEP)
 	echo "  CC    test/selftest.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/selftest.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt
index c3e7d2e..735684e 100644
--- a/programs/test/CMakeLists.txt
+++ b/programs/test/CMakeLists.txt
@@ -3,6 +3,7 @@
 )
 
 set(executables_libs
+    query_included_headers
     selftest
     udp_proxy
 )
diff --git a/programs/test/query_included_headers.c b/programs/test/query_included_headers.c
new file mode 100644
index 0000000..383a2ff
--- /dev/null
+++ b/programs/test/query_included_headers.c
@@ -0,0 +1,41 @@
+/* Ad hoc report on included headers. */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include <psa/crypto.h>
+#include <mbedtls/platform.h>
+
+int main(void)
+{
+
+    /* Which PSA platform header? */
+#if defined(PSA_CRYPTO_PLATFORM_H)
+    mbedtls_printf("PSA_CRYPTO_PLATFORM_H\n");
+#endif
+#if defined(PSA_CRYPTO_PLATFORM_ALT_H)
+    mbedtls_printf("PSA_CRYPTO_PLATFORM_ALT_H\n");
+#endif
+
+    /* Which PSA struct header? */
+#if defined(PSA_CRYPTO_STRUCT_H)
+    mbedtls_printf("PSA_CRYPTO_STRUCT_H\n");
+#endif
+#if defined(PSA_CRYPTO_STRUCT_ALT_H)
+    mbedtls_printf("PSA_CRYPTO_STRUCT_ALT_H\n");
+#endif
+
+}
diff --git a/scripts/mbedtls_dev/bignum_common.py b/scripts/mbedtls_dev/bignum_common.py
index 2422175..5319ec6 100644
--- a/scripts/mbedtls_dev/bignum_common.py
+++ b/scripts/mbedtls_dev/bignum_common.py
@@ -74,6 +74,10 @@
     """Return all pair combinations from input values."""
     return [(x, y) for x in values for y in values]
 
+def hex_digits_for_limb(limbs: int, bits_in_limb: int) -> int:
+    """ Retrun the hex digits need for a number of limbs. """
+    return 2 * (limbs * bits_in_limb // 8)
+
 class OperationCommon(test_data_generation.BaseTest):
     """Common features for bignum binary operations.
 
@@ -138,7 +142,7 @@
 
     @property
     def hex_digits(self) -> int:
-        return 2 * (self.limbs * self.bits_in_limb // 8)
+        return hex_digits_for_limb(self.limbs, self.bits_in_limb)
 
     def format_arg(self, val: str) -> str:
         if self.input_style not in self.input_styles:
diff --git a/scripts/mbedtls_dev/ecp.py b/scripts/mbedtls_dev/ecp.py
index 6370d25..354b234 100644
--- a/scripts/mbedtls_dev/ecp.py
+++ b/scripts/mbedtls_dev/ecp.py
@@ -19,11 +19,13 @@
 from . import test_data_generation
 from . import bignum_common
 
+
 class EcpTarget(test_data_generation.BaseTarget):
     #pylint: disable=abstract-method, too-few-public-methods
     """Target for ecp test case generation."""
     target_basename = 'test_suite_ecp.generated'
 
+
 class EcpP192R1Raw(bignum_common.ModOperationCommon,
                    EcpTarget):
     """Test cases for ecp quasi_reduction()."""
@@ -76,6 +78,73 @@
     def is_valid(self) -> bool:
         return True
 
+
+class EcpP224R1Raw(bignum_common.ModOperationCommon,
+                   EcpTarget):
+    """Test cases for ecp quasi_reduction()."""
+    symbol = "-"
+    test_function = "ecp_mod_p224_raw"
+    test_name = "ecp_mod_p224_raw"
+    input_style = "arch_split"
+    arity = 1
+
+    moduli = ["ffffffffffffffffffffffffffffffff000000000000000000000001"] # type: List[str]
+
+    input_values = [
+        "0", "1",
+
+        # Modulus - 1
+        "ffffffffffffffffffffffffffffffff000000000000000000000000",
+
+        # Maximum canonical P224 multiplication result
+        ("fffffffffffffffffffffffffffffffe000000000000000000000000"
+         "00000001000000000000000000000000000000000000000000000000"),
+
+        # Generate an overflow during reduction
+        ("00000000000000000000000000010000000070000000002000001000"
+         "ffffffffffff9fffffffffe00000efff000070000000002000001003"),
+
+        # Generate an underflow during reduction
+        ("00000001000000000000000000000000000000000000000000000000"
+         "00000000000dc0000000000000000001000000010000000100000003"),
+
+        # First 8 number generated by random.getrandbits(448) - seed(2,2)
+        ("da94e3e8ab73738fcf1822ffbc6887782b491044d5e341245c6e4337"
+         "15ba2bdd177219d30e7a269fd95bafc8f2a4d27bdcf4bb99f4bea973"),
+        ("cdbd47d364be8049a372db8f6e405d93ffed9235288bc781ae662675"
+         "94c9c9500925e4749b575bd13653f8dd9b1f282e4067c3584ee207f8"),
+        ("defc044a09325626e6b58de744ab6cce80877b6f71e1f6d2ef8acd12"
+         "8b4f2fc15f3f57ebf30b94fa82523e86feac7eb7dc38f519b91751da"),
+        ("2d6c797f8f7d9b782a1be9cd8697bbd0e2520e33e44c50556c71c4a6"
+         "6148a86fe8624fab5186ee32ee8d7ee9770348a05d300cb90706a045"),
+        ("8f54f8ceacaab39e83844b40ffa9b9f15c14bc4a829e07b0829a48d4"
+         "22fe99a22c70501e533c91352d3d854e061b90303b08c6e33c729578"),
+        ("97eeab64ca2ce6bc5d3fd983c34c769fe89204e2e8168561867e5e15"
+         "bc01bfce6a27e0dfcbf8754472154e76e4c11ab2fec3f6b32e8d4b8a"),
+        ("a7a83ee0761ebfd2bd143fa9b714210c665d7435c1066932f4767f26"
+         "294365b2721dea3bf63f23d0dbe53fcafb2147df5ca495fa5a91c89b"),
+        ("74667bffe202849da9643a295a9ac6decbd4d3e2d4dec9ef83f0be4e"
+         "80371eb97f81375eecc1cb6347733e847d718d733ff98ff387c56473"),
+
+        # Next 2 number generated by random.getrandbits(224)
+        "eb9ac688b9d39cca91551e8259cc60b17604e4b4e73695c3e652c71a",
+        "f0caeef038c89b38a8acb5137c9260dc74e088a9b9492f258ebdbfe3"
+    ]
+
+    @property
+    def arg_a(self) -> str:
+        hex_digits = bignum_common.hex_digits_for_limb(448 // self.bits_in_limb, self.bits_in_limb)
+        return super().format_arg('{:x}'.format(self.int_a)).zfill(hex_digits)
+
+    def result(self) -> List[str]:
+        result = self.int_a % self.int_n
+        return [self.format_result(result)]
+
+    @property
+    def is_valid(self) -> bool:
+        return True
+
+
 class EcpP521R1Raw(bignum_common.ModOperationCommon,
                    EcpTarget):
     """Test cases for ecp quasi_reduction()."""
diff --git a/tests/.gitignore b/tests/.gitignore
index 15fce68..b85d66a 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -13,6 +13,8 @@
 data_files/ctr_drbg_seed
 data_files/entropy_seed
 
+include/alt-extra/psa/crypto_platform_alt.h
+include/alt-extra/psa/crypto_struct_alt.h
 include/test/instrument_record_status.h
 
 src/*.o
diff --git a/tests/Makefile b/tests/Makefile
index c9283c9..26947f4 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -219,6 +219,7 @@
 	rm -rf $(BINARIES) *.c *.datax
 	rm -f src/*.o src/drivers/*.o src/libmbed*
 	rm -f include/test/instrument_record_status.h
+	rm -f include/alt-extra/*/*_alt.h
 	rm -rf libtestdriver1
 	rm -f ../library/libtestdriver1.a
 else
@@ -244,6 +245,10 @@
 
 test: check
 
+# Generate variants of some headers for testing
+include/alt-extra/%_alt.h: ../include/%.h
+	perl -p -e 's/^(# *(define|ifndef) +\w+_)H\b/$${1}ALT_H/' $< >$@
+
 # Generate test library
 
 # Perl code that is executed to transform each original line from a library
diff --git a/tests/configs/tls13-only.h b/tests/configs/tls13-only.h
index 963086f..38286d1 100644
--- a/tests/configs/tls13-only.h
+++ b/tests/configs/tls13-only.h
@@ -29,10 +29,12 @@
 /* Disable TLS 1.2 and 1.2-specific features */
 #undef MBEDTLS_SSL_ENCRYPT_THEN_MAC
 #undef MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+#undef MBEDTLS_SSL_RENEGOTIATION
 #undef MBEDTLS_SSL_PROTO_TLS1_2
 #undef MBEDTLS_SSL_PROTO_DTLS
 #undef MBEDTLS_SSL_DTLS_ANTI_REPLAY
 #undef MBEDTLS_SSL_DTLS_HELLO_VERIFY
+#undef MBEDTLS_SSL_DTLS_SRTP
 #undef MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
 #undef MBEDTLS_SSL_DTLS_CONNECTION_ID
 #undef MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT
diff --git a/tests/include/alt-extra/psa/crypto.h b/tests/include/alt-extra/psa/crypto.h
new file mode 100644
index 0000000..005f3ae
--- /dev/null
+++ b/tests/include/alt-extra/psa/crypto.h
@@ -0,0 +1,7 @@
+/* The goal of the include/alt-extra directory is to test what happens
+ * if certain files come _after_ the normal include directory.
+ * Make sure that if the alt-extra directory comes before the normal
+ * directory (so we wouldn't be achieving our test objective), the build
+ * will fail.
+ */
+#error "The normal include directory must come first in the include path"
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 353ec69..77c6ef5 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -388,7 +388,7 @@
 
     msg "build: ARM Compiler 6 ($FLAGS)"
     ARM_TOOL_VARIANT="ult" CC="$ARMC6_CC" AR="$ARMC6_AR" CFLAGS="$FLAGS" \
-                    WARNING_CFLAGS='-xc -std=c99' make lib
+                    WARNING_CFLAGS='-Werror -xc -std=c99' make lib
 
     msg "size: ARM Compiler 6 ($FLAGS)"
     "$ARMC6_FROMELF" -z library/*.o
@@ -1219,19 +1219,25 @@
     tests/ssl-opt.sh -f 'Default\|opaque'
 }
 
-component_test_crypto_full_no_md () {
-    msg "build: crypto_full minus MD"
+component_test_crypto_full_md_light_only () {
+    msg "build: crypto_full with only the light subset of MD"
     scripts/config.py crypto_full
+    # Disable MD
     scripts/config.py unset MBEDTLS_MD_C
-    # Direct dependencies
+    # Disable direct dependencies of MD
     scripts/config.py unset MBEDTLS_HKDF_C
     scripts/config.py unset MBEDTLS_HMAC_DRBG_C
     scripts/config.py unset MBEDTLS_PKCS7_C
-    # Indirect dependencies
-    scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC
-    make
+    # Disable indirect dependencies of MD
+    scripts/config.py unset MBEDTLS_ECDSA_DETERMINISTIC # needs HMAC_DRBG
+    # Enable "light" subset of MD
+    make CFLAGS="$ASAN_CFLAGS -DMBEDTLS_MD_LIGHT" LDFLAGS="$ASAN_CFLAGS"
 
-    msg "test: crypto_full minus MD"
+    # Make sure we don't have the HMAC functions, but the hashing functions
+    not grep mbedtls_md_hmac library/md.o
+    grep mbedtls_md library/md.o
+
+    msg "test: crypto_full with only the light subset of MD"
     make test
 }
 
@@ -2064,8 +2070,8 @@
     loc_accel_flags=$( echo "$loc_accel_list" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
     make -C tests libtestdriver1.a CFLAGS="$ASAN_CFLAGS $loc_accel_flags" LDFLAGS="$ASAN_CFLAGS"
 
-    # Configure and build the test driver library
-    # -------------------------------------------
+    # Configure and build the main libraries
+    # --------------------------------------
 
     # Start from default config (no USE_PSA) + driver support + TLS 1.3
     scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
@@ -2083,7 +2089,7 @@
     loc_accel_flags="$loc_accel_flags $( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
     make CFLAGS="$ASAN_CFLAGS -O -Werror -I../tests/include -I../tests -I../../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS"
 
-    # Make sure ECDSA was not re-enabled by accident (additive config)
+    # Make sure this was not re-enabled by accident (additive config)
     not grep mbedtls_ecdsa_ library/ecdsa.o
 
     # Run the tests
@@ -2093,7 +2099,7 @@
     make test
 }
 
-# Auxiliary function to build config for hashes with and without drivers
+# Auxiliary function to build config for ECDSA with and without drivers
 config_psa_crypto_config_ecdsa_use_psa () {
     DRIVER_ONLY="$1"
     # start with config full for maximum coverage (also enables USE_PSA)
@@ -2184,35 +2190,149 @@
 component_test_psa_crypto_config_accel_ecdh () {
     msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated ECDH"
 
+    # Algorithms and key types to accelerate
+    loc_accel_list="ALG_ECDH KEY_TYPE_ECC_KEY_PAIR KEY_TYPE_ECC_PUBLIC_KEY"
+
+    # Configure and build the test driver library
+    # -------------------------------------------
+
     # Disable ALG_STREAM_CIPHER and ALG_ECB_NO_PADDING to avoid having
     # partial support for cipher operations in the driver test library.
     scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_STREAM_CIPHER
     scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_ECB_NO_PADDING
 
-    loc_accel_list="ALG_ECDH KEY_TYPE_ECC_KEY_PAIR KEY_TYPE_ECC_PUBLIC_KEY"
     loc_accel_flags=$( echo "$loc_accel_list" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
     make -C tests libtestdriver1.a CFLAGS=" $ASAN_CFLAGS $loc_accel_flags" LDFLAGS="$ASAN_CFLAGS"
 
+    # Configure and build the main libraries
+    # --------------------------------------
+
+    # Start from default config (no USE_PSA or TLS 1.3) + driver support
     scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
     scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
+
+    # Disable the module that's accelerated
     scripts/config.py unset MBEDTLS_ECDH_C
+
+    # Disable things that depend on it
     scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
     scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
     scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
     scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
     scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
 
+    # Build the main library
     loc_accel_flags="$loc_accel_flags $( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
     make CFLAGS="$ASAN_CFLAGS -O -Werror -I../tests/include -I../tests -I../../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS"
 
+    # Make sure this was not re-enabled by accident (additive config)
     not grep mbedtls_ecdh_ library/ecdh.o
 
+    # Run the tests
+    # -------------
+
     msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated ECDH"
     make test
 }
 
+# Auxiliary function to build config for ECDH with and without drivers.
+#
+# This is used by the two following components to ensure they always use the
+# same config, except for the use of driver or built-in ECDH:
+# - component_test_psa_crypto_config_accel_ecdh_use_psa;
+# - component_test_psa_crypto_config_reference_ecdh_use_psa.
+# This support comparing their test coverage with analyze_outcomes.py.
+config_psa_crypto_config_ecdh_use_psa () {
+    DRIVER_ONLY="$1"
+    # start with config full for maximum coverage (also enables USE_PSA)
+    scripts/config.py full
+    # enable support for drivers and configuring PSA-only algorithms
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    if [ "$DRIVER_ONLY" -eq 1 ]; then
+        # Disable the module that's accelerated
+        scripts/config.py unset MBEDTLS_ECDH_C
+    fi
+    # Disable things that depend on it (regardless of driver or built-in)
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+
+    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)
+    scripts/config.py unset MBEDTLS_ECP_RESTARTABLE
+}
+
+# Keep in sync with component_test_psa_crypto_config_reference_ecdh_use_psa
+component_test_psa_crypto_config_accel_ecdh_use_psa () {
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated ECDH + USE_PSA"
+
+    # Algorithms and key types to accelerate
+    loc_accel_list="ALG_ECDH KEY_TYPE_ECC_KEY_PAIR KEY_TYPE_ECC_PUBLIC_KEY"
+
+    # Configure and build the test driver library
+    # -------------------------------------------
+
+    # Disable ALG_STREAM_CIPHER and ALG_ECB_NO_PADDING to avoid having
+    # partial support for cipher operations in the driver test library.
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_STREAM_CIPHER
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_ECB_NO_PADDING
+
+    loc_accel_flags=$( echo "$loc_accel_list" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
+    make -C tests libtestdriver1.a CFLAGS=" $ASAN_CFLAGS $loc_accel_flags" LDFLAGS="$ASAN_CFLAGS"
+
+    # Configure and build the main libraries
+    # --------------------------------------
+
+    # Use the same config as reference, only without built-in ECDH
+    config_psa_crypto_config_ecdh_use_psa 1
+
+    # Build the main library
+    loc_accel_flags="$loc_accel_flags $( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
+    make CFLAGS="$ASAN_CFLAGS -O -Werror -I../tests/include -I../tests -I../../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS"
+
+    # Make sure this was not re-enabled by accident (additive config)
+    not grep mbedtls_ecdh_ library/ecdh.o
+
+    # Run the tests
+    # -------------
+
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated ECDH + USE_PSA"
+    make test
+
+    # ssl-opt.sh later (probably doesn't pass right now)
+}
+
+# Keep in sync with component_test_psa_crypto_config_accel_ecdh_use_psa.
+# Used by tests/scripts/analyze_outcomes.py for comparison purposes.
+component_test_psa_crypto_config_reference_ecdh_use_psa () {
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with reference ECDH + USE_PSA"
+
+    # To be aligned with the accel component that needs this
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_STREAM_CIPHER
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_ECB_NO_PADDING
+
+    config_psa_crypto_config_ecdh_use_psa 0
+
+    make
+
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with reference ECDH + USE_PSA"
+    make test
+
+    # ssl-opt.sh later when the accel component is ready
+}
+
 component_test_psa_crypto_config_accel_rsa_signature () {
     msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated RSA signature"
 
@@ -2346,8 +2466,7 @@
     scripts/config.py unset MBEDTLS_ENTROPY_C
     scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED # depends on ENTROPY_C
     scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT # depends on former
-    # Also unset MD_C and things that depend on it;
-    # see component_test_crypto_full_no_md.
+    # Also unset MD_C and things that depend on it.
     if [ "$DRIVER_ONLY" -eq 1 ]; then
         scripts/config.py unset MBEDTLS_MD_C
     fi
@@ -3259,6 +3378,27 @@
     rm -f psa_test_config.h psa_user_config.h
 }
 
+component_build_psa_alt_headers () {
+    msg "build: make with PSA alt headers" # ~20s
+
+    # Generate alternative versions of the substitutable headers with the
+    # same content except different include guards.
+    make -C tests include/alt-extra/psa/crypto_platform_alt.h include/alt-extra/psa/crypto_struct_alt.h
+
+    # Build the library and some programs.
+    # Don't build the fuzzers to avoid having to go through hoops to set
+    # a correct include path for programs/fuzz/Makefile.
+    make CFLAGS="-I ../tests/include/alt-extra -DMBEDTLS_PSA_CRYPTO_PLATFORM_FILE='\"psa/crypto_platform_alt.h\"' -DMBEDTLS_PSA_CRYPTO_STRUCT_FILE='\"psa/crypto_struct_alt.h\"'" lib
+    make -C programs -o fuzz CFLAGS="-I ../tests/include/alt-extra -DMBEDTLS_PSA_CRYPTO_PLATFORM_FILE='\"psa/crypto_platform_alt.h\"' -DMBEDTLS_PSA_CRYPTO_STRUCT_FILE='\"psa/crypto_struct_alt.h\"'"
+
+    # Check that we're getting the alternative include guards and not the
+    # original include guards.
+    programs/test/query_included_headers | grep -x PSA_CRYPTO_PLATFORM_ALT_H
+    programs/test/query_included_headers | grep -x PSA_CRYPTO_STRUCT_ALT_H
+    programs/test/query_included_headers | not grep -x PSA_CRYPTO_PLATFORM_H
+    programs/test/query_included_headers | not grep -x PSA_CRYPTO_STRUCT_H
+}
+
 component_test_m32_o0 () {
     # Build without optimization, so as to use portable C code (in a 32-bit
     # build) and not the i386-specific inline assembly.
@@ -3479,6 +3619,15 @@
     scripts/config.py baremetal
     # armc[56] don't support SHA-512 intrinsics
     scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
+
+    # Stop armclang warning about feature detection for A64_CRYPTO.
+    # With this enabled, the library does build correctly under armclang,
+    # but in baremetal builds (as tested here), feature detection is
+    # unavailable, and the user is notified via a #warning. So enabling
+    # this feature would prevent us from building with -Werror on
+    # armclang. Tracked in #7198.
+    scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
+
     scripts/config.py set MBEDTLS_HAVE_ASM
 
     make CC="$ARMC5_CC" AR="$ARMC5_AR" WARNING_CFLAGS='--strict --c99' lib
diff --git a/tests/scripts/analyze_outcomes.py b/tests/scripts/analyze_outcomes.py
index 44c62f7..3fd24e9 100755
--- a/tests/scripts/analyze_outcomes.py
+++ b/tests/scripts/analyze_outcomes.py
@@ -183,6 +183,18 @@
             }
         }
     },
+    'analyze_driver_vs_reference_ecdh': {
+        'test_function': do_analyze_driver_vs_reference,
+        'args': {
+            'component_ref': 'test_psa_crypto_config_reference_ecdh_use_psa',
+            'component_driver': 'test_psa_crypto_config_accel_ecdh_use_psa',
+            'ignored_suites': [
+                'ecdh', # the software implementation that's excluded
+            ],
+            'ignored_tests': {
+            }
+        }
+    },
 }
 
 def main():
diff --git a/tests/scripts/depends.py b/tests/scripts/depends.py
index 52ca412..581baad 100755
--- a/tests/scripts/depends.py
+++ b/tests/scripts/depends.py
@@ -23,7 +23,7 @@
 This script can be divided into several steps:
 
 First, include/mbedtls/mbedtls_config.h or a different config file passed
-in the arguments is parsed to extract any configuration options (collect_config_symbols).
+in the arguments is parsed to extract any configuration options (using config.py).
 
 Then, test domains (groups of jobs, tests) are built based on predefined data
 collected in the DomainData class. Here, each domain has five major traits:
@@ -65,6 +65,11 @@
 import subprocess
 import sys
 import traceback
+from typing import Union
+
+# Add the Mbed TLS Python library directory to the module search path
+import scripts_path # pylint: disable=unused-import
+import config
 
 class Colors: # pylint: disable=too-few-public-methods
     """Minimalistic support for colored output.
@@ -74,6 +79,7 @@
 stop switches the text color back to the default."""
     red = None
     green = None
+    cyan = None
     bold_red = None
     bold_green = None
     def __init__(self, options=None):
@@ -89,6 +95,7 @@
             normal = '\033[0m'
             self.red = ('\033[31m', normal)
             self.green = ('\033[32m', normal)
+            self.cyan = ('\033[36m', normal)
             self.bold_red = ('\033[1;31m', normal)
             self.bold_green = ('\033[1;32m', normal)
 NO_COLORS = Colors(None)
@@ -124,34 +131,38 @@
     else:
         shutil.copy(options.config_backup, options.config)
 
-def run_config_py(options, args):
-    """Run scripts/config.py with the specified arguments."""
-    cmd = ['scripts/config.py']
-    if options.config != 'include/mbedtls/mbedtls_config.h':
-        cmd += ['--file', options.config]
-    cmd += args
-    log_command(cmd)
-    subprocess.check_call(cmd)
+def option_exists(conf, option):
+    return option in conf.settings
 
-def set_reference_config(options):
+def set_config_option_value(conf, option, colors, value: Union[bool, str]):
+    """Set/unset a configuration option, optionally specifying a value.
+value can be either True/False (set/unset config option), or a string,
+which will make a symbol defined with a certain value."""
+    if not option_exists(conf, option):
+        log_line('Symbol {} was not found in {}'.format(option, conf.filename), color=colors.red)
+        return False
+
+    if value is False:
+        log_command(['config.py', 'unset', option])
+        conf.unset(option)
+    elif value is True:
+        log_command(['config.py', 'set', option])
+        conf.set(option)
+    else:
+        log_command(['config.py', 'set', option, value])
+        conf.set(option, value)
+    return True
+
+def set_reference_config(conf, options, colors):
     """Change the library configuration file (mbedtls_config.h) to the reference state.
 The reference state is the one from which the tested configurations are
 derived."""
     # Turn off options that are not relevant to the tests and slow them down.
-    run_config_py(options, ['full'])
-    run_config_py(options, ['unset', 'MBEDTLS_TEST_HOOKS'])
+    log_command(['config.py', 'full'])
+    conf.adapt(config.full_adapter)
+    set_config_option_value(conf, 'MBEDTLS_TEST_HOOKS', colors, False)
     if options.unset_use_psa:
-        run_config_py(options, ['unset', 'MBEDTLS_USE_PSA_CRYPTO'])
-
-def collect_config_symbols(options):
-    """Read the list of settings from mbedtls_config.h.
-Return them in a generator."""
-    with open(options.config, encoding="utf-8") as config_file:
-        rx = re.compile(r'\s*(?://\s*)?#define\s+(\w+)\s*(?:$|/[/*])')
-        for line in config_file:
-            m = re.match(rx, line)
-            if m:
-                yield m.group(1)
+        set_config_option_value(conf, 'MBEDTLS_USE_PSA_CRYPTO', colors, False)
 
 class Job:
     """A job builds the library in a specific configuration and runs some tests."""
@@ -179,19 +190,16 @@
         elif what is False:
             log_line(self.name + ' FAILED', color=colors.red)
         else:
-            log_line('starting ' + self.name)
+            log_line('starting ' + self.name, color=colors.cyan)
 
-    def configure(self, options):
+    def configure(self, conf, options, colors):
         '''Set library configuration options as required for the job.'''
-        set_reference_config(options)
+        set_reference_config(conf, options, colors)
         for key, value in sorted(self.config_settings.items()):
-            if value is True:
-                args = ['set', key]
-            elif value is False:
-                args = ['unset', key]
-            else:
-                args = ['set', key, value]
-            run_config_py(options, args)
+            ret = set_config_option_value(conf, key, colors, value)
+            if ret is False:
+                return False
+        return True
 
     def test(self, options):
         '''Run the job's build and test commands.
@@ -382,11 +390,11 @@
         return [symbol for symbol in self.all_config_symbols
                 if re.match(regexp, symbol)]
 
-    def __init__(self, options):
+    def __init__(self, options, conf):
         """Gather data about the library and establish a list of domains to test."""
         build_command = [options.make_command, 'CFLAGS=-Werror']
         build_and_test = [build_command, [options.make_command, 'test']]
-        self.all_config_symbols = set(collect_config_symbols(options))
+        self.all_config_symbols = set(conf.settings.keys())
         # Find hash modules by name.
         hash_symbols = self.config_symbols_matching(r'MBEDTLS_(MD|RIPEMD|SHA)[0-9]+_C\Z')
         # Find elliptic curve enabling macros by name.
@@ -442,16 +450,19 @@
         else:
             return [self.jobs[name]]
 
-def run(options, job, colors=NO_COLORS):
+def run(options, job, conf, colors=NO_COLORS):
     """Run the specified job (a Job instance)."""
     subprocess.check_call([options.make_command, 'clean'])
     job.announce(colors, None)
-    job.configure(options)
+    if not job.configure(conf, options, colors):
+        job.announce(colors, False)
+        return False
+    conf.write()
     success = job.test(options)
     job.announce(colors, success)
     return success
 
-def run_tests(options, domain_data):
+def run_tests(options, domain_data, conf):
     """Run the desired jobs.
 domain_data should be a DomainData instance that describes the available
 domains and jobs.
@@ -467,7 +478,7 @@
     backup_config(options)
     try:
         for job in jobs:
-            success = run(options, job, colors=colors)
+            success = run(options, job, conf, colors=colors)
             if not success:
                 if options.keep_going:
                     failures.append(job.name)
@@ -533,7 +544,9 @@
                             default=True)
         options = parser.parse_args()
         os.chdir(options.directory)
-        domain_data = DomainData(options)
+        conf = config.ConfigFile(options.config)
+        domain_data = DomainData(options, conf)
+
         if options.tasks is True:
             options.tasks = sorted(domain_data.domains.keys())
         if options.list:
@@ -542,7 +555,7 @@
                     print(domain_name)
             sys.exit(0)
         else:
-            sys.exit(0 if run_tests(options, domain_data) else 1)
+            sys.exit(0 if run_tests(options, domain_data, conf) else 1)
     except Exception: # pylint: disable=broad-except
         traceback.print_exc()
         sys.exit(3)
diff --git a/tests/src/psa_exercise_key.c b/tests/src/psa_exercise_key.c
index ecd1ec4..5f9f767 100644
--- a/tests/src/psa_exercise_key.c
+++ b/tests/src/psa_exercise_key.c
@@ -778,6 +778,10 @@
             /* The representation of an ECC Montgomery public key is
              * the raw compressed point */
             TEST_EQUAL(PSA_BITS_TO_BYTES(bits), exported_length);
+        } else if (PSA_KEY_TYPE_ECC_GET_FAMILY(type) == PSA_ECC_FAMILY_TWISTED_EDWARDS) {
+            /* The representation of an ECC Edwards public key is
+             * the raw compressed point */
+            TEST_EQUAL(PSA_BITS_TO_BYTES(bits + 1), exported_length);
         } else {
             /* The representation of an ECC Weierstrass public key is:
              *      - The byte 0x04;
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 96537c2..ee9f157 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -9,8 +9,7 @@
 #include "bignum_mod_raw_invasive.h"
 
 #if defined(MBEDTLS_TEST_HOOKS) &&                  \
-    (defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||  \
-    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||  \
+    (defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||  \
     defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED))
 #define HAVE_FIX_NEGATIVE
 #endif
@@ -1347,6 +1346,49 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
+void ecp_mod_p224_raw(char *input_N,
+                      char *input_X,
+                      char *result)
+{
+    mbedtls_mpi_uint *X = NULL;
+    mbedtls_mpi_uint *N = NULL;
+    mbedtls_mpi_uint *res = NULL;
+    size_t limbs_X;
+    size_t limbs_N;
+    size_t limbs_res;
+
+    mbedtls_mpi_mod_modulus m;
+    mbedtls_mpi_mod_modulus_init(&m);
+
+    TEST_EQUAL(mbedtls_test_read_mpi_core(&X,   &limbs_X,   input_X), 0);
+    TEST_EQUAL(mbedtls_test_read_mpi_core(&N,   &limbs_N,   input_N), 0);
+    TEST_EQUAL(mbedtls_test_read_mpi_core(&res, &limbs_res, result),  0);
+
+    size_t limbs = limbs_N;
+    size_t bytes = limbs * sizeof(mbedtls_mpi_uint);
+
+    TEST_EQUAL(limbs_X, 448 / biL);
+    TEST_EQUAL(limbs_res, limbs);
+
+    TEST_EQUAL(mbedtls_mpi_mod_modulus_setup(
+                   &m, N, limbs,
+                   MBEDTLS_MPI_MOD_REP_MONTGOMERY), 0);
+
+    TEST_EQUAL(mbedtls_ecp_mod_p224_raw(X, limbs_X), 0);
+    TEST_LE_U(mbedtls_mpi_core_bitlen(X, limbs_X), 224);
+    mbedtls_mpi_mod_raw_fix_quasi_reduction(X, &m);
+    ASSERT_COMPARE(X, bytes, res, bytes);
+
+exit:
+    mbedtls_free(X);
+    mbedtls_free(res);
+
+    mbedtls_mpi_mod_modulus_free(&m);
+    mbedtls_free(N);
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
 void ecp_mod_p521_raw(char *input_N,
                       char *input_X,
                       char *result)
diff --git a/tests/suites/test_suite_md.data b/tests/suites/test_suite_md.data
index 5659ff4..79b8376 100644
--- a/tests/suites/test_suite_md.data
+++ b/tests/suites/test_suite_md.data
@@ -1,6 +1,6 @@
 # Tests of the generic message digest interface
-MD process
-mbedtls_md_process:
+MD list
+mbedtls_md_list:
 
 MD NULL/uninitialised arguments
 md_null_args:
diff --git a/tests/suites/test_suite_md.function b/tests/suites/test_suite_md.function
index 2f60c4e..1e8622b 100644
--- a/tests/suites/test_suite_md.function
+++ b/tests/suites/test_suite_md.function
@@ -3,35 +3,29 @@
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
- * depends_on:MBEDTLS_MD_C
+ * depends_on:MBEDTLS_MD_LIGHT
  * END_DEPENDENCIES
  */
 
-/* BEGIN_CASE */
-void mbedtls_md_process()
+/* BEGIN_CASE depends_on:MBEDTLS_MD_C */
+void mbedtls_md_list()
 {
     const int *md_type_ptr;
     const mbedtls_md_info_t *info;
     mbedtls_md_context_t ctx;
-    unsigned char buf[150];
+    unsigned char out[MBEDTLS_MD_MAX_SIZE] = { 0 };
 
     mbedtls_md_init(&ctx);
-    memset(buf, 0, sizeof(buf));
 
     /*
-     * Very minimal testing of mbedtls_md_process, just make sure the various
-     * xxx_process_wrap() function pointers are valid. (Testing that they
-     * indeed do the right thing would require messing with the internal
-     * state of the underlying mbedtls_md/sha context.)
-     *
-     * Also tests that mbedtls_md_list() only returns valid MDs.
+     * Test that mbedtls_md_list() only returns valid MDs.
      */
     for (md_type_ptr = mbedtls_md_list(); *md_type_ptr != 0; md_type_ptr++) {
         info = mbedtls_md_info_from_type(*md_type_ptr);
         TEST_ASSERT(info != NULL);
         TEST_EQUAL(0, mbedtls_md_setup(&ctx, info, 0));
         TEST_EQUAL(0, mbedtls_md_starts(&ctx));
-        TEST_EQUAL(0, mbedtls_md_process(&ctx, buf));
+        TEST_EQUAL(0, mbedtls_md_finish(&ctx, out));
         mbedtls_md_free(&ctx);
     }
 
@@ -44,21 +38,27 @@
 void md_null_args()
 {
     mbedtls_md_context_t 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 };
 
     mbedtls_md_init(&ctx);
 
     TEST_EQUAL(0, mbedtls_md_get_size(NULL));
+#if defined(MBEDTLS_MD_C)
     TEST_EQUAL(mbedtls_md_get_type(NULL), MBEDTLS_MD_NONE);
     TEST_ASSERT(mbedtls_md_get_name(NULL) == NULL);
 
     TEST_ASSERT(mbedtls_md_info_from_string(NULL) == NULL);
     TEST_ASSERT(mbedtls_md_info_from_ctx(NULL) == NULL);
     TEST_ASSERT(mbedtls_md_info_from_ctx(&ctx) == NULL);
+#endif /* MBEDTLS_MD_C */
 
     TEST_EQUAL(mbedtls_md_setup(&ctx, NULL, 0), MBEDTLS_ERR_MD_BAD_INPUT_DATA);
+#if defined(MBEDTLS_MD_C)
     TEST_EQUAL(mbedtls_md_setup(NULL, info, 0), MBEDTLS_ERR_MD_BAD_INPUT_DATA);
+#endif
 
     TEST_EQUAL(mbedtls_md_starts(NULL), MBEDTLS_ERR_MD_BAD_INPUT_DATA);
     TEST_EQUAL(mbedtls_md_starts(&ctx), MBEDTLS_ERR_MD_BAD_INPUT_DATA);
@@ -71,6 +71,7 @@
 
     TEST_EQUAL(mbedtls_md(NULL, buf, 1, buf), MBEDTLS_ERR_MD_BAD_INPUT_DATA);
 
+#if defined(MBEDTLS_MD_C)
 #if defined(MBEDTLS_FS_IO)
     TEST_EQUAL(mbedtls_md_file(NULL, "", buf), MBEDTLS_ERR_MD_BAD_INPUT_DATA);
 #endif
@@ -93,13 +94,13 @@
 
     TEST_EQUAL(mbedtls_md_hmac(NULL, buf, 1, buf, 1, buf),
                MBEDTLS_ERR_MD_BAD_INPUT_DATA);
-
-    TEST_EQUAL(mbedtls_md_process(NULL, buf), MBEDTLS_ERR_MD_BAD_INPUT_DATA);
-    TEST_EQUAL(mbedtls_md_process(&ctx, buf), MBEDTLS_ERR_MD_BAD_INPUT_DATA);
+#endif /* MBEDTLS_MD_C */
 
     /* Ok, this is not NULL arg but NULL return... */
     TEST_ASSERT(mbedtls_md_info_from_type(MBEDTLS_MD_NONE) == NULL);
+#if defined(MBEDTLS_MD_C)
     TEST_ASSERT(mbedtls_md_info_from_string("no such md") == NULL);
+#endif
 }
 /* END_CASE */
 
@@ -107,24 +108,31 @@
 void md_info(int md_type, char *md_name, int md_size)
 {
     const mbedtls_md_info_t *md_info;
+#if defined(MBEDTLS_MD_C)
     const int *md_type_ptr;
-    int found;
+#else
+    (void) md_name;
+#endif
 
     md_info = mbedtls_md_info_from_type(md_type);
     TEST_ASSERT(md_info != NULL);
+#if defined(MBEDTLS_MD_C)
     TEST_ASSERT(md_info == mbedtls_md_info_from_string(md_name));
+#endif
 
     TEST_EQUAL(mbedtls_md_get_type(md_info), (mbedtls_md_type_t) md_type);
     TEST_EQUAL(mbedtls_md_get_size(md_info), (unsigned char) md_size);
+#if defined(MBEDTLS_MD_C)
     TEST_EQUAL(0, strcmp(mbedtls_md_get_name(md_info), md_name));
 
-    found = 0;
+    int found = 0;
     for (md_type_ptr = mbedtls_md_list(); *md_type_ptr != 0; md_type_ptr++) {
         if (*md_type_ptr == md_type) {
             found = 1;
         }
     }
     TEST_EQUAL(found, 1);
+#endif /* MBEDTLS_MD_C */
 }
 /* END_CASE */
 
@@ -182,8 +190,10 @@
     TEST_ASSERT(md_info != NULL);
     TEST_EQUAL(0, mbedtls_md_setup(&ctx, md_info, 0));
     TEST_EQUAL(0, mbedtls_md_setup(&ctx_copy, md_info, 0));
+#if defined(MBEDTLS_MD_C)
     TEST_ASSERT(mbedtls_md_info_from_ctx(&ctx) == md_info);
     TEST_ASSERT(mbedtls_md_info_from_ctx(&ctx_copy) == md_info);
+#endif /* MBEDTLS_MD_C */
 
     TEST_EQUAL(0, mbedtls_md_starts(&ctx));
     TEST_ASSERT(ctx.md_ctx != NULL);
@@ -222,8 +232,10 @@
     TEST_ASSERT(md_info != NULL);
     TEST_EQUAL(0, mbedtls_md_setup(&ctx, md_info, 0));
     TEST_EQUAL(0, mbedtls_md_setup(&ctx_copy, md_info, 0));
+#if defined(MBEDTLS_MD_C)
     TEST_ASSERT(mbedtls_md_info_from_ctx(&ctx) == md_info);
     TEST_ASSERT(mbedtls_md_info_from_ctx(&ctx_copy) == md_info);
+#endif /* MBEDTLS_MD_C */
 
     halfway = src_str->len / 2;
 
@@ -249,7 +261,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:MBEDTLS_MD_C */
 void mbedtls_md_hmac(int md_type, int trunc_size,
                      data_t *key_str, data_t *src_str,
                      data_t *hash)
@@ -268,7 +280,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:MBEDTLS_MD_C */
 void md_hmac_multi(int md_type, int trunc_size, data_t *key_str,
                    data_t *src_str, data_t *hash)
 {
@@ -282,7 +294,9 @@
     md_info = mbedtls_md_info_from_type(md_type);
     TEST_ASSERT(md_info != NULL);
     TEST_EQUAL(0, mbedtls_md_setup(&ctx, md_info, 1));
+#if defined(MBEDTLS_MD_C)
     TEST_ASSERT(mbedtls_md_info_from_ctx(&ctx) == md_info);
+#endif
 
     halfway = src_str->len / 2;
 
@@ -309,7 +323,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
+/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_MD_C */
 void mbedtls_md_file(int md_type, char *filename,
                      data_t *hash)
 {
diff --git a/tests/suites/test_suite_platform_util.data b/tests/suites/test_suite_platform_util.data
new file mode 100644
index 0000000..948543a
--- /dev/null
+++ b/tests/suites/test_suite_platform_util.data
@@ -0,0 +1,23 @@
+Zeroize len 0, null
+mbedtls_platform_zeroize:0:1
+
+Zeroize len 0, non-null
+mbedtls_platform_zeroize:0:0
+
+Zeroize len 1
+mbedtls_platform_zeroize:1:0
+
+Zeroize len 4
+mbedtls_platform_zeroize:1:0
+
+Zeroize len 5
+mbedtls_platform_zeroize:1:0
+
+Zeroize len 32
+mbedtls_platform_zeroize:32:0
+
+Zeroize len 127
+mbedtls_platform_zeroize:127:0
+
+Zeroize len 128
+mbedtls_platform_zeroize:128:0
diff --git a/tests/suites/test_suite_platform_util.function b/tests/suites/test_suite_platform_util.function
new file mode 100644
index 0000000..e5464e0
--- /dev/null
+++ b/tests/suites/test_suite_platform_util.function
@@ -0,0 +1,41 @@
+/* BEGIN_HEADER */
+#include "mbedtls/platform_util.h"
+/* END_HEADER */
+
+/* BEGIN_CASE */
+void mbedtls_platform_zeroize(int len, int null)
+{
+    char buf[130];
+    char *p = NULL;
+
+    TEST_ASSERT(len <= 128);
+
+    /* Write sentinel values */
+    buf[0] = 2;
+    buf[len + 1] = 2;
+
+    /* Write non-zero content */
+    if (!null) {
+        p = &buf[1];
+        for (int i = 0; i < len; i++) {
+            p[i] = 1;
+        }
+    }
+
+    /* Check content is non-zero */
+    TEST_EQUAL(buf[0], 2);
+    for (int i = 0; i < len; i++) {
+        TEST_ASSERT(p[i] == 1);
+    }
+    TEST_EQUAL(buf[len + 1], 2);
+
+    mbedtls_platform_zeroize(p, len);
+
+    /* Check content is zero and sentinels un-changed */
+    TEST_EQUAL(buf[0], 2);
+    for (int i = 0; i < len; i++) {
+        TEST_ASSERT(p[i] == 0);
+    }
+    TEST_EQUAL(buf[len + 1], 2);
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index cfcdac1..7b55c5f 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -1061,7 +1061,7 @@
 raw_agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_FFDH:PSA_ERROR_NOT_PERMITTED
 
 PSA key policy: raw agreement, key permits raw agreement, but algorithm is not raw
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 raw_agreement_key_policy:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ERROR_NOT_SUPPORTED
 
 PSA key policy: raw agreement, key specifies KDF
@@ -6400,7 +6400,7 @@
 key_agreement_setup:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_INVALID_ARGUMENT
 
 PSA key agreement setup: ECDH, unknown KDF
-depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_ECP_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_ECDH_C
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_ALG_HKDF:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
 key_agreement_setup:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(0)):PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(0)):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":PSA_ERROR_NOT_SUPPORTED
 
 PSA key agreement setup: bad key agreement algorithm
diff --git a/tests/suites/test_suite_psa_crypto_op_fail.function b/tests/suites/test_suite_psa_crypto_op_fail.function
index 970be84..55dce89 100644
--- a/tests/suites/test_suite_psa_crypto_op_fail.function
+++ b/tests/suites/test_suite_psa_crypto_op_fail.function
@@ -245,13 +245,11 @@
                               input, sizeof(input),
                               output, sizeof(output), &length));
 
-    if (PSA_KEY_TYPE_IS_ECC(key_type)) {
-        TEST_STATUS(expected_status,
-                    psa_sign_hash_start(&sign_operation, key_id, alg,
-                                        input, sizeof(input)));
+    TEST_STATUS(expected_status,
+                psa_sign_hash_start(&sign_operation, key_id, alg,
+                                    input, sizeof(input)));
 
-        PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
-    }
+    PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
 
     if (!private_only) {
         /* Determine a plausible signature size to avoid an INVALID_SIGNATURE
@@ -270,14 +268,12 @@
                                     input, sizeof(input),
                                     output, output_length));
 
-        if (PSA_KEY_TYPE_IS_ECC(key_type)) {
-            TEST_STATUS(expected_status,
-                        psa_verify_hash_start(&verify_operation, key_id, alg,
-                                              input, sizeof(input),
-                                              output, output_length));
+        TEST_STATUS(expected_status,
+                    psa_verify_hash_start(&verify_operation, key_id, alg,
+                                          input, sizeof(input),
+                                          output, output_length));
 
-            PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
-        }
+        PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
     }
 
 exit:
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 15246cb..9e37259 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -18,6 +18,12 @@
 #include <constant_time_internal.h>
 #include <test/constant_flow.h>
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
+                                                           psa_to_ssl_errors, \
+                                                           psa_generic_status_to_mbedtls)
+#endif
+
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
@@ -1299,27 +1305,27 @@
                                       transform->psa_key_enc, transform->psa_alg);
 
     if (status != PSA_SUCCESS) {
-        return psa_ssl_status_to_mbedtls(status);
+        return PSA_TO_MBEDTLS_ERR(status);
     }
 
     status = psa_cipher_set_iv(&cipher_op, iv, iv_len);
 
     if (status != PSA_SUCCESS) {
-        return psa_ssl_status_to_mbedtls(status);
+        return PSA_TO_MBEDTLS_ERR(status);
     }
 
     status = psa_cipher_update(&cipher_op,
                                input, ilen, output, ilen, olen);
 
     if (status != PSA_SUCCESS) {
-        return psa_ssl_status_to_mbedtls(status);
+        return PSA_TO_MBEDTLS_ERR(status);
     }
 
     status = psa_cipher_finish(&cipher_op,
                                output + *olen, ilen - *olen, &part_len);
 
     if (status != PSA_SUCCESS) {
-        return psa_ssl_status_to_mbedtls(status);
+        return PSA_TO_MBEDTLS_ERR(status);
     }
 
     *olen += part_len;
@@ -1614,7 +1620,7 @@
                                        &key_bits);
 
     if (status != PSA_SUCCESS) {
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
@@ -1633,7 +1639,7 @@
                                 &t_in->psa_key_enc);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             goto cleanup;
         }
 
@@ -1643,7 +1649,7 @@
                                 &t_out->psa_key_enc);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             goto cleanup;
         }
 
@@ -1655,7 +1661,7 @@
                                 &t_in->psa_key_dec);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             goto cleanup;
         }
 
@@ -1665,7 +1671,7 @@
                                 &t_out->psa_key_dec);
 
         if (status != PSA_SUCCESS) {
-            ret = psa_ssl_status_to_mbedtls(status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
             goto cleanup;
         }
     }
@@ -1735,7 +1741,7 @@
                                                session->peer_cert_digest,
                                                MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN,
                                                &hash_size);
-        ret = psa_ssl_status_to_mbedtls(status);
+        ret = PSA_TO_MBEDTLS_ERR(status);
 #else
         ret = mbedtls_md(mbedtls_md_info_from_type(
                              MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE),