Merge pull request #6823 from mpg/unify-openssl-variables

Use OPENSSL everywhere, not OPENSSL_CMD
diff --git a/.pylintrc b/.pylintrc
index 10c93f8..f395fb9 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -1,5 +1,6 @@
 [MASTER]
 init-hook='import sys; sys.path.append("scripts")'
+min-similarity-lines=10
 
 [BASIC]
 # We're ok with short funtion argument names.
diff --git a/.uncrustify.cfg b/.uncrustify.cfg
index ac9173e..7ce0905 100644
--- a/.uncrustify.cfg
+++ b/.uncrustify.cfg
@@ -187,8 +187,8 @@
 # No space before the ':' in a case statement
 sp_before_case_colon = remove
 
-# No space after a cast - '(char) x' -> '(char)x'
-sp_after_cast = remove
+# Must have space after a cast - '(char)x' -> '(char) x'
+sp_after_cast = add
 
 # No space between 'sizeof' and '('
 sp_sizeof_paren = remove
diff --git a/ChangeLog.d/fix-gettimeofday-overflow.txt b/ChangeLog.d/fix-gettimeofday-overflow.txt
new file mode 100644
index 0000000..b7e10d2
--- /dev/null
+++ b/ChangeLog.d/fix-gettimeofday-overflow.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix possible integer overflow in mbedtls_timing_hardclock(), which
+     could cause a crash in programs/test/benchmark.
diff --git a/ChangeLog.d/fix-iar-warnings.txt b/ChangeLog.d/fix-iar-warnings.txt
new file mode 100644
index 0000000..244e863
--- /dev/null
+++ b/ChangeLog.d/fix-iar-warnings.txt
@@ -0,0 +1,2 @@
+Bugfix
+   * Fix IAR compiler warnings. Contributed by Glenn Strauss in #3835.
diff --git a/ChangeLog.d/fix_build_for_directory_names_containing_spaces.txt b/ChangeLog.d/fix_build_for_directory_names_containing_spaces.txt
new file mode 100644
index 0000000..e7643b7
--- /dev/null
+++ b/ChangeLog.d/fix_build_for_directory_names_containing_spaces.txt
@@ -0,0 +1,4 @@
+Bugfix
+   * Fix a bug in the build where directory names containing spaces were
+     causing generate_errors.pl to error out resulting in a build failure.
+     Fixes issue #6879.
diff --git a/ChangeLog.d/make_sha224_sha384_independent_from_sha256_sha512.txt b/ChangeLog.d/make_sha224_sha384_independent_from_sha256_sha512.txt
new file mode 100644
index 0000000..d2c9b35
--- /dev/null
+++ b/ChangeLog.d/make_sha224_sha384_independent_from_sha256_sha512.txt
@@ -0,0 +1,4 @@
+Features
+   * SHA224_C/SHA384_C are now independent from SHA384_C/SHA512_C respectively.
+     This helps in saving code size when some of the above hashes are not
+     required.
diff --git a/ChangeLog.d/mbedtls_ecp_point_read_binary-compressed-fmt.txt b/ChangeLog.d/mbedtls_ecp_point_read_binary-compressed-fmt.txt
new file mode 100644
index 0000000..44253dd
--- /dev/null
+++ b/ChangeLog.d/mbedtls_ecp_point_read_binary-compressed-fmt.txt
@@ -0,0 +1,6 @@
+Features
+   * Add support for reading points in compressed format
+     (MBEDTLS_ECP_PF_COMPRESSED) with mbedtls_ecp_point_read_binary()
+     (and callers) for Short Weierstrass curves with prime p where p = 3 mod 4
+     (all mbedtls MBEDTLS_ECP_DP_SECP* and MBEDTLS_ECP_DP_BP* curves
+      except MBEDTLS_ECP_DP_SECP224R1 and MBEDTLS_ECP_DP_SECP224K1)
diff --git a/configs/config-ccm-psk-dtls1_2.h b/configs/config-ccm-psk-dtls1_2.h
index 183815d..02bc829 100644
--- a/configs/config-ccm-psk-dtls1_2.h
+++ b/configs/config-ccm-psk-dtls1_2.h
@@ -47,10 +47,6 @@
 #define MBEDTLS_ENTROPY_C
 #define MBEDTLS_MD_C
 #define MBEDTLS_NET_C
-/* The library does not currently support enabling SHA-224 without SHA-256.
- * A future version of the library will have this option disabled
- * by default. */
-#define MBEDTLS_SHA224_C
 #define MBEDTLS_SHA256_C
 #define MBEDTLS_SSL_CLI_C
 #define MBEDTLS_SSL_COOKIE_C
diff --git a/configs/config-ccm-psk-tls1_2.h b/configs/config-ccm-psk-tls1_2.h
index f935a33..84e5db3 100644
--- a/configs/config-ccm-psk-tls1_2.h
+++ b/configs/config-ccm-psk-tls1_2.h
@@ -46,10 +46,6 @@
 #define MBEDTLS_ENTROPY_C
 #define MBEDTLS_MD_C
 #define MBEDTLS_NET_C
-/* The library does not currently support enabling SHA-224 without SHA-256.
- * A future version of the library will have this option disabled
- * by default. */
-#define MBEDTLS_SHA224_C
 #define MBEDTLS_SHA256_C
 #define MBEDTLS_SSL_CLI_C
 #define MBEDTLS_SSL_SRV_C
diff --git a/configs/config-suite-b.h b/configs/config-suite-b.h
index 35622fc..89898b3 100644
--- a/configs/config-suite-b.h
+++ b/configs/config-suite-b.h
@@ -60,10 +60,6 @@
 #define MBEDTLS_OID_C
 #define MBEDTLS_PK_C
 #define MBEDTLS_PK_PARSE_C
-/* The library does not currently support enabling SHA-224 without SHA-256.
- * A future version of the library will have this option disabled
- * by default. */
-#define MBEDTLS_SHA224_C
 #define MBEDTLS_SHA256_C
 #define MBEDTLS_SHA384_C
 #define MBEDTLS_SHA512_C
diff --git a/configs/config-thread.h b/configs/config-thread.h
index c032fdc..0652136 100644
--- a/configs/config-thread.h
+++ b/configs/config-thread.h
@@ -63,10 +63,6 @@
 #define MBEDTLS_OID_C
 #define MBEDTLS_PK_C
 #define MBEDTLS_PK_PARSE_C
-/* The library does not currently support enabling SHA-224 without SHA-256.
- * A future version of the library will have this option disabled
- * by default. */
-#define MBEDTLS_SHA224_C
 #define MBEDTLS_SHA256_C
 #define MBEDTLS_SSL_COOKIE_C
 #define MBEDTLS_SSL_CLI_C
diff --git a/docs/use-psa-crypto.md b/docs/use-psa-crypto.md
index 194d96f..fc5317a 100644
--- a/docs/use-psa-crypto.md
+++ b/docs/use-psa-crypto.md
@@ -95,8 +95,6 @@
 
 Current exceptions:
 
-- Verification of RSA-PSS signatures with a salt length that is different from
-  the hash length.
 - Restartable operations when `MBEDTLS_ECP_RESTARTABLE` is also enabled (see
   the documentation of that option).
 
@@ -107,11 +105,11 @@
 
 Current exceptions:
 
-- Verification of RSA-PSS signatures with a salt length that is different from
-  the hash length, or with an MGF hash that's different from the message hash.
+- Verification of RSA-PSS signatures with an MGF hash that's different from
+  the message hash.
 - Restartable operations when `MBEDTLS_ECP_RESTARTABLE` is also enabled (see
   the documentation of that option).
 
-Other than the above exception, all crypto operations are based on PSA when
+Other than the above exceptions, all crypto operations are based on PSA when
 `MBEDTLS_USE_PSA_CRYPTO` is enabled.
 
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 99584c4..1efabdc 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -695,10 +695,6 @@
 #error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_SHA384_C) && !defined(MBEDTLS_SHA512_C)
-#error "MBEDTLS_SHA384_C defined without MBEDTLS_SHA512_C"
-#endif
-
 #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) && \
     defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
 #error "Must only define one of MBEDTLS_SHA512_USE_A64_CRYPTO_*"
@@ -754,14 +750,6 @@
 #error "MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY defined on non-Aarch64 system"
 #endif
 
-#if defined(MBEDTLS_SHA224_C) && !defined(MBEDTLS_SHA256_C)
-#error "MBEDTLS_SHA224_C defined without MBEDTLS_SHA256_C"
-#endif
-
-#if defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA224_C)
-#error "MBEDTLS_SHA256_C defined without MBEDTLS_SHA224_C"
-#endif
-
 #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) && \
     defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
 #error "Must only define one of MBEDTLS_SHA256_USE_A64_CRYPTO_*"
@@ -872,6 +860,10 @@
 #error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && !defined(MBEDTLS_X509_CRT_PARSE_C)
+#error "MBEDTLS_SSL_ASYNC_PRIVATE defined, but not all prerequisites"
+#endif
+
 #if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) ||     \
     ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) )
 #error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites"
@@ -1021,6 +1013,11 @@
 #error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) && \
+            ( !defined(MBEDTLS_X509_CRT_PARSE_C) )
+#error "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK defined, but not all prerequisites"
+#endif
+
 #if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64)
 #error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously"
 #endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index b9c896f..8a4a0d2 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -1408,6 +1408,7 @@
  * module to perform private key operations instead of performing the
  * operation inside the library.
  *
+ * Requires: MBEDTLS_X509_CRT_PARSE_C
  */
 //#define MBEDTLS_SSL_ASYNC_PRIVATE
 
@@ -2012,6 +2013,8 @@
  * See the documentation of `mbedtls_x509_crt_verify_with_ca_cb()` and
  * `mbedtls_ssl_conf_ca_cb()` for more information.
  *
+ * Requires: MBEDTLS_X509_CRT_PARSE_C
+ *
  * Uncomment to enable trusted certificate callbacks.
  */
 //#define MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
@@ -3046,9 +3049,6 @@
  *
  * Enable the SHA-224 cryptographic hash algorithm.
  *
- * Requires: MBEDTLS_SHA256_C. The library does not currently support enabling
- *           SHA-224 without SHA-256.
- *
  * Module:  library/sha256.c
  * Caller:  library/md.c
  *          library/ssl_cookie.c
@@ -3062,9 +3062,6 @@
  *
  * Enable the SHA-256 cryptographic hash algorithm.
  *
- * Requires: MBEDTLS_SHA224_C. The library does not currently support enabling
- *           SHA-256 without SHA-224.
- *
  * Module:  library/sha256.c
  * Caller:  library/entropy.c
  *          library/md.c
@@ -3132,8 +3129,6 @@
  *
  * Enable the SHA-384 cryptographic hash algorithm.
  *
- * Requires: MBEDTLS_SHA512_C
- *
  * Module:  library/sha512.c
  * Caller:  library/md.c
  *          library/psa_crypto_hash.c
diff --git a/include/mbedtls/md.h b/include/mbedtls/md.h
index fbf938d..85ecc43 100644
--- a/include/mbedtls/md.h
+++ b/include/mbedtls/md.h
@@ -65,8 +65,14 @@
 
 #if defined(MBEDTLS_SHA512_C)
 #define MBEDTLS_MD_MAX_SIZE         64  /* longest known is SHA512 */
+#elif defined(MBEDTLS_SHA384_C)
+#define MBEDTLS_MD_MAX_SIZE         48  /* longest known is SHA384 */
+#elif defined(MBEDTLS_SHA256_C)
+#define MBEDTLS_MD_MAX_SIZE         32  /* longest known is SHA256 */
+#elif defined(MBEDTLS_SHA224_C)
+#define MBEDTLS_MD_MAX_SIZE         28  /* longest known is SHA224 */
 #else
-#define MBEDTLS_MD_MAX_SIZE         32  /* longest known is SHA256 or less */
+#define MBEDTLS_MD_MAX_SIZE         20  /* longest known is SHA1 or RIPE MD-160 */
 #endif
 
 #if defined(MBEDTLS_SHA512_C)
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index db0bfac..386ec42 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -496,7 +496,9 @@
  *
  * \note            If type is MBEDTLS_PK_RSASSA_PSS, then options must point
  *                  to a mbedtls_pk_rsassa_pss_options structure,
- *                  otherwise it must be NULL.
+ *                  otherwise it must be NULL. Note that if
+ *                  #MBEDTLS_USE_PSA_CRYPTO is defined, the salt length is not
+ *                  verified as PSA_ALG_RSA_PSS_ANY_SALT is used.
  */
 int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
                    mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h
index f030bea..f2f5400 100644
--- a/include/mbedtls/psa_util.h
+++ b/include/mbedtls/psa_util.h
@@ -264,22 +264,6 @@
 #define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH \
     PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE( PSA_VENDOR_ECC_MAX_CURVE_BITS )
 
-/* This function transforms an ECC group identifier from
- * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
- * into a PSA ECC group identifier. */
-#if defined(MBEDTLS_ECP_C)
-static inline psa_key_type_t mbedtls_psa_parse_tls_ecc_group(
-    uint16_t tls_ecc_grp_reg_id, size_t *bits )
-{
-    const mbedtls_ecp_curve_info *curve_info =
-        mbedtls_ecp_curve_info_from_tls_id( tls_ecc_grp_reg_id );
-    if( curve_info == NULL )
-        return( 0 );
-    return( PSA_KEY_TYPE_ECC_KEY_PAIR(
-                mbedtls_ecc_group_to_psa( curve_info->grp_id, bits ) ) );
-}
-#endif /* MBEDTLS_ECP_C */
-
 /* Expose whatever RNG the PSA subsystem uses to applications using the
  * mbedtls_xxx API. The declarations and definitions here need to be
  * consistent with the implementation in library/psa_crypto_random_impl.h.
diff --git a/include/mbedtls/sha256.h b/include/mbedtls/sha256.h
index 0cbbac1..d256352 100644
--- a/include/mbedtls/sha256.h
+++ b/include/mbedtls/sha256.h
@@ -96,6 +96,10 @@
  * \param is224    This determines which function to use. This must be
  *                 either \c 0 for SHA-256, or \c 1 for SHA-224.
  *
+ * \note           is224 must be defined accordingly to the enabled
+ *                 MBEDTLS_SHA224_C/MBEDTLS_SHA256_C symbols otherwise the
+ *                 function will return #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA.
+ *
  * \return         \c 0 on success.
  * \return         A negative error code on failure.
  */
@@ -178,13 +182,25 @@
 
 #if defined(MBEDTLS_SELF_TEST)
 
+#if defined(MBEDTLS_SHA224_C)
 /**
- * \brief          The SHA-224 and SHA-256 checkup routine.
+ * \brief          The SHA-224 checkup routine.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ */
+int mbedtls_sha224_self_test( int verbose );
+#endif /* MBEDTLS_SHA224_C */
+
+#if defined(MBEDTLS_SHA256_C)
+/**
+ * \brief          The SHA-256 checkup routine.
  *
  * \return         \c 0 on success.
  * \return         \c 1 on failure.
  */
 int mbedtls_sha256_self_test( int verbose );
+#endif /* MBEDTLS_SHA256_C */
 
 #endif /* MBEDTLS_SELF_TEST */
 
diff --git a/include/mbedtls/sha512.h b/include/mbedtls/sha512.h
index 48901cc..2b1fafd 100644
--- a/include/mbedtls/sha512.h
+++ b/include/mbedtls/sha512.h
@@ -99,9 +99,9 @@
  * \param is384    Determines which function to use. This must be
  *                 either \c 0 for SHA-512, or \c 1 for SHA-384.
  *
- * \note           When \c MBEDTLS_SHA384_C is not defined,
- *                 \p is384 must be \c 0, or the function will return
- *                 #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA.
+ * \note           is384 must be defined accordingly to the enabled
+ *                 MBEDTLS_SHA384_C/MBEDTLS_SHA512_C symbols otherwise the
+ *                 function will return #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA.
  *
  * \return         \c 0 on success.
  * \return         A negative error code on failure.
@@ -175,8 +175,11 @@
  * \param is384    Determines which function to use. This must be either
  *                 \c 0 for SHA-512, or \c 1 for SHA-384.
  *
- * \note           When \c MBEDTLS_SHA384_C is not defined, \p is384 must
- *                 be \c 0, or the function will return
+ * \note           is384 must be defined accordingly with the supported
+ *                 symbols in the config file. If:
+ *                 - is384 is 0, but \c MBEDTLS_SHA384_C is not defined, or
+ *                 - is384 is 1, but \c MBEDTLS_SHA512_C is not defined
+ *                 then the function will return
  *                 #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA.
  *
  * \return         \c 0 on success.
@@ -189,13 +192,26 @@
 
 #if defined(MBEDTLS_SELF_TEST)
 
+#if defined(MBEDTLS_SHA384_C)
  /**
- * \brief          The SHA-384 or SHA-512 checkup routine.
+ * \brief          The SHA-384 checkup routine.
+ *
+ * \return         \c 0 on success.
+ * \return         \c 1 on failure.
+ */
+int mbedtls_sha384_self_test( int verbose );
+#endif /* MBEDTLS_SHA384_C */
+
+#if defined(MBEDTLS_SHA512_C)
+ /**
+ * \brief          The SHA-512 checkup routine.
  *
  * \return         \c 0 on success.
  * \return         \c 1 on failure.
  */
 int mbedtls_sha512_self_test( int verbose );
+#endif /* MBEDTLS_SHA512_C */
+
 #endif /* MBEDTLS_SELF_TEST */
 
 #ifdef __cplusplus
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 7751560..ac13275 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1656,9 +1656,11 @@
     mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform);           /*!<  negotiated transform params
                                                                   *    This pointer owns the transform
                                                                   *    it references.                  */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_negotiate); /*!<  transform params in negotiation
                                                                   *    This pointer owns the transform
                                                                   *    it references.                  */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     /*! The application data transform in TLS 1.3.
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index cf8a7b2..ff50f7e 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -58,6 +58,13 @@
  * value, check with the Arm PSA framework group to pick one that other
  * domains aren't already using. */
 
+/* Tell uncrustify not to touch the constant definitions, otherwise
+ * it might change the spacing to something that is not PSA-compliant
+ * (e.g. adding a space after casts).
+ *
+ * *INDENT-OFF*
+ */
+
 /** The action was completed successfully. */
 #define PSA_SUCCESS ((psa_status_t)0)
 
@@ -328,6 +335,8 @@
  */
 #define PSA_ERROR_DATA_INVALID          ((psa_status_t)-153)
 
+/* *INDENT-ON* */
+
 /**@}*/
 
 /** \defgroup crypto_types Key and algorithm types
@@ -883,7 +892,9 @@
      (alg) & PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG)
 
 /** An invalid algorithm identifier value. */
+/* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */
 #define PSA_ALG_NONE                            ((psa_algorithm_t)0)
+/* *INDENT-ON* */
 
 #define PSA_ALG_HASH_MASK                       ((psa_algorithm_t)0x000000ff)
 /** MD5 */
@@ -2378,7 +2389,9 @@
 
 /** The null key identifier.
  */
+/* *INDENT-OFF* (https://github.com/ARM-software/psa-arch-tests/issues/337) */
 #define PSA_KEY_ID_NULL                         ((psa_key_id_t)0)
+/* *INDENT-ON* */
 /** The minimum value for a key identifier chosen by the application.
  */
 #define PSA_KEY_ID_USER_MIN                     ((psa_key_id_t)0x00000001)
diff --git a/library/aesni.c b/library/aesni.c
index 87d818a..12125c9 100644
--- a/library/aesni.c
+++ b/library/aesni.c
@@ -36,9 +36,11 @@
 
 #include <string.h>
 
+/* *INDENT-OFF* */
 #ifndef asm
 #define asm __asm
 #endif
+/* *INDENT-ON* */
 
 #if defined(MBEDTLS_HAVE_X86_64)
 
diff --git a/library/bignum.c b/library/bignum.c
index fc4ddf6..62eb007 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -1197,9 +1197,9 @@
      */
     if( 0 == d || u1 >= d )
     {
-        if (r != NULL) *r = ~0;
+        if (r != NULL) *r = ~(mbedtls_mpi_uint)0u;
 
-        return ( ~0 );
+        return ( ~(mbedtls_mpi_uint)0u );
     }
 
 #if defined(MBEDTLS_HAVE_UDBL)
@@ -1338,7 +1338,7 @@
     for( i = n; i > t ; i-- )
     {
         if( X.p[i] >= Y.p[t] )
-            Z.p[i - t - 1] = ~0;
+            Z.p[i - t - 1] = ~(mbedtls_mpi_uint)0u;
         else
         {
             Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1],
diff --git a/library/bignum_mod.c b/library/bignum_mod.c
index 31e18e7..bd67241 100644
--- a/library/bignum_mod.c
+++ b/library/bignum_mod.c
@@ -176,6 +176,28 @@
 
 /* BEGIN MERGE SLOT 2 */
 
+int mbedtls_mpi_mod_mul( mbedtls_mpi_mod_residue *X,
+                         const mbedtls_mpi_mod_residue *A,
+                         const mbedtls_mpi_mod_residue *B,
+                         const mbedtls_mpi_mod_modulus *N )
+{
+    if( N->limbs == 0 )
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+    if( X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs )
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+    mbedtls_mpi_uint *T = mbedtls_calloc( N->limbs * 2 + 1, ciL );
+    if( T == NULL )
+        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
+
+    mbedtls_mpi_mod_raw_mul( X->p, A->p, B->p, N, T );
+
+    mbedtls_free( T );
+
+    return( 0 );
+}
+
 /* END MERGE SLOT 2 */
 
 /* BEGIN MERGE SLOT 3 */
@@ -303,6 +325,17 @@
 
 /* BEGIN MERGE SLOT 6 */
 
+int mbedtls_mpi_mod_random( mbedtls_mpi_mod_residue *X,
+                            mbedtls_mpi_uint min,
+                            const mbedtls_mpi_mod_modulus *N,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng )
+{
+    if( X->limbs != N->limbs )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    return( mbedtls_mpi_mod_raw_random( X->p, min, N, f_rng, p_rng ) );
+}
+
 /* END MERGE SLOT 6 */
 
 /* BEGIN MERGE SLOT 7 */
@@ -326,8 +359,7 @@
 
     r->limbs = m->limbs;
 
-    if( m->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY )
-       ret = mbedtls_mpi_mod_raw_to_mont_rep( r->p, m );
+    ret = mbedtls_mpi_mod_raw_canonical_to_modulus_rep( r->p, m );
 
 cleanup:
     return ( ret );
diff --git a/library/bignum_mod.h b/library/bignum_mod.h
index 95aaacc..1b1e920 100644
--- a/library/bignum_mod.h
+++ b/library/bignum_mod.h
@@ -87,12 +87,23 @@
 #include "mbedtls/bignum.h"
 #endif
 
-/* Skip 1 as it is slightly easier to accidentally pass to functions. */
+/** How residues associated with a modulus are represented.
+ *
+ * This also determines which fields of the modulus structure are valid and
+ * what their contents are (see #mbedtls_mpi_mod_modulus).
+ */
 typedef enum
 {
+    /** Representation not chosen (makes the modulus structure invalid). */
     MBEDTLS_MPI_MOD_REP_INVALID    = 0,
+    /* Skip 1 as it is slightly easier to accidentally pass to functions. */
+    /** Montgomery representation. */
     MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2,
-    MBEDTLS_MPI_MOD_REP_OPT_RED
+    /** TODO: document this.
+     *
+     * Residues are in canonical representation.
+     */
+    MBEDTLS_MPI_MOD_REP_OPT_RED,
 } mbedtls_mpi_mod_rep_selector;
 
 /* Make mbedtls_mpi_mod_rep_selector and mbedtls_mpi_mod_ext_rep disjoint to
@@ -124,7 +135,9 @@
     mbedtls_mpi_mod_rep_selector int_rep;    // selector to signal the active member of the union
     union rep
     {
+        /* if int_rep == #MBEDTLS_MPI_MOD_REP_MONTGOMERY */
         mbedtls_mpi_mont_struct mont;
+        /* if int_rep == #MBEDTLS_MPI_MOD_REP_OPT_RED */
         mbedtls_mpi_opt_red_struct ored;
     } rep;
 } mbedtls_mpi_mod_modulus;
@@ -217,6 +230,40 @@
 
 /* BEGIN MERGE SLOT 2 */
 
+/** \brief  Multiply two residues, returning the residue modulo the specified
+ *          modulus.
+ *
+ * \note Currently handles the case when `N->int_rep` is
+ * MBEDTLS_MPI_MOD_REP_MONTGOMERY.
+ *
+ * The size of the operation is determined by \p N. \p A, \p B and \p X must
+ * all be associated with the modulus \p N and must all have the same number
+ * of limbs as \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise. They may not alias \p N (since they must be in canonical
+ * form, they cannot == \p N).
+ *
+ * \param[out] X        The address of the result MPI. Must have the same
+ *                      number of limbs as \p N.
+ *                      On successful completion, \p X contains the result of
+ *                      the multiplication `A * B * R^-1` mod N where
+ *                      `R = 2^(biL * N->limbs)`.
+ * \param[in]  A        The address of the first MPI.
+ * \param[in]  B        The address of the second MPI.
+ * \param[in]  N        The address of the modulus. Used to perform a modulo
+ *                      operation on the result of the multiplication.
+ *
+ * \return      \c 0 if successful.
+ * \return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if all the parameters do not
+ *              have the same number of limbs or \p N is invalid.
+ * \return      #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ */
+int mbedtls_mpi_mod_mul( mbedtls_mpi_mod_residue *X,
+                         const mbedtls_mpi_mod_residue *A,
+                         const mbedtls_mpi_mod_residue *B,
+                         const mbedtls_mpi_mod_modulus *N );
+
 /* END MERGE SLOT 2 */
 
 /* BEGIN MERGE SLOT 3 */
@@ -319,6 +366,39 @@
 
 /* BEGIN MERGE SLOT 6 */
 
+/** Generate a random number uniformly in a range.
+ *
+ * This function generates a random number between \p min inclusive and
+ * \p N exclusive.
+ *
+ * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
+ * when the RNG is a suitably parametrized instance of HMAC_DRBG
+ * and \p min is \c 1.
+ *
+ * \note           There are `N - min` possible outputs. The lower bound
+ *                 \p min can be reached, but the upper bound \p N cannot.
+ *
+ * \param X        The destination residue.
+ * \param min      The minimum value to return. It must be strictly smaller
+ *                 than \b N.
+ * \param N        The modulus.
+ *                 This is the upper bound of the output range, exclusive.
+ * \param f_rng    The RNG function to use. This must not be \c NULL.
+ * \param p_rng    The RNG parameter to be passed to \p f_rng.
+ *
+ * \return         \c 0 if successful.
+ * \return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
+ *                 unable to find a suitable value within a limited number
+ *                 of attempts. This has a negligible probability if \p N
+ *                 is significantly larger than \p min, which is the case
+ *                 for all usual cryptographic applications.
+ */
+int mbedtls_mpi_mod_random( mbedtls_mpi_mod_residue *X,
+                            mbedtls_mpi_uint min,
+                            const mbedtls_mpi_mod_modulus *N,
+                            int (*f_rng)(void *, unsigned char *, size_t),
+                            void *p_rng );
+
 /* END MERGE SLOT 6 */
 
 /* BEGIN MERGE SLOT 7 */
diff --git a/library/bignum_mod_raw.c b/library/bignum_mod_raw.c
index 5950ff6..18599c3 100644
--- a/library/bignum_mod_raw.c
+++ b/library/bignum_mod_raw.c
@@ -186,6 +186,48 @@
 
 /* BEGIN MERGE SLOT 6 */
 
+int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
+    mbedtls_mpi_uint *X,
+    const mbedtls_mpi_mod_modulus *N )
+{
+    switch( N->int_rep )
+    {
+        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+            return( mbedtls_mpi_mod_raw_to_mont_rep( X, N ) );
+        case MBEDTLS_MPI_MOD_REP_OPT_RED:
+            return( 0 );
+        default:
+            return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    }
+}
+
+int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
+    mbedtls_mpi_uint *X,
+    const mbedtls_mpi_mod_modulus *N )
+{
+    switch( N->int_rep )
+    {
+        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+            return( mbedtls_mpi_mod_raw_from_mont_rep( X, N ) );
+        case MBEDTLS_MPI_MOD_REP_OPT_RED:
+            return( 0 );
+        default:
+            return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    }
+}
+
+int mbedtls_mpi_mod_raw_random( mbedtls_mpi_uint *X,
+                                mbedtls_mpi_uint min,
+                                const mbedtls_mpi_mod_modulus *N,
+                                int (*f_rng)(void *, unsigned char *, size_t),
+                                void *p_rng )
+{
+    int ret = mbedtls_mpi_core_random( X, min, N->p, N->limbs, f_rng, p_rng );
+    if( ret != 0 )
+        return( ret );
+    return( mbedtls_mpi_mod_raw_canonical_to_modulus_rep( X, N ) );
+}
+
 /* END MERGE SLOT 6 */
 
 /* BEGIN MERGE SLOT 7 */
diff --git a/library/bignum_mod_raw.h b/library/bignum_mod_raw.h
index 0fac6f8..ea3207f 100644
--- a/library/bignum_mod_raw.h
+++ b/library/bignum_mod_raw.h
@@ -336,6 +336,74 @@
 
 /* BEGIN MERGE SLOT 6 */
 
+/** Convert an MPI from canonical representation (little-endian limb array)
+ * to the representation associated with the modulus.
+ *
+ * \param[in,out] X The limb array to convert.
+ *                  It must have as many limbs as \p N.
+ *                  It is converted in place.
+ *                  If this function returns an error, the content of \p X
+ *                  is unspecified.
+ * \param[in] N     The modulus structure.
+ *
+ *\ return          \c 0 if successful.
+ *                  Otherwise an \c MBEDTLS_ERR_MPI_xxx error code.
+ */
+int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
+    mbedtls_mpi_uint *X,
+    const mbedtls_mpi_mod_modulus *N );
+
+/** Convert an MPI from the representation associated with the modulus
+ * to canonical representation (little-endian limb array).
+ *
+ * \param[in,out] X The limb array to convert.
+ *                  It must have as many limbs as \p N.
+ *                  It is converted in place.
+ *                  If this function returns an error, the content of \p X
+ *                  is unspecified.
+ * \param[in] N     The modulus structure.
+ *
+ *\ return          \c 0 if successful.
+ *                  Otherwise an \c MBEDTLS_ERR_MPI_xxx error code.
+ */
+int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
+    mbedtls_mpi_uint *X,
+    const mbedtls_mpi_mod_modulus *N );
+
+/** Generate a random number uniformly in a range.
+ *
+ * This function generates a random number between \p min inclusive and
+ * \p N exclusive.
+ *
+ * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
+ * when the RNG is a suitably parametrized instance of HMAC_DRBG
+ * and \p min is \c 1.
+ *
+ * \note           There are `N - min` possible outputs. The lower bound
+ *                 \p min can be reached, but the upper bound \p N cannot.
+ *
+ * \param X        The destination MPI, in canonical representation modulo \p N.
+ *                 It must not be aliased with \p N or otherwise overlap it.
+ * \param min      The minimum value to return. It must be strictly smaller
+ *                 than \b N.
+ * \param N        The modulus.
+ *                 This is the upper bound of the output range, exclusive.
+ * \param f_rng    The RNG function to use. This must not be \c NULL.
+ * \param p_rng    The RNG parameter to be passed to \p f_rng.
+ *
+ * \return         \c 0 if successful.
+ * \return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
+ *                 unable to find a suitable value within a limited number
+ *                 of attempts. This has a negligible probability if \p N
+ *                 is significantly larger than \p min, which is the case
+ *                 for all usual cryptographic applications.
+ */
+int mbedtls_mpi_mod_raw_random( mbedtls_mpi_uint *X,
+                                mbedtls_mpi_uint min,
+                                const mbedtls_mpi_mod_modulus *N,
+                                int (*f_rng)(void *, unsigned char *, size_t),
+                                void *p_rng );
+
 /* END MERGE SLOT 6 */
 
 /* BEGIN MERGE SLOT 7 */
diff --git a/library/bn_mul.h b/library/bn_mul.h
index 6b8106f..b7e9690 100644
--- a/library/bn_mul.h
+++ b/library/bn_mul.h
@@ -80,6 +80,7 @@
 
 #endif /* bits in mbedtls_mpi_uint */
 
+/* *INDENT-OFF* */
 #if defined(MBEDTLS_HAVE_ASM)
 
 #ifndef asm
@@ -1071,4 +1072,5 @@
 #define MULADDC_X8_CORE MULADDC_X4_CORE MULADDC_X4_CORE
 #endif /* MULADDC_X8_CORE */
 
+/* *INDENT-ON* */
 #endif /* bn_mul.h */
diff --git a/library/ecp.c b/library/ecp.c
index cd7d554..b6ed60a 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -754,6 +754,13 @@
     return( ret );
 }
 
+#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+static int mbedtls_ecp_sw_derive_y( const mbedtls_ecp_group *grp,
+                                    const mbedtls_mpi *X,
+                                    mbedtls_mpi *Y,
+                                    int parity_bit );
+#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
+
 /*
  * Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748)
  */
@@ -795,16 +802,29 @@
                 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
         }
 
-        if( buf[0] != 0x04 )
-            return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
-
-        if( ilen != 2 * plen + 1 )
+        if( ilen < 1 + plen )
             return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
 
         MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y,
-                                                  buf + 1 + plen, plen ) );
         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) );
+
+        if( buf[0] == 0x04 )
+        {
+            /* format == MBEDTLS_ECP_PF_UNCOMPRESSED */
+            if( ilen != 1 + plen * 2 )
+                return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+            return( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) );
+        }
+        else if( buf[0] == 0x02 || buf[0] == 0x03 )
+        {
+            /* format == MBEDTLS_ECP_PF_COMPRESSED */
+            if( ilen != 1 + plen )
+                return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+            return( mbedtls_ecp_sw_derive_y( grp, &pt->X, &pt->Y,
+                                             ( buf[0] & 1 ) ) );
+        }
+        else
+            return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
     }
 #endif
 
@@ -1191,6 +1211,86 @@
     MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( (X), (Y), (cond) ) )
 
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+
+/*
+ * Computes the right-hand side of the Short Weierstrass equation
+ * RHS = X^3 + A X + B
+ */
+static int ecp_sw_rhs( const mbedtls_ecp_group *grp,
+                       mbedtls_mpi *rhs,
+                       const mbedtls_mpi *X )
+{
+    int ret;
+
+    /* Compute X^3 + A X + B as X (X^2 + A) + B */
+    MPI_ECP_SQR( rhs, X );
+
+    /* Special case for A = -3 */
+    if( grp->A.p == NULL )
+    {
+        MPI_ECP_SUB_INT( rhs, rhs, 3 );
+    }
+    else
+    {
+        MPI_ECP_ADD( rhs, rhs, &grp->A );
+    }
+
+    MPI_ECP_MUL( rhs, rhs, X  );
+    MPI_ECP_ADD( rhs, rhs, &grp->B );
+
+cleanup:
+    return( ret );
+}
+
+/*
+ * Derive Y from X and a parity bit
+ */
+static int mbedtls_ecp_sw_derive_y( const mbedtls_ecp_group *grp,
+                                    const mbedtls_mpi *X,
+                                    mbedtls_mpi *Y,
+                                    int parity_bit )
+{
+    /* w = y^2 = x^3 + ax + b
+     * y = sqrt(w) = w^((p+1)/4) mod p   (for prime p where p = 3 mod 4)
+     *
+     * Note: this method for extracting square root does not validate that w
+     * was indeed a square so this function will return garbage in Y if X
+     * does not correspond to a point on the curve.
+     */
+
+    /* Check prerequisite p = 3 mod 4 */
+    if( mbedtls_mpi_get_bit( &grp->P, 0 ) != 1 ||
+        mbedtls_mpi_get_bit( &grp->P, 1 ) != 1 )
+        return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+
+    int ret;
+    mbedtls_mpi exp;
+    mbedtls_mpi_init( &exp );
+
+    /* use Y to store intermediate result, actually w above */
+    MBEDTLS_MPI_CHK( ecp_sw_rhs( grp, Y, X ) );
+
+    /* w = y^2 */ /* Y contains y^2 intermediate result */
+    /* exp = ((p+1)/4) */
+    MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &exp, &grp->P, 1 ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &exp, 2 ) );
+    /* sqrt(w) = w^((p+1)/4) mod p   (for prime p where p = 3 mod 4) */
+    MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( Y, Y /*y^2*/, &exp, &grp->P, NULL ) );
+
+    /* check parity bit match or else invert Y */
+    /* This quick inversion implementation is valid because Y != 0 for all
+     * Short Weierstrass curves supported by mbedtls, as each supported curve
+     * has an order that is a large prime, so each supported curve does not
+     * have any point of order 2, and a point with Y == 0 would be of order 2 */
+    if( mbedtls_mpi_get_bit( Y, 0 ) != parity_bit )
+        MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( Y, &grp->P, Y ) );
+
+cleanup:
+
+    mbedtls_mpi_free( &exp );
+    return( ret );
+}
+
 /*
  * For curves in short Weierstrass form, we do all the internal operations in
  * Jacobian coordinates.
@@ -2611,23 +2711,10 @@
 
     /*
      * YY = Y^2
-     * RHS = X (X^2 + A) + B = X^3 + A X + B
+     * RHS = X^3 + A X + B
      */
     MPI_ECP_SQR( &YY,  &pt->Y );
-    MPI_ECP_SQR( &RHS, &pt->X );
-
-    /* Special case for A = -3 */
-    if( grp->A.p == NULL )
-    {
-        MPI_ECP_SUB_INT( &RHS, &RHS, 3 );
-    }
-    else
-    {
-        MPI_ECP_ADD( &RHS, &RHS, &grp->A );
-    }
-
-    MPI_ECP_MUL( &RHS, &RHS, &pt->X  );
-    MPI_ECP_ADD( &RHS, &RHS, &grp->B );
+    MBEDTLS_MPI_CHK( ecp_sw_rhs( grp, &RHS, &pt->X ) );
 
     if( MPI_ECP_CMP( &YY, &RHS ) != 0 )
         ret = MBEDTLS_ERR_ECP_INVALID_KEY;
diff --git a/library/lms.c b/library/lms.c
index 46ea567..78c7d26 100644
--- a/library/lms.c
+++ b/library/lms.c
@@ -65,10 +65,9 @@
 
 /* Currently only support H=10 */
 #define H_TREE_HEIGHT_MAX                  10
-#define MERKLE_TREE_NODE_AM_MAX            (1u << (H_TREE_HEIGHT_MAX + 1u))
-#define MERKLE_TREE_NODE_AM(type)          (1u << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
-#define MERKLE_TREE_LEAF_NODE_AM(type)     (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type))
-#define MERKLE_TREE_INTERNAL_NODE_AM(type) (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type))
+#define MERKLE_TREE_NODE_AM(type)          ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
+#define MERKLE_TREE_LEAF_NODE_AM(type)     ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
+#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
 
 #define D_CONST_LEN           (2)
 static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = {0x82, 0x82};
@@ -499,13 +498,21 @@
                             unsigned int leaf_node_id,
                             unsigned char *path )
 {
-    unsigned char tree[MERKLE_TREE_NODE_AM_MAX][MBEDTLS_LMS_M_NODE_BYTES_MAX];
+    const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type);
     unsigned int curr_node_id = leaf_node_id;
     unsigned int adjacent_node_id;
+    unsigned char *tree = NULL;
     unsigned int height;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    ret = calculate_merkle_tree( ctx, ( unsigned char * )tree );
+    tree = mbedtls_calloc( MERKLE_TREE_NODE_AM(ctx->params.type),
+        node_bytes );
+    if ( tree == NULL )
+    {
+        return MBEDTLS_ERR_LMS_ALLOC_FAILED;
+    }
+
+    ret = calculate_merkle_tree( ctx, tree );
     if( ret != 0 )
     {
         goto exit;
@@ -516,9 +523,8 @@
     {
         adjacent_node_id = curr_node_id ^ 1;
 
-        memcpy( &path[height * MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type)],
-                &tree[adjacent_node_id],
-                MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) );
+        memcpy( &path[height * node_bytes],
+                &tree[adjacent_node_id * node_bytes], node_bytes );
 
         curr_node_id >>=1;
     }
@@ -526,7 +532,9 @@
     ret = 0;
 
 exit:
-    mbedtls_platform_zeroize( tree, sizeof( tree ) );
+    mbedtls_platform_zeroize( tree, node_bytes *
+        MERKLE_TREE_NODE_AM(ctx->params.type) );
+    mbedtls_free ( tree );
 
     return( ret );
 }
@@ -659,8 +667,9 @@
 int mbedtls_lms_calculate_public_key( mbedtls_lms_public_t *ctx,
                                       const mbedtls_lms_private_t *priv_ctx )
 {
-    unsigned char tree[MERKLE_TREE_NODE_AM_MAX][MBEDTLS_LMS_M_NODE_BYTES_MAX];
+    const size_t node_bytes = MBEDTLS_LMS_M_NODE_BYTES(priv_ctx->params.type);
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *tree = NULL;
 
     if( ! priv_ctx->have_private_key )
     {
@@ -679,25 +688,33 @@
         return( MBEDTLS_ERR_LMS_BAD_INPUT_DATA );
     }
 
+    tree = mbedtls_calloc( MERKLE_TREE_NODE_AM(priv_ctx->params.type),
+        node_bytes );
+    if ( tree == NULL )
+    {
+        return MBEDTLS_ERR_LMS_ALLOC_FAILED;
+    }
+
     memcpy( &ctx->params, &priv_ctx->params,
             sizeof( mbedtls_lmots_parameters_t ) );
 
-    ret = calculate_merkle_tree( priv_ctx, ( unsigned char * )tree );
+    ret = calculate_merkle_tree( priv_ctx, tree );
     if( ret != 0 )
     {
         goto exit;
     }
 
     /* Root node is always at position 1, due to 1-based indexing */
-    memcpy( ctx->T_1_pub_key, &tree[1],
-            MBEDTLS_LMS_M_NODE_BYTES(ctx->params.type) );
+    memcpy( ctx->T_1_pub_key, &tree[node_bytes], node_bytes );
 
     ctx->have_public_key = 1;
 
     ret = 0;
 
 exit:
-    mbedtls_platform_zeroize( tree, sizeof( tree ) );
+    mbedtls_platform_zeroize( tree, node_bytes *
+        MERKLE_TREE_NODE_AM(priv_ctx->params.type) );
+    mbedtls_free ( tree );
 
     return( ret );
 }
diff --git a/library/padlock.c b/library/padlock.c
index a128775..81bea1f 100644
--- a/library/padlock.c
+++ b/library/padlock.c
@@ -31,9 +31,11 @@
 
 #include <string.h>
 
+/* *INDENT-OFF* */
 #ifndef asm
 #define asm __asm
 #endif
+/* *INDENT-ON* */
 
 #if defined(MBEDTLS_HAVE_X86)
 
diff --git a/library/pk.c b/library/pk.c
index 8dc19ef..a73fa56 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -482,12 +482,9 @@
     pss_opts = (const mbedtls_pk_rsassa_pss_options *) options;
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( pss_opts->mgf1_hash_id == md_alg &&
-        ( (size_t) pss_opts->expected_salt_len == hash_len ||
-            pss_opts->expected_salt_len  == MBEDTLS_RSA_SALT_LEN_ANY ) )
+    if( pss_opts->mgf1_hash_id == md_alg )
     {
-        /* see RSA_PUB_DER_MAX_BYTES in pkwrite.c */
-        unsigned char buf[ 38 + 2 * MBEDTLS_MPI_MAX_SIZE ];
+        unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
         unsigned char *p;
         int key_len;
         size_t signature_length;
@@ -497,10 +494,7 @@
         psa_algorithm_t psa_md_alg = mbedtls_hash_info_psa_from_md( md_alg );
         mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-        psa_algorithm_t psa_sig_alg =
-            ( pss_opts->expected_salt_len == MBEDTLS_RSA_SALT_LEN_ANY ?
-                                 PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg) :
-                                 PSA_ALG_RSA_PSS(psa_md_alg) );
+        psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT( psa_md_alg );
         p = buf + sizeof( buf );
         key_len = mbedtls_pk_write_pubkey( &p, buf, ctx );
 
diff --git a/library/sha256.c b/library/sha256.c
index 1a9a855..6e6a58f 100644
--- a/library/sha256.c
+++ b/library/sha256.c
@@ -24,7 +24,7 @@
 
 #include "common.h"
 
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C)
 
 #include "mbedtls/sha256.h"
 #include "mbedtls/platform_util.h"
@@ -89,9 +89,11 @@
 #include <signal.h>
 #include <setjmp.h>
 
+/* *INDENT-OFF* */
 #ifndef asm
 #define asm __asm__
 #endif
+/* *INDENT-ON* */
 
 static jmp_buf return_from_sigill;
 
@@ -167,12 +169,15 @@
  */
 int mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )
 {
-#if defined(MBEDTLS_SHA224_C)
+#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
     if( is224 != 0 && is224 != 1 )
         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
-#else
+#elif defined(MBEDTLS_SHA256_C)
     if( is224 != 0 )
         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
+#else /* defined MBEDTLS_SHA224_C only */
+    if( is224 == 0 )
+        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
 #endif
 
     ctx->total[0] = 0;
@@ -180,7 +185,7 @@
 
     if( is224 == 0 )
     {
-        /* SHA-256 */
+#if defined(MBEDTLS_SHA256_C)
         ctx->state[0] = 0x6A09E667;
         ctx->state[1] = 0xBB67AE85;
         ctx->state[2] = 0x3C6EF372;
@@ -189,11 +194,11 @@
         ctx->state[5] = 0x9B05688C;
         ctx->state[6] = 0x1F83D9AB;
         ctx->state[7] = 0x5BE0CD19;
+#endif
     }
     else
     {
 #if defined(MBEDTLS_SHA224_C)
-        /* SHA-224 */
         ctx->state[0] = 0xC1059ED8;
         ctx->state[1] = 0x367CD507;
         ctx->state[2] = 0x3070DD17;
@@ -205,7 +210,9 @@
 #endif
     }
 
+#if defined(MBEDTLS_SHA224_C)
     ctx->is224 = is224;
+#endif
 
     return( 0 );
 }
@@ -678,12 +685,15 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_sha256_context ctx;
 
-#if defined(MBEDTLS_SHA224_C)
+#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
     if( is224 != 0 && is224 != 1 )
         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
-#else
+#elif defined(MBEDTLS_SHA256_C)
     if( is224 != 0 )
         return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
+#else /* defined MBEDTLS_SHA224_C only */
+    if( is224 == 0 )
+        return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
 #endif
 
     mbedtls_sha256_init( &ctx );
@@ -707,23 +717,26 @@
 /*
  * FIPS-180-2 test vectors
  */
-static const unsigned char sha256_test_buf[3][57] =
+static const unsigned char sha_test_buf[3][57] =
 {
     { "abc" },
     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
     { "" }
 };
 
-static const size_t sha256_test_buflen[3] =
+static const size_t sha_test_buflen[3] =
 {
     3, 56, 1000
 };
 
-static const unsigned char sha256_test_sum[6][32] =
+typedef const unsigned char (sha_test_sum_t)[32];
+
+/*
+ * SHA-224 test vectors
+ */
+#if defined(MBEDTLS_SHA224_C)
+static sha_test_sum_t sha224_test_sum[] =
 {
-    /*
-     * SHA-224 test vectors
-     */
     { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
       0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
       0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
@@ -735,11 +748,16 @@
     { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
       0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
       0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
-      0x4E, 0xE7, 0xAD, 0x67 },
+      0x4E, 0xE7, 0xAD, 0x67 }
+};
+#endif
 
-    /*
-     * SHA-256 test vectors
-     */
+/*
+ * SHA-256 test vectors
+ */
+#if defined(MBEDTLS_SHA256_C)
+static sha_test_sum_t sha256_test_sum[] =
+{
     { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
       0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
       0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
@@ -753,17 +771,26 @@
       0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
       0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
 };
+#endif
 
 /*
  * Checkup routine
  */
-int mbedtls_sha256_self_test( int verbose )
+static int mbedtls_sha256_common_self_test( int verbose, int is224 )
 {
-    int i, j, k, buflen, ret = 0;
+    int i, buflen, ret = 0;
     unsigned char *buf;
     unsigned char sha256sum[32];
     mbedtls_sha256_context ctx;
 
+#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
+    sha_test_sum_t* sha_test_sum = ( is224 ) ? sha224_test_sum : sha256_test_sum;
+#elif defined(MBEDTLS_SHA256_C)
+    sha_test_sum_t* sha_test_sum = sha256_test_sum;
+#else
+    sha_test_sum_t* sha_test_sum = sha224_test_sum;
+#endif
+
     buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
     if( NULL == buf )
     {
@@ -775,22 +802,19 @@
 
     mbedtls_sha256_init( &ctx );
 
-    for( i = 0; i < 6; i++ )
+    for( i = 0; i < 3; i++ )
     {
-        j = i % 3;
-        k = i < 3;
-
         if( verbose != 0 )
-            mbedtls_printf( "  SHA-%d test #%d: ", 256 - k * 32, j + 1 );
+            mbedtls_printf( "  SHA-%d test #%d: ", 256 - is224 * 32, i + 1 );
 
-        if( ( ret = mbedtls_sha256_starts( &ctx, k ) ) != 0 )
+        if( ( ret = mbedtls_sha256_starts( &ctx, is224 ) ) != 0 )
             goto fail;
 
-        if( j == 2 )
+        if( i == 2 )
         {
             memset( buf, 'a', buflen = 1000 );
 
-            for( j = 0; j < 1000; j++ )
+            for( int j = 0; j < 1000; j++ )
             {
                 ret = mbedtls_sha256_update( &ctx, buf, buflen );
                 if( ret != 0 )
@@ -800,8 +824,8 @@
         }
         else
         {
-            ret = mbedtls_sha256_update( &ctx, sha256_test_buf[j],
-                                             sha256_test_buflen[j] );
+            ret = mbedtls_sha256_update( &ctx, sha_test_buf[i],
+                                             sha_test_buflen[i] );
             if( ret != 0 )
                  goto fail;
         }
@@ -810,7 +834,7 @@
             goto fail;
 
 
-        if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 )
+        if( memcmp( sha256sum, sha_test_sum[i], 32 - is224 * 4 ) != 0 )
         {
             ret = 1;
             goto fail;
@@ -836,6 +860,20 @@
     return( ret );
 }
 
+#if defined(MBEDTLS_SHA256_C)
+int mbedtls_sha256_self_test( int verbose )
+{
+    return mbedtls_sha256_common_self_test( verbose, 0 );
+}
+#endif /* MBEDTLS_SHA256_C */
+
+#if defined(MBEDTLS_SHA224_C)
+int mbedtls_sha224_self_test( int verbose )
+{
+    return mbedtls_sha256_common_self_test( verbose, 1 );
+}
+#endif /* MBEDTLS_SHA224_C */
+
 #endif /* MBEDTLS_SELF_TEST */
 
-#endif /* MBEDTLS_SHA256_C */
+#endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA224_C */
diff --git a/library/sha512.c b/library/sha512.c
index 92ada8c..46e3dab 100644
--- a/library/sha512.c
+++ b/library/sha512.c
@@ -24,7 +24,7 @@
 
 #include "common.h"
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA384_C)
 
 #include "mbedtls/sha512.h"
 #include "mbedtls/platform_util.h"
@@ -104,9 +104,11 @@
 #include <signal.h>
 #include <setjmp.h>
 
+/* *INDENT-OFF* */
 #ifndef asm
 #define asm __asm__
 #endif
+/* *INDENT-ON* */
 
 static jmp_buf return_from_sigill;
 
@@ -191,12 +193,15 @@
  */
 int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
 {
-#if defined(MBEDTLS_SHA384_C)
+#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C)
     if( is384 != 0 && is384 != 1 )
         return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
-#else
+#elif defined(MBEDTLS_SHA512_C)
     if( is384 != 0 )
         return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
+#else /* defined MBEDTLS_SHA384_C only */
+    if( is384 == 0 )
+        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
 #endif
 
     ctx->total[0] = 0;
@@ -204,7 +209,7 @@
 
     if( is384 == 0 )
     {
-        /* SHA-512 */
+#if defined(MBEDTLS_SHA512_C)
         ctx->state[0] = UL64(0x6A09E667F3BCC908);
         ctx->state[1] = UL64(0xBB67AE8584CAA73B);
         ctx->state[2] = UL64(0x3C6EF372FE94F82B);
@@ -213,13 +218,11 @@
         ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
         ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
         ctx->state[7] = UL64(0x5BE0CD19137E2179);
+#endif /* MBEDTLS_SHA512_C */
     }
     else
     {
-#if !defined(MBEDTLS_SHA384_C)
-        return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA );
-#else
-        /* SHA-384 */
+#if defined(MBEDTLS_SHA384_C)
         ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
         ctx->state[1] = UL64(0x629A292A367CD507);
         ctx->state[2] = UL64(0x9159015A3070DD17);
@@ -296,9 +299,11 @@
 #  define mbedtls_internal_sha512_process_a64_crypto      mbedtls_internal_sha512_process
 #endif
 
+/* *INDENT-OFF* */
 #ifndef asm
 #define asm __asm__
 #endif
+/* *INDENT-ON* */
 
 /* Accelerated SHA-512 implementation originally written by Simon Tatham for PuTTY,
  * under the MIT licence; dual-licensed as Apache 2 with his kind permission.
@@ -836,12 +841,15 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_sha512_context ctx;
 
-#if defined(MBEDTLS_SHA384_C)
+#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C)
     if( is384 != 0 && is384 != 1 )
         return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
-#else
+#elif defined(MBEDTLS_SHA512_C)
     if( is384 != 0 )
         return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
+#else /* defined MBEDTLS_SHA384_C only */
+    if( is384 == 0 )
+        return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
 #endif
 
     mbedtls_sha512_init( &ctx );
@@ -866,24 +874,26 @@
 /*
  * FIPS-180-2 test vectors
  */
-static const unsigned char sha512_test_buf[3][113] =
+static const unsigned char sha_test_buf[3][113] =
 {
     { "abc" },
     { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
     { "" }
 };
 
-static const size_t sha512_test_buflen[3] =
+static const size_t sha_test_buflen[3] =
 {
     3, 112, 1000
 };
 
-static const unsigned char sha512_test_sum[][64] =
-{
+typedef const unsigned char (sha_test_sum_t)[64];
+
+/*
+ * SHA-384 test vectors
+ */
 #if defined(MBEDTLS_SHA384_C)
-    /*
-     * SHA-384 test vectors
-     */
+static sha_test_sum_t sha384_test_sum[] =
+{
     { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
       0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
       0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
@@ -901,12 +911,16 @@
       0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
       0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
       0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
-      0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
+      0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }
+};
 #endif /* MBEDTLS_SHA384_C */
 
-    /*
-     * SHA-512 test vectors
-     */
+/*
+ * SHA-512 test vectors
+ */
+#if defined(MBEDTLS_SHA512_C)
+static sha_test_sum_t sha512_test_sum[] =
+{
     { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
       0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
       0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
@@ -932,19 +946,25 @@
       0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
       0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
 };
+#endif /* MBEDTLS_SHA512_C */
 
 #define ARRAY_LENGTH( a )   ( sizeof( a ) / sizeof( ( a )[0] ) )
 
-/*
- * Checkup routine
- */
-int mbedtls_sha512_self_test( int verbose )
+static int mbedtls_sha512_common_self_test( int verbose, int is384 )
 {
-    int i, j, k, buflen, ret = 0;
+    int i, buflen, ret = 0;
     unsigned char *buf;
     unsigned char sha512sum[64];
     mbedtls_sha512_context ctx;
 
+#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_SHA512_C)
+    sha_test_sum_t* sha_test_sum = ( is384 ) ? sha384_test_sum : sha512_test_sum;
+#elif defined(MBEDTLS_SHA512_C)
+    sha_test_sum_t* sha_test_sum = sha512_test_sum;
+#else
+    sha_test_sum_t* sha_test_sum = sha384_test_sum;
+#endif
+
     buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
     if( NULL == buf )
     {
@@ -956,26 +976,19 @@
 
     mbedtls_sha512_init( &ctx );
 
-    for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ )
+    for( i = 0; i < 3; i++ )
     {
-        j = i % 3;
-#if defined(MBEDTLS_SHA384_C)
-        k = i < 3;
-#else
-        k = 0;
-#endif
-
         if( verbose != 0 )
-            mbedtls_printf( "  SHA-%d test #%d: ", 512 - k * 128, j + 1 );
+            mbedtls_printf( "  SHA-%d test #%d: ", 512 - is384 * 128, i + 1 );
 
-        if( ( ret = mbedtls_sha512_starts( &ctx, k ) ) != 0 )
+        if( ( ret = mbedtls_sha512_starts( &ctx, is384 ) ) != 0 )
             goto fail;
 
-        if( j == 2 )
+        if( i == 2 )
         {
             memset( buf, 'a', buflen = 1000 );
 
-            for( j = 0; j < 1000; j++ )
+            for( int j = 0; j < 1000; j++ )
             {
                 ret = mbedtls_sha512_update( &ctx, buf, buflen );
                 if( ret != 0 )
@@ -984,8 +997,8 @@
         }
         else
         {
-            ret = mbedtls_sha512_update( &ctx, sha512_test_buf[j],
-                                             sha512_test_buflen[j] );
+            ret = mbedtls_sha512_update( &ctx, sha_test_buf[i],
+                                             sha_test_buflen[i] );
             if( ret != 0 )
                 goto fail;
         }
@@ -993,7 +1006,7 @@
         if( ( ret = mbedtls_sha512_finish( &ctx, sha512sum ) ) != 0 )
             goto fail;
 
-        if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 )
+        if( memcmp( sha512sum, sha_test_sum[i], 64 - is384 * 16 ) != 0 )
         {
             ret = 1;
             goto fail;
@@ -1019,8 +1032,22 @@
     return( ret );
 }
 
+#if defined(MBEDTLS_SHA512_C)
+int mbedtls_sha512_self_test( int verbose )
+{
+    return mbedtls_sha512_common_self_test( verbose, 0 );
+}
+#endif /* MBEDTLS_SHA512_C */
+
+#if defined(MBEDTLS_SHA384_C)
+int mbedtls_sha384_self_test( int verbose )
+{
+    return mbedtls_sha512_common_self_test( verbose, 1 );
+}
+#endif /* MBEDTLS_SHA384_C */
+
 #undef ARRAY_LENGTH
 
 #endif /* MBEDTLS_SELF_TEST */
 
-#endif /* MBEDTLS_SHA512_C */
+#endif /* MBEDTLS_SHA512_C || MBEDTLS_SHA384_C */
diff --git a/library/ssl_client.c b/library/ssl_client.c
index e838845..925d0c2 100644
--- a/library/ssl_client.c
+++ b/library/ssl_client.c
@@ -24,15 +24,11 @@
 #if defined(MBEDTLS_SSL_CLI_C)
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) || defined(MBEDTLS_SSL_PROTO_TLS1_2)
 
-#include "mbedtls/platform.h"
-
 #include <string.h>
 
 #include "mbedtls/debug.h"
 #include "mbedtls/error.h"
-#if defined(MBEDTLS_HAVE_TIME)
-#include "mbedtls/platform_time.h"
-#endif
+#include "mbedtls/platform.h"
 
 #include "ssl_client.h"
 #include "ssl_misc.h"
@@ -266,15 +262,17 @@
             ( mbedtls_ssl_conf_is_tls12_enabled( ssl->conf ) &&
               mbedtls_ssl_tls12_named_group_is_ecdhe( *group_list ) ) )
         {
-            const mbedtls_ecp_curve_info *curve_info;
-            curve_info = mbedtls_ecp_curve_info_from_tls_id( *group_list );
-            if( curve_info == NULL )
+            if( mbedtls_ssl_get_ecp_group_id_from_tls_id( *group_list ) ==
+                MBEDTLS_ECP_DP_NONE )
+            {
                 continue;
+            }
             MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
             MBEDTLS_PUT_UINT16_BE( *group_list, p, 0 );
             p += 2;
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "NamedGroup: %s ( %x )",
-                                curve_info->name, *group_list ) );
+                        mbedtls_ssl_get_curve_name_from_tls_id( *group_list ),
+                        *group_list ) );
         }
 #endif /* MBEDTLS_ECP_C */
         /* Add DHE groups here */
diff --git a/library/ssl_cookie.c b/library/ssl_cookie.c
index 3f9bf87..a996174 100644
--- a/library/ssl_cookie.c
+++ b/library/ssl_cookie.c
@@ -38,23 +38,19 @@
 #include <string.h>
 
 /*
- * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-384 is
- * available. Try SHA-256 first, 384 wastes resources
+ * 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
  */
-#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
-#define COOKIE_MD           MBEDTLS_MD_SHA224
+#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
+#define COOKIE_MD           MBEDTLS_MD_SHA256
 #define COOKIE_MD_OUTLEN    32
 #define COOKIE_HMAC_LEN     28
 #elif defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
 #define COOKIE_MD           MBEDTLS_MD_SHA384
 #define COOKIE_MD_OUTLEN    48
 #define COOKIE_HMAC_LEN     28
-#elif defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
-#define COOKIE_MD           MBEDTLS_MD_SHA1
-#define COOKIE_MD_OUTLEN    20
-#define COOKIE_HMAC_LEN     20
 #else
-#error "DTLS hello verify needs SHA-1 or SHA-2"
+#error "DTLS hello verify needs SHA-256 or SHA-384"
 #endif
 
 /*
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 8254964..d558e38 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -787,7 +787,7 @@
 
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) ||      \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    const mbedtls_ecp_curve_info **curves;      /*!<  Supported elliptic curves */
+    uint16_t *curves_tls_id;      /*!<  List of TLS IDs of supported elliptic curves */
 #endif
 
 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
@@ -1576,6 +1576,55 @@
 int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id );
 #endif
 
+/**
+ * \brief Return PSA EC info for the specified TLS ID.
+ *
+ * \param tls_id    The TLS ID to look for
+ * \param family    If the TLD ID is supported, then proper \c psa_ecc_family_t
+ *                  value is returned here. Can be NULL.
+ * \param bits      If the TLD ID is supported, then proper bit size is returned
+ *                  here. Can be NULL.
+ * \return          PSA_SUCCESS if the TLS ID is supported,
+ *                  PSA_ERROR_NOT_SUPPORTED otherwise
+ *
+ * \note            If either \c family or \c bits parameters are NULL, then
+ *                  the corresponding value is not returned.
+ *                  The function can be called with both parameters as NULL
+ *                  simply to check if a specific TLS ID is supported.
+ */
+int mbedtls_ssl_get_psa_curve_info_from_tls_id( uint16_t tls_id,
+                                                psa_ecc_family_t *family,
+                                                size_t* bits );
+
+/**
+ * \brief Return \c mbedtls_ecp_group_id for the specified TLS ID.
+ *
+ * \param tls_id    The TLS ID to look for
+ * \return          Proper \c mbedtls_ecp_group_id if the TLS ID is supported,
+ *                  or MBEDTLS_ECP_DP_NONE otherwise
+ */
+mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id( uint16_t tls_id );
+
+/**
+ * \brief Return TLS ID for the specified \c mbedtls_ecp_group_id.
+ *
+ * \param grp_id    The \c mbedtls_ecp_group_id ID to look for
+ * \return          Proper TLS ID if the \c mbedtls_ecp_group_id is supported,
+ *                  or 0 otherwise
+ */
+uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id( mbedtls_ecp_group_id grp_id );
+
+#if defined(MBEDTLS_DEBUG_C)
+/**
+ * \brief Return EC's name for the specified TLS ID.
+ *
+ * \param tls_id    The TLS ID to look for
+ * \return          A pointer to a const string with the proper name. If TLS
+ *                  ID is not supported, a NULL pointer is returned instead.
+ */
+const char* mbedtls_ssl_get_curve_name_from_tls_id( uint16_t tls_id );
+#endif
+
 #if defined(MBEDTLS_SSL_DTLS_SRTP)
 static inline mbedtls_ssl_srtp_profile mbedtls_ssl_check_srtp_profile_value
                                                     ( const uint16_t srtp_profile_value )
@@ -2073,6 +2122,12 @@
 
 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
 /*
+ * Write Signature Algorithm extension
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_write_sig_alg_ext( mbedtls_ssl_context *ssl, unsigned char *buf,
+                                   const unsigned char *end, size_t *out_len );
+/*
  * Parse TLS Signature Algorithm extension
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
@@ -2173,9 +2228,8 @@
 #if defined(MBEDTLS_ECDH_C)
     if( mbedtls_ssl_tls13_named_group_is_ecdhe( named_group ) )
     {
-        const mbedtls_ecp_curve_info *curve_info =
-            mbedtls_ecp_curve_info_from_tls_id( named_group );
-        if( curve_info != NULL )
+        if( mbedtls_ssl_get_ecp_group_id_from_tls_id( named_group ) !=
+                        MBEDTLS_ECP_DP_NONE )
             return( 1 );
     }
 #else
@@ -2619,10 +2673,6 @@
     mbedtls_ssl_protocol_version min_tls_version,
     mbedtls_ssl_protocol_version max_tls_version );
 
-MBEDTLS_CHECK_RETURN_CRITICAL
-int mbedtls_ssl_write_sig_alg_ext( mbedtls_ssl_context *ssl, unsigned char *buf,
-                                   const unsigned char *end, size_t *out_len );
-
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
 MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_parse_server_name_ext( mbedtls_ssl_context *ssl,
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index 753998e..194c326 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -5094,7 +5094,9 @@
      * data.
      */
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) );
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     ssl->transform_in = ssl->transform_negotiate;
+#endif
     ssl->session_in = ssl->session_negotiate;
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index b757613..35565de 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -965,13 +965,16 @@
 static int ssl_handshake_init( mbedtls_ssl_context *ssl )
 {
     /* Clear old handshake information if present */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     if( ssl->transform_negotiate )
         mbedtls_ssl_transform_free( ssl->transform_negotiate );
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
     if( ssl->session_negotiate )
         mbedtls_ssl_session_free( ssl->session_negotiate );
     if( ssl->handshake )
         mbedtls_ssl_handshake_free( ssl );
 
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     /*
      * Either the pointers are now NULL or cleared properly and can be freed.
      * Now allocate missing structures.
@@ -980,6 +983,7 @@
     {
         ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) );
     }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
     if( ssl->session_negotiate == NULL )
     {
@@ -998,18 +1002,23 @@
 #endif
 
     /* All pointers should exist and can be directly freed without issue */
-    if( ssl->handshake == NULL ||
+    if( ssl->handshake           == NULL ||
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
         ssl->transform_negotiate == NULL ||
-        ssl->session_negotiate == NULL )
+#endif
+        ssl->session_negotiate   == NULL )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc() of ssl sub-contexts failed" ) );
 
         mbedtls_free( ssl->handshake );
-        mbedtls_free( ssl->transform_negotiate );
-        mbedtls_free( ssl->session_negotiate );
-
         ssl->handshake = NULL;
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        mbedtls_free( ssl->transform_negotiate );
         ssl->transform_negotiate = NULL;
+#endif
+
+        mbedtls_free( ssl->session_negotiate );
         ssl->session_negotiate = NULL;
 
         return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
@@ -1017,9 +1026,12 @@
 
     /* Initialize structures */
     mbedtls_ssl_session_init( ssl->session_negotiate );
-    mbedtls_ssl_transform_init( ssl->transform_negotiate );
     ssl_handshake_params_init( ssl->handshake );
 
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    mbedtls_ssl_transform_init( ssl->transform_negotiate );
+#endif
+
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
     defined(MBEDTLS_SSL_SRV_C) && \
     defined(MBEDTLS_SSL_SESSION_TICKETS)
@@ -1064,14 +1076,14 @@
 
         for( size_t i = 0; i < length; i++ )
         {
-            const mbedtls_ecp_curve_info *info =
-                        mbedtls_ecp_curve_info_from_grp_id( curve_list[i] );
-            if ( info == NULL )
+            uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(
+                                curve_list[i] );
+            if ( tls_id == 0 )
             {
                 mbedtls_free( group_list );
                 return( MBEDTLS_ERR_SSL_BAD_CONFIG );
             }
-            group_list[i] = info->tls_id;
+            group_list[i] = tls_id;
         }
 
         group_list[length] = 0;
@@ -3215,12 +3227,14 @@
     size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN;
     size_t read_mfl;
 
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     /* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */
     if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
         ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE )
     {
         return ssl_mfl_code_to_length( ssl->conf->mfl_code );
     }
+#endif
 
     /* Check if a smaller max length was negotiated */
     if( ssl->session_out != NULL )
@@ -3232,7 +3246,7 @@
         }
     }
 
-    // During a handshake, use the value being negotiated
+    /* During a handshake, use the value being negotiated */
     if( ssl->session_negotiate != NULL )
     {
         read_mfl = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code );
@@ -3497,12 +3511,15 @@
  *                                 // the structure of mbedtls_ssl_session.
  *
  *    uint8_t minor_ver;           // Protocol minor version. Possible values:
- *                                 // - TLS 1.2 (3)
+ *                                 // - TLS 1.2 (0x0303)
+ *                                 // - TLS 1.3 (0x0304)
  *
  *    select (serialized_session.tls_version) {
  *
  *      case MBEDTLS_SSL_VERSION_TLS1_2:
  *        serialized_session_tls12 data;
+ *      case MBEDTLS_SSL_VERSION_TLS1_3:
+ *        serialized_session_tls13 data;
  *
  *   };
  *
@@ -4004,7 +4021,7 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_hash_abort( &handshake->fin_sha256_psa );
 #else
-    mbedtls_sha256_free(   &handshake->fin_sha256    );
+    mbedtls_sha256_free( &handshake->fin_sha256 );
 #endif
 #endif
 #if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
@@ -4048,7 +4065,7 @@
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
     /* explicit void pointer cast for buggy MS compiler */
-    mbedtls_free( (void *) handshake->curves );
+    mbedtls_free( (void *) handshake->curves_tls_id );
 #endif
 
 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
@@ -4549,10 +4566,12 @@
 
     /* This has been allocated by ssl_handshake_init(), called by
      * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     ssl->transform = ssl->transform_negotiate;
     ssl->transform_in = ssl->transform;
     ssl->transform_out = ssl->transform;
     ssl->transform_negotiate = NULL;
+#endif
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
     prf_func = ssl_tls12prf_from_cs( ssl->session->ciphersuite );
@@ -4788,11 +4807,14 @@
     if( ssl->handshake )
     {
         mbedtls_ssl_handshake_free( ssl );
-        mbedtls_ssl_transform_free( ssl->transform_negotiate );
-        mbedtls_ssl_session_free( ssl->session_negotiate );
-
         mbedtls_free( ssl->handshake );
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        mbedtls_ssl_transform_free( ssl->transform_negotiate );
         mbedtls_free( ssl->transform_negotiate );
+#endif
+
+        mbedtls_ssl_session_free( ssl->session_negotiate );
         mbedtls_free( ssl->session_negotiate );
     }
 
@@ -5468,18 +5490,126 @@
  */
 int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id )
 {
-    const mbedtls_ecp_curve_info *grp_info =
-        mbedtls_ecp_curve_info_from_grp_id( grp_id );
+    uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( grp_id );
 
-    if ( grp_info == NULL )
+    if ( tls_id == 0 )
         return -1;
 
-    uint16_t tls_id = grp_info->tls_id;
-
     return mbedtls_ssl_check_curve_tls_id( ssl, tls_id );
 }
 #endif /* MBEDTLS_ECP_C */
 
+#if defined( MBEDTLS_DEBUG_C )
+#define EC_NAME(_name_)     _name_
+#else
+#define EC_NAME(_name_)     NULL
+#endif
+
+static const struct {
+    uint16_t tls_id;
+    mbedtls_ecp_group_id ecp_group_id;
+    psa_ecc_family_t psa_family;
+    uint16_t bits;
+    const char* name;
+} tls_id_match_table[] =
+{
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_521)
+    { 25, MBEDTLS_ECP_DP_SECP521R1, PSA_ECC_FAMILY_SECP_R1, 521, EC_NAME( "secp521r1" ) },
+#endif
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
+    { 28, MBEDTLS_ECP_DP_BP512R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 512, EC_NAME( "brainpoolP512r1" ) },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_384)
+    { 24, MBEDTLS_ECP_DP_SECP384R1, PSA_ECC_FAMILY_SECP_R1, 384, EC_NAME( "secp384r1" ) },
+#endif
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
+    { 27, MBEDTLS_ECP_DP_BP384R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 384, EC_NAME( "brainpoolP384r1" ) },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_256)
+    { 23, MBEDTLS_ECP_DP_SECP256R1, PSA_ECC_FAMILY_SECP_R1, 256, EC_NAME( "secp256r1" ) },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_256)
+    { 22, MBEDTLS_ECP_DP_SECP256K1, PSA_ECC_FAMILY_SECP_K1, 256, EC_NAME( "secp256k1" ) },
+#endif
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
+    { 26, MBEDTLS_ECP_DP_BP256R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 256, EC_NAME( "brainpoolP256r1" ) },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_224)
+    { 21, MBEDTLS_ECP_DP_SECP224R1, PSA_ECC_FAMILY_SECP_R1, 224, EC_NAME( "secp224r1" ) },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_224)
+    { 20, MBEDTLS_ECP_DP_SECP224K1, PSA_ECC_FAMILY_SECP_K1, 224, EC_NAME( "secp224k1" ) },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_192)
+    { 19, MBEDTLS_ECP_DP_SECP192R1, PSA_ECC_FAMILY_SECP_R1, 192, EC_NAME( "secp192r1" ) },
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_192)
+    { 18, MBEDTLS_ECP_DP_SECP192K1, PSA_ECC_FAMILY_SECP_K1, 192, EC_NAME( "secp192k1" ) },
+#endif
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_255)
+    { 29, MBEDTLS_ECP_DP_CURVE25519, PSA_ECC_FAMILY_MONTGOMERY, 255, EC_NAME( "x25519" ) },
+#endif
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_448)
+    { 30, MBEDTLS_ECP_DP_CURVE448, PSA_ECC_FAMILY_MONTGOMERY, 448, EC_NAME( "x448" ) },
+#endif
+    { 0, MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
+};
+
+int mbedtls_ssl_get_psa_curve_info_from_tls_id( uint16_t tls_id,
+                                                psa_ecc_family_t *family,
+                                                size_t* bits )
+{
+    for( int i = 0; tls_id_match_table[i].tls_id != 0; i++ )
+    {
+        if( tls_id_match_table[i].tls_id == tls_id )
+        {
+            if( family != NULL )
+                *family = tls_id_match_table[i].psa_family;
+            if( bits != NULL )
+                *bits = tls_id_match_table[i].bits;
+            return PSA_SUCCESS;
+        }
+    }
+
+    return PSA_ERROR_NOT_SUPPORTED;
+}
+
+mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id( uint16_t tls_id )
+{
+    for( int i = 0; tls_id_match_table[i].tls_id != 0; i++ )
+    {
+        if( tls_id_match_table[i].tls_id == tls_id )
+            return tls_id_match_table[i].ecp_group_id;
+    }
+
+    return MBEDTLS_ECP_DP_NONE;
+}
+
+uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id( mbedtls_ecp_group_id grp_id )
+{
+    for( int i = 0; tls_id_match_table[i].ecp_group_id != MBEDTLS_ECP_DP_NONE;
+            i++ )
+    {
+        if( tls_id_match_table[i].ecp_group_id == grp_id )
+            return tls_id_match_table[i].tls_id;
+    }
+
+    return 0;
+}
+
+#if defined(MBEDTLS_DEBUG_C)
+const char* mbedtls_ssl_get_curve_name_from_tls_id( uint16_t tls_id )
+{
+    for( int i = 0; tls_id_match_table[i].tls_id != 0; i++ )
+    {
+        if( tls_id_match_table[i].tls_id == tls_id )
+            return tls_id_match_table[i].name;
+    }
+
+    return NULL;
+}
+#endif
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert,
                           const mbedtls_ssl_ciphersuite_t *ciphersuite,
diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c
index 76588d3..30b6481 100644
--- a/library/ssl_tls12_client.c
+++ b/library/ssl_tls12_client.c
@@ -1800,9 +1800,10 @@
                                              unsigned char *end )
 {
     uint16_t tls_id;
-    size_t ecdh_bits = 0;
     uint8_t ecpoint_len;
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    psa_ecc_family_t ec_psa_family = 0;
+    size_t ec_bits = 0;
 
     /*
      * struct {
@@ -1836,13 +1837,14 @@
         return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
     }
 
-    /* Convert EC group to PSA key type. */
-    if( ( handshake->ecdh_psa_type =
-          mbedtls_psa_parse_tls_ecc_group( tls_id, &ecdh_bits ) ) == 0 )
+    /* Convert EC's TLS ID to PSA key type. */
+    if( mbedtls_ssl_get_psa_curve_info_from_tls_id( tls_id, &ec_psa_family,
+                    &ec_bits ) == PSA_ERROR_NOT_SUPPORTED )
     {
         return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
     }
-    handshake->ecdh_bits = ecdh_bits;
+    handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR( ec_psa_family );
+    handshake->ecdh_bits = ec_bits;
 
     /* Keep a copy of the peer's public key */
     ecpoint_len = *(*p)++;
@@ -1870,7 +1872,7 @@
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
 {
-    const mbedtls_ecp_curve_info *curve_info;
+    uint16_t tls_id;
     mbedtls_ecp_group_id grp_id;
 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
     grp_id = ssl->handshake->ecdh_ctx.grp.id;
@@ -1878,14 +1880,15 @@
     grp_id = ssl->handshake->ecdh_ctx.grp_id;
 #endif
 
-    curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id );
-    if( curve_info == NULL )
+    tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( grp_id );
+    if( tls_id == 0 )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) );
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s",
+                mbedtls_ssl_get_curve_name_from_tls_id( tls_id ) ) );
 
     if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 )
         return( -1 );
@@ -2104,8 +2107,9 @@
     peer_key = mbedtls_pk_ec( *peer_pk );
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    size_t ecdh_bits = 0;
     size_t olen = 0;
+    uint16_t tls_id = 0;
+    psa_ecc_family_t ecc_family;
 
     if( mbedtls_ssl_check_curve( ssl, peer_key->grp.id ) != 0 )
     {
@@ -2113,17 +2117,20 @@
         return( MBEDTLS_ERR_SSL_BAD_CERTIFICATE );
     }
 
-    ssl->handshake->ecdh_psa_type =
-        PSA_KEY_TYPE_ECC_KEY_PAIR( mbedtls_ecc_group_to_psa( peer_key->grp.id,
-                                                             &ecdh_bits ) );
-
-    if( ssl->handshake->ecdh_psa_type == 0 || ecdh_bits > 0xffff )
+    tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( peer_key->grp.id );
+    if( tls_id == 0 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Invalid ecc group conversion to psa." ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "ECC group %u not suported",
+                                peer_key->grp.id ) );
         return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
     }
 
-    ssl->handshake->ecdh_bits = (uint16_t) ecdh_bits;
+    /* If the above conversion to TLS ID was fine, then also this one will be,
+       so there is no need to check the return value here */
+    mbedtls_ssl_get_psa_curve_info_from_tls_id( tls_id, &ecc_family,
+                                &ssl->handshake->ecdh_bits );
+
+    ssl->handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR( ecc_family );
 
     /* Store peer's public key in psa format. */
     ret = mbedtls_ecp_point_write_binary( &peer_key->grp, &peer_key->Q,
@@ -2346,16 +2353,16 @@
          * that TLS ID here
          */
         uint16_t read_tls_id = MBEDTLS_GET_UINT16_BE( p, 1 );
-        const mbedtls_ecp_curve_info *curve_info;
+        uint16_t exp_tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(
+                                    MBEDTLS_ECP_DP_SECP256R1 );
 
-        if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id(
-                                MBEDTLS_ECP_DP_SECP256R1 ) ) == NULL )
+        if( exp_tls_id == 0 )
         {
             return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
         }
 
         if( ( *p != MBEDTLS_ECP_TLS_NAMED_CURVE ) ||
-            ( read_tls_id != curve_info->tls_id ) )
+            ( read_tls_id != exp_tls_id ) )
         {
             return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
         }
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index 5cdbcc0..a28cd67 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -180,7 +180,7 @@
 {
     size_t list_size, our_size;
     const unsigned char *p;
-    const mbedtls_ecp_curve_info *curve_info, **curves;
+    uint16_t *curves_tls_id;
 
     if ( len < 2 ) {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
@@ -199,7 +199,7 @@
     }
 
     /* Should never happen unless client duplicates the extension */
-    if( ssl->handshake->curves != NULL )
+    if( ssl->handshake->curves_tls_id != NULL )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
@@ -213,23 +213,25 @@
     if( our_size > MBEDTLS_ECP_DP_MAX )
         our_size = MBEDTLS_ECP_DP_MAX;
 
-    if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL )
+    if( ( curves_tls_id = mbedtls_calloc( our_size,
+                                sizeof( *curves_tls_id ) ) ) == NULL )
     {
         mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
                                         MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
         return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
     }
 
-    ssl->handshake->curves = curves;
+    ssl->handshake->curves_tls_id = curves_tls_id;
 
     p = buf + 2;
     while( list_size > 0 && our_size > 1 )
     {
-        curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] );
+        uint16_t curr_tls_id = MBEDTLS_GET_UINT16_BE( p, 0 );
 
-        if( curve_info != NULL )
+        if( mbedtls_ssl_get_ecp_group_id_from_tls_id( curr_tls_id ) !=
+                                        MBEDTLS_ECP_DP_NONE )
         {
-            *curves++ = curve_info;
+            *curves_tls_id++ = curr_tls_id;
             our_size--;
         }
 
@@ -685,16 +687,18 @@
 #if defined(MBEDTLS_ECDSA_C)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_key_curve( mbedtls_pk_context *pk,
-                                const mbedtls_ecp_curve_info **curves )
+                                uint16_t *curves_tls_id )
 {
-    const mbedtls_ecp_curve_info **crv = curves;
+    uint16_t *curr_tls_id = curves_tls_id;
     mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id;
+    mbedtls_ecp_group_id curr_grp_id;
 
-    while( *crv != NULL )
+    while( *curr_tls_id != 0 )
     {
-        if( (*crv)->grp_id == grp_id )
+        curr_grp_id = mbedtls_ssl_get_ecp_group_id_from_tls_id( *curr_tls_id );
+        if( curr_grp_id == grp_id )
             return( 0 );
-        crv++;
+        curr_tls_id++;
     }
 
     return( -1 );
@@ -789,7 +793,8 @@
 
 #if defined(MBEDTLS_ECDSA_C)
         if( pk_alg == MBEDTLS_PK_ECDSA &&
-            ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 )
+            ssl_check_key_curve( &cur->cert->pk,
+                            ssl->handshake->curves_tls_id ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) );
             continue;
@@ -857,8 +862,8 @@
 
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
     if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) &&
-        ( ssl->handshake->curves == NULL ||
-          ssl->handshake->curves[0] == NULL ) )
+        ( ssl->handshake->curves_tls_id == NULL ||
+          ssl->handshake->curves_tls_id[0] == 0 ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: "
                             "no common elliptic curve" ) );
@@ -2654,7 +2659,8 @@
     unsigned char buf[
         PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
     psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
-    size_t ecdh_bits = 0;
+    uint16_t tls_id = 0;
+    psa_ecc_family_t ecc_family;
     size_t key_len;
     mbedtls_pk_context *pk;
     mbedtls_ecp_keypair *key;
@@ -2698,15 +2704,19 @@
         if( key == NULL )
             return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
 
-        /* Convert EC group to PSA key type. */
-        if( ( ssl->handshake->ecdh_psa_type =
-                    mbedtls_ecc_group_to_psa( key->grp.id,
-                                              &ecdh_bits ) ) == 0 )
+        tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id( key->grp.id );
+        if( tls_id == 0 )
         {
+            /* This elliptic curve is not supported */
             return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
         }
 
-        ssl->handshake->ecdh_bits = ecdh_bits;
+        /* If the above conversion to TLS ID was fine, then also this one will
+           be, so there is no need to check the return value here */
+        mbedtls_ssl_get_psa_curve_info_from_tls_id( tls_id, &ecc_family,
+                                &ssl->handshake->ecdh_bits );
+
+        ssl->handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR( ecc_family );
 
         key_attributes = psa_key_attributes_init();
         psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE );
@@ -2849,7 +2859,6 @@
                                ssl->out_msglen;
         size_t output_offset = 0;
         size_t output_len = 0;
-        const mbedtls_ecp_curve_info *curve_info;
 
         /*
          * The first 3 bytes are:
@@ -2859,13 +2868,14 @@
          * However since we only support secp256r1 for now, we hardcode its
          * TLS ID here
          */
-        if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id(
-                                    MBEDTLS_ECP_DP_SECP256R1 ) ) == NULL )
+        uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(
+                                    MBEDTLS_ECP_DP_SECP256R1 );
+        if( tls_id ==0 )
         {
             return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
         }
         *out_p = MBEDTLS_ECP_TLS_NAMED_CURVE;
-        MBEDTLS_PUT_UINT16_BE( curve_info->tls_id, out_p, 1 );
+        MBEDTLS_PUT_UINT16_BE( tls_id, out_p, 1 );
         output_offset += 3;
 
         ret = mbedtls_psa_ecjpake_write_round( &ssl->handshake->psa_pake_ctx,
@@ -2986,50 +2996,52 @@
          *     ECPoint      public;
          * } ServerECDHParams;
          */
-        const mbedtls_ecp_curve_info **curve = NULL;
+        uint16_t *curr_tls_id = ssl->handshake->curves_tls_id;
         const uint16_t *group_list = mbedtls_ssl_get_groups( ssl );
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         size_t len = 0;
 
         /* Match our preference list against the offered curves */
-        if( group_list == NULL )
+        if( ( group_list == NULL ) || ( curr_tls_id == NULL ) )
             return( MBEDTLS_ERR_SSL_BAD_CONFIG );
         for( ; *group_list != 0; group_list++ )
-            for( curve = ssl->handshake->curves; *curve != NULL; curve++ )
-                if( (*curve)->tls_id == *group_list )
+            for( curr_tls_id = ssl->handshake->curves_tls_id;
+                 *curr_tls_id != 0; curr_tls_id++ )
+                if( *curr_tls_id == *group_list )
                     goto curve_matching_done;
 
 curve_matching_done:
-        if( curve == NULL || *curve == NULL )
+        if( *curr_tls_id == 0 )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) );
             return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
         }
 
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) );
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s",
+                    mbedtls_ssl_get_curve_name_from_tls_id(*curr_tls_id) ) );
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
         psa_status_t status = PSA_ERROR_GENERIC_ERROR;
         psa_key_attributes_t key_attributes;
         mbedtls_ssl_handshake_params *handshake = ssl->handshake;
-        size_t ecdh_bits = 0;
         uint8_t *p = ssl->out_msg + ssl->out_msglen;
         const size_t header_size = 4; // curve_type(1), namedcurve(2),
                                       // data length(1)
         const size_t data_length_size = 1;
+        psa_ecc_family_t ec_psa_family = 0;
+        size_t ec_bits = 0;
 
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Perform PSA-based ECDH computation." ) );
 
-        /* Convert EC group to PSA key type. */
-        handshake->ecdh_psa_type = mbedtls_psa_parse_tls_ecc_group(
-                    (*curve)->tls_id, &ecdh_bits );
-
-        if( handshake->ecdh_psa_type == 0 )
+        /* Convert EC's TLS ID to PSA key type. */
+        if( mbedtls_ssl_get_psa_curve_info_from_tls_id( *curr_tls_id,
+                &ec_psa_family, &ec_bits ) == PSA_ERROR_NOT_SUPPORTED )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "Invalid ecc group parse." ) );
             return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
         }
-        handshake->ecdh_bits = ecdh_bits;
+        handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR( ec_psa_family );
+        handshake->ecdh_bits = ec_bits;
 
         key_attributes = psa_key_attributes_init();
         psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE );
@@ -3047,7 +3059,7 @@
         /*
          * Next two bytes are the namedcurve value
          */
-        MBEDTLS_PUT_UINT16_BE( (*curve)->tls_id, p, 0 );
+        MBEDTLS_PUT_UINT16_BE( *curr_tls_id, p, 0 );
         p += 2;
 
         /* Generate ECDH private key. */
@@ -3093,8 +3105,11 @@
         /* Determine full message length. */
         len += header_size;
 #else
+        mbedtls_ecp_group_id curr_grp_id =
+                    mbedtls_ssl_get_ecp_group_id_from_tls_id( *curr_tls_id );
+
         if( ( ret = mbedtls_ecdh_setup( &ssl->handshake->ecdh_ctx,
-                                        (*curve)->grp_id ) ) != 0 )
+                                        curr_grp_id ) ) != 0 )
         {
             MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret );
             return( ret );
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 839b954..f07c8b6 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -230,9 +230,8 @@
 
     for ( ; *group_list != 0; group_list++ )
     {
-        const mbedtls_ecp_curve_info *curve_info;
-        curve_info = mbedtls_ecp_curve_info_from_tls_id( *group_list );
-        if( curve_info != NULL &&
+        if( ( mbedtls_ssl_get_psa_curve_info_from_tls_id( *group_list,
+                            NULL, NULL ) == PSA_SUCCESS ) &&
             mbedtls_ssl_tls13_named_group_is_ecdhe( *group_list ) )
         {
             *group_id = *group_list;
@@ -385,7 +384,6 @@
                                               const unsigned char *end )
 {
 #if defined(MBEDTLS_ECDH_C)
-    const mbedtls_ecp_curve_info *curve_info = NULL;
     const unsigned char *p = buf;
     int selected_group;
     int found = 0;
@@ -412,8 +410,9 @@
      */
     for( ; *group_list != 0; group_list++ )
     {
-        curve_info = mbedtls_ecp_curve_info_from_tls_id( *group_list );
-        if( curve_info == NULL || curve_info->tls_id != selected_group )
+        if( ( mbedtls_ssl_get_psa_curve_info_from_tls_id( *group_list,
+                NULL, NULL ) == PSA_ERROR_NOT_SUPPORTED ) ||
+                *group_list != selected_group )
             continue;
 
         /* We found a match */
@@ -493,15 +492,15 @@
 #if defined(MBEDTLS_ECDH_C)
     if( mbedtls_ssl_tls13_named_group_is_ecdhe( group ) )
     {
-        const mbedtls_ecp_curve_info *curve_info =
-            mbedtls_ecp_curve_info_from_tls_id( group );
-        if( curve_info == NULL )
+        if( mbedtls_ssl_get_psa_curve_info_from_tls_id( group, NULL, NULL )
+                    == PSA_ERROR_NOT_SUPPORTED )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "Invalid TLS curve group id" ) );
             return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
         }
 
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) );
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s",
+                    mbedtls_ssl_get_curve_name_from_tls_id( group ) ) );
 
         ret = mbedtls_ssl_tls13_read_public_ecdhe_share( ssl, p, end - p );
         if( ret != 0 )
@@ -2805,11 +2804,10 @@
 
     switch( ssl->state )
     {
-        /*
-         * ssl->state is initialized as HELLO_REQUEST. It is the same
-         * as CLIENT_HELLO state.
-         */
         case MBEDTLS_SSL_HELLO_REQUEST:
+            mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_HELLO );
+            break;
+
         case MBEDTLS_SSL_CLIENT_HELLO:
             ret = mbedtls_ssl_write_client_hello( ssl );
             break;
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index 761c00e..121ff43 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -28,16 +28,14 @@
 #include "mbedtls/oid.h"
 #include "mbedtls/platform.h"
 #include "mbedtls/constant_time.h"
-#include <string.h>
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
 
 #include "ssl_misc.h"
 #include "ssl_tls13_invasive.h"
 #include "ssl_tls13_keys.h"
 #include "ssl_debug_helpers.h"
 
-#include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
-
 const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[
                 MBEDTLS_SERVER_HELLO_RANDOM_LEN ] =
                     { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
@@ -1518,16 +1516,19 @@
     psa_key_attributes_t key_attributes;
     size_t own_pubkey_len;
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
-    size_t ecdh_bits = 0;
+    psa_ecc_family_t ec_psa_family = 0;
+    size_t ec_bits = 0;
 
     MBEDTLS_SSL_DEBUG_MSG( 1, ( "Perform PSA-based ECDH computation." ) );
 
-    /* Convert EC group to PSA key type. */
-    if( ( handshake->ecdh_psa_type =
-        mbedtls_psa_parse_tls_ecc_group( named_group, &ecdh_bits ) ) == 0 )
-            return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
-
-    ssl->handshake->ecdh_bits = ecdh_bits;
+    /* Convert EC's TLS ID to PSA key type. */
+    if( mbedtls_ssl_get_psa_curve_info_from_tls_id( named_group,
+                &ec_psa_family, &ec_bits ) == PSA_ERROR_NOT_SUPPORTED )
+    {
+        return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+    }
+    handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR( ec_psa_family );
+    ssl->handshake->ecdh_bits = ec_bits;
 
     key_attributes = psa_key_attributes_init();
     psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE );
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 6caae89..685e10b 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -30,16 +30,6 @@
 #include "ssl_tls13_keys.h"
 #include "ssl_debug_helpers.h"
 
-#if defined(MBEDTLS_ECP_C)
-#include "mbedtls/ecp.h"
-#endif /* MBEDTLS_ECP_C */
-
-#include "mbedtls/platform.h"
-
-#include "ssl_misc.h"
-#include "ssl_tls13_keys.h"
-#include "ssl_debug_helpers.h"
-
 
 static const mbedtls_ssl_ciphersuite_t *ssl_tls13_validate_peer_ciphersuite(
                                       mbedtls_ssl_context *ssl,
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 6313c52..8fb0fef 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -61,9 +61,11 @@
 
 #include "mbedtls/error.h"
 
+/* *INDENT-OFF* */
 #ifndef asm
 #define asm __asm
 #endif
+/* *INDENT-ON* */
 
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
 
@@ -398,7 +400,7 @@
     }
 
     gettimeofday( &tv_cur, NULL );
-    return( ( tv_cur.tv_sec  - tv_init.tv_sec  ) * 1000000
+    return( ( tv_cur.tv_sec  - tv_init.tv_sec  ) * 1000000U
           + ( tv_cur.tv_usec - tv_init.tv_usec ) );
 }
 #endif /* !HAVE_HARDCLOCK */
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 2d6103c..b4701cb 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -243,9 +243,15 @@
 #if defined(MBEDTLS_SHA1_C)
     {"sha1", mbedtls_sha1_self_test},
 #endif
+#if defined(MBEDTLS_SHA224_C)
+    {"sha224", mbedtls_sha224_self_test},
+#endif
 #if defined(MBEDTLS_SHA256_C)
     {"sha256", mbedtls_sha256_self_test},
 #endif
+#if defined(MBEDTLS_SHA384_C)
+    {"sha384", mbedtls_sha384_self_test},
+#endif
 #if defined(MBEDTLS_SHA512_C)
     {"sha512", mbedtls_sha512_self_test},
 #endif
diff --git a/scripts/code_style.py b/scripts/code_style.py
index 68cd556..aae3e24 100755
--- a/scripts/code_style.py
+++ b/scripts/code_style.py
@@ -22,9 +22,10 @@
 import argparse
 import io
 import os
+import re
 import subprocess
 import sys
-from typing import List
+from typing import FrozenSet, List
 
 UNCRUSTIFY_SUPPORTED_VERSION = "0.75.1"
 CONFIG_FILE = ".uncrustify.cfg"
@@ -32,10 +33,33 @@
 UNCRUSTIFY_ARGS = ["-c", CONFIG_FILE]
 STDOUT_UTF8 = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
 STDERR_UTF8 = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
+CHECK_GENERATED_FILES = "tests/scripts/check-generated-files.sh"
 
 def print_err(*args):
     print("Error: ", *args, file=STDERR_UTF8)
 
+# Match FILENAME(s) in "check SCRIPT (FILENAME...)"
+CHECK_CALL_RE = re.compile(r"\n\s*check\s+[^\s#$&*?;|]+([^\n#$&*?;|]+)",
+                           re.ASCII)
+def list_generated_files() -> FrozenSet[str]:
+    """Return the names of generated files.
+
+    We don't reformat generated files, since the result might be different
+    from the output of the generator. Ideally the result of the generator
+    would conform to the code style, but this would be difficult, especially
+    with respect to the placement of line breaks in long logical lines.
+    """
+    # Parse check-generated-files.sh to get an up-to-date list of
+    # generated files. Read the file rather than calling it so that
+    # this script only depends on Git, Python and uncrustify, and not other
+    # tools such as sh or grep which might not be available on Windows.
+    # This introduces a limitation: check-generated-files.sh must have
+    # the expected format and must list the files explicitly, not through
+    # wildcards or command substitution.
+    content = open(CHECK_GENERATED_FILES, encoding="utf-8").read()
+    checks = re.findall(CHECK_CALL_RE, content)
+    return frozenset(word for s in checks for word in s.split())
+
 def get_src_files() -> List[str]:
     """
     Use git ls-files to get a list of the source files
@@ -52,11 +76,14 @@
         print_err("git ls-files returned: " + str(result.returncode))
         return []
     else:
+        generated_files = list_generated_files()
         src_files = str(result.stdout, "utf-8").split()
-        # Don't correct style for files in 3rdparty/
-        src_files = list(filter( \
-                lambda filename: not filename.startswith("3rdparty/"), \
-                src_files))
+        # Don't correct style for third-party files (and, for simplicity,
+        # companion files in the same subtree), or for automatically
+        # generated files (we're correcting the templates instead).
+        src_files = [filename for filename in src_files
+                     if not (filename.startswith("3rdparty/") or
+                             filename in generated_files)]
         return src_files
 
 def get_uncrustify_version() -> str:
@@ -79,8 +106,12 @@
     style_correct = True
     for src_file in src_file_list:
         uncrustify_cmd = [UNCRUSTIFY_EXE] + UNCRUSTIFY_ARGS + [src_file]
-        subprocess.run(uncrustify_cmd, stdout=subprocess.PIPE, \
+        result = subprocess.run(uncrustify_cmd, stdout=subprocess.PIPE, \
                 stderr=subprocess.PIPE, check=False)
+        if result.returncode != 0:
+            print_err("Uncrustify returned " + str(result.returncode) + \
+                    " correcting file " + src_file)
+            return False
 
         # Uncrustify makes changes to the code and places the result in a new
         # file with the extension ".uncrustify". To get the changes (if any)
@@ -101,22 +132,30 @@
 
     return style_correct
 
-def fix_style_single_pass(src_file_list: List[str]) -> None:
+def fix_style_single_pass(src_file_list: List[str]) -> bool:
     """
     Run Uncrustify once over the source files.
     """
     code_change_args = UNCRUSTIFY_ARGS + ["--no-backup"]
     for src_file in src_file_list:
         uncrustify_cmd = [UNCRUSTIFY_EXE] + code_change_args + [src_file]
-        subprocess.run(uncrustify_cmd, check=False, stdout=STDOUT_UTF8, \
-                stderr=STDERR_UTF8)
+        result = subprocess.run(uncrustify_cmd, check=False, \
+                stdout=STDOUT_UTF8, stderr=STDERR_UTF8)
+        if result.returncode != 0:
+            print_err("Uncrustify with file returned: " + \
+                    str(result.returncode) + " correcting file " + \
+                    src_file)
+            return False
+    return True
 
 def fix_style(src_file_list: List[str]) -> int:
     """
     Fix the code style. This takes 2 passes of Uncrustify.
     """
-    fix_style_single_pass(src_file_list)
-    fix_style_single_pass(src_file_list)
+    if not fix_style_single_pass(src_file_list):
+        return 1
+    if not fix_style_single_pass(src_file_list):
+        return 1
 
     # Guard against future changes that cause the codebase to require
     # more passes.
diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl
index 5395abf..878cfba 100755
--- a/scripts/generate_errors.pl
+++ b/scripts/generate_errors.pl
@@ -60,11 +60,11 @@
 my $error_format = <FORMAT_FILE>;
 close(FORMAT_FILE);
 
-my @files = <$include_dir/*.h>;
+my @files = glob qq("$include_dir/*.h");
 my @necessary_include_files;
 my @matches;
 foreach my $file (@files) {
-    open(FILE, '<:crlf', "$file");
+    open(FILE, '<:crlf', $file) or die("$0: $file: $!");
     my $content = <FILE>;
     close FILE;
     my $found = 0;
diff --git a/scripts/mbedtls_dev/bignum_common.py b/scripts/mbedtls_dev/bignum_common.py
index c4efabf..2422175 100644
--- a/scripts/mbedtls_dev/bignum_common.py
+++ b/scripts/mbedtls_dev/bignum_common.py
@@ -15,6 +15,7 @@
 # limitations under the License.
 
 from abc import abstractmethod
+import enum
 from typing import Iterator, List, Tuple, TypeVar, Any
 from itertools import chain
 
@@ -53,7 +54,7 @@
         return 0
     return int(val, 16)
 
-def quote_str(val) -> str:
+def quote_str(val: str) -> str:
     return "\"{}\"".format(val)
 
 def bound_mpi(val: int, bits_in_limb: int) -> int:
@@ -139,7 +140,7 @@
     def hex_digits(self) -> int:
         return 2 * (self.limbs * self.bits_in_limb // 8)
 
-    def format_arg(self, val) -> str:
+    def format_arg(self, val: str) -> str:
         if self.input_style not in self.input_styles:
             raise ValueError("Unknown input style!")
         if self.input_style == "variable":
@@ -147,7 +148,7 @@
         else:
             return val.zfill(self.hex_digits)
 
-    def format_result(self, res) -> str:
+    def format_result(self, res: int) -> str:
         res_str = '{:x}'.format(res)
         return quote_str(self.format_arg(res_str))
 
@@ -245,6 +246,23 @@
                     )
 
 
+class ModulusRepresentation(enum.Enum):
+    """Representation selector of a modulus."""
+    # Numerical values aligned with the type mbedtls_mpi_mod_rep_selector
+    INVALID = 0
+    MONTGOMERY = 2
+    OPT_RED = 3
+
+    def symbol(self) -> str:
+        """The C symbol for this representation selector."""
+        return 'MBEDTLS_MPI_MOD_REP_' + self.name
+
+    @classmethod
+    def supported_representations(cls) -> List['ModulusRepresentation']:
+        """Return all representations that are supported in positive test cases."""
+        return [cls.MONTGOMERY, cls.OPT_RED]
+
+
 class ModOperationCommon(OperationCommon):
     #pylint: disable=abstract-method
     """Target for bignum mod_raw test case generation."""
@@ -266,6 +284,17 @@
     def from_montgomery(self, val: int) -> int:
         return (val * self.r_inv) % self.int_n
 
+    def convert_from_canonical(self, canonical: int,
+                               rep: ModulusRepresentation) -> int:
+        """Convert values from canonical representation to the given representation."""
+        if rep is ModulusRepresentation.MONTGOMERY:
+            return self.to_montgomery(canonical)
+        elif rep is ModulusRepresentation.OPT_RED:
+            return canonical
+        else:
+            raise ValueError('Modulus representation not supported: {}'
+                             .format(rep.name))
+
     @property
     def boundary(self) -> int:
         return self.int_n
@@ -282,6 +311,9 @@
     def arg_n(self) -> str:
         return self.format_arg(self.val_n)
 
+    def format_arg(self, val: str) -> str:
+        return super().format_arg(val).zfill(self.hex_digits)
+
     def arguments(self) -> List[str]:
         return [quote_str(self.arg_n)] + super().arguments()
 
diff --git a/scripts/mbedtls_dev/bignum_mod.py b/scripts/mbedtls_dev/bignum_mod.py
index 25afe30..a83e136 100644
--- a/scripts/mbedtls_dev/bignum_mod.py
+++ b/scripts/mbedtls_dev/bignum_mod.py
@@ -31,6 +31,26 @@
 
 # BEGIN MERGE SLOT 2
 
+class BignumModMul(bignum_common.ModOperationCommon,
+                   BignumModTarget):
+    # pylint:disable=duplicate-code
+    """Test cases for bignum mpi_mod_mul()."""
+    symbol = "*"
+    test_function = "mpi_mod_mul"
+    test_name = "mbedtls_mpi_mod_mul"
+    input_style = "arch_split"
+    arity = 2
+
+    def arguments(self) -> List[str]:
+        return [self.format_result(self.to_montgomery(self.int_a)),
+                self.format_result(self.to_montgomery(self.int_b)),
+                bignum_common.quote_str(self.arg_n)
+               ] + self.result()
+
+    def result(self) -> List[str]:
+        result = (self.int_a * self.int_b) % self.int_n
+        return [self.format_result(self.to_montgomery(result))]
+
 # END MERGE SLOT 2
 
 # BEGIN MERGE SLOT 3
diff --git a/scripts/mbedtls_dev/bignum_mod_raw.py b/scripts/mbedtls_dev/bignum_mod_raw.py
index 09bbbee..f9d9899 100644
--- a/scripts/mbedtls_dev/bignum_mod_raw.py
+++ b/scripts/mbedtls_dev/bignum_mod_raw.py
@@ -14,8 +14,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from typing import Dict, List
+from typing import Iterator, List
 
+from . import test_case
 from . import test_data_generation
 from . import bignum_common
 from .bignum_data import ONLY_PRIME_MODULI
@@ -116,6 +117,88 @@
 
 # BEGIN MERGE SLOT 6
 
+class BignumModRawConvertRep(bignum_common.ModOperationCommon,
+                             BignumModRawTarget):
+    # This is an abstract class, it's ok to have unimplemented methods.
+    #pylint: disable=abstract-method
+    """Test cases for representation conversion."""
+    symbol = ""
+    input_style = "arch_split"
+    arity = 1
+    rep = bignum_common.ModulusRepresentation.INVALID
+
+    def set_representation(self, r: bignum_common.ModulusRepresentation) -> None:
+        self.rep = r
+
+    def arguments(self) -> List[str]:
+        return ([bignum_common.quote_str(self.arg_n), self.rep.symbol(),
+                 bignum_common.quote_str(self.arg_a)] +
+                self.result())
+
+    def description(self) -> str:
+        base = super().description()
+        mod_with_rep = 'mod({})'.format(self.rep.name)
+        return base.replace('mod', mod_with_rep, 1)
+
+    @classmethod
+    def test_cases_for_values(cls, rep: bignum_common.ModulusRepresentation,
+                              n: str, a: str) -> Iterator[test_case.TestCase]:
+        """Emit test cases for the given values (if any).
+
+        This may emit no test cases if a isn't valid for the modulus n,
+        or multiple test cases if rep requires different data depending
+        on the limb size.
+        """
+        for bil in cls.limb_sizes:
+            test_object = cls(n, a, bits_in_limb=bil)
+            test_object.set_representation(rep)
+            # The class is set to having separate test cases for each limb
+            # size, because the Montgomery representation requires it.
+            # But other representations don't require it. So for other
+            # representations, emit a single test case with no dependency
+            # on the limb size.
+            if rep is not bignum_common.ModulusRepresentation.MONTGOMERY:
+                test_object.dependencies = \
+                    [dep for dep in test_object.dependencies
+                     if not dep.startswith('MBEDTLS_HAVE_INT')]
+            if test_object.is_valid:
+                yield test_object.create_test_case()
+            if rep is not bignum_common.ModulusRepresentation.MONTGOMERY:
+                # A single test case (emitted, or skipped due to invalidity)
+                # is enough, since this test case doesn't depend on the
+                # limb size.
+                break
+
+    # The parent class doesn't support non-bignum parameters. So we override
+    # test generation, in order to have the representation as a parameter.
+    @classmethod
+    def generate_function_tests(cls) -> Iterator[test_case.TestCase]:
+
+        for rep in bignum_common.ModulusRepresentation.supported_representations():
+            for n in cls.moduli:
+                for a in cls.input_values:
+                    yield from cls.test_cases_for_values(rep, n, a)
+
+class BignumModRawCanonicalToModulusRep(BignumModRawConvertRep):
+    """Test cases for mpi_mod_raw_canonical_to_modulus_rep."""
+    test_function = "mpi_mod_raw_canonical_to_modulus_rep"
+    test_name = "Rep canon->mod"
+
+    def result(self) -> List[str]:
+        return [self.format_result(self.convert_from_canonical(self.int_a, self.rep))]
+
+class BignumModRawModulusToCanonicalRep(BignumModRawConvertRep):
+    """Test cases for mpi_mod_raw_modulus_to_canonical_rep."""
+    test_function = "mpi_mod_raw_modulus_to_canonical_rep"
+    test_name = "Rep mod->canon"
+
+    @property
+    def arg_a(self) -> str:
+        return self.format_arg("{:x}".format(self.convert_from_canonical(self.int_a, self.rep)))
+
+    def result(self) -> List[str]:
+        return [self.format_result(self.int_a)]
+
 # END MERGE SLOT 6
 
 # BEGIN MERGE SLOT 7
diff --git a/tests/include/test/bignum_helpers.h b/tests/include/test/bignum_helpers.h
new file mode 100644
index 0000000..164017e
--- /dev/null
+++ b/tests/include/test/bignum_helpers.h
@@ -0,0 +1,118 @@
+/**
+ * \file bignum_helpers.h
+ *
+ * \brief   This file contains the prototypes of helper functions for
+ *          bignum-related testing.
+ */
+
+/*
+ *  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.
+ */
+
+#ifndef TEST_BIGNUM_HELPERS_H
+#define TEST_BIGNUM_HELPERS_H
+
+#include <mbedtls/build_info.h>
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+#include <mbedtls/bignum.h>
+#include <bignum_mod.h>
+
+/** Allocate and populate a core MPI from a test case argument.
+ *
+ * This function allocates exactly as many limbs as necessary to fit
+ * the length of the input. In other words, it preserves leading zeros.
+ *
+ * The limb array is allocated with mbedtls_calloc() and must later be
+ * freed with mbedtls_free().
+ *
+ * \param[in,out] pX    The address where a pointer to the allocated limb
+ *                      array will be stored.
+ *                      \c *pX must be null on entry.
+ *                      On exit, \c *pX is null on error or if the number
+ *                      of limbs is 0.
+ * \param[out] plimbs   The address where the number of limbs will be stored.
+ * \param[in] input     The test argument to read.
+ *                      It is interpreted as a hexadecimal representation
+ *                      of a non-negative integer.
+ *
+ * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
+ */
+int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
+                                const char *input );
+
+/** Read a modulus from a hexadecimal string.
+ *
+ * This function allocates exactly as many limbs as necessary to fit
+ * the length of the input. In other words, it preserves leading zeros.
+ *
+ * The limb array is allocated with mbedtls_calloc() and must later be
+ * freed with mbedtls_free(). You can do that by calling
+ * mbedtls_test_mpi_mod_modulus_free_with_limbs().
+ *
+ * \param[in,out] N     A modulus structure. It must be initialized, but
+ *                      not set up.
+ * \param[in] s         The null-terminated hexadecimal string to read from.
+ * \param int_rep       The desired representation of residues.
+ *
+ * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
+ */
+int mbedtls_test_read_mpi_modulus( mbedtls_mpi_mod_modulus *N,
+                                   const char *s,
+                                   mbedtls_mpi_mod_rep_selector int_rep );
+
+/** Free a modulus and its limbs.
+ *
+ * \param[in] N         A modulus structure such that there is no other
+ *                      reference to `N->p`.
+ */
+void mbedtls_test_mpi_mod_modulus_free_with_limbs( mbedtls_mpi_mod_modulus *N );
+
+/** Read an MPI from a hexadecimal string.
+ *
+ * Like mbedtls_mpi_read_string(), but with tighter guarantees around
+ * edge cases.
+ *
+ * - This function guarantees that if \p s begins with '-' then the sign
+ *   bit of the result will be negative, even if the value is 0.
+ *   When this function encounters such a "negative 0", it
+ *   increments #mbedtls_test_case_uses_negative_0.
+ * - The size of the result is exactly the minimum number of limbs needed
+ *   to fit the digits in the input. In particular, this function constructs
+ *   a bignum with 0 limbs for an empty string, and a bignum with leading 0
+ *   limbs if the string has sufficiently many leading 0 digits.
+ *   This is important so that the "0 (null)" and "0 (1 limb)" and
+ *   "leading zeros" test cases do what they claim.
+ *
+ * \param[out] X        The MPI object to populate. It must be initialized.
+ * \param[in] s         The null-terminated hexadecimal string to read from.
+ *
+ * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
+ */
+int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s );
+
+/** Nonzero if the current test case had an input parsed with
+ * mbedtls_test_read_mpi() that is a negative 0 (`"-"`, `"-0"`, `"-00"`, etc.,
+ * constructing a result with the sign bit set to -1 and the value being
+ * all-limbs-0, which is not a valid representation in #mbedtls_mpi but is
+ * tested for robustness).
+ */
+extern unsigned mbedtls_test_case_uses_negative_0;
+
+#endif /* MBEDTLS_BIGNUM_C */
+
+#endif /* TEST_BIGNUM_HELPERS_H */
diff --git a/tests/include/test/drivers/config_test_driver.h b/tests/include/test/drivers/config_test_driver.h
index 6a7fb1f..22518bf 100644
--- a/tests/include/test/drivers/config_test_driver.h
+++ b/tests/include/test/drivers/config_test_driver.h
@@ -35,7 +35,6 @@
 /* PSA core mandatory configuration options */
 #define MBEDTLS_CIPHER_C
 #define MBEDTLS_AES_C
-#define MBEDTLS_SHA224_C
 #define MBEDTLS_SHA256_C
 #define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1
 #define MBEDTLS_CTR_DRBG_C
@@ -46,6 +45,7 @@
  * purpose of a specific set of tests.
  */
 //#define MBEDTLS_SHA1_C
+//#define MBEDTLS_SHA224_C
 //#define MBEDTLS_SHA384_C
 //#define MBEDTLS_SHA512_C
 //#define MBEDTLS_MD_C
diff --git a/tests/include/test/helpers.h b/tests/include/test/helpers.h
index 5f9bde6..b64bfcb 100644
--- a/tests/include/test/helpers.h
+++ b/tests/include/test/helpers.h
@@ -216,6 +216,17 @@
                           int len );
 
 /**
+ * \brief Convert hexadecimal digit to an integer.
+ *
+ * \param c        The digit to convert (`'0'` to `'9'`, `'A'` to `'F'` or
+ *                 `'a'` to `'f'`).
+ * \param[out] uc  On success, the value of the digit (0 to 15).
+ *
+ * \return         0 on success, -1 if \p c is not a hexadecimal digit.
+ */
+int mbedtls_test_ascii2uc(const char c, unsigned char *uc);
+
+/**
  * Allocate and zeroize a buffer.
  *
  * If the size if zero, a pointer to a zeroized 1-byte buffer is returned.
@@ -269,60 +280,4 @@
                                  const char *file, int line);
 #endif
 
-#if defined(MBEDTLS_BIGNUM_C)
-/** Allocate and populate a core MPI from a test case argument.
- *
- * This function allocates exactly as many limbs as necessary to fit
- * the length of the input. In other words, it preserves leading zeros.
- *
- * The limb array is allocated with mbedtls_calloc() and must later be
- * freed with mbedtls_free().
- *
- * \param[in,out] pX    The address where a pointer to the allocated limb
- *                      array will be stored.
- *                      \c *pX must be null on entry.
- *                      On exit, \c *pX is null on error or if the number
- *                      of limbs is 0.
- * \param[out] plimbs   The address where the number of limbs will be stored.
- * \param[in] input     The test argument to read.
- *                      It is interpreted as a hexadecimal representation
- *                      of a non-negative integer.
- *
- * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
- */
-int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
-                                const char *input );
-
-/** Read an MPI from a hexadecimal string.
- *
- * Like mbedtls_mpi_read_string(), but with tighter guarantees around
- * edge cases.
- *
- * - This function guarantees that if \p s begins with '-' then the sign
- *   bit of the result will be negative, even if the value is 0.
- *   When this function encounters such a "negative 0", it
- *   increments #mbedtls_test_case_uses_negative_0.
- * - The size of the result is exactly the minimum number of limbs needed
- *   to fit the digits in the input. In particular, this function constructs
- *   a bignum with 0 limbs for an empty string, and a bignum with leading 0
- *   limbs if the string has sufficiently many leading 0 digits.
- *   This is important so that the "0 (null)" and "0 (1 limb)" and
- *   "leading zeros" test cases do what they claim.
- *
- * \param[out] X        The MPI object to populate. It must be initialized.
- * \param[in] s         The null-terminated hexadecimal string to read from.
- *
- * \return \c 0 on success, an \c MBEDTLS_ERR_MPI_xxx error code otherwise.
- */
-int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s );
-
-/** Nonzero if the current test case had an input parsed with
- * mbedtls_test_read_mpi() that is a negative 0 (`"-"`, `"-0"`, `"-00"`, etc.,
- * constructing a result with the sign bit set to -1 and the value being
- * all-limbs-0, which is not a valid representation in #mbedtls_mpi but is
- * tested for robustness).
- */
-extern unsigned mbedtls_test_case_uses_negative_0;
-#endif /* MBEDTLS_BIGNUM_C */
-
 #endif /* TEST_HELPERS_H */
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 0695a8c..6b11346 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -870,7 +870,7 @@
     else
         opt=''
     fi
-    tests/scripts/check_test_cases.py $opt
+    tests/scripts/check_test_cases.py -q $opt
     unset opt
 }
 
@@ -939,6 +939,19 @@
 
     msg "test: context-info.sh (full config, ASan build)" # ~ 15 sec
     tests/context-info.sh
+
+    msg "test: check direct ECP dependencies in TLS and X.509"
+    docs/architecture/psa-migration/syms.sh full
+
+    # TODO: replace "mbedtls_ecp_curve" with "mbedtls_ecp" also for
+    # "full-tls-external" once Issue6839 is completed
+    not grep mbedtls_ecp_curve full-tls-external
+    not grep mbedtls_ecp full-x509-external
+
+    rm  full-tls-external \
+        full-tls-modules \
+        full-x509-external \
+        full-x509-modules
 }
 
 component_test_psa_crypto_key_id_encodes_owner () {
@@ -1277,6 +1290,57 @@
     make test
 }
 
+component_test_full_no_bignum () {
+    msg "build: full minus bignum"
+    scripts/config.py full
+    scripts/config.py unset MBEDTLS_BIGNUM_C
+    # Direct dependencies of bignum
+    scripts/config.py unset MBEDTLS_ECP_C
+    scripts/config.py unset MBEDTLS_RSA_C
+    scripts/config.py unset MBEDTLS_DHM_C
+    # Direct dependencies of ECP
+    scripts/config.py unset MBEDTLS_ECDH_C
+    scripts/config.py unset MBEDTLS_ECDSA_C
+    scripts/config.py unset MBEDTLS_ECJPAKE_C
+    scripts/config.py unset MBEDTLS_ECP_RESTARTABLE
+    # Indirect dependencies of ECP
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECJPAKE_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
+    # Direct dependencies of DHM
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+    # Direct dependencies of RSA
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_X509_RSASSA_PSS_SUPPORT
+    # PK and its dependencies
+    scripts/config.py unset MBEDTLS_PK_C
+    scripts/config.py unset MBEDTLS_PK_PARSE_C
+    scripts/config.py unset MBEDTLS_PK_WRITE_C
+    scripts/config.py unset MBEDTLS_X509_USE_C
+    scripts/config.py unset MBEDTLS_X509_CRT_PARSE_C
+    scripts/config.py unset MBEDTLS_X509_CRL_PARSE_C
+    scripts/config.py unset MBEDTLS_X509_CSR_PARSE_C
+    scripts/config.py unset MBEDTLS_X509_CREATE_C
+    scripts/config.py unset MBEDTLS_X509_CRT_WRITE_C
+    scripts/config.py unset MBEDTLS_X509_CSR_WRITE_C
+    scripts/config.py unset MBEDTLS_PKCS7_C
+    scripts/config.py unset MBEDTLS_SSL_SERVER_NAME_INDICATION
+    scripts/config.py unset MBEDTLS_SSL_ASYNC_PRIVATE
+    scripts/config.py unset MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
+
+    make
+
+    msg "test: full minus bignum"
+    make test
+}
+
 component_test_tls1_2_default_stream_cipher_only () {
     msg "build: default with only stream cipher"
 
@@ -1969,7 +2033,8 @@
     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
 
-    # SHA384 needed for some ECDSA signature tests.
+    # These hashes are needed for some ECDSA signature tests.
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA224_C
     scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA384_C
     scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA512_C
 
@@ -1978,6 +2043,7 @@
     make -C tests libtestdriver1.a CFLAGS="$ASAN_CFLAGS $loc_accel_flags" LDFLAGS="$ASAN_CFLAGS"
 
     # Restore test driver base configuration
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_SHA224_C
     scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_SHA384_C
     scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_SHA512_C
 
@@ -2062,6 +2128,7 @@
     scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RIPEMD160_C
 
     scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA1_C
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA224_C
     scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_SHA512_C
     # We need to define either MD_C or all of the PSA_WANT_ALG_SHAxxx.
     scripts/config.py -f tests/include/test/drivers/config_test_driver.h set MBEDTLS_MD_C
@@ -2076,6 +2143,7 @@
 
     # Restore test driver base configuration
     scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_SHA1_C
+    scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_SHA224_C
     scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_SHA512_C
     scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_MD_C
     scripts/config.py -f tests/include/test/drivers/config_test_driver.h unset MBEDTLS_PEM_PARSE_C
diff --git a/tests/scripts/basic-build-test.sh b/tests/scripts/basic-build-test.sh
index 4aeeb23..32be0ee 100755
--- a/tests/scripts/basic-build-test.sh
+++ b/tests/scripts/basic-build-test.sh
@@ -243,35 +243,16 @@
     echo
 
 
-    # Step 4e - Coverage
-    echo "Coverage"
-
-    LINES_TESTED=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  lines......: [0-9]*.[0-9]% (\([0-9]*\) of [0-9]* lines)/\1/p')
-    LINES_TOTAL=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  lines......: [0-9]*.[0-9]% ([0-9]* of \([0-9]*\) lines)/\1/p')
-    FUNCS_TESTED=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  functions..: [0-9]*.[0-9]% (\([0-9]*\) of [0-9]* functions)$/\1/p')
-    FUNCS_TOTAL=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  functions..: [0-9]*.[0-9]% ([0-9]* of \([0-9]*\) functions)$/\1/p')
-    BRANCHES_TESTED=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  branches...: [0-9]*.[0-9]% (\([0-9]*\) of [0-9]* branches)$/\1/p')
-    BRANCHES_TOTAL=$(tail -n4 cov-$TEST_OUTPUT|sed -n -e 's/  branches...: [0-9]*.[0-9]% ([0-9]* of \([0-9]*\) branches)$/\1/p')
-
-    LINES_PERCENT=$((1000*$LINES_TESTED/$LINES_TOTAL))
-    LINES_PERCENT="$(($LINES_PERCENT/10)).$(($LINES_PERCENT-($LINES_PERCENT/10)*10))"
-
-    FUNCS_PERCENT=$((1000*$FUNCS_TESTED/$FUNCS_TOTAL))
-    FUNCS_PERCENT="$(($FUNCS_PERCENT/10)).$(($FUNCS_PERCENT-($FUNCS_PERCENT/10)*10))"
-
-    BRANCHES_PERCENT=$((1000*$BRANCHES_TESTED/$BRANCHES_TOTAL))
-    BRANCHES_PERCENT="$(($BRANCHES_PERCENT/10)).$(($BRANCHES_PERCENT-($BRANCHES_PERCENT/10)*10))"
+    # Step 4e - Coverage report
+    echo "Coverage statistics:"
+    sed -n '1,/^Overall coverage/d; /%/p' cov-$TEST_OUTPUT
+    echo
 
     rm unit-test-$TEST_OUTPUT
     rm sys-test-$TEST_OUTPUT
     rm compat-test-$TEST_OUTPUT
     rm cov-$TEST_OUTPUT
 
-    echo "Lines Tested       : $LINES_TESTED of $LINES_TOTAL $LINES_PERCENT%"
-    echo "Functions Tested   : $FUNCS_TESTED of $FUNCS_TOTAL $FUNCS_PERCENT%"
-    echo "Branches Tested    : $BRANCHES_TESTED of $BRANCHES_TOTAL $BRANCHES_PERCENT%"
-    echo
-
     # Mark the report generation as having succeeded. This must be the
     # last thing in the report generation.
     touch "basic-build-test-$$.ok"
diff --git a/tests/scripts/check-generated-files.sh b/tests/scripts/check-generated-files.sh
index 3006ec7..946794c 100755
--- a/tests/scripts/check-generated-files.sh
+++ b/tests/scripts/check-generated-files.sh
@@ -116,6 +116,16 @@
     fi
 }
 
+# Note: if the format of calls to the "check" function changes, update
+# scripts/code_style.py accordingly. For generated C source files (*.h or *.c),
+# the format must be "check SCRIPT FILENAME...". For other source files,
+# any shell syntax is permitted (including e.g. command substitution).
+
+# Note: Instructions to generate those files are replicated in:
+#   - **/Makefile (to (re)build them with make)
+#   - **/CMakeLists.txt (to (re)build them with cmake)
+#   - scripts/make_generated_files.bat (to generate them under Windows)
+
 check scripts/generate_errors.pl library/error.c
 check scripts/generate_query_config.pl programs/test/query_config.c
 check scripts/generate_driver_wrappers.py library/psa_crypto_driver_wrappers.c
diff --git a/tests/scripts/depends.py b/tests/scripts/depends.py
index d09b732..d4fe4fd 100755
--- a/tests/scripts/depends.py
+++ b/tests/scripts/depends.py
@@ -44,12 +44,6 @@
   direct dependencies, but rather non-trivial results of other configs missing. Then
   look for any unset symbols and handle their reverse dependencies.
   Examples of EXCLUSIVE_GROUPS usage:
-  - MBEDTLS_SHA256 job turns off all hashes except SHA256, however, when investigating
-    reverse dependencies, SHA224 is found to depend on SHA256, so it is disabled,
-    and then SHA256 is found to depend on SHA224, so it is also disabled. To handle
-    this, there's a field in EXCLUSIVE_GROUPS that states that in a SHA256 test SHA224
-    should also be enabled before processing reverse dependencies:
-    'MBEDTLS_SHA256_C': ['+MBEDTLS_SHA224_C']
   - MBEDTLS_SHA512_C job turns off all hashes except SHA512. MBEDTLS_SSL_COOKIE_C
     requires either SHA256 or SHA384 to work, so it also has to be disabled.
     This is not a dependency on SHA512_C, but a result of an exclusive domain
@@ -257,17 +251,14 @@
                       'MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED'],
     'MBEDTLS_SHA256_C': ['MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED',
                          'MBEDTLS_ENTROPY_FORCE_SHA256',
-                         'MBEDTLS_SHA224_C',
                          'MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT',
                          'MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY',
                          'MBEDTLS_LMS_C',
                          'MBEDTLS_LMS_PRIVATE'],
-    'MBEDTLS_SHA512_C': ['MBEDTLS_SHA384_C',
-                         'MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT',
+    'MBEDTLS_SHA512_C': ['MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT',
                          'MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY'],
     'MBEDTLS_SHA224_C': ['MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED',
                          'MBEDTLS_ENTROPY_FORCE_SHA256',
-                         'MBEDTLS_SHA256_C',
                          'MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT',
                          'MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY'],
     'MBEDTLS_X509_RSASSA_PSS_SUPPORT': []
@@ -277,8 +268,6 @@
 # These are not necessarily dependencies, but just minimal required changes
 # if a given define is the only one enabled from an exclusive group.
 EXCLUSIVE_GROUPS = {
-    'MBEDTLS_SHA256_C': ['+MBEDTLS_SHA224_C'],
-    'MBEDTLS_SHA384_C': ['+MBEDTLS_SHA512_C'],
     'MBEDTLS_SHA512_C': ['-MBEDTLS_SSL_COOKIE_C',
                          '-MBEDTLS_SSL_PROTO_TLS1_3'],
     'MBEDTLS_ECP_DP_CURVE448_ENABLED': ['-MBEDTLS_ECDSA_C',
@@ -421,15 +410,15 @@
                                               build_and_test),
             # Elliptic curves. Run the test suites.
             'curves': ExclusiveDomain(curve_symbols, build_and_test),
-            # Hash algorithms. Exclude three groups:
-            # - Exclusive domain of MD, RIPEMD, SHA1 (obsolete);
-            # - Exclusive domain of SHA224 (tested with and depends on SHA256);
-            # - Complementary domain of SHA224 and SHA384 - tested with and depend
-            #       on SHA256 and SHA512, respectively.
+            # Hash algorithms. Excluding exclusive domains of MD, RIPEMD, SHA1,
+            # SHA224 and SHA384 because MBEDTLS_ENTROPY_C is extensively used
+            # across various modules, but it depends on either SHA256 or SHA512.
+            # As a consequence an "exclusive" test of anything other than SHA256
+            # or SHA512 with MBEDTLS_ENTROPY_C enabled is not possible.
             'hashes': DualDomain(hash_symbols, build_and_test,
                                  exclude=r'MBEDTLS_(MD|RIPEMD|SHA1_)' \
-                                          '|MBEDTLS_SHA224_'\
-                                          '|!MBEDTLS_(SHA224_|SHA384_)'),
+                                          '|MBEDTLS_SHA224_' \
+                                          '|MBEDTLS_SHA384_'),
             # Key exchange types. Only build the library and the sample
             # programs.
             'kex': ExclusiveDomain(key_exchange_symbols,
diff --git a/tests/scripts/generate_bignum_tests.py b/tests/scripts/generate_bignum_tests.py
index 0b84711..6ee6ab3 100755
--- a/tests/scripts/generate_bignum_tests.py
+++ b/tests/scripts/generate_bignum_tests.py
@@ -60,7 +60,6 @@
 from typing import List
 
 import scripts_path # pylint: disable=unused-import
-from mbedtls_dev import test_case
 from mbedtls_dev import test_data_generation
 from mbedtls_dev import bignum_common
 # Import modules containing additional test classes
diff --git a/tests/src/bignum_helpers.c b/tests/src/bignum_helpers.c
new file mode 100644
index 0000000..d6ec9bd
--- /dev/null
+++ b/tests/src/bignum_helpers.c
@@ -0,0 +1,142 @@
+/**
+ * \file bignum_helpers.c
+ *
+ * \brief   This file contains the prototypes of helper functions for
+ *          bignum-related testing.
+ */
+
+/*
+ *  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.
+ */
+
+#define MBEDTLS_ALLOW_PRIVATE_ACCESS
+#include <test/bignum_helpers.h>
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <mbedtls/bignum.h>
+#include <bignum_core.h>
+#include <bignum_mod.h>
+#include <bignum_mod_raw.h>
+
+#include <test/helpers.h>
+#include <test/macros.h>
+
+int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
+                                const char *input )
+{
+    /* Sanity check */
+    if( *pX != NULL )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    size_t hex_len = strlen( input );
+    size_t byte_len = ( hex_len + 1 ) / 2;
+    *plimbs = CHARS_TO_LIMBS( byte_len );
+
+    /* A core bignum is not allowed to be empty. Forbid it as test data,
+     * this way static analyzers have a chance of knowing we don't expect
+     * the bignum functions to support empty inputs. */
+    if( *plimbs == 0 )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+    *pX = mbedtls_calloc( *plimbs, sizeof( **pX ) );
+    if( *pX == NULL )
+        return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
+
+    unsigned char *byte_start = ( unsigned char * ) *pX;
+    if( byte_len % sizeof( mbedtls_mpi_uint ) != 0 )
+    {
+        byte_start += sizeof( mbedtls_mpi_uint ) - byte_len % sizeof( mbedtls_mpi_uint );
+    }
+    if( ( hex_len & 1 ) != 0 )
+    {
+        /* mbedtls_test_unhexify wants an even number of hex digits */
+        TEST_ASSERT( mbedtls_test_ascii2uc( *input, byte_start ) == 0 );
+        ++byte_start;
+        ++input;
+        --byte_len;
+    }
+    TEST_ASSERT( mbedtls_test_unhexify( byte_start,
+                                        byte_len,
+                                        input,
+                                        &byte_len ) == 0 );
+
+    mbedtls_mpi_core_bigendian_to_host( *pX, *plimbs );
+    return( 0 );
+
+exit:
+    mbedtls_free( *pX );
+    return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+}
+
+int mbedtls_test_read_mpi_modulus( mbedtls_mpi_mod_modulus *N,
+                                   const char *s,
+                                   mbedtls_mpi_mod_rep_selector int_rep )
+{
+    mbedtls_mpi_uint *p = NULL;
+    size_t limbs = 0;
+    if( N->limbs != 0 )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+    int ret = mbedtls_test_read_mpi_core( &p, &limbs, s );
+    if( ret != 0 )
+        return( ret );
+    ret = mbedtls_mpi_mod_modulus_setup( N, p, limbs, int_rep );
+    if( ret != 0 )
+        mbedtls_free( p );
+    return( ret );
+}
+
+void mbedtls_test_mpi_mod_modulus_free_with_limbs( mbedtls_mpi_mod_modulus *N )
+{
+    mbedtls_free( (mbedtls_mpi_uint*) N->p );
+    mbedtls_mpi_mod_modulus_free( N );
+}
+
+int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s )
+{
+    int negative = 0;
+    /* Always set the sign bit to -1 if the input has a minus sign, even for 0.
+     * This creates an invalid representation, which mbedtls_mpi_read_string()
+     * avoids but we want to be able to create that in test data. */
+    if( s[0] == '-' )
+    {
+        ++s;
+        negative = 1;
+    }
+    /* mbedtls_mpi_read_string() currently retains leading zeros.
+     * It always allocates at least one limb for the value 0. */
+    if( s[0] == 0 )
+    {
+        mbedtls_mpi_free( X );
+        return( 0 );
+    }
+    int ret = mbedtls_mpi_read_string( X, 16, s );
+    if( ret != 0 )
+        return( ret );
+    if( negative )
+    {
+        if( mbedtls_mpi_cmp_int( X, 0 ) == 0 )
+            ++mbedtls_test_case_uses_negative_0;
+        X->s = -1;
+    }
+    return( 0 );
+}
+
+#endif /* MBEDTLS_BIGNUM_C */
+
diff --git a/tests/src/helpers.c b/tests/src/helpers.c
index 7c83714..be5c465 100644
--- a/tests/src/helpers.c
+++ b/tests/src/helpers.c
@@ -48,7 +48,7 @@
 #endif /* MBEDTLS_PLATFORM_C */
 }
 
-static int ascii2uc(const char c, unsigned char *uc)
+int mbedtls_test_ascii2uc(const char c, unsigned char *uc)
 {
     if( ( c >= '0' ) && ( c <= '9' ) )
         *uc = c - '0';
@@ -207,10 +207,10 @@
 
     while( *ibuf != 0 )
     {
-        if ( ascii2uc( *(ibuf++), &uc ) != 0 )
+        if ( mbedtls_test_ascii2uc( *(ibuf++), &uc ) != 0 )
             return( -1 );
 
-        if ( ascii2uc( *(ibuf++), &uc2 ) != 0 )
+        if ( mbedtls_test_ascii2uc( *(ibuf++), &uc2 ) != 0 )
             return( -1 );
 
         *(obuf++) = ( uc << 4 ) | uc2;
@@ -350,84 +350,3 @@
     }
 }
 #endif /* MBEDTLS_TEST_HOOKS */
-
-#if defined(MBEDTLS_BIGNUM_C)
-#include "bignum_core.h"
-
-int mbedtls_test_read_mpi_core( mbedtls_mpi_uint **pX, size_t *plimbs,
-                                const char *input )
-{
-    /* Sanity check */
-    if( *pX != NULL )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
-    size_t hex_len = strlen( input );
-    size_t byte_len = ( hex_len + 1 ) / 2;
-    *plimbs = CHARS_TO_LIMBS( byte_len );
-
-    /* A core bignum is not allowed to be empty. Forbid it as test data,
-     * this way static analyzers have a chance of knowing we don't expect
-     * the bignum functions to support empty inputs. */
-    if( *plimbs == 0 )
-        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-
-    *pX = mbedtls_calloc( *plimbs, sizeof( **pX ) );
-    if( *pX == NULL )
-        return( MBEDTLS_ERR_MPI_ALLOC_FAILED );
-
-    unsigned char *byte_start = ( unsigned char * ) *pX;
-    if( byte_len % sizeof( mbedtls_mpi_uint ) != 0 )
-    {
-        byte_start += sizeof( mbedtls_mpi_uint ) - byte_len % sizeof( mbedtls_mpi_uint );
-    }
-    if( ( hex_len & 1 ) != 0 )
-    {
-        /* mbedtls_test_unhexify wants an even number of hex digits */
-        TEST_ASSERT( ascii2uc( *input, byte_start ) == 0 );
-        ++byte_start;
-        ++input;
-        --byte_len;
-    }
-    TEST_ASSERT( mbedtls_test_unhexify( byte_start,
-                                        byte_len,
-                                        input,
-                                        &byte_len ) == 0 );
-
-    mbedtls_mpi_core_bigendian_to_host( *pX, *plimbs );
-    return( 0 );
-
-exit:
-    mbedtls_free( *pX );
-    return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
-}
-
-int mbedtls_test_read_mpi( mbedtls_mpi *X, const char *s )
-{
-    int negative = 0;
-    /* Always set the sign bit to -1 if the input has a minus sign, even for 0.
-     * This creates an invalid representation, which mbedtls_mpi_read_string()
-     * avoids but we want to be able to create that in test data. */
-    if( s[0] == '-' )
-    {
-        ++s;
-        negative = 1;
-    }
-    /* mbedtls_mpi_read_string() currently retains leading zeros.
-     * It always allocates at least one limb for the value 0. */
-    if( s[0] == 0 )
-    {
-        mbedtls_mpi_free( X );
-        return( 0 );
-    }
-    int ret = mbedtls_mpi_read_string( X, 16, s );
-    if( ret != 0 )
-        return( ret );
-    if( negative )
-    {
-        if( mbedtls_mpi_cmp_int( X, 0 ) == 0 )
-            ++mbedtls_test_case_uses_negative_0;
-        X->s = -1;
-    }
-    return( 0 );
-}
-#endif
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 0c1c035..fdd3662 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -2101,6 +2101,8 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
 run_test    "TLS 1.3 opaque key: no suitable algorithm found" \
             "$P_SRV debug_level=4 force_version=tls13 auth_mode=required key_opaque=1 key_opaque_algs=rsa-decrypt,none" \
             "$P_CLI debug_level=4 key_opaque=1 key_opaque_algs=rsa-decrypt,rsa-sign-pss" \
@@ -2114,6 +2116,8 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
 run_test    "TLS 1.3 opaque key: suitable algorithm found" \
             "$P_SRV debug_level=4 force_version=tls13 auth_mode=required key_opaque=1 key_opaque_algs=rsa-decrypt,rsa-sign-pss" \
             "$P_CLI debug_level=4 key_opaque=1 key_opaque_algs=rsa-decrypt,rsa-sign-pss" \
@@ -2122,11 +2126,13 @@
             -c "key type: Opaque" \
             -s "key types: Opaque, Opaque" \
             -C "error" \
-            -S "error" \
+            -S "error"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
 run_test    "TLS 1.3 opaque key: first client sig alg not suitable" \
             "$P_SRV debug_level=4 force_version=tls13 auth_mode=required key_opaque=1 key_opaque_algs=rsa-sign-pss-sha512,none" \
             "$P_CLI debug_level=4 sig_algs=rsa_pss_rsae_sha256,rsa_pss_rsae_sha512" \
@@ -2141,6 +2147,8 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
 requires_config_enabled MBEDTLS_RSA_C
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
 run_test    "TLS 1.3 opaque key: 2 keys on server, suitable algorithm found" \
             "$P_SRV debug_level=4 force_version=tls13 auth_mode=required key_opaque=1 key_opaque_algs2=ecdsa-sign,none key_opaque_algs=rsa-decrypt,rsa-sign-pss" \
             "$P_CLI debug_level=4 key_opaque=1 key_opaque_algs=rsa-decrypt,rsa-sign-pss" \
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index fe33f9b..8249564 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -5,6 +5,7 @@
 #include <test/helpers.h>
 #include <test/macros.h>
 #include <test/random.h>
+#include <test/bignum_helpers.h>
 #include <test/psa_crypto_helpers.h>
 
 #include <stdlib.h>
diff --git a/tests/suites/test_suite_bignum_mod.function b/tests/suites/test_suite_bignum_mod.function
index 79f5134..8ab8ccf 100644
--- a/tests/suites/test_suite_bignum_mod.function
+++ b/tests/suites/test_suite_bignum_mod.function
@@ -2,6 +2,7 @@
 #include "mbedtls/bignum.h"
 #include "mbedtls/entropy.h"
 #include "bignum_mod.h"
+#include "bignum_mod_raw.h"
 #include "constant_time_internal.h"
 #include "test/constant_flow.h"
 
@@ -102,6 +103,145 @@
 
 /* BEGIN MERGE SLOT 2 */
 
+/* BEGIN_CASE */
+void mpi_mod_mul( char * input_A,
+                  char * input_B,
+                  char * input_N,
+                  char * result )
+{
+    mbedtls_mpi_uint *X = NULL;
+
+    mbedtls_mpi_mod_residue rA = { NULL, 0 };
+    mbedtls_mpi_mod_residue rB = { NULL, 0 };
+    mbedtls_mpi_mod_residue rR = { NULL, 0 };
+    mbedtls_mpi_mod_residue rX = { NULL, 0 };
+
+    mbedtls_mpi_mod_modulus m;
+    mbedtls_mpi_mod_modulus_init( &m );
+
+    TEST_EQUAL( test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ),
+                0 );
+
+    TEST_EQUAL( test_read_residue( &rA, &m, input_A, 0 ), 0 );
+    TEST_EQUAL( test_read_residue( &rB, &m, input_B, 0 ), 0 );
+    TEST_EQUAL( test_read_residue( &rR, &m, result,  0 ), 0 );
+
+    const size_t limbs = m.limbs;
+    const size_t bytes = limbs * sizeof( mbedtls_mpi_uint );
+
+    TEST_EQUAL( rA.limbs, limbs );
+    TEST_EQUAL( rB.limbs, limbs );
+    TEST_EQUAL( rR.limbs, limbs );
+
+    ASSERT_ALLOC( X, limbs );
+
+    TEST_EQUAL( mbedtls_mpi_mod_residue_setup( &rX, &m, X, limbs ), 0 );
+
+    TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rB, &m ), 0 );
+    ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+    /* alias X to A */
+    memcpy( rX.p, rA.p, bytes );
+    TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rX, &rB, &m ), 0 );
+    ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+    /* alias X to B */
+    memcpy( rX.p, rB.p, bytes );
+    TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rX, &m ), 0);
+    ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+    /* A == B: alias A and B */
+    if( memcmp( rA.p, rB.p, bytes ) == 0 )
+    {
+        TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rA, &m ), 0 );
+        ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+        /* X, A, B all aliased together */
+        memcpy( rX.p, rA.p, bytes );
+        TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rX, &rX, &m ), 0 );
+        ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+    }
+
+    /* A != B: test B * A */
+    else
+    {
+        TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rB, &rA, &m ), 0 );
+        ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+        /* B * A: alias X to A */
+        memcpy( rX.p, rA.p, bytes );
+        TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rB, &rX, &m ), 0 );
+        ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+
+        /* B + A: alias X to B */
+        memcpy( rX.p, rB.p, bytes );
+        TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rX, &rA, &m ), 0 );
+        ASSERT_COMPARE( rX.p, bytes, rR.p, bytes );
+    }
+
+exit:
+    mbedtls_free( rA.p );
+    mbedtls_free( rB.p );
+    mbedtls_free( rR.p );
+    mbedtls_free( X );
+    mbedtls_free( (mbedtls_mpi_uint *) m.p );
+
+    mbedtls_mpi_mod_modulus_free( &m );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_mul_neg( char * input_A,
+                      char * input_B,
+                      char * input_N,
+                      char * result,
+                      int exp_ret )
+{
+    mbedtls_mpi_uint *X = NULL;
+
+    mbedtls_mpi_mod_residue rA = { NULL, 0 };
+    mbedtls_mpi_mod_residue rB = { NULL, 0 };
+    mbedtls_mpi_mod_residue rR = { NULL, 0 };
+    mbedtls_mpi_mod_residue rX = { NULL, 0 };
+
+    mbedtls_mpi_mod_modulus m;
+    mbedtls_mpi_mod_modulus_init( &m );
+
+    mbedtls_mpi_mod_modulus fake_m;
+    mbedtls_mpi_mod_modulus_init( &fake_m );
+
+    TEST_EQUAL( test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ),
+                0 );
+
+    TEST_EQUAL( test_read_residue( &rA, &m, input_A, 1 ), 0 );
+    TEST_EQUAL( test_read_residue( &rB, &m, input_B, 1 ), 0 );
+    TEST_EQUAL( test_read_residue( &rR, &m, result,  1 ), 0 );
+
+    const size_t limbs = m.limbs;
+
+    ASSERT_ALLOC( X, limbs );
+
+    TEST_EQUAL( mbedtls_mpi_mod_residue_setup( &rX, &m, X, limbs ), 0 );
+    rX.limbs = rR.limbs;
+
+    TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rB, &m ), exp_ret );
+
+    /* Check when m is not initialized */
+    TEST_EQUAL( mbedtls_mpi_mod_mul( &rX, &rA, &rB, &fake_m ),
+                MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
+
+exit:
+    mbedtls_free( rA.p );
+    mbedtls_free( rB.p );
+    mbedtls_free( rR.p );
+    mbedtls_free( X );
+    mbedtls_free( (mbedtls_mpi_uint *) m.p );
+
+    mbedtls_mpi_mod_modulus_free( &m );
+    mbedtls_mpi_mod_modulus_free( &fake_m );
+}
+/* END_CASE */
+
 /* END MERGE SLOT 2 */
 
 /* BEGIN MERGE SLOT 3 */
diff --git a/tests/suites/test_suite_bignum_mod.misc.data b/tests/suites/test_suite_bignum_mod.misc.data
index 6240e21..e369211 100644
--- a/tests/suites/test_suite_bignum_mod.misc.data
+++ b/tests/suites/test_suite_bignum_mod.misc.data
@@ -12,7 +12,14 @@
 # END MERGE SLOT 1
 
 # BEGIN MERGE SLOT 2
+Test mpi_mod_mul #1 N->limbs != A->limbs
+mpi_mod_mul_neg:"1":"00000000000000000000000000000000":"f0000000000000000000000000000000":"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
+Test mpi_mod_mul #2 N->limbs != B->limbs
+mpi_mod_mul_neg:"1234567890abcdef1234567890abcdef":"0":"f0000000000000000000000000000000":"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+Test mpi_mod_mul #3 N->limbs != X->limbs
+mpi_mod_mul_neg:"1234567890abcdef1234567890abcdef":"00000000000000000000000000000000":"f0000000000000000000000000000000":"0":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 # END MERGE SLOT 2
 
 # BEGIN MERGE SLOT 3
diff --git a/tests/suites/test_suite_bignum_mod_raw.function b/tests/suites/test_suite_bignum_mod_raw.function
index 461a18e..4a658e1 100644
--- a/tests/suites/test_suite_bignum_mod_raw.function
+++ b/tests/suites/test_suite_bignum_mod_raw.function
@@ -619,7 +619,59 @@
 /* END MERGE SLOT 5 */
 
 /* BEGIN MERGE SLOT 6 */
+/* BEGIN_CASE */
+void mpi_mod_raw_canonical_to_modulus_rep( const char *input_N, int rep,
+                                           const char *input_A,
+                                           const char *input_X )
+{
+    mbedtls_mpi_mod_modulus N;
+    mbedtls_mpi_mod_modulus_init( &N );
+    mbedtls_mpi_uint *A = NULL;
+    size_t A_limbs = 0;;
+    mbedtls_mpi_uint *X = NULL;
+    size_t X_limbs = 0;
 
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_modulus( &N, input_N, rep ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &X_limbs, input_X ) );
+
+    TEST_EQUAL( 0, mbedtls_mpi_mod_raw_canonical_to_modulus_rep( A, &N ) );
+    ASSERT_COMPARE( A, A_limbs * sizeof( mbedtls_mpi_uint ),
+                    X, X_limbs * sizeof( mbedtls_mpi_uint ) );
+
+exit:
+    mbedtls_test_mpi_mod_modulus_free_with_limbs( &N );
+    mbedtls_free( A );
+    mbedtls_free( X );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_raw_modulus_to_canonical_rep( const char *input_N, int rep,
+                                           const char *input_A,
+                                           const char *input_X )
+{
+    mbedtls_mpi_mod_modulus N;
+    mbedtls_mpi_mod_modulus_init( &N );
+    mbedtls_mpi_uint *A = NULL;
+    size_t A_limbs = 0;
+    mbedtls_mpi_uint *X = NULL;
+    size_t X_limbs = 0;
+
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_modulus( &N, input_N, rep ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &X_limbs, input_X ) );
+
+    TEST_EQUAL( 0, mbedtls_mpi_mod_raw_modulus_to_canonical_rep( A, &N ) );
+    ASSERT_COMPARE( A, A_limbs * sizeof( mbedtls_mpi_uint ),
+                    X, X_limbs * sizeof( mbedtls_mpi_uint ) );
+
+exit:
+    mbedtls_test_mpi_mod_modulus_free_with_limbs( &N );
+    mbedtls_free( A );
+    mbedtls_free( X );
+}
+/* END_CASE */
 /* END MERGE SLOT 6 */
 
 /* BEGIN MERGE SLOT 7 */
diff --git a/tests/suites/test_suite_bignum_random.data b/tests/suites/test_suite_bignum_random.data
index fe29053..ee5e397 100644
--- a/tests/suites/test_suite_bignum_random.data
+++ b/tests/suites/test_suite_bignum_random.data
@@ -17,31 +17,55 @@
 mpi_core_random_basic:0x40000000:"0200000000000000000000000000000000":0
 
 # Use the same data values for mpi_core_random_basic->NOT_ACCEPTABLE
-# and for mpi_random_values where we want to return NOT_ACCEPTABLE but
-# this isn't checked at runtime.
-MPI core random basic: 2^28-1..2^28 (NOT_ACCEPTABLE)
-mpi_core_random_basic:0x0fffffff:"10000000":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+# and for mpi_XXX_random_values where we want to return NOT_ACCEPTABLE
+# but this isn't checked at runtime.
+MPI core random basic: 2^28-1..2^28+1 (NOT_ACCEPTABLE)
+mpi_core_random_basic:0x0fffffff:"10000001":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
 
-MPI random legacy=core: 2^28-1..2^28 (NOT_ACCEPTABLE)
-mpi_random_values:0x0fffffff:"10000000"
+MPI random legacy=core: 2^28-1..2^28+1 (NOT_ACCEPTABLE)
+mpi_legacy_random_values:0x0fffffff:"10000001"
 
-MPI core random basic: 2^29-1..2^29 (NOT_ACCEPTABLE)
-mpi_core_random_basic:0x1fffffff:"20000000":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+MPI random mod=core: 2^28-1..2^28+1 (NOT_ACCEPTABLE) (Mont)
+mpi_mod_random_values:0x0fffffff:"10000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
 
-MPI random legacy=core: 2^29-1..2^29 (NOT_ACCEPTABLE)
-mpi_random_values:0x1fffffff:"20000000"
+MPI random mod=core: 2^28-1..2^28+1 (NOT_ACCEPTABLE) (canon)
+mpi_mod_random_values:0x0fffffff:"10000001":MBEDTLS_MPI_MOD_REP_OPT_RED
 
-MPI core random basic: 2^30-1..2^30 (NOT_ACCEPTABLE)
-mpi_core_random_basic:0x3fffffff:"40000000":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+MPI core random basic: 2^29-1..2^29+1 (NOT_ACCEPTABLE)
+mpi_core_random_basic:0x1fffffff:"20000001":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
 
-MPI random legacy=core: 2^30-1..2^30 (NOT_ACCEPTABLE)
-mpi_random_values:0x3fffffff:"40000000"
+MPI random legacy=core: 2^29-1..2^29+1 (NOT_ACCEPTABLE)
+mpi_legacy_random_values:0x1fffffff:"20000001"
 
-MPI core random basic: 2^31-1..2^31 (NOT_ACCEPTABLE)
-mpi_core_random_basic:0x7fffffff:"80000000":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+MPI random mod=core: 2^29-1..2^29+1 (NOT_ACCEPTABLE) (Mont)
+mpi_mod_random_values:0x1fffffff:"20000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
 
-MPI random legacy=core: 2^31-1..2^31 (NOT_ACCEPTABLE)
-mpi_random_values:0x7fffffff:"80000000"
+MPI random mod=core: 2^29-1..2^29+1 (NOT_ACCEPTABLE) (canon)
+mpi_mod_random_values:0x1fffffff:"20000001":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI core random basic: 2^30-1..2^30+1 (NOT_ACCEPTABLE)
+mpi_core_random_basic:0x3fffffff:"40000001":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+
+MPI random legacy=core: 2^30-1..2^30+1 (NOT_ACCEPTABLE)
+mpi_legacy_random_values:0x3fffffff:"40000001"
+
+MPI random mod=core: 2^30-1..2^30+1 (NOT_ACCEPTABLE) (Mont)
+mpi_mod_random_values:0x3fffffff:"40000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^30-1..2^30+1 (NOT_ACCEPTABLE) (canon)
+mpi_mod_random_values:0x3fffffff:"40000001":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI core random basic: 2^31-1..2^31+1 (NOT_ACCEPTABLE)
+mpi_core_random_basic:0x7fffffff:"80000001":MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
+
+MPI random legacy=core: 2^31-1..2^31+1 (NOT_ACCEPTABLE)
+mpi_legacy_random_values:0x7fffffff:"80000001"
+
+MPI random mod=core: 2^31-1..2^31+1 (NOT_ACCEPTABLE) (Mont)
+mpi_mod_random_values:0x7fffffff:"80000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^31-1..2^31+1 (NOT_ACCEPTABLE) (canon)
+mpi_mod_random_values:0x7fffffff:"80000001":MBEDTLS_MPI_MOD_REP_OPT_RED
 
 MPI random in range: 1..2
 mpi_random_many:1:"02":1000
@@ -214,22 +238,103 @@
 mpi_random_fail:2:"000000000000000001":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
 MPI random legacy=core: 0..1
-mpi_random_values:0:"01"
+mpi_legacy_random_values:0:"01"
 
 MPI random legacy=core: 0..2
-mpi_random_values:0:"02"
+mpi_legacy_random_values:0:"02"
 
 MPI random legacy=core: 1..2
-mpi_random_values:1:"02"
+mpi_legacy_random_values:1:"02"
 
 MPI random legacy=core: 2^30..2^31
-mpi_random_values:0x40000000:"80000000"
+mpi_legacy_random_values:0x40000000:"80000000"
 
 MPI random legacy=core: 2^31-1..2^32-1
-mpi_random_values:0x7fffffff:"ffffffff"
+mpi_legacy_random_values:0x7fffffff:"ffffffff"
 
 MPI random legacy=core: 0..2^256
-mpi_random_values:0:"010000000000000000000000000000000000000000000000000000000000000000"
+mpi_legacy_random_values:0:"010000000000000000000000000000000000000000000000000000000000000000"
 
 MPI random legacy=core: 0..2^256+1
-mpi_random_values:0:"010000000000000000000000000000000000000000000000000000000000000001"
+mpi_legacy_random_values:0:"010000000000000000000000000000000000000000000000000000000000000001"
+
+MPI random mod=core: 0..1 (Mont)
+mpi_mod_random_values:0:"01":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 0..1 (canon)
+mpi_mod_random_values:0:"01":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 0..3 (Mont)
+mpi_mod_random_values:0:"03":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 0..3 (canon)
+mpi_mod_random_values:0:"03":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 1..3 (Mont)
+mpi_mod_random_values:1:"03":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 1..3 (canon)
+mpi_mod_random_values:1:"03":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 2^30..2^31-1 (Mont)
+mpi_mod_random_values:0x40000000:"7fffffff":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^30..2^31-1 (canon)
+mpi_mod_random_values:0x40000000:"7fffffff":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 2^31-1..2^32-1 (Mont)
+mpi_mod_random_values:0x7fffffff:"ffffffff":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 2^31-1..2^32-1 (canon)
+mpi_mod_random_values:0x7fffffff:"ffffffff":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod=core: 0..2^256+1 (Mont)
+mpi_mod_random_values:0:"010000000000000000000000000000000000000000000000000000000000000001":MBEDTLS_MPI_MOD_REP_MONTGOMERY
+
+MPI random mod=core: 0..2^256+1 (canon)
+mpi_mod_random_values:0:"010000000000000000000000000000000000000000000000000000000000000001":MBEDTLS_MPI_MOD_REP_OPT_RED
+
+MPI random mod validation: 1 limb, good, 0..1
+mpi_mod_random_validation:0:"1":0:0
+
+MPI random mod validation: 1 limb, good, 1..3
+mpi_mod_random_validation:1:"3":0:0
+
+MPI random mod validation: 1 limb, good, 2..3
+mpi_mod_random_validation:2:"3":0:0
+
+MPI random mod validation: 1 limb, good, 3..5
+mpi_mod_random_validation:3:"5":0:0
+
+MPI random mod validation: 1 limb, good, 4..5
+mpi_mod_random_validation:4:"5":0:0
+
+MPI random mod validation: 1 limb, good, 5..7
+mpi_mod_random_validation:5:"7":0:0
+
+MPI random mod validation: 1 limb, good, 6..7
+mpi_mod_random_validation:6:"7":0:0
+
+MPI random mod validation: 1 limb, good, 0..0x123
+mpi_mod_random_validation:0:"123":0:0
+
+MPI random mod validation: 2+ limbs, good
+mpi_mod_random_validation:0:"01234567890123456789":0:0
+
+MPI random mod validation: 1 limb, output null
+mpi_mod_random_validation:0:"123":-1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: 1 limb, output too large
+mpi_mod_random_validation:0:"123":1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: 2+ limbs, output too small
+mpi_mod_random_validation:0:"01234567890123456789":-1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: 2+ limbs, output too large
+mpi_mod_random_validation:0:"01234567890123456789":1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: min == upper bound
+mpi_mod_random_validation:0x123:"123":-1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+MPI random mod validation: min > upper bound
+mpi_mod_random_validation:0x124:"123":-1:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_bignum_random.function b/tests/suites/test_suite_bignum_random.function
index 184de5a..4709148 100644
--- a/tests/suites/test_suite_bignum_random.function
+++ b/tests/suites/test_suite_bignum_random.function
@@ -3,11 +3,44 @@
  * functions. Due to the complexity of how these functions are tested,
  * we test all the layers in a single test suite, unlike the way other
  * functions are tested with each layer in its own test suite.
+ *
+ * Test strategy
+ * =============
+ *
+ * There are three main goals for testing random() functions:
+ * - Parameter validation.
+ * - Correctness of outputs (well-formed, in range).
+ * - Distribution of outputs.
+ *
+ * We test parameter validation in a standard way, with unit tests with
+ * positive and negative cases:
+ * - mbedtls_mpi_core_random(): negative cases for mpi_core_random_basic.
+ * - mbedtls_mpi_mod_raw_random(),  mbedtls_mpi_mod_random(): negative
+ *   cases for mpi_mod_random_validation.
+ * - mbedtls_mpi_random(): mpi_random_fail.
+ *
+ * We test the correctness of outputs in positive tests:
+ * - mbedtls_mpi_core_random(): positive cases for mpi_core_random_basic,
+ *   and mpi_random_many.
+ * - mbedtls_mpi_mod_raw_random(), mbedtls_mpi_mod_random(): tested indirectly
+ *   via mpi_mod_random_values.
+ * - mbedtls_mpi_random(): mpi_random_sizes, plus indirectly via
+ *   mpi_random_values.
+ *
+ * We test the distribution of outputs only for mbedtls_mpi_core_random(),
+ * in mpi_random_many, which runs the function multiple times. This also
+ * helps in validating the output range, through test cases with a small
+ * range where any output out of range would be very likely to lead to a
+ * test failure. For the other functions, we validate the distribution
+ * indirectly by testing that these functions consume the random generator
+ * in the same way as mbedtls_mpi_core_random(). This is done in
+ * mpi_mod_random_values and mpi_legacy_random_values.
  */
 
 #include "mbedtls/bignum.h"
 #include "mbedtls/entropy.h"
 #include "bignum_core.h"
+#include "bignum_mod_raw.h"
 #include "constant_time_internal.h"
 
 /* This test suite only manipulates non-negative bignums. */
@@ -110,7 +143,7 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void mpi_random_values( int min, char *max_hex )
+void mpi_legacy_random_values( int min, char *max_hex )
 {
     /* Same RNG as in mpi_core_random_basic */
     mbedtls_test_rnd_pseudo_info rnd_core = rnd_pseudo_seed;
@@ -159,6 +192,77 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void mpi_mod_random_values( int min, char *max_hex, int rep )
+{
+    /* Same RNG as in mpi_core_random_basic */
+    mbedtls_test_rnd_pseudo_info rnd_core = rnd_pseudo_seed;
+    mbedtls_test_rnd_pseudo_info rnd_mod_raw;
+    memcpy( &rnd_mod_raw, &rnd_core, sizeof( rnd_core ) );
+    mbedtls_test_rnd_pseudo_info rnd_mod;
+    memcpy( &rnd_mod, &rnd_core, sizeof( rnd_core ) );
+    mbedtls_mpi_uint *R_core = NULL;
+    mbedtls_mpi_uint *R_mod_raw = NULL;
+    mbedtls_mpi_uint *R_mod_digits = NULL;
+    mbedtls_mpi_mod_residue R_mod;
+    mbedtls_mpi_mod_modulus N;
+    mbedtls_mpi_mod_modulus_init( &N );
+
+    TEST_EQUAL( mbedtls_test_read_mpi_modulus( &N, max_hex, rep ), 0 );
+    ASSERT_ALLOC( R_core, N.limbs );
+    ASSERT_ALLOC( R_mod_raw, N.limbs );
+    ASSERT_ALLOC( R_mod_digits, N.limbs );
+    TEST_EQUAL( mbedtls_mpi_mod_residue_setup( &R_mod, &N,
+                                               R_mod_digits, N.limbs ),
+                0 );
+
+    /* Call the core and mod random() functions with the same random stream. */
+    int core_ret = mbedtls_mpi_core_random( R_core,
+                                            min, N.p, N.limbs,
+                                            mbedtls_test_rnd_pseudo_rand,
+                                            &rnd_core );
+    int mod_raw_ret = mbedtls_mpi_mod_raw_random( R_mod_raw,
+                                                  min, &N,
+                                                  mbedtls_test_rnd_pseudo_rand,
+                                                  &rnd_mod_raw );
+    int mod_ret = mbedtls_mpi_mod_random( &R_mod,
+                                          min, &N,
+                                          mbedtls_test_rnd_pseudo_rand,
+                                          &rnd_mod );
+
+    /* They must return the same status, and, on success, output the
+     * same number, with the same limb count. */
+    TEST_EQUAL( core_ret, mod_raw_ret );
+    TEST_EQUAL( core_ret, mod_ret );
+    if( core_ret == 0 )
+    {
+        TEST_EQUAL( mbedtls_mpi_mod_raw_modulus_to_canonical_rep( R_mod_raw, &N ),
+                    0 );
+        ASSERT_COMPARE( R_core, N.limbs * ciL,
+                        R_mod_raw, N.limbs * ciL );
+        TEST_EQUAL( mbedtls_mpi_mod_raw_modulus_to_canonical_rep( R_mod_digits, &N ),
+                    0 );
+        ASSERT_COMPARE( R_core, N.limbs * ciL,
+                        R_mod_digits, N.limbs * ciL );
+    }
+
+    /* Also check that they have consumed the RNG in the same way. */
+    /* This may theoretically fail on rare platforms with padding in
+     * the structure! If this is a problem in practice, change to a
+     * field-by-field comparison. */
+    ASSERT_COMPARE( &rnd_core, sizeof( rnd_core ),
+                    &rnd_mod_raw, sizeof( rnd_mod_raw ) );
+    ASSERT_COMPARE( &rnd_core, sizeof( rnd_core ),
+                    &rnd_mod, sizeof( rnd_mod ) );
+
+exit:
+    mbedtls_test_mpi_mod_modulus_free_with_limbs( &N );
+    mbedtls_free( R_core );
+    mbedtls_free( R_mod_raw );
+    mbedtls_free( R_mod_digits );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void mpi_random_many( int min, char *bound_hex, int iterations )
 {
     /* Generate numbers in the range 1..bound-1. Do it iterations times.
@@ -312,6 +416,64 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void mpi_mod_random_validation( int min, char *bound_hex,
+                                int result_limbs_delta,
+                                int expected_ret )
+{
+    mbedtls_mpi_uint *result_digits = NULL;
+    mbedtls_mpi_mod_modulus N;
+    mbedtls_mpi_mod_modulus_init( &N );
+
+    TEST_EQUAL( mbedtls_test_read_mpi_modulus( &N, bound_hex,
+                                               MBEDTLS_MPI_MOD_REP_OPT_RED ),
+                0 );
+    size_t result_limbs = N.limbs + result_limbs_delta;
+    ASSERT_ALLOC( result_digits, result_limbs );
+    /* Build a reside that might not match the modulus, to test that
+     * the library function rejects that as expected. */
+    mbedtls_mpi_mod_residue result = {result_digits, result_limbs};
+
+    TEST_EQUAL( mbedtls_mpi_mod_random( &result, min, &N,
+                                        mbedtls_test_rnd_std_rand, NULL ),
+                expected_ret );
+    if( expected_ret == 0 )
+    {
+        /* Success should only be expected when the result has the same
+         * size as the modulus, otherwise it's a mistake in the test data. */
+        TEST_EQUAL( result_limbs, N.limbs );
+        /* Sanity check: check that the result is in range */
+        TEST_EQUAL( mbedtls_mpi_core_lt_ct( result_digits, N.p, N.limbs ),
+                    1 );
+        /* Check result >= min (changes result) */
+        TEST_EQUAL( mbedtls_mpi_core_sub_int( result_digits, result_digits, min,
+                                              result_limbs ),
+                    0 );
+    }
+
+    /* When the result has the right number of limbs, also test mod_raw
+     * (for which this is an unchecked precondition). */
+    if( result_limbs_delta == 0 )
+    {
+        TEST_EQUAL( mbedtls_mpi_mod_raw_random( result_digits, min, &N,
+                                                mbedtls_test_rnd_std_rand, NULL ),
+                    expected_ret );
+        if( expected_ret == 0 )
+        {
+            TEST_EQUAL( mbedtls_mpi_core_lt_ct( result_digits, N.p, N.limbs ),
+                        1 );
+            TEST_EQUAL( mbedtls_mpi_core_sub_int( result_digits, result.p, min,
+                                                  result_limbs ),
+                        0 );
+        }
+    }
+
+exit:
+    mbedtls_test_mpi_mod_modulus_free_with_limbs( &N );
+    mbedtls_free( result_digits );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void mpi_random_fail( int min, data_t *bound_bytes, int expected_ret )
 {
     mbedtls_mpi upper_bound;
diff --git a/tests/suites/test_suite_ecjpake.data b/tests/suites/test_suite_ecjpake.data
index 73808c9..c2ec782 100644
--- a/tests/suites/test_suite_ecjpake.data
+++ b/tests/suites/test_suite_ecjpake.data
@@ -35,7 +35,7 @@
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"0100":MBEDTLS_ERR_ECP_INVALID_KEY
 
 ECJPAKE round one: KKP1: unknown first point format
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41057ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41057ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP1: nothing after first point
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -50,7 +50,7 @@
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b0104":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP1: unknown second point format
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410509f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410509f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP1: nothing after second point
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"41047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -83,7 +83,7 @@
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb120100":MBEDTLS_ERR_ECP_INVALID_KEY
 
 ECJPAKE round one: KKP2: unknown first point format
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241057ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241057ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP2: nothing after first point
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -98,7 +98,7 @@
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b0104":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP2: unknown second point format
-read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410509f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410509f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round one: KKP2: nothing after second point
 read_round_one:MBEDTLS_ECJPAKE_CLIENT:"4104190a07700ffa4be6ae1d79ee0f06aeb544cd5addaabedf70f8623321332c54f355f0fbfec783ed359e5d0bf7377a0fc4ea7ace473c9c112b41ccd41ac56a56124104360a1cea33fce641156458e0a4eac219e96831e6aebc88b3f3752f93a0281d1bf1fb106051db9694a8d6e862a5ef1324a3d9e27894f1ee4f7c59199965a8dd4a2091847d2d22df3ee55faa2a3fb33fd2d1e055a07a7c61ecfb8d80ec00c2c9eb1241047ea6e3a4487037a9e0dbd79262b2cc273e779930fc18409ac5361c5fe669d702e147790aeb4ce7fd6575ab0f6c7fd1c335939aa863ba37ec91b7e32bb013bb2b410409f85b3d20ebd7885ce464c08d056d6428fe4dd9287aa365f131f4360ff386d846898bc4b41583c2a5197f65d78742746c12a5ec0a4ffe2f270a750a1d8fb516":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -149,7 +149,7 @@
 read_round_two_cli:"0300170100":MBEDTLS_ERR_ECP_INVALID_KEY
 
 ECJPAKE round two client: unknown first point format
-read_round_two_cli:"03001741050fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a6":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_two_cli:"03001741050fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a6":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two client: nothing after first point
 read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a6":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -164,7 +164,7 @@
 read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a60104":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two client: unknown second point format
-read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641055516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c8":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641055516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c8":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two client: nothing after second point
 read_round_two_cli:"03001741040fb22b1d5d1123e0ef9feb9d8a2e590a1f4d7ced2c2b06586e8f2a16d4eb2fda4328a20b07d8fd667654ca18c54e32a333a0845451e926ee8804fd7af0aaa7a641045516ea3e54a0d5d8b2ce786b38d383370029a5dbe4459c9dd601b408a24ae6465c8ac905b9eb03b5d3691c139ef83f1cd4200f6c9cd4ec392218a59ed243d3c8":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -203,7 +203,7 @@
 read_round_two_srv:"0100":MBEDTLS_ERR_ECP_INVALID_KEY
 
 ECJPAKE round two server: unknown first point format
-read_round_two_srv:"410569d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_two_srv:"410569d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two server: nothing after first point
 read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
@@ -218,7 +218,7 @@
 read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee0104":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two server: unknown second point format
-read_round_two_srv:"410569d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+read_round_two_srv:"410569d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECJPAKE round two server: nothing after second point
 read_round_two_srv:"410469d54ee85e90ce3f1246742de507e939e81d1dc1c5cb988b58c310c9fdd9524d93720b45541c83ee8841191da7ced86e3312d43623c1d63e74989aba4affd1ee4104077e8c31e20e6bedb760c13593e69f15be85c27d68cd09ccb8c4183608917c5c3d409fac39fefee82f7292d36f0d23e055913f45a52b85dd8a2052e9e129bb4d":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index 4c0ed1c..9311200 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -227,19 +227,51 @@
 
 ECP read binary #2 (zero, invalid first byte)
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
-ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"01":"01":"01":"00":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"01":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
 ECP read binary #3 (zero, OK)
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"00":"01":"01":"00":0
 
-ECP read binary #4 (non-zero, invalid ilen)
+ECP read binary #4 (non-zero, invalid ilen, too short)
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"04001122":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
 
+ECP read binary #4a (non-zero, invalid ilen, too short)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"03001122":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #4b (non-zero, invalid ilen, too short)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"02001122":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #4c (non-zero, invalid ilen, too long)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"040011223344556677889900112233445566778899001122334455":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #4d (non-zero, invalid ilen, too long)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"030011223344556677889900112233445566778899001122334455":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #4e (non-zero, invalid ilen, too long)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"020011223344556677889900112233445566778899001122334455":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
 ECP read binary #5 (non-zero, invalid first byte)
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
-ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc99336ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #5a (non-zero, compressed format, invalid first byte)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0548d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
+
+ECP read binary #5b (non-zero, compressed format, parity 0, OK)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0248d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"6ceed4d7cba482e288669ee1b6415626d6f34d28501e060c":"01":0
+
+ECP read binary #5c (non-zero, compressed format, parity 1, OK)
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP192R1:"0348d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"48d8082a3a1e3112bc03a8ef2f6d40d0a77a6f8e00cc9933":"93112b28345b7d1d7799611e49bea9d8290cb2d7afe1f9f3":"01":0
 
 ECP read binary #6 (non-zero, OK)
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
@@ -285,6 +317,14 @@
 depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
 ecp_read_binary:MBEDTLS_ECP_DP_CURVE448:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff":"0":"1":0
 
+ECP read binary #17 (non-zero, compressed format, p != 3 mod 4, secp224r1)
+depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP224R1:"0200000000000000000000000000000000000000000000000000000000":"01":"01":"01":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+
+ECP read binary #17a (non-zero, compressed format, p != 3 mod 4, secp224k1)
+depends_on:MBEDTLS_ECP_DP_SECP224K1_ENABLED
+ecp_read_binary:MBEDTLS_ECP_DP_SECP224K1:"0200000000000000000000000000000000000000000000000000000000":"01":"01":"01":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
+
 ECP tls read point #1 (zero, invalid length byte)
 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
 mbedtls_ecp_tls_read_point:MBEDTLS_ECP_DP_SECP192R1:"0200":"01":"01":"00":MBEDTLS_ERR_ECP_BAD_INPUT_DATA
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 2971c57..96b9f40 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -642,6 +642,19 @@
         {
             TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P.Y, &Y ) == 0 );
             TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P.Z, &Z ) == 0 );
+
+            if( buf->x[0] == 0x04 &&
+                /* (reading compressed format supported only for
+                 *  Short Weierstrass curves with prime p where p = 3 mod 4) */
+                id != MBEDTLS_ECP_DP_SECP224R1 &&
+                id != MBEDTLS_ECP_DP_SECP224K1 )
+            {
+                /* re-encode in compressed format and test read again */
+                mbedtls_mpi_free( &P.Y );
+                buf->x[0] = 0x02 + mbedtls_mpi_get_bit( &Y, 0 );
+                TEST_ASSERT( mbedtls_ecp_point_read_binary( &grp, &P, buf->x, buf->len/2+1 ) == 0 );
+                TEST_ASSERT( mbedtls_mpi_cmp_mpi( &P.Y, &Y ) == 0 );
+            }
         }
     }
 
@@ -703,8 +716,10 @@
     memset( buf, 0x00, sizeof( buf ) ); vbuf = buf;
     TEST_ASSERT( mbedtls_ecp_tls_write_point( &grp, &grp.G,
                     MBEDTLS_ECP_PF_COMPRESSED, &olen, buf, 256 ) == 0 );
-    TEST_ASSERT( mbedtls_ecp_tls_read_point( &grp, &pt, &vbuf, olen )
-                 == MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+    TEST_ASSERT( mbedtls_ecp_tls_read_point( &grp, &pt, &vbuf, olen ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &grp.G.X, &pt.X ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &grp.G.Y, &pt.Y ) == 0 );
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &grp.G.Z, &pt.Z ) == 0 );
     TEST_ASSERT( vbuf == buf + olen );
 
     memset( buf, 0x00, sizeof( buf ) ); vbuf = buf;
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index bd5d31e..d796f6f 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -456,10 +456,14 @@
 depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA
 pk_rsa_verify_ext_test_vec:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":MBEDTLS_MD_SHA256:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA256:94:128:0
 
-Verify ext RSA #5 (PKCS1 v2.1, wrong salt_len)
-depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA
+Verify ext RSA #5a (PKCS1 v2.1, wrong salt_len) !USE_PSA
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA:!MBEDTLS_USE_PSA_CRYPTO
 pk_rsa_verify_ext_test_vec:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":MBEDTLS_MD_SHA256:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA256:32:128:MBEDTLS_ERR_RSA_INVALID_PADDING
 
+Verify ext RSA #5b (PKCS1 v2.1, wrong salt_len) USE_PSA
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA:MBEDTLS_USE_PSA_CRYPTO
+pk_rsa_verify_ext_test_vec:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":MBEDTLS_MD_SHA256:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA256:32:128:0
+
 Verify ext RSA #6 (PKCS1 v2.1, MGF1 alg != MSG hash alg)
 depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA
 pk_rsa_verify_ext_test_vec:"c0719e9a8d5d838d861dc6f675c899d2b309a3a65bb9fe6b11e5afcbf9a2c0b1":MBEDTLS_MD_NONE:1024:"00dd118a9f99bab068ca2aea3b6a6d5997ed4ec954e40deecea07da01eaae80ec2bb1340db8a128e891324a5c5f5fad8f590d7c8cacbc5fe931dafda1223735279461abaa0572b761631b3a8afe7389b088b63993a0a25ee45d21858bab9931aedd4589a631b37fcf714089f856549f359326dd1e0e86dde52ed66b4a90bda4095":"010001":"0d2bdb0456a3d651d5bd48a4204493898f72cf1aaddd71387cc058bc3f4c235ea6be4010fd61b28e1fbb275462b53775c04be9022d38b6a2e0387dddba86a3f8554d2858044a59fddbd594753fc056fe33c8daddb85dc70d164690b1182209ff84824e0be10e35c379f2f378bf176a9f7cb94d95e44d90276a298c8810f741c9":MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA256:MBEDTLS_RSA_SALT_LEN_ANY:128:0
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index a4c19b8..b236ea8 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -7946,7 +7946,7 @@
                                 &base_key ) );
 
     /* Derive a key. */
-    if ( mbedtls_test_psa_setup_key_derivation_wrap( &operation, base_key, alg,
+    if ( !mbedtls_test_psa_setup_key_derivation_wrap( &operation, base_key, alg,
                                                      input1->x, input1->len,
                                                      input2->x, input2->len,
                                                      capacity ) )
diff --git a/tests/suites/test_suite_shax.data b/tests/suites/test_suite_shax.data
index 3552346..2af85c3 100644
--- a/tests/suites/test_suite_shax.data
+++ b/tests/suites/test_suite_shax.data
@@ -169,10 +169,18 @@
 depends_on:MBEDTLS_SELF_TEST:MBEDTLS_SHA1_C
 sha1_selftest:
 
+SHA-224 Selftest
+depends_on:MBEDTLS_SELF_TEST:MBEDTLS_SHA224_C
+sha224_selftest:
+
 SHA-256 Selftest
 depends_on:MBEDTLS_SELF_TEST:MBEDTLS_SHA256_C
 sha256_selftest:
 
+SHA-384 Selftest
+depends_on:MBEDTLS_SELF_TEST:MBEDTLS_SHA384_C
+sha384_selftest:
+
 SHA-512 Selftest
 depends_on:MBEDTLS_SELF_TEST:MBEDTLS_SHA512_C
 sha512_selftest:
diff --git a/tests/suites/test_suite_shax.function b/tests/suites/test_suite_shax.function
index aebfd84..79afe01 100644
--- a/tests/suites/test_suite_shax.function
+++ b/tests/suites/test_suite_shax.function
@@ -46,9 +46,9 @@
     memset(output, 0x00, 57);
 
 
-    TEST_ASSERT( mbedtls_sha256( src_str->x, src_str->len, output, 1 ) == 0 );
+    TEST_EQUAL( mbedtls_sha256( src_str->x, src_str->len, output, 1 ), 0 );
 
-    TEST_ASSERT( mbedtls_test_hexcmp( output, hash->x, 28, hash->len ) == 0 );
+    TEST_EQUAL( mbedtls_test_hexcmp( output, hash->x, 28, hash->len ), 0 );
 }
 /* END_CASE */
 
@@ -60,9 +60,9 @@
     memset(output, 0x00, 65);
 
 
-    TEST_ASSERT( mbedtls_sha256( src_str->x, src_str->len, output, 0 ) == 0 );
+    TEST_EQUAL( mbedtls_sha256( src_str->x, src_str->len, output, 0 ), 0 );
 
-    TEST_ASSERT( mbedtls_test_hexcmp( output, hash->x, 32, hash->len ) == 0 );
+    TEST_EQUAL( mbedtls_test_hexcmp( output, hash->x, 32, hash->len ), 0 );
 }
 /* END_CASE */
 
@@ -94,9 +94,9 @@
     memset(output, 0x00, 97);
 
 
-    TEST_ASSERT( mbedtls_sha512( src_str->x, src_str->len, output, 1 ) == 0 );
+    TEST_EQUAL( mbedtls_sha512( src_str->x, src_str->len, output, 1 ), 0 );
 
-    TEST_ASSERT( mbedtls_test_hexcmp( output, hash->x, 48, hash->len ) == 0 );
+    TEST_EQUAL( mbedtls_test_hexcmp( output, hash->x, 48, hash->len ), 0 );
 }
 /* END_CASE */
 
@@ -108,9 +108,9 @@
     memset(output, 0x00, 129);
 
 
-    TEST_ASSERT( mbedtls_sha512( src_str->x, src_str->len, output, 0 ) == 0 );
+    TEST_EQUAL( mbedtls_sha512( src_str->x, src_str->len, output, 0 ), 0 );
 
-    TEST_ASSERT( mbedtls_test_hexcmp( output, hash->x, 64, hash->len ) == 0 );
+    TEST_EQUAL( mbedtls_test_hexcmp( output, hash->x, 64, hash->len ), 0 );
 }
 /* END_CASE */
 
@@ -121,16 +121,30 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_SHA224_C:MBEDTLS_SELF_TEST */
+void sha224_selftest(  )
+{
+    TEST_EQUAL( mbedtls_sha224_self_test( 1 ), 0 );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SHA256_C:MBEDTLS_SELF_TEST */
 void sha256_selftest(  )
 {
-    TEST_ASSERT( mbedtls_sha256_self_test( 1 ) == 0 );
+    TEST_EQUAL( mbedtls_sha256_self_test( 1 ), 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SHA384_C:MBEDTLS_SELF_TEST */
+void sha384_selftest(  )
+{
+    TEST_EQUAL( mbedtls_sha384_self_test( 1 ), 0 );
 }
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_SHA512_C:MBEDTLS_SELF_TEST */
 void sha512_selftest(  )
 {
-    TEST_ASSERT( mbedtls_sha512_self_test( 1 ) == 0 );
+    TEST_EQUAL( mbedtls_sha512_self_test( 1 ), 0 );
 }
 /* END_CASE */
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index 1b5e44b..3059e7f 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -3547,3 +3547,6 @@
 EC-JPAKE set opaque password
 depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED:MBEDTLS_USE_PSA_CRYPTO
 ssl_ecjpake_set_password:1
+
+Test Elliptic curves' info parsing
+elliptic_curve_get_properties
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 95fa8ef..b0b9136 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -2597,6 +2597,25 @@
                                         pwd_string, pwd_len );  \
     TEST_EQUAL( ret, exp_ret_val )
 #endif
+
+#define TEST_AVAILABLE_ECC( tls_id_, group_id_, psa_family_, psa_bits_ )   \
+    TEST_EQUAL( mbedtls_ssl_get_ecp_group_id_from_tls_id( tls_id_ ),       \
+                    group_id_ );                                           \
+    TEST_EQUAL( mbedtls_ssl_get_tls_id_from_ecp_group_id( group_id_ ),     \
+                    tls_id_ );                                             \
+    TEST_EQUAL( mbedtls_ssl_get_psa_curve_info_from_tls_id( tls_id_,       \
+                    &psa_family, &psa_bits), PSA_SUCCESS );                \
+    TEST_EQUAL( psa_family_, psa_family );                                 \
+    TEST_EQUAL( psa_bits_, psa_bits );
+
+#define TEST_UNAVAILABLE_ECC( tls_id_, group_id_, psa_family_, psa_bits_ ) \
+    TEST_EQUAL( mbedtls_ssl_get_ecp_group_id_from_tls_id( tls_id_ ),       \
+                    MBEDTLS_ECP_DP_NONE );                                 \
+    TEST_EQUAL( mbedtls_ssl_get_tls_id_from_ecp_group_id( group_id_ ),     \
+                    0 );                                                   \
+    TEST_EQUAL( mbedtls_ssl_get_psa_curve_info_from_tls_id( tls_id_,       \
+                    &psa_family, &psa_bits), PSA_ERROR_NOT_SUPPORTED );
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -4532,7 +4551,7 @@
                                   data_t *transcript,
                                   data_t *binder_expected )
 {
-    unsigned char binder[ MBEDTLS_MD_MAX_SIZE ];
+    unsigned char binder[ MBEDTLS_HASH_MAX_SIZE ];
 
     /* Double-check that we've passed sane parameters. */
     psa_algorithm_t alg = (psa_algorithm_t) hash_alg;
@@ -4664,7 +4683,7 @@
                               data_t *input,
                               data_t *expected )
 {
-    unsigned char secret_new[ MBEDTLS_MD_MAX_SIZE ];
+    unsigned char secret_new[ MBEDTLS_HASH_MAX_SIZE ];
 
     PSA_INIT();
 
@@ -6094,3 +6113,81 @@
     USE_PSA_DONE( );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void elliptic_curve_get_properties( )
+{
+    psa_ecc_family_t psa_family;
+    size_t psa_bits;
+
+    USE_PSA_INIT( );
+
+#if defined( MBEDTLS_ECP_DP_SECP521R1_ENABLED ) || defined(PSA_WANT_ECC_SECP_R1_521)
+    TEST_AVAILABLE_ECC( 25, MBEDTLS_ECP_DP_SECP521R1, PSA_ECC_FAMILY_SECP_R1, 521 );
+#else
+    TEST_UNAVAILABLE_ECC( 25, MBEDTLS_ECP_DP_SECP521R1, PSA_ECC_FAMILY_SECP_R1, 521 );
+#endif
+#if defined( MBEDTLS_ECP_DP_BP512R1_ENABLED ) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
+    TEST_AVAILABLE_ECC( 28, MBEDTLS_ECP_DP_BP512R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 512 );
+#else
+    TEST_UNAVAILABLE_ECC( 28, MBEDTLS_ECP_DP_BP512R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 512 );
+#endif
+#if defined( MBEDTLS_ECP_DP_SECP384R1_ENABLED ) || defined(PSA_WANT_ECC_SECP_R1_384)
+    TEST_AVAILABLE_ECC( 24, MBEDTLS_ECP_DP_SECP384R1, PSA_ECC_FAMILY_SECP_R1, 384 );
+#else
+    TEST_UNAVAILABLE_ECC( 24, MBEDTLS_ECP_DP_SECP384R1, PSA_ECC_FAMILY_SECP_R1, 384 );
+#endif
+#if defined( MBEDTLS_ECP_DP_BP384R1_ENABLED ) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
+    TEST_AVAILABLE_ECC( 27, MBEDTLS_ECP_DP_BP384R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 384 );
+#else
+    TEST_UNAVAILABLE_ECC( 27, MBEDTLS_ECP_DP_BP384R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 384 );
+#endif
+#if defined( MBEDTLS_ECP_DP_SECP256R1_ENABLED ) || defined(PSA_WANT_ECC_SECP_R1_256)
+    TEST_AVAILABLE_ECC( 23, MBEDTLS_ECP_DP_SECP256R1, PSA_ECC_FAMILY_SECP_R1, 256 );
+#else
+    TEST_UNAVAILABLE_ECC( 23, MBEDTLS_ECP_DP_SECP256R1, PSA_ECC_FAMILY_SECP_R1, 256 );
+#endif
+#if defined( MBEDTLS_ECP_DP_SECP256K1_ENABLED ) || defined(PSA_WANT_ECC_SECP_K1_256)
+    TEST_AVAILABLE_ECC( 22, MBEDTLS_ECP_DP_SECP256K1, PSA_ECC_FAMILY_SECP_K1, 256 );
+#else
+    TEST_UNAVAILABLE_ECC( 22, MBEDTLS_ECP_DP_SECP256K1, PSA_ECC_FAMILY_SECP_K1, 256 );
+#endif
+#if defined( MBEDTLS_ECP_DP_BP256R1_ENABLED ) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
+    TEST_AVAILABLE_ECC( 26, MBEDTLS_ECP_DP_BP256R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 256 );
+#else
+    TEST_UNAVAILABLE_ECC( 26, MBEDTLS_ECP_DP_BP256R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 256 );
+#endif
+#if defined( MBEDTLS_ECP_DP_SECP224R1_ENABLED ) || defined(PSA_WANT_ECC_SECP_R1_224)
+    TEST_AVAILABLE_ECC( 21, MBEDTLS_ECP_DP_SECP224R1, PSA_ECC_FAMILY_SECP_R1, 224 );
+#else
+    TEST_UNAVAILABLE_ECC( 21, MBEDTLS_ECP_DP_SECP224R1, PSA_ECC_FAMILY_SECP_R1, 224 );
+#endif
+#if defined( MBEDTLS_ECP_DP_SECP224K1_ENABLED ) || defined(PSA_WANT_ECC_SECP_K1_224)
+    TEST_AVAILABLE_ECC( 20, MBEDTLS_ECP_DP_SECP224K1, PSA_ECC_FAMILY_SECP_K1, 224 );
+#else
+    TEST_UNAVAILABLE_ECC( 20, MBEDTLS_ECP_DP_SECP224K1, PSA_ECC_FAMILY_SECP_K1, 224 );
+#endif
+#if defined( MBEDTLS_ECP_DP_SECP192R1_ENABLED ) || defined(PSA_WANT_ECC_SECP_R1_192)
+    TEST_AVAILABLE_ECC( 19, MBEDTLS_ECP_DP_SECP192R1, PSA_ECC_FAMILY_SECP_R1, 192 );
+#else
+    TEST_UNAVAILABLE_ECC( 19, MBEDTLS_ECP_DP_SECP192R1, PSA_ECC_FAMILY_SECP_R1, 192 );
+#endif
+#if defined( MBEDTLS_ECP_DP_SECP192K1_ENABLED ) || defined(PSA_WANT_ECC_SECP_K1_192)
+    TEST_AVAILABLE_ECC( 18, MBEDTLS_ECP_DP_SECP192K1, PSA_ECC_FAMILY_SECP_K1, 192 );
+#else
+    TEST_UNAVAILABLE_ECC( 18, MBEDTLS_ECP_DP_SECP192K1, PSA_ECC_FAMILY_SECP_K1, 192 );
+#endif
+#if defined( MBEDTLS_ECP_DP_CURVE25519_ENABLED ) || defined(PSA_WANT_ECC_MONTGOMERY_255)
+    TEST_AVAILABLE_ECC( 29, MBEDTLS_ECP_DP_CURVE25519, PSA_ECC_FAMILY_MONTGOMERY, 255 );
+#else
+    TEST_UNAVAILABLE_ECC( 29, MBEDTLS_ECP_DP_CURVE25519, PSA_ECC_FAMILY_MONTGOMERY, 255 );
+#endif
+#if defined( MBEDTLS_ECP_DP_CURVE448_ENABLED ) || defined(PSA_WANT_ECC_MONTGOMERY_448)
+    TEST_AVAILABLE_ECC( 30, MBEDTLS_ECP_DP_CURVE448, PSA_ECC_FAMILY_MONTGOMERY, 448 );
+#else
+    TEST_UNAVAILABLE_ECC( 30, MBEDTLS_ECP_DP_CURVE448, PSA_ECC_FAMILY_MONTGOMERY, 448 );
+#endif
+
+    USE_PSA_DONE( );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index bd03016..002f3dc 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -704,7 +704,7 @@
 x509_verify:"data_files/server5-sha1.crt":"data_files/test-ca2.crt":"data_files/crl-ec-sha256.pem":"NULL":0:0:"compat":"NULL"
 
 X509 CRT verification #37 (Valid, EC CA, SHA224 Digest)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509_verify:"data_files/server5-sha224.crt":"data_files/test-ca2.crt":"data_files/crl-ec-sha256.pem":"NULL":0:0:"compat":"NULL"
 
 X509 CRT verification #38 (Valid, EC CA, SHA384 Digest)
@@ -831,12 +831,16 @@
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509_verify:"data_files/server9-defaults.crt":"data_files/test-ca.crt":"data_files/crl-rsa-pss-sha1.pem":"NULL":0:0:"compat":"NULL"
 
-X509 CRT verification #68 (RSASSA-PSS, wrong salt_len)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-x509_verify:"data_files/server9-bad-saltlen.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:"compat":"NULL"
+X509 CRT verification #68 (RSASSA-PSS, wrong salt_len, !USE_PSA)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA:!MBEDTLS_USE_PSA_CRYPTO
+x509_verify:"data_files/server9-bad-saltlen.crt":"data_files/test-ca.crt":"data_files/crl-rsa-pss-sha1.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:"compat":"NULL"
+
+X509 CRT verification #68 (RSASSA-PSS, wrong salt_len, USE_PSA)
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_USE_PSA_CRYPTO
+x509_verify:"data_files/server9-bad-saltlen.crt":"data_files/test-ca.crt":"data_files/crl-rsa-pss-sha1.pem":"NULL":0:0:"compat":"NULL"
 
 X509 CRT verification #69 (RSASSA-PSS, wrong mgf_hash)
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509_verify:"data_files/server9-bad-mgfhash.crt":"data_files/test-ca.crt":"data_files/crl.pem":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:"compat":"NULL"
 
 X509 CRT verification #70 (v1 trusted CA)
@@ -2113,35 +2117,35 @@
 x509parse_crl:"30143012020100300d06092a864886f70d01010f0500":"":MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG
 
 X509 CRL ASN1 (TBSCertList, sig_oid1 correct, issuer missing)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"30143012020100300d06092a864886f70d01010e0500":"":MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, issuer set missing)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"30163014020100300d06092a864886f70d01010e05003000":"":MBEDTLS_ERR_X509_INVALID_NAME + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, correct issuer, thisUpdate missing)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"30253023020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344":"":MBEDTLS_ERR_X509_INVALID_DATE + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, correct thisUpdate, nextUpdate missing, entries length missing)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"30343032020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c30393031303130303030303030":"":MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, entries present, invalid sig_alg)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"304a3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c30383132333132333539353900":"":MBEDTLS_ERR_X509_INVALID_ALG + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
 
 X509 CRL ASN1 (TBSCertList, entries present, date in entry invalid)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"304a3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd190c30383132333132333539353900":"":MBEDTLS_ERR_X509_INVALID_DATE + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
 
 X509 CRL ASN1 (TBSCertList, sig_alg present, sig_alg does not match)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"30583047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c303831323331323335393539300d06092a864886f70d01010d0500":"":MBEDTLS_ERR_X509_SIG_MISMATCH
 
 X509 CRL ASN1 (TBSCertList, sig present, len mismatch)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"305d3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c303831323331323335393539300d06092a864886f70d01010e05000302000100":"":MBEDTLS_ERR_X509_INVALID_FORMAT + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
 
 # 305c
@@ -2167,35 +2171,35 @@
 x509parse_crl:"305c3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c303831323331323335393539300d06092a864886f70d01010e050003020001":"CRL version   \: 1\nissuer name   \: CN=ABCD\nthis update   \: 2009-01-01 00\:00\:00\nnext update   \: 0000-00-00 00\:00\:00\nRevoked certificates\:\nserial number\: AB\:CD revocation date\: 2008-12-31 23\:59\:59\nsigned using  \: RSA with SHA-224\n":0
 
 X509 CRL ASN1 (TBSCertList, signatureValue missing)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"30583047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c303831323331323335393539300d06092a864886f70d01010e0500":"":MBEDTLS_ERR_X509_INVALID_SIGNATURE + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, signatureAlgorithm missing)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"30493047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd170c303831323331323335393539":"":MBEDTLS_ERR_X509_INVALID_ALG + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, single empty entry at end)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"30373035020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c30393031303130303030303030023000":"":MBEDTLS_ERR_X509_INVALID_SERIAL + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, good entry then empty entry at end)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"304b3049020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301630128202abcd170c3038313233313233353935393000":"":MBEDTLS_ERR_X509_INVALID_SERIAL + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, missing time in entry)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"304e3039020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030300630048202abcd300d06092a864886f70d01010e050003020001":"":MBEDTLS_ERR_X509_INVALID_DATE + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, missing time in entry at end)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"303b3039020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030300630048202abcd":"":MBEDTLS_ERR_X509_INVALID_DATE + MBEDTLS_ERR_ASN1_OUT_OF_DATA
 
 X509 CRL ASN1 (TBSCertList, invalid tag for time in entry)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"305c3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128202abcd190c303831323331323335393539300d06092a864886f70d01010e050003020001":"":MBEDTLS_ERR_X509_INVALID_DATE + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
 
 X509 CRL ASN1 (TBSCertList, invalid tag for serial)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+depends_on:MBEDTLS_RSA_C:MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
 x509parse_crl:"305c3047020100300d06092a864886f70d01010e0500300f310d300b0603550403130441424344170c303930313031303030303030301430128402abcd170c303831323331323335393539300d06092a864886f70d01010e050003020001":"":MBEDTLS_ERR_X509_INVALID_SERIAL + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
 
 X509 CRL ASN1 (TBSCertList, no entries)
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index dc36b81..388d45e 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -665,8 +665,8 @@
 
     res = mbedtls_x509_crt_verify_with_profile( &crt, &ca, &crl, profile, cn_name, &flags, f_vrfy, NULL );
 
-    TEST_ASSERT( res == ( result ) );
-    TEST_ASSERT( flags == (uint32_t)( flags_result ) );
+    TEST_EQUAL( res, result );
+    TEST_EQUAL( flags, (uint32_t) flags_result );
 
 #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
     /* CRLs aren't supported with CA callbacks, so skip the CA callback