Merge pull request #8897 from IVOES/cpp/unbounded-write

ssl_mail_client: Fix unbounded write of sprintf()
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 9d30412..892ed28 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -9,7 +9,8 @@
 Please tick as appropriate and edit the reasons (e.g.: "backport: not needed because this is a new feature")
 
 - [ ] **changelog** provided, or not required
-- [ ] **backport** done, or not required
+- [ ] **3.6 backport** done, or not required
+- [ ] **2.28 backport** done, or not required
 - [ ] **tests** provided, or not required
 
 
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..4fb26b5
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "framework"]
+	path = framework
+	url = https://github.com/Mbed-TLS/mbedtls-framework
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 72f126f..2b10f86 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -5,6 +5,11 @@
 # Required
 version: 2
 
+# Include the framework submodule in the build
+submodules:
+  include:
+  - framework
+
 # Set the version of Python and other tools you might need
 build:
   os: ubuntu-20.04
diff --git a/BRANCHES.md b/BRANCHES.md
index b71247f..bcceda8 100644
--- a/BRANCHES.md
+++ b/BRANCHES.md
@@ -2,31 +2,32 @@
 
 At any point in time, we have a number of maintained branches, currently consisting of:
 
-- The [`master`](https://github.com/Mbed-TLS/mbedtls/tree/master) branch:
+- The [`main`](https://github.com/Mbed-TLS/mbedtls/tree/main) branch:
   this always contains the latest release, including all publicly available
   security fixes.
 - The [`development`](https://github.com/Mbed-TLS/mbedtls/tree/development) branch:
-  this is where the current major version of Mbed TLS (version 3.x) is being
-  prepared. It has API changes that make it incompatible with Mbed TLS 2.x,
+  this is where the next major version of Mbed TLS (version 4.0) is being
+  prepared. It has API changes that make it incompatible with Mbed TLS 3.x,
   as well as all the new features and bug fixes and security fixes.
 - One or more long-time support (LTS) branches: these only get bug fixes and
-  security fixes. Currently, the only supported LTS branch is:
-  [`mbedtls-2.28`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-2.28).
+  security fixes. Currently, the supported LTS branches are:
+- [`mbedtls-2.28`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-2.28).
+- [`mbedtls-3.6`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-3.6).
 
 We retain a number of historical branches, whose names are prefixed by `archive/`,
 such as [`archive/mbedtls-2.7`](https://github.com/Mbed-TLS/mbedtls/tree/archive/mbedtls-2.7).
 These branches will not receive any changes or updates.
 
 We use [Semantic Versioning](https://semver.org/). In particular, we maintain
-API compatibility in the `master` branch across minor version changes (e.g.
+API compatibility in the `main` branch across minor version changes (e.g.
 the API of 3.(x+1) is backward compatible with 3.x). We only break API
 compatibility on major version changes (e.g. from 3.x to 4.0). We also maintain
 ABI compatibility within LTS branches; see the next section for details.
 
-Every major version will become an LTS branch when the next major version is
-released. We may occasionally create LTS branches from other releases at our
-discretion.
-When a new LTS branch is created, it usually remains supported for three years.
+We will make regular LTS releases on an 18-month cycle, each of which will have
+a 3 year support lifetime. On this basis, 3.6 LTS (released March 2024) will be
+supported until March 2027. The next LTS release will be a 4.x release, which is
+planned for September 2025.
 
 ## Backwards Compatibility for application code
 
@@ -102,10 +103,13 @@
 
 The following branches are currently maintained:
 
-- [master](https://github.com/Mbed-TLS/mbedtls/tree/master)
+- [main](https://github.com/Mbed-TLS/mbedtls/tree/main)
 - [`development`](https://github.com/Mbed-TLS/mbedtls/)
+- [`mbedtls-3.6`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-3.6)
+ maintained until March 2027, see
+  <https://github.com/Mbed-TLS/mbedtls/releases/tag/v3.6.0>.
 - [`mbedtls-2.28`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-2.28)
- maintained until at least the end of 2024, see
-  <https://github.com/Mbed-TLS/mbedtls/releases/tag/v2.28.7>.
+ maintained until the end of 2024, see
+  <https://github.com/Mbed-TLS/mbedtls/releases/tag/v2.28.8>.
 
 Users are urged to always use the latest version of a maintained branch.
diff --git a/BUGS.md b/BUGS.md
index 47bde07..a65c606 100644
--- a/BUGS.md
+++ b/BUGS.md
@@ -7,7 +7,7 @@
 If you think you've found a bug in Mbed TLS, please follow these steps:
 
 1. Make sure you're using the latest version of a
-   [maintained branch](BRANCHES.md): `master`, `development`,
+   [maintained branch](BRANCHES.md): `main`, `development`,
    or a long-time support branch.
 2. Check [GitHub](https://github.com/Mbed-TLS/mbedtls/issues) to see if
    your issue has already been reported. If not, …
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5585c78..fb9e1c3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -34,9 +34,15 @@
 cmake_policy(SET CMP0012 NEW)
 
 if(TEST_CPP)
-    project("Mbed TLS" LANGUAGES C CXX)
+    project("Mbed TLS"
+        LANGUAGES C CXX
+        VERSION 3.6.0
+    )
 else()
-    project("Mbed TLS" LANGUAGES C)
+    project("Mbed TLS"
+        LANGUAGES C
+        VERSION 3.6.0
+    )
 endif()
 
 include(GNUInstallDirs)
@@ -277,6 +283,11 @@
     set(CMAKE_INSTALL_LIBDIR "${LIB_INSTALL_DIR}")
 endif()
 
+if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/framework/CMakeLists.txt")
+    message(FATAL_ERROR "${CMAKE_CURRENT_SOURCE_DIR}/framework/CMakeLists.txt not found. Run `git submodule update --init` from the source tree to fetch the submodule contents.")
+endif()
+add_subdirectory(framework)
+
 add_subdirectory(include)
 
 add_subdirectory(3rdparty)
@@ -308,6 +319,8 @@
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/include
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/library)
+    # Request C11, needed for memory poisoning tests
+    set_target_properties(mbedtls_test PROPERTIES C_STANDARD 11)
 
     file(GLOB MBEDTLS_TEST_HELPER_FILES
          ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/test_helpers/*.c)
@@ -388,7 +401,7 @@
     write_basic_package_version_file(
         "cmake/MbedTLSConfigVersion.cmake"
             COMPATIBILITY SameMajorVersion
-            VERSION 3.5.2)
+            VERSION 3.6.0)
 
     install(
         FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/MbedTLSConfig.cmake"
diff --git a/ChangeLog b/ChangeLog
index 28f2654..b691a0f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,266 @@
 Mbed TLS ChangeLog (Sorted per branch, date)
 
+= Mbed TLS 3.6.0 branch released 2024-03-28
+
+API changes
+   * Remove `tls13_` in mbedtls_ssl_tls13_conf_early_data() and
+     mbedtls_ssl_tls13_conf_max_early_data_size() API names. Early data
+     feature may not be TLS 1.3 specific in the future. Fixes #6909.
+
+Default behavior changes
+   * psa_import_key() now only accepts RSA keys in the PSA standard formats.
+     The undocumented ability to import other formats (PKCS#8, SubjectPublicKey,
+     PEM) accepted by the pkparse module has been removed. Applications that
+     need these formats can call mbedtls_pk_parse_{public,}key() followed by
+     mbedtls_pk_import_into_psa().
+
+Requirement changes
+   * Drop support for Visual Studio 2013 and 2015, and Arm Compiler 5.
+
+New deprecations
+   * Rename the MBEDTLS_SHA256_USE_A64_CRYPTO_xxx config options to
+     MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_xxx. The old names may still
+     be used, but are deprecated.
+   * In the PSA API, domain parameters are no longer used for anything.
+     They are deprecated and will be removed in a future version of the
+     library.
+   * mbedtls_ecp_write_key() is deprecated in favor of
+     mbedtls_ecp_write_key_ext().
+
+Removals
+   * In the PSA API, the experimental way to encode the public exponent of
+     an RSA key as a domain parameter is no longer supported. Use
+     psa_generate_key_ext() instead.
+   * Temporary function mbedtls_pk_wrap_as_opaque() is removed. To mimic the
+     same behavior mbedtls_pk_get_psa_attributes() and
+     mbedtls_pk_import_into_psa() can be used to import a PK key into PSA,
+     while mbedtls_pk_setup_opaque() can be used to wrap a PSA key into a opaque
+     PK context.
+
+Features
+   * Added an example program showing how to hash with the PSA API.
+   * Support Armv8-A Crypto Extension acceleration for SHA-256
+     when compiling for Thumb (T32) or 32-bit Arm (A32).
+   * AES-NI is now supported in Windows builds with clang and clang-cl.
+     Resolves #8372.
+   * Add new mbedtls_x509_csr_parse_der_with_ext_cb() routine which allows
+     parsing unsupported certificate extensions via user provided callback.
+   * Enable the new option MBEDTLS_BLOCK_CIPHER_NO_DECRYPT to omit
+     the decryption direction of block ciphers (AES, ARIA, Camellia).
+     This affects both the low-level modules and the high-level APIs
+     (the cipher and PSA interfaces). This option is incompatible with modes
+     that use the decryption direction (ECB in PSA, CBC, XTS, KW) and with DES.
+   * Support use of Armv8-A Cryptographic Extensions for hardware acclerated
+     AES when compiling for Thumb (T32) or 32-bit Arm (A32).
+   * If a cipher or AEAD mechanism has a PSA driver, you can now build the
+     library without the corresponding built-in implementation. Generally
+     speaking that requires both the key type and algorithm to be accelerated
+     or they'll both be built in. However, for CCM and GCM the built-in
+     implementation is able to take advantage of a driver that only
+     accelerates the key type (that is, the block cipher primitive). See
+     docs/driver-only-builds.md for full details and current limitations.
+   * The CTR_DRBG module will now use AES from a PSA driver if MBEDTLS_AES_C is
+     disabled. This requires PSA_WANT_ALG_ECB_NO_PADDING in addition to
+     MBEDTLS_PSA_CRYPTO_C and PSA_WANT_KEY_TYPE_AES.
+   * Fewer modules depend on MBEDTLS_CIPHER_C, making it possible to save code
+     size by disabling it in more circumstances. In particular, the CCM and
+     GCM modules no longer depend on MBEDTLS_CIPHER_C. Also,
+     MBEDTLS_PSA_CRYPTO can now be enabled without MBEDTLS_CIPHER_C if all
+     unauthenticated (non-AEAD) ciphers are disabled, or if they're all
+     fully provided by drivers. See docs/driver-only-builds.md for full
+     details and current limitations; in particular, NIST_KW and PKCS5/PKCS12
+     decryption still unconditionally depend on MBEDTLS_CIPHER_C.
+   * Add support for record size limit extension as defined by RFC 8449
+     and configured with MBEDTLS_SSL_RECORD_SIZE_LIMIT.
+     Application data sent and received will be fragmented according to
+     Record size limits negotiated during handshake.
+   * Improve performance of AES-GCM, AES-CTR and CTR-DRBG when
+     hardware accelerated AES is not present (around 13-23% on 64-bit Arm).
+   * Add functions mbedtls_ecc_group_to_psa() and mbedtls_ecc_group_from_psa()
+     to convert between Mbed TLS and PSA curve identifiers.
+   * Add utility functions to manipulate mbedtls_ecp_keypair objects, filling
+     gaps made by making its fields private: mbedtls_ecp_set_public_key(),
+     mbedtls_ecp_write_public_key(), mbedtls_ecp_keypair_calc_public(),
+     mbedtls_ecp_keypair_get_group_id(). Fixes #5017, #5441, #8367, #8652.
+   * Add functions mbedtls_md_psa_alg_from_type() and
+     mbedtls_md_type_from_psa_alg() to convert between mbedtls_md_type_t and
+     psa_algorithm_t.
+   * Add partial platform support for z/OS.
+   * Improve performance for gcc (versions older than 9.3.0) and IAR.
+   * Add functions mbedtls_ecdsa_raw_to_der() and mbedtls_ecdsa_der_to_raw() to
+     convert ECDSA signatures between raw and DER (ASN.1) formats.
+   * Add support for using AES-CBC 128, 192, and 256 bit schemes
+     with PKCS#5 PBES2. Keys encrypted this way can now be parsed by PK parse.
+   * The new function mbedtls_rsa_get_bitlen() returns the length of the modulus
+     in bits, i.e. the key size for an RSA key.
+   * Add pc files for pkg-config, e.g.:
+     pkg-config --cflags --libs (mbedtls|mbedcrypto|mbedx509)
+   * Add getter (mbedtls_ssl_session_get_ticket_creation_time()) to access
+     `mbedtls_ssl_session.ticket_creation_time`.
+   * The new functions mbedtls_pk_get_psa_attributes() and
+     mbedtls_pk_import_into_psa() provide a uniform way to create a PSA
+     key from a PK key.
+   * The benchmark program now reports times for both ephemeral and static
+     ECDH in all ECDH configurations.
+   * Add support for 8-bit GCM tables for Shoup's algorithm to speedup GCM
+     operations when hardware accelerated AES is not present. Improves
+     performance by around 30% on 64-bit Intel; 125% on Armv7-M.
+   * The new function psa_generate_key_ext() allows generating an RSA
+     key pair with a custom public exponent.
+   * The new function mbedtls_ecp_write_key_ext() is similar to
+     mbedtls_ecp_write_key(), but can be used without separately calculating
+     the output length.
+   * Add new accessor to expose the private group id member of
+     `mbedtls_ecdh_context` structure.
+   * Add new accessor to expose the `MBEDTLS_PRIVATE(ca_istrue)` member of
+     `mbedtls_x509_crt` structure. This requires setting
+     the MBEDTLS_X509_EXT_BASIC_CONSTRAINTS bit in the certificate's
+     ext_types field.
+   * mbedtls_psa_get_random() is always available as soon as
+     MBEDTLS_PSA_CRYPTO_CLIENT is enabled at build time and psa_crypto_init() is
+     called at runtime. This together with MBEDTLS_PSA_RANDOM_STATE can be
+     used as random number generator function (f_rng) and context (p_rng) in
+     legacy functions.
+   * The new functions mbedtls_pk_copy_from_psa() and
+     mbedtls_pk_copy_public_from_psa() provide ways to set up a PK context
+     with the same content as a PSA key.
+   * Add new accessors to expose the private session-id,
+     session-id length, and ciphersuite-id members of
+     `mbedtls_ssl_session` structure.
+     Add new accessor to expose the ciphersuite-id of
+     `mbedtls_ssl_ciphersuite_t` structure.Design ref: #8529
+   * Mbed TLS now supports the writing and reading of TLS 1.3 early data (see
+     docs/tls13-early-data.md). The support enablement is controlled at build
+     time by the MBEDTLS_SSL_EARLY_DATA configuration option and at runtime by
+     the mbedtls_ssl_conf_early_data() API (by default disabled in both cases).
+   * Add protection for multithreaded access to the PSA keystore and protection
+     for multithreaded access to the the PSA global state, including
+     concurrently calling psa_crypto_init() when MBEDTLS_THREADING_C and
+     MBEDTLS_THREADING_PTHREAD are defined. See
+     docs/architecture/psa-thread-safety/psa-thread-safety.md for more details.
+     Resolves issues #3263 and #7945.
+
+Security
+   * Fix a stack buffer overread (less than 256 bytes) when parsing a TLS 1.3
+     ClientHello in a TLS 1.3 server supporting some PSK key exchange mode. A
+     malicious client could cause information disclosure or a denial of service.
+     Fixes CVE-2024-30166.
+   * Passing buffers that are stored in untrusted memory as arguments
+     to PSA functions is now secure by default.
+     The PSA core now protects against modification of inputs or exposure
+     of intermediate outputs during operations. This is currently implemented
+     by copying buffers.
+     This feature increases code size and memory usage. If buffers passed to
+     PSA functions are owned exclusively by the PSA core for the duration of
+     the function call (i.e. no buffer parameters are in shared memory),
+     copying may be disabled by setting MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS.
+     Note that setting this option will cause input-output buffer overlap to
+     be only partially supported (#3266).
+     Fixes CVE-2024-28960.
+   * Restore the maximum TLS version to be negotiated to the configured one
+     when an SSL context is reset with the mbedtls_ssl_session_reset() API.
+     An attacker was able to prevent an Mbed TLS server from establishing any
+     TLS 1.3 connection potentially resulting in a Denial of Service or forced
+     version downgrade from TLS 1.3 to TLS 1.2. Fixes #8654 reported by hey3e.
+     Fixes CVE-2024-28755.
+   * When negotiating TLS version on server side, do not fall back to the
+     TLS 1.2 implementation of the protocol if it is disabled.
+     - If the TLS 1.2 implementation was disabled at build time, a TLS 1.2
+       client could put the TLS 1.3-only server in an infinite loop processing
+       a TLS 1.2 ClientHello, resulting in a denial of service. Reported by
+       Matthias Mucha and Thomas Blattmann, SICK AG.
+     - If the TLS 1.2 implementation was disabled at runtime, a TLS 1.2 client
+       was able to successfully establish a TLS 1.2 connection with the server.
+       Reported by alluettiv on GitHub.
+    Fixes CVE-2024-28836.
+
+Bugfix
+   * Fix the build with CMake when Everest or P256-m is enabled through
+     a user configuration file or the compiler command line. Fixes #8165.
+   * Fix compilation error in C++ programs when MBEDTLS_ASN1_PARSE_C is
+     disabled.
+   * Fix possible NULL dereference issue in X509 cert_req program if an entry
+     in the san parameter is not separated by a colon.
+   * Fix possible NULL dereference issue in X509 cert_write program if an entry
+     in the san parameter is not separated by a colon.
+   * Fix an inconsistency between implementations and usages of `__cpuid`,
+     which mainly causes failures when building Windows target using
+     mingw or clang. Fixes #8334 & #8332.
+   * Fix build failure in conda-forge.  Fixes #8422.
+   * Fix parsing of CSRs with critical extensions.
+   * Switch to milliseconds as the unit for ticket creation and reception time
+     instead of seconds. That avoids rounding errors when computing the age of
+     tickets compared to peer using a millisecond clock (observed with GnuTLS).
+     Fixes #6623.
+   * Fix TLS server accepting TLS 1.2 handshake while TLS 1.2
+     is disabled at runtime. Fixes #8593.
+   * Remove accidental introduction of RSA signature algorithms
+     in TLS Suite B Profile. Fixes #8221.
+   * Fix unsupported PSA asymmetric encryption and decryption
+     (psa_asymmetric_[en|de]crypt) with opaque keys.
+     Resolves #8461.
+   * On Linux on ARMv8, fix a build error with SHA-256 and SHA-512
+     acceleration detection when the libc headers do not define the
+     corresponding constant. Reported by valord577.
+   * Correct initial capacities for key derivation algorithms:TLS12_PRF,
+     TLS12_PSK_TO_MS, PBKDF2-HMAC, PBKDF2-CMAC
+   * Fix mbedtls_pk_get_bitlen() for RSA keys whose size is not a
+     multiple of 8. Fixes #868.
+   * Avoid segmentation fault caused by releasing not initialized
+     entropy resource in gen_key example. Fixes #8809.
+   * mbedtls_pem_read_buffer() now performs a check on the padding data of
+     decrypted keys and it rejects invalid ones.
+   * Fix mbedtls_pk_sign(), mbedtls_pk_verify(), mbedtls_pk_decrypt() and
+     mbedtls_pk_encrypt() on non-opaque RSA keys to honor the padding mode in
+     the RSA context. Before, if MBEDTLS_USE_PSA_CRYPTO was enabled and the
+     RSA context was configured for PKCS#1 v2.1 (PSS/OAEP), the sign/verify
+     functions performed a PKCS#1 v1.5 signature instead and the
+     encrypt/decrypt functions returned an error. Fixes #8824.
+   * Fix missing bitflags in SSL session serialization headers. Their absence
+     allowed SSL sessions saved in one configuration to be loaded in a
+     different, incompatible configuration.
+   * In TLS 1.3 clients, fix an interoperability problem due to the client
+     generating a new random after a HelloRetryRequest. Fixes #8669.
+   * Fix the restoration of the ALPN when loading serialized connection with
+     the mbedtls_ssl_context_load() API.
+   * Fix NULL pointer dereference in mbedtls_pk_verify_ext() when called using
+     an opaque RSA context and specifying MBEDTLS_PK_RSASSA_PSS as key type.
+   * Fix RSA opaque keys always using PKCS1 v1.5 algorithms instead of the
+     primary algorithm of the wrapped PSA key.
+   * Fully support arbitrary overlap between inputs and outputs of PSA
+     functions. Note that overlap is still only partially supported when
+     MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS is set (#3266).
+
+Changes
+   * Use heap memory to allocate DER encoded public/private key.
+     This reduces stack usage significantly for writing a public/private
+     key to a PEM string.
+   * PSA_WANT_ALG_CCM and PSA_WANT_ALG_CCM_STAR_NO_TAG are no more synonyms and
+     they are now treated separately. This means that they should be
+     individually enabled in order to enable respective support; also the
+     corresponding MBEDTLS_PSA_ACCEL symbol should be defined in case
+     acceleration is required.
+   * Moved declaration of functions mbedtls_ecc_group_to_psa and
+     mbedtls_ecc_group_of_psa from psa/crypto_extra.h to mbedtls/psa_util.h
+   * mbedtls_pk_sign_ext() is now always available, not just when
+     PSA (MBEDTLS_PSA_CRYPTO_C) is enabled.
+   * Extended PSA Crypto configurations options for FFDH by making it possible
+     to select only some of the parameters / groups, with the macros
+     PSA_WANT_DH_RFC7919_XXXX. You now need to defined the corresponding macro
+     for each size you want to support. Also, if you have an FFDH accelerator,
+     you'll need to define the appropriate MBEDTLS_PSA_ACCEL macros to signal
+     support for these domain parameters.
+   * RSA support in PSA no longer auto-enables the pkparse and pkwrite modules,
+     saving code size when those are not otherwise enabled.
+   * mbedtls_mpi_exp_mod and code that uses it, notably RSA and DHM operations,
+     have changed their speed/memory compromise as part of a proactive security
+     improvement. The new default value of MBEDTLS_MPI_WINDOW_SIZE roughly
+     preserves the current speed, at the expense of increasing memory
+     consumption.
+   * Rename directory containing Visual Studio files from visualc/VS2013 to
+     visualc/VS2017.
+   * The TLS 1.3 protocol is now enabled in the default configuration.
+
 = Mbed TLS 3.5.2 branch released 2024-01-26
 
 Security
diff --git a/ChangeLog.d/7764.txt b/ChangeLog.d/7764.txt
deleted file mode 100644
index 4cd2079..0000000
--- a/ChangeLog.d/7764.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add functions mbedtls_ecc_group_to_psa() and mbedtls_ecc_group_from_psa()
-     to convert between Mbed TLS and PSA curve identifiers.
diff --git a/ChangeLog.d/7765.txt b/ChangeLog.d/7765.txt
deleted file mode 100644
index 3dd6b5d..0000000
--- a/ChangeLog.d/7765.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add functions mbedtls_ecdsa_raw_to_der() and mbedtls_ecdsa_der_to_raw() to
-     convert ECDSA signatures between raw and DER (ASN.1) formats.
diff --git a/ChangeLog.d/8030.txt b/ChangeLog.d/8030.txt
deleted file mode 100644
index d99c9e7..0000000
--- a/ChangeLog.d/8030.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Changes
-   * Extended PSA Crypto configurations options for FFDH by making it possible
-     to select only some of the parameters / groups, with the macros
-     PSA_WANT_DH_RFC7919_XXXX. You now need to defined the corresponding macro
-     for each size you want to support. Also, if you have an FFDH accelerator,
-     you'll need to define the appropriate MBEDTLS_PSA_ACCEL macros to signal
-     support for these domain parameters.
diff --git a/ChangeLog.d/8340.txt b/ChangeLog.d/8340.txt
deleted file mode 100644
index 5664bf1..0000000
--- a/ChangeLog.d/8340.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Features
-   * Add functions mbedtls_md_psa_alg_from_type() and
-     mbedtls_md_type_from_psa_alg() to convert between mbedtls_md_type_t and
-     psa_algorithm_t.
diff --git a/ChangeLog.d/8372.txt b/ChangeLog.d/8372.txt
deleted file mode 100644
index 4a72edf..0000000
--- a/ChangeLog.d/8372.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   *  AES-NI is now supported in Windows builds with clang and clang-cl.
-      Resolves #8372.
diff --git a/ChangeLog.d/8461.txt b/ChangeLog.d/8461.txt
deleted file mode 100644
index d6a65f0..0000000
--- a/ChangeLog.d/8461.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
-   * Fix unsupported PSA asymmetric encryption and decryption
-     (psa_asymmetric_[en|de]crypt) with opaque keys.
-     Resolves #8461.
diff --git a/ChangeLog.d/8482.txt b/ChangeLog.d/8482.txt
deleted file mode 100644
index a392232..0000000
--- a/ChangeLog.d/8482.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Changes
-    * PSA_WANT_ALG_CCM and PSA_WANT_ALG_CCM_STAR_NO_TAG are no more synonyms and
-      they are now treated separately. This means that they should be
-      individually enabled in order to enable respective support; also the
-      corresponding MBEDTLS_PSA_ACCEL symbol should be defined in case
-      acceleration is required.
diff --git a/ChangeLog.d/8647.txt b/ChangeLog.d/8647.txt
deleted file mode 100644
index 98326dc..0000000
--- a/ChangeLog.d/8647.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-Default behavior changes
-   * psa_import_key() now only accepts RSA keys in the PSA standard formats.
-     The undocumented ability to import other formats (PKCS#8, SubjectPublicKey,
-     PEM) accepted by the pkparse module has been removed. Applications that
-     need these formats can call mbedtls_pk_parse_{public,}key() followed by
-     mbedtls_pk_import_into_psa().
-
-Changes
-   * RSA support in PSA no longer auto-enables the pkparse and pkwrite modules,
-     saving code size when those are not otherwise enabled.
diff --git a/ChangeLog.d/8726.txt b/ChangeLog.d/8726.txt
deleted file mode 100644
index c1e5a40..0000000
--- a/ChangeLog.d/8726.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Features
-   * Add partial platform support for z/OS.
diff --git a/ChangeLog.d/8799.txt b/ChangeLog.d/8799.txt
deleted file mode 100644
index 50e7c11..0000000
--- a/ChangeLog.d/8799.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * mbedtls_pem_read_buffer() now performs a check on the padding data of
-     decrypted keys and it rejects invalid ones.
diff --git a/ChangeLog.d/8824.txt b/ChangeLog.d/8824.txt
deleted file mode 100644
index abc305f..0000000
--- a/ChangeLog.d/8824.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Bugfix
-   * Fix mbedtls_pk_sign(), mbedtls_pk_verify(), mbedtls_pk_decrypt() and
-     mbedtls_pk_encrypt() on non-opaque RSA keys to honor the padding mode in
-     the RSA context. Before, if MBEDTLS_USE_PSA_CRYPTO was enabled, they always
-     used PKCS#1 v1.5 even when the RSA context was configured for PKCS#1 v2.1
-     (PSS/OAEP). Fixes #8824.
-
diff --git a/ChangeLog.d/8848.txt b/ChangeLog.d/8848.txt
deleted file mode 100644
index 71bb7e3..0000000
--- a/ChangeLog.d/8848.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Removals
-   * Temporary function mbedtls_pk_wrap_as_opaque() is removed. To mimic the
-     same behavior mbedtls_pk_get_psa_attributes() and
-     mbedtls_pk_import_into_psa() can be used to import a PK key into PSA,
-     while mbedtls_pk_setup_opaque() can be used to wrap a PSA key into a opaque
-     PK context.
diff --git a/ChangeLog.d/add-aes-cbc-to-pkcs5-pbes2.txt b/ChangeLog.d/add-aes-cbc-to-pkcs5-pbes2.txt
deleted file mode 100644
index 7f0fbc7..0000000
--- a/ChangeLog.d/add-aes-cbc-to-pkcs5-pbes2.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add support for using AES-CBC 128, 192, and 256 bit schemes
-     with PKCS#5 PBES2. Keys encrypted this way can now be parsed by PK parse.
diff --git a/ChangeLog.d/add-block-cipher-no-decrypt.txt b/ChangeLog.d/add-block-cipher-no-decrypt.txt
deleted file mode 100644
index d05bf86..0000000
--- a/ChangeLog.d/add-block-cipher-no-decrypt.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Features
-   * Enable the new option MBEDTLS_BLOCK_CIPHER_NO_DECRYPT to omit
-     the decryption direction of block ciphers (AES, ARIA, Camellia).
-     This affects both the low-level modules and the high-level APIs
-     (the cipher and PSA interfaces). This option is incompatible with modes
-     that use the decryption direction (ECB in PSA, CBC, XTS, KW) and with DES.
diff --git a/ChangeLog.d/add-psa-example-program-hash.txt b/ChangeLog.d/add-psa-example-program-hash.txt
deleted file mode 100644
index ba4da20..0000000
--- a/ChangeLog.d/add-psa-example-program-hash.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Features
-   * Added an example program showing how to hash with the PSA API.
diff --git a/ChangeLog.d/add-record-size-limit-extension-support.txt b/ChangeLog.d/add-record-size-limit-extension-support.txt
deleted file mode 100644
index 3562b85..0000000
--- a/ChangeLog.d/add-record-size-limit-extension-support.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Features
-   * Add support for record size limit extension as defined by RFC 8449
-     and configured with MBEDTLS_SSL_RECORD_SIZE_LIMIT.
-     Application data sent and received will be fragmented according to
-     Record size limits negotiated during handshake.
diff --git a/ChangeLog.d/add_get_ecp_group_id.txt b/ChangeLog.d/add_get_ecp_group_id.txt
deleted file mode 100644
index 3328062..0000000
--- a/ChangeLog.d/add_get_ecp_group_id.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add new accessor to expose the private group id member of
-     `mbedtls_ecdh_context` structure.
diff --git a/ChangeLog.d/armv8-aesce.txt b/ChangeLog.d/armv8-aesce.txt
deleted file mode 100644
index ec5889c..0000000
--- a/ChangeLog.d/armv8-aesce.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Support use of Armv8-A Cryptographic Extensions for hardware acclerated
-     AES when compiling for Thumb (T32) or 32-bit Arm (A32).
diff --git a/ChangeLog.d/asn1-missing-guard-in-rsa.txt b/ChangeLog.d/asn1-missing-guard-in-rsa.txt
new file mode 100644
index 0000000..bb5b470
--- /dev/null
+++ b/ChangeLog.d/asn1-missing-guard-in-rsa.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * MBEDTLS_ASN1_PARSE_C and MBEDTLS_ASN1_WRITE_C are now automatically enabled
+     as soon as MBEDTLS_RSA_C is enabled. Fixes #9041.
diff --git a/ChangeLog.d/benchmark-ecdh.txt b/ChangeLog.d/benchmark-ecdh.txt
deleted file mode 100644
index ef243b8..0000000
--- a/ChangeLog.d/benchmark-ecdh.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * The benchmark program now reports times for both ephemeral and static
-     ECDH in all ECDH configurations.
diff --git a/ChangeLog.d/ctr-perf.txt b/ChangeLog.d/ctr-perf.txt
deleted file mode 100644
index bc04080..0000000
--- a/ChangeLog.d/ctr-perf.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Improve performance of AES-GCM, AES-CTR and CTR-DRBG when
-     hardware accelerated AES is not present (around 13-23% on 64-bit Arm).
diff --git a/ChangeLog.d/domain_parameters.txt b/ChangeLog.d/domain_parameters.txt
deleted file mode 100644
index d860cc4..0000000
--- a/ChangeLog.d/domain_parameters.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-New deprecations
-   * In the PSA API, domain parameters are no longer used for anything.
-     They are deprecated and will be removed in a future version of the
-     library.
-
-Removals
-   * In the PSA API, the experimental way to encode the public exponent of
-     an RSA key as a domain parameter is no longer supported. Use
-     psa_generate_key_ext() instead.
diff --git a/ChangeLog.d/driver-only-cipher.txt b/ChangeLog.d/driver-only-cipher.txt
deleted file mode 100644
index 331b2f9..0000000
--- a/ChangeLog.d/driver-only-cipher.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Features
-   * If a cipher or AEAD mechanism has a PSA driver, you can now build the
-     library without the corresponding built-in implementation. Generally
-     speaking that requires both the key type and algorithm to be accelerated
-     or they'll both be built in. However, for CCM and GCM the built-in
-     implementation is able to take advantage of a driver that only
-     accelerates the key type (that is, the block cipher primitive). See
-     docs/driver-only-builds.md for full details and current limitations.
-   * The CTR_DRBG module will now use AES from a PSA driver if MBEDTLS_AES_C is
-     disabled. This requires PSA_WANT_ALG_ECB_NO_PADDING in addition to
-     MBEDTLS_PSA_CRYPTO_C and PSA_WANT_KEY_TYPE_AES.
diff --git a/ChangeLog.d/ecp-keypair-utilities.txt b/ChangeLog.d/ecp-keypair-utilities.txt
deleted file mode 100644
index 6f9714a..0000000
--- a/ChangeLog.d/ecp-keypair-utilities.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Features
-   * Add utility functions to manipulate mbedtls_ecp_keypair objects, filling
-     gaps made by making its fields private: mbedtls_ecp_set_public_key(),
-     mbedtls_ecp_write_public_key(), mbedtls_ecp_keypair_calc_public(),
-     mbedtls_ecp_keypair_get_group_id(). Fixes #5017, #5441, #8367, #8652.
diff --git a/ChangeLog.d/ecp_write_key.txt b/ChangeLog.d/ecp_write_key.txt
deleted file mode 100644
index 73354c8..0000000
--- a/ChangeLog.d/ecp_write_key.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-Features
-   * The new function mbedtls_ecp_write_key_ext() is similar to
-     mbedtls_ecp_write_key(), but can be used without separately calculating
-     the output length.
-
-New deprecations
-   * mbedtls_ecp_write_key() is deprecated in favor of
-     mbedtls_ecp_write_key_ext().
diff --git a/ChangeLog.d/fix-cmake-3rdparty-custom-config.txt b/ChangeLog.d/fix-cmake-3rdparty-custom-config.txt
deleted file mode 100644
index ec543aa..0000000
--- a/ChangeLog.d/fix-cmake-3rdparty-custom-config.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix the build with CMake when Everest or P256-m is enabled through
-     a user configuration file or the compiler command line. Fixes #8165.
diff --git a/ChangeLog.d/fix-compilation-when-memcpy-is-function-like-macro.txt b/ChangeLog.d/fix-compilation-when-memcpy-is-function-like-macro.txt
new file mode 100644
index 0000000..11e7d25
--- /dev/null
+++ b/ChangeLog.d/fix-compilation-when-memcpy-is-function-like-macro.txt
@@ -0,0 +1,2 @@
+Bugfix
+   * Fix compilation error when memcpy() is a function-like macros. Fixes #8994.
diff --git a/ChangeLog.d/fix-concurrently-loading-non-existent-keys.txt b/ChangeLog.d/fix-concurrently-loading-non-existent-keys.txt
new file mode 100644
index 0000000..8a406a1
--- /dev/null
+++ b/ChangeLog.d/fix-concurrently-loading-non-existent-keys.txt
@@ -0,0 +1,4 @@
+Bugfix
+   * Fix rare concurrent access bug where attempting to operate on a
+     non-existent key while concurrently creating a new key could potentially
+     corrupt the key store.
diff --git a/ChangeLog.d/fix-cpp-compilation-error.txt b/ChangeLog.d/fix-cpp-compilation-error.txt
deleted file mode 100644
index 32d86dc..0000000
--- a/ChangeLog.d/fix-cpp-compilation-error.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix compilation error in C++ programs when MBEDTLS_ASN1_PARSE_C is
-     disabled.
diff --git a/ChangeLog.d/fix-csr-parsing-with-critical-fields-fails.txt b/ChangeLog.d/fix-csr-parsing-with-critical-fields-fails.txt
deleted file mode 100644
index 5b15512..0000000
--- a/ChangeLog.d/fix-csr-parsing-with-critical-fields-fails.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Features
-   * Add new mbedtls_x509_csr_parse_der_with_ext_cb() routine which allows
-     parsing unsupported certificate extensions via user provided callback.
-
-Bugfix
-   * Fix parsing of CSRs with critical extensions.
diff --git a/ChangeLog.d/fix-issue-x509-cert_req.txt b/ChangeLog.d/fix-issue-x509-cert_req.txt
deleted file mode 100644
index 3a5171b..0000000
--- a/ChangeLog.d/fix-issue-x509-cert_req.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix possible NULL dereference issue in X509 cert_req program if an entry
-     in the san parameter is not separated by a colon.
diff --git a/ChangeLog.d/fix-issue-x509-cert_write.txt b/ChangeLog.d/fix-issue-x509-cert_write.txt
deleted file mode 100644
index 43d67c2..0000000
--- a/ChangeLog.d/fix-issue-x509-cert_write.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix possible NULL dereference issue in X509 cert_write program if an entry
-     in the san parameter is not separated by a colon.
diff --git a/ChangeLog.d/fix-linux-builds-in-conda-forge.txt b/ChangeLog.d/fix-linux-builds-in-conda-forge.txt
deleted file mode 100644
index 5cfee85..0000000
--- a/ChangeLog.d/fix-linux-builds-in-conda-forge.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Bugfix
-   * Fix build failure in conda-forge.  Fixes #8422.
diff --git a/ChangeLog.d/fix-mingw32-build.txt b/ChangeLog.d/fix-mingw32-build.txt
deleted file mode 100644
index feef0a2..0000000
--- a/ChangeLog.d/fix-mingw32-build.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
-  * Fix an inconsistency between implementations and usages of `__cpuid`,
-    which mainly causes failures when building Windows target using
-    mingw or clang. Fixes #8334 & #8332.
diff --git a/ChangeLog.d/fix-secure-element-key-creation.txt b/ChangeLog.d/fix-secure-element-key-creation.txt
new file mode 100644
index 0000000..23a46c0
--- /dev/null
+++ b/ChangeLog.d/fix-secure-element-key-creation.txt
@@ -0,0 +1,5 @@
+Bugfix
+   * Fix error handling when creating a key in a dynamic secure element
+     (feature enabled by MBEDTLS_PSA_CRYPTO_SE_C). In a low memory condition,
+     the creation could return PSA_SUCCESS but using or destroying the key
+     would not work. Fixes #8537.
diff --git a/ChangeLog.d/fix-ssl-session-serialization-config.txt b/ChangeLog.d/fix-ssl-session-serialization-config.txt
deleted file mode 100644
index ca1cc81..0000000
--- a/ChangeLog.d/fix-ssl-session-serialization-config.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
-   * Fix missing bitflags in SSL session serialization headers. Their absence
-     allowed SSL sessions saved in one configuration to be loaded in a
-     different, incompatible configuration.
diff --git a/ChangeLog.d/fix-tls-SuiteB.txt b/ChangeLog.d/fix-tls-SuiteB.txt
deleted file mode 100644
index 0be753a..0000000
--- a/ChangeLog.d/fix-tls-SuiteB.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Remove accidental introduction of RSA signature algorithms
-     in TLS Suite B Profile. Fixes #8221.
diff --git a/ChangeLog.d/fix-tls13-server-min-version-check.txt b/ChangeLog.d/fix-tls13-server-min-version-check.txt
deleted file mode 100644
index 258ec6d..0000000
--- a/ChangeLog.d/fix-tls13-server-min-version-check.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix TLS server accepting TLS 1.2 handshake while TLS 1.2
-     is disabled at runtime. Fixes #8593.
diff --git a/ChangeLog.d/fix_kdf_incorrect_initial_capacity.txt b/ChangeLog.d/fix_kdf_incorrect_initial_capacity.txt
deleted file mode 100644
index 10e2795..0000000
--- a/ChangeLog.d/fix_kdf_incorrect_initial_capacity.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Correct initial capacities for key derivation algorithms:TLS12_PRF,
-     TLS12_PSK_TO_MS, PBKDF2-HMAC, PBKDF2-CMAC
diff --git a/ChangeLog.d/fix_ubsan_mp_aead_gcm.txt b/ChangeLog.d/fix_ubsan_mp_aead_gcm.txt
new file mode 100644
index 0000000..e4726a4
--- /dev/null
+++ b/ChangeLog.d/fix_ubsan_mp_aead_gcm.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix undefined behaviour (incrementing a NULL pointer by zero length) when
+     passing in zero length additional data to multipart AEAD.
diff --git a/ChangeLog.d/gcm-large-tables.txt b/ChangeLog.d/gcm-large-tables.txt
deleted file mode 100644
index f9bba5b..0000000
--- a/ChangeLog.d/gcm-large-tables.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Features
-    * Add support for 8-bit GCM tables for Shoup's algorithm to speedup GCM
-      operations when hardware accelerated AES is not present. Improves
-      performance by around 30% on 64-bit Intel; 125% on Armv7-M.
diff --git a/ChangeLog.d/gen-key-segfault.txt b/ChangeLog.d/gen-key-segfault.txt
deleted file mode 100644
index fefc702..0000000
--- a/ChangeLog.d/gen-key-segfault.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Avoid segmentation fault caused by releasing not initialized
-     entropy resource in gen_key example. Fixes #8809.
diff --git a/ChangeLog.d/get_ticket_creation_time.txt b/ChangeLog.d/get_ticket_creation_time.txt
deleted file mode 100644
index 7b5166c..0000000
--- a/ChangeLog.d/get_ticket_creation_time.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add getter (mbedtls_ssl_session_get_ticket_creation_time()) to access
-     `mbedtls_ssl_session.ticket_creation_time`.
diff --git a/ChangeLog.d/gnutls_anti_replay_fail.txt b/ChangeLog.d/gnutls_anti_replay_fail.txt
deleted file mode 100644
index cb35284..0000000
--- a/ChangeLog.d/gnutls_anti_replay_fail.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
-    * Switch to milliseconds as the unit for ticket creation and reception time
-      instead of seconds. That avoids rounding errors when computing the age of
-      tickets compared to peer using a millisecond clock (observed with GnuTLS).
-      Fixes #6623.
diff --git a/ChangeLog.d/iar-gcc-perf.txt b/ChangeLog.d/iar-gcc-perf.txt
deleted file mode 100644
index fb0fbb1..0000000
--- a/ChangeLog.d/iar-gcc-perf.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Features
-   * Improve performance for gcc (versions older than 9.3.0) and IAR.
diff --git a/ChangeLog.d/linux-aarch64-hwcap.txt b/ChangeLog.d/linux-aarch64-hwcap.txt
deleted file mode 100644
index 23af878..0000000
--- a/ChangeLog.d/linux-aarch64-hwcap.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
-   * On Linux on ARMv8, fix a build error with SHA-256 and SHA-512
-     acceleration detection when the libc headers do not define the
-     corresponding constant. Reported by valord577.
diff --git a/ChangeLog.d/mbedtls_pk_import_into_psa.txt b/ChangeLog.d/mbedtls_pk_import_into_psa.txt
deleted file mode 100644
index c294f44..0000000
--- a/ChangeLog.d/mbedtls_pk_import_into_psa.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Features
-   * The new functions mbedtls_pk_get_psa_attributes() and
-     mbedtls_pk_import_into_psa() provide a uniform way to create a PSA
-     key from a PK key.
diff --git a/ChangeLog.d/move-mbedtls-ecc-psa-helpers.txt b/ChangeLog.d/move-mbedtls-ecc-psa-helpers.txt
deleted file mode 100644
index 85d970c..0000000
--- a/ChangeLog.d/move-mbedtls-ecc-psa-helpers.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Changes
-    * Moved declaration of functions mbedtls_ecc_group_to_psa and
-      mbedtls_ecc_group_of_psa from psa/crypto_extra.h to mbedtls/psa_util.h
diff --git a/ChangeLog.d/no-cipher.txt b/ChangeLog.d/no-cipher.txt
deleted file mode 100644
index 87f2f6d..0000000
--- a/ChangeLog.d/no-cipher.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-Features
-   * Fewer modules depend on MBEDTLS_CIPHER_C, making it possible to save code
-     size by disabling it in more circumstances. In particular, the CCM and
-     GCM modules no longer depend on MBEDTLS_CIPHER_C. Also,
-     MBEDTLS_PSA_CRYPTO can now be enabled without MBEDTLS_CIPHER_C if all
-     unauthenticated (non-AEAD) ciphers are disabled, or if they're all
-     fully provided by drivers. See docs/driver-only-builds.md for full
-     details and current limitations; in particular, NIST_KW and PKCS5/PKCS12
-     decryption still unconditionally depend on MBEDTLS_CIPHER_C.
diff --git a/ChangeLog.d/non-psa-pk-implementation.txt b/ChangeLog.d/non-psa-pk-implementation.txt
deleted file mode 100644
index 535bbf5..0000000
--- a/ChangeLog.d/non-psa-pk-implementation.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Changes
-   * mbedtls_pk_sign_ext() is now always available, not just when
-     PSA (MBEDTLS_PSA_CRYPTO_C) is enabled.
diff --git a/ChangeLog.d/pkg-config-files-addition.txt b/ChangeLog.d/pkg-config-files-addition.txt
deleted file mode 100644
index e459470..0000000
--- a/ChangeLog.d/pkg-config-files-addition.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Features
-   * Add pc files for pkg-config, e.g.:
-     pkg-config --cflags --libs (mbedtls|mbedcrypto|mbedx509)
-
diff --git a/ChangeLog.d/pkwrite-pem-use-heap.txt b/ChangeLog.d/pkwrite-pem-use-heap.txt
deleted file mode 100644
index 11db7b6..0000000
--- a/ChangeLog.d/pkwrite-pem-use-heap.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Changes
-   * Use heap memory to allocate DER encoded public/private key.
-     This reduces stack usage significantly for writing a public/private
-     key to a PEM string.
diff --git a/ChangeLog.d/psa_generate_key_ext.txt b/ChangeLog.d/psa_generate_key_ext.txt
deleted file mode 100644
index 8340f01..0000000
--- a/ChangeLog.d/psa_generate_key_ext.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * The new function psa_generate_key_ext() allows generating an RSA
-     key pair with a custom public exponent.
diff --git a/ChangeLog.d/rename-conf-early-data-API.txt b/ChangeLog.d/rename-conf-early-data-API.txt
deleted file mode 100644
index d436811..0000000
--- a/ChangeLog.d/rename-conf-early-data-API.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-API changes
-   * Remove `tls13_` in mbedtls_ssl_tls13_conf_early_data() and
-     mbedtls_ssl_tls13_conf_max_early_data_size() API names. Early data
-     feature may not be TLS 1.3 specific in the future. Fixes #6909.
diff --git a/ChangeLog.d/rsa-bitlen.txt b/ChangeLog.d/rsa-bitlen.txt
deleted file mode 100644
index bcd185f..0000000
--- a/ChangeLog.d/rsa-bitlen.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Bugfix
-   * Fix mbedtls_pk_get_bitlen() for RSA keys whose size is not a
-     multiple of 8. Fixes #868.
-
-Features
-   * The new function mbedtls_rsa_get_bitlen() returns the length of the modulus
-     in bits, i.e. the key size for an RSA key.
diff --git a/ChangeLog.d/sha256-armce-arm.txt b/ChangeLog.d/sha256-armce-arm.txt
deleted file mode 100644
index 5b18eb3..0000000
--- a/ChangeLog.d/sha256-armce-arm.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Features
-    * Support Armv8-A Crypto Extension acceleration for SHA-256
-      when compiling for Thumb (T32) or 32-bit Arm (A32).
-New deprecations
-    * Rename the MBEDTLS_SHA256_USE_A64_CRYPTO_xxx config options to
-      MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_xxx. The old names may still
-      be used, but are deprecated.
diff --git a/ChangeLog.d/tls13-without-tickets.txt b/ChangeLog.d/tls13-without-tickets.txt
new file mode 100644
index 0000000..8ceef21
--- /dev/null
+++ b/ChangeLog.d/tls13-without-tickets.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix TLS 1.3 client build and runtime when support for session tickets is
+     disabled (MBEDTLS_SSL_SESSION_TICKETS configuration option). Fixes #6395.
diff --git a/ChangeLog.d/x509-add-ca_istrue.txt b/ChangeLog.d/x509-add-ca_istrue.txt
deleted file mode 100644
index c950dbc..0000000
--- a/ChangeLog.d/x509-add-ca_istrue.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Features
-   * Add new accessor to expose the `MBEDTLS_PRIVATE(ca_istrue)` member of
-     `mbedtls_x509_crt` structure. This requires setting
-     the MBEDTLS_X509_EXT_BASIC_CONSTRAINTS bit in the certificate's
-     ext_types field.
diff --git a/Makefile b/Makefile
index 885948c..fb80529 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,20 @@
 PREFIX=mbedtls_
 PERL ?= perl
 
+ifneq (,$(filter-out lib library/%,$(or $(MAKECMDGOALS),all)))
+    ifeq (,$(wildcard framework/exported.make))
+        # Use the define keyword to get a multi-line message.
+        # GNU make appends ".  Stop.", so tweak the ending of our message accordingly.
+        define error_message
+$(MBEDTLS_PATH)/framework/exported.make not found.
+Run `git submodule update --init` to fetch the submodule contents.
+This is a fatal error
+        endef
+        $(error $(error_message))
+    endif
+    include framework/exported.make
+endif
+
 .SILENT:
 
 .PHONY: all no_test programs lib tests install uninstall clean test check lcov apidoc apidoc_clean
@@ -60,7 +74,7 @@
 endif
 
 .PHONY: visualc_files
-VISUALC_FILES = visualc/VS2013/mbedTLS.sln visualc/VS2013/mbedTLS.vcxproj
+VISUALC_FILES = visualc/VS2017/mbedTLS.sln visualc/VS2017/mbedTLS.vcxproj
 # TODO: $(app).vcxproj for each $(app) in programs/
 visualc_files: $(VISUALC_FILES)
 
@@ -69,9 +83,9 @@
 # they just need to be present.
 $(VISUALC_FILES): | library/generated_files
 $(VISUALC_FILES): $(gen_file_dep) scripts/generate_visualc_files.pl
-$(VISUALC_FILES): $(gen_file_dep) scripts/data_files/vs2013-app-template.vcxproj
-$(VISUALC_FILES): $(gen_file_dep) scripts/data_files/vs2013-main-template.vcxproj
-$(VISUALC_FILES): $(gen_file_dep) scripts/data_files/vs2013-sln-template.sln
+$(VISUALC_FILES): $(gen_file_dep) scripts/data_files/vs2017-app-template.vcxproj
+$(VISUALC_FILES): $(gen_file_dep) scripts/data_files/vs2017-main-template.vcxproj
+$(VISUALC_FILES): $(gen_file_dep) scripts/data_files/vs2017-sln-template.sln
 # TODO: also the list of .c and .h source files, but not their content
 $(VISUALC_FILES):
 	echo "  Gen   $@ ..."
@@ -147,10 +161,10 @@
 	$(MAKE) -C programs neat
 	$(MAKE) -C tests neat
 ifndef WINDOWS
-	rm -f visualc/VS2013/*.vcxproj visualc/VS2013/mbedTLS.sln
+	rm -f visualc/VS2017/*.vcxproj visualc/VS2017/mbedTLS.sln
 else
-	if exist visualc\VS2013\*.vcxproj del /Q /F visualc\VS2013\*.vcxproj
-	if exist visualc\VS2013\mbedTLS.sln del /Q /F visualc\VS2013\mbedTLS.sln
+	if exist visualc\VS2017\*.vcxproj del /Q /F visualc\VS2017\*.vcxproj
+	if exist visualc\VS2017\mbedTLS.sln del /Q /F visualc\VS2017\mbedTLS.sln
 endif
 
 check: lib tests
diff --git a/README.md b/README.md
index 2505d8f..b70c67e 100644
--- a/README.md
+++ b/README.md
@@ -47,13 +47,17 @@
 You need the following tools to build the library with the provided makefiles:
 
 * GNU Make 3.82 or a build tool that CMake supports.
-* A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, IAR 8 and Visual Studio 2013. More recent versions should work. Slightly older versions may work.
+* A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, Arm Compiler 6, IAR 8 and Visual Studio 2017. More recent versions should work. Slightly older versions may work.
 * Python 3.8 to generate the test code. Python is also needed to integrate PSA drivers and to build the development branch (see next section).
 * Perl to run the tests, and to generate some source files in the development branch.
 * CMake 3.10.2 or later (if using CMake).
-* Microsoft Visual Studio 2013 or later (if using Visual Studio).
+* Microsoft Visual Studio 2017 or later (if using Visual Studio).
 * Doxygen 1.8.11 or later (if building the documentation; slightly older versions should work).
 
+### Git usage
+
+The `development` branch and the `mbedtls-3.6` long-term support branch of Mbed TLS use a [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules#_cloning_submodules) ([framework](https://github.com/Mbed-TLS/mbedtls-framework)). This is not needed to merely compile the library at a release tag. This is not needed to consume a release archive (zip or tar).
+
 ### Generated source files in the development branch
 
 The source code of Mbed TLS includes some files that are automatically generated by scripts and whose content depends only on the Mbed TLS source, not on the platform or on the library configuration. These files are not included in the development branch of Mbed TLS, but the generated files are included in official releases. This section explains how to generate the missing files in the development branch.
@@ -221,7 +225,7 @@
 
 ### Microsoft Visual Studio
 
-The build files for Microsoft Visual Studio are generated for Visual Studio 2013.
+The build files for Microsoft Visual Studio are generated for Visual Studio 2017.
 
 The solution file `mbedTLS.sln` contains all the basic projects needed to build the library and all the programs. The files in tests are not generated and compiled, as these need Python and perl environments as well. However, the selftest program in `programs/test/` is still available.
 
@@ -246,7 +250,7 @@
 -   `tests/scripts/depends.py` test builds in configurations with a single curve, key exchange, hash, cipher, or pkalg on.
 -   `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `mbedtls_config.h`, etc).
 
-Instead of manually installing the required versions of all tools required for testing, it is possible to use the Docker images from our CI systems, as explained in [our testing infrastructure repository](https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start).
+Instead of manually installing the required versions of all tools required for testing, it is possible to use the Docker images from our CI systems, as explained in [our testing infrastructure repository](https://github.com/Mbed-TLS/mbedtls-test/blob/main/README.md#quick-start).
 
 Porting Mbed TLS
 ----------------
diff --git a/docs/architecture/Makefile b/docs/architecture/Makefile
index 6252ab0..5bee504 100644
--- a/docs/architecture/Makefile
+++ b/docs/architecture/Makefile
@@ -2,20 +2,7 @@
 
 default: all
 
-all_markdown = \
-               alternative-implementations.md \
-               mbed-crypto-storage-specification.md \
-               psa-crypto-implementation-structure.md \
-               psa-migration/psa-limitations.md \
-               psa-migration/strategy.md \
-               psa-migration/tasks-g2.md \
-               psa-migration/testing.md \
-               testing/driver-interface-test-strategy.md \
-               testing/invasive-testing.md \
-               testing/psa-storage-format-testing.md \
-               testing/test-framework.md \
-               tls13-support.md \
-	       # This line is intentionally left blank
+all_markdown = $(wildcard *.md */*.md)
 
 html: $(all_markdown:.md=.html)
 pdf: $(all_markdown:.md=.pdf)
diff --git a/docs/architecture/psa-shared-memory.md b/docs/architecture/psa-shared-memory.md
new file mode 100644
index 0000000..ef3a6b0
--- /dev/null
+++ b/docs/architecture/psa-shared-memory.md
@@ -0,0 +1,685 @@
+PSA API functions and shared memory
+===================================
+
+## Introduction
+
+This document discusses the security architecture of systems where PSA API functions might receive arguments that are in memory that is shared with an untrusted process. On such systems, the untrusted process might access a shared memory buffer while the cryptography library is using it, and thus cause unexpected behavior in the cryptography code.
+
+### Core assumptions
+
+We assume the following scope limitations:
+
+* Only PSA Crypto API functions are in scope (including Mbed TLS extensions to the official API specification). Legacy crypto, X.509, TLS, or any other function which is not called `psa_xxx` is out of scope.
+* We only consider [input buffers](https://arm-software.github.io/psa-api/crypto/1.1/overview/conventions.html#input-buffer-sizes) and [output buffers](https://arm-software.github.io/psa-api/crypto/1.1/overview/conventions.html#output-buffer-sizes). Any other data is assumed to be in non-shared memory.
+
+## System architecture discussion
+
+### Architecture overview
+
+We consider a system that has memory separation between partitions: a partition can't access another partition's memory directly. Partitions are meant to be isolated from each other: a partition may only affect the integrity of another partition via well-defined system interfaces. For example, this can be a Unix/POSIX-like system that isolates processes, or isolation between the secure world and the non-secure world relying on a mechanism such as TrustZone, or isolation between secure-world applications on such a system.
+
+More precisely, we consider such a system where our PSA Crypto implementation is running inside one partition, called the **crypto service**. The crypto service receives remote procedure calls (RPC) from other partitions, validates their arguments (e.g. validation of key identifier ownership), and calls a PSA Crypto API function. This document is concerned with environments where the arguments passed to a PSA Crypto API function may be in shared memory (as opposed to environments where the inputs are always copied into memory that is solely accessible by the crypto service before calling the API function, and likewise with output buffers after the function returns).
+
+When the data is accessible to another partition, there is a risk that this other partition will access it while the crypto implementation is working. Although this could be prevented by suspending the whole system while crypto is working, such a limitation is rarely desirable and most systems don't offer a way to do it. (Even systems that have absolute thread priorities, and where crypto has a higher priority than any untrusted partition, may be vulnerable due to having multiple cores or asynchronous data transfers with peripherals.)
+
+The crypto service must guarantee that it behaves as if the rest of the world was suspended while it is executed. A behavior that is only possible if an untrusted entity accesses a buffer while the crypto service is processing the data is a security violation.
+
+### Risks and vulnerabilities
+
+We consider a security architecture with two or three entities:
+
+* a crypto service, which offers PSA crypto API calls over RPC (remote procedure call) using shared memory for some input or output arguments;
+* a client of the crypto service, which makes a RPC to the crypto service;
+* in some scenarios, a client of the client, which makes a RPC to the crypto client which re-shares the memory with the crypto service.
+
+The behavior of RPC is defined for in terms of values of inputs and outputs. This models an ideal world where the content of input and output buffers is not accessible outside the crypto service while it is processing an RPC. It is a security violation if the crypto service behaves in a way that cannot be achieved by setting the inputs before the RPC call, and reading the outputs after the RPC call is finished.
+
+#### Read-read inconsistency
+
+If an input argument is in shared memory, there is a risk of a **read-read inconsistency**:
+
+1. The crypto code reads part of the input and validates it, or injects it into a calculation.
+2. The client (or client's client) modifies the input.
+3. The crypto code reads the same part again, and performs an action which would be impossible if the input had had the same value all along.
+
+Vulnerability example (parsing): suppose the input contains data with a type-length-value or length-value encoding (for example, importing an RSA key). The crypto code reads the length field and checks that it fits within the buffer. (This could be the length of the overall data, or the length of an embedded field) Later, the crypto code reads the length again and uses it without validation. A malicious client can modify the length field in the shared memory between the two reads and thus cause a buffer overread on the second read.
+
+Vulnerability example (dual processing): consider an RPC to perform authenticated encryption, using a mechanism with an encrypt-and-MAC structure. The authenticated encryption implementation separately calculates the ciphertext and the MAC from the plaintext. A client sets the plaintext input to `"PPPP"`, then starts the RPC call, then changes the input buffer to `"QQQQ"` while the crypto service is working.
+
+* Any of `enc("PPPP")+mac("PPPP")`, `enc("PPQQ")+mac("PPQQ")` or `enc("QQQQ")+mac("QQQQ")` are valid outputs: they are outputs that can be produced by this authenticated encryption RPC.
+* If the authenticated encryption calculates the ciphertext before the client changes the output buffer and calculates the MAC after that change, reading the input buffer again each time, the output will be `enc("PPPP")+mac("QQQQ")`. There is no input that can lead to this output, hence this behavior violates the security guarantees of the crypto service.
+
+#### Write-read inconsistency
+
+If an output argument is in shared memory, there is a risk of a **write-read inconsistency**:
+
+1. The crypto code writes some intermediate data into the output buffer.
+2. The client (or client's client) modifies the intermediate data.
+3. The crypto code reads the intermediate data back and continues the calculation, leading to an outcome that would not be possible if the intermediate data had not been modified.
+
+Vulnerability example: suppose that an RSA signature function works by formatting the data in place in the output buffer, then applying the RSA private-key operation in place. (This is how `mbedtls_rsa_pkcs1_sign` works.) A malicious client may write badly formatted data into the buffer, so that the private-key operation is not a valid signature (e.g. it could be a decryption), violating the RSA key's usage policy.
+
+Vulnerability example with chained calls: we consider the same RSA signature operation as before. In this example, we additionally assume that the data to sign comes from an attestation application which signs some data on behalf of a final client: the key and the data to sign are under the attestation application's control, and the final client must not be able to obtain arbitrary signatures. The final client shares an output buffer for the signature with the attestation application, and the attestation application re-shares this buffer with the crypto service. A malicious final client can modify the intermediate data and thus sign arbitrary data.
+
+#### Write-write disclosure
+
+If an output argument is in shared memory, there is a risk of a **write-write disclosure**:
+
+1. The crypto code writes some intermediate data into the output buffer. This intermediate data must remain confidential.
+2. The client (or client's client) reads the intermediate data.
+3. The crypto code overwrites the intermediate data.
+
+Vulnerability example with chained calls (temporary exposure): an application encrypts some data, and lets its clients store the ciphertext. Clients may not have access to the plaintext. To save memory, when it calls the crypto service, it passes an output buffer that is in the final client's memory. Suppose the encryption mechanism works by copying its input to the output buffer then encrypting in place (for example, to simplify considerations related to overlap, or because the implementation relies on a low-level API that works in place). In this scenario, the plaintext is exposed to the final client while the encryption in progress, which violates the confidentiality of the plaintext.
+
+Vulnerability example with chained calls (backtrack): we consider a provisioning application that provides a data encryption service on behalf of multiple clients, using a single shared key. Clients are not allowed to access each other's data. The provisioning application isolates clients by including the client identity in the associated data. Suppose that an AEAD decryption function processes the ciphertext incrementally by simultaneously writing the plaintext to the output buffer and calculating the tag. (This is how AEAD decryption usually works.) At the end, if the tag is wrong, the decryption function wipes the output buffer. Assume that the output buffer for the plaintext is shared from the client to the provisioning application, which re-shares it with the crypto service. A malicious client can read another client (the victim)'s encrypted data by passing the ciphertext to the provisioning application, which will attempt to decrypt it with associated data identifying the requesting client. Although the operation will fail beacuse the tag is wrong, the malicious client still reads the victim plaintext.
+
+#### Write-read feedback
+
+If a function both has an input argument and an output argument in shared memory, and processes its input incrementally to emit output incrementally, the following sequence of events is possible:
+
+1. The crypto code processes part of the input and writes the corresponding part of the output.
+2. The client reads the early output and uses that to calculate the next part of the input.
+3. The crypto code processes the rest of the input.
+
+There are cryptographic mechanisms for which this breaks security properties. An example is [CBC encryption](https://link.springer.com/content/pdf/10.1007/3-540-45708-9_2.pdf): if the client can choose the content of a plaintext block after seeing the immediately preceding ciphertext block, this gives the client a decryption oracle. This is a security violation if the key policy only allowed the client to encrypt, not to decrypt.
+
+TODO: is this a risk we want to take into account? Although this extends the possible behaviors of the one-shot interface, the client can do the same thing legitimately with the multipart interface.
+
+### Possible countermeasures
+
+In this section, we briefly discuss generic countermeasures.
+
+#### Copying
+
+Copying is a valid countermeasure. It is conceptually simple. However, it is often unattractive because it requires additional memory and time.
+
+Note that although copying is very easy to write into a program, there is a risk that a compiler (especially with whole-program optimization) may optimize the copy away, if it does not understand that copies between shared memory and non-shared memory are semantically meaningful.
+
+Example: the PSA Firmware Framework 1.0 forbids shared memory between partitions. This restriction is lifted in version 1.1 due to concerns over RAM usage.
+
+#### Careful accesses
+
+The following rules guarantee that shared memory cannot result in a security violation other than [write-read feedback](#write-read-feedback):
+
+* Never read the same input twice at the same index.
+* Never read back from an output.
+* Never write to the output twice at the same index.
+    * This rule can usefully be relaxed in many circumstances. It is ok to write data that is independent of the inputs (and not otherwise confidential), then overwrite it. For example, it is ok to zero the output buffer before starting to process the input.
+
+These rules are very difficult to enforce.
+
+Example: these are the rules that a GlobalPlatform TEE Trusted Application (application running on the secure side of TrustZone on Cortex-A) must follow.
+
+## Protection requirements
+
+### Responsibility for protection
+
+A call to a crypto service to perform a crypto operation involves the following components:
+
+1. The remote procedure call framework provided by the operating system.
+2. The code of the crypto service.
+3. The code of the PSA Crypto dispatch layer (also known as the core), which is provided by Mbed TLS.
+4. The driver implementing the cryptographic mechanism, which may be provided by Mbed TLS (built-in driver) or by a third-party driver.
+
+The [PSA Crypto API specification](https://arm-software.github.io/psa-api/crypto/1.1/overview/conventions.html#stability-of-parameters) puts the responsibility for protection on the implementation of the PSA Crypto API, i.e. (3) or (4).
+
+> In an environment with multiple threads or with shared memory, the implementation carefully accesses non-overlapping buffer parameters in order to prevent any security risk resulting from the content of the buffer being modified or observed during the execution of the function. (...)
+
+In Mbed TLS 2.x and 3.x up to and including 3.5.0, there is no defense against buffers in shared memory. The responsibility shifts to (1) or (2), but this is not documented.
+
+In the remainder of this chapter, we will discuss how to implement this high-level requirement where it belongs: inside the implementation of the PSA Crypto API. Note that this allows two possible levels: in the dispatch layer (independently of the implementation of each mechanism) or in the driver (specific to each implementation).
+
+#### Protection in the dispatch layer
+
+The dispatch layer has no control over how the driver layer will access buffers. Therefore the only possible protection at this layer method is to ensure that drivers have no access to shared memory. This means that any buffer located in shared memory must be copied into or out of a buffer in memory owned by the crypto service (heap or stack). This adds inefficiency, mostly in terms of RAM usage.
+
+For buffers with a small static size limit, this is something we often do for convenience, especially with output buffers. However, as of Mbed TLS 3.5.0, it is not done systematically.
+
+It is ok to skip the copy if it is known for sure that a buffer is not in shared memory. However, the location of the buffer is not under the control of Mbed TLS. This means skipping the copy would have to be a compile-time or run-time option which has to be set by the application using Mbed TLS. This is both an additional maintenance cost (more code to analyze, more testing burden), and a residual security risk in case the party who is responsible for setting this option does not set it correctly. As a consequence, Mbed TLS will not offer this configurability unless there is a compelling argument.
+
+#### Protection in the driver layer
+
+Putting the responsibility for protection in the driver layer increases the overall amount of work since there are more driver implementations than dispatch implementations. (This is true even inside Mbed TLS: almost all API functions have multiple underlying implementations, one for each algorithm.) It also increases the risk to the ecosystem since some drivers might not protect correctly. Therefore having drivers be responsible for protection is only a good choice if there is a definite benefit to it, compared to allocating an internal buffer and copying. An expected benefit in some cases is that there are practical protection methods other than copying.
+
+Some cryptographic mechanisms are naturally implemented by processing the input in a single pass, with a low risk of ever reading the same byte twice, and by writing the final output directly into the output buffer. For such mechanism, it is sensible to mandate that drivers respect these rules.
+
+In the next section, we will analyze how susceptible various cryptographic mechanisms are to shared memory vulnerabilities.
+
+### Susceptibility of different mechanisms
+
+#### Operations involving small buffers
+
+For operations involving **small buffers**, the cost of copying is low. For many of those, the risk of not copying is high:
+
+* Any parsing of formatted data has a high risk of [read-read inconsistency](#read-read-inconsistency).
+* An internal review shows that for RSA operations, it is natural for an implementation to have a [write-read inconsistency](#write-read-inconsistency) or a [write-write disclosure](#write-write-disclosure).
+
+Note that in this context, a “small buffer” is one with a size limit that is known at compile time, and small enough that copying the data is not prohibitive. For example, an RSA key fits in a small buffer. A hash input is not a small buffer, even if it happens to be only a few bytes long in one particular call.
+
+The following buffers are considered small buffers:
+
+* Any input or output directly related to asymmetric cryptography (signature, encryption/decryption, key exchange, PAKE), including key import and export.
+    * Note that this does not include inputs or outputs that are not processed by an asymmetric primitives, for example the message input to `psa_sign_message` or `psa_verify_message`.
+* Cooked key derivation output.
+* The output of a hash or MAC operation.
+
+**Design decision: the dispatch layer shall copy all small buffers**.
+
+#### Symmetric cryptography inputs with small output
+
+Message inputs to hash, MAC and key derivation operations are at a low risk of [read-read inconsistency](#read-read-inconsistency) because they are unformatted data, and for all specified algorithms, it is natural to process the input one byte at a time.
+
+**Design decision: require symmetric cryptography drivers to read their input without a risk of read-read inconsistency**.
+
+TODO: what about IV/nonce inputs? They are typically small, but don't necessarily have a static size limit (e.g. GCM recommends a 12-byte nonce, but also allows large nonces).
+
+#### Key derivation outputs
+
+Key derivation typically emits its output as a stream, with no error condition detected after setup other than operational failures (e.g. communication failure with an accelerator) or running out of data to emit (which can easily be checked before emitting any data, since the data size is known in advance).
+
+(Note that this is about raw byte output, not about cooked key derivation, i.e. deriving a structured key, which is considered a [small buffer](#operations-involving-small-buffers).)
+
+**Design decision: require key derivation drivers to emit their output without reading back from the output buffer**.
+
+#### Cipher and AEAD
+
+AEAD decryption is at risk of [write-write disclosure](#write-write-disclosure) when the tag does not match.
+
+AEAD encryption and decryption are at risk of [read-read inconsistency](#read-read-inconsistency) if they process the input multiple times, which is natural in a number of cases:
+
+* when encrypting with an encrypt-and-authenticate or authenticate-then-encrypt structure (one read to calculate the authentication tag and another read to encrypt);
+* when decrypting with an encrypt-then-authenticate structure (one read to decrypt and one read to calculate the authentication tag);
+* with SIV modes (not yet present in the PSA API, but likely to come one day) (one full pass to calculate the IV, then another full pass for the core authenticated encryption);
+
+Cipher and AEAD outputs are at risk of [write-read inconsistency](#write-read-inconsistency) and [write-write disclosure](#write-write-disclosure) if they are implemented by copying the input into the output buffer with `memmove`, then processing the data in place. In particular, this approach makes it easy to fully support overlapping, since `memmove` will take care of overlapping cases correctly, which is otherwise hard to do portably (C99 does not offer an efficient, portable way to check whether two buffers overlap).
+
+**Design decision: the dispatch layer shall allocate an intermediate buffer for cipher and AEAD plaintext/ciphertext inputs and outputs**.
+
+Note that this can be a single buffer for the input and the output if the driver supports in-place operation (which it is supposed to, since it is supposed to support arbitrary overlap, although this is not always the case in Mbed TLS, a [known issue](https://github.com/Mbed-TLS/mbedtls/issues/3266)). A side benefit of doing this intermediate copy is that overlap will be supported.
+
+For all currently implemented AEAD modes, the associated data is only processed once to calculate an intermediate value of the authentication tag.
+
+**Design decision: for now, require AEAD drivers to read the additional data without a risk of read-read inconsistency**. Make a note to revisit this when we start supporting an SIV mode, at which point the dispatch layer shall copy the input for modes that are not known to be low-risk.
+
+#### Message signature
+
+For signature algorithms with a hash-and-sign framework, the input to sign/verify-message is passed to a hash, and thus can follow the same rules as [symmetric cryptography inputs with small output](#symmetric-cryptography-inputs-with-small-output). This is also true for `PSA_ALG_RSA_PKCS1V15_SIGN_RAW`, which is the only non-hash-and-sign signature mechanism implemented in Mbed TLS 3.5. This is not true for PureEdDSA (`#PSA_ALG_PURE_EDDSA`), which is not yet implemented: [PureEdDSA signature](https://www.rfc-editor.org/rfc/rfc8032#section-5.1.6) processes the message twice. (However, PureEdDSA verification only processes the message once.)
+
+**Design decision: for now, require sign/verify-message drivers to read their input without a risk of read-read inconsistency**. Make a note to revisit this when we start supporting PureEdDSA, at which point the dispatch layer shall copy the input for algorithms such as PureEdDSA that are not known to be low-risk.
+
+## Design of shared memory protection
+
+This section explains how Mbed TLS implements the shared memory protection strategy summarized below.
+
+### Shared memory protection strategy
+
+* The core (dispatch layer) shall make a copy of the following buffers, so that drivers do not receive arguments that are in shared memory:
+    * Any input or output from asymmetric cryptography (signature, encryption/decryption, key exchange, PAKE), including key import and export.
+    * Plaintext/ciphertext inputs and outputs for cipher and AEAD.
+    * The output of a hash or MAC operation.
+    * Cooked key derivation output.
+
+* A document shall explain the requirements on drivers for arguments whose access needs to be protected:
+    * Hash and MAC input.
+    * Cipher/AEAD IV/nonce (to be confirmed).
+    * AEAD associated data (to be confirmed).
+    * Key derivation input (excluding key agreement).
+    * Raw key derivation output (excluding cooked key derivation output).
+
+* The built-in implementations of cryptographic mechanisms with arguments whose access needs to be protected shall protect those arguments.
+
+Justification: see “[Susceptibility of different mechanisms](#susceptibility-of-different-mechanisms)”.
+
+### Implementation of copying
+
+Copy what needs copying. This is broadly straightforward, however there are a few things to consider.
+
+#### Compiler optimization of copies
+
+It is unclear whether the compiler will attempt to optimize away copying operations.
+
+Once the copying code is implemented, it should be evaluated to see whether compiler optimization is a problem. Specifically, for the major compilers supported by Mbed TLS:
+* Write a small program that uses a PSA function which copies inputs or outputs.
+* Build the program with link-time optimization / full-program optimization enabled (e.g. `-flto` with `gcc`). Try also enabling the most extreme optimization options such as `-Ofast` (`gcc`) and `-Oz` (`clang`).
+* Inspect the generated code with `objdump` or a similar tool to see if copying operations are preserved.
+
+If copying behaviour is preserved by all major compilers then assume that compiler optimization is not a problem.
+
+If copying behaviour is optimized away by the compiler, further investigation is needed. Experiment with using the `volatile` keyword to force the compiler not to optimize accesses to the copied buffers. If the `volatile` keyword is not sufficient, we may be able to use compiler or target-specific techniques to prevent optimization, for example memory barriers or empty `asm` blocks. These may be implemented and verified for important platforms while retaining a C implementation that is likely to be correct on most platforms as a fallback - the same approach taken by the constant-time module.
+
+**Open questions: Will the compiler optimize away copies? If so, can it be prevented from doing so in a portable way?**
+
+#### Copying code
+
+We may either copy buffers on an ad-hoc basis using `memcpy()` in each PSA function, or use a unified set of functions for copying input and output data. The advantages of the latter are obvious:
+
+* Any test hooks need only be added in one place.
+* Copying code must only be reviewed for correctness in one place, rather than in all functions where it occurs.
+* Copy bypass is simpler as we can just replace these functions with no-ops in a single place.
+* Any complexity needed to prevent the compiler optimizing copies away does not have to be duplicated.
+
+On the other hand, the only advantage of ad-hoc copying is slightly greater flexibility.
+
+**Design decision: Create a unified set of functions for copying input and output data.**
+
+#### Copying in multipart APIs
+
+Multipart APIs may follow one of 2 possible approaches for copying of input:
+
+##### 1. Allocate a buffer and copy input on each call to `update()`
+
+This is simple and mirrors the approach for one-shot APIs nicely. However, allocating memory in the middle of a multi-part operation is likely to be bad for performance. Multipart APIs are designed in part for systems that do not have time to perform an operation at once, so introducing poor performance may be a problem here.
+
+**Open question: Does memory allocation in `update()` cause a performance problem? If so, to what extent?**
+
+##### 2. Allocate a buffer at the start of the operation and subdivide calls to `update()`
+
+In this approach, input and output buffers are allocated at the start of the operation that are large enough to hold the expected average call to `update()`. When `update()` is called with larger buffers than these, the PSA API layer makes multiple calls to the driver, chopping the input into chunks of the temporary buffer size and filling the output from the results until the operation is finished.
+
+This would be more complicated than approach (1) and introduces some extra issues. For example, if one of the intermediate calls to the driver's `update()` returns an error, it is not possible for the driver's state to be rolled back to before the first call to `update()`. It is unclear how this could be solved.
+
+However, this approach would reduce memory usage in some cases and prevent memory allocation during an operation. Additionally, since the input and output buffers would be fixed-size it would be possible to allocate them statically, avoiding the need for any dynamic memory allocation at all.
+
+**Design decision: Initially use approach (1) and treat approach (2) as an optimization to be done if necessary.**
+
+### Validation of copying
+
+#### Validation of copying by review
+
+This is fairly self-explanatory. Review all functions that use shared memory and ensure that they each copy memory. This is the simplest strategy to implement but is less reliable than automated validation.
+
+#### Validation of copying with memory pools
+
+Proposed general idea: have tests where the test code calling API functions allocates memory in a certain pool, and code in the library allocates memory in a different pool. Test drivers check that needs-copying arguments are within the library pool, not within the test pool.
+
+#### Validation of copying by memory poisoning
+
+Proposed general idea: in test code, “poison” the memory area used by input and output parameters that must be copied. Poisoning means something that prevents accessing memory while it is poisoned. This could be via memory protection (allocate with `mmap` then disable access with `mprotect`), or some kind of poisoning for an analyzer such as MSan or Valgrind.
+
+In the library, the code that does the copying temporarily unpoisons the memory by calling a test hook.
+
+```c
+static void copy_to_user(void *copy_buffer, void *const input_buffer, size_t length) {
+#if defined(MBEDTLS_TEST_HOOKS)
+    if (memory_poison_hook != NULL) {
+        memory_poison_hook(copy_buffer, length);
+    }
+#endif
+    memcpy(copy_buffer, input_buffer, length);
+#if defined(MBEDTLS_TEST_HOOKS)
+    if (memory_unpoison_hook != NULL) {
+        memory_unpoison_hook(copy_buffer, length);
+    }
+#endif
+}
+```
+The reason to poison the memory before calling the library, rather than after the copy-in (and symmetrically for output buffers) is so that the test will fail if we forget to copy, or we copy the wrong thing. This would not be the case if we relied on the library's copy function to do the poisoning: that would only validate that the driver code does not access the memory on the condition that the copy is done as expected.
+
+##### Options for implementing poisoning
+
+There are several different ways that poisoning could be implemented:
+
+1. Using Valgrind's memcheck tool. Valgrind provides a macro `VALGRIND_MAKE_MEM_NO_ACCESS` that allows manual memory poisoning. Valgrind memory poisoning is already used for constant-flow testing in Mbed TLS.
+2. Using Memory Sanitizer (MSan), which allows us to mark memory as uninitialized. This is also used for constant-flow testing. It is suitable for input buffers only, since it allows us to detect when a poisoned buffer is read but not when it is written.
+3. Using Address Sanitizer (ASan). This provides `ASAN_POISON_MEMORY_REGION` which marks memory as inaccessible.
+4. Allocating buffers separate pages and calling `mprotect()` to set pages as inaccessible. This has the disadvantage that we will have to manually ensure that buffers sit in their own pages, which likely means making a copy.
+5. Filling buffers with random data, keeping a copy of the original. For input buffers, keep a copy of the original and copy it back once the PSA function returns. For output buffers, fill them with random data and keep a separate copy of it. In the memory poisoning hooks, compare the copy of random data with the original to ensure that the output buffer has not been written directly.
+
+Approach (2) is insufficient for the full testing we require as we need to be able to check both input and output buffers.
+
+Approach (5) is simple and requires no extra tooling. It is likely to have good performance as it does not use any sanitizers. However, it requires the memory poisoning test hooks to maintain extra copies of the buffers, which seems difficult to implement in practice. Additionally, it does not precisely test the property we want to validate, so we are relying on the tests to fail if given random data as input. It is possible (if unlikely) that the PSA function will access the poisoned buffer without causing the test to fail. This becomes more likely when we consider test cases that call PSA functions on incorrect inputs to check that the correct error is returned. For these reasons, this memory poisoning approach seems unsuitable.
+
+All three remaining approaches are suitable for our purposes. However, approach (4) is more complex than the other two. To implement it, we would need to allocate poisoned buffers in separate memory pages. They would require special handling and test code would likely have to be designed around this special handling.
+
+Meanwhile, approaches (1) and (3) are much more convenient. We are simply required to call a special macro on some buffer that was allocated by us and the sanitizer takes care of everything else. Of these two, ASan appears to have a limitation related to buffer alignment. From code comments quoted in [the documentation](https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning):
+
+> This function is not guaranteed to poison the whole region - it may poison only subregion of [addr, addr+size) due to ASan alignment restrictions.
+
+Specifically, ASan will round the buffer size down to 8 bytes before poisoning due to details of its implementation. For more information on this, see [Microsoft documentation of this feature](https://learn.microsoft.com/en-us/cpp/sanitizers/asan-runtime?view=msvc-170#alignment-requirements-for-addresssanitizer-poisoning).
+
+It should be possible to work around this by manually rounding buffer lengths up to the nearest multiple of 8 in the poisoning function, although it's remotely possible that this will cause other problems. Valgrind does not appear to have this limitation (unless Valgrind is simply more poorly documented). However, running tests under Valgrind causes a much greater slowdown compared with ASan. As a result, it would be beneficial to implement support for both Valgrind and ASan, to give the extra flexibility to choose either performance or accuracy as required. This should be simple as both have very similar memory poisoning interfaces.
+
+**Design decision: Implement memory poisoning tests with both Valgrind's memcheck and ASan manual poisoning.**
+
+##### Validation with new tests
+
+Validation with newly created tests would be simpler to implement than using existing tests, since the tests can be written to take into account memory poisoning. It is also possible to build such a testsuite using existing tests as a starting point - `mbedtls_test_psa_exercise_key` is a test helper that already exercises many PSA operations on a key. This would need to be extended to cover operations without keys (e.g. hashes) and multipart operations, but it provides a good base from which to build all of the required testing.
+
+Additionally, we can ensure that all functions are exercised by automatically generating test data files.
+
+##### Validation with existing tests
+
+An alternative approach would be to integrate memory poisoning validation with existing tests. This has two main advantages:
+
+* All of the tests are written already, potentially saving development time.
+* The code coverage of these tests is greater than would be achievable writing new tests from scratch. In practice this advantage is small as buffer copying will take place in the dispatch layer. The tests are therefore independent of the values of parameters passed to the driver, so extra coverage in these parameters does not gain anything.
+
+It may be possible to transparently implement memory poisoning so that existing tests can work without modification. This would be achieved by replacing the implementation of `malloc()` with one that allocates poisoned buffers. However, there are some difficulties with this:
+
+* Not all buffers allocated by tests are used as inputs and outputs to PSA functions being tested.
+* Those buffers that are inputs to a PSA function need to be unpoisoned right up until the function is called, so that they can be filled with input data.
+* Those buffers that are outputs from a PSA function need to be unpoisoned straight after the function returns, so that they can be read to check the output is correct.
+
+These issues may be solved by creating some kind of test wrapper around every PSA function call that poisons the memory. However, it is unclear how straightforward this will be in practice. If this is simple to achieve, the extra coverage and time saved on new tests will be a benefit. If not, writing new tests is the best strategy.
+
+**Design decision: Add memory poisoning transparently to existing tests.**
+
+#### Discussion of copying validation
+
+Of all discussed approaches, validation by memory poisoning appears as the best. This is because it:
+
+* Does not require complex linking against different versions of `malloc()` (as is the case with the memory pool approach).
+* Allows automated testing (unlike the review approach).
+
+**Design decision: Use a memory poisoning approach to validate copying.**
+
+### Shared memory protection requirements
+
+TODO: write document and reference it here.
+
+### Validation of careful access for built-in drivers
+
+For PSA functions whose inputs and outputs are not copied, it is important that we validate that the builtin drivers are correctly accessing their inputs and outputs so as not to cause a security issue. Specifically, we must check that each memory location in a shared buffer is not accessed more than once by a driver function. In this section we examine various possible methods for performing this validation.
+
+Note: We are focusing on read-read inconsistencies for now, as most of the cases where we aren't copying are inputs.
+
+#### Review
+
+As with validation of copying, the simplest method of validation we can implement is careful code review. This is the least desirable method of validation for several reasons:
+
+1. It is tedious for the reviewers.
+2. Reviewers are prone to make mistakes (especially when performing tedious tasks).
+3. It requires engineering time linear in the number of PSA functions to be tested.
+4. It cannot assure the quality of third-party drivers, whereas automated tests can be ported to any driver implementation in principle.
+
+If all other approaches turn out to be prohibitively difficult, code review exists as a fallback option. However, it should be understood that this is far from ideal.
+
+#### Tests using `mprotect()`
+
+Checking that a memory location is not accessed more than once may be achieved by using `mprotect()` on a Linux system to cause a segmentation fault whenever a memory access happens. Tests based on this approach are sketched below.
+
+##### Linux mprotect+ptrace
+
+Idea: call `mmap` to allocate memory for arguments and `mprotect` to deny or reenable access. Use `ptrace` from a parent process to react to SIGSEGV from a denied access. On SIGSEGV happening in the faulting region:
+
+1. Use `ptrace` to execute a `mprotect` system call in the child to enable access. TODO: How? `ptrace` can modify registers and memory in the child, which includes changing parameters of a syscall that's about to be executed, but not directly cause the child process to execute a syscall that it wasn't about to execute.
+2. Use `ptrace` with `PTRACE_SINGLESTEP` to re-execute the failed load/store instrution.
+3. Use `ptrace` to execute a `mprotect` system call in the child to disable access.
+4. Use `PTRACE_CONT` to resume the child execution.
+
+Record the addresses that are accessed. Mark the test as failed if the same address is read twice.
+
+##### Debugger + mprotect
+
+Idea: call `mmap` to allocate memory for arguments and `mprotect` to deny or reenable access. Use a debugger to handle SIGSEGV (Gdb: set signal catchpoint). If the segfault was due to accessing the protected region:
+
+1. Execute `mprotect` to allow access.
+2. Single-step the load/store instruction.
+3. Execute `mprotect` to disable access.
+4. Continue execution.
+
+Record the addresses that are accessed. Mark the test as failed if the same address is read twice. This part might be hard to do in the gdb language, so we may want to just log the addresses and then use a separate program to analyze the logs, or do the gdb tasks from Python.
+
+#### Instrumentation (Valgrind)
+
+An alternative approach is to use a dynamic instrumentation tool (the most obvious being Valgrind) to trace memory accesses and check that each of the important memory addresses is accessed no more than once.
+
+Valgrind has no tool specifically that checks the property that we are looking for. However, it is possible to generate a memory trace with Valgrind using the following:
+
+```
+valgrind --tool=lackey --trace-mem=yes --log-file=logfile ./myprogram
+```
+This will execute `myprogram` and dump a record of every memory access to `logfile`, with its address and data width. If `myprogram` is a test that does the following:
+
+1. Set up input and output buffers for a PSA function call.
+2. Leak the start and end address of each buffer via `print()`.
+3. Write data into the input buffer exactly once.
+4. Call the PSA function.
+5. Read data from the output buffer exactly once.
+
+Then it should be possible to parse the output from the program and from Valgrind and check that each location was accessed exactly twice: once by the program's setup and once by the PSA function.
+
+#### Fixed Virtual Platform testing
+
+It may be possible to measure double accesses by running tests on a Fixed Virtual Platform such as Corstone 310 ecosystem FVP, available [here](https://developer.arm.com/downloads/-/arm-ecosystem-fvps). There exists a pre-packaged example program for the Corstone 310 FVP available as part of the Open IoT SDK [here](https://git.gitlab.arm.com/iot/open-iot-sdk/examples/sdk-examples/-/tree/main/examples/mbedtls/cmsis-rtx/corstone-310) that could provide a starting point for a set of tests.
+
+Running on an FVP allows two approaches to careful-access testing:
+
+* Convenient scripted use of a debugger with [Iris](https://developer.arm.com/documentation/101196/latest/). This allows memory watchpoints to be set, perhaps more flexibly than with GDB.
+* Tracing of all memory accesses with [Tarmac Trace](https://developer.arm.com/documentation/100964/1123/Plug-ins-for-Fast-Models/TarmacTrace). To validate the single-access properties, the [processor memory access trace source](https://developer.arm.com/documentation/100964/1123/Plug-ins-for-Fast-Models/TarmacTrace/Processor-memory-access-trace) can be used to output all memory accesses happening on the FVP. This output can then be easily parsed and processed to ensure that the input and output buffers are accessed only once. The addresses of buffers can either be leaked by the program through printing to the serial port or set to fixed values in the FVP's linker script.
+
+#### Discussion of careful-access validation
+
+The best approach for validating the correctness of memory accesses is an open question that requires further investigation. To answer this question, each of the test strategies discussed above must be prototyped as follows:
+
+1. Take 1-2 days to create a basic prototype of a test that uses the approach.
+2. Document the prototype - write a short guide that can be followed to arrive at the same prototype.
+3. Evaluate the prototype according to its usefulness. The criteria of evaluation should include:
+   * Ease of implementation - Was the prototype simple to implement? Having implemented it, is it simple to extend it to do all of the required testing?
+   * Flexibility - Could the prototype be extended to cover other careful-access testing that may be needed in future?
+   * Performance - Does the test method perform well? Will it cause significant slowdown to CI jobs?
+   * Ease of reproduction - Does the prototype require a particular platform or tool to be set up? How easy would it be for an external user to run the prototype?
+   * Comprehensibility - Accounting for the lower code quality of a prototype, would developers unfamiliar with the tests based on the prototype be able to understand them easily?
+   * Portability - How well can this approach be ported to multiple platforms? This would allow us to ensure that there are no double-accesses due to a bug that only affects a specific target.
+
+Once each prototype is complete, choose the best approach to implement the careful-access testing. Implement tests using this approach for each of the PSA interfaces that require careful-access testing:
+
+* Hash
+* MAC
+* AEAD (additional data only)
+* Key derivation
+* Asymmetric signature (input only)
+
+##### New vs existing tests
+
+Most of the test methods discussed above need extra setup. Some require leaking of buffer bounds, predictable memory access patterns or allocation of special buffers. FVP testing even requires the tests to be run on a non-host target.
+
+With this complexity in mind it does not seem feasible to run careful-access tests using existing testsuites. Instead, new tests should be written that exercise the drivers in the required way. Fortunately, the only interfaces that need testing are hash, MAC, AEAD (testing over AD only), Key derivation and Asymmetric signature, which limits the number of new tests that must be written.
+
+#### Validation of validation for careful-access
+
+In order to ensure that the careful-access validation works, it is necessary to write tests to check that we can correctly detect careful-access violations when they occur. To do this, write a test function that:
+
+* Reads its input multiple times at the same location.
+* Writes to its output multiple times at the same location.
+
+Then, write a careful-access test for this function and ensure that it fails.
+
+## Analysis of argument protection in built-in drivers
+
+TODO: analyze the built-in implementations of mechanisms for which there is a requirement on drivers. By code inspection, how satisfied are we that they meet the requirement?
+
+## Copy bypass
+
+For efficiency, we are likely to want mechanisms to bypass the copy and process buffers directly in builds that are not affected by shared memory considerations.
+
+Expand this section to document any mechanisms that bypass the copy.
+
+Make sure that such mechanisms preserve the guarantees when buffers overlap.
+
+## Detailed design
+
+### Implementation by module
+
+Module | Input protection strategy | Output protection strategy | Notes
+---|---|---|---
+Hash and MAC | Careful access | Careful access | Low risk of multiple-access as the input and output are raw unformatted data.
+Cipher | Copying | Copying |
+AEAD | Copying (careful access for additional data) | Copying |
+Key derivation | Careful access | Careful access |
+Asymmetric signature | Careful access | Copying | Inputs to signatures are passed to a hash. This will no longer hold once PureEdDSA support is implemented.
+Asymmetric encryption | Copying | Copying |
+Key agreement | Copying | Copying |
+PAKE | Copying | Copying |
+Key import / export | Copying | Copying | Keys may be imported and exported in DER format, which is a structured format and therefore susceptible to read-read inconsistencies and potentially write-read inconsistencies.
+
+### Copying functions
+
+As discussed in [Copying code](#copying-code), it is simpler to use a single unified API for copying. Therefore, we create the following functions:
+
+* `psa_crypto_copy_input(const uint8_t *input, size_t input_length, uint8_t *input_copy, size_t input_copy_length)`
+* `psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_length, uint8_t *output, size_t output_length)`
+
+These seem to be a repeat of the same function, however it is useful to retain two separate functions for input and output parameters so that we can use different test hooks in each when using memory poisoning for tests.
+
+Given that the majority of functions will be allocating memory on the heap to copy, it is helpful to build convenience functions that allocate the memory as well.
+
+In order to keep track of allocated copies on the heap, we can create new structs:
+
+```c
+typedef struct psa_crypto_local_input_s {
+    uint8_t *buffer;
+    size_t length;
+} psa_crypto_local_input_t;
+
+typedef struct psa_crypto_local_output_s {
+    uint8_t *original;
+    uint8_t *buffer;
+    size_t length;
+} psa_crypto_local_output_t;
+```
+
+These may be used to keep track of input and output copies' state, and ensure that their length is always stored with them. In the case of output copies, we keep a pointer to the original buffer so that it is easy to perform a writeback to the original once we have finished outputting.
+
+With these structs we may create 2 pairs of functions, one pair for input copies:
+
+```c
+psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len,
+                                          psa_crypto_local_input_t *local_input);
+
+void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input);
+```
+
+* `psa_crypto_local_input_alloc()` calls `calloc()` to allocate a new buffer of length `input_len`, copies the contents across from `input`. It then stores `input_len` and the pointer to the copy in the struct `local_input`.
+* `psa_crypto_local_input_free()` calls `free()` on the local input that is referred to by `local_input` and sets the pointer in the struct to `NULL`.
+
+We also create a pair of functions for output copies:
+
+```c
+psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len,
+                                           psa_crypto_local_output_t *local_output);
+
+psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output);
+```
+
+* `psa_crypto_local_output_alloc()` calls `calloc()` to allocate a new buffer of length `output_len` and stores `output_len` and the pointer to the buffer in the struct `local_output`. It also stores a pointer to `output` in `local_output->original`.
+* `psa_crypto_local_output_free()` copies the contents of the output buffer `local_output->buffer` into the buffer `local_output->original`, calls `free()` on `local_output->buffer` and sets it to `NULL`.
+
+Some PSA functions may not use these convenience functions as they may have local optimizations that reduce memory usage. For example, ciphers may be able to use a single intermediate buffer for both input and output.
+
+In order to abstract the management of the copy state further, to make it simpler to add, we create the following 6 convenience macros:
+
+For inputs:
+
+* `LOCAL_INPUT_DECLARE(input, input_copy_name)`, which declares and initializes a `psa_crypto_local_input_t` and a pointer with the name `input_copy_name` in the current scope.
+* `LOCAL_INPUT_ALLOC(input, input_size, input_copy)`, which tries to allocate an input using `psa_crypto_local_input_alloc()`. On failure, it sets an error code and jumps to an exit label. On success, it sets `input_copy` to point to the copy of the buffer.
+* `LOCAL_INPUT_FREE(input, input_copy)`, which frees the input copy using `psa_crypto_local_input_free()` and sets `input_copy` to `NULL`.
+
+For outputs:
+
+* `LOCAL_OUTPUT_DECLARE(output, output_copy_name)`, analogous to `LOCAL_INPUT_DECLARE()` for `psa_crypto_local_output_t`.
+* `LOCAL_OUTPUT_ALLOC(output, output_size, output_copy)`, analogous to `LOCAL_INPUT_ALLOC()` for outputs, calling `psa_crypto_local_output_alloc()`.
+* `LOCAL_OUTPUT_FREE(output, output_copy)`, analogous to `LOCAL_INPUT_FREE()` for outputs. If the `psa_crypto_local_output_t` is in an invalid state (the copy pointer is valid, but the original pointer is `NULL`) this macro sets an error status.
+
+These macros allow PSA functions to have copying added while keeping the code mostly unmodified. Consider a hypothetical PSA function:
+
+```c
+psa_status_t psa_foo(const uint8_t *input, size_t input_length,
+                     uint8_t *output, size_t output_size, size_t *output_length)
+{
+    /* Do some operation on input and output */
+}
+```
+
+By changing the name of the input and output parameters, we can retain the original variable name as the name of the local copy while using a new name (e.g. with the suffix `_external`) for the original buffer. This allows copying to be added near-seamlessly as follows:
+
+```c
+psa_status_t psa_foo(const uint8_t *input_external, size_t input_length,
+                     uint8_t *output_external, size_t output_size, size_t *output_length)
+{
+    psa_status_t status;
+
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
+    LOCAL_INPUT_ALLOC(input_external, input);
+    LOCAL_OUTPUT_ALLOC(output_external, output);
+
+    /* Do some operation on input and output */
+
+exit:
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(output_external, output);
+}
+```
+
+A second advantage of using macros for the copying (other than simple convenience) is that it allows copying to be easily disabled by defining alternate macros that function as no-ops. Since buffer copying is specific to systems where shared memory is passed to PSA functions, it is useful to be able to disable it where it is not needed, to save code size.
+
+To this end, the macros above are defined conditionally on a new config option, `MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS`, which may be set whenever PSA functions are assumed to have exclusive access to their input and output buffers. When `MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS` is set, the macros do not perform copying.
+
+### Implementation of copying validation
+
+As discussed in the [design exploration of copying validation](#validation-of-copying), the best strategy for validation of copies appears to be validation by memory poisoning, implemented using Valgrind and ASan.
+
+To perform memory poisoning, we must implement the functions alluded to in [Validation of copying by memory poisoning](#validation-of-copying-by-memory-poisoning):
+```c
+void mbedtls_test_memory_poison(const unsigned char *ptr, size_t size);
+void mbedtls_test_memory_unpoison(const unsigned char *ptr, size_t size);
+```
+This should poison or unpoison the given buffer, respectively.
+
+* `mbedtls_test_memory_poison()` is equivalent to calling `VALGRIND_MAKE_MEM_NOACCESS(ptr, size)` or `ASAN_POISON_MEMORY_REGION(ptr, size)`.
+* `mbedtls_test_memory_unpoison()` is equivalent to calling `VALGRIND_MAKE_MEM_DEFINED(ptr, size)` or `ASAN_UNPOISON_MEMORY_REGION(ptr, size)`.
+
+The PSA copying function must then have test hooks implemented as outlined in [Validation of copying by memory poisoning](#validation-of-copying-by-memory-poisoning).
+
+As discussed in [the design exploration](#validation-with-existing-tests), the preferred approach for implementing copy-testing is to implement it transparently using existing tests. This is specified in more detail below.
+
+#### Transparent allocation-based memory poisoning
+
+In order to implement transparent memory poisoning we require a wrapper around all PSA function calls that poisons any input and output buffers.
+
+The easiest way to do this is to create wrapper functions that poison the memory and then `#define` PSA function names to be wrapped versions of themselves. For example, to replace `psa_aead_update()`:
+```c
+psa_status_t mem_poison_psa_aead_update(psa_aead_operation_t *operation,
+                                        const uint8_t *input,
+                                        size_t input_length,
+                                        uint8_t *output,
+                                        size_t output_size,
+                                        size_t *output_length)
+{
+    mbedtls_test_memory_poison(input, input_length);
+    mbedtls_test_memory_poison(output, output_size);
+    psa_status_t status = psa_aead_update(operation, input, input_length,
+                                          output, output_size, output_length);
+    mbedtls_test_memory_unpoison(input, input_length);
+    mbedtls_test_memory_unpoison(output, output_size);
+
+    return status;
+}
+
+#define psa_aead_update(...) mem_poison_psa_aead_update(__VA_ARGS__)
+```
+
+There now exists a more generic mechanism for making exactly this kind of transformation - the PSA test wrappers, which exist in the files `tests/include/test/psa_test_wrappers.h` and `tests/src/psa_test_wrappers.c`. These are wrappers around all PSA functions that allow testing code to be inserted at the start and end of a PSA function call.
+
+The test wrappers are generated by a script, although they are not automatically generated as part of the build process. Instead, they are checked into source control and must be manually updated when functions change by running `tests/scripts/generate_psa_wrappers.py`.
+
+Poisoning code is added to these test wrappers where relevant in order to pre-poison and post-unpoison the parameters to the functions.
+
+#### Configuration of poisoning tests
+
+Since the memory poisoning tests will require the use of interfaces specific to the sanitizers used to poison memory, they must only be enabled when we are building with ASan or Valgrind. For now, we can auto-detect ASan at compile-time and set an option: `MBEDTLS_TEST_MEMORY_CAN_POISON`. When this option is enabled, we build with memory-poisoning support. This enables transparent testing with ASan without needing any extra configuration options.
+
+Auto-detection and memory-poisoning with Valgrind is left for future work.
+
+#### Validation of validation for copying
+
+To make sure that we can correctly detect functions that access their input/output buffers rather than the copies, it would be best to write a test function that misbehaves and test it with memory poisoning. Specifically, the function should:
+
+* Read its input buffer and after calling the input-buffer-copying function to create a local copy of its input.
+* Write to its output buffer before and after calling the output-buffer-copying function to copy-back its output.
+
+Then, we could write a test that uses this function with memory poisoning and ensure that it fails. Since we are expecting a failure due to memory-poisoning, we would run this test separately from the rest of the memory-poisoning testing.
+
+This testing is implemented in `programs/test/metatest.c`, which is a program designed to check that test failures happen correctly. It may be run via the script `tests/scripts/run-metatests.sh`.
diff --git a/docs/architecture/psa-thread-safety/key-slot-state-transitions.png b/docs/architecture/psa-thread-safety/key-slot-state-transitions.png
index 34cc79b..08e4cc0 100644
--- a/docs/architecture/psa-thread-safety/key-slot-state-transitions.png
+++ b/docs/architecture/psa-thread-safety/key-slot-state-transitions.png
Binary files differ
diff --git a/docs/architecture/psa-thread-safety/psa-thread-safety.md b/docs/architecture/psa-thread-safety/psa-thread-safety.md
index dc5d7e1..edb94c5 100644
--- a/docs/architecture/psa-thread-safety/psa-thread-safety.md
+++ b/docs/architecture/psa-thread-safety/psa-thread-safety.md
@@ -1,450 +1,367 @@
-# Thread safety of the PSA subsystem
+# Thread-safety of the PSA subsystem
 
-Currently PSA Crypto API calls in Mbed TLS releases are not thread-safe. In Mbed TLS 3.6 we are planning to add a minimal support for thread-safety of the PSA Crypto API (see section [Strategy for 3.6](#strategy-for-36)).
+Currently, PSA Crypto API calls in Mbed TLS releases are not thread-safe.
 
-In the [Design analysis](#design-analysis) section we analyse design choices. This discussion is not constrained to what is planned for 3.6 and considers future developments. It also leaves some questions open and discusses options that have been (or probably will be) rejected.
+As of Mbed TLS 3.6, an MVP for making the [PSA Crypto key management API](https://arm-software.github.io/psa-api/crypto/1.1/api/keys/management.html) and [`psa_crypto_init`](https://arm-software.github.io/psa-api/crypto/1.1/api/library/library.html#c.psa_crypto_init) thread-safe has been implemented. Implementations which only ever call PSA functions from a single thread are not affected by this new feature.
 
-## Design analysis
+Summary of recent work:
 
-This section explores possible designs and does not reflect what is currently implemented.
+- Key Store:
+    - Slot states are described in the [Key slot states](#key-slot-states) section. They guarantee safe concurrent access to slot contents.
+    - Key slots are protected by a global mutex, as described in [Key store consistency and abstraction function](#key-store-consistency-and-abstraction-function).
+    - Key destruction strategy abiding by [Key destruction guarantees](#key-destruction-guarantees), with an implementation discussed in [Key destruction implementation](#key-destruction-implementation).
+- `global_data` variables in `psa_crypto.c` and `psa_crypto_slot_management.c` are now protected by mutexes, as described in the [Global data](#global-data) section.
+- The testing system has now been made thread-safe. Tests can now spin up multiple threads, see [Thread-safe testing](#thread-safe-testing) for details.
+- Some multithreaded testing of the key management API has been added, this is outlined in [Testing-and-analysis](#testing-and-analysis).
+- The solution uses the pre-existing `MBEDTLS_THREADING_C` threading abstraction.
+- The core makes no additional guarantees for drivers. See [Driver policy](#driver-policy) for details.
 
-### Requirements
+The other functions in the PSA Crypto API are planned to be made thread-safe in future, but currently we are not testing this.
 
-#### Backward compatibility requirement
+## Overview of the document
 
-Code that is currently working must keep working. There can be an exception for code that uses features that are advertised as experimental; for example, it would be annoying but ok to add extra requirements for drivers.
+* The [Guarantees](#guarantees) section describes the properties that are followed when PSA functions are invoked by multiple threads.
+* The [Usage guide](#usage-guide) section gives guidance on initializing, using and freeing PSA when using multiple threads.
+* The [Current strategy](#current-strategy) section describes how thread-safety of key management and `global_data` is achieved.
+* The [Testing and analysis](#testing-and-analysis) section discusses the state of our testing, as well as how this testing will be extended in future.
+* The [Future work](#future-work) section outlines our long-term goals for thread-safety; it also analyses how we might go about achieving these goals.
 
-(In this section, “currently” means Mbed TLS releases without proper concurrency management: 3.0.0, 3.1.0, and any other subsequent 3.x version.)
+## Definitions
 
-In particular, if you either protect all PSA calls with a mutex, or only ever call PSA functions from a single thread, your application currently works and must keep working. If your application currently builds and works with `MBEDTLS_PSA_CRYPTO_C` and `MBEDTLS_THREADING_C` enabled, it must keep building and working.
+*Concurrent calls*
 
-As a consequence, we must not add a new platform requirement beyond mutexes for the base case. It would be ok to add new platform requirements if they're only needed for PSA drivers, or if they're only performance improvements.
+The PSA specification defines concurrent calls as: "In some environments, an application can make calls to the Crypto API in separate threads. In such an environment, concurrent calls are two or more calls to the API whose execution can overlap in time." (See PSA documentation [here](https://arm-software.github.io/psa-api/crypto/1.1/overview/conventions.html#concurrent-calls).)
 
-Tempting platform requirements that we cannot add to the default `MBEDTLS_THREADING_C` include:
+*Thread-safety*
 
-* Releasing a mutex from a different thread than the one that acquired it. This isn't even guaranteed to work with pthreads.
-* New primitives such as semaphores or condition variables.
+In general, a system is thread-safe if any valid set of concurrent calls is handled as if the effect and return code of every call is equivalent to some sequential ordering. We implement a weaker notion of thread-safety, we only guarantee thread-safety in the circumstances described in the [PSA Concurrent calling conventions](#psa-concurrent-calling-conventions) section.
 
-#### Correctness out of the box
+## Guarantees
 
-If you build with `MBEDTLS_PSA_CRYPTO_C` and `MBEDTLS_THREADING_C`, the code must be functionally correct: no race conditions, deadlocks or livelocks.
+### Correctness out of the box
 
-The [PSA Crypto API specification](https://armmbed.github.io/mbed-crypto/html/overview/conventions.html#concurrent-calls) defines minimum expectations for concurrent calls. They must work as if they had been executed one at a time (excluding resource-management errors), except that the following cases have undefined behavior:
+Building with `MBEDTLS_PSA_CRYPTO_C` and `MBEDTLS_THREADING_C` gives code which is correct; there are no race-conditions, deadlocks or livelocks when concurrently calling any set of PSA key management functions once `psa_crypto_init` has been called (see the [Initialization](#initialization) section for details on how to correctly initialize the PSA subsystem when using multiple threads).
 
-* Destroying a key while it's in use.
-* Concurrent calls using the same operation object. (An operation object may not be used by more than one thread at a time. But it can move from one thread to another between calls.)
-* Overlap of an output buffer with an input or output of a concurrent call.
-* Modification of an input buffer during a call.
+We do not test or support calling other PSA API functions concurrently.
 
-Note that while the specification does not define the behavior in such cases, Mbed TLS can be used as a crypto service. It's acceptable if an application can mess itself up, but it is not acceptable if an application can mess up the crypto service. As a consequence, destroying a key while it's in use may violate the security property that all key material is erased as soon as `psa_destroy_key` returns, but it may not cause data corruption or read-after-free inside the key store.
+There is no busy-waiting in our implementation, every API call completes in a finite number of steps regardless of the locking policy of the underlying mutexes.
 
-#### No spinning
+When only considering key management functions: Mbed TLS 3.6 abides by the minimum expectation for concurrent calls set by the PSA specification (see [PSA Concurrent calling conventions](#psa-concurrent-calling-conventions)).
 
-The code must not spin on a potentially non-blocking task. For example, this is proscribed:
-```
-lock(m);
-while (!its_my_turn) {
-    unlock(m);
-    lock(m);
-}
-```
+#### PSA Concurrent calling conventions
 
-Rationale: this can cause battery drain, and can even be a livelock (spinning forever), e.g. if the thread that might unblock this one has a lower priority.
+These are the conventions which are planned to be added to the PSA 1.2 specification, Mbed TLS 3.6 abides by these when only considering [key management functions](https://arm-software.github.io/psa-api/crypto/1.1/api/keys/management.html):
 
-#### Driver requirements
+> The result of two or more concurrent calls must be consistent with the same set of calls being executed sequentially in some order, provided that the calls obey the following constraints:
+>
+> * There is no overlap between an output parameter of one call and an input or output parameter of another call. Overlap between input parameters is permitted.
+>
+> * A call to `psa_destroy_key()` must not overlap with a concurrent call to any of the following functions:
+>     - Any call where the same key identifier is a parameter to the call.
+>     - Any call in a multi-part operation, where the same key identifier was used as a parameter to a previous step in the multi-part operation.
+>
+> * Concurrent calls must not use the same operation object.
+>
+> If any of these constraints are violated, the behaviour is undefined.
+>
+> The consistency requirement does not apply to errors that arise from resource failures or limitations. For example, errors resulting from resource exhaustion can arise in concurrent execution that do not arise in sequential execution.
+>
+> As an example of this rule: suppose two calls are executed concurrently which both attempt to create a new key with the same key identifier that is not already in the key store. Then:
+> * If one call returns `PSA_ERROR_ALREADY_EXISTS`, then the other call must succeed.
+> * If one of the calls succeeds, then the other must fail: either with `PSA_ERROR_ALREADY_EXISTS` or some other error status.
+> * Both calls can fail with error codes that are not `PSA_ERROR_ALREADY_EXISTS`.
+>
+> If the application concurrently modifies an input parameter while a function call is in progress, the behaviour is undefined.
 
-At the time of writing, the driver interface specification does not consider multithreaded environments.
+### Backwards compatibility
 
-We need to define clear policies so that driver implementers know what to expect. Here are two possible policies at two ends of the spectrum; what is desirable is probably somewhere in between.
+Code which was working prior to Mbed TLS 3.6 will still work. Implementations which only ever call PSA functions from a single thread, or which protect all PSA calls using a mutex, are not affected by this new feature. If an application previously worked with a 3.X version, it will still work on version 3.6.
 
-* **Policy 1:** Driver entry points may be called concurrently from multiple threads, even if they're using the same key, and even including destroying a key while an operation is in progress on it.
-* **Policy 2:** At most one driver entry point is active at any given time.
+### Supported threading implementations
 
-Combining the two we arrive at **Policy 3**:
+Currently, the only threading library with support shipped in the code base is pthread (enabled by `MBEDTLS_THREADING_PTHREAD`). The only concurrency primitives we use are mutexes, see [Condition variables](#condition-variables) for discussion about implementing new primitives in future major releases.
 
-* By default, each driver only has at most one entry point active at any given time. In other words, each driver has its own exclusive lock.
-* Drivers have an optional `"thread_safe"` boolean property. If true, it allows concurrent calls to this driver.
-* Even with a thread-safe driver, the core never starts the destruction of a key while there are operations in progress on it, and never performs concurrent calls on the same multipart operation.
+Users can add support to any platform which has mutexes using the Mbed TLS platform abstraction layer (see `include/mbedtls/threading.h` for details).
 
-#### Long-term performance requirements
+We intend to ship support for other platforms including Windows in future releases.
 
-In the short term, correctness is the important thing. We can start with a global lock.
+### Key destruction guarantees
 
-In the medium to long term, performing a slow or blocking operation (for example, a driver call, or an RSA decryption) should not block other threads, even if they're calling the same driver or using the same key object.
+Much like all other API calls, `psa_destroy_key` does not block indefinitely, and when `psa_destroy_key` returns:
 
-We may want to go directly to a more sophisticated approach because when a system works with a global lock, it's typically hard to get rid of it to get more fine-grained concurrency.
+1. The key identifier does not exist. This is a functional requirement for persistent keys: any thread can immediately create a new key with the same identifier.
+2. The resources from the key have been freed. This allows threads to create similar keys immediately after destruction, regardless of resources.
 
-#### Key destruction short-term requirements
+When `psa_destroy_key` is called on a key that is in use, guarantee 2 may be violated. This is consistent with the PSA specification requirements, as destruction of a key in use is undefined.
 
-##### Summary of guarantees in the short term
+In future versions we aim to enforce stronger requirements for key destruction, see [Long term key destruction requirements](#long-term-key-destruction-requirements) for details.
 
-When `psa_destroy_key` returns:
+### Driver policy
 
-1. The key identifier doesn't exist. Rationale: this is a functional requirement for persistent keys: the caller can immediately create a new key with the same identifier.
-2. The resources from the key have been freed. Rationale: in a low-resource condition, this may be necessary for the caller to re-create a similar key, which should be possible.
-3. The call must not block indefinitely, and in particular cannot wait for an event that is triggered by application code such as calling an abort function. Rationale: this may not strictly be a functional requirement, but it is an expectation `psa_destroy_key` does not block forever due to another thread, which could potentially be another process on a multi-process system. In particular, it is only acceptable for `psa_destroy_key` to block, when waiting for another thread to complete a PSA Cryptography API call that it had already started.
+The core makes no additional guarantees for drivers. Driver entry points may be called concurrently from multiple threads. Threads can concurrently call entry points using the same key, there is also no protection from destroying a key which is in use.
 
-When `psa_destroy_key` is called on a key that is in use, guarantee 2. might be violated. (This is consistent with the requirement [“Correctness out of the box”](#correctness-out-of-the-box), as destroying a key while it's in use is undefined behavior.)
-
-#### Key destruction long-term requirements
-
-The [PSA Crypto API specification](https://armmbed.github.io/mbed-crypto/html/api/keys/management.html#key-destruction) mandates that implementations make a best effort to ensure that the key material cannot be recovered. In the long term, it would be good to guarantee that `psa_destroy_key` wipes all copies of the key material.
-
-##### Summary of guarantees in the long term
-
-When `psa_destroy_key` returns:
-
-1. The key identifier doesn't exist. Rationale: this is a functional requirement for persistent keys: the caller can immediately create a new key with the same identifier.
-2. The resources from the key have been freed. Rationale: in a low-resource condition, this may be necessary for the caller to re-create a similar key, which should be possible.
-3. The call must not block indefinitely, and in particular cannot wait for an event that is triggered by application code such as calling an abort function. Rationale: this may not strictly be a functional requirement, but it is an expectation `psa_destroy_key` does not block forever due to another thread, which could potentially be another process on a multi-process system. In particular, it is only acceptable for `psa_destroy_key` to block, when waiting for another thread to complete a PSA Cryptography API call that it had already started.
-4. No copy of the key material exists. Rationale: this is a security requirement. We do not have this requirement yet, but we need to document this as a security weakness, and we would like to satisfy this security requirement in the future.
-
-As opposed to the short term requirements, all the above guarantees hold even if `psa_destroy_key` is called on a key that is in use.
-
-### Resources to protect
-
-Analysis of the behavior of the PSA key store as of Mbed TLS 9202ba37b19d3ea25c8451fd8597fce69eaa6867.
-
-#### Global variables
-
-* `psa_crypto_slot_management::global_data.key_slots[i]`: see [“Key slots”](#key-slots).
-
-* `psa_crypto_slot_management::global_data.key_slots_initialized`:
-    * `psa_initialize_key_slots`: modification.
-    * `psa_wipe_all_key_slots`: modification.
-    * `psa_get_empty_key_slot`: read.
-    * `psa_get_and_lock_key_slot`: read.
-
-* `psa_crypto::global_data.rng`: depends on the RNG implementation. See [“Random generator”](#random-generator).
-    * `psa_generate_random`: query.
-    * `mbedtls_psa_crypto_configure_entropy_sources` (only if `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is enabled): setup. Only called from `psa_crypto_init` via `mbedtls_psa_random_init`, or from test code.
-    * `mbedtls_psa_crypto_free`: deinit.
-    * `psa_crypto_init`: seed (via `mbedtls_psa_random_seed`); setup via `mbedtls_psa_crypto_configure_entropy_sources.
-
-* `psa_crypto::global_data.{initialized,rng_state}`: these are bit-fields and cannot be modified independently so they must be protected by the same mutex. The following functions access these fields:
-    * `mbedtls_psa_crypto_configure_entropy_sources` [`rng_state`] (only if `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is enabled): read. Only called from `psa_crypto_init` via `mbedtls_psa_random_init`, or from test code.
-    * `mbedtls_psa_crypto_free`: modification.
-    * `psa_crypto_init`: modification.
-    * Many functions via `GUARD_MODULE_INITIALIZED`: read.
-
-#### Key slots
-
-##### Key slot array traversal
-
-“Occupied key slot” is determined by `psa_is_key_slot_occupied` based on `slot->attr.type`.
-
-The following functions traverse the key slot array:
-
-* `psa_get_and_lock_key_slot_in_memory`: reads `slot->attr.id`.
-* `psa_get_and_lock_key_slot_in_memory`: calls `psa_lock_key_slot` on one occupied slot.
-* `psa_get_empty_key_slot`: calls `psa_is_key_slot_occupied`.
-* `psa_get_empty_key_slot`: calls `psa_wipe_key_slot` and more modifications on one occupied slot with no active user.
-* `psa_get_empty_key_slot`: calls `psa_lock_key_slot` and more modification on one unoccupied slot.
-* `psa_wipe_all_key_slots`: writes to all slots.
-* `mbedtls_psa_get_stats`: reads from all slots.
-
-##### Key slot state
-
-The following functions modify a slot's usage state:
-
-* `psa_lock_key_slot`: writes to `slot->lock_count`.
-* `psa_unlock_key_slot`: writes to `slot->lock_count`.
-* `psa_wipe_key_slot`: writes to `slot->lock_count`.
-* `psa_destroy_key`: reads `slot->lock_count`, calls `psa_lock_key_slot`.
-* `psa_wipe_all_key_slots`: writes to all slots.
-* `psa_get_empty_key_slot`: writes to `slot->lock_count` and calls `psa_wipe_key_slot` and `psa_lock_key_slot` on one occupied slot with no active user; calls `psa_lock_key_slot` on one unoccupied slot.
-* `psa_close_key`: reads `slot->lock_count`; calls `psa_get_and_lock_key_slot_in_memory`, `psa_wipe_key_slot` and `psa_unlock_key_slot`.
-* `psa_purge_key`: reads `slot->lock_count`; calls `psa_get_and_lock_key_slot_in_memory`, `psa_wipe_key_slot` and `psa_unlock_key_slot`.
-
-**slot->attr access:**
-`psa_crypto_core.h`:
-* `psa_key_slot_set_flags` - writes to attr.flags
-* `psa_key_slot_set_bits_in_flags` - writes to attr.flags
-* `psa_key_slot_clear_bits` - writes to attr.flags
-* `psa_is_key_slot_occupied` - reads attr.type (but see “[Determining whether a key slot is occupied](#determining-whether-a-key-slot-is-occupied)”)
-* `psa_key_slot_get_flags` - reads attr.flags
-
-`psa_crypto_slot_management.c`:
-* `psa_get_and_lock_key_slot_in_memory` - reads attr.id
-* `psa_get_empty_key_slot` - reads attr.lifetime
-* `psa_load_persistent_key_into_slot` - passes attr pointer to psa_load_persistent_key
-* `psa_load_persistent_key` - reads attr.id and passes pointer to psa_parse_key_data_from_storage
-* `psa_parse_key_data_from_storage` - writes to many attributes
-* `psa_get_and_lock_key_slot` - writes to attr.id, attr.lifetime, and attr.policy.usage
-* `psa_purge_key` - reads attr.lifetime, calls psa_wipe_key_slot
-* `mbedtls_psa_get_stats` - reads attr.lifetime, attr.id
-
-`psa_crypto.c`:
-* `psa_get_and_lock_key_slot_with_policy` - reads attr.type, attr.policy.
-* `psa_get_and_lock_transparent_key_slot_with_policy` - reads attr.lifetime
-* `psa_destroy_key` - reads attr.lifetime, attr.id
-* `psa_get_key_attributes` - copies all publicly available attributes of a key
-* `psa_export_key` - copies attributes
-* `psa_export_public_key` - reads attr.type, copies attributes
-* `psa_start_key_creation` - writes to the whole attr structure 
-* `psa_validate_optional_attributes` - reads attr.type, attr.bits
-* `psa_import_key` - reads attr.bits
-* `psa_copy_key` - reads attr.bits, attr.type, attr.lifetime, attr.policy
-* `psa_mac_setup` - copies whole attr structure
-* `psa_mac_compute_internal` - copies whole attr structure
-* `psa_verify_internal` - copies whole attr structure
-* `psa_sign_internal` - copies whole attr structure, reads attr.type
-* `psa_assymmetric_encrypt` - reads attr.type
-* `psa_assymetric_decrypt` - reads attr.type
-* `psa_cipher_setup` - copies whole attr structure, reads attr.type
-* `psa_cipher_encrypt` - copies whole attr structure, reads attr.type
-* `psa_cipher_decrypt` - copies whole attr structure, reads attr.type
-* `psa_aead_encrypt` - copies whole attr structure
-* `psa_aead_decrypt` - copies whole attr structure
-* `psa_aead_setup` - copies whole attr structure
-* `psa_generate_derived_key_internal` - reads attr.type, writes to and reads from attr.bits, copies whole attr structure
-* `psa_key_derivation_input_key` - reads attr.type
-* `psa_key_agreement_raw_internal` - reads attr.type and attr.bits
-
-##### Determining whether a key slot is occupied
-
-`psa_is_key_slot_occupied` currently uses the `attr.type` field to determine whether a key slot is occupied. This works because we maintain the invariant that an occupied slot contains key material. With concurrency, it is desirable to allow a key slot to be reserved, but not yet contain key material or even metadata. When creating a key, determining the key type can be costly, for example when loading a persistent key from storage or (not yet implemented) when importing or unwrapping a key using an interface that determines the key type from the data that it parses. So we should not need to hold the global key store lock while the key type is undetermined.
-
-Instead, `psa_is_key_slot_occupied` should use the key identifier to decide whether a slot is occupied. The key identifier is always readily available: when allocating a slot for a persistent key, it's an input of the function that allocates the key slot; when allocating a slot for a volatile key, the identifier is calculated from the choice of slot.
-
-Alternatively, we could use a dedicated indicator that the slot is occupied. The advantage of this is that no field of the `attr` structure would be needed to determine the slot state. This would be a clean separation between key attributes and slot state and `attr` could be treated exactly like key slot content. This would save code size and maintenance effort. The cost of it would be that each slot would need an extra field to indicate whether it is occupied.
-
-##### Key slot content
-
-Other than what is used to determine the [“key slot state”](#key-slot-state), the contents of a key slot are only accessed as follows:
-
-* Modification during key creation (between `psa_start_key_creation` and `psa_finish_key_creation` or `psa_fail_key_creation`).
-* Destruction in `psa_wipe_key_slot`.
-* Read in many functions, between calls to `psa_lock_key_slot` and `psa_unlock_key_slot`.
-
-**slot->key access:** 
-* `psa_allocate_buffer_to_slot` - allocates key.data, sets key.bytes;
-* `psa_copy_key_material_into_slot` - writes to key.data
-* `psa_remove_key_data_from_memory` - writes and reads to/from key data
-* `psa_get_key_attributes` - reads from key data
-* `psa_export_key` - passes key data to psa_driver_wrapper_export_key
-* `psa_export_public_key` - passes key data to psa_driver_wrapper_export_public_key
-* `psa_finish_key_creation` - passes key data to psa_save_persistent_key
-* `psa_validate_optional_attributes` - passes key data and bytes to mbedtls_psa_rsa_load_representation
-* `psa_import_key` - passes key data to psa_driver_wrapper_import_key
-* `psa_copy_key` - passes key data to psa_driver_wrapper_copy_key, psa_copy_key_material_into_slot
-* `psa_mac_setup` - passes key data to psa_driver_wrapper_mac_sign_setup, psa_driver_wrapper_mac_verify_setup
-* `psa_mac_compute_internal` - passes key data to psa_driver_wrapper_mac_compute
-* `psa_sign_internal` - passes key data to psa_driver_wrapper_sign_message, psa_driver_wrapper_sign_hash
-* `psa_verify_internal` - passes key data to psa_driver_wrapper_verify_message, psa_driver_wrapper_verify_hash
-* `psa_asymmetric_encrypt` - passes key data to mbedtls_psa_rsa_load_representation
-* `psa_asymmetric_decrypt` - passes key data to mbedtls_psa_rsa_load_representation
-* `psa_cipher_setup ` - passes key data to psa_driver_wrapper_cipher_encrypt_setup and psa_driver_wrapper_cipher_decrypt_setup
-* `psa_cipher_encrypt` - passes key data to psa_driver_wrapper_cipher_encrypt
-* `psa_cipher_decrypt` - passes key data to psa_driver_wrapper_cipher_decrypt
-* `psa_aead_encrypt` - passes key data to psa_driver_wrapper_aead_encrypt
-* `psa_aead_decrypt` - passes key data to psa_driver_wrapper_aead_decrypt
-* `psa_aead_setup` - passes key data to psa_driver_wrapper_aead_encrypt_setup and psa_driver_wrapper_aead_decrypt_setup
-* `psa_generate_derived_key_internal` - passes key data to psa_driver_wrapper_import_key
-* `psa_key_derivation_input_key` - passes key data to psa_key_derivation_input_internal
-* `psa_key_agreement_raw_internal` - passes key data to mbedtls_psa_ecp_load_representation
-* `psa_generate_key` - passes key data to psa_driver_wrapper_generate_key
-
-#### Random generator
+### Random number generators
 
 The PSA RNG can be accessed both from various PSA functions, and from application code via `mbedtls_psa_get_random`.
 
-With the built-in RNG implementations using `mbedtls_ctr_drbg_context` or `mbedtls_hmac_drbg_context`, querying the RNG with `mbedtls_xxx_drbg_random()` is thread-safe (protected by a mutex inside the RNG implementation), but other operations (init, free, seed) are not.
+When using the built-in RNG implementations, i.e. when `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is disabled, querying the RNG is thread-safe (`mbedtls_psa_random_init` and `mbedtls_psa_random_seed` are only thread-safe when called while holding `mbedtls_threading_psa_rngdata_mutex`. `mbedtls_psa_random_free` is not thread-safe).
 
-When `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is enabled, thread safety depends on the implementation.
+When `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is enabled, it is down to the external implementation to ensure thread-safety, should threading be enabled.
 
-#### Driver resources
+## Usage guide
 
-Depends on the driver. The PSA driver interface specification does not discuss whether drivers must support concurrent calls.
+### Initialization
 
-### Simple global lock strategy
+The PSA subsystem is initialized via a call to [`psa_crypto_init`](https://arm-software.github.io/psa-api/crypto/1.1/api/library/library.html#c.psa_crypto_init). This is a thread-safe function, and multiple calls to `psa_crypto_init` are explicitly allowed. It is valid to have multiple threads each calling `psa_crypto_init` followed by a call to any PSA key management function (if the init succeeds).
 
-Have a single mutex protecting all accesses to the key store and other global variables. In practice, this means every PSA API function needs to take the lock on entry and release on exit, except for:
+### General usage
 
-* Hash function.
-* Accessors for key attributes and other local structures.
+Once initialized, threads can use any PSA function if there is no overlap between their calls. All threads share the same set of keys, as soon as one thread returns from creating/loading a key via a key management API call the key can be used by any thread. If multiple threads attempt to load the same persistent key, with the same key identifier, only one thread can succeed - the others will return `PSA_ERROR_ALREADY_EXISTS`.
 
-Note that operation functions do need to take the lock, since they need to prevent the destruction of the key.
+Applications may need careful handling of resource management errors. As explained in ([PSA Concurrent calling conventions](#psa-concurrent-calling-conventions)), operations in progress can have memory related side effects. It is possible for a lack of resources to cause errors which do not arise in sequential execution. For example, multiple threads attempting to load the same persistent key can lead to some threads returning `PSA_ERROR_INSUFFICIENT_MEMORY` if the key is not currently in the key store - while trying to load a persistent key into the key store a thread temporarily reserves a free key slot.
 
-Note that this does not protect access to the RNG via `mbedtls_psa_get_random`, which is guaranteed to be thread-safe when `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is disabled.
+If a mutex operation fails, which only happens if the mutex implementation fails, the error code `PSA_ERROR_SERVICE_FAILURE` will be returned. If this code is returned, execution of the PSA subsystem must be stopped. All functions which have internal mutex locks and unlocks (except for when the lock/unlock occurs in a function that has no return value) will return with this error code in this situation.
 
-This approach is conceptually simple, but requires extra instrumentation to every function and has bad performance in a multithreaded environment since a slow operation in one thread blocks unrelated operations on other threads.
+### Freeing
 
-### Global lock excluding slot content
+There is no thread-safe way to free all PSA resources. This is because any such operation would need to wait for all other threads to complete their tasks before wiping resources.
 
-Have a single mutex protecting all accesses to the key store and other global variables, except that it's ok to access the content of a key slot without taking the lock if one of the following conditions holds:
+`mbedtls_psa_crypto_free` must only be called by a single thread once all threads have completed their operations.
 
-* The key slot is in a state that guarantees that the thread has exclusive access.
-* The key slot is in a state that guarantees that no other thread can modify the slot content, and the accessing thread is only reading the slot.
+## Current strategy
 
-Note that a thread must hold the global mutex when it reads or changes a slot's state.
+This section describes how we have implemented thread-safety. There is discussion of: techniques, internal properties for enforcing thread-safe access, how the system stays consistent and our abstraction model.
 
-#### Slot states
+### Protected resources
 
-For concurrency purposes, a slot can be in one of four states:
+#### Global data
 
-* EMPTY: no thread is currently accessing the slot, and no information is stored in the slot. Any thread is able to change the slot's state to FILLING and begin loading data.
-* FILLING: one thread is currently loading or creating material to fill the slot, this thread is responsible for the next state transition. Other threads cannot read the contents of a slot which is in FILLING.
-* FULL: the slot contains a key, and any thread is able to use the key after registering as a reader.
-* PENDING_DELETION: the key within the slot has been destroyed or marked for destruction, but at least one thread is still registered as a reader. No thread can register to read this slot. The slot must not be wiped until the last reader de-registers, wiping the slot by calling `psa_wipe_key_slot`.
+We have added a mutex `mbedtls_threading_psa_globaldata_mutex` defined in `include/mbedtls/threading.h`, which is used to make `psa_crypto_init` thread-safe.
 
-To change `slot` to state `new_state`, a function must call `psa_slot_state_transition(slot, new_state)`.
+There are two `psa_global_data_t` structs, each with a single instance `global_data`:
 
-A counter field within each slot keeps track of how many readers have registered. Library functions must call `psa_register_read` before reading the key data within a slot, and `psa_unregister_read` after they have finished operating.
+* The struct in `library/psa_crypto.c` is protected by `mbedtls_threading_psa_globaldata_mutex`. The RNG fields within this struct are not protected by this mutex, and are not always thread-safe (see [Random number generators](#random-number-generators)).
+* The struct in `library/psa_crypto_slot_management.c` has two fields: `key_slots` is protected as described in [Key slots](#key-slots), `key_slots_initialized` is protected by the global data mutex.
 
-Any call to `psa_slot_state_transition`, `psa_register_read` or `psa_unregister_read` must be performed by a thread which holds the global mutex.
+#### Mutex usage
 
-##### Linearizability of the system
+A deadlock would occur if a thread attempts to lock a mutex while already holding it. Functions which need to be called while holding the global mutex have documentation to say this.
+
+To avoid performance degradation, functions must hold mutexes for as short a time as possible. In particular, they must not start expensive operations (eg. doing cryptography) while holding the mutex.
+
+#### Key slots
+
+
+Keys are stored internally in a global array of key slots known as the "key store", defined in `library/psa_slot_management.c`.
+
+##### Key slot states
+
+Each key slot has a state variable and a `registered_readers` counter. These two variables dictate whether an operation can access a slot, and in what way the slot can be used.
+
+There are four possible states for a key slot:
+
+* `PSA_SLOT_EMPTY`: no thread is currently accessing the slot, and no information is stored in the slot. Any thread is able to change the slot's state to `PSA_SLOT_FILLING` and begin to load data into the slot.
+* `PSA_SLOT_FILLING`: one thread is currently loading or creating material to fill the slot, this thread is responsible for the next state transition. Other threads cannot read the contents of a slot which is in this state.
+* `PSA_SLOT_FULL`: the slot contains a key, and any thread is able to use the key after registering as a reader, increasing `registered_readers` by 1.
+* `PSA_SLOT_PENDING_DELETION`: the key within the slot has been destroyed or marked for destruction, but at least one thread is still registered as a reader (`registered_readers > 0`). No thread can register to read this slot. The slot must not be wiped until the last reader unregisters. It is during the last unregister that the contents of the slot are wiped, and the slot's state is set to `PSA_SLOT_EMPTY`.
+
+###### Key slot state transition diagram
+![](key-slot-state-transitions.png)
+
+In the state transition diagram above, an arrow between two states `q1` and `q2` with label `f` indicates that if the state of a slot is `q1` immediately before `f`'s linearization point, it may be `q2` immediately after `f`'s linearization point. Internal functions have italicized labels. The `PSA_SLOT_PENDING_DELETION -> PSA_SLOT_EMPTY` transition can be done by any function which calls `psa_unregister_read`.
+
+The state transition diagram can be generated in https://app.diagrams.net/ via this [url](https://viewer.diagrams.net/?tags=%7B%7D&highlight=0000ff&edit=_blank&layers=1&nav=1#R3Vxbd5s4EP4t%2B%2BDH5CBxf6zrJJvW7aYn7W7dFx9qZFstBg7gW379CnMxkoUtY%2BGQ%2BiVISCPQjD59mhnSU98vNg%2BRE84%2FBS7yelBxNz110IMQAEsnf9KabVZjmHnFLMJu3mhf8YxfUF6p5LVL7KKYapgEgZfgkK6cBL6PJglV50RRsKabTQOPHjV0Zuig4nnieIe1%2F2E3mWe1FjT39X8jPJsXIwPDzu4snKJx%2Fibx3HGDdaVKveup76MgSLKrxeY98tLJK%2BYl63dfc7d8sAj5iUiHH%2BBlOP338cP6i%2B37%2Ff7oV%2Fjr442aSVk53jJ%2F4R40PCKv7%2BIVuZyll%2FffhsOimsiv3OE0njvxOEKOi6K4uPszYtuzUnbzk2yLSScPTvRLCv31HCfoOXQm6Z01MbF0hGThkRIgl04cZkqf4g1yS1HVScnnaYWiBG0qVfkkPaBggZJoS5rkdzUrV1hhsUpeXlf0n1fNK6ov6pzc4mal5L1SyEWulzN0BABHSeyM%2Be671NpJaeI5cYwn9ERFwdJ30xkaKKREJifafs9v7QqjamGwqbYbbIvSBidlJ3I9qtTvu6SFoketNuJgGU3QabtMnGiGkiPttKwdcqlVfKjbiu50ju6Kugh5ToJX9NrnKTQf4SnA5M1qTUc3GJvI3jvvVV2rrCDTvrUrP4sSq6mM2GyaDsTurK2chAsMENaiBC7WcBg746UfoRmOExTtEKCy2HH9UieaGzo%2Fya5BL2wPz%2FzUmInloIhUpOsXE1h%2Bl99YYNdNZfQjFOMX5%2BdOXmpzYToLu3nR%2Bz19wLXC48uMRYpyc8lHofCbhyDKLVRMm1LZDbzMwAoxgOkSTKcxakfpIjvD3aenr6O3CfOdQ3lbOsrneK1U8BocxetyXygLo2qhZl9ojvJQEOVBt1CetpwDNBYG%2BRObRcuoXvDSU6g%2BdbA3%2Fo224wkB9QQH%2FlvD9WJhdRHXc8mQEsr2bw%2FkDzf2%2B8fh8PHzQ6exWjVeGas1kb3xrFPTX3%2FcsenVlaSLKOnp7vNgZ%2B6CehrcDe%2B%2BPv7z%2BW3qqHOkx2yL84ifUZudhZtznsKJdYrzwE5xHqiQzc%2FSoAnI2VTTDXoX1DXj1gS6CS1TJwWVES9KiIDBMCvtuozIEkEMLkciZAVFKzSeRgjtuFLsBQmfJwkCDXeYmExAwuViXBw6OWpnOVuBC12kbKUY7VosDfD4hnyYvNWbHA6zXq96POyWEzCFSkUpoNIgqEaDGkhdewVWqpZiNgNLTWHAkti6yphk237B5oA5xT6O5wLHyjcGXOVSvRi5bogVabZJQ5cqx0ItrtQrABmPkzO6nCzJRuqWFOx6YQ1xN1lzRBMNa6idQjStiNmWMdyGHi%2FdYASxB4sawCI24GwrzfLlWf%2FANo2NpqIcfy7ItAcn2mvWMfnkInvipotn0NcmAD9MQu8FLR%2Fxs%2F7uaSN2nq1hpyejMpew0pqwTzNKKjYkMZKx47tjL5j8Lvn2%2BPtFA6VyJ14Q7wj8Wb3CJbHaaq%2BDwf8wel7iuIxdDqgWvZou5Oe5ZJr0Q%2F1ae5zKS6mQQtarG5SgT6PCztuN5GiCG1u3IjnQhJSV6HrDjQ3UOdauxMRV3gmRi1UuipMo2F6OcXLwtLMQVy5jCS4IzTLoM2CxDC403xuaTdktQByXicj32nKJ%2Bym0Oh8X28e3bnltVYbX6k1D1arJOBsEibssi6t3NDR1w3YBeI4uLinUymYc9ZJwBxRujjY9CNzZuUqSjLAnlIarFj2hon4DvdPwY4Cm8MOkyhjtJUByra547orZHXCpzgKKtPSXFFCKrpKJDO3mbCP9ha%2FXK2VWn4aGJjDUHE50QTjp2Gmtxkt3NpxAhs0Y7WXe8c0O1tKZhr42eZ61NQ4PqdPbdV8dX%2FYywsvlF05yIRGorwSJPKrNaFJ6iKaxX6oryMTEGxoHSFTNvIWWpWtQszUbqpbKyqVCy1AIts6NnpC3qY4CbPohTEW9NaFS%2FtTjbwTso8IAOEeY3vzJ2gnKcLP23%2FKnMcdBQQJgKrpFc0hJFLKNbJwnvNwMp3BsWbMvqx%2F3Hye%2BH3I%2FjJHDGanEmkZf47XGGEWzFruViqMyOTI667YSxmX9hCNNHmPk2pwQYUxxBi%2FCIEsRPMtPP0M%2BipykgYM%2FCM%2BPJaT00kURXu3yfsbBMgmX1DOfn1X9GlB5FB0kIKWuAe65%2BGLvHSX0almMsLMJDCeyCeScfv6wT%2FdEAyKimUz7YFkRebtSbpNNu7IPcs6F8zEZQaIh4L0gqUvww0j7vh7F%2FW9ujL7iR%2FfmYWy1QF0KOy2JxzmWSicnvP4nF93KumPJi9n4UMmQFxOKWea550bW3W9qcrPiuCZdz4yaJ4x1gVwcXb8SyAWwDTlsQmUijIxPogmYkeL%2B3%2BJkzff%2FXEi9%2Bx8%3D).
+##### Key slot access primitives
+
+The state of a key slot is updated via the internal function `psa_key_slot_state_transition`. To change the state of `slot` from `expected_state` to `new_state`, when `new_state` is not `PSA_SLOT_EMPTY`, one must call `psa_key_slot_state_transition(slot, expected_state, new_state)`; if the state was not `expected_state` then `PSA_ERROR_CORRUPTION_DETECTED` is returned. The sole reason for having an expected state parameter here is to help guarantee that our functions work as expected, this error code cannot occur without an internal coding error.
+
+Changing a slot's state to `PSA_SLOT_EMPTY` is done via `psa_wipe_key_slot`, this function wipes the entirety of the key slot.
+
+The reader count of a slot is incremented via `psa_register_read`, and decremented via `psa_unregister_read`. Library functions register to read a slot via the `psa_get_and_lock_key_slot_X` functions, read from the slot, then call `psa_unregister_read` to make known that they have finished reading the slot's contents.
+
+##### Key store consistency and abstraction function
+
+The key store is protected by a single global mutex `mbedtls_threading_key_slot_mutex`.
+
+We maintain the consistency of the key store by ensuring that all reads and writes to `slot->state` and `slot->registered_readers` are performed under `mbedtls_threading_key_slot_mutex`. All the access primitives described above must be called while the mutex is held; there is a convenience function `psa_unregister_read_under_mutex` which wraps a call to `psa_unregister_read` in a mutex lock/unlock pair.
+
+A thread can only traverse the key store while holding `mbedtls_threading_key_slot_mutex`, the set of keys within the key store which the thread holding the mutex can access is equivalent to the set:
+
+    {mbedtls_svc_key_id_t k : (\exists slot := &global_data.key_slots[i]) [
+                                  (slot->state == PSA_SLOT_FULL) &&
+                                  (slot->attr.id == k)]}
+
+The union of this set and the set of persistent keys not currently loaded into slots is our abstraction function for the key store, any key not in this union does not currently exist as far as the code is concerned (even if the key is in a slot which has a `PSA_SLOT_FILLING` or `PSA_SLOT_PENDING_DELETION` state). Attempting to start using any key which is not a member of the union will result in a `PSA_ERROR_INVALID_HANDLE` error code.
+
+##### Locking and unlocking the mutex
+
+If a lock or unlock operation fails and this is the first failure within a function, the function will return `PSA_ERROR_SERVICE_FAILURE`. If a lock or unlock operation fails after a different failure has been identified, the status code is not overwritten.
+
+We have defined a set of macros in `library/psa_crypto_core.h` to capture the common pattern of (un)locking the mutex and returning or jumping to an exit label upon failure.
+
+##### Key creation and loading
+
+To load a new key into a slot, the following internal utility functions are used:
+
+* `psa_reserve_free_key_slot` - This function, which must be called under `mbedtls_threading_key_slot_mutex`, iterates through the key store to find a slot whose state is `PSA_SLOT_EMPTY`. If found, it reserves the slot by setting its state to `PSA_SLOT_FILLING`. If not found, it will see if there are any persistent keys loaded which do not have any readers, if there are it will kick one such key out of the key store.
+* `psa_start_key_creation` - This function wraps around `psa_reserve_free_key_slot`, if a slot has been found then the slot id is set. This second step is not done under the mutex, at this point the calling thread has exclusive access to the slot.
+* `psa_finish_key_creation` - After the contents of the key have been loaded (again this loading is not done under the mutex), the thread calls `psa_finish_key_creation`. This function takes the mutex, checks that the key does not exist in the key store (this check cannot be done before this stage), sets the slot's state to `PSA_SLOT_FULL` and releases the mutex. Upon success, any thread is immediately able to use the new key.
+* `psa_fail_key_creation` - If there is a failure at any point in the key creation stage, this clean-up function takes the mutex, wipes the slot, and releases the mutex. Immediately after this unlock, any thread can start to use the slot for another key load.
+
+##### Re-loading persistent keys
+
+As described above, persistent keys can be kicked out of the key slot array provided they are not currently being used (`registered_readers == 0`). When attempting to use a persistent key that has been kicked out of a slot, the call to `psa_get_and_lock_key_slot` will see that the key is not in a slot, call `psa_reserve_free_key_slot` and load the key back into the reserved slot. This entire sequence is done during a single mutex lock, which is necessary for thread-safety (see documentation of `psa_get_and_lock_key_slot`).
+
+If `psa_reserve_free_key_slot` cannot find a suitable slot, the key cannot be loaded back in. This will lead to a `PSA_ERROR_INSUFFICIENT_MEMORY` error.
+
+##### Using existing keys
+
+One-shot operations follow a standard pattern when using an existing key:
+
+* They call one of the `psa_get_and_lock_key_slot_X` functions, which then finds the key and registers the thread as a reader.
+* They operate on the key slot, usually copying the key into a separate buffer to be used by the operation. This step is not performed under the key slot mutex.
+* Once finished, they call `psa_unregister_read_under_mutex`.
+
+Multi-part and restartable operations each have a "setup" function where the key is passed in, these functions follow the above pattern. The key is copied into the `operation` object, and the thread unregisters from reading the key (the operations do not access the key slots again). The copy of the key will not be destroyed during a call to `psa_destroy_key`, the thread running the operation is responsible for deleting its copy in the clean-up. This may need to change to enforce the long term key requirements ([Long term key destruction requirements](#long-term-key-destruction-requirements)).
+
+##### Key destruction implementation
+
+The locking strategy here is explained in `library/psa_crypto.c`. The destroying thread (the thread calling `psa_destroy_key`) does not always wipe the key slot. The destroying thread registers to read the key, sets the slot's state to `PSA_SLOT_PENDING_DELETION`, wipes the slot from memory if the key is persistent, and then unregisters from reading the slot.
+
+`psa_unregister_read` internally calls `psa_wipe_key_slot` if and only if the slot's state is `PSA_SLOT_PENDING_DELETION` and the slot's registered reader counter is equal to 1. This implements a "last one out closes the door" approach. The final thread to unregister from reading a destroyed key will automatically wipe the contents of the slot; no readers remain to reference the slot post deletion, so there cannot be corruption.
+
+### linearizability of the system
 
 To satisfy the requirements in [Correctness out of the box](#correctness-out-of-the-box), we require our functions to be "linearizable" (under certain constraints). This means that any (constraint satisfying) set of concurrent calls are performed as if they were executed in some sequential order.
 
 The standard way of reasoning that this is the case is to identify a "linearization point" for each call, this is a single execution step where the function takes effect (this is usually a step in which the effects of the call become visible to other threads). If every call has a linearization point, the set of calls is equivalent to sequentially performing the calls in order of when their linearization point occurred.
 
-We only require linearizability to hold in the case where a resource-management error is not returned. In a set of concurrent calls, it is permitted for a call c to fail with a PSA_ERROR_INSUFFICIENT_MEMORY return code even if there does not exist a sequential ordering of the calls in which c returns this error. Even if such an error occurs, all calls are still required to be functionally correct.
+We only require linearizability to hold in the case where a resource-management error is not returned. In a set of concurrent calls, it is permitted for a call c to fail with a `PSA_ERROR_INSUFFICIENT_MEMORY` return code even if there does not exist a sequential ordering of the calls in which c returns this error. Even if such an error occurs, all calls are still required to be functionally correct.
 
-We only access and modify a slot's state and reader count while we hold the global lock. This ensures the memory in which these fields are stored is correctly synchronized. It also ensures that the key data within the slot is synchronised where needed (the writer unlocks the mutex after filling the data, and any reader must lock the mutex before reading the data).
+To help justify that our system is linearizable, here are the linearization points/planned linearization points of each PSA call :
 
-To help justify that our system is linearizable, here is a list of key slot state changing functions and their linearization points (for the sake of brevity not all failure cases are covered, but those cases are not complex):
-* `psa_wipe_key_slot, psa_register_read, psa_unregister_read, psa_slot_state_transition,` - These functions are all always performed under the global mutex, so they have no effects visible to other threads (this implies that they are linearizable).
-* `psa_get_empty_key_slot, psa_get_and_lock_key_slot_in_memory, psa_load_X_key_into_slot, psa_fail_key_creation` - These functions hold the mutex for all non-setup/finalizing code, their linearization points are the release of the mutex.
-* `psa_get_and_lock_key_slot` - If the key is already in a slot, the linearization point is the linearization point of the call to `psa_get_and_lock_key_slot_in_memory`. If the key is not in a slot and is loaded into one, the linearization point is the linearization point of the call to `psa_load_X_key_into_slot`.
-* `psa_start_key_creation` - From the perspective of other threads, the only effect of a successful call to this function is that the amount of usable resources decreases (a key slot which was usable is now unusable). Since we do not consider resource management as linearizable behaviour, when arguing for linearizability of the system we consider this function to have no visible effect to other threads.
-* `psa_finish_key_creation` - On a successful load, we lock the mutex and set the state of the slot to FULL, the linearization point is then the following unlock. On an unsuccessful load, the linearization point is when we return - no action we have performed has been made visible to another thread as the slot is still in a FILLING state.
-* `psa_destroy_key, psa_close_key, psa_purge_key` - As per the requirements, we need only argue for the case where the key is not in use here. The linearization point is the unlock after wiping the data and setting the slot state to EMPTY.
-* `psa_import_key, psa_copy_key, psa_generate_key, mbedtls_psa_register_se_key` - These functions call both `psa_start_key_creation` and `psa_finish_key_creation`, the linearization point of a successful call is the linearization point of the call to `psa_finish_key_creation`. The linearization point of an unsuccessful call is the linearization point of the call to `psa_fail_key_creation`.
-* `psa_key_derivation_output_key` - Same as above. If the operation object is in use by multiple threads, the behaviour need not be linearizable.
+* Key creation functions (including `psa_copy_key`) - The linearization point for a successful call is the mutex unlock within `psa_finish_key_creation`; it is at this point that the key becomes visible to other threads. The linearization point for a failed call is the closest mutex unlock after the failure is first identified.
+* `psa_destroy_key` - The linearization point for a successful destruction is the mutex unlock, the slot is now in the state `PSA_SLOT_PENDING_DELETION` meaning that the key has been destroyed. For failures, the linearization point is the same.
+* `psa_purge_key`, `psa_close_key` - The linearization point is the mutex unlock after wiping the slot for a success, or unregistering for a failure.
+* One shot operations - The linearization point is the final unlock of the mutex within `psa_get_and_lock_key_slot`, as that is the point in which it is decided whether or not the key exists.
+* Multi-part operations - The linearization point of the key input function is the final unlock of the mutex within `psa_get_and_lock_key_slot`. All other steps have no non resource-related side effects (except for key derivation, covered in the key creation functions).
 
-Library functions which operate on a slot will return `PSA_ERROR_BAD_STATE` if the slot is in an inappropriate state for the function at the linearization point.
+Please note that one shot operations and multi-part operations are not yet considered thread-safe, as we have not yet tested whether they rely on unprotected global resources. The key slot access in these operations is thread-safe.
 
-##### Key slot state transition diagram
+## Testing and analysis
 
-![](key-slot-state-transitions.png)
+### Thread-safe testing
 
-In the state transition diagram above, an arrow between two states `q1` and `q2` with label `f` indicates that if the state of a slot is `q1` immediately before `f`'s linearization point, it may be `q2` immediately after `f`'s linearization point.
+It is now possible for individual tests to spin up multiple threads. This work has made the global variables used in tests thread-safe. If multiple threads fail a test assert, the first failure will be reported with correct line numbers.
 
-##### Generating the key slot state transition diagram from source
+Although the `step` feature used in some tests is thread-safe, it may produce unexpected results for multi-threaded tests. `mbedtls_test_set_step` or `mbedtls_test_increment_step` calls within threads can happen in any order, thus may not produce the desired result when precise ordering is required.
 
-To generate the state transition diagram in https://app.diagrams.net/, open the following url:
+### Current state of testing
 
-https://viewer.diagrams.net/?tags=%7B%7D&highlight=FFFFFF&edit=_blank&layers=1&nav=1&title=key-slot-state-transitions#R5Vxbd5s4EP4t%2B%2BDH5iAJcXms4ySbrdtNT7qX9MWHgGyrxcABHNv59SsM2EhgDBhs3PVL0CANoBl9fDMaMkC3i%2FWDb3jzz65F7AGUrPUAjQYQAqBh9ieSbGKJIqFYMPOplXTaC57pO0mEUiJdUosEXMfQde2QerzQdB2HmCEnM3zfXfHdpq7NX9UzZiQneDYNOy%2F9h1rhPJZqUN3Lfyd0Nk%2BvDBQ9PrMw0s7JkwRzw3JXGRG6G6Bb33XD%2BGixviV2NHnpvMTj7g%2Bc3d2YT5ywyoDv4H08%2Ffvxj9VX3XGGw5cf3o9PHxJjvBn2MnngAVRspm9o0Td2OIsO7%2F8aj1Mx0585U9B5bgQTnxgW8YP07Ksv9he1bOcn3KSTzm6c2Zc1hqs5DcmzZ5jRmRVzsegK4cJmLcAOjcCLjT6la2LtVGUnJZmnN%2BKHZJ0RJZP0QNwFCf0N65KclbXEYDuPTdqrjP0T0Txj%2BlRmJB4322neG4UdJHapYSMACowkzphjfYy8nbVM2wgCavIT5btLx4pmaCSxFpscf%2FNvcmrbeMk2Rutsv9Emba1puBvEjl8y8v2QqJGOOGiNwF36Jjnul6Hhz0hY0k%2BO%2BxGLW8V522Zshwtsl8p8YhshfePXfpFBkys8uZQ92UHXwYrgE%2FFzJ6Oya1VUpOo3euancWplJKiNpymnduttu0k4wQFhzgGXjk9mNAiJv13seX9kBhkbr%2BxlwK9Xm86cyEeZQxCfCaJlSRnafkxOLKhlRTqGPgnou%2FG61Re5khc93PZx8XCAR4XOVb56RADYvTOSq3CwXAQM0g2UVJ2zxAd4mt%2BkaoAwxJ1OA9KNLasA%2Ft3np28v14nevQNvvXXwTmBYysAwKIXhHdxLWbiXjsB9c%2FCGFcEb9Au8ec%2FJgWxl7D7yDugYrFO6mXE4LzAmU4Pak59kMzEZXofUdfoM2ema6SNkJ5ohp1Qc3x1%2B51%2FF94%2Fj8eOXh17DMFIuDMNyldderTjnt18u0Lm4kXAVIz3dfRlt3b2inUZ347tvj39%2BuU4b9Y7PqF3RmepRZbPotTmdSdNOx%2BgM7BWdgRJ7%2BWkyVAGLJmWs8G9BLCs3KsAq1FTMGkhQX5XrAEUgTfJ5yY5WyHXYFSdk4YWbLeEJbDfsMdlJF1Qfuc5OjXwuegOKXtTt48sNbhIwxaMuGjL1K98VYYwkpRijMDjg0QBEWawUZJAmqc1QRpYElGG%2BjgSX7DoFVow0U%2BrQYH41cVW6uE7Gmg%2FM7rKu8mCDWvEpRSvUegboKaKfgi3Npf%2B2RZaYbZwv51492dMcg6rm3FGvMEhWMecwitowb4MVQZHIoQ9ADPMBY5PplizPwzes82imSlL5fUGhPzjSX9bK9LOD%2BI6bLp7RUDYBfTA9%2B50sH%2Bkz%2Fvi0rha6CVsGFQO4lNEZjjWxXfNnhtTV0GDabkCiobVGeUtm8uyo%2BtFjf9A%2FtVEb6A%2BQxntZO1k1nr5CfC7sR0X74K3QzixwVwxrMzyz2zy9XBHw%2B5WnhyrkvATjhoAPDuVWzsQpUVGsUwhDFglC392cDl%2FtQGVvIW63jFsIpmVN4aOZdBmc6L47HN5wkNc9xsmX4LfHwKs%2BTB6Eu57AE6N3mcwa0gBnbaSCorO1uaqsZpJ7CtDrXKQjHouQVn7P4l2iIzwWl%2BrvhsfmyyOup9JFbo3gsegeC47bEvh1kUgsNGT7%2BxSXxrfW6BzsFV4iIbzFTesukCpkCSvG72153HXtRZQumlYiRF3YcmqLPqVZzC4ThIWzc5ZKrspbEzwMdbg1UTUtiHsNKwpoCitCPZfSXfFtMSMprufiQsLeAkprhVwRoECekbQVj%2FG7GF0UchXb9UxV%2FcehoQkMNYcTXBFO%2BhXVwQNJ%2BNpwAgWWonRXHlrsdrDA7XJpoFzQUyN9tKIeyeXoryNvXr5Q26jQ2H0P1y6IAXQhEMuT3pwlz55TOohNfcESIXHSeMcSbbNAGpahrMs6RBoS9XLVGbAS0NRNA7GnyV4F6PxNqBK6UaG0%2B6HyJwJ6qTIA6ijDze%2Bso%2BxSPoToZXqpfK3%2Fz9JLT3S5Hk%2FhRNNmX9%2B%2B338yHccr%2FIyqHfLGlZw1%2BiSzM%2BpWtRC2X0VqSKgew2JeqDLc4iOZqvaoW6HPVWJuEQOzXcOaeMQPIlxxwi0ZY%2Ffk1q%2Ba2Gp6XVI7pM4JakrLN66DGpaiQAuIiGVQGIie6Pxnq6CAl6wAqu9Cv9gXl1VT%2F1VL9%2Fa74OmW%2Brk2T%2Fnkbu57gsolw4KiqrUde0WnLBnW3P9fj7j7%2Fr%2BjoLv%2FAA%3D%3D
+Our testing is a work in progress. It is not feasible to run our traditional, single-threaded, tests in such a way that tests concurrency. We need to write new test suites for concurrency testing.
 
-#### Destruction of a key in use
+Our tests currently only run on pthread, we hope to expand this in the future (our API already allows this).
 
-Problem: In [Key destruction long-term requirements](#key-destruction-long-term-requirements) we require that the key slot is destroyed (by `psa_wipe_key_slot`) even while it's in use (FILLING or with at least one reader).
+We run tests using [ThreadSanitizer](https://clang.llvm.org/docs/ThreadSanitizer.html) to detect data races. We test the key store, and test that our key slot state system is enforced. We also test the thread-safety of `psa_crypto_init`.
 
-How do we ensure that? This needs something more sophisticated than mutexes (concurrency number >2)! Even a per-slot mutex isn't enough (we'd need a reader-writer lock).
+Currently, not every API call is tested, we also cannot feasibly test every combination of concurrent API calls. API calls can in general be split into a few categories, each category calling the same internal key management functions in the same order - it is the internal functions that are in charge of locking mutexes and interacting with the key store; we test the thread-safety of these functions.
 
-Solution: after some team discussion, we've decided to rely on a new threading abstraction which mimics C11 (i.e. `mbedtls_fff` where `fff` is the C11 function name, having the same parameters and return type, with default implementations for C11, pthreads and Windows). We'll likely use condition variables in addition to mutexes.
+Since we do not run every cryptographic operation concurrently, we do not test that operations are free of unexpected global variables.
 
-##### Mutex only
+### Expanding testing
 
-When calling `psa_wipe_key_slot` it is the callers responsibility to set the slot state to PENDING_DELETION first. For most functions this is a clean {FULL, !has_readers} -> PENDING_DELETION transition: psa_get_empty_key_slot, psa_get_and_lock_key_slot, psa_close_key, psa_purge_key.
+Through future work on testing, it would be good to:
 
-`psa_wipe_all_key_slots` is only called from `mbedtls_psa_crypto_free`, here we will need to return an error as we won't be able to free the key store if a key is in use without compromising the state of the secure side. This is acceptable as an untrusted application cannot call `mbedtls_psa_crypto_free` in a crypto service. In a service integration, `mbedtls_psa_crypto_free` on the client cuts the communication with the crypto service. Also, this is the current behaviour.
+* For every API call, have a test which runs multiple copies of the call simultaneously.
+* After implementing other threading platforms, expand the tests to these platforms.
+* Have increased testing for kicking persistent keys out of slots.
+* Explicitly test that all global variables are protected, for this we would need to cover every operation in a concurrent scenario while running ThreadSanitizer.
+* Run tests on more threading implementations, once these implementations are supported.
 
-`psa_destroy_key` registers as a reader, marks the slot as deleted, deletes persistent keys and opaque keys and unregisters before returning. This will free the key ID, but the slot might be still in use. This only works if drivers are protected by a mutex (and the persistent storage as well if needed). `psa_destroy_key` transfers to PENDING_DELETION as an intermediate state. The last reading operation will wipe the key slot upon unregistering. In case of volatile keys freeing up the ID while the slot is still in use does not provide any benefit and we don't need to do it.
+### Performance
 
-These are serious limitations, but this can be implemented with mutexes only and arguably satisfies the [Key destruction short-term requirements](#key-destruction-short-term-requirements).
+Key loading does somewhat run in parallel, deriving the key and copying it key into the slot is not done under any mutex.
 
-Variations:
+Key destruction is entirely sequential, this is required for persistent keys to stop issues with re-loading keys which cannot otherwise be avoided without changing our approach to thread-safety.
 
-1. As a first step the multipart operations would lock the keys for reading on setup and release on free
-2. In a later stage this would be improved by locking the keys on entry into multi-part API calls and released before exiting.
 
-The second variant can't be implemented as a backward compatible improvement on the first as multipart operations that were successfully completed in the first case, would fail in the second. If we want to implement these incrementally, multipart operations in a multithreaded environment must be left unsupported in the first variant. This makes the first variant impractical (multipart operations returning an error in builds with multithreading enabled is not a behaviour that would be very useful to release).
+## Future work
 
-We can't reuse the `lock_count` field to mark key slots deleted, as we still need to keep track the lock count while the slot is marked for deletion. This means that we will need to add a new field to key slots. This new field can be reused to indicate whether the slot is occupied (see section [Determining whether a key slot is occupied](#determining-whether-a-key-slot-is-occupied)). (There would be three states: deleted, occupied, empty.)
+### Long term requirements
+
+As explained previously, we eventually aim to make the entirety of the PSA API thread-safe. This will build on the work that we have already completed. This requires a full suite of testing, see [Expanding testing](#expanding-testing) for details.
+
+### Long term performance requirements
+
+Our plan for cryptographic operations is that they are not performed under any global mutex. One-shot operations and multi-part operations will each only hold the global mutex for finding the relevant key in the key slot, and unregistering as a reader after the operation, using their own operation-specific mutexes to guard any shared data that they use.
+
+We aim to eventually replace some/all of the mutexes with RWLocks, if possible.
+
+### Long term key destruction requirements
+
+The [PSA Crypto Key destruction specification](https://arm-software.github.io/psa-api/crypto/1.1/api/keys/management.html#key-destruction) mandates that implementations make a best effort to ensure that the key material cannot be recovered. In the long term, it would be good to guarantee that `psa_destroy_key` wipes all copies of the key material.
+
+Here are our long term key destruction goals:
+
+`psa_destroy_key` does not block indefinitely, and when `psa_destroy_key` returns:
+
+1. The key identifier does not exist. This is a functional requirement for persistent keys: any thread can immediately create a new key with the same identifier.
+2. The resources from the key have been freed. This allows threads to create similar keys immediately after destruction, regardless of resources.
+4. No copy of the key material exists. Rationale: this is a security requirement. We do not have this requirement yet, but we need to document this as a security weakness, and we would like to satisfy this security requirement in the future.
 
 #### Condition variables
 
-Clean UNUSED -> PENDING_DELETION transition works as before.
+It would be ideal to add these to a future major version; we cannot add these as requirements to the default `MBEDTLS_THREADING_C` for backwards compatibility reasons.
 
-`psa_wipe_all_key_slots` and `psa_destroy_key` mark the slot as deleted and go to sleep until the slot has no registered readers. When waking up, they wipe the slot, and return.
+Condition variables would enable us to fulfil the final requirement in [Long term key destruction requirements](#long-term-key-destruction-requirements). Destruction would then work as follows:
 
-If the slot is already marked as deleted the threads calling `psa_wipe_all_key_slots` and `psa_destroy_key` go to sleep until the deletion completes. To satisfy [Key destruction long-term requirements](#key-destruction-long-term-requirements) none of the threads may return from the call until the slot is deleted completely. This can be achieved by signalling them when the slot has already been wiped and ready for use, that is not marked for deletion anymore. To handle spurious wake-ups, these threads need to be able to tell whether the slot was already deleted. This is not trivial, because by the time the thread wakes up, theoretically the slot might be in any state. It might have been reused and maybe even marked for deletion again.
+ * When a thread calls `psa_destroy_key`, they continue as normal until the `psa_unregister_read` call.
+ * Instead of calling `psa_unregister_read`, the thread waits until the condition `slot->registered_readers == 1` is true (the destroying thread is the final reader).
+ * At this point, the destroying thread directly calls `psa_wipe_key_slot`.
 
-To resolve this, we can either:
+A few changes are needed for this to follow our destruction requirements:
 
-1. Depend on the deletion marker. If the slot has been reused and is marked for deletion again, the threads keep waiting until the second deletion completes.
-2. Introduce a uuid (eg a global counter plus a slot ID), which is recorded by the thread waiting for deletion and checks whether it matches. If it doesn't, the function can return as the slot was already reallocated. If it does match, it can check whether it is still marked for deletion, if it is, the thread goes back to sleep, if it isn't, the function can return.
+ * Multi-part operations will need to remain registered as readers of their key slot until their copy of the key is destroyed, i.e. at the end of the finish/abort call.
+ * The functionality where `psa_unregister_read` can wipe the key slot will need to be removed, slot wiping is now only done by the destroying/wiping thread.
 
-##### Platform abstraction
+### Protecting operation contexts
 
-Introducing condition variables to the platform abstraction layer would be best done in a major version. If we can't wait until that, we will need to introduce a new compile time flag. Considering that this only will be needed on the PSA Crypto side and the upcoming split, it makes sense to make this flag responsible for the entire PSA Crypto threading support. Therefore if we want to keep the option open for implementing this in a backward compatible manner, we need to introduce and use this new flag already when implementing [Mutex only](#mutex-only). (If we keep the abstraction layer for mutexes the same, this shouldn't mean increase in code size and would mean only minimal effort on the porting side.)
+Currently, we rely on the crypto service to ensure that the same operation is not invoked concurrently. This abides by the PSA Crypto API Specification ([PSA Concurrent calling conventions](#psa-concurrent-calling-conventions)).
 
-#### Operation contexts
+Concurrent access to the same operation object can compromise the crypto service. For example, if the operation context has a pointer (depending on the compiler and the platform, the pointer assignment may or may not be atomic). This violates the functional correctness requirement of the crypto service.
 
-Concurrent access to the same operation context can compromise the crypto service for example if the operation context has a pointer (depending on the compiler and the platform, the pointer assignment may or may not be atomic). This violates the functional correctness requirement of the crypto service. (Concurrent calls to operations is undefined behaviour, but still should not compromise the CIA of the crypto service.)
+If, in future, we want to protect against this within the library then operations will require a status field protected by a global mutex. On entry, API calls would check the state and return an error if the state is ACTIVE. If the state is INACTIVE, then the call will set the state to ACTIVE, do the operation section and then restore the state to INACTIVE before returning.
 
-If we want to protect against this in the library, operations will need a status field protected by a global mutex similarly to key slots. On entry, API calls would check the state and return an error if it is already ACTIVE. Otherwise they set it to ACTIVE and restore it to INACTIVE before returning.
+### Future driver work
 
-Alternatively, protecting operation contexts can be left as the responsibility of the crypto service. The [PSA Crypto API Specification](https://arm-software.github.io/psa-api/crypto/1.1/overview/conventions.html#concurrent-calls) does not require the library to provide any protection in this case. A crypto service can easily add its own mutex in its operation structure wrapper (the same structure where it keeps track of which client connection owns that operation object).
+A future policy we may wish to enforce for drivers is:
 
-#### Drivers
-
-Each driver that hasn’t got the "thread_safe” property set has a dedicated mutex.
-
-Implementing "thread_safe” drivers depends on the condition variable protection in the key store, as we must guarantee that the core never starts the destruction of a key while there are operations in progress on it.
-
-Start with implementing threading for drivers without the "thread_safe” property (all drivers behave like the property wasn't set). Add "thread_safe" drivers at some point after the [Condition variables](#condition-variables) approach is implemented in the core.
-
-##### Reentrancy
-
-It is natural sometimes to want to perform cryptographic operations from a driver, for example calculating a hash as part of various other crypto primitives, or using a block cipher in a driver for a mode, etc. Also encrypting/authenticating communication with a secure element.
-
-**Non-thread-safe drivers:**
-
-A driver is non-thread-safe if the `thread-safe` property (see [Driver requirements](#driver-requirements)) is set to false.
+* By default, each driver only has at most one entry point active at any given time. In other words, each driver has its own exclusive lock.
+* Drivers have an optional `"thread_safe"` boolean property. If true, it allows concurrent calls to this driver.
+* Even with a thread-safe driver, the core never starts the destruction of a key while there are operations in progress on it, and never performs concurrent calls on the same multipart operation.
 
 In the non-thread-safe case we have these natural assumptions/requirements:
-1. Drivers don't call the core for any operation for which they provide an entry point
-2. The core doesn't hold the driver mutex between calls to entry points
 
-With these, the only way of a deadlock is when we have several drivers and they have circular dependencies. That is, Driver A makes a call that is despatched to Driver B and upon executing that Driver B makes a call that is despatched to Driver A. For example Driver A does CCM calls Driver B to do CBC-MAC, which in turn calls Driver A to do AES. This example is pretty contrived and it is hard to find a more practical example.
+1. Drivers don't call the core for any operation for which they provide an entry point.
+2. The core doesn't hold the driver mutex between calls to entry points.
+
+With these, the only way of a deadlock is when there are several drivers with circular dependencies. That is, Driver A makes a call that is dispatched to Driver B; upon executing this call Driver B makes a call that is dispatched to Driver A. For example Driver A does CCM, which calls driver B to do CBC-MAC, which in turn calls Driver A to perform AES.
 
 Potential ways for resolving this:
-1. Non-thread-safe drivers must not call the core
-2. Provide a new public API that drivers can safely call
-3. Make the dispatch layer public for drivers to call
+
+1. Non-thread-safe drivers must not call the core.
+2. Provide a new public API that drivers can safely call.
+3. Make the dispatch layer public for drivers to call.
 4. There is a whitelist of core APIs that drivers can call. Drivers providing entry points to these must not make a call to the core when handling these calls. (Drivers are still allowed to call any core API that can't have a driver entry point.)
 
 The first is too restrictive, the second and the third would require making it a stable API, and would likely increase the code size for a relatively rare feature. We are choosing the fourth as that is the most viable option.
 
 **Thread-safe drivers:**
 
-A driver is non-thread-safe if the `thread-safe` property (see [Driver requirements](#driver-requirements)) is set to true.
+A driver would be non-thread-safe if the `thread-safe` property is set to true.
 
-To make reentrancy in non-thread-safe drivers work, thread-safe drivers must not make a call to the core when handling a call that is on the non-thread-safe driver core API whitelist.
+To make re-entrancy in non-thread-safe drivers work, thread-safe drivers must not make a call to the core when handling a call that is on the non-thread-safe driver core API whitelist.
 
-Thread-safe drivers have less guarantees from the core and need to implement more complex logic and we can reasonably expect them to be more flexible in terms of reentrancy as well. At this point it is hard to see what further guarantees would be useful and feasible. Therefore, we don't provide any further guarantees for now.
+Thread-safe drivers have fewer guarantees from the core and need to implement more complex logic. We can reasonably expect them to be more flexible in terms of re-entrancy as well. At this point it is hard to see what further guarantees would be useful and feasible. Therefore, we don't provide any further guarantees for now.
 
-Thread-safe drivers must not make any assumption about the operation of the core beyond what is discussed in the [Reentrancy](#reentrancy) and [Driver requirements](#driver-requirements) sections.
-
-#### Global data
-
-PSA Crypto makes use of a `global_data` variable that will be accessible from multiple threads and needs to be protected. Any function accessing this variable (or its members) must take the corresponding lock first. Since `global_data` holds the RNG state, these will involve relatively expensive operations and therefore ideally `global_data` should be protected by its own, dedicated lock (different from the one protecting the key store).
-
-Note that this does not protect access to the RNG via `mbedtls_psa_get_random`, which is guaranteed to be thread-safe when `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is disabled. Still, doing so is conceptually simpler and we probably will want to remove the lower level mutex in the long run, since the corresponding interface will be removed from the public API. The two mutexes are different and are always taken in the same order, there is no risk of deadlock.
-
-The purpose of `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` is very similar to the driver interface (and might even be added to it in the long run), therefore it makes sense to handle it the same way. In particular, we can use the `global_data` mutex to protect it as a default and when we implement the "thread_safe” property for drivers, we implement it for `MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` as well.
-
-#### Implementation notes
-
-Since we only have simple mutexes, locking the same mutex from the same thread is a deadlock. Therefore functions taking the global mutex must not be called while holding the same mutex. Functions taking the mutex will document this fact and the implications.
-
-Releasing the mutex before a function call might introduce race conditions. Therefore might not be practical to take the mutex in low level access functions. If functions like that don't take the mutex, they need to rely on the caller to take it for them. These functions will document that the caller is required to hold the mutex.
-
-To avoid performance degradation, functions must hold mutexes for as short time as possible. In particular, they must not start expensive operations (eg. doing cryptography) while holding the mutex.
-
-## Strategy for 3.6
-
-The goal is to provide viable threading support without extending the platform abstraction. (Condition variables should be added in 4.0.) This means that we will be relying on mutexes only.
-
-- Key Store
-    - Slot states are described in the [Slot states](#slot-states) section. They guarantee safe concurrent access to slot contents.
-    - Slot states will be protected by a global mutex as described in the introduction of the [Global lock excluding slot content](#global-lock-excluding-slot-content) section.
-    - Simple key destruction strategy as described in the [Mutex only](#mutex-only) section (variant 2).
-    - The slot state and key attributes will be separated as described in the last paragraph of the [Determining whether a key slot is occupied](#determining-whether-a-key-slot-is-occupied) section.
-- The main `global_data` (the one in `psa_crypto.c`) shall be protected by its own mutex as described in the [Global data](#global-data) section.
-- The solution shall use the pre-existing `MBEDTLS_THREADING_C` threading abstraction. That is, the flag proposed in the [Platform abstraction](#platform-abstraction) section won't be implemented.
-- The core makes no additional guarantees for drivers. That is, Policy 1 in section [Driver requirements](#driver-requirements) applies.
+Thread-safe drivers must not make any assumption about the operation of the core beyond what is discussed here.
diff --git a/docs/architecture/testing/driver-interface-test-strategy.md b/docs/architecture/testing/driver-interface-test-strategy.md
index 380fd39..5fc5e18 100644
--- a/docs/architecture/testing/driver-interface-test-strategy.md
+++ b/docs/architecture/testing/driver-interface-test-strategy.md
@@ -114,7 +114,7 @@
 
 A PKCS#11 driver would be a good candidate. It would be useful as part of our product offering.
 
-## Transparent driver interface testing
+## Unified driver interface testing
 
 The [unified driver interface](../../proposed/psa-driver-interface.md) defines interfaces for accelerators.
 
@@ -128,6 +128,470 @@
 
 The driver interface includes a fallback mechanism so that a driver can reject a request at runtime and let another driver handle the request. For each entry point, there must be at least three test runs with two or more drivers available with driver A configured to fall back to driver B, with one run where A returns `PSA_SUCCESS`, one where A returns `PSA_ERROR_NOT_SUPPORTED` and B is invoked, and one where A returns a different error and B is not invoked.
 
-## Entropy and randomness interface testing
+### Test drivers
 
-TODO
+We have test drivers that are enabled by `PSA_CRYPTO_DRIVER_TEST` (not present
+in the usual config files, must be defined on the command line or in a custom
+config file). Those test drivers are implemented in `tests/src/drivers/*.c`
+and their API is declared in `tests/include/test/drivers/*.h`.
+
+We have two test driver registered: `mbedtls_test_opaque_driver` and
+`mbedtls_test_transparent_driver`. These are described in
+`scripts/data_files/driver_jsons/mbedtls_test_xxx_driver.json` (as much as our
+JSON support currently allows). Each of the drivers can potentially implement
+support for several mechanism; conversely, each of the file mentioned in the
+previous paragraph can potentially contribute to both the opaque and the
+transparent test driver.
+
+Each entry point is instrumented to record the number of hits for each part of
+the driver (same division as the files) and the status of the last call. It is
+also possible to force the next call to return a specified status, and
+sometimes more things can be forced: see the various
+`mbedtls_test_driver_XXX_hooks_t` structures declared by each driver (and
+subsections below).
+
+The drivers can use one of two back-ends:
+- internal: this requires the built-in implementation to be present.
+- libtestdriver1: this allows the built-in implementation to be omitted from
+  the build.
+
+Historical note: internal was initially the only back-end; then support for
+libtestdriver1 was added gradually. Support for libtestdriver1 is now complete
+(see following sub-sections), so we could remove internal now. Note it's
+useful to have builds with both a driver and the built-in, in order to test
+fallback to built-in, which is currently done only with internal, but this can
+be achieved with libtestdriver1 just as well.
+
+Note on instrumentation: originally, when only the internal backend was
+available, hits were how we knew that the driver was called, as opposed to
+directly calling the built-in code. With libtestdriver1, we can check that by
+ensuring that the built-in code is not present, so if the operation gives the
+correct result, only a driver call can have calculated that result. So,
+nowadays there is low value in checking the hit count. There is still some
+value for hit counts, e.g. checking that we don't call a multipart entry point
+when we intended to call the one-shot entry point, but it's limited.
+
+Note: our test drivers tend to provide all possible entry points (with a few
+exceptions that may not be intentional, see the next sections). However, in
+some cases, when an entry point is not available, the core is supposed to
+implement it using other entry points, for example:
+- `mac_verify` may use `mac_compute` if the driver does no provide verify;
+- for things that have both one-shot and multi-part API, the driver can
+  provide only the multi-part entry points, and the core is supposed to
+implement one-shot on top of it (but still call the one-shot entry points when
+they're available);
+- `sign/verify_message` can be implemented on top of `sign/verify_hash` for
+  some algorithms;
+- (not sure if the list is exhaustive).
+
+Ideally, we'd want build options for the test drivers so that we can test with
+different combinations of entry points present, and make sure the core behaves
+appropriately when some entry points are absent but other entry points allow
+implementing the operation. This will remain hard to test until we have proper
+support for JSON-defined drivers with auto-generation of dispatch code.
+(The `MBEDTLS_PSA_ACCEL_xxx` macros we currently use are not expressive enough
+to specify which entry points are supported for a given mechanism.)
+
+Our implementation of PSA Crypto is structured in a way that the built-in
+implementation of each operation follows the driver API, see
+[`../architecture/psa-crypto-implementation-structure.md`](../architecture/psa-crypto-implementation-structure.html).
+This makes implementing the test drivers very easy: each entry point has a
+corresponding `mbedtls_psa_xxx()` function that it can call as its
+implementation - with the `libtestdriver1` back-end the function is called
+`libtestdriver1_mbedtls_psa_xxx()` instead.
+
+A nice consequence of that strategy is that when an entry point has
+test-driver support, most of the time, it automatically works for all
+algorithms and key types supported by the library. (The exception being when
+the driver needs to call a different function for different key types, as is
+the case with some asymmetric key management operations.) (Note: it's still
+useful to test drivers in configurations with partial algorithm support, and
+that can still be done by configuring libtestdriver1 and the main library as
+desired.)
+
+The renaming process for `libtestdriver1` is implemented as a few Perl regexes
+applied to a copy of the library code, see the `libtestdriver1.a` target in
+`tests/Makefile`. Another modification that's done to this copy is appending
+`tests/include/test/drivers/crypto_config_test_driver_extension.h` to
+`psa/crypto_config.h`. This file reverses the `ACCEL`/`BUILTIN` macros so that
+`libtestdriver1` includes as built-in what the main `libmbedcrypto.a` will
+have accelerated; see that file's initial comment for details. See also
+`helper_libtestdriver1_` functions and the preceding comment in `all.sh` for
+how libtestdriver is used in practice.
+
+This general framework needs specific code for each family of operations. At a
+given point in time, not all operations have the same level of support. The
+following sub-sections describe the status of the test driver support, mostly
+following the structure and order of sections 9.6 and 10.2 to 10.10 of the
+[PSA Crypto standard](https://arm-software.github.io/psa-api/crypto/1.1/) as
+that is also a natural division for implementing test drivers (that's how the
+code is divided into files).
+
+#### Key management
+
+The following entry points are declared in `test/drivers/key_management.h`:
+
+- `"init"` (transparent and opaque)
+- `"generate_key"` (transparent and opaque)
+- `"export_public_key"` (transparent and opaque)
+- `"import_key"` (transparent and opaque)
+- `"export_key"` (opaque only)
+- `"get_builtin_key"` (opaque only)
+- `"copy_key"` (opaque only)
+
+The transparent driver fully implements the declared entry points, and can use
+any backend: internal or libtestdriver1.
+
+The opaque's driver implementation status is as follows:
+- `"generate_key"`: not implemented, always returns `NOT_SUPPORTED`.
+- `"export_public_key"`: implemented only for ECC and RSA keys, both backends.
+- `"import_key"`: implemented except for DH keys, both backends.
+- `"export_key"`: implemented for built-in keys (ECC and AES), and for
+  non-builtin keys except DH keys. (Backend not relevant.)
+- `"get_builtin_key"`: implemented - provisioned keys: AES-128 and ECC
+  secp2456r1. (Backend not relevant.)
+- `"copy_key"`: implemented - emulates a SE without storage. (Backend not
+  relevant.)
+
+Note: the `"init"` entry point is not part of the "key management" family, but
+listed here as it's declared and implemented in the same file. With the
+transparent driver and the libtestdriver1 backend, it calls
+`libtestdriver1_psa_crypto_init()`, which partially but not fully ensures
+that this entry point is called before other entry points in the test drivers.
+With the opaque driver, this entry point just does nothing an returns success.
+
+The following entry points are defined by the driver interface but missing
+from our test drivers:
+- `"allocate_key"`, `"destroy_key"`: this is for opaque drivers that store the
+  key material internally.
+
+Note: the instrumentation also allows forcing the output and its length.
+
+#### Message digests (Hashes)
+
+The following entry points are declared (transparent only):
+- `"hash_compute"`
+- `"hash_setup"`
+- `"hash_clone"`
+- `"hash_update"`
+- `"hash_finish"`
+- `"hash_abort"`
+
+The transparent driver fully implements the declared entry points, and can use
+any backend: internal or libtestdriver1.
+
+This familly is not part of the opaque driver as it doesn't use keys.
+
+#### Message authentication codes (MAC)
+
+The following entry points are declared (transparent and opaque):
+- `"mac_compute"`
+- `"mac_sign_setup"`
+- `"mac_verify_setup"`
+- `"mac_update"`
+- `"mac_sign_finish"`
+- `"mac_verify_finish"`
+- `"mac_abort"`
+
+The transparent driver fully implements the declared entry points, and can use
+any backend: internal or libtestdriver1.
+
+The opaque driver only implements the instrumentation but not the actual
+operations: entry points will always return `NOT_SUPPORTED`, unless another
+status is forced.
+
+The following entry points are not implemented:
+- `mac_verify`: this mostly makes sense for opaque drivers; the core will fall
+  back to using `"mac_compute"` if this is not implemented. So, perhaps
+ideally we should test both with `"mac_verify"` implemented and with it not
+implemented? Anyway, we have a test gap here.
+
+#### Unauthenticated ciphers
+
+The following entry points are declared (transparent and opaque):
+- `"cipher_encrypt"`
+- `"cipher_decrypt"`
+- `"cipher_encrypt_setup"`
+- `"cipher_decrypt_setup"`
+- `"cipher_set_iv"`
+- `"cipher_update"`
+- `"cipher_finish"`
+- `"cipher_abort"`
+
+The transparent driver fully implements the declared entry points, and can use
+any backend: internal or libtestdriver1.
+
+The opaque driver is not implemented at all, neither instumentation nor the
+operation: entry points always return `NOT_SUPPORTED`.
+
+Note: the instrumentation also allows forcing a specific output and output
+length.
+
+#### Authenticated encryption with associated data (AEAD)
+
+The following entry points are declared (transparent only):
+- `"aead_encrypt"`
+- `"aead_decrypt"`
+- `"aead_encrypt_setup"`
+- `"aead_decrypt_setup"`
+- `"aead_set_nonce"`
+- `"aead_set_lengths"`
+- `"aead_update_ad"`
+- `"aead_update"`
+- `"aead_finish"`
+- `"aead_verify"`
+- `"aead_abort"`
+
+The transparent driver fully implements the declared entry points, and can use
+any backend: internal or libtestdriver1.
+
+The opaque driver does not implement or even declare entry points for this
+family.
+
+Note: the instrumentation records the number of hits per entry point, not just
+the total number of hits for this family.
+
+#### Key derivation
+
+Not covered at all by the test drivers.
+
+That's a test gap which reflects a feature gap: the driver interface does
+define a key derivation family of entry points, but we don't currently
+implement that part of the driver interface, see #5488 and related issues.
+
+#### Asymmetric signature
+
+The following entry points are declared (transparent and opaque):
+
+- `"sign_message"`
+- `"verify_message"`
+- `"sign_hash"`
+- `"verify_hash"`
+
+The transparent driver fully implements the declared entry points, and can use
+any backend: internal or libtestdriver1.
+
+The opaque driver is not implemented at all, neither instumentation nor the
+operation: entry points always return `NOT_SUPPORTED`.
+
+Note: the instrumentation also allows forcing a specific output and output
+length, and has two instance of the hooks structure: one for sign, the other
+for verify.
+
+Note: when a driver implements only the `"xxx_hash"` entry points, the core is
+supposed to implement the `psa_xxx_message()` functions by computing the hash
+itself before calling the `"xxx_hash"` entry point. Since the test driver does
+implement the `"xxx_message"` entry point, it's not exercising that part of
+the core's expected behaviour.
+
+#### Asymmetric encryption
+
+The following entry points are declared (transparent and opaque):
+
+- `"asymmetric_encrypt"`
+- `"asymmetric_decrypt"`
+
+The transparent driver fully implements the declared entry points, and can use
+any backend: internal or libtestdriver1.
+
+The opaque driver implements the declared entry points, and can use any
+backend: internal or libtestdriver1. However it does not implement the
+instrumentation (hits, forced output/status), as this [was not an immediate
+priority](https://github.com/Mbed-TLS/mbedtls/pull/8700#issuecomment-1892466159).
+
+Note: the instrumentation also allows forcing a specific output and output
+length.
+
+#### Key agreement
+
+The following entry points are declared (transparent and opaque):
+
+- `"key_agreement"`
+
+The transparent driver fully implements the declared entry points, and can use
+any backend: internal or libtestdriver1.
+
+The opaque driver is not implemented at all, neither instumentation nor the
+operation: entry points always return `NOT_SUPPORTED`.
+
+Note: the instrumentation also allows forcing a specific output and output
+length.
+
+#### Other cryptographic services (Random number generation)
+
+Not covered at all by the test drivers.
+
+The driver interface defines a `"get_entropy"` entry point, as well as a
+"Random generation" family of entry points. None of those are currently
+implemented in the library. Part of it will be planned for 4.0, see #8150.
+
+#### PAKE extension
+
+The following entry points are declared (transparent only):
+- `"pake_setup"`
+- `"pake_output"`
+- `"pake_input"`
+- `"pake_get_implicit_key"`
+- `"pake_abort"`
+
+Note: the instrumentation records hits per entry point and allows forcing the
+output and its length, as well as forcing the status of setup independently
+from the others.
+
+The transparent driver fully implements the declared entry points, and can use
+any backend: internal or libtestdriver1.
+
+The opaque driver does not implement or even declare entry points for this
+family.
+
+### Driver wrapper test suite
+
+We have a test suite dedicated to driver dispatch, which takes advantage of the
+instrumentation in the test drivers described in the previous section, in
+order to check that drivers are called when they're supposed to, and that the
+core behaves as expected when they return errors (in particular, that we fall
+back to the built-in implementation when the driver returns `NOT_SUPPORTED`).
+
+This is `test_suite_psa_crypto_driver_wrappers`, which is maintained manually
+(that is, the test cases in the `.data` files are not auto-generated). The
+entire test suite depends on the test drivers being enabled
+(`PSA_CRYPTO_DRIVER_TEST`), which is not the case in the default or full
+config.
+
+The test suite is focused on driver usage (mostly by checking the expected
+number of hits) but also does some validation of the results: for
+deterministic algorithms, known-answers tests are used, and for the rest, some
+consistency checks are done (more or less detailled depending on the algorithm
+and build configuration).
+
+#### Configurations coverage
+
+The driver wrappers test suite has cases that expect both the driver and the
+built-in to be present, and also cases that expect the driver to be present
+but not the built-in. As such, it's impossible for a single configuration to
+run all test cases, and we need at least two: driver+built-in, and
+driver-only.
+
+- The driver+built-in case is covered by `test_psa_crypto_drivers` in `all.sh`.
+This covers all areas (key types and algs) at once.
+- The driver-only case is split into multiple `all.sh` components whose names
+  start with `test_psa_crypto_config_accel`; we have one or more component per
+area, see below.
+
+Here's a summary of driver-only coverage, grouped by families of key types.
+
+Hash (key types: none)
+- `test_psa_crypto_config_accel_hash`: all algs, default config, no parity
+  testing.
+- `test_psa_crypto_config_accel_hash_use_psa`: all algs, full config, with
+  parity testing.
+
+HMAC (key type: HMAC)
+- `test_psa_crypto_config_accel_hmac`: all algs, full config except a few
+  exclusions (PKCS5, PKCS7, HMAC-DRBG, legacy HKDF, deterministic ECDSA), with
+parity testing.
+
+Cipher, AEAD and CMAC (key types: DES, AES, ARIA, CHACHA20, CAMELLIA):
+- `test_psa_crypto_config_accel_cipher_aead_cmac`: all key types and algs, full
+  config with a few exclusions (NIST-KW), with parity testing.
+- `test_psa_crypto_config_accel_des`: only DES (with all algs), full
+  config, no parity testing.
+- `test_psa_crypto_config_accel_aead`: only AEAD algs (with all relevant key
+  types), full config, no parity testing.
+
+Key derivation (key types: `DERIVE`, `RAW_DATA`, `PASSWORD`, `PEPPER`,
+`PASSWORD_HASH`):
+- No testing as we don't have driver support yet (see previous section).
+
+RSA (key types: `RSA_KEY_PAIR_xxx`, `RSA_PUBLIC_KEY`):
+- `test_psa_crypto_config_accel_rsa_crypto`: all 4 algs (encryption &
+  signature, v1.5 & v2.1), config `crypto_full`, with parity testing excluding
+PK.
+
+DH (key types: `DH_KEY_PAIR_xxx`, `DH_PUBLIC_KEY`):
+- `test_psa_crypto_config_accel_ffdh`: all key types and algs, full config,
+  with parity testing.
+- `test_psa_crypto_config_accel_ecc_ffdh_no_bignum`: with also bignum removed.
+
+ECC (key types: `ECC_KEY_PAIR_xxx`, `ECC_PUBLIC_KEY`):
+- Single algorithm accelerated (both key types, all curves):
+  - `test_psa_crypto_config_accel_ecdh`: default config, no parity testing.
+  - `test_psa_crypto_config_accel_ecdsa`: default config, no parity testing.
+  - `test_psa_crypto_config_accel_pake`: full config, no parity testing.
+- All key types, algs and curves accelerated (full config with exceptions,
+  with parity testing):
+  - `test_psa_crypto_config_accel_ecc_ecp_light_only`: `ECP_C` mostly disabled
+  - `test_psa_crypto_config_accel_ecc_no_ecp_at_all`: `ECP_C` fully disabled
+  - `test_psa_crypto_config_accel_ecc_no_bignum`: `BIGNUM_C` disabled (DH disabled)
+  - `test_psa_crypto_config_accel_ecc_ffdh_no_bignum`: `BIGNUM_C` disabled (DH accelerated)
+- Other - all algs accelerated but only some algs/curves (full config with
+  exceptions, no parity testing):
+  - `test_psa_crypto_config_accel_ecc_some_key_types`
+  - `test_psa_crypto_config_accel_ecc_non_weierstrass_curves`
+  - `test_psa_crypto_config_accel_ecc_weierstrass_curves`
+
+Note: `analyze_outcomes.py` provides a list of test cases that are not
+executed in any configuration tested on the CI. We're missing driver-only HMAC
+testing, but no test is flagged as never executed there; this reveals we don't
+have "fallback not available" cases for MAC, see #8565.
+
+#### Test case coverage
+
+Since `test_suite_psa_crypto_driver_wrappers.data` is maintained manually,
+we need to make sure it exercises all the cases that need to be tested. In the
+future, this file should be generated in order to ensure exhaustiveness.
+
+In the meantime, one way to observe (lack of) completeness is to look at line
+coverage in test driver implementaitons - this doesn't reveal all gaps, but it
+does reveal cases where we thought about something when writing the test
+driver, but not when writing test functions/data.
+
+Key management:
+- `mbedtls_test_transparent_generate_key()` is not tested with RSA keys.
+- `mbedtls_test_transparent_import_key()` is not tested with DH keys.
+- `mbedtls_test_opaque_import_key()` is not tested with unstructured keys nor
+  with RSA keys (nor DH keys since that's not implemented).
+- `mbedtls_test_opaque_export_key()` is not tested with non-built-in keys.
+- `mbedtls_test_transparent_export_public_key()` is not tested with RSA or DH keys.
+- `mbedtls_test_opaque_export_public_key()` is not tested with non-built-in keys.
+- `mbedtls_test_opaque_copy_key()` is not tested at all.
+
+Hash:
+- `mbedtls_test_transparent_hash_finish()` is not tested with a forced status.
+
+MAC:
+- The following are not tested with a forced status:
+  - `mbedtls_test_transparent_mac_sign_setup()`
+  - `mbedtls_test_transparent_mac_verify_setup()`
+  - `mbedtls_test_transparent_mac_update()`
+  - `mbedtls_test_transparent_mac_verify_finish()`
+  - `mbedtls_test_transparent_mac_abort()`
+- No opaque entry point is tested (they're not implemented either).
+
+Cipher:
+- The following are not tested with a forced status nor with a forced output:
+  - `mbedtls_test_transparent_cipher_encrypt()`
+  - `mbedtls_test_transparent_cipher_finish()`
+- No opaque entry point is tested (they're not implemented either).
+
+AEAD:
+- The following are not tested with a forced status:
+  - `mbedtls_test_transparent_aead_set_nonce()`
+  - `mbedtls_test_transparent_aead_set_lengths()`
+  - `mbedtls_test_transparent_aead_update_ad()`
+  - `mbedtls_test_transparent_aead_update()`
+  - `mbedtls_test_transparent_aead_finish()`
+  - `mbedtls_test_transparent_aead_verify()`
+- `mbedtls_test_transparent_aead_verify()` is not tested with an invalid tag
+  (though it might be in another test suite).
+
+Signature:
+- `sign_hash()` is not tested with RSA-PSS
+- No opaque entry point is tested (they're not implemented either).
+
+Key agreement:
+- `mbedtls_test_transparent_key_agreement()` is not tested with FFDH.
+- No opaque entry point is tested (they're not implemented either).
+
+PAKE:
+- All lines are covered.
diff --git a/docs/architecture/tls13-support.md b/docs/architecture/tls13-support.md
index 6db0e54..d6fc19e 100644
--- a/docs/architecture/tls13-support.md
+++ b/docs/architecture/tls13-support.md
@@ -4,17 +4,8 @@
 Overview
 --------
 
-Mbed TLS provides a partial implementation of the TLS 1.3 protocol defined in
-the "Support description" section below. The TLS 1.3 support enablement
-is controlled by the MBEDTLS_SSL_PROTO_TLS1_3 configuration option.
-
-The development of the TLS 1.3 protocol is based on the TLS 1.3 prototype
-located at https://github.com/hannestschofenig/mbedtls. The prototype is
-itself based on a version of the development branch that we aim to keep as
-recent as possible (ideally the head) by merging regularly commits of the
-development branch into the prototype. The section "Prototype upstreaming
-status" below describes what remains to be upstreamed.
-
+Mbed TLS provides an implementation of the TLS 1.3 protocol. The TLS 1.3 support
+may be enabled using the MBEDTLS_SSL_PROTO_TLS1_3 configuration option.
 
 Support description
 -------------------
@@ -26,14 +17,14 @@
 
   - Mbed TLS supports ECDHE key establishment.
 
-  - Mbed TLS does not support DHE key establishment.
+  - Mbed TLS supports DHE key establishment.
 
   - Mbed TLS supports pre-shared keys for key establishment, pre-shared keys
     provisioned externally as well as provisioned via the ticket mechanism.
 
   - Mbed TLS supports session resumption via the ticket mechanism.
 
-  - Mbed TLS does not support sending or receiving early data (0-RTT data).
+  - Mbed TLS supports sending and receiving early data (0-RTT data).
 
 - Supported cipher suites: depends on the library configuration. Potentially
   all of them:
@@ -51,7 +42,7 @@
   | signature_algorithms         | YES     |
   | use_srtp                     | no      |
   | heartbeat                    | no      |
-  | apln                         | YES     |
+  | alpn                         | YES     |
   | signed_certificate_timestamp | no      |
   | client_certificate_type      | no      |
   | server_certificate_type      | no      |
@@ -59,7 +50,7 @@
   | key_share                    | YES     |
   | pre_shared_key               | YES     |
   | psk_key_exchange_modes       | YES     |
-  | early_data                   | no      |
+  | early_data                   | YES     |
   | cookie                       | no      |
   | supported_versions           | YES     |
   | certificate_authorities      | no      |
@@ -71,7 +62,8 @@
   Potentially all ECDHE groups:
   secp256r1, x25519, secp384r1, x448 and secp521r1.
 
-  Finite field groups (DHE) are not supported.
+  Potentially all DHE groups:
+  ffdhe2048, ffdhe3072, ffdhe4096, ffdhe6144 and ffdhe8192.
 
 - Supported signature algorithms (both for certificates and CertificateVerify):
   depends on the library configuration.
@@ -105,7 +97,7 @@
 
   | Mbed TLS configuration option            | Support |
   | ---------------------------------------- | ------- |
-  | MBEDTLS_SSL_ALL_ALERT_MESSAGES           | no      |
+  | MBEDTLS_SSL_ALL_ALERT_MESSAGES           | yes     |
   | MBEDTLS_SSL_ASYNC_PRIVATE                | no      |
   | MBEDTLS_SSL_CONTEXT_SERIALIZATION        | no      |
   | MBEDTLS_SSL_DEBUG_ALL                    | no      |
@@ -167,33 +159,6 @@
     TLS 1.3 specification.
 
 
-Prototype upstreaming status
-----------------------------
-
-The following parts of the TLS 1.3 prototype remain to be upstreamed:
-
-- Sending (client) and receiving (server) early data (0-RTT data).
-
-- New TLS Message Processing Stack (MPS)
-
-  The TLS 1.3 prototype is developed alongside a rewrite of the TLS messaging layer,
-  encompassing low-level details such as record parsing, handshake reassembly, and
-  DTLS retransmission state machine.
-
-  MPS has the following components:
-  - Layer 1 (Datagram handling)
-  - Layer 2 (Record handling)
-  - Layer 3 (Message handling)
-  - Layer 4 (Retransmission State Machine)
-  - Reader  (Abstracted pointer arithmetic and reassembly logic for incoming data)
-  - Writer  (Abstracted pointer arithmetic and fragmentation logic for outgoing data)
-
-  Of those components, the following have been upstreamed
-  as part of `MBEDTLS_SSL_PROTO_TLS1_3`:
-
-  - Reader ([`library/mps_reader.h`](../../library/mps_reader.h))
-
-
 Coding rules checklist for TLS 1.3
 ----------------------------------
 
@@ -266,10 +231,6 @@
     - the macro to check for data when reading from an input buffer
       `MBEDTLS_SSL_CHK_BUF_READ_PTR`.
 
-    These macros were introduced after the prototype was written thus are
-    likely not to be used in prototype where we now would use them in
-    development.
-
     The three first types, MBEDTLS_BYTE_{0-8}, MBEDTLS_PUT_UINT{8|16|32|64}_BE
     and MBEDTLS_GET_UINT{8|16|32|64}_BE improve the readability of the code and
     reduce the risk of writing or reading bytes in the wrong order.
@@ -472,175 +433,3 @@
 
 * state change: the state change is done in the main state handler to ease
 the navigation of the state machine transitions.
-
-
-Writing and reading early or 0-RTT data
----------------------------------------
-
-An application function to write and send a buffer of data to a server through
-TLS may plausibly look like:
-
-```
-int write_data( mbedtls_ssl_context *ssl,
-                const unsigned char *data_to_write,
-                size_t data_to_write_len,
-                size_t *data_written )
-{
-    *data_written = 0;
-
-    while( *data_written < data_to_write_len )
-    {
-        ret = mbedtls_ssl_write( ssl, data_to_write + *data_written,
-                                 data_to_write_len - *data_written );
-
-        if( ret < 0 &&
-            ret != MBEDTLS_ERR_SSL_WANT_READ &&
-            ret != MBEDTLS_ERR_SSL_WANT_WRITE )
-        {
-            return( ret );
-        }
-
-        *data_written += ret;
-    }
-
-    return( 0 );
-}
-```
-where ssl is the SSL context to use, data_to_write the address of the data
-buffer and data_to_write_len the number of data bytes. The handshake may
-not be completed, not even started for the SSL context ssl when the function is
-called and in that case the mbedtls_ssl_write() API takes care transparently of
-completing the handshake before to write and send data to the server. The
-mbedtls_ssl_write() may not been able to write and send all data in one go thus
-the need for a loop calling it as long as there are still data to write and
-send.
-
-An application function to write and send early data and only early data,
-data sent during the first flight of client messages while the handshake is in
-its initial phase, would look completely similar but the call to
-mbedtls_ssl_write_early_data() instead of mbedtls_ssl_write().
-```
-int write_early_data( mbedtls_ssl_context *ssl,
-                      const unsigned char *data_to_write,
-                      size_t data_to_write_len,
-                      size_t *data_written )
-{
-    *data_written = 0;
-
-    while( *data_written < data_to_write_len )
-    {
-        ret = mbedtls_ssl_write_early_data( ssl, data_to_write + *data_written,
-                                            data_to_write_len - *data_written );
-
-        if( ret < 0 &&
-            ret != MBEDTLS_ERR_SSL_WANT_READ &&
-            ret != MBEDTLS_ERR_SSL_WANT_WRITE )
-        {
-            return( ret );
-        }
-
-        *data_written += ret;
-    }
-
-    return( 0 );
-}
-```
-Note that compared to write_data(), write_early_data() can also return
-MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA and that should be handled
-specifically by the user of write_early_data(). A fresh SSL context (typically
-just after a call to mbedtls_ssl_setup() or mbedtls_ssl_session_reset()) would
-be expected when calling `write_early_data`.
-
-All together, code to write and send a buffer of data as long as possible as
-early data and then as standard post-handshake application data could
-plausibly look like:
-
-```
-ret = write_early_data( ssl, data_to_write, data_to_write_len,
-                        &early_data_written );
-if( ret < 0 &&
-    ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA )
-{
-    goto error;
-}
-
-ret = write_data( ssl, data_to_write + early_data_written,
-                  data_to_write_len - early_data_written, &data_written );
-if( ret < 0 )
-    goto error;
-
-data_written += early_data_written;
-```
-
-Finally, taking into account that the server may reject early data, application
-code to write and send a buffer of data could plausibly look like:
-```
-ret = write_early_data( ssl, data_to_write, data_to_write_len,
-                        &early_data_written );
-if( ret < 0 &&
-    ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA )
-{
-    goto error;
-}
-
-/*
- * Make sure the handshake is completed as it is a requisite to
- * mbedtls_ssl_get_early_data_status().
- */
-while( !mbedtls_ssl_is_handshake_over( ssl ) )
-{
-    ret = mbedtls_ssl_handshake( ssl );
-    if( ret < 0 &&
-        ret != MBEDTLS_ERR_SSL_WANT_READ &&
-        ret != MBEDTLS_ERR_SSL_WANT_WRITE )
-    {
-        goto error;
-    }
-}
-
-ret = mbedtls_ssl_get_early_data_status( ssl );
-if( ret < 0 )
-    goto error;
-
-if( ret == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED )
-   early_data_written = 0;
-
-ret = write_data( ssl, data_to_write + early_data_written,
-                  data_to_write_len - early_data_written, &data_written );
-if( ret < 0 )
-    goto error;
-
-data_written += early_data_written;
-```
-
-Basically, the same holds for reading early data on the server side without the
-complication of possible rejection. An application function to read early data
-into a given buffer could plausibly look like:
-```
-int read_early_data( mbedtls_ssl_context *ssl,
-                     unsigned char *buffer,
-                     size_t buffer_size,
-                     size_t *data_len )
-{
-    *data_len = 0;
-
-    while( *data_len < buffer_size )
-    {
-        ret = mbedtls_ssl_read_early_data( ssl, buffer + *data_len,
-                                           buffer_size - *data_len );
-
-        if( ret < 0 &&
-            ret != MBEDTLS_ERR_SSL_WANT_READ &&
-            ret != MBEDTLS_ERR_SSL_WANT_WRITE )
-        {
-            return( ret );
-        }
-
-        *data_len += ret;
-    }
-
-    return( 0 );
-}
-```
-with again calls to read_early_data() expected to be done with a fresh SSL
-context.
diff --git a/docs/psa-transition.md b/docs/psa-transition.md
index 94b57eb..bbb7da2 100644
--- a/docs/psa-transition.md
+++ b/docs/psa-transition.md
@@ -50,7 +50,7 @@
 
 To make the PSA API available, make sure that the configuration option [`MBEDTLS_PSA_CRYPTO_C`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/mbedtls__config_8h/#c.MBEDTLS_PSA_CRYPTO_C) is enabled. (It is enabled in the default configuration.)
 
-You should probably enable [`MBEDTLS_USE_PSA_CRYPTO`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/mbedtls__config_8h/#mbedtls__config_8h_1a70fd7b97d5f11170546583f2095942a6) as well (it is disabled by default). This option causes the PK, X.509 and TLS modules to use PSA crypto under the hood. Some functions that facilitate the transition (for example, to convert between metadata encodings or between key representations) are only available when `MBEDTLS_USE_PSA_CRYPTO` is enabled.
+You should probably enable [`MBEDTLS_USE_PSA_CRYPTO`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/mbedtls__config_8h/#mbedtls__config_8h_1a70fd7b97d5f11170546583f2095942a6) as well (it is disabled by default). This option causes the PK, X.509 and TLS modules to use PSA crypto under the hood.
 
 By default, the PSA crypto API offers a similar set of cryptographic mechanisms as those offered by the legacy API (configured by `MBEDTLS_XXX` macros). The PSA crypto API also has its own configuration mechanism; see “[Cryptographic mechanism availability](#cryptographic-mechanism-availability)”.
 
@@ -779,9 +779,9 @@
 
 The easiest way to create a key pair object is by randomly generating it with [`psa_generate_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__random/#group__random_1ga1985eae417dfbccedf50d5fff54ea8c5). Compared with the low-level functions from the legacy API (`mbedtls_rsa_gen_key`, `mbedtls_ecp_gen_privkey`, `mbedtls_ecp_gen_keypair`, `mbedtls_ecp_gen_keypair_base`, `mbedtls_ecdsa_genkey`), this directly creates an object that can be used with high-level APIs, but removes some of the flexibility. Note that if you want to export the generated private key, you must pass the flag [`PSA_KEY_USAGE_EXPORT`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__policy/#group__policy_1ga7dddccdd1303176e87a4d20c87b589ed) to [`psa_set_key_usage_flags`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga42a65b3c4522ce9b67ea5ea7720e17de); exporting the public key with [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) is always permitted.
 
-For RSA keys, `psa_generate_key` always uses 65537 as the public exponent. If you need a different public exponent, use the legacy interface to create the key then import it as described in “[Importing legacy keys via the PK module](#importing-legacy-keys-via-the-pk-module)”.
+For RSA keys, `psa_generate_key` uses 65537 as the public exponent. You can use [`psa_generate_key_ext`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__random/#group__random_1ga6776360ae8046a4456a5f990f997da58) to select a different public exponent. As of Mbed TLS 3.6.0, selecting a different public exponent is only supported with the built-in RSA implementation, not with PSA drivers.
 
-To create a key object from existing material, use [`psa_import_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga0336ea76bf30587ab204a8296462327b). While this function has the same basic goal as the PK parse functions (`mbedtls_pk_parse_key`, `mbedtls_pk_parse_public_key`, `mbedtls_pk_parse_subpubkey`), it is limited to a single format that just contains the number(s) that make up the key, with very little metadata. This format is a substring of one of the formats accepted by the PK functions (except for finite-field Diffie-Hellman which the PK module does not support). The table below summarizes the PSA import/export format for key pairs and public keys; see the documentation of [`psa_export_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga668e35be8d2852ad3feeef74ac6f75bf) and [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) for more details.
+To create a key object from existing material, use [`psa_import_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga0336ea76bf30587ab204a8296462327b). This function has the same basic goal as the PK parse functions (`mbedtls_pk_parse_key`, `mbedtls_pk_parse_public_key`, `mbedtls_pk_parse_subpubkey`), but only supports a single format that just contains the number(s) that make up the key, with very little metadata. The table below summarizes the PSA import/export format for key pairs and public keys; see the documentation of [`psa_export_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1ga668e35be8d2852ad3feeef74ac6f75bf) and [`psa_export_public_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__import__export/#group__import__export_1gaf22ae73312217aaede2ea02cdebb6062) for more details.
 
 | Key type | PSA import/export format |
 | -------- | ------------------------ |
@@ -795,95 +795,45 @@
 
 There is no equivalent of `mbedtls_pk_parse_keyfile` and `mbedtls_pk_parse_public_keyfile`. Either call the legacy function or load the file data manually.
 
-A future extension of the PSA API will support other import formats. Until those are implemented, see the following subsections for ways to use the PK module for key parsing and construct a PSA key object from the PK object.
+A future extension of the PSA API will support other import formats. Until those are implemented, see the following subsection for how to use the PK module for key parsing and construct a PSA key object from the PK object.
 
-#### Importing legacy keys via the PK module
+### Creating a PSA key via PK
 
-You can use glue functions in the PK module to create a key object using the legacy API, then import that object into the PSA subsystem. This is useful for use cases that the PSA API does not currently cover, such as:
+You can use the PK module as an intermediate step to create an RSA or ECC key for use with PSA. This is useful for use cases that the PSA API does not currently cover, such as:
 
 * Parsing a key in a format with metadata without knowing its type ahead of time.
+* Parsing a key in a format that the PK module supports, but `psa_import_key` doesn't.
 * Importing a key which you have in the form of a list of numbers, rather than the binary encoding required by `psa_import_key`.
 * Importing a key with less information than what the PSA API needs, for example an ECC public key in a compressed format, an RSA private key without the private exponent, or an RSA private key without the CRT parameters.
-* Generating an RSA key with $e \ne 65537$.
 
-#### Importing a PK key by wrapping
+For such use cases:
 
-If you have a PK object, you can call `mbedtls_pk_wrap_as_opaque` to create a PSA key object with the same key material. (This function is only present in builds with `MBEDTLS_USE_PSA_CRYPTO` enabled. It is experimental and [will likely be replaced by a slightly different interface in a future version of Mbed TLS](https://github.com/Mbed-TLS/mbedtls/issues/7760)). This function automatically determines the PSA key type and lets you specify the usage policy (see “[Public-key cryptography policies](#public-key-cryptography-policies)”). Once you've called this function, you can destroy the PK object. This function calls `psa_import_key` internally; call [`psa_destroy_key`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__key__management/#group__key__management_1ga5f52644312291335682fbc0292c43cd2) to destroy the PSA key object once your application no longer needs it. Common scenarios where this workflow is useful are:
+1. First create a PK object with the desired key material.
+2. Call [`mbedtls_pk_get_psa_attributes`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/pk_8h/#pk_8h_1a7aa7b33cffb6981d95d1632631de9244) to fill PSA attributes corresponding to the PK key. Pass one of the following values as the `usage` parameter:
+    * `PSA_KEY_USAGE_SIGN_HASH` or `PSA_KEY_USAGE_SIGN_MESSAGE` for a key pair used for signing.
+    * `PSA_KEY_USAGE_DECRYPT` for a key pair used for decryption.
+    * `PSA_KEY_USAGE_DERIVE` for a key pair used for key agreement.
+    * `PSA_KEY_USAGE_VERIFY_HASH` or `PSA_KEY_USAGE_VERIFY_MESSAGE` for a public key pair used for signature verification.
+    * `PSA_KEY_USAGE_ENCRYPT` for a key pair used for encryption.
+3. Optionally, tweak the attributes (this is rarely necessary). For example:
+    * Call [`psa_set_key_usage_flags`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1ga42a65b3c4522ce9b67ea5ea7720e17de), [`psa_set_key_algorithm`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gaeb8341ca52baa0279475ea3fd3bcdc98) and/or [`psa_set_key_enrollment_algorithm`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/crypto__extra_8h/#group__attributes_1gaffa134b74aa52aa3ed9397fcab4005aa) to change the key's policy (by default, it allows what can be done through the PK module).
+    · Call [`psa_set_key_id`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gae48fcfdc72a23e7499957d7f54ff5a64) and perhaps [`psa_set_key_lifetime`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/group/group__attributes/#group__attributes_1gac03ccf09ca6d36cc3d5b43f8303db6f7) to create a PSA persistent key.
+4. Call [`mbedtls_pk_import_into_psa`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/pk_8h/#pk_8h_1ad59835d14832daf0f4b4bd0a4555abb9) to import the key into the PSA key store.
+5. You can now free the PK object with `mbedtls_pk_free`.
 
-* You have working code that's calling `mbedtls_pk_parse_key`, `mbedtls_pk_parse_public_key`, `mbedtls_pk_parse_subpubkey`, `mbedtls_pk_parse_keyfile` or `mbedtls_pk_parse_public_keyfile` to create a PK object.
-* You have working code that's using the `rsa.h` or `ecp.h` API to create a key object, and there is no PSA equivalent.
-
-You can use this workflow to import an RSA key via an `mbedtls_rsa_context` object or an ECC key via an `mbedtls_ecp_keypair` object:
-
-1. Call `mbedtls_pk_init` then `mbedtls_pk_setup` to set up a PK context for the desired key type (`MBEDTLS_PK_RSA` or `MBEDTLS_PK_ECKEY`).
-2. Call `mbedtls_pk_rsa` or `mbedtls_pk_ec` to obtain the underlying low-level context.
-3. Call `mbedtls_rsa_xxx` or `mbedtls_ecp_xxx` functions to construct the desired key. For example:
-    * `mbedtls_rsa_import` or `mbedtls_rsa_import_raw` followed by `mbedtls_rsa_complete` to create an RSA private key without all the parameters required by the PSA API.
-    * `mbedtls_rsa_gen_key` to generate an RSA private key with a custom public exponent.
-4. Call `mbedtls_pk_wrap_as_opaque` as described above to create a corresponding PSA key object.
-5. Call `mbedtls_pk_free` to free the resources associated with the PK object.
-
-#### Importing a PK key by export-import
-
-This section explains how to export a PK object in the PSA import format. The process depends on the key type. You can use `mbedtls_pk_get_type` or `mbedtls_pk_can_do` to distinguish between RSA and ECC keys. The snippets below assume that the key is in an `mbedtls_pk_context pk`, and omit error checking.
-
-For an RSA private key:
+Here is some sample code illustrating the above process, with error checking omitted.
 
 ```
-unsigned char buf[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
-size_t length = mbedtls_pk_write_key_der(&pk, buf, sizeof(buf));
+mbedtls_pk_context pk;
+mbedtls_pk_init(&pk);
+mbedtls_pk_parse_key(&pk, key_buffer, key_buffer_length, NULL, 0,
+                     mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE);
 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-psa_set_key_attributes(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
-psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_... | ...);
-psa_set_key_algorithm(&attributes, PSA_ALGORITHM_...);
-psa_key_id_t key_id = 0;
-psa_import_key(&attributes, buf + sizeof(buf) - length, length, &key_id);
+mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_SIGN_HASH, &attributes);
+psa_key_id_t key_id;
+mbedtls_pk_import_into_psa(&pk, &attributes, &key_id);
 mbedtls_pk_free(&pk);
-```
-
-For an ECC private key (a future version of Mbed TLS [will provide a more direct way to find the curve family](https://github.com/Mbed-TLS/mbedtls/issues/7764)):
-
-```
-unsigned char buf[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
-mbedtls_ecp_keypair *ec = mbedtls_pk_ec(&pk);
-psa_ecc_curve_t curve;
-{
-    mbedtls_ecp_group grp;
-    mbedtls_ecp_group_init(&grp);
-    mbedtls_ecp_point Q;
-    mbedtls_ecp_point_init(&Q);
-    mbedtls_mpi d;
-    mbedtls_mpi_init(&d);
-    mbedtls_ecp_export(ec, &grp, &d, &Q);
-    size_t bits;
-    curve = mbedtls_ecc_group_to_psa(grp.id, &bits);
-    mbedtls_ecp_group_free(&grp);
-    mbedtls_ecp_point_free(&Q);
-    mbedtls_mpi_free(&d);
-}
-size_t length;
-mbedtls_ecp_write_key_ext(ec, &length, buf, sizeof(buf));
-psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
-psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_... | ...);
-psa_set_key_algorithm(&attributes, PSA_ALGORITHM_...);
-psa_key_id_t key_id = 0;
-psa_import_key(&attributes, buf, length, &key_id);
-mbedtls_pk_free(&pk);
-```
-
-For an RSA or ECC public key:
-
-```
-unsigned char buf[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
-size_t length = mbedtls_pk_write_pubkey(&pk, buf, sizeof(buf));
-psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-psa_set_key_attributes(&attributes, ...); // need to determine the type manually
-psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_... | ...);
-psa_set_key_algorithm(&attributes, PSA_ALGORITHM_...);
-psa_key_id_t key_id = 0;
-psa_import_key(&attributes, buf + sizeof(buf) - length, length, &key_id);
-mbedtls_pk_free(&pk);
+psa_sign_hash(key_id, ...);
 ```
 
 #### Importing an elliptic curve key from ECP
@@ -952,11 +902,33 @@
 
 The export format is the same format used for `psa_import_key`, described in “[Creating keys for asymmetric cryptography](#creating-keys-for-asymmetric-cryptography)” above.
 
-A future extension of the PSA API will support other export formats. Until those are implemented, see “[Exporting a PK key by wrapping](#exporting-a-pk-key-by-wrapping)” for ways to use the PK module to format a PSA key.
+A future extension of the PSA API will support other export formats. Until those are implemented, see “[Exposing a PSA key via PK](#exposing-a-psa-key-via-pk)” for ways to use the PK module to format a PSA key.
 
-#### Exporting a PK key by wrapping
+#### Exposing a PSA key via PK
 
-You can wrap a PSA key object in a PK key context with `mbedtls_pk_setup_opaque`. This allows you to call functions such as `mbedtls_pk_write_key_der`, `mbedtls_pk_write_pubkey_der`, `mbedtls_pk_write_pubkey_pem`, `mbedtls_pk_write_key_pem` or `mbedtls_pk_write_pubkey` to export the key data in various formats.
+This section discusses how to use a PSA key in a context that requires a PK object, such as PK formatting functions (`mbedtls_pk_write_key_der`, `mbedtls_pk_write_pubkey_der`, `mbedtls_pk_write_pubkey_pem`, `mbedtls_pk_write_key_pem` or `mbedtls_pk_write_pubkey`), Mbed TLS X.509 functions, Mbed TLS SSL functions, or another API that involves `mbedtls_pk_context` objects. The PSA key must be an RSA or ECC key since the PK module does not support DH keys. Three functions from `pk.h` help with that:
+
+* [`mbedtls_pk_copy_from_psa`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/pk_8h/#pk_8h_1ab8e88836fd9ee344ffe630c40447bd08) copies a PSA key into a PK object. The PSA key must be exportable. The PK object remains valid even if the PSA key is destroyed.
+* [`mbedtls_pk_copy_public_from_psa`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/pk_8h/#pk_8h_1a2a50247a528889c12ea0ddddb8b15a4e) copies the public part of a PSA key into a PK object. The PK object remains valid even if the PSA key is destroyed.
+* [`mbedtls_pk_setup_opaque`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/pk_8h/#pk_8h_1a4c04ac22ab9c1ae09cc29438c308bf05) sets up a PK object that wraps the PSA key. This functionality is only available when `MBEDTLS_USE_PSA_CRYPTO` is enabled. The PK object has the type `MBEDTLS_PK_OPAQUE` regardless of whether the key is an RSA or ECC key. The PK object can only be used as permitted by the PSA key's policy. The PK object contains a reference to the PSA key identifier, therefore PSA key must not be destroyed as long as the PK object remains alive.
+
+Here is some sample code illustrating how to use the PK module to format a PSA public key or the public key of a PSA key pair.
+```
+int write_psa_pubkey(psa_key_id_t key_id,
+                     unsigned char *buf, size_t size, size_t *len) {
+    mbedtls_pk_context pk;
+    mbedtls_pk_init(&pk);
+    int ret = mbedtls_pk_copy_public_from_psa(key_id, &pk);
+    if (ret != 0) goto exit;
+    ret = mbedtls_pk_write_pubkey_der(&pk, buf, size);
+    if (ret < 0) goto exit;
+    *len = ret;
+    memmove(buf, buf + size - ret, ret);
+    ret = 0;
+exit:
+    mbedtls_pk_free(&pk);
+}
+```
 
 ### Signature operations
 
@@ -983,7 +955,8 @@
 
 #### ECDSA signature
 
-**Note: in the PSA API, the format of an ECDSA signature is the raw fixed-size format. This is different from the legacy API** which uses the ASN.1 DER format for ECDSA signatures. A future version of Mbed TLS [will provide a way to convert between the two formats](https://github.com/Mbed-TLS/mbedtls/issues/7765).
+**Note: in the PSA API, the format of an ECDSA signature is the raw fixed-size format. This is different from the legacy API** which uses the ASN.1 DER format for ECDSA signatures. To convert between the two formats, use [`mbedtls_ecdsa_raw_to_der`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/psa__util_8h/#group__psa__tls__helpers_1ga9295799b5437bdff8ce8abd524c5ef2e) or [`mbedtls_ecdsa_der_to_raw`](https://mbed-tls.readthedocs.io/projects/api/en/development/api/file/psa__util_8h/#group__psa__tls__helpers_1ga33b3cf65d5992ccc724b7ee00186ae61).
+
 <!-- The following are specific to the DER format and therefore have no PSA equivalent: MBEDTLS_ECDSA_MAX_SIG_LEN, MBEDTLS_ECDSA_MAX_LEN -->
 
 ECDSA is the mechanism provided by `mbedtls_pk_sign` and `mbedtls_pk_verify` for ECDSA keys, as well as by `mbedtls_ecdsa_sign`, `mbedtls_ecdsa_sign_det_ext`, `mbedtls_ecdsa_write_signature`, `mbedtls_ecdsa_verify` and `mbedtls_ecdsa_read_signature`.
diff --git a/docs/tls13-early-data.md b/docs/tls13-early-data.md
new file mode 100644
index 0000000..4b6f5d3
--- /dev/null
+++ b/docs/tls13-early-data.md
@@ -0,0 +1,192 @@
+
+Writing early data
+------------------
+
+An application function to write and send a buffer of data to a server through
+TLS may plausibly look like:
+
+```
+int write_data(mbedtls_ssl_context *ssl,
+               const unsigned char *data_to_write,
+               size_t data_to_write_len,
+               size_t *data_written)
+{
+    int ret;
+    *data_written = 0;
+
+    while (*data_written < data_to_write_len) {
+        ret = mbedtls_ssl_write(ssl, data_to_write + *data_written,
+                                data_to_write_len - *data_written);
+
+        if (ret < 0 &&
+            ret != MBEDTLS_ERR_SSL_WANT_READ &&
+            ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
+            return ret;
+        }
+
+        *data_written += ret;
+    }
+
+    return 0;
+}
+```
+where ssl is the SSL context to use, data_to_write the address of the data
+buffer and data_to_write_len the number of data bytes. The handshake may
+not be completed, not even started for the SSL context ssl when the function is
+called and in that case the mbedtls_ssl_write() API takes care transparently of
+completing the handshake before to write and send data to the server. The
+mbedtls_ssl_write() may not be able to write and send all data in one go thus
+the need for a loop calling it as long as there are still data to write and
+send.
+
+An application function to write and send early data and only early data,
+data sent during the first flight of client messages while the handshake is in
+its initial phase, would look completely similar but the call to
+mbedtls_ssl_write_early_data() instead of mbedtls_ssl_write().
+```
+int write_early_data(mbedtls_ssl_context *ssl,
+                     const unsigned char *data_to_write,
+                     size_t data_to_write_len,
+                     size_t *data_written)
+{
+    int ret;
+    *data_written = 0;
+
+    while (*data_written < data_to_write_len) {
+        ret = mbedtls_ssl_write_early_data(ssl, data_to_write + *data_written,
+                                           data_to_write_len - *data_written);
+
+        if (ret < 0 &&
+            ret != MBEDTLS_ERR_SSL_WANT_READ &&
+            ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
+            return ret;
+        }
+
+        *data_written += ret;
+    }
+
+    return 0;
+}
+```
+Note that compared to write_data(), write_early_data() can also return
+MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA and that should be handled
+specifically by the user of write_early_data(). A fresh SSL context (typically
+just after a call to mbedtls_ssl_setup() or mbedtls_ssl_session_reset()) would
+be expected when calling `write_early_data`.
+
+All together, code to write and send a buffer of data as long as possible as
+early data and then as standard post-handshake application data could
+plausibly look like:
+
+```
+ret = write_early_data(ssl,
+                       data_to_write,
+                       data_to_write_len,
+                       &early_data_written);
+if (ret < 0 &&
+    ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA) {
+    goto error;
+}
+
+ret = write_data(ssl,
+                 data_to_write + early_data_written,
+                 data_to_write_len - early_data_written,
+                 &data_written);
+if (ret < 0) {
+    goto error;
+}
+
+data_written += early_data_written;
+```
+
+Finally, taking into account that the server may reject early data, application
+code to write and send a buffer of data could plausibly look like:
+```
+ret = write_early_data(ssl,
+                       data_to_write,
+                       data_to_write_len,
+                       &early_data_written);
+if (ret < 0 &&
+    ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA) {
+    goto error;
+}
+
+/*
+ * Make sure the handshake is completed as it is a requisite of
+ * mbedtls_ssl_get_early_data_status().
+ */
+while (!mbedtls_ssl_is_handshake_over(ssl)) {
+    ret = mbedtls_ssl_handshake(ssl);
+    if (ret < 0 &&
+        ret != MBEDTLS_ERR_SSL_WANT_READ &&
+        ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
+        goto error;
+    }
+}
+
+ret = mbedtls_ssl_get_early_data_status(ssl);
+if (ret < 0) {
+    goto error;
+}
+
+if (ret == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) {
+   early_data_written = 0;
+}
+
+ret = write_data(ssl,
+                 data_to_write + early_data_written,
+                 data_to_write_len - early_data_written,
+                 &data_written);
+if (ret < 0) {
+    goto error;
+}
+
+data_written += early_data_written;
+```
+
+Reading early data
+------------------
+Mbed TLS provides the mbedtls_ssl_read_early_data() API to read the early data
+that a TLS 1.3 server might receive during the TLS 1.3 handshake.
+
+While establishing a TLS 1.3 connection with a client using a combination
+of the mbedtls_ssl_handshake(), mbedtls_ssl_read() and mbedtls_ssl_write() APIs,
+the reception of early data is signaled by an API returning the
+MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA error code. Early data can then be read
+with the mbedtls_ssl_read_early_data() API.
+
+For example, a typical code to establish a TLS connection, where ssl is the SSL
+context to use:
+```
+while ((int ret = mbedtls_ssl_handshake(&ssl)) != 0) {
+
+    if (ret < 0 &&
+        ret != MBEDTLS_ERR_SSL_WANT_READ &&
+        ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
+        break;
+    }
+}
+```
+could be adapted to handle early data in the following way:
+```
+size_t data_read_len = 0;
+while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
+
+    if (ret == MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA) {
+        ret = mbedtls_ssl_read_early_data(&ssl,
+                                          buffer + data_read_len,
+                                          sizeof(buffer) - data_read_len);
+        if (ret < 0) {
+            break;
+        }
+        data_read_len += ret;
+        continue;
+    }
+
+    if (ret < 0 &&
+        ret != MBEDTLS_ERR_SSL_WANT_READ &&
+        ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
+        break;
+    }
+}
+```
diff --git a/docs/use-psa-crypto.md b/docs/use-psa-crypto.md
index 92d0985..f2983bd 100644
--- a/docs/use-psa-crypto.md
+++ b/docs/use-psa-crypto.md
@@ -75,13 +75,8 @@
 
 **Benefits:** isolation of long-term secrets, use of PSA Crypto drivers.
 
-**Limitations:** can only wrap a key pair, can only use it for private key
-operations. (That is, signature generation, and for RSA decryption too.)
-Note: for ECDSA, currently this uses randomized ECDSA while Mbed TLS uses
-deterministic ECDSA by default. The following operations are not supported
-with a context set this way, while they would be available with a normal
-context: `mbedtls_pk_check_pair()`, `mbedtls_pk_debug()`, all public key
-operations.
+**Limitations:** please refer to the documentation of `mbedtls_pk_setup_opaque()`
+for a full list of supported operations and limitations.
 
 **Use in X.509 and TLS:** opt-in. The application needs to construct the PK context
 using the new API in order to get the benefits; it can then pass the
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index 17762d7..3eb5f75 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -10,7 +10,7 @@
  */
 
 /**
- * @mainpage Mbed TLS v3.5.2 API Documentation
+ * @mainpage Mbed TLS v3.6.0 API Documentation
  *
  * This documentation describes the internal structure of Mbed TLS.  It was
  * automatically generated from specially formatted comment blocks in
diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile
index f2695a1..c4505ac 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -1,4 +1,4 @@
-PROJECT_NAME           = "Mbed TLS v3.5.2"
+PROJECT_NAME           = "Mbed TLS v3.6.0"
 OUTPUT_DIRECTORY       = ../apidoc/
 FULL_PATH_NAMES        = NO
 OPTIMIZE_OUTPUT_FOR_C  = YES
diff --git a/framework b/framework
new file mode 160000
index 0000000..750634d
--- /dev/null
+++ b/framework
@@ -0,0 +1 @@
+Subproject commit 750634d3a51eb9d61b59fd5d801546927c946588
diff --git a/include/mbedtls/bignum.h b/include/mbedtls/bignum.h
index 931e06d..71d7b97 100644
--- a/include/mbedtls/bignum.h
+++ b/include/mbedtls/bignum.h
@@ -51,15 +51,15 @@
 
 #if !defined(MBEDTLS_MPI_WINDOW_SIZE)
 /*
- * Maximum window size used for modular exponentiation. Default: 2
+ * Maximum window size used for modular exponentiation. Default: 3
  * Minimum value: 1. Maximum value: 6.
  *
  * Result is an array of ( 2 ** MBEDTLS_MPI_WINDOW_SIZE ) MPIs used
- * for the sliding window calculation. (So 64 by default)
+ * for the sliding window calculation. (So 8 by default)
  *
  * Reduction in size, reduces speed.
  */
-#define MBEDTLS_MPI_WINDOW_SIZE                           2        /**< Maximum window size used. */
+#define MBEDTLS_MPI_WINDOW_SIZE                           3        /**< Maximum window size used. */
 #endif /* !MBEDTLS_MPI_WINDOW_SIZE */
 
 #if !defined(MBEDTLS_MPI_MAX_SIZE)
diff --git a/include/mbedtls/build_info.h b/include/mbedtls/build_info.h
index 99a449b..eab167f 100644
--- a/include/mbedtls/build_info.h
+++ b/include/mbedtls/build_info.h
@@ -25,17 +25,17 @@
  * Major, Minor, Patchlevel
  */
 #define MBEDTLS_VERSION_MAJOR  3
-#define MBEDTLS_VERSION_MINOR  5
-#define MBEDTLS_VERSION_PATCH  2
+#define MBEDTLS_VERSION_MINOR  6
+#define MBEDTLS_VERSION_PATCH  0
 
 /**
  * The single version number has the following structure:
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x03050200
-#define MBEDTLS_VERSION_STRING         "3.5.2"
-#define MBEDTLS_VERSION_STRING_FULL    "Mbed TLS 3.5.2"
+#define MBEDTLS_VERSION_NUMBER         0x03060000
+#define MBEDTLS_VERSION_STRING         "3.6.0"
+#define MBEDTLS_VERSION_STRING_FULL    "Mbed TLS 3.6.0"
 
 /* Macros for build-time platform detection */
 
diff --git a/include/mbedtls/config_adjust_legacy_crypto.h b/include/mbedtls/config_adjust_legacy_crypto.h
index 9b06041..e477c07 100644
--- a/include/mbedtls/config_adjust_legacy_crypto.h
+++ b/include/mbedtls/config_adjust_legacy_crypto.h
@@ -293,6 +293,14 @@
 #define MBEDTLS_ECP_LIGHT
 #endif
 
+/* Backward compatibility: after #8740 the RSA module offers functions to parse
+ * and write RSA private/public keys without relying on the PK one. Of course
+ * this needs ASN1 support to do so, so we enable it here. */
+#if defined(MBEDTLS_RSA_C)
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#endif
+
 /* MBEDTLS_PK_PARSE_EC_COMPRESSED is introduced in Mbed TLS version 3.5, while
  * in previous version compressed points were automatically supported as long
  * as PK_PARSE_C and ECP_C were enabled. As a consequence, for backward
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index 7cf4153..3592141 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -1469,6 +1469,26 @@
 //#define MBEDTLS_PSA_INJECT_ENTROPY
 
 /**
+ * \def MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS
+ *
+ * Assume all buffers passed to PSA functions are owned exclusively by the
+ * PSA function and are not stored in shared memory.
+ *
+ * This option may be enabled if all buffers passed to any PSA function reside
+ * in memory that is accessible only to the PSA function during its execution.
+ *
+ * This option MUST be disabled whenever buffer arguments are in memory shared
+ * with an untrusted party, for example where arguments to PSA calls are passed
+ * across a trust boundary.
+ *
+ * \note Enabling this option reduces memory usage and code size.
+ *
+ * \note Enabling this option causes overlap of input and output buffers
+ *       not to be supported by PSA functions.
+ */
+//#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS
+
+/**
  * \def MBEDTLS_RSA_NO_CRT
  *
  * Do not use the Chinese Remainder Theorem
@@ -1724,9 +1744,6 @@
  *
  * Enable support for RFC 8449 record_size_limit extension in SSL (TLS 1.3 only).
  *
- * \warning This extension is currently in development and must NOT be used except
- *          for testing purposes.
- *
  * Requires: MBEDTLS_SSL_PROTO_TLS1_3
  *
  * Uncomment this macro to enable support for the record_size_limit extension
@@ -1774,7 +1791,7 @@
  *
  * Uncomment this macro to enable the support for TLS 1.3.
  */
-//#define MBEDTLS_SSL_PROTO_TLS1_3
+#define MBEDTLS_SSL_PROTO_TLS1_3
 
 /**
  * \def MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
@@ -1796,7 +1813,7 @@
  * effect on the build.
  *
  */
-//#define MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+#define MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
 
 /**
  * \def MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
@@ -1854,9 +1871,6 @@
  * Comment this to disable support for early data. If MBEDTLS_SSL_PROTO_TLS1_3
  * is not enabled, this option does not have any effect on the build.
  *
- * This feature is experimental, not completed and thus not ready for
- * production.
- *
  * \note The maximum amount of early data can be set with
  *       MBEDTLS_SSL_MAX_EARLY_DATA_SIZE.
  *
@@ -2211,7 +2225,7 @@
  * Enable AES-NI support on x86-64 or x86-32.
  *
  * \note AESNI is only supported with certain compilers and target options:
- * - Visual Studio 2013: supported.
+ * - Visual Studio: supported
  * - GCC, x86-64, target not explicitly supporting AESNI:
  *   requires MBEDTLS_HAVE_ASM.
  * - GCC, x86-32, target not explicitly supporting AESNI:
@@ -3201,6 +3215,9 @@
  * \deprecated This feature is deprecated. Please switch to the PSA driver
  *             interface.
  *
+ * \warning    This feature is not thread-safe, and should not be used in a
+ *             multi-threaded environment.
+ *
  * Module:  library/psa_crypto_se.c
  *
  * Requires: MBEDTLS_PSA_CRYPTO_C, MBEDTLS_PSA_CRYPTO_STORAGE_C
@@ -4142,10 +4159,6 @@
  *
  * If MBEDTLS_SSL_EARLY_DATA is not defined, this default value does not
  * have any impact on the build.
- *
- * This feature is experimental, not completed and thus not ready for
- * production.
- *
  */
 //#define MBEDTLS_SSL_MAX_EARLY_DATA_SIZE        1024
 
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index ff80290..52f4cc6 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -359,32 +359,40 @@
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 /**
- * \brief           Initialize a PK context to wrap a PSA key.
+ * \brief Initialize a PK context to wrap a PSA key.
  *
- * \note            This function replaces mbedtls_pk_setup() for contexts
- *                  that wrap a (possibly opaque) PSA key instead of
- *                  storing and manipulating the key material directly.
+ * This function creates a PK context which wraps a PSA key. The PSA wrapped
+ * key must be an EC or RSA key pair (DH is not suported in the PK module).
  *
- * \param ctx       The context to initialize. It must be empty (type NONE).
- * \param key       The PSA key to wrap, which must hold an ECC or RSA key
- *                  pair (see notes below).
+ * Under the hood PSA functions will be used to perform the required
+ * operations and, based on the key type, used algorithms will be:
+ * * EC:
+ *     * verify, verify_ext, sign, sign_ext: ECDSA.
+ * * RSA:
+ *     * sign, decrypt: use the primary algorithm in the wrapped PSA key;
+ *     * sign_ext: RSA PSS if the pk_type is #MBEDTLS_PK_RSASSA_PSS, otherwise
+ *       it falls back to the sign() case;
+ *     * verify, verify_ext, encrypt: not supported.
  *
- * \note            The wrapped key must remain valid as long as the
- *                  wrapping PK context is in use, that is at least between
- *                  the point this function is called and the point
- *                  mbedtls_pk_free() is called on this context. The wrapped
- *                  key might then be independently used or destroyed.
+ * In order for the above operations to succeed, the policy of the wrapped PSA
+ * key must allow the specified algorithm.
  *
- * \note            This function is currently only available for ECC or RSA
- *                  key pairs (that is, keys containing private key material).
- *                  Support for other key types may be added later.
+ * Opaque PK contexts wrapping an EC keys also support \c mbedtls_pk_check_pair(),
+ * whereas RSA ones do not.
  *
- * \return          \c 0 on success.
- * \return          #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input
- *                  (context already used, invalid key identifier).
- * \return          #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an
- *                  ECC key pair.
- * \return          #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure.
+ * \warning The PSA wrapped key must remain valid as long as the wrapping PK
+ *          context is in use, that is at least between the point this function
+ *          is called and the point mbedtls_pk_free() is called on this context.
+ *
+ * \param ctx The context to initialize. It must be empty (type NONE).
+ * \param key The PSA key to wrap, which must hold an ECC or RSA key pair.
+ *
+ * \return    \c 0 on success.
+ * \return    #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input (context already
+ *            used, invalid key identifier).
+ * \return    #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an ECC or
+ *            RSA key pair.
+ * \return    #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure.
  */
 int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx,
                             const mbedtls_svc_key_id_t key);
@@ -458,7 +466,7 @@
  *                  PSA_ALG_RSA_PKCS1V15_CRYPT,
  *                  PSA_ALG_ECDSA(hash),
  *                  PSA_ALG_ECDH, where hash is a specific hash.
- * \param usage  PSA usage flag to check against, must be composed of:
+ * \param usage     PSA usage flag to check against, must be composed of:
  *                  PSA_KEY_USAGE_SIGN_HASH
  *                  PSA_KEY_USAGE_DECRYPT
  *                  PSA_KEY_USAGE_DERIVE.
@@ -479,25 +487,25 @@
                           psa_key_usage_t usage);
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 /**
  * \brief           Determine valid PSA attributes that can be used to
  *                  import a key into PSA.
  *
- *                  The attributes determined by this function are suitable
- *                  for calling mbedtls_pk_import_into_psa() to create
- *                  a PSA key with the same key material.
+ * The attributes determined by this function are suitable
+ * for calling mbedtls_pk_import_into_psa() to create
+ * a PSA key with the same key material.
  *
- *                  The typical flow of operations involving this function is
- *                  ```
- *                  psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
- *                  int ret = mbedtls_pk_get_psa_attributes(pk, &attributes);
- *                  if (ret != 0) ...; // error handling omitted
- *                  // Tweak attributes if desired
- *                  psa_key_id_t key_id = 0;
- *                  ret = mbedtls_pk_import_into_psa(pk, &attributes, &key_id);
- *                  if (ret != 0) ...; // error handling omitted
- *                  ```
+ * The typical flow of operations involving this function is
+ * ```
+ * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ * int ret = mbedtls_pk_get_psa_attributes(pk, &attributes);
+ * if (ret != 0) ...; // error handling omitted
+ * // Tweak attributes if desired
+ * psa_key_id_t key_id = 0;
+ * ret = mbedtls_pk_import_into_psa(pk, &attributes, &key_id);
+ * if (ret != 0) ...; // error handling omitted
+ * ```
  *
  * \note            This function does not support RSA-alt contexts
  *                  (set up with mbedtls_pk_setup_rsa_alt()).
@@ -596,24 +604,23 @@
 /**
  * \brief           Import a key into the PSA key store.
  *
- *                  This function is equivalent to calling psa_import_key()
- *                  with the key material from \p pk.
+ * This function is equivalent to calling psa_import_key()
+ * with the key material from \p pk.
  *
- *                  The typical way to use this function is:
- *                  -# Call mbedtls_pk_get_psa_attributes() to obtain
- *                     attributes for the given key.
- *                  -# If desired, modify the attributes, for example:
- *                      - To create a persistent key, call
- *                        psa_set_key_identifier() and optionally
- *                        psa_set_key_lifetime().
- *                      - To import only the public part of a key pair:
- *                        ```
- *                        psa_set_key_type(&attributes,
- *                                         PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
- *                                             psa_get_key_type(&attributes)));
- *                        ```
- *                      - Restrict the key usage if desired.
- *                  -# Call mbedtls_pk_import_into_psa().
+ * The typical way to use this function is:
+ * -# Call mbedtls_pk_get_psa_attributes() to obtain
+ *    attributes for the given key.
+ * -# If desired, modify the attributes, for example:
+ *     - To create a persistent key, call
+ *       psa_set_key_identifier() and optionally
+ *       psa_set_key_lifetime().
+ *     - To import only the public part of a key pair:
+ *
+ *           psa_set_key_type(&attributes,
+ *                            PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
+ *                                psa_get_key_type(&attributes)));
+ *     - Restrict the key usage if desired.
+ * -# Call mbedtls_pk_import_into_psa().
  *
  * \note            This function does not support RSA-alt contexts
  *                  (set up with mbedtls_pk_setup_rsa_alt()).
@@ -640,7 +647,76 @@
 int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk,
                                const psa_key_attributes_t *attributes,
                                mbedtls_svc_key_id_t *key_id);
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+/**
+ * \brief           Create a PK context starting from a key stored in PSA.
+ *                  This key:
+ *                  - must be exportable and
+ *                  - must be an RSA or EC key pair or public key (FFDH is not supported in PK).
+ *
+ *                  The resulting PK object will be a transparent type:
+ *                  - #MBEDTLS_PK_RSA for RSA keys or
+ *                  - #MBEDTLS_PK_ECKEY for EC keys.
+ *
+ *                  Once this functions returns the PK object will be completely
+ *                  independent from the original PSA key that it was generated
+ *                  from.
+ *                  Calling mbedtls_pk_sign(), mbedtls_pk_verify(),
+ *                  mbedtls_pk_encrypt(), mbedtls_pk_decrypt() on the resulting
+ *                  PK context will perform the corresponding algorithm for that
+ *                  PK context type.
+ *                  * For ECDSA, the choice of deterministic vs randomized will
+ *                    be based on the compile-time setting #MBEDTLS_ECDSA_DETERMINISTIC.
+ *                  * For an RSA key, the output PK context will allow both
+ *                    encrypt/decrypt and sign/verify regardless of the original
+ *                    key's policy.
+ *                    The original key's policy determines the output key's padding
+ *                    mode: PCKS1 v2.1 is set if the PSA key policy is OAEP or PSS,
+ *                    otherwise PKCS1 v1.5 is set.
+ *
+ * \param key_id    The key identifier of the key stored in PSA.
+ * \param pk        The PK context that will be filled. It must be initialized,
+ *                  but not set up.
+ *
+ * \return          0 on success.
+ * \return          #MBEDTLS_ERR_PK_BAD_INPUT_DATA in case the provided input
+ *                  parameters are not correct.
+ */
+int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk);
+
+/**
+ * \brief           Create a PK context for the public key of a PSA key.
+ *
+ *                  The key must be an RSA or ECC key. It can be either a
+ *                  public key or a key pair, and only the public key is copied.
+ *                  The resulting PK object will be a transparent type:
+ *                  - #MBEDTLS_PK_RSA for RSA keys or
+ *                  - #MBEDTLS_PK_ECKEY for EC keys.
+ *
+ *                  Once this functions returns the PK object will be completely
+ *                  independent from the original PSA key that it was generated
+ *                  from.
+ *                  Calling mbedtls_pk_verify() or
+ *                  mbedtls_pk_encrypt() on the resulting
+ *                  PK context will perform the corresponding algorithm for that
+ *                  PK context type.
+ *
+ *                  For an RSA key, the output PK context will allow both
+ *                  encrypt and verify regardless of the original key's policy.
+ *                  The original key's policy determines the output key's padding
+ *                  mode: PCKS1 v2.1 is set if the PSA key policy is OAEP or PSS,
+ *                  otherwise PKCS1 v1.5 is set.
+ *
+ * \param key_id    The key identifier of the key stored in PSA.
+ * \param pk        The PK context that will be filled. It must be initialized,
+ *                  but not set up.
+ *
+ * \return          0 on success.
+ * \return          MBEDTLS_ERR_PK_BAD_INPUT_DATA in case the provided input
+ *                  parameters are not correct.
+ */
+int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk);
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
 
 /**
  * \brief           Verify signature (including padding if relevant).
diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h
index 984f031..c78cc23 100644
--- a/include/mbedtls/psa_util.h
+++ b/include/mbedtls/psa_util.h
@@ -21,44 +21,24 @@
  * otherwise error codes would be unknown in test_suite_psa_crypto_util.data.*/
 #include <mbedtls/asn1write.h>
 
-#if defined(MBEDTLS_PSA_CRYPTO_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.
- * See that file for implementation documentation. */
-
-
-/* The type of a `f_rng` random generator function that many library functions
- * take.
- *
- * This type name is not part of the Mbed TLS stable API. It may be renamed
- * or moved without warning.
- */
-typedef int mbedtls_f_rng_t(void *p_rng, unsigned char *output, size_t output_size);
-
-#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 
 /** The random generator function for the PSA subsystem.
  *
  * This function is suitable as the `f_rng` random generator function
- * parameter of many `mbedtls_xxx` functions. Use #MBEDTLS_PSA_RANDOM_STATE
- * to obtain the \p p_rng parameter.
+ * parameter of many `mbedtls_xxx` functions.
  *
  * The implementation of this function depends on the configuration of the
  * library.
  *
- * \note Depending on the configuration, this may be a function or
- *       a pointer to a function.
- *
  * \note This function may only be used if the PSA crypto subsystem is active.
  *       This means that you must call psa_crypto_init() before any call to
  *       this function, and you must not call this function after calling
  *       mbedtls_psa_crypto_free().
  *
- * \param p_rng         The random generator context. This must be
- *                      #MBEDTLS_PSA_RANDOM_STATE. No other state is
- *                      supported.
+ * \param p_rng         This parameter is only kept for backward compatibility
+ *                      reasons with legacy `f_rng` functions and it's ignored.
+ *                      Set to #MBEDTLS_PSA_RANDOM_STATE or NULL.
  * \param output        The buffer to fill. It must have room for
  *                      \c output_size bytes.
  * \param output_size   The number of bytes to write to \p output.
@@ -80,32 +60,11 @@
 
 /** The random generator state for the PSA subsystem.
  *
- * This macro expands to an expression which is suitable as the `p_rng`
- * random generator state parameter of many `mbedtls_xxx` functions.
- * It must be used in combination with the random generator function
- * mbedtls_psa_get_random().
- *
- * The implementation of this macro depends on the configuration of the
- * library. Do not make any assumption on its nature.
+ * This macro always expands to NULL because the `p_rng` parameter is unused
+ * in mbedtls_psa_get_random(), but it's kept for interface's backward
+ * compatibility.
  */
-#define MBEDTLS_PSA_RANDOM_STATE NULL
-
-#else /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
-
-#if defined(MBEDTLS_CTR_DRBG_C)
-#include "mbedtls/ctr_drbg.h"
-typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t;
-static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_ctr_drbg_random;
-#elif defined(MBEDTLS_HMAC_DRBG_C)
-#include "mbedtls/hmac_drbg.h"
-typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t;
-static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random;
-#endif
-extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state;
-
-#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state
-
-#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
+#define MBEDTLS_PSA_RANDOM_STATE    NULL
 
 /** \defgroup psa_tls_helpers TLS helper functions
  * @{
@@ -180,7 +139,7 @@
 {
     return (mbedtls_md_type_t) (psa_alg & PSA_ALG_HASH_MASK);
 }
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
 
 #if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
 
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 78395d2..ca130a3 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -741,42 +741,12 @@
 #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
 typedef enum {
 /*
- * The client has not sent the first ClientHello yet, it is unknown if the
- * client will send an early data indication extension or not.
- */
-    MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN,
-
-/*
  * See documentation of mbedtls_ssl_get_early_data_status().
  */
-    MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT,
+    MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED,
     MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED,
     MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED,
-
-/*
- * The client has sent an early data indication extension in its first
- * ClientHello, it has not received the response (ServerHello or
- * HelloRetryRequest) from the server yet. The transform to protect early data
- * is not set and early data cannot be sent yet.
- */
-    MBEDTLS_SSL_EARLY_DATA_STATUS_SENT,
-
-/*
- * The client has sent an early data indication extension in its first
- * ClientHello, it has not received the response (ServerHello or
- * HelloRetryRequest) from the server yet. The transform to protect early data
- * has been set and early data can be written now.
- */
-    MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE,
-
-/*
- * The client has sent an early data indication extension in its first
- * ClientHello, the server has accepted them and the client has received the
- * server Finished message. It cannot send early data to the server anymore.
- */
-    MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED,
 } mbedtls_ssl_early_data_status;
-
 #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */
 
 /**
@@ -1334,6 +1304,11 @@
     char *MBEDTLS_PRIVATE(hostname);             /*!< host name binded with tickets */
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_CLI_C */
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C)
+    char *ticket_alpn;                      /*!< ALPN negotiated in the session
+                                                 during which the ticket was generated. */
+#endif
+
 #if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_CLI_C)
     /*! Time in milliseconds when the last ticket was received. */
     mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_reception_time);
@@ -1737,10 +1712,10 @@
 
 #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
     /**
-     * Status of the negotiation of the use of early data. Reset to
-     * MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN when the context is reset.
+     * State of the negotiation and transfer of early data. Reset to
+     * MBEDTLS_SSL_EARLY_DATA_STATE_IDLE when the context is reset.
      */
-    mbedtls_ssl_early_data_status MBEDTLS_PRIVATE(early_data_status);
+    int MBEDTLS_PRIVATE(early_data_state);
 #endif
 
     unsigned MBEDTLS_PRIVATE(badmac_seen);       /*!< records with a bad MAC received    */
@@ -1859,7 +1834,8 @@
                                                          *   within a single datagram.  */
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C)
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+#if defined(MBEDTLS_SSL_SRV_C)
     /*
      * One of:
      * MBEDTLS_SSL_EARLY_DATA_NO_DISCARD
@@ -1868,6 +1844,8 @@
      */
     uint8_t MBEDTLS_PRIVATE(discard_early_data_record);
 #endif
+    uint32_t MBEDTLS_PRIVATE(total_early_data_size); /*!< Number of received/written early data bytes */
+#endif /* MBEDTLS_SSL_EARLY_DATA */
 
     /*
      * Record layer (outgoing data)
@@ -2124,9 +2102,6 @@
  *  MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA indicating that some early data have
  *  been received. To read the early data, call mbedtls_ssl_read_early_data()
  *  before calling the original function again.
- *
- * \warning This interface is experimental and may change without notice.
- *
  */
 void mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf,
                                  int early_data_enabled);
@@ -2152,12 +2127,9 @@
  * \param[in] conf                  The SSL configuration to use.
  * \param[in] max_early_data_size   The maximum amount of 0-RTT data.
  *
- * \warning This interface is experimental and may change without notice.
- *
  * \warning This interface DOES NOT influence/limit the amount of early data
  *          that can be received through previously created and issued tickets,
  *          which clients may have stored.
- *
  */
 void mbedtls_ssl_conf_max_early_data_size(
     mbedtls_ssl_config *conf, uint32_t max_early_data_size);
@@ -2718,6 +2690,43 @@
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */
 
 /**
+ * \brief          Get the session-id buffer.
+ *
+ * \param session  SSL session.
+ *
+ * \return         The address of the session-id buffer.
+ */
+static inline unsigned const char (*mbedtls_ssl_session_get_id(const mbedtls_ssl_session *
+                                                               session))[32]
+{
+    return &session->MBEDTLS_PRIVATE(id);
+}
+
+/**
+ * \brief          Get the size of the session-id.
+ *
+ * \param session  SSL session.
+ *
+ * \return         size_t size of session-id buffer.
+ */
+static inline size_t mbedtls_ssl_session_get_id_len(const mbedtls_ssl_session *session)
+{
+    return session->MBEDTLS_PRIVATE(id_len);
+}
+
+/**
+ * \brief          Get the ciphersuite-id.
+ *
+ * \param session  SSL session.
+ *
+ * \return         int represetation for ciphersuite.
+ */
+static inline int mbedtls_ssl_session_get_ciphersuite_id(const mbedtls_ssl_session *session)
+{
+    return session->MBEDTLS_PRIVATE(ciphersuite);
+}
+
+/**
  * \brief   Configure a key export callback.
  *          (Default: none.)
  *
@@ -3207,16 +3216,16 @@
  *                 a full handshake.
  *
  * \note           This function can handle a variety of mechanisms for session
- *                 resumption: For TLS 1.2, both session ID-based resumption and
- *                 ticket-based resumption will be considered. For TLS 1.3,
- *                 once implemented, sessions equate to tickets, and loading
- *                 one or more sessions via this call will lead to their
- *                 corresponding tickets being advertised as resumption PSKs
- *                 by the client.
- *
- * \note           Calling this function multiple times will only be useful
- *                 once TLS 1.3 is supported. For TLS 1.2 connections, this
- *                 function should be called at most once.
+ *                 resumption: For TLS 1.2, both session ID-based resumption
+ *                 and ticket-based resumption will be considered. For TLS 1.3,
+ *                 sessions equate to tickets, and loading one session by
+ *                 calling this function will lead to its corresponding ticket
+ *                 being advertised as resumption PSK by the client. This
+ *                 depends on session tickets being enabled (see
+ *                 #MBEDTLS_SSL_SESSION_TICKETS configuration option) though.
+ *                 If session tickets are disabled, a call to this function
+ *                 with a TLS 1.3 session, will not have any effect on the next
+ *                 handshake for the SSL context \p ssl.
  *
  * \param ssl      The SSL context representing the connection which should
  *                 be attempted to be setup using session resumption. This
@@ -3231,9 +3240,10 @@
  *
  * \return         \c 0 if successful.
  * \return         \c MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the session
- *                 could not be loaded because of an implementation limitation.
- *                 This error is non-fatal, and has no observable effect on
- *                 the SSL context or the session that was attempted to be loaded.
+ *                 could not be loaded because one session has already been
+ *                 loaded. This error is non-fatal, and has no observable
+ *                 effect on the SSL context or the session that was attempted
+ *                 to be loaded.
  * \return         Another negative error code on other kinds of failure.
  *
  * \sa             mbedtls_ssl_get_session()
@@ -3300,8 +3310,16 @@
  *                 to determine the necessary size by calling this function
  *                 with \p buf set to \c NULL and \p buf_len to \c 0.
  *
+ * \note           For TLS 1.3 sessions, this feature is supported only if the
+ *                 MBEDTLS_SSL_SESSION_TICKETS configuration option is enabled,
+ *                 as in TLS 1.3 session resumption is possible only with
+ *                 tickets.
+ *
  * \return         \c 0 if successful.
  * \return         #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small.
+ * \return         #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the
+ *                 MBEDTLS_SSL_SESSION_TICKETS configuration option is disabled
+ *                 and the session is a TLS 1.3 session.
  */
 int mbedtls_ssl_session_save(const mbedtls_ssl_session *session,
                              unsigned char *buf,
@@ -4828,23 +4846,16 @@
  * \note           This function can handle a variety of mechanisms for session
  *                 resumption: For TLS 1.2, both session ID-based resumption and
  *                 ticket-based resumption will be considered. For TLS 1.3,
- *                 once implemented, sessions equate to tickets, and calling
- *                 this function multiple times will export the available
- *                 tickets one a time until no further tickets are available,
- *                 in which case MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE will
- *                 be returned.
- *
- * \note           Calling this function multiple times will only be useful
- *                 once TLS 1.3 is supported. For TLS 1.2 connections, this
- *                 function should be called at most once.
+ *                 sessions equate to tickets, and if session tickets are
+ *                 enabled (see #MBEDTLS_SSL_SESSION_TICKETS configuration
+ *                 option), this function exports the last received ticket and
+ *                 the exported session may be used to resume the TLS 1.3
+ *                 session. If session tickets are disabled, exported sessions
+ *                 cannot be used to resume a TLS 1.3 session.
  *
  * \return         \c 0 if successful. In this case, \p session can be used for
  *                 session resumption by passing it to mbedtls_ssl_set_session(),
  *                 and serialized for storage via mbedtls_ssl_session_save().
- * \return         #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no further session
- *                 is available for export.
- *                 This error is a non-fatal, and has no observable effect on
- *                 the SSL context or the destination session.
  * \return         Another negative error code on other kinds of failure.
  *
  * \sa             mbedtls_ssl_set_session()
@@ -5214,6 +5225,11 @@
  *                   same warnings apply to any use of the
  *                   early_exporter_master_secret.
  *
+ * \warning        Mbed TLS does not implement any of the anti-replay defenses
+ *                 defined in section 8 of the TLS 1.3 specification:
+ *                 single-use of tickets or ClientHello recording within a
+ *                 given time window.
+ *
  * \note           This function is used in conjunction with
  *                 mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(),
  *                 mbedtls_ssl_read() and mbedtls_ssl_write() to read early
@@ -5337,8 +5353,8 @@
  * \return         #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called
  *                 prior to completion of the handshake.
  *
- * \return         #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT if the client has
- *                 not indicated the use of early data to the server.
+ * \return         #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED if the client
+ *                 has not indicated the use of early data to the server.
  *
  * \return         #MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED if the client has
  *                 indicated the use of early data and the server has accepted
diff --git a/include/mbedtls/ssl_ciphersuites.h b/include/mbedtls/ssl_ciphersuites.h
index f755ef3..12d4462 100644
--- a/include/mbedtls/ssl_ciphersuites.h
+++ b/include/mbedtls/ssl_ciphersuites.h
@@ -468,6 +468,11 @@
     return info->MBEDTLS_PRIVATE(name);
 }
 
+static inline int mbedtls_ssl_ciphersuite_get_id(const mbedtls_ssl_ciphersuite_t *info)
+{
+    return info->MBEDTLS_PRIVATE(id);
+}
+
 size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info);
 
 #ifdef __cplusplus
diff --git a/include/mbedtls/ssl_ticket.h b/include/mbedtls/ssl_ticket.h
index 5842049..2ee1400 100644
--- a/include/mbedtls/ssl_ticket.h
+++ b/include/mbedtls/ssl_ticket.h
@@ -108,10 +108,16 @@
  *                  least as strong as the strongest ciphersuite
  *                  supported. Usually that means a 256-bit key.
  *
- * \note            The lifetime of the keys is twice the lifetime of tickets.
- *                  It is recommended to pick a reasonable lifetime so as not
+ * \note            It is recommended to pick a reasonable lifetime so as not
  *                  to negate the benefits of forward secrecy.
  *
+ * \note            The TLS 1.3 specification states that ticket lifetime must
+ *                  be smaller than seven days. If ticket lifetime has been
+ *                  set to a value greater than seven days in this module then
+ *                  if the TLS 1.3 is configured to send tickets after the
+ *                  handshake it will fail the connection when trying to send
+ *                  the first ticket.
+ *
  * \return          0 if successful,
  *                  or a specific MBEDTLS_ERR_XXX error code
  */
@@ -145,10 +151,16 @@
  * \note            \c klength must be sufficient for use by cipher specified
  *                  to \c mbedtls_ssl_ticket_setup
  *
- * \note            The lifetime of the keys is twice the lifetime of tickets.
- *                  It is recommended to pick a reasonable lifetime so as not
+ * \note            It is recommended to pick a reasonable lifetime so as not
  *                  to negate the benefits of forward secrecy.
  *
+ * \note            The TLS 1.3 specification states that ticket lifetime must
+ *                  be smaller than seven days. If ticket lifetime has been
+ *                  set to a value greater than seven days in this module then
+ *                  if the TLS 1.3 is configured to send tickets after the
+ *                  handshake it will fail the connection when trying to send
+ *                  the first ticket.
+ *
  * \return          0 if successful,
  *                  or a specific MBEDTLS_ERR_XXX error code
  */
diff --git a/include/mbedtls/threading.h b/include/mbedtls/threading.h
index b4e0502..d50d04e 100644
--- a/include/mbedtls/threading.h
+++ b/include/mbedtls/threading.h
@@ -112,6 +112,20 @@
  * psa_key_slot_state_transition(), psa_register_read(), psa_unregister_read(),
  * psa_key_slot_has_readers() and psa_wipe_key_slot(). */
 extern mbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex;
+
+/*
+ * A mutex used to make the non-rng PSA global_data struct members thread safe.
+ *
+ * This mutex must be held when reading or writing to any of the PSA global_data
+ * structure members, other than the rng_state or rng struct. */
+extern mbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex;
+
+/*
+ * A mutex used to make the PSA global_data rng data thread safe.
+ *
+ * This mutex must be held when reading or writing to the PSA
+ * global_data rng_state or rng struct members. */
+extern mbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex;
 #endif
 
 #endif /* MBEDTLS_THREADING_C */
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 73889e0..7083bd9 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -527,6 +527,11 @@
  * If a key is currently in use in a multipart operation, then destroying the
  * key will cause the multipart operation to fail.
  *
+ * \warning    We can only guarantee that the the key material will
+ *             eventually be wiped from memory. With threading enabled
+ *             and during concurrent execution, copies of the key material may
+ *             still exist until all threads have finished using the key.
+ *
  * \param key  Identifier of the key to erase. If this is \c 0, do nothing and
  *             return #PSA_SUCCESS.
  *
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index 31ea686..c21bad8 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -469,7 +469,7 @@
  *     - \c flags: must be 0.
  *     - \c data: the public exponent, in little-endian order.
  *       This must be an odd integer and must not be 1.
- *       Implementations must support 65535, should support 3 and may
+ *       Implementations must support 65537, should support 3 and may
  *       support other values.
  *       When not using a driver, Mbed TLS supports values up to \c INT_MAX.
  *       If this is empty or if the custom production parameters are omitted
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 47ecf17..37a9724 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -56,6 +56,7 @@
     padlock.c
     pem.c
     pk.c
+    pk_ecc.c
     pk_wrap.c
     pkcs12.c
     pkcs5.c
@@ -219,11 +220,13 @@
     set(libs ${libs} ws2_32 bcrypt)
 endif(WIN32)
 
-if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
-    SET(CMAKE_C_ARCHIVE_CREATE   "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
-    SET(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
-    SET(CMAKE_C_ARCHIVE_FINISH   "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
-    SET(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
+if(CMAKE_C_COMPILER_ID MATCHES "AppleClang")
+    set(CMAKE_C_ARCHIVE_CREATE   "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
+    set(CMAKE_C_ARCHIVE_FINISH   "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
+endif()
+if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
+    set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> Scr <TARGET> <LINK_FLAGS> <OBJECTS>")
+    set(CMAKE_CXX_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols -c <TARGET>")
 endif()
 
 if(HAIKU)
@@ -297,7 +300,7 @@
 if(USE_SHARED_MBEDTLS_LIBRARY)
     set(CMAKE_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR})
     add_library(${mbedcrypto_target} SHARED ${src_crypto})
-    set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 3.5.2 SOVERSION 15)
+    set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 3.6.0 SOVERSION 16)
     target_link_libraries(${mbedcrypto_target} PUBLIC ${libs})
 
     if(TARGET ${everest_target})
@@ -309,11 +312,11 @@
     endif()
 
     add_library(${mbedx509_target} SHARED ${src_x509})
-    set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.5.2 SOVERSION 6)
+    set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.6.0 SOVERSION 7)
     target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target})
 
     add_library(${mbedtls_target} SHARED ${src_tls})
-    set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.5.2 SOVERSION 20)
+    set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.6.0 SOVERSION 21)
     target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target})
 endif(USE_SHARED_MBEDTLS_LIBRARY)
 
diff --git a/library/Makefile b/library/Makefile
index d11a98d..388fcea 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -1,3 +1,26 @@
+ifndef MBEDTLS_PATH
+MBEDTLS_PATH := ..
+endif
+
+GENERATED_FILES := \
+	error.c version_features.c \
+	ssl_debug_helpers_generated.c \
+	psa_crypto_driver_wrappers.h \
+	psa_crypto_driver_wrappers_no_static.c
+
+ifneq ($(GENERATED_FILES),$(wildcard $(GENERATED_FILES)))
+    ifeq (,$(wildcard $(MBEDTLS_PATH)/framework/exported.make))
+        # Use the define keyword to get a multi-line message.
+        # GNU make appends ".  Stop.", so tweak the ending of our message accordingly.
+        define error_message
+$(MBEDTLS_PATH)/framework/exported.make not found.
+Run `git submodule update --init` to fetch the submodule contents.
+This is a fatal error
+        endef
+        $(error $(error_message))
+    endif
+    include $(MBEDTLS_PATH)/framework/exported.make
+endif
 
 # Also see "include/mbedtls/mbedtls_config.h"
 
@@ -51,9 +74,9 @@
 endif
 endif
 
-SOEXT_TLS?=so.20
-SOEXT_X509?=so.6
-SOEXT_CRYPTO?=so.15
+SOEXT_TLS?=so.21
+SOEXT_X509?=so.7
+SOEXT_CRYPTO?=so.16
 
 # Set AR_DASH= (empty string) to use an ar implementation that does not accept
 # the - prefix for command line options (e.g. llvm-ar)
@@ -125,6 +148,7 @@
 	     padlock.o \
 	     pem.o \
 	     pk.o \
+	     pk_ecc.o \
 	     pk_wrap.o \
 	     pkcs12.o \
 	     pkcs5.o \
@@ -314,11 +338,6 @@
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $<
 
 .PHONY: generated_files
-GENERATED_FILES = \
-	error.c version_features.c \
-	ssl_debug_helpers_generated.c \
-	psa_crypto_driver_wrappers.h \
-	psa_crypto_driver_wrappers_no_static.c
 generated_files: $(GENERATED_FILES)
 
 # See root Makefile
diff --git a/library/bignum.c b/library/bignum.c
index d3d72ab..c45fd5b 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -37,6 +37,19 @@
 
 #include "mbedtls/platform.h"
 
+
+
+/*
+ * Conditionally select an MPI sign in constant time.
+ * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid
+ * values.)
+ */
+static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond,
+                                                  signed short sign1, signed short sign2)
+{
+    return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1;
+}
+
 /*
  * Compare signed values in constant time
  */
@@ -112,7 +125,7 @@
     {
         mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
 
-        X->s = (int) mbedtls_ct_uint_if(do_assign, Y->s, X->s);
+        X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s);
 
         mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
 
@@ -149,8 +162,8 @@
     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
 
     s = X->s;
-    X->s = (int) mbedtls_ct_uint_if(do_swap, Y->s, X->s);
-    Y->s = (int) mbedtls_ct_uint_if(do_swap, s, Y->s);
+    X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s);
+    Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s);
 
     mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
 
@@ -288,8 +301,7 @@
  * This function is not constant-time. Leading zeros in Y may be removed.
  *
  * Ensure that X does not shrink. This is not guaranteed by the public API,
- * but some code in the bignum module relies on this property, for example
- * in mbedtls_mpi_exp_mod().
+ * but some code in the bignum module might still rely on this property.
  */
 int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
 {
@@ -1598,98 +1610,11 @@
     return 0;
 }
 
-static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
-{
-    *mm = mbedtls_mpi_core_montmul_init(N->p);
-}
-
-/** Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
- *
- * \param[in,out]   A   One of the numbers to multiply.
- *                      It must have at least as many limbs as N
- *                      (A->n >= N->n), and any limbs beyond n are ignored.
- *                      On successful completion, A contains the result of
- *                      the multiplication A * B * R^-1 mod N where
- *                      R = (2^ciL)^n.
- * \param[in]       B   One of the numbers to multiply.
- *                      It must be nonzero and must not have more limbs than N
- *                      (B->n <= N->n).
- * \param[in]       N   The modulus. \p N must be odd.
- * \param           mm  The value calculated by `mpi_montg_init(&mm, N)`.
- *                      This is -N^-1 mod 2^ciL.
- * \param[in,out]   T   A bignum for temporary storage.
- *                      It must be at least twice the limb size of N plus 1
- *                      (T->n >= 2 * N->n + 1).
- *                      Its initial content is unused and
- *                      its final content is indeterminate.
- *                      It does not get reallocated.
- */
-static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
-                        const mbedtls_mpi *N, mbedtls_mpi_uint mm,
-                        mbedtls_mpi *T)
-{
-    mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p);
-}
-
-/*
- * Montgomery reduction: A = A * R^-1 mod N
- *
- * See mpi_montmul() regarding constraints and guarantees on the parameters.
- */
-static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
-                        mbedtls_mpi_uint mm, mbedtls_mpi *T)
-{
-    mbedtls_mpi_uint z = 1;
-    mbedtls_mpi U;
-    U.n = 1;
-    U.s = 1;
-    U.p = &z;
-
-    mpi_montmul(A, &U, N, mm, T);
-}
-
-/**
- * Select an MPI from a table without leaking the index.
- *
- * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
- * reads the entire table in order to avoid leaking the value of idx to an
- * attacker able to observe memory access patterns.
- *
- * \param[out] R        Where to write the selected MPI.
- * \param[in] T         The table to read from.
- * \param[in] T_size    The number of elements in the table.
- * \param[in] idx       The index of the element to select;
- *                      this must satisfy 0 <= idx < T_size.
- *
- * \return \c 0 on success, or a negative error code.
- */
-static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    for (size_t i = 0; i < T_size; i++) {
-        MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
-                                                     (unsigned char) mbedtls_ct_uint_eq(i, idx)));
-    }
-cleanup:
-    return ret;
-}
-
-/*
- * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
- */
 int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
                         const mbedtls_mpi *E, const mbedtls_mpi *N,
                         mbedtls_mpi *prec_RR)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t window_bitsize;
-    size_t i, j, nblimbs;
-    size_t bufsize, nbits;
-    size_t exponent_bits_in_window = 0;
-    mbedtls_mpi_uint ei, mm, state;
-    mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
-    int neg;
 
     if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -1705,261 +1630,88 @@
     }
 
     /*
-     * Init temps and window size
+     * Ensure that the exponent that we are passing to the core is not NULL.
      */
-    mpi_montg_init(&mm, N);
-    mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
-    mbedtls_mpi_init(&Apos);
-    mbedtls_mpi_init(&WW);
-    memset(W, 0, sizeof(W));
-
-    i = mbedtls_mpi_bitlen(E);
-
-    window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
-                     (i >  79) ? 4 : (i >  23) ? 3 : 1;
-
-#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
-    if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
-        window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
+    if (E->n == 0) {
+        ret = mbedtls_mpi_lset(X, 1);
+        return ret;
     }
-#endif
-
-    const size_t w_table_used_size = (size_t) 1 << window_bitsize;
 
     /*
-     * This function is not constant-trace: its memory accesses depend on the
-     * exponent value. To defend against timing attacks, callers (such as RSA
-     * and DHM) should use exponent blinding. However this is not enough if the
-     * adversary can find the exponent in a single trace, so this function
-     * takes extra precautions against adversaries who can observe memory
-     * access patterns.
-     *
-     * This function performs a series of multiplications by table elements and
-     * squarings, and we want the prevent the adversary from finding out which
-     * table element was used, and from distinguishing between multiplications
-     * and squarings. Firstly, when multiplying by an element of the window
-     * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
-     * squarings as having a different memory access patterns from other
-     * multiplications. So secondly, we put the accumulator in the table as
-     * well, and also do a constant-trace table lookup to multiply by the
-     * accumulator which is W[x_index].
-     *
-     * This way, all multiplications take the form of a lookup-and-multiply.
-     * The number of lookup-and-multiply operations inside each iteration of
-     * the main loop still depends on the bits of the exponent, but since the
-     * other operations in the loop don't have an easily recognizable memory
-     * trace, an adversary is unlikely to be able to observe the exact
-     * patterns.
-     *
-     * An adversary may still be able to recover the exponent if they can
-     * observe both memory accesses and branches. However, branch prediction
-     * exploitation typically requires many traces of execution over the same
-     * data, which is defeated by randomized blinding.
+     * Allocate working memory for mbedtls_mpi_core_exp_mod()
      */
-    const size_t x_index = 0;
-    mbedtls_mpi_init(&W[x_index]);
-
-    j = N->n + 1;
-    /* All W[i] including the accumulator must have at least N->n limbs for
-     * the mpi_montmul() and mpi_montred() calls later. Here we ensure that
-     * W[1] and the accumulator W[x_index] are large enough. later we'll grow
-     * other W[i] to the same length. They must not be shrunk midway through
-     * this function!
-     */
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1],  j));
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
-
-    /*
-     * Compensate for negative A (and correct at the end)
-     */
-    neg = (A->s == -1);
-    if (neg) {
-        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
-        Apos.s = 1;
-        A = &Apos;
+    size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n);
+    mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint));
+    if (T == NULL) {
+        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
     }
 
+    mbedtls_mpi RR;
+    mbedtls_mpi_init(&RR);
+
     /*
      * If 1st call, pre-compute R^2 mod N
      */
     if (prec_RR == NULL || prec_RR->p == NULL) {
-        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
-        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
-        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));
 
         if (prec_RR != NULL) {
-            memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
+            *prec_RR = RR;
         }
     } else {
-        memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n));
+        RR = *prec_RR;
     }
 
     /*
-     * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+     * To preserve constness we need to make a copy of A. Using X for this to
+     * save memory.
      */
-    if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
-        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
-        /* This should be a no-op because W[1] is already that large before
-         * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
-         * in mpi_montmul() below, so let's make sure. */
-        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
-    } else {
-        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
-    }
-
-    /* Note that this is safe because W[1] always has at least N->n limbs
-     * (it grew above and was preserved by mbedtls_mpi_copy()). */
-    mpi_montmul(&W[1], &RR, N, mm, &T);
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
 
     /*
-     * W[x_index] = R^2 * R^-1 mod N = R mod N
+     * Compensate for negative A (and correct at the end).
      */
-    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
-    mpi_montred(&W[x_index], N, mm, &T);
+    X->s = 1;
 
-
-    if (window_bitsize > 1) {
-        /*
-         * W[i] = W[1] ^ i
-         *
-         * The first bit of the sliding window is always 1 and therefore we
-         * only need to store the second half of the table.
-         *
-         * (There are two special elements in the table: W[0] for the
-         * accumulator/result and W[1] for A in Montgomery form. Both of these
-         * are already set at this point.)
-         */
-        j = w_table_used_size / 2;
-
-        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
-        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
-
-        for (i = 0; i < window_bitsize - 1; i++) {
-            mpi_montmul(&W[j], &W[j], N, mm, &T);
-        }
-
-        /*
-         * W[i] = W[i - 1] * W[1]
-         */
-        for (i = j + 1; i < w_table_used_size; i++) {
-            MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
-            MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
-
-            mpi_montmul(&W[i], &W[1], N, mm, &T);
-        }
+    /*
+     * Make sure that X is in a form that is safe for consumption by
+     * the core functions.
+     *
+     * - The core functions will not touch the limbs of X above N->n. The
+     *   result will be correct if those limbs are 0, which the mod call
+     *   ensures.
+     * - Also, X must have at least as many limbs as N for the calls to the
+     *   core functions.
+     */
+    if (mbedtls_mpi_cmp_mpi(X, N) >= 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
     }
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n));
 
-    nblimbs = E->n;
-    bufsize = 0;
-    nbits   = 0;
-    state   = 0;
-
-    while (1) {
-        if (bufsize == 0) {
-            if (nblimbs == 0) {
-                break;
-            }
-
-            nblimbs--;
-
-            bufsize = sizeof(mbedtls_mpi_uint) << 3;
-        }
-
-        bufsize--;
-
-        ei = (E->p[nblimbs] >> bufsize) & 1;
-
-        /*
-         * skip leading 0s
-         */
-        if (ei == 0 && state == 0) {
-            continue;
-        }
-
-        if (ei == 0 && state == 1) {
-            /*
-             * out of window, square W[x_index]
-             */
-            MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
-            mpi_montmul(&W[x_index], &WW, N, mm, &T);
-            continue;
-        }
-
-        /*
-         * add ei to current window
-         */
-        state = 2;
-
-        nbits++;
-        exponent_bits_in_window |= (ei << (window_bitsize - nbits));
-
-        if (nbits == window_bitsize) {
-            /*
-             * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
-             */
-            for (i = 0; i < window_bitsize; i++) {
-                MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
-                                           x_index));
-                mpi_montmul(&W[x_index], &WW, N, mm, &T);
-            }
-
-            /*
-             * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
-             */
-            MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
-                                       exponent_bits_in_window));
-            mpi_montmul(&W[x_index], &WW, N, mm, &T);
-
-            state--;
-            nbits = 0;
-            exponent_bits_in_window = 0;
-        }
+    /*
+     * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod().
+     */
+    {
+        mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);
+        mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T);
+        mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
+        mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T);
     }
 
     /*
-     * process the remaining bits
+     * Correct for negative A.
      */
-    for (i = 0; i < nbits; i++) {
-        MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
-        mpi_montmul(&W[x_index], &WW, N, mm, &T);
+    if (A->s == -1 && (E->p[0] & 1) != 0) {
+        mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n);
+        X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1);
 
-        exponent_bits_in_window <<= 1;
-
-        if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
-            MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
-            mpi_montmul(&W[x_index], &WW, N, mm, &T);
-        }
+        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X));
     }
 
-    /*
-     * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
-     */
-    mpi_montred(&W[x_index], N, mm, &T);
-
-    if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
-        W[x_index].s = -1;
-        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
-    }
-
-    /*
-     * Load the result in the output variable.
-     */
-    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &W[x_index]));
-
 cleanup:
 
-    /* The first bit of the sliding window is always 1 and therefore the first
-     * half of the table was unused. */
-    for (i = w_table_used_size/2; i < w_table_used_size; i++) {
-        mbedtls_mpi_free(&W[i]);
-    }
-
-    mbedtls_mpi_free(&W[x_index]);
-    mbedtls_mpi_free(&W[1]);
-    mbedtls_mpi_free(&T);
-    mbedtls_mpi_free(&Apos);
-    mbedtls_mpi_free(&WW);
+    mbedtls_mpi_zeroize_and_free(T, T_limbs);
 
     if (prec_RR == NULL || prec_RR->p == NULL) {
         mbedtls_mpi_free(&RR);
diff --git a/library/bignum_core.c b/library/bignum_core.c
index dfed60d..1a3e0b9 100644
--- a/library/bignum_core.c
+++ b/library/bignum_core.c
@@ -856,16 +856,17 @@
     return c;
 }
 
-mbedtls_mpi_uint mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
-                                                size_t limbs)
+mbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
+                                                      size_t limbs)
 {
+    volatile const mbedtls_mpi_uint *force_read_A = A;
     mbedtls_mpi_uint bits = 0;
 
     for (size_t i = 0; i < limbs; i++) {
-        bits |= A[i];
+        bits |= force_read_A[i];
     }
 
-    return bits;
+    return mbedtls_ct_bool(bits);
 }
 
 void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X,
diff --git a/library/bignum_core.h b/library/bignum_core.h
index b56be0a..92c8d47 100644
--- a/library/bignum_core.h
+++ b/library/bignum_core.h
@@ -662,11 +662,11 @@
  * \param[in] A   The MPI to test.
  * \param limbs   Number of limbs in \p A.
  *
- * \return        0 if `A == 0`
- *                non-0 (may be any value) if `A != 0`.
+ * \return        MBEDTLS_CT_FALSE if `A == 0`
+ *                MBEDTLS_CT_TRUE  if `A != 0`.
  */
-mbedtls_mpi_uint mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
-                                                size_t limbs);
+mbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
+                                                      size_t limbs);
 
 /**
  * \brief          Returns the number of limbs of working memory required for
diff --git a/library/cmac.c b/library/cmac.c
index f40cae2..eda10d0 100644
--- a/library/cmac.c
+++ b/library/cmac.c
@@ -34,6 +34,7 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform.h"
+#include "constant_time_internal.h"
 
 #include <string.h>
 
@@ -56,39 +57,33 @@
                               size_t blocksize)
 {
     const unsigned char R_128 = 0x87;
-    const unsigned char R_64 = 0x1B;
-    unsigned char R_n, mask;
-    unsigned char overflow = 0x00;
+    unsigned char R_n;
+    uint32_t overflow = 0x00;
     int i;
 
     if (blocksize == MBEDTLS_AES_BLOCK_SIZE) {
         R_n = R_128;
-    } else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) {
+    }
+#if defined(MBEDTLS_DES_C)
+    else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) {
+        const unsigned char R_64 = 0x1B;
         R_n = R_64;
-    } else {
+    }
+#endif
+    else {
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-    for (i = (int) blocksize - 1; i >= 0; i--) {
-        output[i] = input[i] << 1 | overflow;
-        overflow = input[i] >> 7;
+    for (i = (int) blocksize - 4; i >= 0; i -= 4) {
+        uint32_t i32 = MBEDTLS_GET_UINT32_BE(&input[i], 0);
+        uint32_t new_overflow = i32 >> 31;
+        i32 = (i32 << 1) | overflow;
+        MBEDTLS_PUT_UINT32_BE(i32, &output[i], 0);
+        overflow = new_overflow;
     }
 
-    /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
-     * using bit operations to avoid branches */
-
-    /* MSVC has a warning about unary minus on unsigned, but this is
-     * well-defined and precisely what we want to do here */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-    mask = -(input[0] >> 7);
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
-    output[blocksize - 1] ^= R_n & mask;
+    R_n = (unsigned char) mbedtls_ct_uint_if_else_0(mbedtls_ct_bool(input[0] >> 7), R_n);
+    output[blocksize - 1] ^= R_n;
 
     return 0;
 }
@@ -217,6 +212,10 @@
     block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
     state = ctx->cmac_ctx->state;
 
+    /* Without the MBEDTLS_ASSUME below, gcc -O3 will generate a warning of the form
+     * error: writing 16 bytes into a region of size 0 [-Werror=stringop-overflow=] */
+    MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE);
+
     /* Is there data still to process from the last call, that's greater in
      * size than a block? */
     if (cmac_ctx->unprocessed_len > 0 &&
@@ -284,6 +283,7 @@
 
     cmac_ctx = ctx->cmac_ctx;
     block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
+    MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE); // silence GCC warning
     state = cmac_ctx->state;
 
     mbedtls_platform_zeroize(K1, sizeof(K1));
diff --git a/library/gcm.c b/library/gcm.c
index 90c1d1d..5dfac23 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -412,8 +412,17 @@
         while (iv_len > 0) {
             use_len = (iv_len < 16) ? iv_len : 16;
 
+#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic warning "-Wstringop-overflow=0"
+#endif
+
             mbedtls_xor(ctx->y, ctx->y, p, use_len);
 
+#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
+#pragma GCC diagnostic pop
+#endif
+
             gcm_mult(ctx, ctx->y, ctx->y);
 
             iv_len -= use_len;
diff --git a/library/pk.c b/library/pk.c
index 003ef4a..e33a243 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -35,6 +35,10 @@
 #include <limits.h>
 #include <stdint.h>
 
+#define PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE \
+    (PSA_EXPORT_KEY_PAIR_MAX_SIZE > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) ? \
+    PSA_EXPORT_KEY_PAIR_MAX_SIZE : PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
+
 /*
  * Initialise a mbedtls_pk_context
  */
@@ -320,14 +324,14 @@
     }
 
     psa_algorithm_t key_alg = psa_get_key_algorithm(&attributes);
-    /* Key's enrollment is available only when MBEDTLS_PSA_CRYPTO_CLIENT is
-     * defined, i.e. when the Mbed TLS implementation of PSA Crypto is being used.
+    /* Key's enrollment is available only when an Mbed TLS implementation of PSA
+     * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined.
      * Even though we don't officially support using other implementations of PSA
-     * Crypto with TLS and X.509 (yet), we're still trying to simplify the life of
-     * people who would like to try it before it's officially supported. */
-#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+     * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations
+     * separated. */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
     psa_algorithm_t key_alg2 = psa_get_key_enrollment_algorithm(&attributes);
-#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
+#endif /* MBEDTLS_PSA_CRYPTO_C */
     key_usage = psa_get_key_usage_flags(&attributes);
     psa_reset_key_attributes(&attributes);
 
@@ -345,11 +349,11 @@
     if (alg == key_alg) {
         return 1;
     }
-#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+#if defined(MBEDTLS_PSA_CRYPTO_C)
     if (alg == key_alg2) {
         return 1;
     }
-#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
+#endif /* MBEDTLS_PSA_CRYPTO_C */
 
     /*
      * If key_alg [or key_alg2] is a hash-and-sign with a wildcard for the hash,
@@ -357,26 +361,25 @@
      * then alg is compliant with this key alg
      */
     if (PSA_ALG_IS_SIGN_HASH(alg)) {
-
         if (PSA_ALG_IS_SIGN_HASH(key_alg) &&
             PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH &&
             (alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) {
             return 1;
         }
-#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+#if defined(MBEDTLS_PSA_CRYPTO_C)
         if (PSA_ALG_IS_SIGN_HASH(key_alg2) &&
             PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH &&
             (alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) {
             return 1;
         }
-#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
+#endif /* MBEDTLS_PSA_CRYPTO_C */
     }
 
     return 0;
 }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 #if defined(MBEDTLS_RSA_C)
 static psa_algorithm_t psa_algorithm_for_rsa(const mbedtls_rsa_context *rsa,
                                              int want_crypt)
@@ -573,7 +576,14 @@
     }
 
     psa_set_key_usage_flags(attributes, more_usage);
+    /* Key's enrollment is available only when an Mbed TLS implementation of PSA
+     * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined.
+     * Even though we don't officially support using other implementations of PSA
+     * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations
+     * separated. */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
     psa_set_key_enrollment_algorithm(attributes, PSA_ALG_NONE);
+#endif
 
     return 0;
 }
@@ -850,7 +860,137 @@
         return import_pair_into_psa(pk, attributes, key_id);
     }
 }
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+static int copy_from_psa(mbedtls_svc_key_id_t key_id,
+                         mbedtls_pk_context *pk,
+                         int public_only)
+{
+    psa_status_t status;
+    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_type_t key_type;
+    psa_algorithm_t alg_type;
+    size_t key_bits;
+    /* Use a buffer size large enough to contain either a key pair or public key. */
+    unsigned char exp_key[PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE];
+    size_t exp_key_len;
+    int ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+
+    if (pk == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    status = psa_get_key_attributes(key_id, &key_attr);
+    if (status != PSA_SUCCESS) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    if (public_only) {
+        status = psa_export_public_key(key_id, exp_key, sizeof(exp_key), &exp_key_len);
+    } else {
+        status = psa_export_key(key_id, exp_key, sizeof(exp_key), &exp_key_len);
+    }
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+        goto exit;
+    }
+
+    key_type = psa_get_key_type(&key_attr);
+    if (public_only) {
+        key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type);
+    }
+    key_bits = psa_get_key_bits(&key_attr);
+    alg_type = psa_get_key_algorithm(&key_attr);
+
+#if defined(MBEDTLS_RSA_C)
+    if ((key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) ||
+        (key_type == PSA_KEY_TYPE_RSA_PUBLIC_KEY)) {
+
+        ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
+        if (ret != 0) {
+            goto exit;
+        }
+
+        if (key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+            ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), exp_key, exp_key_len);
+        } else {
+            ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), exp_key, exp_key_len);
+        }
+        if (ret != 0) {
+            goto exit;
+        }
+
+        mbedtls_md_type_t md_type = MBEDTLS_MD_NONE;
+        if (PSA_ALG_GET_HASH(alg_type) != PSA_ALG_ANY_HASH) {
+            md_type = mbedtls_md_type_from_psa_alg(alg_type);
+        }
+
+        if (PSA_ALG_IS_RSA_OAEP(alg_type) || PSA_ALG_IS_RSA_PSS(alg_type)) {
+            ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V21, md_type);
+        } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg_type) ||
+                   alg_type == PSA_ALG_RSA_PKCS1V15_CRYPT) {
+            ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V15, md_type);
+        }
+        if (ret != 0) {
+            goto exit;
+        }
+    } else
+#endif /* MBEDTLS_RSA_C */
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ||
+        PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type)) {
+        mbedtls_ecp_group_id grp_id;
+
+        ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
+        if (ret != 0) {
+            goto exit;
+        }
+
+        grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(key_type), key_bits);
+        ret = mbedtls_pk_ecc_set_group(pk, grp_id);
+        if (ret != 0) {
+            goto exit;
+        }
+
+        if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {
+            ret = mbedtls_pk_ecc_set_key(pk, exp_key, exp_key_len);
+            if (ret != 0) {
+                goto exit;
+            }
+            ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, exp_key, exp_key_len,
+                                                     mbedtls_psa_get_random,
+                                                     MBEDTLS_PSA_RANDOM_STATE);
+        } else {
+            ret = mbedtls_pk_ecc_set_pubkey(pk, exp_key, exp_key_len);
+        }
+        if (ret != 0) {
+            goto exit;
+        }
+    } else
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+    {
+        (void) key_bits;
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+exit:
+    psa_reset_key_attributes(&key_attr);
+    mbedtls_platform_zeroize(exp_key, sizeof(exp_key));
+
+    return ret;
+}
+
+int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id,
+                             mbedtls_pk_context *pk)
+{
+    return copy_from_psa(key_id, pk, 0);
+}
+
+int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id,
+                                    mbedtls_pk_context *pk)
+{
+    return copy_from_psa(key_id, pk, 1);
+}
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
 
 /*
  * Helper for mbedtls_pk_sign and mbedtls_pk_verify
@@ -987,6 +1127,12 @@
         return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len);
     }
 
+    /* Ensure the PK context is of the right type otherwise mbedtls_pk_rsa()
+     * below would return a NULL pointer. */
+    if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_RSA) {
+        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+    }
+
 #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_pk_rsassa_pss_options *pss_opts;
@@ -1017,7 +1163,7 @@
         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
         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);
+        key_len = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*ctx), buf, &p);
 
         if (key_len < 0) {
             return key_len;
@@ -1182,34 +1328,19 @@
     }
 
     if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) {
-        psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
-        psa_algorithm_t psa_alg, psa_enrollment_alg, sign_alg;
         psa_status_t status;
 
-        status = psa_get_key_attributes(ctx->priv_id, &key_attr);
-        if (status != PSA_SUCCESS) {
-            return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
-        }
-        psa_alg = psa_get_key_algorithm(&key_attr);
-        psa_enrollment_alg = psa_get_key_enrollment_algorithm(&key_attr);
-        psa_reset_key_attributes(&key_attr);
-
-        /* Since we're PK type is MBEDTLS_PK_RSASSA_PSS at least one between
-         * alg and enrollment alg should be of type RSA_PSS. */
-        if (PSA_ALG_IS_RSA_PSS(psa_alg)) {
-            sign_alg = psa_alg;
-        } else if (PSA_ALG_IS_RSA_PSS(psa_enrollment_alg)) {
-            sign_alg = psa_enrollment_alg;
-        } else {
-            /* The opaque key has no RSA PSS algorithm associated. */
-            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-        }
-        /* Adjust the hashing algorithm. */
-        sign_alg = (sign_alg & ~PSA_ALG_HASH_MASK) | PSA_ALG_GET_HASH(psa_md_alg);
-
-        status = psa_sign_hash(ctx->priv_id, sign_alg,
+        /* PSA_ALG_RSA_PSS() behaves the same as PSA_ALG_RSA_PSS_ANY_SALT() when
+         * performing a signature, but they are encoded differently. Instead of
+         * extracting the proper one from the wrapped key policy, just try both. */
+        status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS(psa_md_alg),
                                hash, hash_len,
                                sig, sig_size, sig_len);
+        if (status == PSA_ERROR_NOT_PERMITTED) {
+            status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg),
+                                   hash, hash_len,
+                                   sig, sig_size, sig_len);
+        }
         return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
     }
 
diff --git a/library/pk_ecc.c b/library/pk_ecc.c
new file mode 100644
index 0000000..86218ff
--- /dev/null
+++ b/library/pk_ecc.c
@@ -0,0 +1,255 @@
+/*
+ *  ECC setters for PK.
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#include "mbedtls/pk.h"
+#include "mbedtls/error.h"
+#include "mbedtls/ecp.h"
+#include "pk_internal.h"
+
+#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+
+int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id)
+{
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    size_t ec_bits;
+    psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits);
+
+    /* group may already be initialized; if so, make sure IDs match */
+    if ((pk->ec_family != 0 && pk->ec_family != ec_family) ||
+        (pk->ec_bits != 0 && pk->ec_bits != ec_bits)) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+    }
+
+    /* set group */
+    pk->ec_family = ec_family;
+    pk->ec_bits = ec_bits;
+
+    return 0;
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+    mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk);
+
+    /* grp may already be initialized; if so, make sure IDs match */
+    if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE &&
+        mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+    }
+
+    /* set group */
+    return mbedtls_ecp_group_load(&(ecp->grp), grp_id);
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+}
+
+int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len)
+{
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_usage_t flags;
+    psa_status_t status;
+
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family));
+    if (pk->ec_family == PSA_ECC_FAMILY_MONTGOMERY) {
+        /* Do not set algorithm here because Montgomery keys cannot do ECDSA and
+         * the PK module cannot do ECDH. When the key will be used in TLS for
+         * ECDH, it will be exported and then re-imported with proper flags
+         * and algorithm. */
+        flags = PSA_KEY_USAGE_EXPORT;
+    } else {
+        psa_set_key_algorithm(&attributes,
+                              MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH));
+        flags = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE |
+                PSA_KEY_USAGE_EXPORT;
+    }
+    psa_set_key_usage_flags(&attributes, flags);
+
+    status = psa_import_key(&attributes, key, key_len, &pk->priv_id);
+    return psa_pk_status_to_mbedtls(status);
+
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+
+    mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk);
+    int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len);
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+    }
+    return 0;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+}
+
+int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,
+                                       const unsigned char *prv, size_t prv_len,
+                                       int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+
+    (void) f_rng;
+    (void) p_rng;
+    (void) prv;
+    (void) prv_len;
+    psa_status_t status;
+
+    status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw),
+                                   &pk->pub_raw_len);
+    return psa_pk_status_to_mbedtls(status);
+
+#elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */
+
+    (void) f_rng;
+    (void) p_rng;
+    psa_status_t status;
+
+    mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
+    size_t curve_bits;
+    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits);
+
+    /* Import private key into PSA, from serialized input */
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+    psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
+    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);
+    status = psa_import_key(&key_attr, prv, prv_len, &key_id);
+    if (status != PSA_SUCCESS) {
+        return psa_pk_status_to_mbedtls(status);
+    }
+
+    /* Export public key from PSA */
+    unsigned char pub[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
+    size_t pub_len;
+    status = psa_export_public_key(key_id, pub, sizeof(pub), &pub_len);
+    psa_status_t destruction_status = psa_destroy_key(key_id);
+    if (status != PSA_SUCCESS) {
+        return psa_pk_status_to_mbedtls(status);
+    } else if (destruction_status != PSA_SUCCESS) {
+        return psa_pk_status_to_mbedtls(destruction_status);
+    }
+
+    /* Load serialized public key into ecp_keypair structure */
+    return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, pub, pub_len);
+
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+
+    (void) prv;
+    (void) prv_len;
+
+    mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
+    return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng);
+
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+}
+
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+/*
+ * Set the public key: fallback using ECP_LIGHT in the USE_PSA_EC_DATA case.
+ *
+ * Normally, when MBEDTLS_PK_USE_PSA_EC_DATA is enabled, we only use PSA
+ * functions to handle keys. However, currently psa_import_key() does not
+ * support compressed points. In case that support was explicitly requested,
+ * this fallback uses ECP functions to get the job done. This is the reason
+ * why MBEDTLS_PK_PARSE_EC_COMPRESSED auto-enables MBEDTLS_ECP_LIGHT.
+ *
+ * [in/out] pk: in: must have the group set, see mbedtls_pk_ecc_set_group().
+ *              out: will have the public key set.
+ * [in] pub, pub_len: the public key as an ECPoint,
+ *                    in any format supported by ECP.
+ *
+ * Return:
+ * - 0 on success;
+ * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
+ *   but not supported;
+ * - another error code otherwise.
+ */
+static int pk_ecc_set_pubkey_psa_ecp_fallback(mbedtls_pk_context *pk,
+                                              const unsigned char *pub,
+                                              size_t pub_len)
+{
+#if !defined(MBEDTLS_PK_PARSE_EC_COMPRESSED)
+    (void) pk;
+    (void) pub;
+    (void) pub_len;
+    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+#else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
+    mbedtls_ecp_keypair ecp_key;
+    mbedtls_ecp_group_id ecp_group_id;
+    int ret;
+
+    ecp_group_id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits);
+
+    mbedtls_ecp_keypair_init(&ecp_key);
+    ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q,
+                                        pub, pub_len);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q,
+                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                         &pk->pub_raw_len, pk->pub_raw,
+                                         sizeof(pk->pub_raw));
+
+exit:
+    mbedtls_ecp_keypair_free(&ecp_key);
+    return ret;
+#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
+}
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+
+int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len)
+{
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+
+    /* Load the key */
+    if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) {
+        /* Format directly supported by PSA:
+         * - non-Weierstrass curves that only have one format;
+         * - uncompressed format for Weierstrass curves. */
+        if (pub_len > sizeof(pk->pub_raw)) {
+            return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
+        }
+        memcpy(pk->pub_raw, pub, pub_len);
+        pk->pub_raw_len = pub_len;
+    } else {
+        /* Other format, try the fallback */
+        int ret = pk_ecc_set_pubkey_psa_ecp_fallback(pk, pub, pub_len);
+        if (ret != 0) {
+            return ret;
+        }
+    }
+
+    /* Validate the key by trying to import it */
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT;
+
+    psa_set_key_usage_flags(&key_attrs, 0);
+    psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family));
+    psa_set_key_bits(&key_attrs, pk->ec_bits);
+
+    if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len,
+                        &key_id) != PSA_SUCCESS) ||
+        (psa_destroy_key(key_id) != PSA_SUCCESS)) {
+        return MBEDTLS_ERR_PK_INVALID_PUBKEY;
+    }
+
+    return 0;
+
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+
+    int ret;
+    mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx;
+    ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len);
+    if (ret != 0) {
+        return ret;
+    }
+    return mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q);
+
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+}
+
+#endif /* MBEDTLS_PK_C && MBEDTLS_PK_HAVE_ECC_KEYS */
diff --git a/library/pk_internal.h b/library/pk_internal.h
index f5924ad..e86a3a0 100644
--- a/library/pk_internal.h
+++ b/library/pk_internal.h
@@ -127,6 +127,62 @@
 
     return MBEDTLS_PK_IS_RFC8410_GROUP_ID(id);
 }
+
+/*
+ * Set the group used by this key.
+ *
+ * [in/out] pk: in: must have been pk_setup() to an ECC type
+ *              out: will have group (curve) information set
+ * [in] grp_in: a supported group ID (not NONE)
+ */
+int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id);
+
+/*
+ * Set the private key material
+ *
+ * [in/out] pk: in: must have the group set already, see mbedtls_pk_ecc_set_group().
+ *              out: will have the private key set.
+ * [in] key, key_len: the raw private key (no ASN.1 wrapping).
+ */
+int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len);
+
+/*
+ * Set the public key.
+ *
+ * [in/out] pk: in: must have its group set, see mbedtls_pk_ecc_set_group().
+ *              out: will have the public key set.
+ * [in] pub, pub_len: the raw public key (an ECPoint).
+ *
+ * Return:
+ * - 0 on success;
+ * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
+ *   but not supported;
+ * - another error code otherwise.
+ */
+int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len);
+
+/*
+ * Derive a public key from its private counterpart.
+ * Computationally intensive, only use when public key is not available.
+ *
+ * [in/out] pk: in: must have the private key set, see mbedtls_pk_ecc_set_key().
+ *              out: will have the public key set.
+ * [in] prv, prv_len: the raw private key (see note below).
+ * [in] f_rng, p_rng: RNG function and context.
+ *
+ * Note: the private key information is always available from pk,
+ * however for convenience the serialized version is also passed,
+ * as it's available at each calling site, and useful in some configs
+ * (as otherwise we would have to re-serialize it from the pk context).
+ *
+ * There are three implementations of this function:
+ * 1. MBEDTLS_PK_USE_PSA_EC_DATA,
+ * 2. MBEDTLS_USE_PSA_CRYPTO but not MBEDTLS_PK_USE_PSA_EC_DATA,
+ * 3. not MBEDTLS_USE_PSA_CRYPTO.
+ */
+int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,
+                                       const unsigned char *prv, size_t prv_len,
+                                       int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
 /* Helper for (deterministic) ECDSA */
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 846175e..19196b5 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -368,7 +368,7 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_algorithm_t psa_md_alg;
+    psa_algorithm_t psa_md_alg, psa_encrypt_alg;
     psa_status_t status;
     int key_len;
     unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
@@ -389,10 +389,11 @@
     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
     if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
         psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa));
-        psa_set_key_algorithm(&attributes, PSA_ALG_RSA_OAEP(psa_md_alg));
+        psa_encrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg);
     } else {
-        psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+        psa_encrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT;
     }
+    psa_set_key_algorithm(&attributes, psa_encrypt_alg);
     psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
 
     status = psa_import_key(&attributes,
@@ -403,7 +404,7 @@
         goto cleanup;
     }
 
-    status = psa_asymmetric_encrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
+    status = psa_asymmetric_encrypt(key_id, psa_encrypt_alg,
                                     input, ilen,
                                     NULL, 0,
                                     output, osize, olen);
@@ -1468,16 +1469,29 @@
                               unsigned char *output, size_t *olen, size_t osize,
                               int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t alg;
+    psa_key_type_t type;
     psa_status_t status;
 
     /* PSA has its own RNG */
     (void) f_rng;
     (void) p_rng;
 
-    status = psa_asymmetric_decrypt(pk->priv_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
-                                    input, ilen,
-                                    NULL, 0,
-                                    output, osize, olen);
+    status = psa_get_key_attributes(pk->priv_id, &attributes);
+    if (status != PSA_SUCCESS) {
+        return PSA_PK_TO_MBEDTLS_ERR(status);
+    }
+
+    type = psa_get_key_type(&attributes);
+    alg = psa_get_key_algorithm(&attributes);
+    psa_reset_key_attributes(&attributes);
+
+    if (!PSA_KEY_TYPE_IS_RSA(type)) {
+        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+    }
+
+    status = psa_asymmetric_decrypt(pk->priv_id, alg, input, ilen, NULL, 0, output, osize, olen);
     if (status != PSA_SUCCESS) {
         return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
     }
@@ -1507,17 +1521,16 @@
     }
 
     type = psa_get_key_type(&attributes);
+    alg = psa_get_key_algorithm(&attributes);
     psa_reset_key_attributes(&attributes);
 
     if (PSA_KEY_TYPE_IS_RSA(type)) {
-        alg = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg));
+        alg = (alg & ~PSA_ALG_HASH_MASK) | mbedtls_md_psa_alg_from_type(md_alg);
     } else {
         return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
     }
 
-    /* make the signature */
-    status = psa_sign_hash(pk->priv_id, alg, hash, hash_len,
-                           sig, sig_size, sig_len);
+    status = psa_sign_hash(pk->priv_id, alg, hash, hash_len, sig, sig_size, sig_len);
     if (status != PSA_SUCCESS) {
         if (PSA_KEY_TYPE_IS_RSA(type)) {
             return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
diff --git a/library/pkparse.c b/library/pkparse.c
index 5a3d3b2..4f6ee13 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -46,302 +46,6 @@
 
 /***********************************************************************
  *
- *      ECC setters
- *
- * 1. This is an abstraction layer around MBEDTLS_PK_USE_PSA_EC_DATA:
- *    this macro will not appear outside this section.
- * 2. All inputs are raw: no metadata, no ASN.1 until the next section.
- *
- **********************************************************************/
-
-/*
- * Set the group used by this key.
- *
- * [in/out] pk: in: must have been pk_setup() to an ECC type
- *              out: will have group (curve) information set
- * [in] grp_in: a supported group ID (not NONE)
- */
-static int pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id)
-{
-#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
-    size_t ec_bits;
-    psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits);
-
-    /* group may already be initialized; if so, make sure IDs match */
-    if ((pk->ec_family != 0 && pk->ec_family != ec_family) ||
-        (pk->ec_bits != 0 && pk->ec_bits != ec_bits)) {
-        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
-    }
-
-    /* set group */
-    pk->ec_family = ec_family;
-    pk->ec_bits = ec_bits;
-
-    return 0;
-#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
-    mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk);
-
-    /* grp may already be initialized; if so, make sure IDs match */
-    if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE &&
-        mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) {
-        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
-    }
-
-    /* set group */
-    return mbedtls_ecp_group_load(&(ecp->grp), grp_id);
-#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
-}
-
-/*
- * Set the private key material
- *
- * [in/out] pk: in: must have the group set already, see pk_ecc_set_group().
- *              out: will have the private key set.
- * [in] key, key_len: the raw private key (no ASN.1 wrapping).
- */
-static int pk_ecc_set_key(mbedtls_pk_context *pk,
-                          unsigned char *key, size_t key_len)
-{
-#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_usage_t flags;
-    psa_status_t status;
-
-    psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family));
-    if (pk->ec_family == PSA_ECC_FAMILY_MONTGOMERY) {
-        /* Do not set algorithm here because Montgomery keys cannot do ECDSA and
-         * the PK module cannot do ECDH. When the key will be used in TLS for
-         * ECDH, it will be exported and then re-imported with proper flags
-         * and algorithm. */
-        flags = PSA_KEY_USAGE_EXPORT;
-    } else {
-        psa_set_key_algorithm(&attributes,
-                              MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH));
-        flags = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE |
-                PSA_KEY_USAGE_EXPORT;
-    }
-    psa_set_key_usage_flags(&attributes, flags);
-
-    status = psa_import_key(&attributes, key, key_len, &pk->priv_id);
-    return psa_pk_status_to_mbedtls(status);
-
-#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
-
-    mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk);
-    int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len);
-    if (ret != 0) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
-    }
-    return 0;
-#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
-}
-
-/*
- * Derive a public key from its private counterpart.
- * Computationally intensive, only use when public key is not available.
- *
- * [in/out] pk: in: must have the private key set, see pk_ecc_set_key().
- *              out: will have the public key set.
- * [in] prv, prv_len: the raw private key (see note below).
- * [in] f_rng, p_rng: RNG function and context.
- *
- * Note: the private key information is always available from pk,
- * however for convenience the serialized version is also passed,
- * as it's available at each calling site, and useful in some configs
- * (as otherwise we would have to re-serialize it from the pk context).
- *
- * There are three implementations of this function:
- * 1. MBEDTLS_PK_USE_PSA_EC_DATA,
- * 2. MBEDTLS_USE_PSA_CRYPTO but not MBEDTLS_PK_USE_PSA_EC_DATA,
- * 3. not MBEDTLS_USE_PSA_CRYPTO.
- */
-static int pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,
-                                      const unsigned char *prv, size_t prv_len,
-                                      int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
-{
-#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
-
-    (void) f_rng;
-    (void) p_rng;
-    (void) prv;
-    (void) prv_len;
-    psa_status_t status;
-
-    status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw),
-                                   &pk->pub_raw_len);
-    return psa_pk_status_to_mbedtls(status);
-
-#elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */
-
-    (void) f_rng;
-    (void) p_rng;
-    psa_status_t status;
-
-    mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
-    size_t curve_bits;
-    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits);
-
-    /* Import private key into PSA, from serialized input */
-    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
-    psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
-    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);
-    status = psa_import_key(&key_attr, prv, prv_len, &key_id);
-    if (status != PSA_SUCCESS) {
-        return psa_pk_status_to_mbedtls(status);
-    }
-
-    /* Export public key from PSA */
-    unsigned char pub[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
-    size_t pub_len;
-    status = psa_export_public_key(key_id, pub, sizeof(pub), &pub_len);
-    psa_status_t destruction_status = psa_destroy_key(key_id);
-    if (status != PSA_SUCCESS) {
-        return psa_pk_status_to_mbedtls(status);
-    } else if (destruction_status != PSA_SUCCESS) {
-        return psa_pk_status_to_mbedtls(destruction_status);
-    }
-
-    /* Load serialized public key into ecp_keypair structure */
-    return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, pub, pub_len);
-
-#else /* MBEDTLS_USE_PSA_CRYPTO */
-
-    (void) prv;
-    (void) prv_len;
-
-    mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
-    return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng);
-
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-}
-
-#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
-/*
- * Set the public key: fallback using ECP_LIGHT in the USE_PSA_EC_DATA case.
- *
- * Normally, when MBEDTLS_PK_USE_PSA_EC_DATA is enabled, we only use PSA
- * functions to handle keys. However, currently psa_import_key() does not
- * support compressed points. In case that support was explicitly requested,
- * this fallback uses ECP functions to get the job done. This is the reason
- * why MBEDTLS_PK_PARSE_EC_COMPRESSED auto-enables MBEDTLS_ECP_LIGHT.
- *
- * [in/out] pk: in: must have the group set, see pk_ecc_set_group().
- *              out: will have the public key set.
- * [in] pub, pub_len: the public key as an ECPoint,
- *                    in any format supported by ECP.
- *
- * Return:
- * - 0 on success;
- * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
- *   but not supported;
- * - another error code otherwise.
- */
-static int pk_ecc_set_pubkey_psa_ecp_fallback(mbedtls_pk_context *pk,
-                                              const unsigned char *pub,
-                                              size_t pub_len)
-{
-#if !defined(MBEDTLS_PK_PARSE_EC_COMPRESSED)
-    (void) pk;
-    (void) pub;
-    (void) pub_len;
-    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
-#else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
-    mbedtls_ecp_keypair ecp_key;
-    mbedtls_ecp_group_id ecp_group_id;
-    int ret;
-
-    ecp_group_id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits);
-
-    mbedtls_ecp_keypair_init(&ecp_key);
-    ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id);
-    if (ret != 0) {
-        goto exit;
-    }
-    ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q,
-                                        pub, pub_len);
-    if (ret != 0) {
-        goto exit;
-    }
-    ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q,
-                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
-                                         &pk->pub_raw_len, pk->pub_raw,
-                                         sizeof(pk->pub_raw));
-
-exit:
-    mbedtls_ecp_keypair_free(&ecp_key);
-    return ret;
-#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
-}
-#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
-
-/*
- * Set the public key.
- *
- * [in/out] pk: in: must have its group set, see pk_ecc_set_group().
- *              out: will have the public key set.
- * [in] pub, pub_len: the raw public key (an ECPoint).
- *
- * Return:
- * - 0 on success;
- * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
- *   but not supported;
- * - another error code otherwise.
- */
-static int pk_ecc_set_pubkey(mbedtls_pk_context *pk,
-                             const unsigned char *pub, size_t pub_len)
-{
-#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
-
-    /* Load the key */
-    if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) {
-        /* Format directly supported by PSA:
-         * - non-Weierstrass curves that only have one format;
-         * - uncompressed format for Weierstrass curves. */
-        if (pub_len > sizeof(pk->pub_raw)) {
-            return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
-        }
-        memcpy(pk->pub_raw, pub, pub_len);
-        pk->pub_raw_len = pub_len;
-    } else {
-        /* Other format, try the fallback */
-        int ret = pk_ecc_set_pubkey_psa_ecp_fallback(pk, pub, pub_len);
-        if (ret != 0) {
-            return ret;
-        }
-    }
-
-    /* Validate the key by trying to import it */
-    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT;
-
-    psa_set_key_usage_flags(&key_attrs, 0);
-    psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family));
-    psa_set_key_bits(&key_attrs, pk->ec_bits);
-
-    if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len,
-                        &key_id) != PSA_SUCCESS) ||
-        (psa_destroy_key(key_id) != PSA_SUCCESS)) {
-        return MBEDTLS_ERR_PK_INVALID_PUBKEY;
-    }
-
-    return 0;
-
-#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
-
-    int ret;
-    mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx;
-    ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len);
-    if (ret != 0) {
-        return ret;
-    }
-    return mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q);
-
-#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
-}
-
-/***********************************************************************
- *
  *      Low-level ECC parsing: optional support for SpecifiedECDomain
  *
  * There are two functions here that are used by the rest of the code:
@@ -698,7 +402,7 @@
         }
     }
 
-    return pk_ecc_set_group(pk, grp_id);
+    return mbedtls_pk_ecc_set_group(pk, grp_id);
 }
 
 #if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
@@ -714,7 +418,7 @@
         return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
     }
 
-    return pk_ecc_set_group(pk, grp_id);
+    return mbedtls_pk_ecc_set_group(pk, grp_id);
 }
 
 /*
@@ -740,7 +444,7 @@
     /*
      * Load the private key
      */
-    ret = pk_ecc_set_key(pk, key, len);
+    ret = mbedtls_pk_ecc_set_key(pk, key, len);
     if (ret != 0) {
         return ret;
     }
@@ -748,7 +452,7 @@
     /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys,
      * which never contain a public key. As such, derive the public key
      * unconditionally. */
-    if ((ret = pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) {
+    if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) {
         return ret;
     }
 
@@ -874,7 +578,7 @@
             ret = pk_use_ecparams(&alg_params, pk);
         }
         if (ret == 0) {
-            ret = pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p));
+            ret = mbedtls_pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p));
             *p += end - *p;
         }
     } else
@@ -966,7 +670,7 @@
     /*
      * Load the private key
      */
-    ret = pk_ecc_set_key(pk, d, d_len);
+    ret = mbedtls_pk_ecc_set_key(pk, d, d_len);
     if (ret != 0) {
         return ret;
     }
@@ -990,11 +694,11 @@
                                          MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
             }
 
-            if ((ret = pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) {
+            if ((ret = mbedtls_pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) {
                 pubkey_done = 1;
             } else {
                 /*
-                 * The only acceptable failure mode of pk_ecc_set_pubkey() above
+                 * The only acceptable failure mode of mbedtls_pk_ecc_set_pubkey() above
                  * is if the point format is not recognized.
                  */
                 if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
@@ -1007,7 +711,7 @@
     }
 
     if (!pubkey_done) {
-        if ((ret = pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) {
+        if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) {
             return ret;
         }
     }
diff --git a/library/pkwrite.h b/library/pkwrite.h
index 544ab2f..01dc3d2 100644
--- a/library/pkwrite.h
+++ b/library/pkwrite.h
@@ -109,4 +109,13 @@
 #define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES   0
 
 #endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+/* Define the maximum available public key DER length based on the supported
+ * key types (EC and/or RSA). */
+#if (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
+#define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE    MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES
+#else
+#define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE    MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES
+#endif
+
 #endif /* MBEDTLS_PK_WRITE_H */
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 3c2b6a0..02554d1 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -71,6 +71,7 @@
 #include "mbedtls/sha256.h"
 #include "mbedtls/sha512.h"
 #include "mbedtls/psa_util.h"
+#include "mbedtls/threading.h"
 
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) ||          \
     defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) ||  \
@@ -92,35 +93,205 @@
 #define RNG_INITIALIZED 1
 #define RNG_SEEDED 2
 
+/* IDs for PSA crypto subsystems. Starts at 1 to catch potential uninitialized
+ * variables as arguments. */
+typedef enum {
+    PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS = 1,
+    PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS,
+    PSA_CRYPTO_SUBSYSTEM_RNG,
+    PSA_CRYPTO_SUBSYSTEM_TRANSACTION,
+} mbedtls_psa_crypto_subsystem;
+
+/* Initialization flags for global_data::initialized */
+#define PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED    0x01
+#define PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED          0x02
+#define PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED        0x04
+
+#define PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED                ( \
+        PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED | \
+        PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED | \
+        PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)
+
 typedef struct {
     uint8_t initialized;
     uint8_t rng_state;
-    uint8_t drivers_initialized;
     mbedtls_psa_random_context_t rng;
 } psa_global_data_t;
 
 static psa_global_data_t global_data;
 
-#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
-mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state =
-    &global_data.rng.drbg;
-#endif
+static uint8_t psa_get_initialized(void)
+{
+    uint8_t initialized;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    initialized = global_data.rng_state == RNG_SEEDED;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    initialized =
+        (initialized && (global_data.initialized == PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED));
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    return initialized;
+}
+
+static uint8_t psa_get_drivers_initialized(void)
+{
+    uint8_t initialized;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    initialized = (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) != 0;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    return initialized;
+}
 
 #define GUARD_MODULE_INITIALIZED        \
-    if (global_data.initialized == 0)  \
+    if (psa_get_initialized() == 0)     \
     return PSA_ERROR_BAD_STATE;
 
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+
+/* Declare a local copy of an input buffer and a variable that will be used
+ * to store a pointer to the start of the buffer.
+ *
+ * Note: This macro must be called before any operations which may jump to
+ * the exit label, so that the local input copy object is safe to be freed.
+ *
+ * Assumptions:
+ * - input is the name of a pointer to the buffer to be copied
+ * - The name LOCAL_INPUT_COPY_OF_input is unused in the current scope
+ * - input_copy_name is a name that is unused in the current scope
+ */
+#define LOCAL_INPUT_DECLARE(input, input_copy_name) \
+    psa_crypto_local_input_t LOCAL_INPUT_COPY_OF_##input = PSA_CRYPTO_LOCAL_INPUT_INIT; \
+    const uint8_t *input_copy_name = NULL;
+
+/* Allocate a copy of the buffer input and set the pointer input_copy to
+ * point to the start of the copy.
+ *
+ * Assumptions:
+ * - psa_status_t status exists
+ * - An exit label is declared
+ * - input is the name of a pointer to the buffer to be copied
+ * - LOCAL_INPUT_DECLARE(input, input_copy) has previously been called
+ */
+#define LOCAL_INPUT_ALLOC(input, length, input_copy) \
+    status = psa_crypto_local_input_alloc(input, length, \
+                                          &LOCAL_INPUT_COPY_OF_##input); \
+    if (status != PSA_SUCCESS) { \
+        goto exit; \
+    } \
+    input_copy = LOCAL_INPUT_COPY_OF_##input.buffer;
+
+/* Free the local input copy allocated previously by LOCAL_INPUT_ALLOC()
+ *
+ * Assumptions:
+ * - input_copy is the name of the input copy pointer set by LOCAL_INPUT_ALLOC()
+ * - input is the name of the original buffer that was copied
+ */
+#define LOCAL_INPUT_FREE(input, input_copy) \
+    input_copy = NULL; \
+    psa_crypto_local_input_free(&LOCAL_INPUT_COPY_OF_##input);
+
+/* Declare a local copy of an output buffer and a variable that will be used
+ * to store a pointer to the start of the buffer.
+ *
+ * Note: This macro must be called before any operations which may jump to
+ * the exit label, so that the local output copy object is safe to be freed.
+ *
+ * Assumptions:
+ * - output is the name of a pointer to the buffer to be copied
+ * - The name LOCAL_OUTPUT_COPY_OF_output is unused in the current scope
+ * - output_copy_name is a name that is unused in the current scope
+ */
+#define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \
+    psa_crypto_local_output_t LOCAL_OUTPUT_COPY_OF_##output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; \
+    uint8_t *output_copy_name = NULL;
+
+/* Allocate a copy of the buffer output and set the pointer output_copy to
+ * point to the start of the copy.
+ *
+ * Assumptions:
+ * - psa_status_t status exists
+ * - An exit label is declared
+ * - output is the name of a pointer to the buffer to be copied
+ * - LOCAL_OUTPUT_DECLARE(output, output_copy) has previously been called
+ */
+#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \
+    status = psa_crypto_local_output_alloc(output, length, \
+                                           &LOCAL_OUTPUT_COPY_OF_##output); \
+    if (status != PSA_SUCCESS) { \
+        goto exit; \
+    } \
+    output_copy = LOCAL_OUTPUT_COPY_OF_##output.buffer;
+
+/* Free the local output copy allocated previously by LOCAL_OUTPUT_ALLOC()
+ * after first copying back its contents to the original buffer.
+ *
+ * Assumptions:
+ * - psa_status_t status exists
+ * - output_copy is the name of the output copy pointer set by LOCAL_OUTPUT_ALLOC()
+ * - output is the name of the original buffer that was copied
+ */
+#define LOCAL_OUTPUT_FREE(output, output_copy) \
+    output_copy = NULL; \
+    do { \
+        psa_status_t local_output_status; \
+        local_output_status = psa_crypto_local_output_free(&LOCAL_OUTPUT_COPY_OF_##output); \
+        if (local_output_status != PSA_SUCCESS) { \
+            /* Since this error case is an internal error, it's more serious than \
+             * any existing error code and so it's fine to overwrite the existing \
+             * status. */ \
+            status = local_output_status; \
+        } \
+    } while (0)
+#else /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */
+#define LOCAL_INPUT_DECLARE(input, input_copy_name) \
+    const uint8_t *input_copy_name = NULL;
+#define LOCAL_INPUT_ALLOC(input, length, input_copy) \
+    input_copy = input;
+#define LOCAL_INPUT_FREE(input, input_copy) \
+    input_copy = NULL;
+#define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \
+    uint8_t *output_copy_name = NULL;
+#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \
+    output_copy = output;
+#define LOCAL_OUTPUT_FREE(output, output_copy) \
+    output_copy = NULL;
+#endif /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */
+
+
 int psa_can_do_hash(psa_algorithm_t hash_alg)
 {
     (void) hash_alg;
-    return global_data.drivers_initialized;
+    return psa_get_drivers_initialized();
 }
 
 int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg)
 {
     (void) key_type;
     (void) cipher_alg;
-    return global_data.drivers_initialized;
+    return psa_get_drivers_initialized();
 }
 
 
@@ -1106,6 +1277,17 @@
      * fully destroyed. */
     PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(
                                     &mbedtls_threading_key_slot_mutex));
+
+    if (slot->state == PSA_SLOT_PENDING_DELETION) {
+        /* Another thread has destroyed the key between us locking the slot
+         * and us gaining the mutex. Unregister from the slot,
+         * and report that the key does not exist. */
+        status = psa_unregister_read(slot);
+
+        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                                  &mbedtls_threading_key_slot_mutex));
+        return (status == PSA_SUCCESS) ? PSA_ERROR_INVALID_HANDLE : status;
+    }
 #endif
     /* Set the key slot containing the key description's state to
      * PENDING_DELETION. This stops new operations from registering
@@ -1115,10 +1297,10 @@
      * If the key is persistent, we can now delete the copy of the key
      * from memory. If the key is opaque, we require the driver to
      * deal with the deletion. */
-    status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL,
-                                           PSA_SLOT_PENDING_DELETION);
+    overall_status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL,
+                                                   PSA_SLOT_PENDING_DELETION);
 
-    if (status != PSA_SUCCESS) {
+    if (overall_status != PSA_SUCCESS) {
         goto exit;
     }
 
@@ -1291,13 +1473,14 @@
 }
 
 psa_status_t psa_export_key(mbedtls_svc_key_id_t key,
-                            uint8_t *data,
+                            uint8_t *data_external,
                             size_t data_size,
                             size_t *data_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
+    LOCAL_OUTPUT_DECLARE(data_external, data);
 
     /* Reject a zero-length output buffer now, since this can never be a
      * valid key representation. This way we know that data must be a valid
@@ -1322,12 +1505,18 @@
         return status;
     }
 
+    LOCAL_OUTPUT_ALLOC(data_external, data_size, data);
+
     status = psa_driver_wrapper_export_key(&slot->attr,
                                            slot->key.data, slot->key.bytes,
                                            data, data_size, data_length);
 
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
     unlock_status = psa_unregister_read_under_mutex(slot);
 
+    LOCAL_OUTPUT_FREE(data_external, data);
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
 
@@ -1399,7 +1588,7 @@
 }
 
 psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key,
-                                   uint8_t *data,
+                                   uint8_t *data_external,
                                    size_t data_size,
                                    size_t *data_length)
 {
@@ -1407,6 +1596,8 @@
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
 
+    LOCAL_OUTPUT_DECLARE(data_external, data);
+
     /* Reject a zero-length output buffer now, since this can never be a
      * valid key representation. This way we know that data must be a valid
      * pointer and we can do things like memset(data, ..., data_size). */
@@ -1426,6 +1617,8 @@
         return status;
     }
 
+    LOCAL_OUTPUT_ALLOC(data_external, data_size, data);
+
     if (!PSA_KEY_TYPE_IS_ASYMMETRIC(slot->attr.type)) {
         status = PSA_ERROR_INVALID_ARGUMENT;
         goto exit;
@@ -1438,6 +1631,7 @@
 exit:
     unlock_status = psa_unregister_read_under_mutex(slot);
 
+    LOCAL_OUTPUT_FREE(data_external, data);
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
 
@@ -1641,6 +1835,9 @@
 
         status = psa_copy_key_material_into_slot(
             slot, (uint8_t *) (&slot_number), sizeof(slot_number));
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
     }
 
     if (*p_drv == NULL && method == PSA_KEY_CREATION_REGISTER) {
@@ -1843,11 +2040,12 @@
 }
 
 psa_status_t psa_import_key(const psa_key_attributes_t *attributes,
-                            const uint8_t *data,
+                            const uint8_t *data_external,
                             size_t data_length,
                             mbedtls_svc_key_id_t *key)
 {
     psa_status_t status;
+    LOCAL_INPUT_DECLARE(data_external, data);
     psa_key_slot_t *slot = NULL;
     psa_se_drv_table_entry_t *driver = NULL;
     size_t bits;
@@ -1867,6 +2065,8 @@
         return PSA_ERROR_NOT_SUPPORTED;
     }
 
+    LOCAL_INPUT_ALLOC(data_external, data_length, data);
+
     status = psa_start_key_creation(PSA_KEY_CREATION_IMPORT, attributes,
                                     &slot, &driver);
     if (status != PSA_SUCCESS) {
@@ -1921,6 +2121,7 @@
 
     status = psa_finish_key_creation(slot, driver, key);
 exit:
+    LOCAL_INPUT_FREE(data_external, data);
     if (status != PSA_SUCCESS) {
         psa_fail_key_creation(slot, driver);
     }
@@ -2122,10 +2323,11 @@
 }
 
 psa_status_t psa_hash_update(psa_hash_operation_t *operation,
-                             const uint8_t *input,
+                             const uint8_t *input_external,
                              size_t input_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(input_external, input);
 
     if (operation->id == 0) {
         status = PSA_ERROR_BAD_STATE;
@@ -2138,6 +2340,7 @@
         return PSA_SUCCESS;
     }
 
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
     status = psa_driver_wrapper_hash_update(operation, input, input_length);
 
 exit:
@@ -2145,32 +2348,57 @@
         psa_hash_abort(operation);
     }
 
+    LOCAL_INPUT_FREE(input_external, input);
     return status;
 }
 
-psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
-                             uint8_t *hash,
-                             size_t hash_size,
-                             size_t *hash_length)
+static psa_status_t psa_hash_finish_internal(psa_hash_operation_t *operation,
+                                             uint8_t *hash,
+                                             size_t hash_size,
+                                             size_t *hash_length)
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
     *hash_length = 0;
     if (operation->id == 0) {
         return PSA_ERROR_BAD_STATE;
     }
 
-    psa_status_t status = psa_driver_wrapper_hash_finish(
+    status = psa_driver_wrapper_hash_finish(
         operation, hash, hash_size, hash_length);
     psa_hash_abort(operation);
+
+    return status;
+}
+
+psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
+                             uint8_t *hash_external,
+                             size_t hash_size,
+                             size_t *hash_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_OUTPUT_DECLARE(hash_external, hash);
+
+    LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash);
+    status = psa_hash_finish_internal(operation, hash, hash_size, hash_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_OUTPUT_FREE(hash_external, hash);
     return status;
 }
 
 psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
-                             const uint8_t *hash,
+                             const uint8_t *hash_external,
                              size_t hash_length)
 {
     uint8_t actual_hash[PSA_HASH_MAX_SIZE];
     size_t actual_hash_length;
-    psa_status_t status = psa_hash_finish(
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(hash_external, hash);
+
+    status = psa_hash_finish_internal(
         operation,
         actual_hash, sizeof(actual_hash),
         &actual_hash_length);
@@ -2184,6 +2412,7 @@
         goto exit;
     }
 
+    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
     if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) {
         status = PSA_ERROR_INVALID_SIGNATURE;
     }
@@ -2193,36 +2422,55 @@
     if (status != PSA_SUCCESS) {
         psa_hash_abort(operation);
     }
-
+    LOCAL_INPUT_FREE(hash_external, hash);
     return status;
 }
 
 psa_status_t psa_hash_compute(psa_algorithm_t alg,
-                              const uint8_t *input, size_t input_length,
-                              uint8_t *hash, size_t hash_size,
+                              const uint8_t *input_external, size_t input_length,
+                              uint8_t *hash_external, size_t hash_size,
                               size_t *hash_length)
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(hash_external, hash);
+
     *hash_length = 0;
     if (!PSA_ALG_IS_HASH(alg)) {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
-    return psa_driver_wrapper_hash_compute(alg, input, input_length,
-                                           hash, hash_size, hash_length);
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash);
+    status = psa_driver_wrapper_hash_compute(alg, input, input_length,
+                                             hash, hash_size, hash_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(hash_external, hash);
+    return status;
 }
 
 psa_status_t psa_hash_compare(psa_algorithm_t alg,
-                              const uint8_t *input, size_t input_length,
-                              const uint8_t *hash, size_t hash_length)
+                              const uint8_t *input_external, size_t input_length,
+                              const uint8_t *hash_external, size_t hash_length)
 {
     uint8_t actual_hash[PSA_HASH_MAX_SIZE];
     size_t actual_hash_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_INPUT_DECLARE(hash_external, hash);
 
     if (!PSA_ALG_IS_HASH(alg)) {
-        return PSA_ERROR_INVALID_ARGUMENT;
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        return status;
     }
 
-    psa_status_t status = psa_driver_wrapper_hash_compute(
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    status = psa_driver_wrapper_hash_compute(
         alg, input, input_length,
         actual_hash, sizeof(actual_hash),
         &actual_hash_length);
@@ -2233,12 +2481,18 @@
         status = PSA_ERROR_INVALID_SIGNATURE;
         goto exit;
     }
+
+    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
     if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) {
         status = PSA_ERROR_INVALID_SIGNATURE;
     }
 
 exit:
     mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash));
+
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_INPUT_FREE(hash_external, hash);
+
     return status;
 }
 
@@ -2403,35 +2657,48 @@
 }
 
 psa_status_t psa_mac_update(psa_mac_operation_t *operation,
-                            const uint8_t *input,
+                            const uint8_t *input_external,
                             size_t input_length)
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(input_external, input);
+
     if (operation->id == 0) {
-        return PSA_ERROR_BAD_STATE;
+        status = PSA_ERROR_BAD_STATE;
+        return status;
     }
 
     /* Don't require hash implementations to behave correctly on a
      * zero-length input, which may have an invalid pointer. */
     if (input_length == 0) {
-        return PSA_SUCCESS;
+        status = PSA_SUCCESS;
+        return status;
     }
 
-    psa_status_t status = psa_driver_wrapper_mac_update(operation,
-                                                        input, input_length);
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    status = psa_driver_wrapper_mac_update(operation, input, input_length);
+
     if (status != PSA_SUCCESS) {
         psa_mac_abort(operation);
     }
 
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(input_external, input);
+
     return status;
 }
 
 psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,
-                                 uint8_t *mac,
+                                 uint8_t *mac_external,
                                  size_t mac_size,
                                  size_t *mac_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_OUTPUT_DECLARE(mac_external, mac);
+    LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac);
 
     if (operation->id == 0) {
         status = PSA_ERROR_BAD_STATE;
@@ -2455,6 +2722,7 @@
         goto exit;
     }
 
+
     status = psa_driver_wrapper_mac_sign_finish(operation,
                                                 mac, operation->mac_size,
                                                 mac_length);
@@ -2471,19 +2739,23 @@
         operation->mac_size = 0;
     }
 
-    psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length);
+    if (mac != NULL) {
+        psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length);
+    }
 
     abort_status = psa_mac_abort(operation);
+    LOCAL_OUTPUT_FREE(mac_external, mac);
 
     return status == PSA_SUCCESS ? abort_status : status;
 }
 
 psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,
-                                   const uint8_t *mac,
+                                   const uint8_t *mac_external,
                                    size_t mac_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(mac_external, mac);
 
     if (operation->id == 0) {
         status = PSA_ERROR_BAD_STATE;
@@ -2500,11 +2772,13 @@
         goto exit;
     }
 
+    LOCAL_INPUT_ALLOC(mac_external, mac_length, mac);
     status = psa_driver_wrapper_mac_verify_finish(operation,
                                                   mac, mac_length);
 
 exit:
     abort_status = psa_mac_abort(operation);
+    LOCAL_INPUT_FREE(mac_external, mac);
 
     return status == PSA_SUCCESS ? abort_status : status;
 }
@@ -2571,28 +2845,45 @@
 
 psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key,
                              psa_algorithm_t alg,
-                             const uint8_t *input,
+                             const uint8_t *input_external,
                              size_t input_length,
-                             uint8_t *mac,
+                             uint8_t *mac_external,
                              size_t mac_size,
                              size_t *mac_length)
 {
-    return psa_mac_compute_internal(key, alg,
-                                    input, input_length,
-                                    mac, mac_size, mac_length, 1);
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(mac_external, mac);
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac);
+    status = psa_mac_compute_internal(key, alg,
+                                      input, input_length,
+                                      mac, mac_size, mac_length, 1);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(mac_external, mac);
+
+    return status;
 }
 
 psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key,
                             psa_algorithm_t alg,
-                            const uint8_t *input,
+                            const uint8_t *input_external,
                             size_t input_length,
-                            const uint8_t *mac,
+                            const uint8_t *mac_external,
                             size_t mac_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     uint8_t actual_mac[PSA_MAC_MAX_SIZE];
     size_t actual_mac_length;
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_INPUT_DECLARE(mac_external, mac);
 
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
     status = psa_mac_compute_internal(key, alg,
                                       input, input_length,
                                       actual_mac, sizeof(actual_mac),
@@ -2605,6 +2896,8 @@
         status = PSA_ERROR_INVALID_SIGNATURE;
         goto exit;
     }
+
+    LOCAL_INPUT_ALLOC(mac_external, mac_length, mac);
     if (mbedtls_ct_memcmp(mac, actual_mac, actual_mac_length) != 0) {
         status = PSA_ERROR_INVALID_SIGNATURE;
         goto exit;
@@ -2612,6 +2905,8 @@
 
 exit:
     mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac));
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_INPUT_FREE(mac_external, mac);
 
     return status;
 }
@@ -2790,15 +3085,27 @@
 
 psa_status_t psa_sign_message(mbedtls_svc_key_id_t key,
                               psa_algorithm_t alg,
-                              const uint8_t *input,
+                              const uint8_t *input_external,
                               size_t input_length,
-                              uint8_t *signature,
+                              uint8_t *signature_external,
                               size_t signature_size,
                               size_t *signature_length)
 {
-    return psa_sign_internal(
-        key, 1, alg, input, input_length,
-        signature, signature_size, signature_length);
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(signature_external, signature);
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature);
+    status = psa_sign_internal(key, 1, alg, input, input_length, signature,
+                               signature_size, signature_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(signature_external, signature);
+    return status;
 }
 
 psa_status_t psa_verify_message_builtin(
@@ -2837,14 +3144,27 @@
 
 psa_status_t psa_verify_message(mbedtls_svc_key_id_t key,
                                 psa_algorithm_t alg,
-                                const uint8_t *input,
+                                const uint8_t *input_external,
                                 size_t input_length,
-                                const uint8_t *signature,
+                                const uint8_t *signature_external,
                                 size_t signature_length)
 {
-    return psa_verify_internal(
-        key, 1, alg, input, input_length,
-        signature, signature_length);
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_INPUT_DECLARE(signature_external, signature);
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);
+    status = psa_verify_internal(key, 1, alg, input, input_length, signature,
+                                 signature_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_INPUT_FREE(signature_external, signature);
+
+    return status;
 }
 
 psa_status_t psa_sign_hash_builtin(
@@ -2897,15 +3217,28 @@
 
 psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key,
                            psa_algorithm_t alg,
-                           const uint8_t *hash,
+                           const uint8_t *hash_external,
                            size_t hash_length,
-                           uint8_t *signature,
+                           uint8_t *signature_external,
                            size_t signature_size,
                            size_t *signature_length)
 {
-    return psa_sign_internal(
-        key, 0, alg, hash, hash_length,
-        signature, signature_size, signature_length);
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(hash_external, hash);
+    LOCAL_OUTPUT_DECLARE(signature_external, signature);
+
+    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
+    LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature);
+    status = psa_sign_internal(key, 0, alg, hash, hash_length, signature,
+                               signature_size, signature_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(hash_external, hash);
+    LOCAL_OUTPUT_FREE(signature_external, signature);
+
+    return status;
 }
 
 psa_status_t psa_verify_hash_builtin(
@@ -2957,23 +3290,36 @@
 
 psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key,
                              psa_algorithm_t alg,
-                             const uint8_t *hash,
+                             const uint8_t *hash_external,
                              size_t hash_length,
-                             const uint8_t *signature,
+                             const uint8_t *signature_external,
                              size_t signature_length)
 {
-    return psa_verify_internal(
-        key, 0, alg, hash, hash_length,
-        signature, signature_length);
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(hash_external, hash);
+    LOCAL_INPUT_DECLARE(signature_external, signature);
+
+    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
+    LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);
+    status = psa_verify_internal(key, 0, alg, hash, hash_length, signature,
+                                 signature_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(hash_external, hash);
+    LOCAL_INPUT_FREE(signature_external, signature);
+
+    return status;
 }
 
 psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key,
                                     psa_algorithm_t alg,
-                                    const uint8_t *input,
+                                    const uint8_t *input_external,
                                     size_t input_length,
-                                    const uint8_t *salt,
+                                    const uint8_t *salt_external,
                                     size_t salt_length,
-                                    uint8_t *output,
+                                    uint8_t *output_external,
                                     size_t output_size,
                                     size_t *output_length)
 {
@@ -2981,6 +3327,10 @@
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
 
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_INPUT_DECLARE(salt_external, salt);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
     (void) input;
     (void) input_length;
     (void) salt;
@@ -3004,6 +3354,10 @@
         goto exit;
     }
 
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_INPUT_ALLOC(salt_external, salt_length, salt);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
     status = psa_driver_wrapper_asymmetric_encrypt(
         &slot->attr, slot->key.data, slot->key.bytes,
         alg, input, input_length, salt, salt_length,
@@ -3011,16 +3365,20 @@
 exit:
     unlock_status = psa_unregister_read_under_mutex(slot);
 
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_INPUT_FREE(salt_external, salt);
+    LOCAL_OUTPUT_FREE(output_external, output);
+
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
 
 psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key,
                                     psa_algorithm_t alg,
-                                    const uint8_t *input,
+                                    const uint8_t *input_external,
                                     size_t input_length,
-                                    const uint8_t *salt,
+                                    const uint8_t *salt_external,
                                     size_t salt_length,
-                                    uint8_t *output,
+                                    uint8_t *output_external,
                                     size_t output_size,
                                     size_t *output_length)
 {
@@ -3028,6 +3386,10 @@
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
 
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_INPUT_DECLARE(salt_external, salt);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
     (void) input;
     (void) input_length;
     (void) salt;
@@ -3050,6 +3412,10 @@
         goto exit;
     }
 
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_INPUT_ALLOC(salt_external, salt_length, salt);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
     status = psa_driver_wrapper_asymmetric_decrypt(
         &slot->attr, slot->key.data, slot->key.bytes,
         alg, input, input_length, salt, salt_length,
@@ -3058,6 +3424,10 @@
 exit:
     unlock_status = psa_unregister_read_under_mutex(slot);
 
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_INPUT_FREE(salt_external, salt);
+    LOCAL_OUTPUT_FREE(output_external, output);
+
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
 
@@ -3115,12 +3485,14 @@
 psa_status_t psa_sign_hash_start(
     psa_sign_hash_interruptible_operation_t *operation,
     mbedtls_svc_key_id_t key, psa_algorithm_t alg,
-    const uint8_t *hash, size_t hash_length)
+    const uint8_t *hash_external, size_t hash_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
 
+    LOCAL_INPUT_DECLARE(hash_external, hash);
+
     /* Check that start has not been previously called, or operation has not
      * previously errored. */
     if (operation->id != 0 || operation->error_occurred) {
@@ -3146,6 +3518,8 @@
         goto exit;
     }
 
+    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
+
     /* Ensure ops count gets reset, in case of operation re-use. */
     operation->num_ops = 0;
 
@@ -3166,17 +3540,21 @@
         operation->error_occurred = 1;
     }
 
+    LOCAL_INPUT_FREE(hash_external, hash);
+
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
 
 
 psa_status_t psa_sign_hash_complete(
     psa_sign_hash_interruptible_operation_t *operation,
-    uint8_t *signature, size_t signature_size,
+    uint8_t *signature_external, size_t signature_size,
     size_t *signature_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
+    LOCAL_OUTPUT_DECLARE(signature_external, signature);
+
     *signature_length = 0;
 
     /* Check that start has been called first, and that operation has not
@@ -3193,6 +3571,8 @@
         goto exit;
     }
 
+    LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature);
+
     status = psa_driver_wrapper_sign_hash_complete(operation, signature,
                                                    signature_size,
                                                    signature_length);
@@ -3202,8 +3582,10 @@
 
 exit:
 
-    psa_wipe_tag_output_buffer(signature, status, signature_size,
-                               *signature_length);
+    if (signature != NULL) {
+        psa_wipe_tag_output_buffer(signature, status, signature_size,
+                                   *signature_length);
+    }
 
     if (status != PSA_OPERATION_INCOMPLETE) {
         if (status != PSA_SUCCESS) {
@@ -3213,6 +3595,8 @@
         psa_sign_hash_abort_internal(operation);
     }
 
+    LOCAL_OUTPUT_FREE(signature_external, signature);
+
     return status;
 }
 
@@ -3259,13 +3643,16 @@
 psa_status_t psa_verify_hash_start(
     psa_verify_hash_interruptible_operation_t *operation,
     mbedtls_svc_key_id_t key, psa_algorithm_t alg,
-    const uint8_t *hash, size_t hash_length,
-    const uint8_t *signature, size_t signature_length)
+    const uint8_t *hash_external, size_t hash_length,
+    const uint8_t *signature_external, size_t signature_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
 
+    LOCAL_INPUT_DECLARE(hash_external, hash);
+    LOCAL_INPUT_DECLARE(signature_external, signature);
+
     /* Check that start has not been previously called, or operation has not
      * previously errored. */
     if (operation->id != 0 || operation->error_occurred) {
@@ -3287,6 +3674,9 @@
         return status;
     }
 
+    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
+    LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);
+
     /* Ensure ops count gets reset, in case of operation re-use. */
     operation->num_ops = 0;
 
@@ -3295,6 +3685,9 @@
                                                   slot->key.bytes,
                                                   alg, hash, hash_length,
                                                   signature, signature_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
 
     if (status != PSA_SUCCESS) {
         operation->error_occurred = 1;
@@ -3307,6 +3700,9 @@
         operation->error_occurred = 1;
     }
 
+    LOCAL_INPUT_FREE(hash_external, hash);
+    LOCAL_INPUT_FREE(signature_external, signature);
+
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
 
@@ -3804,6 +4200,52 @@
         * defined( MBEDTLS_ECP_RESTARTABLE ) */
 }
 
+static psa_status_t psa_generate_random_internal(uint8_t *output,
+                                                 size_t output_size)
+{
+    GUARD_MODULE_INITIALIZED;
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+
+    psa_status_t status;
+    size_t output_length = 0;
+    status = mbedtls_psa_external_get_random(&global_data.rng,
+                                             output, output_size,
+                                             &output_length);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    /* Breaking up a request into smaller chunks is currently not supported
+     * for the external RNG interface. */
+    if (output_length != output_size) {
+        return PSA_ERROR_INSUFFICIENT_ENTROPY;
+    }
+    return PSA_SUCCESS;
+
+#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+    while (output_size > 0) {
+        int ret = MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
+        size_t request_size =
+            (output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ?
+             MBEDTLS_PSA_RANDOM_MAX_REQUEST :
+             output_size);
+#if defined(MBEDTLS_CTR_DRBG_C)
+        ret = mbedtls_ctr_drbg_random(&global_data.rng.drbg, output, request_size);
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+        ret = mbedtls_hmac_drbg_random(&global_data.rng.drbg, output, request_size);
+#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */
+        if (ret != 0) {
+            return mbedtls_to_psa_error(ret);
+        }
+        output_size -= request_size;
+        output += request_size;
+    }
+    return PSA_SUCCESS;
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+}
+
+
 /****************************************************************/
 /* Symmetric cryptography */
 /****************************************************************/
@@ -3888,14 +4330,15 @@
 }
 
 psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation,
-                                    uint8_t *iv,
+                                    uint8_t *iv_external,
                                     size_t iv_size,
                                     size_t *iv_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE];
     size_t default_iv_length = 0;
 
+    LOCAL_OUTPUT_DECLARE(iv_external, iv);
+
     if (operation->id == 0) {
         status = PSA_ERROR_BAD_STATE;
         goto exit;
@@ -3917,33 +4360,40 @@
         goto exit;
     }
 
-    status = psa_generate_random(local_iv, default_iv_length);
+    LOCAL_OUTPUT_ALLOC(iv_external, default_iv_length, iv);
+
+    status = psa_generate_random_internal(iv, default_iv_length);
     if (status != PSA_SUCCESS) {
         goto exit;
     }
 
     status = psa_driver_wrapper_cipher_set_iv(operation,
-                                              local_iv, default_iv_length);
+                                              iv, default_iv_length);
 
 exit:
     if (status == PSA_SUCCESS) {
-        memcpy(iv, local_iv, default_iv_length);
         *iv_length = default_iv_length;
         operation->iv_set = 1;
     } else {
         *iv_length = 0;
         psa_cipher_abort(operation);
+        if (iv != NULL) {
+            mbedtls_platform_zeroize(iv, default_iv_length);
+        }
     }
 
+    LOCAL_OUTPUT_FREE(iv_external, iv);
     return status;
 }
 
 psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
-                               const uint8_t *iv,
+                               const uint8_t *iv_external,
                                size_t iv_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
+    LOCAL_INPUT_DECLARE(iv_external, iv);
+
     if (operation->id == 0) {
         status = PSA_ERROR_BAD_STATE;
         goto exit;
@@ -3959,6 +4409,8 @@
         goto exit;
     }
 
+    LOCAL_INPUT_ALLOC(iv_external, iv_length, iv);
+
     status = psa_driver_wrapper_cipher_set_iv(operation,
                                               iv,
                                               iv_length);
@@ -3969,18 +4421,24 @@
     } else {
         psa_cipher_abort(operation);
     }
+
+    LOCAL_INPUT_FREE(iv_external, iv);
+
     return status;
 }
 
 psa_status_t psa_cipher_update(psa_cipher_operation_t *operation,
-                               const uint8_t *input,
+                               const uint8_t *input_external,
                                size_t input_length,
-                               uint8_t *output,
+                               uint8_t *output_external,
                                size_t output_size,
                                size_t *output_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
     if (operation->id == 0) {
         status = PSA_ERROR_BAD_STATE;
         goto exit;
@@ -3991,6 +4449,9 @@
         goto exit;
     }
 
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
     status = psa_driver_wrapper_cipher_update(operation,
                                               input,
                                               input_length,
@@ -4003,16 +4464,21 @@
         psa_cipher_abort(operation);
     }
 
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(output_external, output);
+
     return status;
 }
 
 psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,
-                               uint8_t *output,
+                               uint8_t *output_external,
                                size_t output_size,
                                size_t *output_length)
 {
     psa_status_t status = PSA_ERROR_GENERIC_ERROR;
 
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
     if (operation->id == 0) {
         status = PSA_ERROR_BAD_STATE;
         goto exit;
@@ -4023,6 +4489,8 @@
         goto exit;
     }
 
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
     status = psa_driver_wrapper_cipher_finish(operation,
                                               output,
                                               output_size,
@@ -4030,13 +4498,15 @@
 
 exit:
     if (status == PSA_SUCCESS) {
-        return psa_cipher_abort(operation);
+        status = psa_cipher_abort(operation);
     } else {
         *output_length = 0;
         (void) psa_cipher_abort(operation);
-
-        return status;
     }
+
+    LOCAL_OUTPUT_FREE(output_external, output);
+
+    return status;
 }
 
 psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation)
@@ -4059,9 +4529,9 @@
 
 psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key,
                                 psa_algorithm_t alg,
-                                const uint8_t *input,
+                                const uint8_t *input_external,
                                 size_t input_length,
-                                uint8_t *output,
+                                uint8_t *output_external,
                                 size_t output_size,
                                 size_t *output_length)
 {
@@ -4071,6 +4541,9 @@
     uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE];
     size_t default_iv_length = 0;
 
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
     if (!PSA_ALG_IS_CIPHER(alg)) {
         status = PSA_ERROR_INVALID_ARGUMENT;
         goto exit;
@@ -4095,12 +4568,15 @@
             goto exit;
         }
 
-        status = psa_generate_random(local_iv, default_iv_length);
+        status = psa_generate_random_internal(local_iv, default_iv_length);
         if (status != PSA_SUCCESS) {
             goto exit;
         }
     }
 
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
     status = psa_driver_wrapper_cipher_encrypt(
         &slot->attr, slot->key.data, slot->key.bytes,
         alg, local_iv, default_iv_length, input, input_length,
@@ -4122,14 +4598,17 @@
         *output_length = 0;
     }
 
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(output_external, output);
+
     return status;
 }
 
 psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key,
                                 psa_algorithm_t alg,
-                                const uint8_t *input,
+                                const uint8_t *input_external,
                                 size_t input_length,
-                                uint8_t *output,
+                                uint8_t *output_external,
                                 size_t output_size,
                                 size_t *output_length)
 {
@@ -4137,6 +4616,9 @@
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot = NULL;
 
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
     if (!PSA_ALG_IS_CIPHER(alg)) {
         status = PSA_ERROR_INVALID_ARGUMENT;
         goto exit;
@@ -4158,6 +4640,9 @@
         goto exit;
     }
 
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
     status = psa_driver_wrapper_cipher_decrypt(
         &slot->attr, slot->key.data, slot->key.bytes,
         alg, input, input_length,
@@ -4173,6 +4658,9 @@
         *output_length = 0;
     }
 
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(output_external, output);
+
     return status;
 }
 
@@ -4242,19 +4730,24 @@
 
 psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key,
                               psa_algorithm_t alg,
-                              const uint8_t *nonce,
+                              const uint8_t *nonce_external,
                               size_t nonce_length,
-                              const uint8_t *additional_data,
+                              const uint8_t *additional_data_external,
                               size_t additional_data_length,
-                              const uint8_t *plaintext,
+                              const uint8_t *plaintext_external,
                               size_t plaintext_length,
-                              uint8_t *ciphertext,
+                              uint8_t *ciphertext_external,
                               size_t ciphertext_size,
                               size_t *ciphertext_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
 
+    LOCAL_INPUT_DECLARE(nonce_external, nonce);
+    LOCAL_INPUT_DECLARE(additional_data_external, additional_data);
+    LOCAL_INPUT_DECLARE(plaintext_external, plaintext);
+    LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext);
+
     *ciphertext_length = 0;
 
     status = psa_aead_check_algorithm(alg);
@@ -4268,6 +4761,11 @@
         return status;
     }
 
+    LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);
+    LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, additional_data);
+    LOCAL_INPUT_ALLOC(plaintext_external, plaintext_length, plaintext);
+    LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext);
+
     status = psa_aead_check_nonce_length(alg, nonce_length);
     if (status != PSA_SUCCESS) {
         goto exit;
@@ -4286,6 +4784,11 @@
     }
 
 exit:
+    LOCAL_INPUT_FREE(nonce_external, nonce);
+    LOCAL_INPUT_FREE(additional_data_external, additional_data);
+    LOCAL_INPUT_FREE(plaintext_external, plaintext);
+    LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext);
+
     psa_unregister_read_under_mutex(slot);
 
     return status;
@@ -4293,19 +4796,24 @@
 
 psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key,
                               psa_algorithm_t alg,
-                              const uint8_t *nonce,
+                              const uint8_t *nonce_external,
                               size_t nonce_length,
-                              const uint8_t *additional_data,
+                              const uint8_t *additional_data_external,
                               size_t additional_data_length,
-                              const uint8_t *ciphertext,
+                              const uint8_t *ciphertext_external,
                               size_t ciphertext_length,
-                              uint8_t *plaintext,
+                              uint8_t *plaintext_external,
                               size_t plaintext_size,
                               size_t *plaintext_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
 
+    LOCAL_INPUT_DECLARE(nonce_external, nonce);
+    LOCAL_INPUT_DECLARE(additional_data_external, additional_data);
+    LOCAL_INPUT_DECLARE(ciphertext_external, ciphertext);
+    LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext);
+
     *plaintext_length = 0;
 
     status = psa_aead_check_algorithm(alg);
@@ -4319,6 +4827,12 @@
         return status;
     }
 
+    LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);
+    LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length,
+                      additional_data);
+    LOCAL_INPUT_ALLOC(ciphertext_external, ciphertext_length, ciphertext);
+    LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext);
+
     status = psa_aead_check_nonce_length(alg, nonce_length);
     if (status != PSA_SUCCESS) {
         goto exit;
@@ -4337,6 +4851,11 @@
     }
 
 exit:
+    LOCAL_INPUT_FREE(nonce_external, nonce);
+    LOCAL_INPUT_FREE(additional_data_external, additional_data);
+    LOCAL_INPUT_FREE(ciphertext_external, ciphertext);
+    LOCAL_OUTPUT_FREE(plaintext_external, plaintext);
+
     psa_unregister_read_under_mutex(slot);
 
     return status;
@@ -4473,9 +4992,44 @@
     return psa_aead_setup(operation, 0, key, alg);
 }
 
+static psa_status_t psa_aead_set_nonce_internal(psa_aead_operation_t *operation,
+                                                const uint8_t *nonce,
+                                                size_t nonce_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (operation->nonce_set) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    status = psa_aead_check_nonce_length(operation->alg, nonce_length);
+    if (status != PSA_SUCCESS) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_aead_set_nonce(operation, nonce,
+                                               nonce_length);
+
+exit:
+    if (status == PSA_SUCCESS) {
+        operation->nonce_set = 1;
+    } else {
+        psa_aead_abort(operation);
+    }
+
+    return status;
+}
+
 /* Generate a random nonce / IV for multipart AEAD operation */
 psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation,
-                                     uint8_t *nonce,
+                                     uint8_t *nonce_external,
                                      size_t nonce_size,
                                      size_t *nonce_length)
 {
@@ -4483,6 +5037,9 @@
     uint8_t local_nonce[PSA_AEAD_NONCE_MAX_SIZE];
     size_t required_nonce_size = 0;
 
+    LOCAL_OUTPUT_DECLARE(nonce_external, nonce);
+    LOCAL_OUTPUT_ALLOC(nonce_external, nonce_size, nonce);
+
     *nonce_length = 0;
 
     if (operation->id == 0) {
@@ -4511,12 +5068,13 @@
         goto exit;
     }
 
-    status = psa_generate_random(local_nonce, required_nonce_size);
+    status = psa_generate_random_internal(local_nonce, required_nonce_size);
     if (status != PSA_SUCCESS) {
         goto exit;
     }
 
-    status = psa_aead_set_nonce(operation, local_nonce, required_nonce_size);
+    status = psa_aead_set_nonce_internal(operation, local_nonce,
+                                         required_nonce_size);
 
 exit:
     if (status == PSA_SUCCESS) {
@@ -4526,42 +5084,30 @@
         psa_aead_abort(operation);
     }
 
+    LOCAL_OUTPUT_FREE(nonce_external, nonce);
+
     return status;
 }
 
 /* Set the nonce for a multipart authenticated encryption or decryption
    operation.*/
 psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation,
-                                const uint8_t *nonce,
+                                const uint8_t *nonce_external,
                                 size_t nonce_length)
 {
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t status;
 
-    if (operation->id == 0) {
-        status = PSA_ERROR_BAD_STATE;
-        goto exit;
-    }
+    LOCAL_INPUT_DECLARE(nonce_external, nonce);
+    LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);
 
-    if (operation->nonce_set) {
-        status = PSA_ERROR_BAD_STATE;
-        goto exit;
-    }
+    status = psa_aead_set_nonce_internal(operation, nonce, nonce_length);
 
-    status = psa_aead_check_nonce_length(operation->alg, nonce_length);
-    if (status != PSA_SUCCESS) {
-        status = PSA_ERROR_INVALID_ARGUMENT;
-        goto exit;
-    }
-
-    status = psa_driver_wrapper_aead_set_nonce(operation, nonce,
-                                               nonce_length);
-
+/* Exit label is only needed for buffer copying, prevent unused warnings. */
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
 exit:
-    if (status == PSA_SUCCESS) {
-        operation->nonce_set = 1;
-    } else {
-        psa_aead_abort(operation);
-    }
+#endif
+
+    LOCAL_INPUT_FREE(nonce_external, nonce);
 
     return status;
 }
@@ -4633,11 +5179,14 @@
 
 /* Pass additional data to an active multipart AEAD operation. */
 psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation,
-                                const uint8_t *input,
+                                const uint8_t *input_external,
                                 size_t input_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+
     if (operation->id == 0) {
         status = PSA_ERROR_BAD_STATE;
         goto exit;
@@ -4648,6 +5197,12 @@
         goto exit;
     }
 
+    /* No input to add (zero length), nothing to do. */
+    if (input_length == 0) {
+        status = PSA_SUCCESS;
+        goto exit;
+    }
+
     if (operation->lengths_set) {
         if (operation->ad_remaining < input_length) {
             status = PSA_ERROR_INVALID_ARGUMENT;
@@ -4673,20 +5228,29 @@
         psa_aead_abort(operation);
     }
 
+    LOCAL_INPUT_FREE(input_external, input);
+
     return status;
 }
 
 /* Encrypt or decrypt a message fragment in an active multipart AEAD
    operation.*/
 psa_status_t psa_aead_update(psa_aead_operation_t *operation,
-                             const uint8_t *input,
+                             const uint8_t *input_external,
                              size_t input_length,
-                             uint8_t *output,
+                             uint8_t *output_external,
                              size_t output_size,
                              size_t *output_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
+
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
     *output_length = 0;
 
     if (operation->id == 0) {
@@ -4733,6 +5297,9 @@
         psa_aead_abort(operation);
     }
 
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(output_external, output);
+
     return status;
 }
 
@@ -4752,15 +5319,21 @@
 
 /* Finish encrypting a message in a multipart AEAD operation. */
 psa_status_t psa_aead_finish(psa_aead_operation_t *operation,
-                             uint8_t *ciphertext,
+                             uint8_t *ciphertext_external,
                              size_t ciphertext_size,
                              size_t *ciphertext_length,
-                             uint8_t *tag,
+                             uint8_t *tag_external,
                              size_t tag_size,
                              size_t *tag_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
+    LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext);
+    LOCAL_OUTPUT_DECLARE(tag_external, tag);
+
+    LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext);
+    LOCAL_OUTPUT_ALLOC(tag_external, tag_size, tag);
+
     *ciphertext_length = 0;
     *tag_length = tag_size;
 
@@ -4791,20 +5364,29 @@
 
     psa_aead_abort(operation);
 
+    LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext);
+    LOCAL_OUTPUT_FREE(tag_external, tag);
+
     return status;
 }
 
 /* Finish authenticating and decrypting a message in a multipart AEAD
    operation.*/
 psa_status_t psa_aead_verify(psa_aead_operation_t *operation,
-                             uint8_t *plaintext,
+                             uint8_t *plaintext_external,
                              size_t plaintext_size,
                              size_t *plaintext_length,
-                             const uint8_t *tag,
+                             const uint8_t *tag_external,
                              size_t tag_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
+    LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext);
+    LOCAL_INPUT_DECLARE(tag_external, tag);
+
+    LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext);
+    LOCAL_INPUT_ALLOC(tag_external, tag_length, tag);
+
     *plaintext_length = 0;
 
     status = psa_aead_final_checks(operation);
@@ -4825,6 +5407,9 @@
 exit:
     psa_aead_abort(operation);
 
+    LOCAL_OUTPUT_FREE(plaintext_external, plaintext);
+    LOCAL_INPUT_FREE(tag_external, tag);
+
     return status;
 }
 
@@ -5431,10 +6016,12 @@
 
 psa_status_t psa_key_derivation_output_bytes(
     psa_key_derivation_operation_t *operation,
-    uint8_t *output,
+    uint8_t *output_external,
     size_t output_length)
 {
     psa_status_t status;
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
     psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);
 
     if (operation->alg == 0) {
@@ -5442,13 +6029,6 @@
         return PSA_ERROR_BAD_STATE;
     }
 
-    if (output_length > operation->capacity) {
-        operation->capacity = 0;
-        /* Go through the error path to wipe all confidential data now
-         * that the operation object is useless. */
-        status = PSA_ERROR_INSUFFICIENT_DATA;
-        goto exit;
-    }
     if (output_length == 0 && operation->capacity == 0) {
         /* Edge case: this is a finished operation, and 0 bytes
          * were requested. The right error in this case could
@@ -5458,6 +6038,16 @@
          * output_length > 0. */
         return PSA_ERROR_INSUFFICIENT_DATA;
     }
+
+    LOCAL_OUTPUT_ALLOC(output_external, output_length, output);
+    if (output_length > operation->capacity) {
+        operation->capacity = 0;
+        /* Go through the error path to wipe all confidential data now
+         * that the operation object is useless. */
+        status = PSA_ERROR_INSUFFICIENT_DATA;
+        goto exit;
+    }
+
     operation->capacity -= output_length;
 
 #if defined(BUILTIN_ALG_ANY_HKDF)
@@ -5491,7 +6081,10 @@
 
     {
         (void) kdf_alg;
-        return PSA_ERROR_BAD_STATE;
+        status = PSA_ERROR_BAD_STATE;
+        LOCAL_OUTPUT_FREE(output_external, output);
+
+        return status;
     }
 
 exit:
@@ -5503,8 +6096,12 @@
         psa_algorithm_t alg = operation->alg;
         psa_key_derivation_abort(operation);
         operation->alg = alg;
-        memset(output, '!', output_length);
+        if (output != NULL) {
+            memset(output, '!', output_length);
+        }
     }
+
+    LOCAL_OUTPUT_FREE(output_external, output);
     return status;
 }
 
@@ -6563,12 +7160,12 @@
 {
     psa_status_t status = PSA_SUCCESS;
     if (input_len > PSA_HASH_BLOCK_LENGTH(hash_alg)) {
-        status = psa_hash_compute(hash_alg, input, input_len, output,
-                                  PSA_HMAC_MAX_HASH_BLOCK_SIZE, output_len);
-    } else {
+        return psa_hash_compute(hash_alg, input, input_len, output,
+                                PSA_HMAC_MAX_HASH_BLOCK_SIZE, output_len);
+    } else if (input_len > 0) {
         memcpy(output, input, input_len);
-        *output_len = PSA_HASH_BLOCK_LENGTH(hash_alg);
     }
+    *output_len = PSA_HASH_BLOCK_LENGTH(hash_alg);
     return status;
 }
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
@@ -6802,12 +7399,22 @@
 psa_status_t psa_key_derivation_input_bytes(
     psa_key_derivation_operation_t *operation,
     psa_key_derivation_step_t step,
-    const uint8_t *data,
+    const uint8_t *data_external,
     size_t data_length)
 {
-    return psa_key_derivation_input_internal(operation, step,
-                                             PSA_KEY_TYPE_NONE,
-                                             data, data_length);
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(data_external, data);
+
+    LOCAL_INPUT_ALLOC(data_external, data_length, data);
+
+    status = psa_key_derivation_input_internal(operation, step,
+                                               PSA_KEY_TYPE_NONE,
+                                               data, data_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(data_external, data);
+    return status;
 }
 
 psa_status_t psa_key_derivation_input_integer(
@@ -6940,7 +7547,7 @@
                                                size_t peer_key_length)
 {
     psa_status_t status;
-    uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE];
+    uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE] = { 0 };
     size_t shared_secret_length = 0;
     psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(operation->alg);
 
@@ -6971,12 +7578,13 @@
 psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *operation,
                                               psa_key_derivation_step_t step,
                                               mbedtls_svc_key_id_t private_key,
-                                              const uint8_t *peer_key,
+                                              const uint8_t *peer_key_external,
                                               size_t peer_key_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
+    LOCAL_INPUT_DECLARE(peer_key_external, peer_key);
 
     if (!PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) {
         return PSA_ERROR_INVALID_ARGUMENT;
@@ -6986,9 +7594,15 @@
     if (status != PSA_SUCCESS) {
         return status;
     }
+
+    LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key);
     status = psa_key_agreement_internal(operation, step,
                                         slot,
                                         peer_key, peer_key_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
     if (status != PSA_SUCCESS) {
         psa_key_derivation_abort(operation);
     } else {
@@ -7000,15 +7614,16 @@
     }
 
     unlock_status = psa_unregister_read_under_mutex(slot);
+    LOCAL_INPUT_FREE(peer_key_external, peer_key);
 
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
 
 psa_status_t psa_raw_key_agreement(psa_algorithm_t alg,
                                    mbedtls_svc_key_id_t private_key,
-                                   const uint8_t *peer_key,
+                                   const uint8_t *peer_key_external,
                                    size_t peer_key_length,
-                                   uint8_t *output,
+                                   uint8_t *output_external,
                                    size_t output_size,
                                    size_t *output_length)
 {
@@ -7016,6 +7631,9 @@
     psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot = NULL;
     size_t expected_length;
+    LOCAL_INPUT_DECLARE(peer_key_external, peer_key);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
 
     if (!PSA_ALG_IS_KEY_AGREEMENT(alg)) {
         status = PSA_ERROR_INVALID_ARGUMENT;
@@ -7042,13 +7660,16 @@
         goto exit;
     }
 
+    LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key);
     status = psa_key_agreement_raw_internal(alg, slot,
                                             peer_key, peer_key_length,
                                             output, output_size,
                                             output_length);
 
 exit:
-    if (status != PSA_SUCCESS) {
+    /* Check for successful allocation of output,
+     * with an unsuccessful status. */
+    if (output != NULL && status != PSA_SUCCESS) {
         /* If an error happens and is not handled properly, the output
          * may be used as a key to protect sensitive data. Arrange for such
          * a key to be random, which is likely to result in decryption or
@@ -7056,17 +7677,23 @@
          * some constant data such as zeros, which would result in the data
          * being protected with a reproducible, easily knowable key.
          */
-        psa_generate_random(output, output_size);
+        psa_generate_random_internal(output, output_size);
         *output_length = output_size;
     }
 
+    if (output == NULL) {
+        /* output allocation failed. */
+        *output_length = 0;
+    }
+
     unlock_status = psa_unregister_read_under_mutex(slot);
 
+    LOCAL_INPUT_FREE(peer_key_external, peer_key);
+    LOCAL_OUTPUT_FREE(output_external, output);
     return (status == PSA_SUCCESS) ? unlock_status : status;
 }
 
 
-
 /****************************************************************/
 /* Random generation */
 /****************************************************************/
@@ -7076,6 +7703,9 @@
 #endif
 
 /** Initialize the PSA random generator.
+ *
+ *  Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling
+ *  this function if mutexes are enabled.
  */
 static void mbedtls_psa_random_init(mbedtls_psa_random_context_t *rng)
 {
@@ -7103,18 +7733,21 @@
                                MBEDTLS_ENTROPY_SOURCE_STRONG);
 #endif
 
-    mbedtls_psa_drbg_init(MBEDTLS_PSA_RANDOM_STATE);
+    mbedtls_psa_drbg_init(&rng->drbg);
 #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 }
 
 /** Deinitialize the PSA random generator.
+ *
+ *  Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling
+ *  this function if mutexes are enabled.
  */
 static void mbedtls_psa_random_free(mbedtls_psa_random_context_t *rng)
 {
 #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
     memset(rng, 0, sizeof(*rng));
 #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
-    mbedtls_psa_drbg_free(MBEDTLS_PSA_RANDOM_STATE);
+    mbedtls_psa_drbg_free(&rng->drbg);
     rng->entropy_free(&rng->entropy);
 #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 }
@@ -7129,90 +7762,34 @@
     return PSA_SUCCESS;
 #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
     const unsigned char drbg_seed[] = "PSA";
-    int ret = mbedtls_psa_drbg_seed(&rng->entropy,
+    int ret = mbedtls_psa_drbg_seed(&rng->drbg, &rng->entropy,
                                     drbg_seed, sizeof(drbg_seed) - 1);
     return mbedtls_to_psa_error(ret);
 #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 }
 
-psa_status_t psa_generate_random(uint8_t *output,
+psa_status_t psa_generate_random(uint8_t *output_external,
                                  size_t output_size)
 {
-    GUARD_MODULE_INITIALIZED;
+    psa_status_t status;
 
-#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
 
-    size_t output_length = 0;
-    psa_status_t status = mbedtls_psa_external_get_random(&global_data.rng,
-                                                          output, output_size,
-                                                          &output_length);
-    if (status != PSA_SUCCESS) {
-        return status;
-    }
-    /* Breaking up a request into smaller chunks is currently not supported
-     * for the external RNG interface. */
-    if (output_length != output_size) {
-        return PSA_ERROR_INSUFFICIENT_ENTROPY;
-    }
-    return PSA_SUCCESS;
+    status = psa_generate_random_internal(output, output_size);
 
-#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
-
-    while (output_size > 0) {
-        size_t request_size =
-            (output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ?
-             MBEDTLS_PSA_RANDOM_MAX_REQUEST :
-             output_size);
-        int ret = mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE,
-                                         output, request_size);
-        if (ret != 0) {
-            return mbedtls_to_psa_error(ret);
-        }
-        output_size -= request_size;
-        output += request_size;
-    }
-    return PSA_SUCCESS;
-#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_OUTPUT_FREE(output_external, output);
+    return status;
 }
 
-/* Wrapper function allowing the classic API to use the PSA RNG.
- *
- * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls
- * `psa_generate_random(...)`. The state parameter is ignored since the
- * PSA API doesn't support passing an explicit state.
- *
- * In the non-external case, psa_generate_random() calls an
- * `mbedtls_xxx_drbg_random` function which has exactly the same signature
- * and semantics as mbedtls_psa_get_random(). As an optimization,
- * instead of doing this back-and-forth between the PSA API and the
- * classic API, psa_crypto_random_impl.h defines `mbedtls_psa_get_random`
- * as a constant function pointer to `mbedtls_xxx_drbg_random`.
- */
-#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
-int mbedtls_psa_get_random(void *p_rng,
-                           unsigned char *output,
-                           size_t output_size)
-{
-    /* This function takes a pointer to the RNG state because that's what
-     * classic mbedtls functions using an RNG expect. The PSA RNG manages
-     * its own state internally and doesn't let the caller access that state.
-     * So we just ignore the state parameter, and in practice we'll pass
-     * NULL. */
-    (void) p_rng;
-    psa_status_t status = psa_generate_random(output, output_size);
-    if (status == PSA_SUCCESS) {
-        return 0;
-    } else {
-        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
-    }
-}
-#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
-
 #if defined(MBEDTLS_PSA_INJECT_ENTROPY)
 psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed,
                                         size_t seed_size)
 {
-    if (global_data.initialized) {
+    if (psa_get_initialized()) {
         return PSA_ERROR_NOT_PERMITTED;
     }
 
@@ -7301,7 +7878,7 @@
     (void) params_data_length;
 
     if (key_type_is_raw_bytes(type)) {
-        status = psa_generate_random(key_buffer, key_buffer_size);
+        status = psa_generate_random_internal(key_buffer, key_buffer_size);
         if (status != PSA_SUCCESS) {
             return status;
         }
@@ -7454,28 +8031,77 @@
     void (* entropy_init)(mbedtls_entropy_context *ctx),
     void (* entropy_free)(mbedtls_entropy_context *ctx))
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
     if (global_data.rng_state != RNG_NOT_INITIALIZED) {
-        return PSA_ERROR_BAD_STATE;
+        status = PSA_ERROR_BAD_STATE;
+    } else {
+        global_data.rng.entropy_init = entropy_init;
+        global_data.rng.entropy_free = entropy_free;
+        status = PSA_SUCCESS;
     }
-    global_data.rng.entropy_init = entropy_init;
-    global_data.rng.entropy_free = entropy_free;
-    return PSA_SUCCESS;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    return status;
 }
 #endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
 
 void mbedtls_psa_crypto_free(void)
 {
-    psa_wipe_all_key_slots();
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    /* Nothing to do to free transaction. */
+    if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) {
+        global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
+    }
+
+    if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED) {
+        psa_wipe_all_key_slots();
+        global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
     if (global_data.rng_state != RNG_NOT_INITIALIZED) {
         mbedtls_psa_random_free(&global_data.rng);
     }
-    /* Wipe all remaining data, including configuration.
-     * In particular, this sets all state indicator to the value
-     * indicating "uninitialized". */
-    mbedtls_platform_zeroize(&global_data, sizeof(global_data));
+    global_data.rng_state = RNG_NOT_INITIALIZED;
+    mbedtls_platform_zeroize(&global_data.rng, sizeof(global_data.rng));
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
 
     /* Terminate drivers */
-    psa_driver_wrapper_free();
+    if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) {
+        psa_driver_wrapper_free();
+        global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
 }
 
 #if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
@@ -7503,57 +8129,171 @@
 }
 #endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
 
+static psa_status_t mbedtls_psa_crypto_init_subsystem(mbedtls_psa_crypto_subsystem subsystem)
+{
+    psa_status_t status = PSA_SUCCESS;
+    uint8_t driver_wrappers_initialized = 0;
+
+    switch (subsystem) {
+        case PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS:
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED)) {
+                /* Init drivers */
+                status = psa_driver_wrapper_init();
+
+                /* Drivers need shutdown regardless of startup errors. */
+                global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED;
+
+
+            }
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
+                                            &mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            break;
+
+        case PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS:
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED)) {
+                status = psa_initialize_key_slots();
+
+                /* Need to wipe keys even if initialization fails. */
+                global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED;
+
+            }
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
+                                            &mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            break;
+
+        case PSA_CRYPTO_SUBSYSTEM_RNG:
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            driver_wrappers_initialized =
+                (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED);
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
+                                            &mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            /* Need to use separate mutex here, as initialisation can require
+             * testing of init flags, which requires locking the global data
+             * mutex. */
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            /* Initialize and seed the random generator. */
+            if (global_data.rng_state == RNG_NOT_INITIALIZED && driver_wrappers_initialized) {
+                mbedtls_psa_random_init(&global_data.rng);
+                global_data.rng_state = RNG_INITIALIZED;
+
+                status = mbedtls_psa_random_seed(&global_data.rng);
+                if (status == PSA_SUCCESS) {
+                    global_data.rng_state = RNG_SEEDED;
+                }
+            }
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
+                                            &mbedtls_threading_psa_rngdata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            break;
+
+        case PSA_CRYPTO_SUBSYSTEM_TRANSACTION:
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)) {
+#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
+                status = psa_crypto_load_transaction();
+                if (status == PSA_SUCCESS) {
+                    status = psa_crypto_recover_transaction(&psa_crypto_transaction);
+                    if (status == PSA_SUCCESS) {
+                        global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
+                    }
+                    status = psa_crypto_stop_transaction();
+                } else if (status == PSA_ERROR_DOES_NOT_EXIST) {
+                    /* There's no transaction to complete. It's all good. */
+                    global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
+                    status = PSA_SUCCESS;
+                }
+#else /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */
+                global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
+                status = PSA_SUCCESS;
+#endif /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */
+            }
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
+                                            &mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            break;
+
+        default:
+            status = PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    /* Exit label only required when using threading macros. */
+#if defined(MBEDTLS_THREADING_C)
+exit:
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    return status;
+}
+
 psa_status_t psa_crypto_init(void)
 {
     psa_status_t status;
 
-    /* Double initialization is explicitly allowed. */
-    if (global_data.initialized != 0) {
+    /* Double initialization is explicitly allowed. Early out if everything is
+     * done. */
+    if (psa_get_initialized()) {
         return PSA_SUCCESS;
     }
 
-    /* Init drivers */
-    status = psa_driver_wrapper_init();
-    if (status != PSA_SUCCESS) {
-        goto exit;
-    }
-    global_data.drivers_initialized = 1;
-
-    status = psa_initialize_key_slots();
+    status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS);
     if (status != PSA_SUCCESS) {
         goto exit;
     }
 
-    /* Initialize and seed the random generator. */
-    mbedtls_psa_random_init(&global_data.rng);
-    global_data.rng_state = RNG_INITIALIZED;
-    status = mbedtls_psa_random_seed(&global_data.rng);
+    status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS);
     if (status != PSA_SUCCESS) {
         goto exit;
     }
-    global_data.rng_state = RNG_SEEDED;
 
-#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
-    status = psa_crypto_load_transaction();
-    if (status == PSA_SUCCESS) {
-        status = psa_crypto_recover_transaction(&psa_crypto_transaction);
-        if (status != PSA_SUCCESS) {
-            goto exit;
-        }
-        status = psa_crypto_stop_transaction();
-    } else if (status == PSA_ERROR_DOES_NOT_EXIST) {
-        /* There's no transaction to complete. It's all good. */
-        status = PSA_SUCCESS;
+    status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_RNG);
+    if (status != PSA_SUCCESS) {
+        goto exit;
     }
-#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
 
-    /* All done. */
-    global_data.initialized = 1;
+    status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_TRANSACTION);
 
 exit:
+
     if (status != PSA_SUCCESS) {
         mbedtls_psa_crypto_free();
     }
+
     return status;
 }
 
@@ -7759,10 +8499,11 @@
 
 psa_status_t psa_pake_set_user(
     psa_pake_operation_t *operation,
-    const uint8_t *user_id,
+    const uint8_t *user_id_external,
     size_t user_id_len)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(user_id_external, user_id);
 
     if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
         status = PSA_ERROR_BAD_STATE;
@@ -7785,21 +8526,28 @@
         goto exit;
     }
 
+    LOCAL_INPUT_ALLOC(user_id_external, user_id_len, user_id);
+
     memcpy(operation->data.inputs.user, user_id, user_id_len);
     operation->data.inputs.user_len = user_id_len;
 
-    return PSA_SUCCESS;
+    status = PSA_SUCCESS;
+
 exit:
-    psa_pake_abort(operation);
+    LOCAL_INPUT_FREE(user_id_external, user_id);
+    if (status != PSA_SUCCESS) {
+        psa_pake_abort(operation);
+    }
     return status;
 }
 
 psa_status_t psa_pake_set_peer(
     psa_pake_operation_t *operation,
-    const uint8_t *peer_id,
+    const uint8_t *peer_id_external,
     size_t peer_id_len)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(peer_id_external, peer_id);
 
     if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
         status = PSA_ERROR_BAD_STATE;
@@ -7822,12 +8570,18 @@
         goto exit;
     }
 
+    LOCAL_INPUT_ALLOC(peer_id_external, peer_id_len, peer_id);
+
     memcpy(operation->data.inputs.peer, peer_id, peer_id_len);
     operation->data.inputs.peer_len = peer_id_len;
 
-    return PSA_SUCCESS;
+    status = PSA_SUCCESS;
+
 exit:
-    psa_pake_abort(operation);
+    LOCAL_INPUT_FREE(peer_id_external, peer_id);
+    if (status != PSA_SUCCESS) {
+        psa_pake_abort(operation);
+    }
     return status;
 }
 
@@ -8013,12 +8767,13 @@
 psa_status_t psa_pake_output(
     psa_pake_operation_t *operation,
     psa_pake_step_t step,
-    uint8_t *output,
+    uint8_t *output_external,
     size_t output_size,
     size_t *output_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID;
+    LOCAL_OUTPUT_DECLARE(output_external, output);
     *output_length = 0;
 
     if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
@@ -8055,6 +8810,8 @@
             goto exit;
     }
 
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
     status = psa_driver_wrapper_pake_output(operation, driver_step,
                                             output, output_size, output_length);
 
@@ -8076,16 +8833,18 @@
             goto exit;
     }
 
-    return PSA_SUCCESS;
 exit:
-    psa_pake_abort(operation);
+    LOCAL_OUTPUT_FREE(output_external, output);
+    if (status != PSA_SUCCESS) {
+        psa_pake_abort(operation);
+    }
     return status;
 }
 
 psa_status_t psa_pake_input(
     psa_pake_operation_t *operation,
     psa_pake_step_t step,
-    const uint8_t *input,
+    const uint8_t *input_external,
     size_t input_length)
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
@@ -8093,6 +8852,7 @@
     const size_t max_input_length = (size_t) PSA_PAKE_INPUT_SIZE(operation->alg,
                                                                  operation->primitive,
                                                                  step);
+    LOCAL_INPUT_DECLARE(input_external, input);
 
     if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
         status = psa_pake_complete_inputs(operation);
@@ -8128,6 +8888,7 @@
             goto exit;
     }
 
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
     status = psa_driver_wrapper_pake_input(operation, driver_step,
                                            input, input_length);
 
@@ -8149,9 +8910,11 @@
             goto exit;
     }
 
-    return PSA_SUCCESS;
 exit:
-    psa_pake_abort(operation);
+    LOCAL_INPUT_FREE(input_external, input);
+    if (status != PSA_SUCCESS) {
+        psa_pake_abort(operation);
+    }
     return status;
 }
 
@@ -8231,4 +8994,182 @@
 }
 #endif /* PSA_WANT_ALG_SOME_PAKE */
 
+/* Memory copying test hooks. These are called before input copy, after input
+ * copy, before output copy and after output copy, respectively.
+ * They are used by memory-poisoning tests to temporarily unpoison buffers
+ * while they are copied. */
+#if defined(MBEDTLS_TEST_HOOKS)
+void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len) = NULL;
+void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len) = NULL;
+void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len) = NULL;
+void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len) = NULL;
+#endif
+
+/** Copy from an input buffer to a local copy.
+ *
+ * \param[in] input             Pointer to input buffer.
+ * \param[in] input_len         Length of the input buffer.
+ * \param[out] input_copy       Pointer to a local copy in which to store the input data.
+ * \param[out] input_copy_len   Length of the local copy buffer.
+ * \return                      #PSA_SUCCESS, if the buffer was successfully
+ *                              copied.
+ * \return                      #PSA_ERROR_CORRUPTION_DETECTED, if the local
+ *                              copy is too small to hold contents of the
+ *                              input buffer.
+ */
+MBEDTLS_STATIC_TESTABLE
+psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len,
+                                   uint8_t *input_copy, size_t input_copy_len)
+{
+    if (input_len > input_copy_len) {
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+#if defined(MBEDTLS_TEST_HOOKS)
+    if (psa_input_pre_copy_hook != NULL) {
+        psa_input_pre_copy_hook(input, input_len);
+    }
+#endif
+
+    if (input_len > 0) {
+        memcpy(input_copy, input, input_len);
+    }
+
+#if defined(MBEDTLS_TEST_HOOKS)
+    if (psa_input_post_copy_hook != NULL) {
+        psa_input_post_copy_hook(input, input_len);
+    }
+#endif
+
+    return PSA_SUCCESS;
+}
+
+/** Copy from a local output buffer into a user-supplied one.
+ *
+ * \param[in] output_copy       Pointer to a local buffer containing the output.
+ * \param[in] output_copy_len   Length of the local buffer.
+ * \param[out] output           Pointer to user-supplied output buffer.
+ * \param[out] output_len       Length of the user-supplied output buffer.
+ * \return                      #PSA_SUCCESS, if the buffer was successfully
+ *                              copied.
+ * \return                      #PSA_ERROR_BUFFER_TOO_SMALL, if the
+ *                              user-supplied output buffer is too small to
+ *                              hold the contents of the local buffer.
+ */
+MBEDTLS_STATIC_TESTABLE
+psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len,
+                                    uint8_t *output, size_t output_len)
+{
+    if (output_len < output_copy_len) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+#if defined(MBEDTLS_TEST_HOOKS)
+    if (psa_output_pre_copy_hook != NULL) {
+        psa_output_pre_copy_hook(output, output_len);
+    }
+#endif
+
+    if (output_copy_len > 0) {
+        memcpy(output, output_copy, output_copy_len);
+    }
+
+#if defined(MBEDTLS_TEST_HOOKS)
+    if (psa_output_post_copy_hook != NULL) {
+        psa_output_post_copy_hook(output, output_len);
+    }
+#endif
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len,
+                                          psa_crypto_local_input_t *local_input)
+{
+    psa_status_t status;
+
+    *local_input = PSA_CRYPTO_LOCAL_INPUT_INIT;
+
+    if (input_len == 0) {
+        return PSA_SUCCESS;
+    }
+
+    local_input->buffer = mbedtls_calloc(input_len, 1);
+    if (local_input->buffer == NULL) {
+        /* Since we dealt with the zero-length case above, we know that
+         * a NULL return value means a failure of allocation. */
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+    /* From now on, we must free local_input->buffer on error. */
+
+    local_input->length = input_len;
+
+    status = psa_crypto_copy_input(input, input_len,
+                                   local_input->buffer, local_input->length);
+    if (status != PSA_SUCCESS) {
+        goto error;
+    }
+
+    return PSA_SUCCESS;
+
+error:
+    mbedtls_free(local_input->buffer);
+    local_input->buffer = NULL;
+    local_input->length = 0;
+    return status;
+}
+
+void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input)
+{
+    mbedtls_free(local_input->buffer);
+    local_input->buffer = NULL;
+    local_input->length = 0;
+}
+
+psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len,
+                                           psa_crypto_local_output_t *local_output)
+{
+    *local_output = PSA_CRYPTO_LOCAL_OUTPUT_INIT;
+
+    if (output_len == 0) {
+        return PSA_SUCCESS;
+    }
+    local_output->buffer = mbedtls_calloc(output_len, 1);
+    if (local_output->buffer == NULL) {
+        /* Since we dealt with the zero-length case above, we know that
+         * a NULL return value means a failure of allocation. */
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+    local_output->length = output_len;
+    local_output->original = output;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output)
+{
+    psa_status_t status;
+
+    if (local_output->buffer == NULL) {
+        local_output->length = 0;
+        return PSA_SUCCESS;
+    }
+    if (local_output->original == NULL) {
+        /* We have an internal copy but nothing to copy back to. */
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    status = psa_crypto_copy_output(local_output->buffer, local_output->length,
+                                    local_output->original, local_output->length);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    mbedtls_free(local_output->buffer);
+    local_output->buffer = NULL;
+    local_output->length = 0;
+
+    return PSA_SUCCESS;
+}
+
 #endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/library/psa_crypto_cipher.c b/library/psa_crypto_cipher.c
index a45fb0f..881d673 100644
--- a/library/psa_crypto_cipher.c
+++ b/library/psa_crypto_cipher.c
@@ -532,7 +532,11 @@
                                        output_length);
     } else
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
-    {
+    if (input_length == 0) {
+        /* There is no input, nothing to be done */
+        *output_length = 0;
+        status = PSA_SUCCESS;
+    } else {
         status = mbedtls_to_psa_error(
             mbedtls_cipher_update(&operation->ctx.cipher, input,
                                   input_length, output, output_length));
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index d4bdf92..9462d2e 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -884,4 +884,74 @@
 psa_status_t mbedtls_psa_verify_hash_abort(
     mbedtls_psa_verify_hash_interruptible_operation_t *operation);
 
+typedef struct psa_crypto_local_input_s {
+    uint8_t *buffer;
+    size_t length;
+} psa_crypto_local_input_t;
+
+#define PSA_CRYPTO_LOCAL_INPUT_INIT ((psa_crypto_local_input_t) { NULL, 0 })
+
+/** Allocate a local copy of an input buffer and copy the contents into it.
+ *
+ * \param[in] input             Pointer to input buffer.
+ * \param[in] input_len         Length of the input buffer.
+ * \param[out] local_input      Pointer to a psa_crypto_local_input_t struct
+ *                              containing a local input copy.
+ * \return                      #PSA_SUCCESS, if the buffer was successfully
+ *                              copied.
+ * \return                      #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of
+ *                              the buffer cannot be allocated.
+ */
+psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len,
+                                          psa_crypto_local_input_t *local_input);
+
+/** Free a local copy of an input buffer.
+ *
+ * \param[in] local_input       Pointer to a psa_crypto_local_input_t struct
+ *                              populated by a previous call to
+ *                              psa_crypto_local_input_alloc().
+ */
+void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input);
+
+typedef struct psa_crypto_local_output_s {
+    uint8_t *original;
+    uint8_t *buffer;
+    size_t length;
+} psa_crypto_local_output_t;
+
+#define PSA_CRYPTO_LOCAL_OUTPUT_INIT ((psa_crypto_local_output_t) { NULL, NULL, 0 })
+
+/** Allocate a local copy of an output buffer.
+ *
+ * \note                        This does not copy any data from the original
+ *                              output buffer but only allocates a buffer
+ *                              whose contents will be copied back to the
+ *                              original in a future call to
+ *                              psa_crypto_local_output_free().
+ *
+ * \param[in] output            Pointer to output buffer.
+ * \param[in] output_len        Length of the output buffer.
+ * \param[out] local_output     Pointer to a psa_crypto_local_output_t struct to
+ *                              populate with the local output copy.
+ * \return                      #PSA_SUCCESS, if the buffer was successfully
+ *                              copied.
+ * \return                      #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of
+ *                              the buffer cannot be allocated.
+ */
+psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len,
+                                           psa_crypto_local_output_t *local_output);
+
+/** Copy from a local copy of an output buffer back to the original, then
+ *  free the local copy.
+ *
+ * \param[in] local_output      Pointer to a psa_crypto_local_output_t struct
+ *                              populated by a previous call to
+ *                              psa_crypto_local_output_alloc().
+ * \return                      #PSA_SUCCESS, if the local output was
+ *                              successfully copied back to the original.
+ * \return                      #PSA_ERROR_CORRUPTION_DETECTED, if the output
+ *                              could not be copied back to the original.
+ */
+psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output);
+
 #endif /* PSA_CRYPTO_CORE_H */
diff --git a/library/psa_crypto_invasive.h b/library/psa_crypto_invasive.h
index 8b445a1..51c90c6 100644
--- a/library/psa_crypto_invasive.h
+++ b/library/psa_crypto_invasive.h
@@ -72,6 +72,21 @@
 psa_status_t psa_mac_key_can_do(
     psa_algorithm_t algorithm,
     psa_key_type_t key_type);
+
+psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len,
+                                   uint8_t *input_copy, size_t input_copy_len);
+
+psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len,
+                                    uint8_t *output, size_t output_len);
+
+/*
+ * Test hooks to use for memory unpoisoning/poisoning in copy functions.
+ */
+extern void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len);
+extern void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len);
+extern void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len);
+extern void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len);
+
 #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C */
 
 #endif /* PSA_CRYPTO_INVASIVE_H */
diff --git a/library/psa_crypto_random_impl.h b/library/psa_crypto_random_impl.h
index 64b8949..533fb2e 100644
--- a/library/psa_crypto_random_impl.h
+++ b/library/psa_crypto_random_impl.h
@@ -1,14 +1,6 @@
 /** \file psa_crypto_random_impl.h
  *
  * \brief PSA crypto random generator implementation abstraction.
- *
- * The definitions here need to be consistent with the declarations
- * in include/psa_util_internal.h. This file contains some redundant
- * declarations to increase the chance that a compiler will detect
- * inconsistencies if one file is changed without updating the other,
- * but not all potential inconsistencies can be enforced, so make sure
- * to check the public declarations and contracts in
- * include/psa_util_internal.h if you modify this file.
  */
 /*
  *  Copyright The Mbed TLS Contributors
@@ -22,22 +14,12 @@
 
 #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
 
-#include <string.h>
-#include <mbedtls/entropy.h> // only for error codes
-#include <psa/crypto.h>
-
 typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t;
 
-/* Trivial wrapper around psa_generate_random(). */
-int mbedtls_psa_get_random(void *p_rng,
-                           unsigned char *output,
-                           size_t output_size);
-
-/* The PSA RNG API doesn't need any externally maintained state. */
-#define MBEDTLS_PSA_RANDOM_STATE NULL
-
 #else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 
+#include "mbedtls/entropy.h"
+
 /* Choose a DRBG based on configuration and availability */
 #if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)
 
@@ -67,11 +49,37 @@
 #error "No hash algorithm available for HMAC_DBRG."
 #endif
 
-#else
+#else /* !MBEDTLS_PSA_HMAC_DRBG_MD_TYPE && !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/
+
 #error "No DRBG module available for the psa_crypto module."
+
+#endif /* !MBEDTLS_PSA_HMAC_DRBG_MD_TYPE && !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+#include "mbedtls/ctr_drbg.h"
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+#include "mbedtls/hmac_drbg.h"
+#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */
+
+/* The maximum number of bytes that mbedtls_psa_get_random() is expected to return. */
+#if defined(MBEDTLS_CTR_DRBG_C)
+#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST
 #endif
 
-#include "mbedtls/entropy.h"
+#if defined(MBEDTLS_CTR_DRBG_C)
+typedef mbedtls_ctr_drbg_context            mbedtls_psa_drbg_context_t;
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+typedef mbedtls_hmac_drbg_context           mbedtls_psa_drbg_context_t;
+#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */
+
+typedef struct {
+    void (* entropy_init)(mbedtls_entropy_context *ctx);
+    void (* entropy_free)(mbedtls_entropy_context *ctx);
+    mbedtls_entropy_context entropy;
+    mbedtls_psa_drbg_context_t drbg;
+} mbedtls_psa_random_context_t;
 
 /** Initialize the PSA DRBG.
  *
@@ -99,63 +107,6 @@
 #endif
 }
 
-/** The type of the PSA random generator context.
- *
- * The random generator context is composed of an entropy context and
- * a DRBG context.
- */
-typedef struct {
-    void (* entropy_init)(mbedtls_entropy_context *ctx);
-    void (* entropy_free)(mbedtls_entropy_context *ctx);
-    mbedtls_entropy_context entropy;
-    mbedtls_psa_drbg_context_t drbg;
-} mbedtls_psa_random_context_t;
-
-/* Defined in include/psa_util_internal.h so that it's visible to
- * application code. The declaration here is redundant, but included
- * as a safety net to make it more likely that a future change that
- * accidentally causes the implementation to diverge from the interface
- * will be noticed. */
-/* Do not include the declaration under MSVC because it doesn't accept it
- * ("error C2370: 'mbedtls_psa_get_random' : redefinition; different storage class").
- * Observed with Visual Studio 2013. A known bug apparently:
- * https://stackoverflow.com/questions/8146541/duplicate-external-static-declarations-not-allowed-in-visual-studio
- */
-#if !defined(_MSC_VER)
-static mbedtls_f_rng_t *const mbedtls_psa_get_random;
-#endif
-
-/** The maximum number of bytes that mbedtls_psa_get_random() is expected to
- * return.
- */
-#if defined(MBEDTLS_CTR_DRBG_C)
-#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST
-#elif defined(MBEDTLS_HMAC_DRBG_C)
-#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST
-#endif
-
-/** A pointer to the PSA DRBG state.
- *
- * This variable is only intended to be used through the macro
- * #MBEDTLS_PSA_RANDOM_STATE.
- */
-/* psa_crypto.c sets this variable to a pointer to the DRBG state in the
- * global PSA crypto state. */
-/* The type `mbedtls_psa_drbg_context_t` is defined in
- * include/psa_util_internal.h so that `mbedtls_psa_random_state` can be
- * declared there and be visible to application code. */
-extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state;
-
-/** A pointer to the PSA DRBG state.
- *
- * This macro expands to an expression that is suitable as the \c p_rng
- * parameter to pass to mbedtls_psa_get_random().
- *
- * This macro exists in all configurations where the psa_crypto module is
- * enabled. Its expansion depends on the configuration.
- */
-#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state
-
 /** Seed the PSA DRBG.
  *
  * \param entropy       An entropy context to read the seed from.
@@ -167,23 +118,15 @@
  * \return              \c 0 on success.
  * \return              An Mbed TLS error code (\c MBEDTLS_ERR_xxx) on failure.
  */
-static inline int mbedtls_psa_drbg_seed(
-    mbedtls_entropy_context *entropy,
-    const unsigned char *custom, size_t len)
+static inline int mbedtls_psa_drbg_seed(mbedtls_psa_drbg_context_t *drbg_ctx,
+                                        mbedtls_entropy_context *entropy,
+                                        const unsigned char *custom, size_t len)
 {
 #if defined(MBEDTLS_CTR_DRBG_C)
-    return mbedtls_ctr_drbg_seed(MBEDTLS_PSA_RANDOM_STATE,
-                                 mbedtls_entropy_func,
-                                 entropy,
-                                 custom, len);
+    return mbedtls_ctr_drbg_seed(drbg_ctx, mbedtls_entropy_func, entropy, custom, len);
 #elif defined(MBEDTLS_HMAC_DRBG_C)
-    const mbedtls_md_info_t *md_info =
-        mbedtls_md_info_from_type(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE);
-    return mbedtls_hmac_drbg_seed(MBEDTLS_PSA_RANDOM_STATE,
-                                  md_info,
-                                  mbedtls_entropy_func,
-                                  entropy,
-                                  custom, len);
+    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE);
+    return mbedtls_hmac_drbg_seed(drbg_ctx, md_info, mbedtls_entropy_func, entropy, custom, len);
 #endif
 }
 
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
index 5dee32f..9986a44 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -34,6 +34,23 @@
 
 static psa_global_data_t global_data;
 
+static uint8_t psa_get_key_slots_initialized(void)
+{
+    uint8_t initialized;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    initialized = global_data.key_slots_initialized;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    return initialized;
+}
+
 int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok)
 {
     psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
@@ -136,7 +153,9 @@
 {
     /* Nothing to do: program startup and psa_wipe_all_key_slots() both
      * guarantee that the key slots are initialized to all-zero, which
-     * means that all the key slots are in a valid, empty state. */
+     * means that all the key slots are in a valid, empty state. The global
+     * data mutex is already held when calling this function, so no need to
+     * lock it here, to set the flag. */
     global_data.key_slots_initialized = 1;
     return PSA_SUCCESS;
 }
@@ -151,6 +170,7 @@
         slot->state = PSA_SLOT_PENDING_DELETION;
         (void) psa_wipe_key_slot(slot);
     }
+    /* The global data mutex is already held when calling this function. */
     global_data.key_slots_initialized = 0;
 }
 
@@ -161,7 +181,7 @@
     size_t slot_idx;
     psa_key_slot_t *selected_slot, *unused_persistent_key_slot;
 
-    if (!global_data.key_slots_initialized) {
+    if (!psa_get_key_slots_initialized()) {
         status = PSA_ERROR_BAD_STATE;
         goto error;
     }
@@ -344,7 +364,7 @@
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
     *p_slot = NULL;
-    if (!global_data.key_slots_initialized) {
+    if (!psa_get_key_slots_initialized()) {
         return PSA_ERROR_BAD_STATE;
     }
 
@@ -404,6 +424,8 @@
     if (status != PSA_SUCCESS) {
         psa_wipe_key_slot(*p_slot);
 
+        /* If the key does not exist, we need to return
+         * PSA_ERROR_INVALID_HANDLE. */
         if (status == PSA_ERROR_DOES_NOT_EXIST) {
             status = PSA_ERROR_INVALID_HANDLE;
         }
@@ -420,6 +442,9 @@
     status = PSA_ERROR_INVALID_HANDLE;
 #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
 
+    if (status != PSA_SUCCESS) {
+        *p_slot = NULL;
+    }
 #if defined(MBEDTLS_THREADING_C)
     PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
                               &mbedtls_threading_key_slot_mutex));
diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h
index bcfc9d8..a84be7d 100644
--- a/library/psa_crypto_slot_management.h
+++ b/library/psa_crypto_slot_management.h
@@ -58,6 +58,9 @@
  * It is the responsibility of the caller to call psa_unregister_read(slot)
  * when they have finished reading the contents of the slot.
  *
+ * On failure, `*p_slot` is set to NULL. This ensures that it is always valid
+ * to call psa_unregister_read on the returned slot.
+ *
  * \param key           Key identifier to query.
  * \param[out] p_slot   On success, `*p_slot` contains a pointer to the
  *                      key slot containing the description of the key
diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h
index f1ea265..d7f5b18 100644
--- a/library/psa_crypto_storage.h
+++ b/library/psa_crypto_storage.h
@@ -231,8 +231,9 @@
  * This type is designed to be serialized by writing the memory representation
  * and reading it back on the same device.
  *
- * \note The transaction mechanism is designed for a single active transaction
- *       at a time. The transaction object is #psa_crypto_transaction.
+ * \note The transaction mechanism is not thread-safe. There can only be one
+ *       single active transaction at a time.
+ *       The transaction object is #psa_crypto_transaction.
  *
  * \note If an API call starts a transaction, it must complete this transaction
  *       before returning to the application.
diff --git a/library/psa_util.c b/library/psa_util.c
index 125b173..4ccc5b0 100644
--- a/library/psa_util.c
+++ b/library/psa_util.c
@@ -18,7 +18,7 @@
 
 #include "psa_util_internal.h"
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 
 #include <psa/crypto.h>
 
@@ -46,6 +46,7 @@
 #if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
 #include <mbedtls/cipher.h>
 #endif
+#include <mbedtls/entropy.h>
 
 /* PSA_SUCCESS is kept at the top of each error table since
  * it's the most common status when everything functions properly. */
@@ -338,7 +339,31 @@
 }
 #endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
 
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+/* Wrapper function allowing the classic API to use the PSA RNG.
+ *
+ * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls
+ * `psa_generate_random(...)`. The state parameter is ignored since the
+ * PSA API doesn't support passing an explicit state.
+ */
+int mbedtls_psa_get_random(void *p_rng,
+                           unsigned char *output,
+                           size_t output_size)
+{
+    /* This function takes a pointer to the RNG state because that's what
+     * classic mbedtls functions using an RNG expect. The PSA RNG manages
+     * its own state internally and doesn't let the caller access that state.
+     * So we just ignore the state parameter, and in practice we'll pass
+     * NULL. */
+    (void) p_rng;
+    psa_status_t status = psa_generate_random(output, output_size);
+    if (status == PSA_SUCCESS) {
+        return 0;
+    } else {
+        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+    }
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
 
 #if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
 
diff --git a/library/psa_util_internal.h b/library/psa_util_internal.h
index 3e62d5f..70a08a0 100644
--- a/library/psa_util_internal.h
+++ b/library/psa_util_internal.h
@@ -16,7 +16,7 @@
 
 #include "psa/crypto.h"
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 
 /*************************************************************************
  * FFDH
@@ -96,5 +96,5 @@
                           sizeof(error_list)/sizeof(error_list[0]),   \
                           fallback_f)
 
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
 #endif /* MBEDTLS_PSA_UTIL_INTERNAL_H */
diff --git a/library/rsa.c b/library/rsa.c
index 5debc69..7eb4a25 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -2231,7 +2231,7 @@
     if (ctx->padding != MBEDTLS_RSA_PKCS_V21) {
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
-    if (ctx->hash_id == MBEDTLS_MD_NONE) {
+    if ((ctx->hash_id == MBEDTLS_MD_NONE) && (md_alg == MBEDTLS_MD_NONE)) {
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
     return rsa_rsassa_pss_sign_no_mode_check(ctx, f_rng, p_rng, md_alg, hashlen, hash, saltlen,
diff --git a/library/sha3.c b/library/sha3.c
index 27d495f..5738559 100644
--- a/library/sha3.c
+++ b/library/sha3.c
@@ -14,6 +14,33 @@
 
 #if defined(MBEDTLS_SHA3_C)
 
+/*
+ * These macros select manually unrolled implementations of parts of the main permutation function.
+ *
+ * Unrolling has a major impact on both performance and code size. gcc performance benefits a lot
+ * from manually unrolling at higher optimisation levels.
+ *
+ * Depending on your size/perf priorities, compiler and target, it may be beneficial to adjust
+ * these; the defaults here should give sensible trade-offs for gcc and clang on aarch64 and
+ * x86-64.
+ */
+#if !defined(MBEDTLS_SHA3_THETA_UNROLL)
+    #define MBEDTLS_SHA3_THETA_UNROLL 0 //no-check-names
+#endif
+#if !defined(MBEDTLS_SHA3_CHI_UNROLL)
+    #if defined(__OPTIMIZE_SIZE__)
+        #define MBEDTLS_SHA3_CHI_UNROLL 0 //no-check-names
+    #else
+        #define MBEDTLS_SHA3_CHI_UNROLL 1 //no-check-names
+    #endif
+#endif
+#if !defined(MBEDTLS_SHA3_PI_UNROLL)
+    #define MBEDTLS_SHA3_PI_UNROLL 1 //no-check-names
+#endif
+#if !defined(MBEDTLS_SHA3_RHO_UNROLL)
+    #define MBEDTLS_SHA3_RHO_UNROLL 1 //no-check-names
+#endif
+
 #include "mbedtls/sha3.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
@@ -56,18 +83,15 @@
 };
 #undef H
 
-static const uint8_t rho[24] = {
-    1, 62, 28, 27, 36, 44,  6, 55, 20,
-    3, 10, 43, 25, 39, 41, 45, 15,
-    21,  8, 18,  2, 61, 56, 14
+static const uint32_t rho[6] = {
+    0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832
 };
 
-static const uint8_t pi[24] = {
-    10,  7, 11, 17, 18, 3,  5, 16,  8, 21, 24, 4,
-    15, 23, 19, 13, 12, 2, 20, 14, 22,  9,  6, 1,
+static const uint32_t pi[6] = {
+    0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916
 };
 
-#define ROT64(x, y) (((x) << (y)) | ((x) >> (64U - (y))))
+#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right
 #define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \
 } while (0)
 #define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3)))
@@ -84,39 +108,97 @@
         uint64_t t;
 
         /* Theta */
+#if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names
+        for (i = 0; i < 5; i++) {
+            lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
+        }
+        for (i = 0; i < 5; i++) {
+            t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63);
+            s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t;
+        }
+#else
         lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
         lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
         lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
         lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
         lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
 
-        t = lane[4] ^ ROT64(lane[1], 1);
+        t = lane[4] ^ ROTR64(lane[1], 63);
         s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;
 
-        t = lane[0] ^ ROT64(lane[2], 1);
+        t = lane[0] ^ ROTR64(lane[2], 63);
         s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;
 
-        t = lane[1] ^ ROT64(lane[3], 1);
+        t = lane[1] ^ ROTR64(lane[3], 63);
         s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;
 
-        t = lane[2] ^ ROT64(lane[4], 1);
+        t = lane[2] ^ ROTR64(lane[4], 63);
         s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;
 
-        t = lane[3] ^ ROT64(lane[0], 1);
+        t = lane[3] ^ ROTR64(lane[0], 63);
         s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;
+#endif
 
         /* Rho */
-        for (i = 1; i < 25; i++) {
-            s[i] = ROT64(s[i], rho[i-1]);
+        for (i = 1; i < 25; i += 4) {
+            uint32_t r = rho[(i - 1) >> 2];
+#if MBEDTLS_SHA3_RHO_UNROLL == 0
+            for (int j = i; j < i + 4; j++) {
+                uint8_t r8 = (uint8_t) (r >> 24);
+                r <<= 8;
+                s[j] = ROTR64(s[j], r8);
+            }
+#else
+            s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r));
+            s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r));
+            s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r));
+            s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r));
+#endif
         }
 
         /* Pi */
         t = s[1];
-        for (i = 0; i < 24; i++) {
-            SWAP(s[pi[i]], t);
+#if MBEDTLS_SHA3_PI_UNROLL == 0
+        for (i = 0; i < 24; i += 4) {
+            uint32_t p = pi[i >> 2];
+            for (unsigned j = 0; j < 4; j++) {
+                SWAP(s[p & 0xff], t);
+                p >>= 8;
+            }
         }
+#else
+        uint32_t p = pi[0];
+        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+        p = pi[1];
+        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+        p = pi[2];
+        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+        p = pi[3];
+        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+        p = pi[4];
+        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+        p = pi[5];
+        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+#endif
 
         /* Chi */
+#if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names
+        for (i = 0; i <= 20; i += 5) {
+            lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2];
+            lane[3] = s[i + 3]; lane[4] = s[i + 4];
+            s[i + 0] ^= (~lane[1]) & lane[2];
+            s[i + 1] ^= (~lane[2]) & lane[3];
+            s[i + 2] ^= (~lane[3]) & lane[4];
+            s[i + 3] ^= (~lane[4]) & lane[0];
+            s[i + 4] ^= (~lane[0]) & lane[1];
+        }
+#else
         lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
         s[0] ^= (~lane[1]) & lane[2];
         s[1] ^= (~lane[2]) & lane[3];
@@ -151,6 +233,7 @@
         s[22] ^= (~lane[3]) & lane[4];
         s[23] ^= (~lane[4]) & lane[0];
         s[24] ^= (~lane[0]) & lane[1];
+#endif
 
         /* Iota */
         /* Decompress the round masks (see definition of rc) */
diff --git a/library/ssl_client.c b/library/ssl_client.c
index 6d988a8..345e608 100644
--- a/library/ssl_client.c
+++ b/library/ssl_client.c
@@ -765,11 +765,6 @@
           MBEDTLS_SSL_SESSION_TICKETS &&
           MBEDTLS_HAVE_TIME */
 
-    if (ssl->conf->f_rng == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
-        return MBEDTLS_ERR_SSL_NO_RNG;
-    }
-
     /* Bet on the highest configured version if we are not in a TLS 1.2
      * renegotiation or session resumption.
      */
@@ -797,10 +792,15 @@
         (ssl->handshake->cookie == NULL))
 #endif
     {
-        ret = ssl_generate_random(ssl);
-        if (ret != 0) {
-            MBEDTLS_SSL_DEBUG_RET(1, "Random bytes generation failed", ret);
-            return ret;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        if (!ssl->handshake->hello_retry_request_flag)
+#endif
+        {
+            ret = ssl_generate_random(ssl);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "Random bytes generation failed", ret);
+                return ret;
+            }
         }
     }
 
diff --git a/library/ssl_debug_helpers.h b/library/ssl_debug_helpers.h
index a8e3140..4889e77 100644
--- a/library/ssl_debug_helpers.h
+++ b/library/ssl_debug_helpers.h
@@ -23,6 +23,7 @@
 
 #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
 const char *mbedtls_ssl_early_data_status_str(mbedtls_ssl_early_data_status in);
+const char *mbedtls_ssl_early_data_state_str(mbedtls_ssl_early_data_state in);
 #endif
 
 const char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in);
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index d8844fc..a8807f6 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -2150,6 +2150,60 @@
                                            unsigned char *buf,
                                            const unsigned char *end,
                                            size_t *out_len);
+
+int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl,
+                                           size_t early_data_len);
+
+typedef enum {
+/*
+ * The client has not sent the first ClientHello yet, the negotiation of early
+ * data has not started yet.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_IDLE,
+
+/*
+ * In its ClientHello, the client has not included an early data indication
+ * extension.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT,
+
+/*
+ * The client has sent an early data indication extension in its first
+ * ClientHello, it has not received the response (ServerHello or
+ * HelloRetryRequest) from the server yet. The transform to protect early data
+ * is not set either as for middlebox compatibility a dummy CCS may have to be
+ * sent in clear. Early data cannot be sent to the server yet.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT,
+
+/*
+ * The client has sent an early data indication extension in its first
+ * ClientHello, it has not received the response (ServerHello or
+ * HelloRetryRequest) from the server yet. The transform to protect early data
+ * has been set and early data can be written now.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE,
+
+/*
+ * The client has indicated the use of early data and the server has accepted
+ * it.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED,
+
+/*
+ * The client has indicated the use of early data but the server has rejected
+ * it.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED,
+
+/*
+ * The client has sent an early data indication extension in its first
+ * ClientHello, the server has accepted them and the client has received the
+ * server Finished message. It cannot send early data to the server anymore.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED,
+
+} mbedtls_ssl_early_data_state;
 #endif /* MBEDTLS_SSL_EARLY_DATA */
 
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
@@ -2798,6 +2852,13 @@
                                      const char *hostname);
 #endif
 
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \
+    defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session,
+                                        const char *alpn);
+#endif
+
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
 
 #define MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME (604800)
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index 2a6d434..2bdad84 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -4005,7 +4005,11 @@
                  MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD)) {
                 MBEDTLS_SSL_DEBUG_MSG(
                     3, ("EarlyData: deprotect and discard app data records."));
-                /* TODO: Add max_early_data_size check here, see issue 6347 */
+
+                ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len);
+                if (ret != 0) {
+                    return ret;
+                }
                 ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
             }
 #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */
@@ -4129,9 +4133,15 @@
      */
     if (ssl->discard_early_data_record == MBEDTLS_SSL_EARLY_DATA_DISCARD) {
         if (rec->type == MBEDTLS_SSL_MSG_APPLICATION_DATA) {
+
+            ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len);
+            if (ret != 0) {
+                return ret;
+            }
+
             MBEDTLS_SSL_DEBUG_MSG(
                 3, ("EarlyData: Ignore application message before 2nd ClientHello"));
-            /* TODO: Add max_early_data_size check here, see issue 6347 */
+
             return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
         } else if (rec->type == MBEDTLS_SSL_MSG_HANDSHAKE) {
             ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;
@@ -5560,9 +5570,9 @@
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_SSL_CLI_C)
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_check_new_session_ticket(mbedtls_ssl_context *ssl)
+static int ssl_tls13_is_new_session_ticket(mbedtls_ssl_context *ssl)
 {
 
     if ((ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl)) ||
@@ -5570,15 +5580,9 @@
         return 0;
     }
 
-    ssl->keep_current_message = 1;
-
-    MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received"));
-    mbedtls_ssl_handshake_set_state(ssl,
-                                    MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
-
-    return MBEDTLS_ERR_SSL_WANT_READ;
+    return 1;
 }
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+#endif /* MBEDTLS_SSL_CLI_C */
 
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)
@@ -5586,14 +5590,23 @@
 
     MBEDTLS_SSL_DEBUG_MSG(3, ("received post-handshake message"));
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_SSL_CLI_C)
     if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-        int ret = ssl_tls13_check_new_session_ticket(ssl);
-        if (ret != 0) {
-            return ret;
+        if (ssl_tls13_is_new_session_ticket(ssl)) {
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+            MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received"));
+            ssl->keep_current_message = 1;
+
+            mbedtls_ssl_handshake_set_state(ssl,
+                                            MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
+            return MBEDTLS_ERR_SSL_WANT_READ;
+#else
+            MBEDTLS_SSL_DEBUG_MSG(3, ("Ignore NewSessionTicket, not supported."));
+            return 0;
+#endif
         }
     }
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+#endif /* MBEDTLS_SSL_CLI_C */
 
     /* Fail in all other cases. */
     return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
@@ -6064,7 +6077,7 @@
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const struct mbedtls_ssl_config *conf;
-    int written_data_len = 0;
+    uint32_t remaining;
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> write early_data"));
 
@@ -6087,21 +6100,21 @@
     }
 
     /*
-     * If we are at the beginning of the handshake, the early data status being
-     * equal to MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN or
-     * MBEDTLS_SSL_EARLY_DATA_STATUS_SENT advance the handshake just
+     * If we are at the beginning of the handshake, the early data state being
+     * equal to MBEDTLS_SSL_EARLY_DATA_STATE_IDLE or
+     * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT advance the handshake just
      * enough to be able to send early data if possible. That way, we can
      * guarantee that when starting the handshake with this function we will
-     * send at least one record of early data. Note that when the status is
-     * MBEDTLS_SSL_EARLY_DATA_STATUS_SENT and not yet
-     * MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE, we cannot send early data yet
+     * send at least one record of early data. Note that when the state is
+     * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT and not yet
+     * MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE, we cannot send early data
      * as the early data outbound transform has not been set as we may have to
      * first send a dummy CCS in clear.
      */
-    if ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) ||
-        (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) {
-        while ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) ||
-               (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) {
+    if ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) ||
+        (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) {
+        while ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) ||
+               (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) {
             ret = mbedtls_ssl_handshake_step(ssl);
             if (ret != 0) {
                 MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake_step", ret);
@@ -6114,15 +6127,24 @@
                 return ret;
             }
         }
+        remaining = ssl->session_negotiate->max_early_data_size;
     } else {
         /*
-         * If we are past the point where we can send early data, return
-         * immediatly. Otherwise, progress the handshake as much as possible to
-         * not delay it too much. If we reach a point where we can still send
-         * early data, then we will send some.
+         * If we are past the point where we can send early data or we have
+         * already reached the maximum early data size, return immediatly.
+         * Otherwise, progress the handshake as much as possible to not delay
+         * it too much. If we reach a point where we can still send early data,
+         * then we will send some.
          */
-        if ((ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE) &&
-            (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED)) {
+        if ((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) &&
+            (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED)) {
+            return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
+        }
+
+        remaining = ssl->session_negotiate->max_early_data_size -
+                    ssl->total_early_data_size;
+
+        if (remaining == 0) {
             return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
         }
 
@@ -6133,16 +6155,24 @@
         }
     }
 
-    if ((ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE) &&
-        (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED)) {
+    if (((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) &&
+         (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED))
+        || (remaining == 0)) {
         return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
     }
 
-    written_data_len = ssl_write_real(ssl, buf, len);
+    if (len > remaining) {
+        len = remaining;
+    }
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, len=%d", written_data_len));
+    ret = ssl_write_real(ssl, buf, len);
+    if (ret >= 0) {
+        ssl->total_early_data_size += ret;
+    }
 
-    return written_data_len;
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, ret=%d", ret));
+
+    return ret;
 }
 #endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */
 
diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c
index 5da3887..6a31b0b 100644
--- a/library/ssl_ticket.c
+++ b/library/ssl_ticket.c
@@ -504,7 +504,7 @@
 #if defined(MBEDTLS_HAVE_TIME)
     mbedtls_ms_time_t ticket_creation_time, ticket_age;
     mbedtls_ms_time_t ticket_lifetime =
-        (mbedtls_ms_time_t) ctx->ticket_lifetime * 1000;
+        (mbedtls_ms_time_t) key->lifetime * 1000;
 
     ret = mbedtls_ssl_session_get_ticket_creation_time(session,
                                                        &ticket_creation_time);
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index b09db1e..c2c2b6f 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -238,6 +238,11 @@
 #endif
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
 
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \
+    defined(MBEDTLS_SSL_EARLY_DATA)
+    dst->ticket_alpn = NULL;
+#endif
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 
 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
@@ -275,6 +280,16 @@
 
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \
+    defined(MBEDTLS_SSL_EARLY_DATA)
+    {
+        int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn);
+        if (ret != 0) {
+            return ret;
+        }
+    }
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_ALPN && MBEDTLS_SSL_EARLY_DATA */
+
 #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
     if (src->ticket != NULL) {
         dst->ticket = mbedtls_calloc(1, src->ticket_len);
@@ -1096,11 +1111,12 @@
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
 #if defined(MBEDTLS_SSL_CLI_C)
-    ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN;
+    ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IDLE;
 #endif
 #if defined(MBEDTLS_SSL_SRV_C)
     ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;
 #endif
+    ssl->total_early_data_size = 0;
 #endif /* MBEDTLS_SSL_EARLY_DATA */
 
     /* Initialize structures */
@@ -1361,6 +1377,11 @@
     }
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
+    if (ssl->conf->f_rng == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
+        return MBEDTLS_ERR_SSL_NO_RNG;
+    }
+
     /* Space for further checks */
 
     return 0;
@@ -1545,6 +1566,7 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     ssl->state = MBEDTLS_SSL_HELLO_REQUEST;
+    ssl->tls_version = ssl->conf->max_tls_version;
 
     mbedtls_ssl_session_reset_msg_layer(ssl, partial);
 
@@ -1738,6 +1760,7 @@
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
         const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
             mbedtls_ssl_ciphersuite_from_id(session->ciphersuite);
 
@@ -1748,6 +1771,14 @@
                                       session->ciphersuite));
             return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         }
+#else
+        /*
+         * If session tickets are not enabled, it is not possible to resume a
+         * TLS 1.3 session, thus do not make any change to the SSL context in
+         * the first place.
+         */
+        return 0;
+#endif
     }
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
@@ -3744,9 +3775,16 @@
     size_t hostname_len = (session->hostname == NULL) ?
                           0 : strlen(session->hostname) + 1;
 #endif
+
+#if defined(MBEDTLS_SSL_SRV_C) && \
+    defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+    const size_t alpn_len = (session->ticket_alpn == NULL) ?
+                            0 : strlen(session->ticket_alpn) + 1;
+#endif
     size_t needed =   4  /* ticket_age_add */
                     + 1  /* ticket_flags */
                     + 1; /* resumption_key length */
+
     *olen = 0;
 
     if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) {
@@ -3765,6 +3803,15 @@
     needed += 8; /* ticket_creation_time or ticket_reception_time */
 #endif
 
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+        needed +=   2                         /* alpn_len */
+                  + alpn_len;                 /* alpn */
+#endif
+    }
+#endif /* MBEDTLS_SSL_SRV_C */
+
 #if defined(MBEDTLS_SSL_CLI_C)
     if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
@@ -3807,13 +3854,26 @@
     p += 2;
 #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
 
-#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+#if defined(MBEDTLS_SSL_SRV_C)
     if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+#if defined(MBEDTLS_HAVE_TIME)
         MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0);
         p += 8;
-    }
 #endif /* MBEDTLS_HAVE_TIME */
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+        MBEDTLS_PUT_UINT16_BE(alpn_len, p, 0);
+        p += 2;
+
+        if (alpn_len > 0) {
+            /* save chosen alpn */
+            memcpy(p, session->ticket_alpn, alpn_len);
+            p += alpn_len;
+        }
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */
+    }
+#endif /* MBEDTLS_SSL_SRV_C */
+
 #if defined(MBEDTLS_SSL_CLI_C)
     if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
@@ -3888,16 +3948,41 @@
     p += 2;
 #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
 
-#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+#if  defined(MBEDTLS_SSL_SRV_C)
     if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+#if defined(MBEDTLS_HAVE_TIME)
         if (end - p < 8) {
             return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         }
         session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0);
         p += 8;
-    }
 #endif /* MBEDTLS_HAVE_TIME */
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+        size_t alpn_len;
+
+        if (end - p < 2) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+
+        alpn_len = MBEDTLS_GET_UINT16_BE(p, 0);
+        p += 2;
+
+        if (end - p < (long int) alpn_len) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+
+        if (alpn_len > 0) {
+            int ret = mbedtls_ssl_session_set_ticket_alpn(session, (char *) p);
+            if (ret != 0) {
+                return ret;
+            }
+            p += alpn_len;
+        }
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */
+    }
+#endif /* MBEDTLS_SSL_SRV_C */
+
 #if defined(MBEDTLS_SSL_CLI_C)
     if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
@@ -3973,7 +4058,7 @@
 }
 
 static int ssl_tls13_session_load(const mbedtls_ssl_session *session,
-                                  unsigned char *buf,
+                                  const unsigned char *buf,
                                   size_t buf_len)
 {
     ((void) session);
@@ -4054,6 +4139,13 @@
 #define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 0
 #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
 
+#if defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C) && \
+    defined(MBEDTLS_SSL_EARLY_DATA)
+#define SSL_SERIALIZED_SESSION_CONFIG_ALPN 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_ALPN 0
+#endif /* MBEDTLS_SSL_ALPN */
+
 #define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT          0
 #define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT           1
 #define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2
@@ -4064,6 +4156,7 @@
 #define SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT           7
 #define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT    8
 #define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT   9
+#define SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT          10
 
 #define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG                           \
     ((uint16_t) (                                                      \
@@ -4080,7 +4173,9 @@
          (SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA << \
              SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT) | \
          (SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE << \
-             SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT)))
+             SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_ALPN << \
+             SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT)))
 
 static const unsigned char ssl_serialized_session_header[] = {
     MBEDTLS_VERSION_MAJOR,
@@ -4155,8 +4250,12 @@
  * #endif
  *    select ( endpoint ) {
  *         case client: ClientOnlyData;
+ *         case server:
  * #if defined(MBEDTLS_HAVE_TIME)
- *         case server: uint64 ticket_creation_time;
+ *                      uint64 ticket_creation_time;
+ * #endif
+ * #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+ *                      opaque ticket_alpn<0..256>;
  * #endif
  *     };
  * } serialized_session_tls13;
@@ -4846,6 +4945,11 @@
     mbedtls_free(session->ticket);
 #endif
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && \
+    defined(MBEDTLS_SSL_SRV_C)
+    mbedtls_free(session->ticket_alpn);
+#endif
+
     mbedtls_platform_zeroize(session, sizeof(mbedtls_ssl_session));
 }
 
@@ -5344,7 +5448,7 @@
             /* alpn_chosen should point to an item in the configured list */
             for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) {
                 if (strlen(*cur) == alpn_len &&
-                    memcmp(p, cur, alpn_len) == 0) {
+                    memcmp(p, *cur, alpn_len) == 0) {
                     ssl->alpn_chosen = *cur;
                     break;
                 }
@@ -9792,4 +9896,36 @@
           MBEDTLS_SSL_SERVER_NAME_INDICATION &&
           MBEDTLS_SSL_CLI_C */
 
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \
+    defined(MBEDTLS_SSL_ALPN)
+int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session,
+                                        const char *alpn)
+{
+    size_t alpn_len = 0;
+
+    if (alpn != NULL) {
+        alpn_len = strlen(alpn);
+
+        if (alpn_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+    }
+
+    if (session->ticket_alpn != NULL) {
+        mbedtls_zeroize_and_free(session->ticket_alpn,
+                                 strlen(session->ticket_alpn));
+        session->ticket_alpn = NULL;
+    }
+
+    if (alpn != NULL) {
+        session->ticket_alpn = mbedtls_calloc(alpn_len + 1, 1);
+        if (session->ticket_alpn == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
+        memcpy(session->ticket_alpn, alpn, alpn_len);
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */
 #endif /* MBEDTLS_SSL_TLS_C */
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index 5bee188..b49a8ae 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -2178,11 +2178,6 @@
     }
 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
 
-    if (ssl->conf->f_rng == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
-        return MBEDTLS_ERR_SSL_NO_RNG;
-    }
-
     /*
      *     0  .   0   handshake type
      *     1  .   3   handshake length
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 88d6c9e..162e3a3 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -666,6 +666,7 @@
     return 0;
 }
 
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 static psa_algorithm_t ssl_tls13_get_ciphersuite_hash_alg(int ciphersuite)
 {
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info = NULL;
@@ -678,7 +679,6 @@
     return PSA_ALG_NONE;
 }
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 static int ssl_tls13_has_configured_ticket(mbedtls_ssl_context *ssl)
 {
     mbedtls_ssl_session *session = ssl->session_negotiate;
@@ -1181,12 +1181,12 @@
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
     /* In the first ClientHello, write the early data indication extension if
-     * necessary and update the early data status.
+     * necessary and update the early data state.
      * If an HRR has been received and thus we are currently writing the
      * second ClientHello, the second ClientHello must not contain an early
-     * data extension and the early data status must stay as it is:
-     * MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT or
-     * MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED.
+     * data extension and the early data state must stay as it is:
+     * MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT or
+     * MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED.
      */
     if (!ssl->handshake->hello_retry_request_flag) {
         if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) &&
@@ -1199,9 +1199,9 @@
             }
             p += ext_len;
 
-            ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_SENT;
+            ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT;
         } else {
-            ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT;
+            ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT;
         }
     }
 #endif /* MBEDTLS_SSL_EARLY_DATA */
@@ -1239,7 +1239,7 @@
     size_t psk_len;
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
 
-    if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT) {
+    if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT) {
         MBEDTLS_SSL_DEBUG_MSG(
             1, ("Set hs psk for early data when writing the first psk"));
 
@@ -1302,7 +1302,7 @@
             1, ("Switch to early data keys for outbound traffic"));
         mbedtls_ssl_set_outbound_transform(
             ssl, ssl->handshake->transform_earlydata);
-        ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE;
+        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE;
 #endif
     }
 #endif /* MBEDTLS_SSL_EARLY_DATA */
@@ -1919,7 +1919,7 @@
      * cases we compute it here.
      */
 #if defined(MBEDTLS_SSL_EARLY_DATA)
-    if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT ||
+    if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT ||
         handshake->key_exchange_mode ==
         MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL)
 #endif
@@ -1975,8 +1975,8 @@
     ssl->session_negotiate->ciphersuite = ssl->handshake->ciphersuite_info->id;
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
-    if (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) {
-        ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
+    if (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) {
+        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED;
     }
 #endif
 
@@ -2238,9 +2238,10 @@
             return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
         }
 
-        ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
-    } else if (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) {
-        ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
+        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED;
+    } else if (ssl->early_data_state !=
+               MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) {
+        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED;
     }
 #endif
 
@@ -2324,16 +2325,16 @@
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    switch (ssl->early_data_status) {
-        case MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT:
-            return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT;
+    switch (ssl->early_data_state) {
+        case MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT:
+            return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED;
             break;
 
-        case MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED:
+        case MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED:
             return MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
             break;
 
-        case MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED:
+        case MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED:
             return MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
             break;
 
@@ -2604,8 +2605,8 @@
     }
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
-    if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED) {
-        ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED;
+    if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED) {
+        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED;
         mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA);
     } else
 #endif /* MBEDTLS_SSL_EARLY_DATA */
@@ -2916,12 +2917,17 @@
         return ret;
     }
 
-    /* session has been updated, allow export */
-    session->exported = 0;
-
     return 0;
 }
 
+/* Non negative return values for ssl_tls13_postprocess_new_session_ticket().
+ * - POSTPROCESS_NEW_SESSION_TICKET_SIGNAL, all good, we have to signal the
+ *   application that a valid ticket has been received.
+ * - POSTPROCESS_NEW_SESSION_TICKET_DISCARD, no fatal error, we keep the
+ *   connection alive but we do not signal the ticket to the application.
+ */
+#define POSTPROCESS_NEW_SESSION_TICKET_SIGNAL 0
+#define POSTPROCESS_NEW_SESSION_TICKET_DISCARD 1
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl,
                                                     unsigned char *ticket_nonce,
@@ -2933,6 +2939,10 @@
     psa_algorithm_t psa_hash_alg;
     int hash_length;
 
+    if (session->ticket_lifetime == 0) {
+        return POSTPROCESS_NEW_SESSION_TICKET_DISCARD;
+    }
+
 #if defined(MBEDTLS_HAVE_TIME)
     /* Store ticket creation time */
     session->ticket_reception_time = mbedtls_ms_time();
@@ -2989,7 +2999,7 @@
         session, ssl->conf->tls13_kex_modes);
     MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);
 
-    return 0;
+    return POSTPROCESS_NEW_SESSION_TICKET_SIGNAL;
 }
 
 /*
@@ -3010,12 +3020,37 @@
                              ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET,
                              &buf, &buf_len));
 
+    /*
+     * We are about to update (maybe only partially) ticket data thus block
+     * any session export for the time being.
+     */
+    ssl->session->exported = 1;
+
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_new_session_ticket(
                              ssl, buf, buf + buf_len,
                              &ticket_nonce, &ticket_nonce_len));
 
-    MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_new_session_ticket(
-                             ssl, ticket_nonce, ticket_nonce_len));
+    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_postprocess_new_session_ticket(
+                                 ssl, ticket_nonce, ticket_nonce_len));
+
+    switch (ret) {
+        case POSTPROCESS_NEW_SESSION_TICKET_SIGNAL:
+            /*
+             * All good, we have received a new valid ticket, session data can
+             * be exported now and we signal the ticket to the application.
+             */
+            ssl->session->exported = 0;
+            ret = MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET;
+            break;
+
+        case POSTPROCESS_NEW_SESSION_TICKET_DISCARD:
+            ret = 0;
+            MBEDTLS_SSL_DEBUG_MSG(2, ("Discard new session ticket"));
+            break;
+
+        default:
+            ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
 
     mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);
 
@@ -3123,7 +3158,7 @@
                     1, ("Switch to early data keys for outbound traffic"));
                 mbedtls_ssl_set_outbound_transform(
                     ssl, ssl->handshake->transform_earlydata);
-                ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE;
+                ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE;
             }
             break;
 #endif /* MBEDTLS_SSL_EARLY_DATA */
@@ -3132,10 +3167,6 @@
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
         case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET:
             ret = ssl_tls13_process_new_session_ticket(ssl);
-            if (ret != 0) {
-                break;
-            }
-            ret = MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET;
             break;
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index bc73704..3be6db7 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -193,10 +193,12 @@
     idx = 64;
 
     if (from == MBEDTLS_SSL_IS_CLIENT) {
-        memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(client_cv));
+        memcpy(verify_buffer + idx, mbedtls_ssl_tls13_labels.client_cv,
+               MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv));
         idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv);
     } else { /* from == MBEDTLS_SSL_IS_SERVER */
-        memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(server_cv));
+        memcpy(verify_buffer + idx, mbedtls_ssl_tls13_labels.server_cv,
+               MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv));
         idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv);
     }
 
@@ -1454,6 +1456,54 @@
 
     return 0;
 }
+
+#if defined(MBEDTLS_SSL_SRV_C)
+int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl,
+                                           size_t early_data_len)
+{
+    /*
+     * This function should be called only while an handshake is in progress
+     * and thus a session under negotiation. Add a sanity check to detect a
+     * misuse.
+     */
+    if (ssl->session_negotiate == NULL) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    /* RFC 8446 section 4.6.1
+     *
+     * A server receiving more than max_early_data_size bytes of 0-RTT data
+     * SHOULD terminate the connection with an "unexpected_message" alert.
+     * Note that if it is still possible to send early_data_len bytes of early
+     * data, it means that early_data_len is smaller than max_early_data_size
+     * (type uint32_t) and can fit in an uint32_t. We use this further
+     * down.
+     */
+    if (early_data_len >
+        (ssl->session_negotiate->max_early_data_size -
+         ssl->total_early_data_size)) {
+
+        MBEDTLS_SSL_DEBUG_MSG(
+            2, ("EarlyData: Too much early data received, %u + %" MBEDTLS_PRINTF_SIZET " > %u",
+                ssl->total_early_data_size, early_data_len,
+                ssl->session_negotiate->max_early_data_size));
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
+            MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+    /*
+     * early_data_len has been checked to be less than max_early_data_size
+     * that is uint32_t. Its cast to an uint32_t below is thus safe. We need
+     * the cast to appease some compilers.
+     */
+    ssl->total_early_data_size += (uint32_t) early_data_len;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SRV_C */
 #endif /* MBEDTLS_SSL_EARLY_DATA */
 
 /* Reset SSL context and update hash for handling HRR.
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 3a968aa..6fe8cae 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -39,6 +39,63 @@
     return ciphersuite_info;
 }
 
+static void ssl_tls13_select_ciphersuite(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *cipher_suites,
+    const unsigned char *cipher_suites_end,
+    int psk_ciphersuite_id,
+    psa_algorithm_t psk_hash_alg,
+    const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info)
+{
+    *selected_ciphersuite_info = NULL;
+
+    /*
+     * In a compliant ClientHello the byte-length of the list of ciphersuites
+     * is even and this function relies on this fact. This should have been
+     * checked in the main ClientHello parsing function. Double check here.
+     */
+    if ((cipher_suites_end - cipher_suites) & 1) {
+        return;
+    }
+
+    for (const unsigned char *p = cipher_suites;
+         p < cipher_suites_end; p += 2) {
+        /*
+         * "cipher_suites_end - p is even" is an invariant of the loop. As
+         * cipher_suites_end - p > 0, we have cipher_suites_end - p >= 2 and it
+         * is thus safe to read two bytes.
+         */
+        uint16_t id = MBEDTLS_GET_UINT16_BE(p, 0);
+
+        const mbedtls_ssl_ciphersuite_t *info =
+            ssl_tls13_validate_peer_ciphersuite(ssl, id);
+        if (info == NULL) {
+            continue;
+        }
+
+        /*
+         * If a valid PSK ciphersuite identifier has been passed in, we want
+         * an exact match.
+         */
+        if (psk_ciphersuite_id != 0) {
+            if (id != psk_ciphersuite_id) {
+                continue;
+            }
+        } else if (psk_hash_alg != PSA_ALG_NONE) {
+            if (mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac) !=
+                psk_hash_alg) {
+                continue;
+            }
+        }
+
+        *selected_ciphersuite_info = info;
+        return;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%x",
+                              (unsigned) psk_ciphersuite_id, psk_hash_alg));
+}
+
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
 /* From RFC 8446:
  *
@@ -90,15 +147,37 @@
     return 0;
 }
 
-#define SSL_TLS1_3_OFFERED_PSK_NOT_MATCH   1
-#define SSL_TLS1_3_OFFERED_PSK_MATCH       0
+/*
+ * Non-error return values of
+ * ssl_tls13_offered_psks_check_identity_match_ticket() and
+ * ssl_tls13_offered_psks_check_identity_match(). They are positive to
+ * not collide with error codes that are negative. Zero
+ * (SSL_TLS1_3_PSK_IDENTITY_MATCH) in case of success as it may be propagated
+ * up by the callers of this function as a generic success condition.
+ *
+ * The return value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE means
+ * that the pre-shared-key identity matches that of a ticket or an externally-
+ * provisioned pre-shared-key. We have thus been able to retrieve the
+ * attributes of the pre-shared-key but at least one of them does not meet
+ * some criteria and the pre-shared-key cannot be used. For example, a ticket
+ * is expired or its version is not TLS 1.3. Note eventually that the return
+ * value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE does not have
+ * anything to do with binder check. A binder check is done only when a
+ * suitable pre-shared-key has been selected and only for that selected
+ * pre-shared-key: if the binder check fails, we fail the handshake and we do
+ * not try to find another pre-shared-key for which the binder check would
+ * succeed as recommended by the specification.
+ */
+#define SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH 2
+#define SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE 1
+#define SSL_TLS1_3_PSK_IDENTITY_MATCH 0
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl);
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl);
 
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_offered_psks_check_identity_match_ticket(
     mbedtls_ssl_context *ssl,
@@ -109,7 +188,6 @@
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *ticket_buffer;
-    unsigned int key_exchanges;
 #if defined(MBEDTLS_HAVE_TIME)
     mbedtls_ms_time_t now;
     mbedtls_ms_time_t server_age;
@@ -123,7 +201,7 @@
 
     /* Ticket parser is not configured, Skip */
     if (ssl->conf->f_ticket_parse == NULL || identity_len == 0) {
-        return 0;
+        return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
     }
 
     /* We create a copy of the encrypted ticket since the ticket parsing
@@ -133,63 +211,51 @@
      */
     ticket_buffer = mbedtls_calloc(1, identity_len);
     if (ticket_buffer == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small"));
         return MBEDTLS_ERR_SSL_ALLOC_FAILED;
     }
     memcpy(ticket_buffer, identity, identity_len);
 
-    if ((ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket,
-                                         session,
-                                         ticket_buffer, identity_len)) != 0) {
-        if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {
-            MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic"));
-        } else if (ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) {
+    ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket,
+                                    session,
+                                    ticket_buffer, identity_len);
+    switch (ret) {
+        case 0:
+            ret = SSL_TLS1_3_PSK_IDENTITY_MATCH;
+            break;
+
+        case MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED:
             MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is expired"));
-        } else {
+            ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE;
+            break;
+
+        case MBEDTLS_ERR_SSL_INVALID_MAC:
+            MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic"));
+            ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
+            break;
+
+        default:
             MBEDTLS_SSL_DEBUG_RET(1, "ticket_parse", ret);
-        }
+            ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
     }
 
     /* We delete the temporary buffer */
     mbedtls_free(ticket_buffer);
 
-    if (ret == 0 && session->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket TLS version is not 1.3."));
-        /* TODO: Define new return value for this case. */
-        ret = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
-    }
-
-    if (ret != 0) {
+    if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) {
         goto exit;
     }
 
-    /* RFC 8446 section 4.2.9
-     *
-     * Servers SHOULD NOT send NewSessionTicket with tickets that are not
-     * compatible with the advertised modes; however, if a server does so,
-     * the impact will just be that the client's attempts at resumption fail.
-     *
-     * We regard the ticket with incompatible key exchange modes as not match.
+    /*
+     * The identity matches that of a ticket. Now check that it has suitable
+     * attributes and bet it will not be the case.
      */
-    ret = MBEDTLS_ERR_ERROR_GENERIC_ERROR;
-    MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);
+    ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE;
 
-    key_exchanges = 0;
-    if (mbedtls_ssl_tls13_session_ticket_allow_psk_ephemeral(session) &&
-        ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) {
-        key_exchanges |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
-    }
-    if (mbedtls_ssl_tls13_session_ticket_allow_psk(session) &&
-        ssl_tls13_key_exchange_is_psk_available(ssl)) {
-        key_exchanges |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
-    }
-
-    if (key_exchanges == 0) {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("No suitable key exchange mode"));
+    if (session->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket TLS version is not 1.3."));
         goto exit;
     }
 
-    ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
 #if defined(MBEDTLS_HAVE_TIME)
     now = mbedtls_ms_time();
 
@@ -242,13 +308,15 @@
                 age_diff));
         goto exit;
     }
-
-    ret = 0;
-
 #endif /* MBEDTLS_HAVE_TIME */
 
+    /*
+     * All good, we have found a suitable ticket.
+     */
+    ret = SSL_TLS1_3_PSK_IDENTITY_MATCH;
+
 exit:
-    if (ret != 0) {
+    if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) {
         mbedtls_ssl_session_free(session);
     }
 
@@ -273,13 +341,11 @@
     *psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL;
 
     MBEDTLS_SSL_DEBUG_BUF(4, "identity", identity, identity_len);
-    ssl->handshake->resume = 0;
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    if (ssl_tls13_offered_psks_check_identity_match_ticket(
-            ssl, identity, identity_len, obfuscated_ticket_age,
-            session) == SSL_TLS1_3_OFFERED_PSK_MATCH) {
-        ssl->handshake->resume = 1;
+    ret = ssl_tls13_offered_psks_check_identity_match_ticket(
+        ssl, identity, identity_len, obfuscated_ticket_age, session);
+    if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH) {
         *psk_type = MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION;
         ret = mbedtls_ssl_set_hs_psk(ssl,
                                      session->resumption_key,
@@ -294,7 +360,9 @@
                               session->resumption_key_len);
         MBEDTLS_SSL_DEBUG_MSG(4, ("ticket: obfuscated_ticket_age: %u",
                                   (unsigned) obfuscated_ticket_age));
-        return SSL_TLS1_3_OFFERED_PSK_MATCH;
+        return SSL_TLS1_3_PSK_IDENTITY_MATCH;
+    } else if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE) {
+        return SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE;
     }
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
@@ -302,9 +370,9 @@
     if (ssl->conf->f_psk != NULL) {
         if (ssl->conf->f_psk(
                 ssl->conf->p_psk, ssl, identity, identity_len) == 0) {
-            return SSL_TLS1_3_OFFERED_PSK_MATCH;
+            return SSL_TLS1_3_PSK_IDENTITY_MATCH;
         }
-        return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH;
+        return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
     }
 
     MBEDTLS_SSL_DEBUG_BUF(5, "identity", identity, identity_len);
@@ -318,12 +386,20 @@
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret);
             return ret;
         }
-        return SSL_TLS1_3_OFFERED_PSK_MATCH;
+        return SSL_TLS1_3_PSK_IDENTITY_MATCH;
     }
 
-    return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH;
+    return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
 }
 
+/*
+ * Non-error return values of ssl_tls13_offered_psks_check_binder_match().
+ * They are positive to not collide with error codes that are negative. Zero
+ * (SSL_TLS1_3_BINDER_MATCH) in case of success as it may be propagated up
+ * by the callers of this function as a generic success condition.
+ */
+#define SSL_TLS1_3_BINDER_DOES_NOT_MATCH 1
+#define SSL_TLS1_3_BINDER_MATCH 0
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_offered_psks_check_binder_match(
     mbedtls_ssl_context *ssl,
@@ -338,6 +414,10 @@
     size_t psk_len;
     unsigned char server_computed_binder[PSA_HASH_MAX_SIZE];
 
+    if (binder_len != PSA_HASH_LENGTH(psk_hash_alg)) {
+        return SSL_TLS1_3_BINDER_DOES_NOT_MATCH;
+    }
+
     /* Get current state of handshake transcript. */
     ret = mbedtls_ssl_get_handshake_transcript(
         ssl, mbedtls_md_type_from_psa_alg(psk_hash_alg),
@@ -367,101 +447,19 @@
                           server_computed_binder, transcript_len);
     MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( received ): ", binder, binder_len);
 
-    if (mbedtls_ct_memcmp(server_computed_binder, binder, binder_len) == 0) {
-        return SSL_TLS1_3_OFFERED_PSK_MATCH;
+    if (mbedtls_ct_memcmp(server_computed_binder,
+                          binder,
+                          PSA_HASH_LENGTH(psk_hash_alg)) == 0) {
+        return SSL_TLS1_3_BINDER_MATCH;
     }
 
     mbedtls_platform_zeroize(server_computed_binder,
                              sizeof(server_computed_binder));
-    return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH;
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_select_ciphersuite_for_psk(
-    mbedtls_ssl_context *ssl,
-    const unsigned char *cipher_suites,
-    const unsigned char *cipher_suites_end,
-    uint16_t *selected_ciphersuite,
-    const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info)
-{
-    psa_algorithm_t psk_hash_alg = PSA_ALG_SHA_256;
-
-    *selected_ciphersuite = 0;
-    *selected_ciphersuite_info = NULL;
-
-    /* RFC 8446, page 55.
-     *
-     * For externally established PSKs, the Hash algorithm MUST be set when the
-     * PSK is established or default to SHA-256 if no such algorithm is defined.
-     *
-     */
-
-    /*
-     * Search for a matching ciphersuite
-     */
-    for (const unsigned char *p = cipher_suites;
-         p < cipher_suites_end; p += 2) {
-        uint16_t cipher_suite;
-        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-
-        cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0);
-        ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(ssl,
-                                                               cipher_suite);
-        if (ciphersuite_info == NULL) {
-            continue;
-        }
-
-        /* MAC of selected ciphersuite MUST be same with PSK binder if exist.
-         * Otherwise, client should reject.
-         */
-        if (psk_hash_alg ==
-            mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac)) {
-            *selected_ciphersuite = cipher_suite;
-            *selected_ciphersuite_info = ciphersuite_info;
-            return 0;
-        }
-    }
-    MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite"));
-    return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    return SSL_TLS1_3_BINDER_DOES_NOT_MATCH;
 }
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_select_ciphersuite_for_resumption(
-    mbedtls_ssl_context *ssl,
-    const unsigned char *cipher_suites,
-    const unsigned char *cipher_suites_end,
-    mbedtls_ssl_session *session,
-    uint16_t *selected_ciphersuite,
-    const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info)
-{
-
-    *selected_ciphersuite = 0;
-    *selected_ciphersuite_info = NULL;
-    for (const unsigned char *p = cipher_suites; p < cipher_suites_end; p += 2) {
-        uint16_t cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0);
-        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-
-        if (cipher_suite != session->ciphersuite) {
-            continue;
-        }
-
-        ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(ssl,
-                                                               cipher_suite);
-        if (ciphersuite_info == NULL) {
-            continue;
-        }
-
-        *selected_ciphersuite = cipher_suite;
-        *selected_ciphersuite_info = ciphersuite_info;
-
-        return 0;
-    }
-
-    return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_session_copy_ticket(mbedtls_ssl_session *dst,
                                          const mbedtls_ssl_session *src)
 {
@@ -475,12 +473,26 @@
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
     dst->max_early_data_size = src->max_early_data_size;
-#endif
+
+#if defined(MBEDTLS_SSL_ALPN)
+    int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn);
+    if (ret != 0) {
+        return ret;
+    }
+#endif /* MBEDTLS_SSL_ALPN */
+#endif /* MBEDTLS_SSL_EARLY_DATA*/
 
     return 0;
 }
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
+struct psk_attributes {
+    int type;
+    int key_exchange_mode;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+};
+#define PSK_ATTRIBUTES_INIT { 0, 0, NULL }
+
 /* Parser for pre_shared_key extension in client hello
  *    struct {
  *        opaque identity<1..2^16-1>;
@@ -507,7 +519,8 @@
     const unsigned char *pre_shared_key_ext,
     const unsigned char *pre_shared_key_ext_end,
     const unsigned char *ciphersuites,
-    const unsigned char *ciphersuites_end)
+    const unsigned char *ciphersuites_end,
+    struct psk_attributes *psk)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const unsigned char *identities = pre_shared_key_ext;
@@ -558,13 +571,12 @@
         uint32_t obfuscated_ticket_age;
         const unsigned char *binder;
         size_t binder_len;
-        int psk_type;
-        uint16_t cipher_suite;
-        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+        int psk_ciphersuite_id;
+        psa_algorithm_t psk_hash_alg;
+        int allowed_key_exchange_modes;
+
         mbedtls_ssl_session session;
         mbedtls_ssl_session_init(&session);
-#endif
 
         MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, identities_end, 2 + 1 + 4);
         identity_len = MBEDTLS_GET_UINT16_BE(p_identity_len, 0);
@@ -586,47 +598,74 @@
 
         ret = ssl_tls13_offered_psks_check_identity_match(
             ssl, identity, identity_len, obfuscated_ticket_age,
-            &psk_type, &session);
-        if (ret != SSL_TLS1_3_OFFERED_PSK_MATCH) {
+            &psk->type, &session);
+        if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) {
             continue;
         }
 
         MBEDTLS_SSL_DEBUG_MSG(4, ("found matched identity"));
-        switch (psk_type) {
+
+        switch (psk->type) {
             case MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL:
-                ret = ssl_tls13_select_ciphersuite_for_psk(
-                    ssl, ciphersuites, ciphersuites_end,
-                    &cipher_suite, &ciphersuite_info);
+                psk_ciphersuite_id = 0;
+                psk_hash_alg = PSA_ALG_SHA_256;
+                allowed_key_exchange_modes =
+                    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL;
                 break;
-            case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION:
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
-                ret = ssl_tls13_select_ciphersuite_for_resumption(
-                    ssl, ciphersuites, ciphersuites_end, &session,
-                    &cipher_suite, &ciphersuite_info);
-                if (ret != 0) {
-                    mbedtls_ssl_session_free(&session);
-                }
-#else
-                ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-#endif
+            case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION:
+                psk_ciphersuite_id = session.ciphersuite;
+                psk_hash_alg = PSA_ALG_NONE;
+                ssl->session_negotiate->ticket_flags = session.ticket_flags;
+                allowed_key_exchange_modes =
+                    session.ticket_flags &
+                    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL;
                 break;
+#endif
             default:
                 return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
-        if (ret != 0) {
-            /* See below, no cipher_suite available, abort handshake */
+
+        psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE;
+
+        if ((allowed_key_exchange_modes &
+             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) &&
+            ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) {
+            psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
+        } else if ((allowed_key_exchange_modes &
+                    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) &&
+                   ssl_tls13_key_exchange_is_psk_available(ssl)) {
+            psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
+        }
+
+        if (psk->key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("No suitable PSK key exchange mode"));
+            continue;
+        }
+
+        ssl_tls13_select_ciphersuite(ssl, ciphersuites, ciphersuites_end,
+                                     psk_ciphersuite_id, psk_hash_alg,
+                                     &psk->ciphersuite_info);
+
+        if (psk->ciphersuite_info == NULL) {
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+            mbedtls_ssl_session_free(&session);
+#endif
+            /*
+             * We consider finding a ciphersuite suitable for the PSK as part
+             * of the validation of its binder. Thus if we do not find one, we
+             * abort the handshake with a decrypt_error alert.
+             */
             MBEDTLS_SSL_PEND_FATAL_ALERT(
                 MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,
                 MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
-            MBEDTLS_SSL_DEBUG_RET(
-                2, "ssl_tls13_select_ciphersuite", ret);
-            return ret;
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
         }
 
         ret = ssl_tls13_offered_psks_check_binder_match(
-            ssl, binder, binder_len, psk_type,
-            mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac));
-        if (ret != SSL_TLS1_3_OFFERED_PSK_MATCH) {
+            ssl, binder, binder_len, psk->type,
+            mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) psk->ciphersuite_info->mac));
+        if (ret != SSL_TLS1_3_BINDER_MATCH) {
             /* For security reasons, the handshake should be aborted when we
              * fail to validate a binder value. See RFC 8446 section 4.2.11.2
              * and appendix E.6. */
@@ -644,13 +683,8 @@
 
         matched_identity = identity_id;
 
-        /* Update handshake parameters */
-        ssl->handshake->ciphersuite_info = ciphersuite_info;
-        ssl->session_negotiate->ciphersuite = cipher_suite;
-        MBEDTLS_SSL_DEBUG_MSG(2, ("overwrite ciphersuite: %04x - %s",
-                                  cipher_suite, ciphersuite_info->name));
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
-        if (psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
+        if (psk->type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
             ret = ssl_tls13_session_copy_ticket(ssl->session_negotiate,
                                                 &session);
             mbedtls_ssl_session_free(&session);
@@ -676,7 +710,7 @@
         return ret;
     }
     if (matched_identity == -1) {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("No matched PSK or ticket."));
+        MBEDTLS_SSL_DEBUG_MSG(3, ("No usable PSK or ticket."));
         return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
     }
 
@@ -1003,21 +1037,29 @@
 
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_ticket_is_kex_mode_permitted(mbedtls_ssl_context *ssl,
-                                                  unsigned int kex_mode)
+static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl)
 {
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    if (ssl->handshake->resume) {
-        if (!mbedtls_ssl_tls13_session_ticket_has_flags(
-                ssl->session_negotiate, kex_mode)) {
-            return 0;
-        }
-    }
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED)
+    return mbedtls_ssl_conf_tls13_is_psk_enabled(ssl) &&
+           mbedtls_ssl_tls13_is_psk_supported(ssl) &&
+           ssl_tls13_client_hello_has_exts_for_psk_key_exchange(ssl);
 #else
     ((void) ssl);
-    ((void) kex_mode);
+    return 0;
 #endif
-    return 1;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl)
+{
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
+    return mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl) &&
+           mbedtls_ssl_tls13_is_psk_ephemeral_supported(ssl) &&
+           ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(ssl);
+#else
+    ((void) ssl);
+    return 0;
+#endif
 }
 #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
 
@@ -1033,83 +1075,6 @@
 #endif
 }
 
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl)
-{
-#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED)
-    return ssl_tls13_ticket_is_kex_mode_permitted(
-        ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) &&
-           mbedtls_ssl_conf_tls13_is_psk_enabled(ssl) &&
-           mbedtls_ssl_tls13_is_psk_supported(ssl) &&
-           ssl_tls13_client_hello_has_exts_for_psk_key_exchange(ssl);
-#else
-    ((void) ssl);
-    return 0;
-#endif
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl)
-{
-#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
-    return ssl_tls13_ticket_is_kex_mode_permitted(
-        ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) &&
-           mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl) &&
-           mbedtls_ssl_tls13_is_psk_ephemeral_supported(ssl) &&
-           ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(ssl);
-#else
-    ((void) ssl);
-    return 0;
-#endif
-}
-
-static int ssl_tls13_determine_key_exchange_mode(mbedtls_ssl_context *ssl)
-{
-    /*
-     * Determine the key exchange algorithm to use.
-     * There are three types of key exchanges supported in TLS 1.3:
-     * - (EC)DH with ECDSA,
-     * - (EC)DH with PSK,
-     * - plain PSK.
-     *
-     * The PSK-based key exchanges may additionally be used with 0-RTT.
-     *
-     * Our built-in order of preference is
-     *  1 ) (EC)DHE-PSK Mode ( psk_ephemeral )
-     *  2 ) Certificate Mode ( ephemeral )
-     *  3 ) Plain PSK Mode ( psk )
-     */
-
-    ssl->handshake->key_exchange_mode =
-        MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE;
-
-    if (ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) {
-        ssl->handshake->key_exchange_mode =
-            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
-        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk_ephemeral"));
-    } else
-    if (ssl_tls13_key_exchange_is_ephemeral_available(ssl)) {
-        ssl->handshake->key_exchange_mode =
-            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;
-        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: ephemeral"));
-    } else
-    if (ssl_tls13_key_exchange_is_psk_available(ssl)) {
-        ssl->handshake->key_exchange_mode =
-            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
-        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk"));
-    } else {
-        MBEDTLS_SSL_DEBUG_MSG(
-            1,
-            ("ClientHello message misses mandatory extensions."));
-        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION,
-                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
-        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
-    }
-
-    return 0;
-
-}
-
 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
     defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
 
@@ -1301,6 +1266,8 @@
     int no_usable_share_for_key_agreement = 0;
 
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    int got_psk = 0;
+    struct psk_attributes psk = PSK_ATTRIBUTES_INIT;
     const unsigned char *pre_shared_key_ext = NULL;
     const unsigned char *pre_shared_key_ext_end = NULL;
 #endif
@@ -1464,37 +1431,20 @@
      */
     MBEDTLS_SSL_DEBUG_BUF(3, "client hello, list of cipher suites",
                           cipher_suites, cipher_suites_len);
-    for (const unsigned char *cipher_suites_p = cipher_suites;
-         cipher_suites_p < cipher_suites_end; cipher_suites_p += 2) {
-        uint16_t cipher_suite;
-        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
 
-        /*
-         * "cipher_suites_end - cipher_suites_p is even" is an invariant of the
-         * loop. As cipher_suites_end - cipher_suites_p > 0, we have
-         * cipher_suites_end - cipher_suites_p >= 2 and it is thus safe to read
-         * two bytes.
-         */
-        cipher_suite = MBEDTLS_GET_UINT16_BE(cipher_suites_p, 0);
-        ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(
-            ssl, cipher_suite);
-        if (ciphersuite_info == NULL) {
-            continue;
-        }
-
-        ssl->session_negotiate->ciphersuite = cipher_suite;
-        handshake->ciphersuite_info = ciphersuite_info;
-        MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %04x - %s",
-                                  cipher_suite,
-                                  ciphersuite_info->name));
-        break;
-    }
+    ssl_tls13_select_ciphersuite(ssl, cipher_suites, cipher_suites_end,
+                                 0, PSA_ALG_NONE, &handshake->ciphersuite_info);
 
     if (handshake->ciphersuite_info == NULL) {
         MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
                                      MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
         return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
     }
+    ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %04x - %s",
+                              ((unsigned) handshake->ciphersuite_info->id),
+                              handshake->ciphersuite_info->name));
 
     /* ...
      * opaque legacy_compression_methods<1..2^8-1>;
@@ -1734,10 +1684,11 @@
     /* Update checksum with either
      * - The entire content of the CH message, if no PSK extension is present
      * - The content up to but excluding the PSK extension, if present.
+     * Always parse the pre-shared-key extension when present in the
+     * ClientHello even if some pre-requisites for PSK key exchange modes are
+     * not met. That way we always validate the syntax of the extension.
      */
-    /* If we've settled on a PSK-based exchange, parse PSK identity ext */
-    if (ssl_tls13_key_exchange_is_psk_available(ssl) ||
-        ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) {
+    if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) {
         ret = handshake->update_checksum(ssl, buf,
                                          pre_shared_key_ext - buf);
         if (0 != ret) {
@@ -1748,10 +1699,11 @@
                                                  pre_shared_key_ext,
                                                  pre_shared_key_ext_end,
                                                  cipher_suites,
-                                                 cipher_suites_end);
-        if (ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) {
-            handshake->received_extensions &= ~MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY);
-        } else if (ret != 0) {
+                                                 cipher_suites_end,
+                                                 &psk);
+        if (ret == 0) {
+            got_psk = 1;
+        } else if (ret != MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) {
             MBEDTLS_SSL_DEBUG_RET(
                 1, "ssl_tls13_parse_pre_shared_key_ext", ret);
             return ret;
@@ -1766,12 +1718,68 @@
         }
     }
 
-    ret = ssl_tls13_determine_key_exchange_mode(ssl);
-    if (ret < 0) {
-        return ret;
+    /*
+     * Determine the key exchange algorithm to use.
+     * There are three types of key exchanges supported in TLS 1.3:
+     * - (EC)DH with ECDSA,
+     * - (EC)DH with PSK,
+     * - plain PSK.
+     *
+     * The PSK-based key exchanges may additionally be used with 0-RTT.
+     *
+     * Our built-in order of preference is
+     *  1 ) (EC)DHE-PSK Mode ( psk_ephemeral )
+     *  2 ) Certificate Mode ( ephemeral )
+     *  3 ) Plain PSK Mode ( psk )
+     */
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    if (got_psk && (psk.key_exchange_mode ==
+                    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL)) {
+        handshake->key_exchange_mode =
+            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
+        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk_ephemeral"));
+
+    } else
+#endif
+    if (ssl_tls13_key_exchange_is_ephemeral_available(ssl)) {
+        handshake->key_exchange_mode =
+            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;
+        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: ephemeral"));
+
+    }
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    else if (got_psk && (psk.key_exchange_mode ==
+                         MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK)) {
+        handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
+        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk"));
+    }
+#endif
+    else {
+        MBEDTLS_SSL_DEBUG_MSG(
+            1,
+            ("ClientHello message misses mandatory extensions."));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION,
+                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
     }
 
-    if (ssl->handshake->key_exchange_mode !=
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    if (handshake->key_exchange_mode &
+        MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL) {
+        handshake->ciphersuite_info = psk.ciphersuite_info;
+        ssl->session_negotiate->ciphersuite = psk.ciphersuite_info->id;
+
+        MBEDTLS_SSL_DEBUG_MSG(2, ("Select PSK ciphersuite: %04x - %s",
+                                  ((unsigned) psk.ciphersuite_info->id),
+                                  psk.ciphersuite_info->name));
+
+        if (psk.type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
+            handshake->resume = 1;
+        }
+    }
+#endif
+
+    if (handshake->key_exchange_mode !=
         MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) {
         hrr_required = (no_usable_share_for_key_agreement != 0);
     }
@@ -1815,7 +1823,6 @@
      * NOTE:
      *  - The TLS version number is checked in
      *    ssl_tls13_offered_psks_check_identity_match_ticket().
-     *  - ALPN is not checked for the time being (TODO).
      */
 
     if (handshake->selected_identity != 0) {
@@ -1842,6 +1849,28 @@
         return -1;
     }
 
+#if defined(MBEDTLS_SSL_ALPN)
+    const char *alpn = mbedtls_ssl_get_alpn_protocol(ssl);
+    size_t alpn_len;
+
+    if (alpn == NULL && ssl->session_negotiate->ticket_alpn == NULL) {
+        return 0;
+    }
+
+    if (alpn != NULL) {
+        alpn_len = strlen(alpn);
+    }
+
+    if (alpn == NULL ||
+        ssl->session_negotiate->ticket_alpn == NULL ||
+        alpn_len != strlen(ssl->session_negotiate->ticket_alpn) ||
+        (memcmp(alpn, ssl->session_negotiate->ticket_alpn, alpn_len) != 0)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("EarlyData: rejected, the selected ALPN is different "
+                                  "from the one associated with the pre-shared key."));
+        return -1;
+    }
+#endif
+
     return 0;
 }
 #endif /* MBEDTLS_SSL_EARLY_DATA */
@@ -1973,10 +2002,6 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *server_randbytes =
         ssl->handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN;
-    if (ssl->conf->f_rng == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
-        return MBEDTLS_ERR_SSL_NO_RNG;
-    }
 
     if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, server_randbytes,
                                 MBEDTLS_SERVER_HELLO_RANDOM_LEN)) != 0) {
@@ -2913,17 +2938,14 @@
     }
 
     if (ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA) {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("Received early data"));
-        /* RFC 8446 section 4.6.1
-         *
-         * A server receiving more than max_early_data_size bytes of 0-RTT data
-         * SHOULD terminate the connection with an "unexpected_message" alert.
-         *
-         * TODO: Add received data size check here.
-         */
         if (ssl->in_offt == NULL) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("Received early data"));
             /* Set the reading pointer */
             ssl->in_offt = ssl->in_msg;
+            ret = mbedtls_ssl_tls13_check_early_data_len(ssl, ssl->in_msglen);
+            if (ret != 0) {
+                return ret;
+            }
         }
         return SSL_GOT_EARLY_DATA;
     }
@@ -3085,6 +3107,7 @@
     return 0;
 }
 
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 /*
  * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET
  */
@@ -3114,7 +3137,6 @@
     return SSL_NEW_SESSION_TICKET_WRITE;
 }
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl,
                                                 unsigned char *ticket_nonce,
@@ -3141,11 +3163,21 @@
         ssl->conf->max_early_data_size > 0) {
         mbedtls_ssl_tls13_session_set_ticket_flags(
             session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA);
+        session->max_early_data_size = ssl->conf->max_early_data_size;
     }
 #endif /* MBEDTLS_SSL_EARLY_DATA */
 
     MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+    if (session->ticket_alpn == NULL) {
+        ret = mbedtls_ssl_session_set_ticket_alpn(session, ssl->alpn_chosen);
+        if (ret != 0) {
+            return ret;
+        }
+    }
+#endif
+
     /* Generate ticket_age_add */
     if ((ret = ssl->conf->f_rng(ssl->conf->p_rng,
                                 (unsigned char *) &session->ticket_age_add,
@@ -3275,20 +3307,21 @@
         MBEDTLS_SSL_DEBUG_RET(1, "write_ticket", ret);
         return ret;
     }
-    /* RFC 8446 4.6.1
+
+    /* RFC 8446 section 4.6.1
+     *
      *  ticket_lifetime:  Indicates the lifetime in seconds as a 32-bit
-     *      unsigned integer in network byte order from the time of ticket
-     *      issuance.  Servers MUST NOT use any value greater than
-     *      604800 seconds (7 days).  The value of zero indicates that the
-     *      ticket should be discarded immediately.  Clients MUST NOT cache
-     *      tickets for longer than 7 days, regardless of the ticket_lifetime,
-     *      and MAY delete tickets earlier based on local policy.  A server
-     *      MAY treat a ticket as valid for a shorter period of time than what
-     *      is stated in the ticket_lifetime.
+     *     unsigned integer in network byte order from the time of ticket
+     *     issuance.  Servers MUST NOT use any value greater than
+     *     604800 seconds (7 days) ...
      */
     if (ticket_lifetime > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME) {
-        ticket_lifetime = MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME;
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("Ticket lifetime (%u) is greater than 7 days.",
+                (unsigned int) ticket_lifetime));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
+
     MBEDTLS_PUT_UINT32_BE(ticket_lifetime, p, 0);
     MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime: %u",
                               (unsigned int) ticket_lifetime));
diff --git a/library/threading.c b/library/threading.c
index c28290f..85db243 100644
--- a/library/threading.c
+++ b/library/threading.c
@@ -150,6 +150,8 @@
 #endif
 #if defined(MBEDTLS_PSA_CRYPTO_C)
     mbedtls_mutex_init(&mbedtls_threading_key_slot_mutex);
+    mbedtls_mutex_init(&mbedtls_threading_psa_globaldata_mutex);
+    mbedtls_mutex_init(&mbedtls_threading_psa_rngdata_mutex);
 #endif
 }
 
@@ -166,6 +168,8 @@
 #endif
 #if defined(MBEDTLS_PSA_CRYPTO_C)
     mbedtls_mutex_free(&mbedtls_threading_key_slot_mutex);
+    mbedtls_mutex_free(&mbedtls_threading_psa_globaldata_mutex);
+    mbedtls_mutex_free(&mbedtls_threading_psa_rngdata_mutex);
 #endif
 }
 #endif /* MBEDTLS_THREADING_ALT */
@@ -184,6 +188,8 @@
 #endif
 #if defined(MBEDTLS_PSA_CRYPTO_C)
 mbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex MUTEX_INIT;
+mbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex MUTEX_INIT;
+mbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex MUTEX_INIT;
 #endif
 
 #endif /* MBEDTLS_THREADING_C */
diff --git a/programs/Makefile b/programs/Makefile
index 6baf465..8d1da6d 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -7,6 +7,9 @@
 DLOPEN_LDFLAGS ?=
 endif
 
+ifdef RECORD_PSA_STATUS_COVERAGE_LOG
+LOCAL_CFLAGS += -Werror -DRECORD_PSA_STATUS_COVERAGE_LOG
+endif
 DEP=${MBEDLIBS} ${MBEDTLS_TEST_OBJS}
 
 # Only build the dlopen test in shared library builds, and not when building
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 332befd..43133d9 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -3072,16 +3072,16 @@
                 frags++;
                 written += ret;
             } while (written < len);
-        }
 
 end_of_early_data:
 
-        buf[written] = '\0';
-        mbedtls_printf(
-            " %" MBEDTLS_PRINTF_SIZET " bytes of early data written in %" MBEDTLS_PRINTF_SIZET " fragments\n\n%s\n",
-            written,
-            frags,
-            (char *) buf);
+            buf[written] = '\0';
+            mbedtls_printf(
+                " %" MBEDTLS_PRINTF_SIZET " bytes of early data written in %" MBEDTLS_PRINTF_SIZET " fragments\n\n%s\n",
+                written,
+                frags,
+                (char *) buf);
+        }
 #endif /* MBEDTLS_SSL_EARLY_DATA */
 
         while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index f00a111..a5d2ed1 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -122,7 +122,8 @@
 #define DFL_SNI                 NULL
 #define DFL_ALPN_STRING         NULL
 #define DFL_GROUPS              NULL
-#define DFL_MAX_EARLY_DATA_SIZE 0
+#define DFL_EARLY_DATA          -1
+#define DFL_MAX_EARLY_DATA_SIZE ((uint32_t) -1)
 #define DFL_SIG_ALGS            NULL
 #define DFL_DHM_FILE            NULL
 #define DFL_TRANSPORT           MBEDTLS_SSL_TRANSPORT_STREAM
@@ -429,9 +430,10 @@
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
 #define USAGE_EARLY_DATA \
-    "    max_early_data_size=%%d default: -1 (disabled)\n"             \
-    "                            options: -1 (disabled), "           \
-    "                                     >= 0 (enabled, max amount of early data )\n"
+    "    early_data=%%d      default: library default\n" \
+    "                        options: 0 (disabled), 1 (enabled)\n" \
+    "    max_early_data_size=%%d default: library default\n" \
+    "                            options: max amount of early data\n"
 #else
 #define USAGE_EARLY_DATA ""
 #endif /* MBEDTLS_SSL_EARLY_DATA */
@@ -694,7 +696,10 @@
     const char *cid_val_renego; /* the CID to use for incoming messages
                                  * after renegotiation                      */
     int reproducible;           /* make communication reproducible          */
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    int early_data;               /* early data enablement flag             */
     uint32_t max_early_data_size; /* max amount of early data               */
+#endif
     int query_config_mode;      /* whether to read config                   */
     int use_srtp;               /* Support SRTP                             */
     int force_srtp_profile;     /* SRTP protection profile to use or all    */
@@ -1609,10 +1614,6 @@
     };
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
 
-#if defined(MBEDTLS_SSL_EARLY_DATA)
-    int tls13_early_data_enabled = MBEDTLS_SSL_EARLY_DATA_DISABLED;
-#endif
-
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
     mbedtls_memory_buffer_alloc_init(alloc_buf, sizeof(alloc_buf));
 #if defined(MBEDTLS_MEMORY_DEBUG)
@@ -1747,7 +1748,10 @@
     opt.sni                 = DFL_SNI;
     opt.alpn_string         = DFL_ALPN_STRING;
     opt.groups              = DFL_GROUPS;
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    opt.early_data          = DFL_EARLY_DATA;
     opt.max_early_data_size = DFL_MAX_EARLY_DATA_SIZE;
+#endif
     opt.sig_algs            = DFL_SIG_ALGS;
     opt.dhm_file            = DFL_DHM_FILE;
     opt.transport           = DFL_TRANSPORT;
@@ -1980,14 +1984,18 @@
         }
 #endif
 #if defined(MBEDTLS_SSL_EARLY_DATA)
-        else if (strcmp(p, "max_early_data_size") == 0) {
-            long long value = atoll(q);
-            tls13_early_data_enabled =
-                value >= 0 ? MBEDTLS_SSL_EARLY_DATA_ENABLED :
-                MBEDTLS_SSL_EARLY_DATA_DISABLED;
-            if (tls13_early_data_enabled) {
-                opt.max_early_data_size = atoi(q);
+        else if (strcmp(p, "early_data") == 0) {
+            switch (atoi(q)) {
+                case 0:
+                    opt.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED;
+                    break;
+                case 1:
+                    opt.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED;
+                    break;
+                default: goto usage;
             }
+        } else if (strcmp(p, "max_early_data_size") == 0) {
+            opt.max_early_data_size = (uint32_t) atoll(q);
         }
 #endif /* MBEDTLS_SSL_EARLY_DATA */
         else if (strcmp(p, "renegotiation") == 0) {
@@ -2805,8 +2813,10 @@
     }
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
-    mbedtls_ssl_conf_early_data(&conf, tls13_early_data_enabled);
-    if (tls13_early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) {
+    if (opt.early_data != DFL_EARLY_DATA) {
+        mbedtls_ssl_conf_early_data(&conf, opt.early_data);
+    }
+    if (opt.max_early_data_size != DFL_MAX_EARLY_DATA_SIZE) {
         mbedtls_ssl_conf_max_early_data_size(
             &conf, opt.max_early_data_size);
     }
diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt
index f91f786..0d43ffd 100644
--- a/programs/test/CMakeLists.txt
+++ b/programs/test/CMakeLists.txt
@@ -78,6 +78,9 @@
         target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
     endif()
 
+    # Request C11, required for memory poisoning
+    set_target_properties(${exe} PROPERTIES C_STANDARD 11)
+
     # This emulates "if ( ... IN_LIST ... )" which becomes available in CMake 3.3
     list(FIND executables_libs ${exe} exe_index)
     if (${exe_index} GREATER -1)
diff --git a/programs/test/metatest.c b/programs/test/metatest.c
index 5a45f71..c52e579 100644
--- a/programs/test/metatest.c
+++ b/programs/test/metatest.c
@@ -27,11 +27,14 @@
  */
 
 
+#include <mbedtls/debug.h>
 #include <mbedtls/platform.h>
 #include <mbedtls/platform_util.h>
 #include "test/helpers.h"
 #include "test/threading_helpers.h"
 #include "test/macros.h"
+#include "test/memory.h"
+#include "common.h"
 
 #include <stdio.h>
 #include <string.h>
@@ -59,6 +62,15 @@
     memset((void *) p, false_but_the_compiler_does_not_know, n);
 }
 
+/* Simulate an access to the given object, to avoid compiler optimizations
+ * in code that prepares or consumes the object. */
+static void do_nothing_with_object(void *p)
+{
+    (void) p;
+}
+void(*volatile do_nothing_with_object_but_the_compiler_does_not_know)(void *) =
+    do_nothing_with_object;
+
 
 /****************************************************************/
 /* Test framework features */
@@ -70,6 +82,41 @@
     mbedtls_test_fail("Forced test failure", __LINE__, __FILE__);
 }
 
+void meta_test_not_equal(const char *name)
+{
+    int left = 20;
+    int right = 10;
+
+    (void) name;
+
+    TEST_EQUAL(left, right);
+exit:
+    ;
+}
+
+void meta_test_not_le_s(const char *name)
+{
+    int left = 20;
+    int right = 10;
+
+    (void) name;
+
+    TEST_LE_S(left, right);
+exit:
+    ;
+}
+
+void meta_test_not_le_u(const char *name)
+{
+    size_t left = 20;
+    size_t right = 10;
+
+    (void) name;
+
+    TEST_LE_U(left, right);
+exit:
+    ;
+}
 
 /****************************************************************/
 /* Platform features */
@@ -143,6 +190,65 @@
     /* Leak of a heap object */
 }
 
+/* name = "test_memory_poison_%(start)_%(offset)_%(count)_%(direction)"
+ * Poison a region starting at start from an 8-byte aligned origin,
+ * encompassing count bytes. Access the region at offset from the start.
+ * %(start), %(offset) and %(count) are decimal integers.
+ * %(direction) is either the character 'r' for read or 'w' for write.
+ */
+void test_memory_poison(const char *name)
+{
+    size_t start = 0, offset = 0, count = 0;
+    char direction = 'r';
+    if (sscanf(name,
+               "%*[^0-9]%" MBEDTLS_PRINTF_SIZET
+               "%*[^0-9]%" MBEDTLS_PRINTF_SIZET
+               "%*[^0-9]%" MBEDTLS_PRINTF_SIZET
+               "_%c",
+               &start, &offset, &count, &direction) != 4) {
+        mbedtls_fprintf(stderr, "%s: Bad name format: %s\n", __func__, name);
+        return;
+    }
+
+    union {
+        long long ll;
+        unsigned char buf[32];
+    } aligned;
+    memset(aligned.buf, 'a', sizeof(aligned.buf));
+
+    if (start > sizeof(aligned.buf)) {
+        mbedtls_fprintf(stderr,
+                        "%s: start=%" MBEDTLS_PRINTF_SIZET
+                        " > size=%" MBEDTLS_PRINTF_SIZET,
+                        __func__, start, sizeof(aligned.buf));
+        return;
+    }
+    if (start + count > sizeof(aligned.buf)) {
+        mbedtls_fprintf(stderr,
+                        "%s: start+count=%" MBEDTLS_PRINTF_SIZET
+                        " > size=%" MBEDTLS_PRINTF_SIZET,
+                        __func__, start + count, sizeof(aligned.buf));
+        return;
+    }
+    if (offset >= count) {
+        mbedtls_fprintf(stderr,
+                        "%s: offset=%" MBEDTLS_PRINTF_SIZET
+                        " >= count=%" MBEDTLS_PRINTF_SIZET,
+                        __func__, offset, count);
+        return;
+    }
+
+    MBEDTLS_TEST_MEMORY_POISON(aligned.buf + start, count);
+
+    if (direction == 'w') {
+        aligned.buf[start + offset] = 'b';
+        do_nothing_with_object_but_the_compiler_does_not_know(aligned.buf);
+    } else {
+        do_nothing_with_object_but_the_compiler_does_not_know(aligned.buf);
+        mbedtls_printf("%u\n", (unsigned) aligned.buf[start + offset]);
+    }
+}
+
 
 /****************************************************************/
 /* Threading */
@@ -285,12 +391,31 @@
  */
 metatest_t metatests[] = {
     { "test_fail", "any", meta_test_fail },
+    { "test_not_equal", "any", meta_test_not_equal },
+    { "test_not_le_s", "any", meta_test_not_le_s },
+    { "test_not_le_u", "any", meta_test_not_le_u },
     { "null_dereference", "any", null_pointer_dereference },
     { "null_call", "any", null_pointer_call },
     { "read_after_free", "asan", read_after_free },
     { "double_free", "asan", double_free },
     { "read_uninitialized_stack", "msan", read_uninitialized_stack },
     { "memory_leak", "asan", memory_leak },
+    { "test_memory_poison_0_0_8_r", "poison", test_memory_poison },
+    { "test_memory_poison_0_0_8_w", "poison", test_memory_poison },
+    { "test_memory_poison_0_7_8_r", "poison", test_memory_poison },
+    { "test_memory_poison_0_7_8_w", "poison", test_memory_poison },
+    { "test_memory_poison_0_0_1_r", "poison", test_memory_poison },
+    { "test_memory_poison_0_0_1_w", "poison", test_memory_poison },
+    { "test_memory_poison_0_1_2_r", "poison", test_memory_poison },
+    { "test_memory_poison_0_1_2_w", "poison", test_memory_poison },
+    { "test_memory_poison_7_0_8_r", "poison", test_memory_poison },
+    { "test_memory_poison_7_0_8_w", "poison", test_memory_poison },
+    { "test_memory_poison_7_7_8_r", "poison", test_memory_poison },
+    { "test_memory_poison_7_7_8_w", "poison", test_memory_poison },
+    { "test_memory_poison_7_0_1_r", "poison", test_memory_poison },
+    { "test_memory_poison_7_0_1_w", "poison", test_memory_poison },
+    { "test_memory_poison_7_1_2_r", "poison", test_memory_poison },
+    { "test_memory_poison_7_1_2_w", "poison", test_memory_poison },
     { "mutex_lock_not_initialized", "pthread", mutex_lock_not_initialized },
     { "mutex_unlock_not_initialized", "pthread", mutex_unlock_not_initialized },
     { "mutex_free_not_initialized", "pthread", mutex_free_not_initialized },
diff --git a/scripts/code_style.py b/scripts/code_style.py
index 08ec4af..07952b6 100755
--- a/scripts/code_style.py
+++ b/scripts/code_style.py
@@ -51,6 +51,13 @@
     checks = re.findall(CHECK_CALL_RE, content)
     return frozenset(word for s in checks for word in s.split())
 
+# Check for comment string indicating an auto-generated file
+AUTOGEN_RE = re.compile(r"Warning[ :-]+This file is (now )?auto[ -]?generated",
+                        re.ASCII | re.IGNORECASE)
+def is_file_autogenerated(filename):
+    content = open(filename, encoding="utf-8").read()
+    return AUTOGEN_RE.search(content) is not None
+
 def get_src_files(since: Optional[str]) -> List[str]:
     """
     Use git to get a list of the source files.
@@ -85,7 +92,8 @@
     # 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)]
+                         filename in generated_files or
+                         is_file_autogenerated(filename))]
     return src_files
 
 def get_uncrustify_version() -> str:
diff --git a/scripts/common.make b/scripts/common.make
index 2714bcd..9908a3c 100644
--- a/scripts/common.make
+++ b/scripts/common.make
@@ -4,6 +4,18 @@
 MBEDTLS_PATH := ..
 endif
 
+ifeq (,$(wildcard $(MBEDTLS_PATH)/framework/exported.make))
+    # Use the define keyword to get a multi-line message.
+    # GNU make appends ".  Stop.", so tweak the ending of our message accordingly.
+    define error_message
+$(MBEDTLS_PATH)/framework/exported.make not found.
+Run `git submodule update --init` to fetch the submodule contents.
+This is a fatal error
+    endef
+    $(error $(error_message))
+endif
+include $(MBEDTLS_PATH)/framework/exported.make
+
 CFLAGS	?= -O2
 WARNING_CFLAGS ?= -Wall -Wextra -Wformat=2 -Wno-format-nonliteral
 WARNING_CXXFLAGS ?= -Wall -Wextra -Wformat=2 -Wno-format-nonliteral
diff --git a/scripts/config.py b/scripts/config.py
index ab0e5ea..c53f9e7 100755
--- a/scripts/config.py
+++ b/scripts/config.py
@@ -198,6 +198,7 @@
     'MBEDTLS_NO_UDBL_DIVISION', # influences anything that uses bignum
     'MBEDTLS_PSA_P256M_DRIVER_ENABLED', # influences SECP256R1 KeyGen/ECDH/ECDSA
     'MBEDTLS_PLATFORM_NO_STD_FUNCTIONS', # removes a feature
+    'MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS', # removes a feature
     'MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG', # behavior change + build dependency
     'MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER', # incompatible with USE_PSA_CRYPTO
     'MBEDTLS_PSA_CRYPTO_SPM', # platform dependency (PSA SPM)
diff --git a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers_no_static.c.jinja b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers_no_static.c.jinja
index 261cd2a..f612cf0 100644
--- a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers_no_static.c.jinja
+++ b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers_no_static.c.jinja
@@ -206,11 +206,11 @@
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
     switch( location )
     {
-#if defined(PSA_CRYPTO_DRIVER_TEST)
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
 {% with nest_indent=8 %}
 {% include "OS-template-opaque.jinja" -%}
 {% endwith -%}
-#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
         default:
             (void) slot_number;
             (void) key_buffer;
diff --git a/scripts/data_files/vs2013-app-template.vcxproj b/scripts/data_files/vs2017-app-template.vcxproj
similarity index 96%
rename from scripts/data_files/vs2013-app-template.vcxproj
rename to scripts/data_files/vs2017-app-template.vcxproj
index 2fe9cf3..36ca317 100644
--- a/scripts/data_files/vs2013-app-template.vcxproj
+++ b/scripts/data_files/vs2017-app-template.vcxproj
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Debug|Win32">

       <Configuration>Debug</Configuration>

@@ -37,23 +37,27 @@
     <ConfigurationType>Application</ConfigurationType>

     <UseDebugLibraries>true</UseDebugLibraries>

     <CharacterSet>Unicode</CharacterSet>

+    <PlatformToolset>v141</PlatformToolset>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

     <ConfigurationType>Application</ConfigurationType>

     <UseDebugLibraries>true</UseDebugLibraries>

     <CharacterSet>Unicode</CharacterSet>

+    <PlatformToolset>v141</PlatformToolset>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

     <ConfigurationType>Application</ConfigurationType>

     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

+    <PlatformToolset>v141</PlatformToolset>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

     <ConfigurationType>Application</ConfigurationType>

     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

+    <PlatformToolset>v141</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/scripts/data_files/vs2013-main-template.vcxproj b/scripts/data_files/vs2017-main-template.vcxproj
similarity index 96%
rename from scripts/data_files/vs2013-main-template.vcxproj
rename to scripts/data_files/vs2017-main-template.vcxproj
index 51861e1..448f9cd 100644
--- a/scripts/data_files/vs2013-main-template.vcxproj
+++ b/scripts/data_files/vs2017-main-template.vcxproj
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

   <ItemGroup Label="ProjectConfigurations">

     <ProjectConfiguration Include="Debug|Win32">

       <Configuration>Debug</Configuration>

@@ -28,23 +28,27 @@
     <ConfigurationType>StaticLibrary</ConfigurationType>

     <UseDebugLibraries>true</UseDebugLibraries>

     <CharacterSet>Unicode</CharacterSet>

+    <PlatformToolset>v141</PlatformToolset>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

     <ConfigurationType>StaticLibrary</ConfigurationType>

     <UseDebugLibraries>true</UseDebugLibraries>

     <CharacterSet>Unicode</CharacterSet>

+    <PlatformToolset>v141</PlatformToolset>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

     <ConfigurationType>StaticLibrary</ConfigurationType>

     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

+    <PlatformToolset>v141</PlatformToolset>

   </PropertyGroup>

   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

     <ConfigurationType>StaticLibrary</ConfigurationType>

     <UseDebugLibraries>false</UseDebugLibraries>

     <WholeProgramOptimization>true</WholeProgramOptimization>

     <CharacterSet>Unicode</CharacterSet>

+    <PlatformToolset>v141</PlatformToolset>

   </PropertyGroup>

   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

   <ImportGroup Label="ExtensionSettings">

diff --git a/scripts/data_files/vs2013-sln-template.sln b/scripts/data_files/vs2017-sln-template.sln
similarity index 92%
rename from scripts/data_files/vs2013-sln-template.sln
rename to scripts/data_files/vs2017-sln-template.sln
index 615ce04..80efb10 100644
--- a/scripts/data_files/vs2013-sln-template.sln
+++ b/scripts/data_files/vs2017-sln-template.sln
@@ -1,8 +1,8 @@
 

 Microsoft Visual Studio Solution File, Format Version 12.00

-# Visual Studio 2013

-VisualStudioVersion = 12.0.31101.0

-MinimumVisualStudioVersion = 10.0.40219.1

+# Visual Studio 2017

+VisualStudioVersion = 15.0.26228.4

+MinimumVisualStudioVersion = 15.0.26228.4

 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mbedTLS", "mbedTLS.vcxproj", "{46CF2D25-6A36-4189-B59C-E4815388E554}"

 EndProject

 APP_ENTRIES

diff --git a/scripts/generate_visualc_files.pl b/scripts/generate_visualc_files.pl
index 96ade2f..a0dfc57 100755
--- a/scripts/generate_visualc_files.pl
+++ b/scripts/generate_visualc_files.pl
@@ -1,7 +1,7 @@
 #!/usr/bin/env perl
 
 # Generate main file, individual apps and solution files for
-# MS Visual Studio 2013
+# MS Visual Studio 2017
 #
 # Must be run from Mbed TLS root or scripts directory.
 # Takes no argument.
@@ -13,12 +13,12 @@
 use strict;
 use Digest::MD5 'md5_hex';
 
-my $vsx_dir = "visualc/VS2013";
+my $vsx_dir = "visualc/VS2017";
 my $vsx_ext = "vcxproj";
-my $vsx_app_tpl_file = "scripts/data_files/vs2013-app-template.$vsx_ext";
-my $vsx_main_tpl_file = "scripts/data_files/vs2013-main-template.$vsx_ext";
+my $vsx_app_tpl_file = "scripts/data_files/vs2017-app-template.$vsx_ext";
+my $vsx_main_tpl_file = "scripts/data_files/vs2017-main-template.$vsx_ext";
 my $vsx_main_file = "$vsx_dir/mbedTLS.$vsx_ext";
-my $vsx_sln_tpl_file = "scripts/data_files/vs2013-sln-template.sln";
+my $vsx_sln_tpl_file = "scripts/data_files/vs2017-sln-template.sln";
 my $vsx_sln_file = "$vsx_dir/mbedTLS.sln";
 
 my $programs_dir = 'programs';
diff --git a/scripts/lcov.sh b/scripts/lcov.sh
index 0584a0a..9a0c582 100755
--- a/scripts/lcov.sh
+++ b/scripts/lcov.sh
@@ -39,13 +39,19 @@
 lcov_library_report () {
     rm -rf Coverage
     mkdir Coverage Coverage/tmp
-    lcov --capture --initial --directory $library_dir -o Coverage/tmp/files.info
-    lcov --rc lcov_branch_coverage=1 --capture --directory $library_dir -o Coverage/tmp/tests.info
-    lcov --rc lcov_branch_coverage=1 --add-tracefile Coverage/tmp/files.info --add-tracefile Coverage/tmp/tests.info -o Coverage/tmp/all.info
-    lcov --rc lcov_branch_coverage=1 --remove Coverage/tmp/all.info -o Coverage/tmp/final.info '*.h'
-    gendesc tests/Descriptions.txt -o Coverage/tmp/descriptions
-    genhtml --title "$title" --description-file Coverage/tmp/descriptions --keep-descriptions --legend --branch-coverage -o Coverage Coverage/tmp/final.info
-    rm -f Coverage/tmp/*.info Coverage/tmp/descriptions
+    # Pass absolute paths as lcov output files. This works around a bug
+    # whereby lcov tries to create the output file in the root directory
+    # if it has emitted a warning. A fix was released in lcov 1.13 in 2016.
+    # Ubuntu 16.04 is affected, 18.04 and above are not.
+    # https://github.com/linux-test-project/lcov/commit/632c25a0d1f5e4d2f4fd5b28ce7c8b86d388c91f
+    COVTMP=$PWD/Coverage/tmp
+    lcov --capture --initial --directory $library_dir -o "$COVTMP/files.info"
+    lcov --rc lcov_branch_coverage=1 --capture --directory $library_dir -o "$COVTMP/tests.info"
+    lcov --rc lcov_branch_coverage=1 --add-tracefile "$COVTMP/files.info" --add-tracefile "$COVTMP/tests.info" -o "$COVTMP/all.info"
+    lcov --rc lcov_branch_coverage=1 --remove "$COVTMP/all.info" -o "$COVTMP/final.info" '*.h'
+    gendesc tests/Descriptions.txt -o "$COVTMP/descriptions"
+    genhtml --title "$title" --description-file "$COVTMP/descriptions" --keep-descriptions --legend --branch-coverage -o Coverage "$COVTMP/final.info"
+    rm -f "$COVTMP/"*.info "$COVTMP/descriptions"
     echo "Coverage report in: Coverage/index.html"
 }
 
diff --git a/scripts/mbedtls_dev/asymmetric_key_data.py b/scripts/mbedtls_dev/asymmetric_key_data.py
index 8ca6758..175bc9f 100644
--- a/scripts/mbedtls_dev/asymmetric_key_data.py
+++ b/scripts/mbedtls_dev/asymmetric_key_data.py
@@ -137,6 +137,54 @@
   02818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3
  0203010001
 """),
+        1026: ("""
+3082025e
+ 020100
+ 02818102d09661fc74224ba7be7907abef4f5e8bcc264a802c978f7eaa5855ada05436d75db768d20f68595dbcc3d725b138e80b247e44a4163a0542fab612acbbde45f2e93894aa253bddef6a7becdc9cc29a99bacf48dc6e38db7a33e9ac924c520fc6be7d6e5646c1d67fb8b2b97ac60beecc3bb8e75bed8315aa3fe46f748a66d6ef
+ 0203010001
+ 0281806a4a346beba97f655fe834647d2944f5f40815e7302caf02ed179893c2d989395d5e877cacbf24a77a079d3db71580ccdbf63023d00f80e52f5c1a0716b323b7bfcbdc8a1781c44c4153e3da228d17b2dc78eb1f44cff60fe1150808a6e38ba2470aee2e948a6898ddadea56d9470927aca8d94a0338c11a8e95715b5f94e011
+ 024101f5418534c36236fc9fd38934d7c06dfed3829151ccab56b6330c641f7796a71924cf8119ca26e186ecd3068d6607a05260db4857651980436891adde9eb92ab7
+ 02410170042fbdbaba1e102b7f7f1dc9d940cfdcd85dd0ea65f543c6432e9c5480724bb49b1e5f80ca2b9f84cd6644bfb2e3d0968090b89f534dc2951e606db909dd89
+ 0241014b6c1aeb1c14a04ec04e5975fb015cb914984c054dd22bef24299939c514733f88bb3a9d16b04685b3a883b8923190ab672715d9d31add57b4983de1e8087e59
+ 02410117bf76f308b0560e00a2c864427dcd50b5161c2aa523a00f46f4e6c79b4c90958fd2a282028aac227477169888085a38c34f33b3c41934f1071db23b75ff53d1
+ 02410120a428b4e0c4a6f202920fd49cc9886e6b6719d40a3ad0604f5d5efd5ef6973a573ab324f38ecb8e669a69341597081e240b6ae4e2714887dd78dadaeb0b9216
+""", """
+308189
+ 02818102d09661fc74224ba7be7907abef4f5e8bcc264a802c978f7eaa5855ada05436d75db768d20f68595dbcc3d725b138e80b247e44a4163a0542fab612acbbde45f2e93894aa253bddef6a7becdc9cc29a99bacf48dc6e38db7a33e9ac924c520fc6be7d6e5646c1d67fb8b2b97ac60beecc3bb8e75bed8315aa3fe46f748a66d6ef
+ 0203010001
+"""),
+        1028: ("""
+3082025e
+ 020100
+ 0281810e62a76f0e0b59683a7ebf7cbfd37b1d1781d8f1b900604b507f0f04c72a3d340d067bcd53bea3caff4e4ae694f0b6d8f591a4167fbf7f372ab57e83a69a3f26f447bcf582bc9621a30a3b44d6b43e986d1a867b07489e4f9bfcadaa82a2782dc2729a631fb1fb9ffb794b4e53c76239e04d4a8f80352588db29462dde18237cf5
+ 0203010001
+ 02818101cfa0422e3bb60c15ef2e96db4499e789f5d634ea64567b2cdd6e2bdd121f85edccdee9b4ed178c5f33816101a7c371518b3e23f9fdc71b90242cd310b6b31428b0b64eb9596be0cc044cc85048982f90b706e66ccdd39ad5a1a7b64cf034eac0c35d7ace93f2bcd3ce243bd8f83b46f509ca2f805063002af2bb2d88b6ee36a9
+ 024103f0886d2977526f3f3f6a075600232ce3008517276dd3721dee08fd6c999fc976b9e8dd2bc143385fa4b48735ce81c66b501d7129ee7860cfbef23b5da91e6c2d
+ 024103a6c8734aace59d5f386f97de450f8a12d63ae6ac15d336e010c9fcf03a32f0611881ac6cd8b3f989925c0f025af26cf26aebd7d9b04eb503048dca2f503c28e9
+ 0241019b300451c3b47866f113e9a9c6a490c87c8dc6c2eca42902caea1f6907b97e0a4a02072aafc1185ae66c34345bddcd683361cda1aaf8a98009f9f8fa56d97081
+ 02401bcca849173d38e1e50ec48872ab54a2dcc621a80a7a1e8ea951287988718d5e85d90d64ab4926e9a575a168a385c421ad765813fc3f4af8cd00de7b6bba6e49
+ 0241036dcf69f6e548c8acfb536fb6cd186f8b8f20d313361d0447c1b5e380f4113e578b31e867dda47d44ad3761e793f725031b8d379f389de277a9a0137651df548a
+""", """
+308189
+ 0281810e62a76f0e0b59683a7ebf7cbfd37b1d1781d8f1b900604b507f0f04c72a3d340d067bcd53bea3caff4e4ae694f0b6d8f591a4167fbf7f372ab57e83a69a3f26f447bcf582bc9621a30a3b44d6b43e986d1a867b07489e4f9bfcadaa82a2782dc2729a631fb1fb9ffb794b4e53c76239e04d4a8f80352588db29462dde18237cf5
+ 0203010001
+"""),
+        1030: ("""
+3082025f
+ 020100
+ 0281812b7cd197f5796d1f8e576b2b37723fd9210814ef1c1995f9899d50058f379d239c66878e922f34c6ae3672c8598fcd5d47b764d2ec156e134d03cf6a94d38d2ea8bc76dbbc60c4b974219090eaf287497d7dcf7f119cfa867496f7e91c12b5d552e1d1461a80dbe9a59db3b016c6c0141c3b2a0e226089b855cb88ef656408bd89
+ 0203010001
+ 0281810210d5ff531cacb22f8cf7dd1fd9fb0376f3647f2e9ab3df9c89b9ad3c98e68b89adeb29901dd2f2cf2ac1f817726278830ec8a8d0fdd19d496ec6bc683671174786b7d6a8e822fa71d65ad35abbdf0e6e55ff2c1821b62bc630192160e5c9b3dcafc65ae6b2a088fbc5591da58a45dd7a30960f7d3def75b80cdf73247360e8fb
+ 0241072e371a3ba861e78e3eb9313065faab0a97216e9544bfc2d5b403844b43273705755a85aa0baf7114770cfeca20bca17ac19bc4cbba106a33b3dddca0fb535f33
+ 0241060e6af37ab4ea11f52b9344e7160eb2a53f1075e1229a7f10a301de3359f53e981ea0e17df0fb380f089e5c37dd40daa29eefd205f5c87b38f8fef636b57ba053
+ 0241023a5dd09ef83540b30b554d24f64f9c28d212068cfc62ffe26d53b605e05557a632ee9e90cfc56531f36aadd82be63bb8aa405a04d8bbe5281bc45883fed7b4af
+ 0241041de6dbad4caf5417a9504965201c4b99827de8f369f7456a84b3ef5c4ec9238c7a3d782a8915ebec643a698b5bee0af0c243592bce0042aadeaf49a4b4c6dd9b
+ 024105d32dee952b503b536fcecf19ec08236a9cd945c49551bf99f15b674fc21aa199f4c4211f0f0007c417c1fb4155326a2142fca454bbd38d6dbc6caa7ac335a17c
+""", """
+308189
+ 0281812b7cd197f5796d1f8e576b2b37723fd9210814ef1c1995f9899d50058f379d239c66878e922f34c6ae3672c8598fcd5d47b764d2ec156e134d03cf6a94d38d2ea8bc76dbbc60c4b974219090eaf287497d7dcf7f119cfa867496f7e91c12b5d552e1d1461a80dbe9a59db3b016c6c0141c3b2a0e226089b855cb88ef656408bd89
+ 0203010001
+"""),
         1536: ("""
 3082037b
  020100
@@ -153,5 +201,37 @@
  0281c100c870feb6ca6b1d2bd9f2dd99e20f1fe2d7e5192de662229dbe162bd1ba66336a7182903ca0b72796cd441c83d24bcdc3e9a2f5e4399c8a043f1c3ddf04754a66d4cfe7b3671a37dd31a9b4c13bfe06ee90f9d94ddaa06de67a52ac863e68f756736ceb014405a6160579640f831dddccc34ad0b05070e3f9954a58d1815813e1b83bcadba814789c87f1ef2ba5d738b793ec456a67360eea1b5faf1c7cc7bf24f3b2a9d0f8958b1096e0f0c335f8888d0c63a51c3c0337214fa3f5efdf6dcc35
  0203010001
 """),
+        2048: ("""
+308204a3
+ 020100
+ 0282010100f7bb6b8eab40491cd64455ec04d4ed8db5051a9738fc7af73ff3b097511cce40aaf76537b1353504427986b7b2b53a964a6937b558ec0d1dea274af2b8fff2f094c243fa577266a79db0c26ffe30416d23ef05dd5fecab413ebbb4f8526ae720a94584226b37d92ef463fc736cb38e530e7488d9162f5726807bc543138a2d258adb4d680221c2532381ccfa81bc89bc3d7b84039c2df41ce3ec8db91c2380e781ba3aa9e23b74ed9973d4908efca47aa8d9b7b0a4423297a404427c3f3cd6e0782e4553880f06ba39a64f4a7b0eef921a6050a207cefadcf07394a3e18ea915dc8497e7ae61fc3162f62f5065a692af077266f7360c2076cebeaf14cb22c1ed
+ 0203010001
+ 0282010000b8962dce604bc62e7678f48ca80cfff456ad36e2f6d329cc911a42ba7cf5b9b8f5aae1005e4a06f6e591279038d8508f2b62badfa5223da3cc94fa8360d5556f6d6852be75ea08135cac1834da719a4e7837e166d1d2c6c816b64661c10766b02f705cc4489f947428255835a909214341c21335ae12181dd81e611d59b1db70667bebd7e92b71e1d388318d3ec14d616f72c231f6727a183e6818285bd65f6572cadc9012248821b2d0ae6cedd30ca440d4d34cd77e2cf6b40ed2c7d856b30d474733fce0fb695c3e6530c079aed955e4073055f2655d4b671e291fde400f2f06d0b33f87d261e0ad3dae48a913841b34cfed03790fcaee00de2e90fb9621
+ 02818100fcbe89cd1aa319e49ef4f72149bf06da57dcc64d3de605e9ff3e76fc66f4b1e2878245ffd71990511b17e97f33818889a8c21b5527fd181327affe88f9bba670c4e6f1e6309bd0323074e4cbcf23dce3c19b8d5495f56a93059ba7414f28ed1ec906ad18c63de1148abcfe9be7986000f425e580b70e43e48e24fa9d51aaae4d
+ 02818100faec5a7bed2e53cfca1e167db4641db5a00fe2c328125423d594789f3ec072c623e7afbdee0089fd26307651f6d3611a88af28c34585d5cb713a650c35933f58944db9bd15ba9fc28b07e6705b7b3ef1ccb48d21a53569c8b84c444b61ea5c6e67b54f0afd852ffb8c92a111fab8677263eeb80cf1a3403b4a9a209776947221
+ 0281802ff99afeabc7b9ea83a1cc272d706d4494d8fb6b3e0ca3a2bf28843d74ed8db68a3258472ff5524792f4ff057e296059810717591ab61813cabcc57c0aab6bf48bebaa8f1f3af45212909dbd721c449996ee87ed3e69cf49090f7ab812e699dbf61ca64ec592895ef4d6db1d8ce08798a6bf6ac8fbf6613cc91e8bd3c0e4bd21
+ 02818100b29b34590bddb308afecb4c3ab78abf1114add755e7b956aa0677b6896a933c937db7dabaad2b565fd1df7caa5ef9629e5eb100fd6d7c9f372d846fee6cfb6025e25e934df57a4ca3c5e5637d9d6235ac80428852f6c92acae0a937e38e731fde0521d3e4c70d653ae9edc89c8b623e4379fbf606f4b6db8068528f7c70f2921
+ 0281800ed47ae05b275a23a7dfe3ffb727e3a268e626a59d401d2d846de26954ff54fc9ed93a9af33fac2c967a18e0f86145083e39923454bc10da5f4937e836b99851956bffb301ce9e06789786693213fcde6d5f2933d52bb29dc340ea011257788d3c5775eb6569230aafbf08752d40a8419de71b01d4927e27c1079caada0568b1
+               """, """
+3082010a
+ 0282010100f7bb6b8eab40491cd64455ec04d4ed8db5051a9738fc7af73ff3b097511cce40aaf76537b1353504427986b7b2b53a964a6937b558ec0d1dea274af2b8fff2f094c243fa577266a79db0c26ffe30416d23ef05dd5fecab413ebbb4f8526ae720a94584226b37d92ef463fc736cb38e530e7488d9162f5726807bc543138a2d258adb4d680221c2532381ccfa81bc89bc3d7b84039c2df41ce3ec8db91c2380e781ba3aa9e23b74ed9973d4908efca47aa8d9b7b0a4423297a404427c3f3cd6e0782e4553880f06ba39a64f4a7b0eef921a6050a207cefadcf07394a3e18ea915dc8497e7ae61fc3162f62f5065a692af077266f7360c2076cebeaf14cb22c1ed
+ 0203010001
+"""),
+        4096: ("""
+30820929
+ 020100
+ 0282020100cc8725f6b38d5d01aeeb07d36e03de4d31a0261ce74fe11a895ecfd13d168aee932af135ffbb849877273897081f3f7593c14ae82bc266c10544f726ae1ccf133d8a4018d380dfa25251c011107b7513a943346aa0e0dec11d8d7fa25644653c118daabce6d41f066f6621768801478055780e91b68ea3c95856d172a89032b39c824e8b7dc1a3f8aee4f6b368baa3cd68f50d52680117e9b913d7f8c852a0d1008e8b87a5c97e37afc11a080550557b8b4dcbd8e192ed3366d83a09d27c77e150f66855b5dcfdb2df151bd7f444250eaf6fe3f236826c81fa848101bfaad535ffb522d6ff97c9dd1e43b82cce2921d153c15450c4724ffd3efdca578e013650a03a5cf501fc58600fb5c860c0ef0cfe0ac0712d441313dca41a4d7d411e6c83b2151749d28be4692f62373db07e4a79051c5682ec20d491c4cfc7bc140f35fa15e5a1fa756d65b8ef93addf4c47c4a35b184f22a1ef089948f946f6faeb6470f26746e658cf9b4177417842e6d373558089aff721b930e9ec61b4f6a02c052c6924d39a5bbb15ed1106c4010f4dd69c79d042c8b31661b1ee486bc69db5f2f07a50d85b20699d601315625bb869629c7f4c5d48b211d097f438acec95973a38d421090af0f13484e4e94b8cb5efc18507f4b931df39987ffb2830293e4da381aaf70b3292952ef934e2b40fdebba3d9701b76e1be548274b2602d888537482d
+ 0203010001
+ 028202001a943e9c0089f0aa0116048a96abb486321a86916f82fb352460789fcfb1400550853e5afedc9ad6e877259cc4feb093c24b968534f89abb5f48aed8ad3c4bb1cba7cd7c1c724d3dae36770010b5068a334f2b3ee720c9f9ed320001f3f587f5662f939e605df519343d60c0635ccd32b188bc55f5d434173c9e6db2199341af833990e50246f99cddf79dd2c35babe14c103a76b8d2d98d73528f98c249b0a1f09155b31f599fc833542422a2342623bbbef4ac7ee605e2cdecf01fea25683bd4f66ca924ccef00418adff730c4714f66ffa2af0da3e5df7f539c634289fc12bc24093ec8f0ec180af0907cec1ebec911fa180fb5f3c80ed852896ad6e6b3eccb44de62193d52118cab2b171071d5fdaa7c4288fc7766d57774f4be46151bb90ace7c10c215f62ed26e52e6122436f532bd54fc08272adb216a2db433d5699c40ad58faa2660898ffccfc98002f8bb0361b4cf9ed6e93c1ca96d34a1ef40460f85918cfde4a8193b51ecea4b3903cae924a8fad5f8308954c9f19a7597bf0a75126a557e49f8bbd31fc4e8556f230640bf36204c6cf3d56dca5a41d860307ba6705a698681100a327f91739c486c470ba71d03d285314b0d7d04008e03f2a2b85e7c243d6fd9b97a02168c069ec572d3f0ca15ebcb1739f3a0b3c147a88e0b74f45a007ae927d6f822bf50b87b1e93fe7d9180bc6bc12bde6c8070d10c97331
+ 0282010100f50ebceac9d3c64482a8c265d6365461aa4a31a6a7633a24c8e34794ecdfcab1d6b52fb6a5f38055cc32d6a61b889550de27b3d0bd68b6d4fda041598ab98887143988576806b1c48720794902952ebe1bf0def65a0e6f94067056e6864fa2882e3a16f246282093d037639078182dd0a6eb21d3bad0637901a268b14c632c9d0b1690ed88abdde03f528247aa2e41557d0865ad34e53ff53ae0e5dea195d93fe65c25871f6f23adf34b6e960c2978f2b7475dafce6cbb26a53934d26c193d67f32de91035eeb89022beb7d5df784ac20ca6ab91bf6b775b6c9416f605b4841736cbfbd22ad98ab2e8428457e0793f5af40e550b48765d59e6e1b4a4a1f571f1
+ 0282010100d5a91d4d44bb9b73c1fe0248925e2c0ec1de51390bd8a73b453da51ae29325ae7657089fd4ee4a2fd96e345b57f672d7d484fde99189ab0a6365bf2b38680d6bb947f4b217be660323c26b86d643ae686d82e36ec00cfd038942443caa04a0f91e68ec717935b45e790311be56440d7176949594688ed1dd5c9103c57c158d05e4c37b98d81898030744a64f6ebdbf750aab79757e34dac422163ea7c0f42b97710c861978b24100385aad727e5f3836a74ea4bf1d36ef2a5edf9c9e8f996ef3191348450ea9f1d4a63db29cb06f63e5badb18e4d40f5112b658d1cc23cb65388aca03d141a6bc5fbd9429fe33d340d3e85bfa848908d60b562f894e8a337dfd
+ 0282010100c4950f0d95dc51d791ad094d223b3113abc49af1e2a361f83242c8a07a28c8744315d3f1c44c82edd0c21398eacb75648ae1f48885f92379d6ffa08cd11126a99d9acd79b8946e3486659185f511718ec5e1432b02714426cdc77e9eacade36735161a643dcd60dcd2922c47af5f4e196c5d8124555f67fca148048dfe062cbaca334f0d8daeb96d73be9f8e17c1c55d6bd0b9a7e99fe1dfba5cc16a07dbaa8c6d220c64c9dda114a0f029052b3a75b0d73fe3b2ed7821e5cd7307a1a95fd1f7ba8760c8454b7c38fbf65c88b01cd273ba2c55c3b477e426ae025a2cffc4a095f2ba4e0779a24b765b85489f2a0e79b95fc0c38e2a91f12ef65ca749ce369431
+ 028201002aa48e0c95e33bab66d4637048863314deec9819629be30499552c56a951e4fb64f309ed9c79d2a4aa28ac9a6e7be97fda1290fac4e94d11cdb4c8eabf5f450e72f4418a29e2fe493221e3840dcf8447a353b440ae63e93b83718e5ced31ef4ec91af7d5cdf3420478f27be019278be7515b665f305f10d3b55ddbfad64116dc4e4415aef3b234e4a5d6b5bab4c77a26c9f25f536bd4f0b4a478fc184f126c80d53742ac62c270e6b258a6b56b3365ecc28797a9ed12c1b91b265603ef751807bcc1747313f22729e1e3fe79f75cc3fb5dc7ccb81efacf9b847945a6109ecf9cf156505cbb55a3d317eb325661d18fe6bb416046837318053b365199334c03a1
+ 0282010100ee63706030a4ece9fe3bddcfc49f5a83f37f63ebcb29dbdc999f6ff54b596f115cf1eca09990108a439518e996f689fdde89b2c67edc04bf8e366734c2ae3017ec14e042050e7c656840146ca048394dcebe90dd2195349bbad306569031b2ef6e9171d2ae7797c8844e548394ca3b768d8496e99ef63abb59b0ff7fc70eb53153dd0f59018a275acba701f2c76a15c894f53461fedf65bc25c2c5cec396e556a1a919bc7a056393d50644126dcdef9256642e65a6043cbce9497e192cf2cb33648e117f41dbf01900acb93b0c78ddf31f381f4db3f9ccbbb69093dabf2e89dbbc0cb72f20c005a2519e3a874146495d7aacf3416a422e560986f22f39456e7f
+               """, """
+3082020a
+ 0282020100cc8725f6b38d5d01aeeb07d36e03de4d31a0261ce74fe11a895ecfd13d168aee932af135ffbb849877273897081f3f7593c14ae82bc266c10544f726ae1ccf133d8a4018d380dfa25251c011107b7513a943346aa0e0dec11d8d7fa25644653c118daabce6d41f066f6621768801478055780e91b68ea3c95856d172a89032b39c824e8b7dc1a3f8aee4f6b368baa3cd68f50d52680117e9b913d7f8c852a0d1008e8b87a5c97e37afc11a080550557b8b4dcbd8e192ed3366d83a09d27c77e150f66855b5dcfdb2df151bd7f444250eaf6fe3f236826c81fa848101bfaad535ffb522d6ff97c9dd1e43b82cce2921d153c15450c4724ffd3efdca578e013650a03a5cf501fc58600fb5c860c0ef0cfe0ac0712d441313dca41a4d7d411e6c83b2151749d28be4692f62373db07e4a79051c5682ec20d491c4cfc7bc140f35fa15e5a1fa756d65b8ef93addf4c47c4a35b184f22a1ef089948f946f6faeb6470f26746e658cf9b4177417842e6d373558089aff721b930e9ec61b4f6a02c052c6924d39a5bbb15ed1106c4010f4dd69c79d042c8b31661b1ee486bc69db5f2f07a50d85b20699d601315625bb869629c7f4c5d48b211d097f438acec95973a38d421090af0f13484e4e94b8cb5efc18507f4b931df39987ffb2830293e4da381aaf70b3292952ef934e2b40fdebba3d9701b76e1be548274b2602d888537482d
+ 0203010001
+"""),
     },
 })
diff --git a/scripts/mbedtls_dev/c_parsing_helper.py b/scripts/mbedtls_dev/c_parsing_helper.py
new file mode 100644
index 0000000..2657b7d
--- /dev/null
+++ b/scripts/mbedtls_dev/c_parsing_helper.py
@@ -0,0 +1,131 @@
+"""Helper functions to parse C code in heavily constrained scenarios.
+
+Currently supported functionality:
+
+* read_function_declarations: read function declarations from a header file.
+"""
+
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+### WARNING: the code in this file has not been extensively reviewed yet.
+### We do not think it is harmful, but it may be below our normal standards
+### for robustness and maintainability.
+
+import re
+from typing import Dict, Iterable, Iterator, List, Optional, Tuple
+
+
+class ArgumentInfo:
+    """Information about an argument to an API function."""
+    #pylint: disable=too-few-public-methods
+
+    _KEYWORDS = [
+        'const', 'register', 'restrict',
+        'int', 'long', 'short', 'signed', 'unsigned',
+    ]
+    _DECLARATION_RE = re.compile(
+        r'(?P<type>\w[\w\s*]*?)\s*' +
+        r'(?!(?:' + r'|'.join(_KEYWORDS) + r'))(?P<name>\b\w+\b)?' +
+        r'\s*(?P<suffix>\[[^][]*\])?\Z',
+        re.A | re.S)
+
+    @classmethod
+    def normalize_type(cls, typ: str) -> str:
+        """Normalize whitespace in a type."""
+        typ = re.sub(r'\s+', r' ', typ)
+        typ = re.sub(r'\s*\*', r' *', typ)
+        return typ
+
+    def __init__(self, decl: str) -> None:
+        self.decl = decl.strip()
+        m = self._DECLARATION_RE.match(self.decl)
+        if not m:
+            raise ValueError(self.decl)
+        self.type = self.normalize_type(m.group('type')) #type: str
+        self.name = m.group('name') #type: Optional[str]
+        self.suffix = m.group('suffix') if m.group('suffix') else '' #type: str
+
+
+class FunctionInfo:
+    """Information about an API function."""
+    #pylint: disable=too-few-public-methods
+
+    # Regex matching the declaration of a function that returns void.
+    VOID_RE = re.compile(r'\s*\bvoid\s*\Z', re.A)
+
+    def __init__(self, #pylint: disable=too-many-arguments
+                 filename: str,
+                 line_number: int,
+                 qualifiers: Iterable[str],
+                 return_type: str,
+                 name: str,
+                 arguments: List[str]) -> None:
+        self.filename = filename
+        self.line_number = line_number
+        self.qualifiers = frozenset(qualifiers)
+        self.return_type = return_type
+        self.name = name
+        self.arguments = [ArgumentInfo(arg) for arg in arguments]
+
+    def returns_void(self) -> bool:
+        """Whether the function returns void."""
+        return bool(self.VOID_RE.search(self.return_type))
+
+
+# Match one C comment.
+# Note that we match both comment types, so things like // in a /*...*/
+# comment are handled correctly.
+_C_COMMENT_RE = re.compile(r'//(?:[^\n]|\\\n)*|/\*.*?\*/', re.S)
+_NOT_NEWLINES_RE = re.compile(r'[^\n]+')
+
+def read_logical_lines(filename: str) -> Iterator[Tuple[int, str]]:
+    """Read logical lines from a file.
+
+    Logical lines are one or more physical line, with balanced parentheses.
+    """
+    with open(filename, encoding='utf-8') as inp:
+        content = inp.read()
+    # Strip comments, but keep newlines for line numbering
+    content = re.sub(_C_COMMENT_RE,
+                     lambda m: re.sub(_NOT_NEWLINES_RE, "", m.group(0)),
+                     content)
+    lines = enumerate(content.splitlines(), 1)
+    for line_number, line in lines:
+        # Read a logical line, containing balanced parentheses.
+        # We assume that parentheses are balanced (this should be ok
+        # since comments have been stripped), otherwise there will be
+        # a gigantic logical line at the end.
+        paren_level = line.count('(') - line.count(')')
+        while paren_level > 0:
+            _, more = next(lines) #pylint: disable=stop-iteration-return
+            paren_level += more.count('(') - more.count(')')
+            line += '\n' + more
+        yield line_number, line
+
+_C_FUNCTION_DECLARATION_RE = re.compile(
+    r'(?P<qualifiers>(?:(?:extern|inline|static)\b\s*)*)'
+    r'(?P<return_type>\w[\w\s*]*?)\s*' +
+    r'\b(?P<name>\w+)' +
+    r'\s*\((?P<arguments>.*)\)\s*;',
+    re.A | re.S)
+
+def read_function_declarations(functions: Dict[str, FunctionInfo],
+                               filename: str) -> None:
+    """Collect function declarations from a C header file."""
+    for line_number, line in read_logical_lines(filename):
+        m = _C_FUNCTION_DECLARATION_RE.match(line)
+        if not m:
+            continue
+        qualifiers = m.group('qualifiers').split()
+        return_type = m.group('return_type')
+        name = m.group('name')
+        arguments = m.group('arguments').split(',')
+        if len(arguments) == 1 and re.match(FunctionInfo.VOID_RE, arguments[0]):
+            arguments = []
+        # Note: we replace any existing declaration for the same name.
+        functions[name] = FunctionInfo(filename, line_number,
+                                       qualifiers,
+                                       return_type,
+                                       name,
+                                       arguments)
diff --git a/scripts/mbedtls_dev/c_wrapper_generator.py b/scripts/mbedtls_dev/c_wrapper_generator.py
new file mode 100644
index 0000000..3cf1e05
--- /dev/null
+++ b/scripts/mbedtls_dev/c_wrapper_generator.py
@@ -0,0 +1,473 @@
+"""Generate C wrapper functions.
+"""
+
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+### WARNING: the code in this file has not been extensively reviewed yet.
+### We do not think it is harmful, but it may be below our normal standards
+### for robustness and maintainability.
+
+import os
+import re
+import sys
+import typing
+from typing import Dict, List, Optional, Tuple
+
+from .c_parsing_helper import ArgumentInfo, FunctionInfo
+from . import typing_util
+
+
+def c_declare(prefix: str, name: str, suffix: str) -> str:
+    """Format a declaration of name with the given type prefix and suffix."""
+    if not prefix.endswith('*'):
+        prefix += ' '
+    return prefix + name + suffix
+
+
+WrapperInfo = typing.NamedTuple('WrapperInfo', [
+    ('argument_names', List[str]),
+    ('guard', Optional[str]),
+    ('wrapper_name', str),
+])
+
+
+class Base:
+    """Generate a C source file containing wrapper functions."""
+
+    # This class is designed to have many methods potentially overloaded.
+    # Tell pylint not to complain about methods that have unused arguments:
+    # child classes are likely to override those methods and need the
+    # arguments in question.
+    #pylint: disable=no-self-use,unused-argument
+
+    # Prefix prepended to the function's name to form the wrapper name.
+    _WRAPPER_NAME_PREFIX = ''
+    # Suffix appended to the function's name to form the wrapper name.
+    _WRAPPER_NAME_SUFFIX = '_wrap'
+
+    # Functions with one of these qualifiers are skipped.
+    _SKIP_FUNCTION_WITH_QUALIFIERS = frozenset(['inline', 'static'])
+
+    def __init__(self):
+        """Construct a wrapper generator object.
+        """
+        self.program_name = os.path.basename(sys.argv[0])
+        # To be populated in a derived class
+        self.functions = {} #type: Dict[str, FunctionInfo]
+        # Preprocessor symbol used as a guard against multiple inclusion in the
+        # header. Must be set before writing output to a header.
+        # Not used when writing .c output.
+        self.header_guard = None #type: Optional[str]
+
+    def _write_prologue(self, out: typing_util.Writable, header: bool) -> None:
+        """Write the prologue of a C file.
+
+        This includes a description comment and some include directives.
+        """
+        out.write("""/* Automatically generated by {}, do not edit! */
+
+/* Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+"""
+                  .format(self.program_name))
+        if header:
+            out.write("""
+#ifndef {guard}
+#define {guard}
+
+#ifdef __cplusplus
+extern "C" {{
+#endif
+"""
+                      .format(guard=self.header_guard))
+        out.write("""
+#include <mbedtls/build_info.h>
+""")
+
+    def _write_epilogue(self, out: typing_util.Writable, header: bool) -> None:
+        """Write the epilogue of a C file.
+        """
+        if header:
+            out.write("""
+#ifdef __cplusplus
+}}
+#endif
+
+#endif /* {guard} */
+"""
+                      .format(guard=self.header_guard))
+        out.write("""
+/* End of automatically generated file. */
+""")
+
+    def _wrapper_function_name(self, original_name: str) -> str:
+        """The name of the wrapper function.
+
+        By default, this adds a suffix.
+        """
+        return (self._WRAPPER_NAME_PREFIX +
+                original_name +
+                self._WRAPPER_NAME_SUFFIX)
+
+    def _wrapper_declaration_start(self,
+                                   function: FunctionInfo,
+                                   wrapper_name: str) -> str:
+        """The beginning of the wrapper function declaration.
+
+        This ends just before the opening parenthesis of the argument list.
+
+        This is a string containing at least the return type and the
+        function name. It may start with additional qualifiers or attributes
+        such as `static`, `__attribute__((...))`, etc.
+        """
+        return c_declare(function.return_type, wrapper_name, '')
+
+    def _argument_name(self,
+                       function_name: str,
+                       num: int,
+                       arg: ArgumentInfo) -> str:
+        """Name to use for the given argument in the wrapper function.
+
+        Argument numbers count from 0.
+        """
+        name = 'arg' + str(num)
+        if arg.name:
+            name += '_' + arg.name
+        return name
+
+    def _wrapper_declaration_argument(self,
+                                      function_name: str,
+                                      num: int, name: str,
+                                      arg: ArgumentInfo) -> str:
+        """One argument definition in the wrapper function declaration.
+
+        Argument numbers count from 0.
+        """
+        return c_declare(arg.type, name, arg.suffix)
+
+    def _underlying_function_name(self, function: FunctionInfo) -> str:
+        """The name of the underlying function.
+
+        By default, this is the name of the wrapped function.
+        """
+        return function.name
+
+    def _return_variable_name(self, function: FunctionInfo) -> str:
+        """The name of the variable that will contain the return value."""
+        return 'retval'
+
+    def _write_function_call(self, out: typing_util.Writable,
+                             function: FunctionInfo,
+                             argument_names: List[str]) -> None:
+        """Write the call to the underlying function.
+        """
+        # Note that the function name is in parentheses, to avoid calling
+        # a function-like macro with the same name, since in typical usage
+        # there is a function-like macro with the same name which is the
+        # wrapper.
+        call = '({})({})'.format(self._underlying_function_name(function),
+                                 ', '.join(argument_names))
+        if function.returns_void():
+            out.write('    {};\n'.format(call))
+        else:
+            ret_name = self._return_variable_name(function)
+            ret_decl = c_declare(function.return_type, ret_name, '')
+            out.write('    {} = {};\n'.format(ret_decl, call))
+
+    def _write_function_return(self, out: typing_util.Writable,
+                               function: FunctionInfo,
+                               if_void: bool = False) -> None:
+        """Write a return statement.
+
+        If the function returns void, only write a statement if if_void is true.
+        """
+        if function.returns_void():
+            if if_void:
+                out.write('    return;\n')
+        else:
+            ret_name = self._return_variable_name(function)
+            out.write('    return {};\n'.format(ret_name))
+
+    def _write_function_body(self, out: typing_util.Writable,
+                             function: FunctionInfo,
+                             argument_names: List[str]) -> None:
+        """Write the body of the wrapper code for the specified function.
+        """
+        self._write_function_call(out, function, argument_names)
+        self._write_function_return(out, function)
+
+    def _skip_function(self, function: FunctionInfo) -> bool:
+        """Whether to skip this function.
+
+        By default, static or inline functions are skipped.
+        """
+        if not self._SKIP_FUNCTION_WITH_QUALIFIERS.isdisjoint(function.qualifiers):
+            return True
+        return False
+
+    _FUNCTION_GUARDS = {
+    } #type: Dict[str, str]
+
+    def _function_guard(self, function: FunctionInfo) -> Optional[str]:
+        """A preprocessor condition for this function.
+
+        The wrapper will be guarded with `#if` on this condition, if not None.
+        """
+        return self._FUNCTION_GUARDS.get(function.name)
+
+    def _wrapper_info(self, function: FunctionInfo) -> Optional[WrapperInfo]:
+        """Information about the wrapper for one function.
+
+        Return None if the function should be skipped.
+        """
+        if self._skip_function(function):
+            return None
+        argument_names = [self._argument_name(function.name, num, arg)
+                          for num, arg in enumerate(function.arguments)]
+        return WrapperInfo(
+            argument_names=argument_names,
+            guard=self._function_guard(function),
+            wrapper_name=self._wrapper_function_name(function.name),
+        )
+
+    def _write_function_prototype(self, out: typing_util.Writable,
+                                  function: FunctionInfo,
+                                  wrapper: WrapperInfo,
+                                  header: bool) -> None:
+        """Write the prototype of a wrapper function.
+
+        If header is true, write a function declaration, with a semicolon at
+        the end. Otherwise just write the prototype, intended to be followed
+        by the function's body.
+        """
+        declaration_start = self._wrapper_declaration_start(function,
+                                                            wrapper.wrapper_name)
+        arg_indent = '    '
+        terminator = ';\n' if header else '\n'
+        if function.arguments:
+            out.write(declaration_start + '(\n')
+            for num in range(len(function.arguments)):
+                arg_def = self._wrapper_declaration_argument(
+                    function.name,
+                    num, wrapper.argument_names[num], function.arguments[num])
+                arg_terminator = \
+                    (')' + terminator if num == len(function.arguments) - 1 else
+                     ',\n')
+                out.write(arg_indent + arg_def + arg_terminator)
+        else:
+            out.write(declaration_start + '(void)' + terminator)
+
+    def _write_c_function(self, out: typing_util.Writable,
+                          function: FunctionInfo) -> None:
+        """Write wrapper code for one function.
+
+        Do nothing if the function is skipped.
+        """
+        wrapper = self._wrapper_info(function)
+        if wrapper is None:
+            return
+        out.write("""
+/* Wrapper for {} */
+"""
+                  .format(function.name))
+        if wrapper.guard is not None:
+            out.write('#if {}\n'.format(wrapper.guard))
+        self._write_function_prototype(out, function, wrapper, False)
+        out.write('{\n')
+        self._write_function_body(out, function, wrapper.argument_names)
+        out.write('}\n')
+        if wrapper.guard is not None:
+            out.write('#endif /* {} */\n'.format(wrapper.guard))
+
+    def _write_h_function_declaration(self, out: typing_util.Writable,
+                                      function: FunctionInfo,
+                                      wrapper: WrapperInfo) -> None:
+        """Write the declaration of one wrapper function.
+        """
+        self._write_function_prototype(out, function, wrapper, True)
+
+    def _write_h_macro_definition(self, out: typing_util.Writable,
+                                  function: FunctionInfo,
+                                  wrapper: WrapperInfo) -> None:
+        """Write the macro definition for one wrapper.
+        """
+        arg_list = ', '.join(wrapper.argument_names)
+        out.write('#define {function_name}({args}) \\\n    {wrapper_name}({args})\n'
+                  .format(function_name=function.name,
+                          wrapper_name=wrapper.wrapper_name,
+                          args=arg_list))
+
+    def _write_h_function(self, out: typing_util.Writable,
+                          function: FunctionInfo) -> None:
+        """Write the complete header content for one wrapper.
+
+        This is the declaration of the wrapper function, and the
+        definition of a function-like macro that calls the wrapper function.
+
+        Do nothing if the function is skipped.
+        """
+        wrapper = self._wrapper_info(function)
+        if wrapper is None:
+            return
+        out.write('\n')
+        if wrapper.guard is not None:
+            out.write('#if {}\n'.format(wrapper.guard))
+        self._write_h_function_declaration(out, function, wrapper)
+        self._write_h_macro_definition(out, function, wrapper)
+        if wrapper.guard is not None:
+            out.write('#endif /* {} */\n'.format(wrapper.guard))
+
+    def write_c_file(self, filename: str) -> None:
+        """Output a whole C file containing function wrapper definitions."""
+        with open(filename, 'w', encoding='utf-8') as out:
+            self._write_prologue(out, False)
+            for name in sorted(self.functions):
+                self._write_c_function(out, self.functions[name])
+            self._write_epilogue(out, False)
+
+    def _header_guard_from_file_name(self, filename: str) -> str:
+        """Preprocessor symbol used as a guard against multiple inclusion."""
+        # Heuristic to strip irrelevant leading directories
+        filename = re.sub(r'.*include[\\/]', r'', filename)
+        return re.sub(r'[^0-9A-Za-z]', r'_', filename, re.A).upper()
+
+    def write_h_file(self, filename: str) -> None:
+        """Output a header file with function wrapper declarations and macro definitions."""
+        self.header_guard = self._header_guard_from_file_name(filename)
+        with open(filename, 'w', encoding='utf-8') as out:
+            self._write_prologue(out, True)
+            for name in sorted(self.functions):
+                self._write_h_function(out, self.functions[name])
+            self._write_epilogue(out, True)
+
+
+class UnknownTypeForPrintf(Exception):
+    """Exception raised when attempting to generate code that logs a value of an unknown type."""
+
+    def __init__(self, typ: str) -> None:
+        super().__init__("Unknown type for printf format generation: " + typ)
+
+
+class Logging(Base):
+    """Generate wrapper functions that log the inputs and outputs."""
+
+    def __init__(self) -> None:
+        """Construct a wrapper generator including logging of inputs and outputs.
+
+        Log to stdout by default. Call `set_stream` to change this.
+        """
+        super().__init__()
+        self.stream = 'stdout'
+
+    def set_stream(self, stream: str) -> None:
+        """Set the stdio stream to log to.
+
+        Call this method before calling `write_c_output` or `write_h_output`.
+        """
+        self.stream = stream
+
+    def _write_prologue(self, out: typing_util.Writable, header: bool) -> None:
+        super()._write_prologue(out, header)
+        if not header:
+            out.write("""
+#if defined(MBEDTLS_FS_IO) && defined(MBEDTLS_TEST_HOOKS)
+#include <stdio.h>
+#include <inttypes.h>
+#include <mbedtls/debug.h> // for MBEDTLS_PRINTF_SIZET
+#include <mbedtls/platform.h> // for mbedtls_fprintf
+#endif /* defined(MBEDTLS_FS_IO) && defined(MBEDTLS_TEST_HOOKS) */
+""")
+
+    _PRINTF_SIMPLE_FORMAT = {
+        'int': '%d',
+        'long': '%ld',
+        'long long': '%lld',
+        'size_t': '%"MBEDTLS_PRINTF_SIZET"',
+        'unsigned': '0x%08x',
+        'unsigned int': '0x%08x',
+        'unsigned long': '0x%08lx',
+        'unsigned long long': '0x%016llx',
+    }
+
+    def _printf_simple_format(self, typ: str) -> Optional[str]:
+        """Use this printf format for a value of typ.
+
+        Return None if values of typ need more complex handling.
+        """
+        return self._PRINTF_SIMPLE_FORMAT.get(typ)
+
+    _PRINTF_TYPE_CAST = {
+        'int32_t': 'int',
+        'uint32_t': 'unsigned',
+        'uint64_t': 'unsigned long long',
+    } #type: Dict[str, str]
+
+    def _printf_type_cast(self, typ: str) -> Optional[str]:
+        """Cast values of typ to this type before passing them to printf.
+
+        Return None if values of the given type do not need a cast.
+        """
+        return self._PRINTF_TYPE_CAST.get(typ)
+
+    _POINTER_TYPE_RE = re.compile(r'\s*\*\Z')
+
+    def _printf_parameters(self, typ: str, var: str) -> Tuple[str, List[str]]:
+        """The printf format and arguments for a value of type typ stored in var.
+        """
+        expr = var
+        base_type = typ
+        # For outputs via a pointer, get the value that has been written.
+        # Note: we don't support pointers to pointers here.
+        pointer_match = self._POINTER_TYPE_RE.search(base_type)
+        if pointer_match:
+            base_type = base_type[:pointer_match.start(0)]
+            expr = '*({})'.format(expr)
+        # Maybe cast the value to a standard type.
+        cast_to = self._printf_type_cast(base_type)
+        if cast_to is not None:
+            expr = '({}) {}'.format(cast_to, expr)
+            base_type = cast_to
+        # Try standard types.
+        fmt = self._printf_simple_format(base_type)
+        if fmt is not None:
+            return '{}={}'.format(var, fmt), [expr]
+        raise UnknownTypeForPrintf(typ)
+
+    def _write_function_logging(self, out: typing_util.Writable,
+                                function: FunctionInfo,
+                                argument_names: List[str]) -> None:
+        """Write code to log the function's inputs and outputs."""
+        formats, values = '%s', ['"' + function.name + '"']
+        for arg_info, arg_name in zip(function.arguments, argument_names):
+            fmt, vals = self._printf_parameters(arg_info.type, arg_name)
+            if fmt:
+                formats += ' ' + fmt
+                values += vals
+        if not function.returns_void():
+            ret_name = self._return_variable_name(function)
+            fmt, vals = self._printf_parameters(function.return_type, ret_name)
+            if fmt:
+                formats += ' ' + fmt
+                values += vals
+        out.write("""\
+#if defined(MBEDTLS_FS_IO) && defined(MBEDTLS_TEST_HOOKS)
+    if ({stream}) {{
+        mbedtls_fprintf({stream}, "{formats}\\n",
+                        {values});
+    }}
+#endif /* defined(MBEDTLS_FS_IO) && defined(MBEDTLS_TEST_HOOKS) */
+"""
+                  .format(stream=self.stream,
+                          formats=formats,
+                          values=', '.join(values)))
+
+    def _write_function_body(self, out: typing_util.Writable,
+                             function: FunctionInfo,
+                             argument_names: List[str]) -> None:
+        """Write the body of the wrapper code for the specified function.
+        """
+        self._write_function_call(out, function, argument_names)
+        self._write_function_logging(out, function, argument_names)
+        self._write_function_return(out, function)
diff --git a/scripts/windows_msbuild.bat b/scripts/windows_msbuild.bat
index ff2b9f2..2bc6a51 100644
--- a/scripts/windows_msbuild.bat
+++ b/scripts/windows_msbuild.bat
@@ -14,7 +14,7 @@
 @rem vcvarsall.bat will silently change the directory to that directory.

 @rem Setting the VSCMD_START_DIR environment variable causes it to change

 @rem to that directory instead.

-set "VSCMD_START_DIR=%~dp0\..\visualc\VS2013"

+set "VSCMD_START_DIR=%~dp0\..\visualc\VS2017"

 

 "%vcvarsall%" x64 && ^

 msbuild /t:Rebuild /p:Configuration=%cfg%%retarget% /m mbedTLS.sln

diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 70f5bc9..589643a 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -252,6 +252,8 @@
     target_include_directories(test_suite_${data_name}
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../library)
+    # Request C11, which is needed for memory poisoning tests
+    set_target_properties(test_suite_${data_name} PROPERTIES C_STANDARD 11)
 
     if(${data_name} MATCHES ${SKIP_TEST_SUITES_REGEX})
         message(STATUS "The test suite ${data_name} will not be executed.")
diff --git a/tests/Makefile b/tests/Makefile
index f82c267..c2a0b84 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -208,6 +208,7 @@
 	s/\b(?=mbedtls_|psa_)/libtestdriver1_/g;
 endef
 
+libtestdriver1.a: export MBEDTLS_PATH := $(patsubst ../..//%,/%,../../$(MBEDTLS_PATH))
 libtestdriver1.a:
 	# Copy the library and fake a 3rdparty Makefile include.
 	rm -Rf ./libtestdriver1
diff --git a/tests/compat.sh b/tests/compat.sh
index ac29e50..20f2dbd 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -125,28 +125,34 @@
 print_test_case() {
     for i in $3; do
         uniform_title $1 $2 $i
-        echo $TITLE
+        echo "compat;$TITLE"
     done
 }
 
 # list_test_cases lists all potential test cases in compat.sh without execution
 list_test_cases() {
-    reset_ciphersuites
     for TYPE in $TYPES; do
+        reset_ciphersuites
         add_common_ciphersuites
         add_openssl_ciphersuites
         add_gnutls_ciphersuites
         add_mbedtls_ciphersuites
-    done
 
-    for VERIFY in $VERIFIES; do
-        VERIF=$(echo $VERIFY | tr '[:upper:]' '[:lower:]')
-        for MODE in $MODES; do
-            print_test_case m O "$O_CIPHERS"
-            print_test_case O m "$O_CIPHERS"
-            print_test_case m G "$G_CIPHERS"
-            print_test_case G m "$G_CIPHERS"
-            print_test_case m m "$M_CIPHERS"
+        # PSK cipher suites do not allow client certificate verification.
+        SUB_VERIFIES=$VERIFIES
+        if [ "$TYPE" = "PSK" ]; then
+            SUB_VERIFIES="NO"
+        fi
+
+        for VERIFY in $SUB_VERIFIES; do
+            VERIF=$(echo $VERIFY | tr '[:upper:]' '[:lower:]')
+            for MODE in $MODES; do
+                print_test_case m O "$O_CIPHERS"
+                print_test_case O m "$O_CIPHERS"
+                print_test_case m G "$G_CIPHERS"
+                print_test_case G m "$G_CIPHERS"
+                print_test_case m m "$M_CIPHERS"
+            done
         done
     done
 }
@@ -264,12 +270,6 @@
         # Ciphersuite for GnuTLS
         G_CIPHERS=$( filter "$G_CIPHERS" )
     fi
-
-    # For GnuTLS client -> Mbed TLS server,
-    # we need to force IPv4 by connecting to 127.0.0.1 but then auth fails
-    if is_dtls "$MODE" && [ "X$VERIFY" = "XYES" ]; then
-        G_CIPHERS=""
-    fi
 }
 
 reset_ciphersuites()
@@ -588,7 +588,18 @@
 # o_check_ciphersuite STANDARD_CIPHER_SUITE
 o_check_ciphersuite()
 {
-    if [ "${O_SUPPORT_ECDH}" = "NO" ]; then
+    # skip DTLS when lack of support was declared
+    if test "$OSSL_NO_DTLS" -gt 0 && is_dtls "$MODE"; then
+        SKIP_NEXT_="YES"
+    fi
+
+    # skip DTLS 1.2 is support was not detected
+    if [ "$O_SUPPORT_DTLS12" = "NO" -a "$MODE" = "dtls12" ]; then
+        SKIP_NEXT="YES"
+    fi
+
+    # skip static ECDH when OpenSSL doesn't support it
+    if [ "${O_SUPPORT_STATIC_ECDH}" = "NO" ]; then
         case "$1" in
             *ECDH_*) SKIP_NEXT="YES"
         esac
@@ -665,10 +676,25 @@
     esac
 
     case $($OPENSSL ciphers ALL) in
-        *ECDH-ECDSA*|*ECDH-RSA*) O_SUPPORT_ECDH="YES";;
-        *) O_SUPPORT_ECDH="NO";;
+        *ECDH-ECDSA*|*ECDH-RSA*) O_SUPPORT_STATIC_ECDH="YES";;
+        *) O_SUPPORT_STATIC_ECDH="NO";;
     esac
 
+    case $($OPENSSL ciphers ALL) in
+        *DES-CBC-*) O_SUPPORT_SINGLE_DES="YES";;
+        *) O_SUPPORT_SINGLE_DES="NO";;
+    esac
+
+    # OpenSSL <1.0.2 doesn't support DTLS 1.2. Check if OpenSSL
+    # supports -dtls1_2 from the s_server help. (The s_client
+    # help isn't accurate as of 1.0.2g: it supports DTLS 1.2
+    # but doesn't list it. But the s_server help seems to be
+    # accurate.)
+    O_SUPPORT_DTLS12="NO"
+    if $OPENSSL s_server -help 2>&1 | grep -q "^ *-dtls1_2 "; then
+        O_SUPPORT_DTLS12="YES"
+    fi
+
     if [ "X$VERIFY" = "XYES" ];
     then
         M_SERVER_ARGS="$M_SERVER_ARGS ca_file=data_files/test-ca_cat12.crt auth_mode=required"
@@ -939,13 +965,7 @@
             ;;
 
         [Gg]nu*)
-            # need to force IPv4 with UDP, but keep localhost for auth
-            if is_dtls "$MODE"; then
-                G_HOST="127.0.0.1"
-            else
-                G_HOST="localhost"
-            fi
-            CLIENT_CMD="$GNUTLS_CLI $G_CLIENT_ARGS --priority $G_PRIO_MODE:$3 $G_HOST"
+            CLIENT_CMD="$GNUTLS_CLI $G_CLIENT_ARGS --priority $G_PRIO_MODE:$3 localhost"
             log "$CLIENT_CMD"
             echo "$CLIENT_CMD" > $CLI_OUT
             printf 'GET HTTP/1.0\r\n\r\n' | $CLIENT_CMD >> $CLI_OUT 2>&1 &
@@ -1115,19 +1135,6 @@
 
                 [Oo]pen*)
 
-                    if test "$OSSL_NO_DTLS" -gt 0 && is_dtls "$MODE"; then
-                        continue;
-                    fi
-
-                    # OpenSSL <1.0.2 doesn't support DTLS 1.2. Check if OpenSSL
-                    # supports $O_MODE from the s_server help. (The s_client
-                    # help isn't accurate as of 1.0.2g: it supports DTLS 1.2
-                    # but doesn't list it. But the s_server help seems to be
-                    # accurate.)
-                    if ! $OPENSSL s_server -help 2>&1 | grep -q "^ *-$O_MODE "; then
-                        continue;
-                    fi
-
                     reset_ciphersuites
                     add_common_ciphersuites
                     add_openssl_ciphersuites
diff --git a/tests/configs/user-config-for-test.h b/tests/configs/user-config-for-test.h
index 639496b..f40f838 100644
--- a/tests/configs/user-config-for-test.h
+++ b/tests/configs/user-config-for-test.h
@@ -37,24 +37,61 @@
 #endif
 
 /* Use the accelerator driver for all cryptographic mechanisms for which
- * the test driver implemented. */
+ * the test driver is implemented. This is copied from psa/crypto_config.h
+ * with the parts not implemented by the test driver commented out. */
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DERIVE
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_PASSWORD
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_PASSWORD_HASH
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_HMAC
 #define MBEDTLS_PSA_ACCEL_KEY_TYPE_AES
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA
 #define MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DES
 #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY
 #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC
 #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT
 #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT
 #define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE
-#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR
+//#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RAW_DATA
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY
+
 #define MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING
 #define MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7
-#define MBEDTLS_PSA_ACCEL_ALG_CTR
+#define MBEDTLS_PSA_ACCEL_ALG_CCM
+#define MBEDTLS_PSA_ACCEL_ALG_CCM_STAR_NO_TAG
+#define MBEDTLS_PSA_ACCEL_ALG_CMAC
 #define MBEDTLS_PSA_ACCEL_ALG_CFB
-#define MBEDTLS_PSA_ACCEL_ALG_ECDSA
+#define MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305
+#define MBEDTLS_PSA_ACCEL_ALG_CTR
 #define MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA
+#define MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING
+#define MBEDTLS_PSA_ACCEL_ALG_ECDH
+#define MBEDTLS_PSA_ACCEL_ALG_FFDH
+#define MBEDTLS_PSA_ACCEL_ALG_ECDSA
+#define MBEDTLS_PSA_ACCEL_ALG_JPAKE
+#define MBEDTLS_PSA_ACCEL_ALG_GCM
+//#define MBEDTLS_PSA_ACCEL_ALG_HKDF
+//#define MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT
+//#define MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND
+#define MBEDTLS_PSA_ACCEL_ALG_HMAC
 #define MBEDTLS_PSA_ACCEL_ALG_MD5
 #define MBEDTLS_PSA_ACCEL_ALG_OFB
+//#define MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC
+//#define MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128
 #define MBEDTLS_PSA_ACCEL_ALG_RIPEMD160
+#define MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP
+#define MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT
 #define MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN
 #define MBEDTLS_PSA_ACCEL_ALG_RSA_PSS
 #define MBEDTLS_PSA_ACCEL_ALG_SHA_1
@@ -62,9 +99,14 @@
 #define MBEDTLS_PSA_ACCEL_ALG_SHA_256
 #define MBEDTLS_PSA_ACCEL_ALG_SHA_384
 #define MBEDTLS_PSA_ACCEL_ALG_SHA_512
-#define MBEDTLS_PSA_ACCEL_ALG_XTS
-#define MBEDTLS_PSA_ACCEL_ALG_CMAC
-#define MBEDTLS_PSA_ACCEL_ALG_HMAC
+#define MBEDTLS_PSA_ACCEL_ALG_SHA3_224
+#define MBEDTLS_PSA_ACCEL_ALG_SHA3_256
+#define MBEDTLS_PSA_ACCEL_ALG_SHA3_384
+#define MBEDTLS_PSA_ACCEL_ALG_SHA3_512
+#define MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER
+//#define MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF
+//#define MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS
+//#define MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS
 
 #endif  /* PSA_CRYPTO_DRIVER_TEST_ALL */
 
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index d6df19c..bbbfa9c 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -706,17 +706,43 @@
 ### Password used for PKCS8-encoded encrypted RSA keys
 keys_rsa_pkcs8_pwd = PolarSSLTest
 
-### Basic 1024-, 2048- and 4096-bit unencrypted RSA keys from which
+### Basic unencrypted RSA keys from which
 ### all other encrypted RSA keys are derived.
+keys_rsa_base =
+### TODO: the commands require OpenSSL 1.x to work as desired. With
+### OpenSSL 3.x, they produce pkcs8 files.
+rsa_pkcs1_768_clear.pem:
+	$(OPENSSL) genrsa -out $@ 768
+keys_rsa_base += rsa_pkcs1_768_clear.pem
+rsa_pkcs1_769_clear.pem:
+	$(OPENSSL) genrsa -out $@ 769
+keys_rsa_base += rsa_pkcs1_769_clear.pem
+rsa_pkcs1_770_clear.pem:
+	$(OPENSSL) genrsa -out $@ 770
+keys_rsa_base += rsa_pkcs1_770_clear.pem
+rsa_pkcs1_776_clear.pem:
+	$(OPENSSL) genrsa -out $@ 776
+keys_rsa_base += rsa_pkcs1_776_clear.pem
+rsa_pkcs1_784_clear.pem:
+	$(OPENSSL) genrsa -out $@ 784
+keys_rsa_base += rsa_pkcs1_784_clear.pem
 rsa_pkcs1_1024_clear.pem:
 	$(OPENSSL) genrsa -out $@ 1024
-all_final += rsa_pkcs1_1024_clear.pem
+keys_rsa_base += rsa_pkcs1_1024_clear.pem
 rsa_pkcs1_2048_clear.pem:
 	$(OPENSSL) genrsa -out $@ 2048
-all_final += rsa_pkcs1_2048_clear.pem
+keys_rsa_base += rsa_pkcs1_2048_clear.pem
 rsa_pkcs1_4096_clear.pem:
 	$(OPENSSL) genrsa -out $@ 4096
-all_final += rsa_pkcs1_4096_clear.pem
+keys_rsa_base += rsa_pkcs1_4096_clear.pem
+
+all_final += $(keys_rsa_base)
+
+### PKCS1-encoded, plaintext RSA keys in derived forms
+
+rsa_pkcs1_%.der: rsa_pkcs1_%.pem
+	$(OPENSSL) pkey -inform PEM -in $< -outform DER -out $@
+all_final += $(keys_rsa_base:.pem=.der)
 
 ###
 ### PKCS1-encoded, encrypted RSA keys
@@ -1170,8 +1196,8 @@
 ### Rules to generate all RSA keys from a particular class
 ###
 
-### Generate basic unencrypted RSA keys
-keys_rsa_unenc: rsa_pkcs1_1024_clear.pem rsa_pkcs1_2048_clear.pem rsa_pkcs1_4096_clear.pem
+### Generate cleartext RSA keys in derived formats
+keys_rsa_cleartext: $(keys_rsa_base) $(keys_rsa_base:.pem=.der)
 
 ### Generate PKCS1-encoded encrypted RSA keys
 keys_rsa_enc_basic: keys_rsa_enc_basic_1024 keys_rsa_enc_basic_2048 keys_rsa_enc_basic_4096
@@ -1183,7 +1209,8 @@
 keys_rsa_enc_pkcs8_v2: keys_rsa_enc_pkcs8_v2_1024 keys_rsa_enc_pkcs8_v2_2048 keys_rsa_enc_pkcs8_v2_4096 keys_rsa_enc_pkcs8_v2_1024_sha224 keys_rsa_enc_pkcs8_v2_2048_sha224 keys_rsa_enc_pkcs8_v2_4096_sha224 keys_rsa_enc_pkcs8_v2_1024_sha256 keys_rsa_enc_pkcs8_v2_2048_sha256 keys_rsa_enc_pkcs8_v2_4096_sha256 keys_rsa_enc_pkcs8_v2_1024_sha384 keys_rsa_enc_pkcs8_v2_2048_sha384 keys_rsa_enc_pkcs8_v2_4096_sha384 keys_rsa_enc_pkcs8_v2_1024_sha512 keys_rsa_enc_pkcs8_v2_2048_sha512 keys_rsa_enc_pkcs8_v2_4096_sha512
 
 ### Generate all RSA keys
-keys_rsa_all: keys_rsa_unenc keys_rsa_enc_basic keys_rsa_enc_pkcs8_v1 keys_rsa_enc_pkcs8_v2
+keys_rsa_all: keys_rsa_base keys_rsa_cleartext
+keys_rsa_all: keys_rsa_enc_basic keys_rsa_enc_pkcs8_v1 keys_rsa_enc_pkcs8_v2
 
 ################################################################
 #### Generate various EC keys
@@ -1765,6 +1792,22 @@
 	$(MBEDTLS_CERT_WRITE) request_file=server2.req.sha256 serial=2 issuer_crt=$(test_ca_crt) issuer_key=$(test_ca_key_file_rsa) issuer_pwd=$(test_ca_pwd_rsa) not_before=20190210144406 not_after=20290210144406 md=SHA256 version=3 output_file=$@
 all_final += server2-sha256.crt
 
+server2-sha256.ku-ka.crt: SERVER2_CRT_SERIAL=22
+server2-sha256.ku-ka.crt: SERVER2_KEY_USAGE=key_agreement
+server2-sha256.ku-ke.crt: SERVER2_CRT_SERIAL=23
+server2-sha256.ku-ke.crt: SERVER2_KEY_USAGE=key_encipherment
+server2-sha256.ku-ds.crt: SERVER2_CRT_SERIAL=24
+server2-sha256.ku-ds.crt: SERVER2_KEY_USAGE=digital_signature
+server2-sha256.ku-ds_ke.crt: SERVER2_CRT_SERIAL=28
+server2-sha256.ku-ds_ke.crt: SERVER2_KEY_USAGE=digital_signature,key_encipherment
+server2-sha256.ku-%.crt: server2.req.sha256
+	$(MBEDTLS_CERT_WRITE) request_file=server2.req.sha256 serial=$(SERVER2_CRT_SERIAL) \
+		issuer_crt=$(test_ca_crt) issuer_key=$(test_ca_key_file_rsa) issuer_pwd=$(test_ca_pwd_rsa) \
+		key_usage="$(SERVER2_KEY_USAGE)" \
+		not_before=20190210144406 not_after=20290210144406 md=SHA256 version=3 output_file=$@
+all_final += server2-sha256.ku-ka.crt server2-sha256.ku-ke.crt server2-sha256.ku-ds.crt server2-sha256.ku-ds_ke.crt
+
+all_final += server2.ku-ka.crt server2.ku-ke.crt server2.ku-ds.crt server2.ku-ds_ke.crt
 server2.ku-ka.crt: SERVER2_CRT_SERIAL=42
 server2.ku-ka.crt: SERVER2_KEY_USAGE=key_agreement
 server2.ku-ke.crt: SERVER2_CRT_SERIAL=43
@@ -2161,7 +2204,7 @@
 
 .PHONY: default all_final all
 .PHONY: keys_rsa_all
-.PHONY: keys_rsa_unenc keys_rsa_enc_basic
+.PHONY: keys_rsa_enc_basic
 .PHONY: keys_rsa_enc_pkcs8_v1 keys_rsa_enc_pkcs8_v2
 .PHONY: keys_rsa_enc_basic_1024 keys_rsa_enc_basic_2048 keys_rsa_enc_basic_4096
 .PHONY: keys_rsa_enc_pkcs8_v1_1024 keys_rsa_enc_pkcs8_v2_1024
diff --git a/tests/data_files/rsa_pkcs1_1024_clear.der b/tests/data_files/rsa_pkcs1_1024_clear.der
new file mode 100644
index 0000000..cec2c30
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_1024_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_2048_clear.der b/tests/data_files/rsa_pkcs1_2048_clear.der
new file mode 100644
index 0000000..667051b
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_2048_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_4096_clear.der b/tests/data_files/rsa_pkcs1_4096_clear.der
new file mode 100644
index 0000000..9dc971e
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_4096_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_768_clear.der b/tests/data_files/rsa_pkcs1_768_clear.der
new file mode 100644
index 0000000..a80b891
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_768_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_768_clear.pem b/tests/data_files/rsa_pkcs1_768_clear.pem
new file mode 100644
index 0000000..33140c3
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_768_clear.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBywIBAAJhANmJY6FPDF0oqQEJCSrTx+ezfCU8qB6NwF2SqrphhhRFCYaMiKeg
+bRVB4pCxjGrDM2iuwlMy2QqJo4TST4MgMbK44fG7fHip+IhD/lJAfSsL56ZKz3T9
+tlog4VFGynJL1wIDAQABAmEAjB02Etw7dnWOBaCwSumFxPOSbtmW37clxB+H3+yY
+081zyToTewSVvi9loxT5AHshHYt2P+c6ylbUUEV6ZhC3mDqYMcuQmX5pJ2MhaK4T
+cCihi9eBhROPzudJ27Jx84wBAjEA9CKkG30d9+PgbUp+KnMxZuavEG4U45EDEUOG
+5+MRgSnRlPz8JsiY+Q6ReeBaEZiBAjEA5BvToGaPFSkbFT1HiV4zEEDQoXrNUO/l
+vAP6p7fCLh2nnaIRIwuHwxTUhG8pe3hXAjEAzKJAtj3gockjc9ht+n0F2r/f28C5
+x6nkTVMxwCsHoCGCaATKAmRAPPrmG6dfN8KBAjAcwNkzPdpJW44bZkcPLL2ZDeJ+
+iGE7E5JM2d+Npp8mevx25Uftt/VcBNMpAm4jLy8CMHCcVdhdVFydsL8DSYRnWD8x
+1tn1npbAeyiMHBxyhDF9EP1me7rEHvJ4Wl61HSXQNA==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/data_files/rsa_pkcs1_769_clear.der b/tests/data_files/rsa_pkcs1_769_clear.der
new file mode 100644
index 0000000..c4bfe6c
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_769_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_769_clear.pem b/tests/data_files/rsa_pkcs1_769_clear.pem
new file mode 100644
index 0000000..25e12bd
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_769_clear.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBzAIBAAJhAbUzqda7ne4UGzC60NkNAXxewl/l7X5W1scvWQVKbshsSQoHcOPj
+12RmuuA2sR6MzTNxBxsb52HNbrlqZYN5L07uanwM2bio5xl1SFXN2p3hzE2EHlM1
+nBq0sSXbX4Ua+QIDAQABAmEA1RgMVPx3Wp50LkkwGErtiXgKV4GTQzwCTW13f0ur
+OYcGBpxf2sOnrWkg9r3RkKlg25cI5IVMb8HhHtmwqGxbmF08zu5e4Jb3zaR59lTs
+uOEhVudWBtSRsid6qZug0Pt9AjEBvN2EO7Vn0xMQPphOwMR7htVzxxsADRBHmS+1
+pppCFLOpwqVDObcnl3pVw2wGd3PTAjEA+5cKqX6tfKUwNR88/urAGg+T3YsqNs4t
+5t5HuGs7AsYj0xDTTvHEsIwaovCEwBKDAjBSTDiWQyz941zx94M6Lh8cBojwoJIV
+2JkmQak9NPRcmBAjricNmlB8uWj8ShO4LXkCMQDj0c0c2JIeibLSl7vzFf3oW2zJ
+M6iBQkh8g5GsZKVmCKgOC3FdTj6Oo//GxkdfaiMCMQGsQWYVeZ43Eqn+ZYSeX7Sz
+Fol0BMyjvKXTpCznqk9+c1T86c9Cw2Rd/7NLJmPmGR4=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/data_files/rsa_pkcs1_770_clear.der b/tests/data_files/rsa_pkcs1_770_clear.der
new file mode 100644
index 0000000..89e140f
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_770_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_770_clear.pem b/tests/data_files/rsa_pkcs1_770_clear.pem
new file mode 100644
index 0000000..0a707a8
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_770_clear.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBzQIBAAJhA0tr23/I4PgNNhnJdvdVGlg2hiAKKWD7kYcXGEZgPqTyY1rVND8q
+oqI7n9IJiC4A0l+N7lZceGVotMj/dPY1DTMWT01NsEJXh47lQJNdHhpJysZyodmF
++N71sstc2iynMQIDAQABAmEBGOm/nfwGEhg0YLpdSVuq/p6KZbl8trSTb+8dQrNj
+qgShWuuQD0ngCTDatlY+aTQTp82hyjT7+EtGfxzofA8pWHSV1uvuJVWamKy8AtV1
+YXo5lREZyjTgdJzuKjwIx00BAjEB4XPP3C/etfJzmCcCYoK+TYjSCdYdIbVIZZTR
+8xgarUBu2KzedKfcdR0H8yklRpxpAjEBwHe8tsyXpzbX8E0fe+qKGrp/hWeosThd
+3LbhYN+6NVs7YUkthICJa4TZfC5qyPuJAjEBxOtjTvvFoxsL/cYs6ymeB2jAVzqT
+O0PEcLOY8vzpE7V60eGGgO3taks+UFWT2KKJAjEAhCGDI2SiJe0dsDo41Xyj1f4u
+xjJlXFmcJgRn4O/p4ACSPTafR5PLaTdKELFoWvDpAjEBeGO+jrDgz6aoJ7eka8JM
+xAWHubm0UPsr7JILYSsxViJFWIVGwIgnJU4Ny8U5LhfS
+-----END RSA PRIVATE KEY-----
diff --git a/tests/data_files/rsa_pkcs1_776_clear.der b/tests/data_files/rsa_pkcs1_776_clear.der
new file mode 100644
index 0000000..a311c67
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_776_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_776_clear.pem b/tests/data_files/rsa_pkcs1_776_clear.pem
new file mode 100644
index 0000000..e62f7b1
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_776_clear.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBzgIBAAJiANnXRUGM65e+JIE48z8L9fxWiIrBffeFynsFih4lhFrIliTf++Jy
+R98lR8TGLO0x2Cosfb+vPcX7+bNdvqOn3q53NcYYFnih7GuNHeC/BAsI6c5H2HT3
+Rw3LCJPBk/yXhFsCAwEAAQJhP/xdWV29LbsqGdLSkChBPrdkL+2ZxITF7tC3uxcm
+A0x73aT05ZTPy5m1tPTI6XsEjOHlZNkYUkqebCSAk+Jwoi8eMjqkejry7R92SBEx
+vRxhSxYkFiY3M1AxUO1km9QZYQIxDz25KT5pjdnXmcXon4wjsplmKlVXRoy11Cju
+kLLZLIM+wLW0nhiks0CsrNY6VTcL0wIxDksBCJ3sMRKQcUW/MLmorTHTvV5iraKr
+YS5A0e37Y4i/g3VEJrzWaTr1FpKMMwD4WQIxCO9w3KNAku9CHV8P8Gnii9SvNuZt
+kmjwOP/+TUrtU9FmOujMiVt9Q7IJChNWg5sQDQIxBMin1Ol+d0I+ZBszDazmPumx
+c+1WW8VZVRJ1EY50mHDZoLcsE0cbAGeCRobQM/X8KQIxAbOSOWnQiL+4QuY5rQ05
+W2BL3qSET7u75RcT3ePnaZsJf5CweulDtVOVy8cq2sXQWw==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/data_files/rsa_pkcs1_784_clear.der b/tests/data_files/rsa_pkcs1_784_clear.der
new file mode 100644
index 0000000..94f3d3b
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_784_clear.der
Binary files differ
diff --git a/tests/data_files/rsa_pkcs1_784_clear.pem b/tests/data_files/rsa_pkcs1_784_clear.pem
new file mode 100644
index 0000000..b7b424b
--- /dev/null
+++ b/tests/data_files/rsa_pkcs1_784_clear.pem
@@ -0,0 +1,12 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIB0wIBAAJjAL2x2bcoZLRL21gXcWsVJpjy65T7t6lsg/7loYbeZoIM1YCbgOaw
+j3c2bkiToc53k1siXpXSLzdIyPCvs7Tm9q1mNHi4pMmiOU/49wXKZzEr8+iIMHXf
+GVxysbIsch/1m/yTAgMBAAECYhsXm5CdJETb0Kf0MS6qBqkxiJPun3yDExcElN0+
+RkWsr5F+pBpOfS75hya2bxWd3l2WyEA3JTTkveghmsOy3UzPC/IhQLGFYOsRg6ia
+yflUVObDrrdmXL0ysI2V4a0770MBAjIA3fXqP6Q8rg5WE2RddFeAGYTmfaDU9RGH
+8ee4w0kITTXOr23WHEgIYuspKMB01gvg+QIyANrJMJ8VzwJdeq28KSBTCtQawLGH
+mXzzsaSiD14hjEDQnVTkBEWMhtbyudm0NXjuOOsCMXj2gAbW9srUvUwsMlIpLYK6
+zvJAKE62kyPeaO7kakXJwS4R6dHX39oo1nGDESllp+ECMgDKEvcgiHEZuyNbIiZO
+H8UpoMgHcLn4adDSwYg2JgA3wTb/uFalsiS8lZXImSSmXEkfAjE3y7xpVjmzp3W2
+/iNSKwBWTOLyu06KQ03gQEtvuXyEk6Nx+8siz9RHyjKnRL4HzRM9
+-----END RSA PRIVATE KEY-----
diff --git a/tests/data_files/server2-sha256.ku-ds.crt b/tests/data_files/server2-sha256.ku-ds.crt
new file mode 100644
index 0000000..0d4866c
--- /dev/null
+++ b/tests/data_files/server2-sha256.ku-ds.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRzCCAi+gAwIBAgIBGDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN
+owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz
+NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM
+tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P
+hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya
+HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNdMFswCQYD
+VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw
+FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3
+DQEBCwUAA4IBAQAtKutVrQunnzOQg3TP2vnOT8Qr5LrbvsSBaPEm21Oxkpr0gJcC
+/BgON5WrBdfpEDZ5jOMGgqdF3AxFzh/Zw1EBr2y2wIcleodtzV5j2fTQV9MPYJ9z
+XYfhNsr9idt/i4YCqJSe6lB/+GG/p+9jtMLGMjfSkNnG7ppa7Sv6NVsAxgbKskTw
+WU/z7T7Y/afK5omAPpHfWddzCl5o+o9VFi5scYyjv2iNPkRiTMDh4bE8RVm9vxcf
+TMH14TSa1Y6OkaTuzJLbU3V8yJZ67s2SK89Trd75SQ+B62nZYe+0NG+6b2s+D97y
+ex2x2EbfK/nxEL2Gv7/xG4gcpzxmKObhPpsS
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server2-sha256.ku-ds_ke.crt b/tests/data_files/server2-sha256.ku-ds_ke.crt
new file mode 100644
index 0000000..e89e17d
--- /dev/null
+++ b/tests/data_files/server2-sha256.ku-ds_ke.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRzCCAi+gAwIBAgIBHDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN
+owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz
+NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM
+tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P
+hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya
+HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNdMFswCQYD
+VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw
+FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDgYDVR0PAQH/BAQDAgWgMA0GCSqGSIb3
+DQEBCwUAA4IBAQBZBDKh6TRkGh9ro5l/Rv6/LE9slTLCrAAjCA6fT2dig6WsijmK
+OLwjjuWRdKT+SPrm+42db4j++KcPVk/HwPNkbcXF7sAHy13DGi47mi7ySKqCiOZ8
+RVnpBWjZJpMzXi5l8RgXGK10v2C4iPX3E7iRw+CYTZjOWfjnzHUWqQ93eu3s6OU3
+3FobrPFKYkS9CvqvbGBIqpv8TTAoAvUAsjUbQHY2SlqlJLw2DUmewmeBzS2ItNyp
+BO367lTm03z+nG77pZYOhgxch8EA2RcIuoEExj0tHZcG3JLOz60ijqqG1lxjrTXV
+qMDRttuL8jisekj4gZD90T9JdMHpz8goNhO7
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server2-sha256.ku-ka.crt b/tests/data_files/server2-sha256.ku-ka.crt
new file mode 100644
index 0000000..326876b
--- /dev/null
+++ b/tests/data_files/server2-sha256.ku-ka.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRzCCAi+gAwIBAgIBFjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN
+owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz
+NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM
+tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P
+hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya
+HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNdMFswCQYD
+VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw
+FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDgYDVR0PAQH/BAQDAgMIMA0GCSqGSIb3
+DQEBCwUAA4IBAQBsd9wHhcSkcO/AyrHRw33RVgdydoUIcopGHCnl+6ThQj9lM2cF
+eh7Zdu2GVyd2yyIeI7c+N1w1NOLxXYk4vviU6J/Jol706UefflMEMHIwgJqakWdj
+uq8o7CTOEhMpzSE6AfNj02jLb3qrkoJGB+STIwgx2IYdDzTrIr2Cb2T9zbDJCQBd
+l2PTVR5id/+Uy4h+2KNJzgRgOUIPc0eFN0aE5a7IHRx3q7h5h/DbBaQU4tVmaAYF
+o/6XlBvwVxan87w+hLfnFHUO7eMe0jnLvH2O+MW4ZeYh4VP2Jq7cLJQgTfCbFK9L
+PNG8gfhW71rcMRTxwKM5qziJ8h6PeomSglsO
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server2-sha256.ku-ke.crt b/tests/data_files/server2-sha256.ku-ke.crt
new file mode 100644
index 0000000..ca5c3c7
--- /dev/null
+++ b/tests/data_files/server2-sha256.ku-ke.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRzCCAi+gAwIBAgIBFzANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G
+A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN
+owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz
+NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM
+tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P
+hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya
+HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNdMFswCQYD
+VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw
+FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDgYDVR0PAQH/BAQDAgUgMA0GCSqGSIb3
+DQEBCwUAA4IBAQAuR/fgNifvtW6ukLxp+VFlYael3kAGJpKhe271fjkaqiyBB9Qt
+NfFX1HDq1hJe8c8uf+SgFnY6rg1BjdctrEU92avPYjhpsyYEuSjt9LAtLfpeMaWD
+ltem8PNh/lkR+v0xqeYsDcHTv/oR9NfCIqoPFWOPlH7CvLowNbI06D8KkKiWAlL1
+tC62db6T5sOrmcmyjLoKUyerBqCWC+MM4G+AXMdfp54/xLOvkTq/K1cu1oRIGIYL
+SSAtVeRQXqwgaH2M2EkN79joF6XnjGG27TN8rCS7gxJm87vZjtZiSFugwhFFHFhX
+Gmp9IkBVZKQci1NbTY18l/2wxFYICv486sAV
+-----END CERTIFICATE-----
diff --git a/tests/include/test/drivers/config_test_driver.h b/tests/include/test/drivers/config_test_driver.h
index 4eb27f0..ec8bcb6 100644
--- a/tests/include/test/drivers/config_test_driver.h
+++ b/tests/include/test/drivers/config_test_driver.h
@@ -40,5 +40,7 @@
 //#define MBEDTLS_MD_C
 //#define MBEDTLS_PEM_PARSE_C
 //#define MBEDTLS_BASE64_C
+//#define MBEDTLS_THREADING_C
+//#define MBEDTLS_THREADING_PTHREAD
 
 #endif /* MBEDTLS_CONFIG_H */
diff --git a/tests/include/test/drivers/crypto_config_test_driver_extension.h b/tests/include/test/drivers/crypto_config_test_driver_extension.h
index dac07ac..66378e7 100644
--- a/tests/include/test/drivers/crypto_config_test_driver_extension.h
+++ b/tests/include/test/drivers/crypto_config_test_driver_extension.h
@@ -1,9 +1,24 @@
 /**
- * This file is intended to be used to build PSA test driver libraries. It is
- * intended to be appended by the test build system to the crypto_config.h file
- * of the Mbed TLS library the test library will be linked to. It mirrors the
- * PSA_ACCEL_* macros defining the cryptographic operations the test library
- * supports.
+ * This file is intended to be used to build PSA external test driver
+ * libraries (libtestdriver1).
+ *
+ * It is intended to be appended by the test build system to the
+ * crypto_config.h file of the Mbed TLS library the test library will be
+ * linked to (see `tests/Makefile` libtestdriver1 target). This is done in
+ * order to insert it at the right time: after the main configuration
+ * (PSA_WANT) but before the logic that determines what built-ins to enable
+ * based on PSA_WANT and MBEDTLS_PSA_ACCEL macros.
+ *
+ * It reverses the PSA_ACCEL_* macros defining the cryptographic operations
+ * that will be accelerated in the main library:
+ * - When something is accelerated in the main library, we need it supported
+ *   in libtestdriver1, so we disable the accel macro in order to the built-in
+ *   to be enabled.
+ * - When something is NOT accelerated in the main library, we don't need it
+ *   in libtestdriver1, so we enable its accel macro in order to the built-in
+ *   to be disabled, to keep libtestdriver1 minimal. (We can't adjust the
+ *   PSA_WANT macros as they need to be the same between libtestdriver1 and
+ *   the main library, since they determine the ABI between the two.)
  */
 
 #include "psa/crypto_legacy.h"
diff --git a/tests/include/test/drivers/key_management.h b/tests/include/test/drivers/key_management.h
index 7b5c4c7..1d9bc43 100644
--- a/tests/include/test/drivers/key_management.h
+++ b/tests/include/test/drivers/key_management.h
@@ -26,8 +26,10 @@
     /* Count the amount of times one of the key management driver functions
      * is called. */
     unsigned long hits;
-    /* Subset of hits which only counts key operations with EC key */
+    /* Subset of hits which only counts public key export operations */
     unsigned long hits_export_public_key;
+    /* Subset of hits which only counts key generation operations */
+    unsigned long hits_generate_key;
     /* Location of the last key management driver called to import a key. */
     psa_key_location_t location;
 } mbedtls_test_driver_key_management_hooks_t;
@@ -36,7 +38,7 @@
  * sense that no PSA specification will assign a meaning to this location
  * (stated first in version 1.0.1 of the specification) and that it is not
  * used as a location of an opaque test drivers. */
-#define MBEDTLS_TEST_DRIVER_KEY_MANAGEMENT_INIT { NULL, 0, PSA_SUCCESS, 0, 0, 0x800000 }
+#define MBEDTLS_TEST_DRIVER_KEY_MANAGEMENT_INIT { NULL, 0, PSA_SUCCESS, 0, 0, 0, 0x800000 }
 static inline mbedtls_test_driver_key_management_hooks_t
 mbedtls_test_driver_key_management_hooks_init(void)
 {
diff --git a/tests/include/test/memory.h b/tests/include/test/memory.h
new file mode 100644
index 0000000..940d9e6
--- /dev/null
+++ b/tests/include/test/memory.h
@@ -0,0 +1,108 @@
+/**
+ * \file memory.h
+ *
+ * \brief   Helper macros and functions related to testing memory management.
+ */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef TEST_MEMORY_H
+#define TEST_MEMORY_H
+
+#include "mbedtls/build_info.h"
+#include "mbedtls/platform.h"
+#include "test/helpers.h"
+
+/** \def MBEDTLS_TEST_MEMORY_CAN_POISON
+ *
+ * This macro is defined if the tests are compiled with a method to mark
+ * memory as poisoned, which can be used to enforce some memory access
+ * policies.
+ *
+ * Support for the C11 thread_local keyword is also required.
+ *
+ * Currently, only Asan (Address Sanitizer) is supported.
+ */
+#if defined(MBEDTLS_TEST_HAVE_ASAN) && \
+    (__STDC_VERSION__ >= 201112L) && \
+    !defined(PSA_CRYPTO_DRIVER_TEST)
+#  define MBEDTLS_TEST_MEMORY_CAN_POISON
+#endif
+
+/** \def MBEDTLS_TEST_MEMORY_POISON(buf, size)
+ *
+ * Poison a memory area so that any attempt to read or write from it will
+ * cause a runtime failure.
+ *
+ * Depending on the implementation, this may poison a few bytes beyond the
+ * indicated region, but will never poison a separate object on the heap
+ * or a separate object with more than the alignment of a long long.
+ *
+ * The behavior is undefined if any part of the memory area is invalid.
+ *
+ * This is a no-op in builds without a poisoning method.
+ * See #MBEDTLS_TEST_MEMORY_CAN_POISON.
+ *
+ * \param buf   Pointer to the beginning of the memory area to poison.
+ * \param size  Size of the memory area in bytes.
+ */
+
+/** \def MBEDTLS_TEST_MEMORY_UNPOISON(buf, size)
+ *
+ * Undo the effect of #MBEDTLS_TEST_MEMORY_POISON.
+ *
+ * The behavior is undefined if any part of the memory area is invalid,
+ * or if the memory area contains a mixture of poisoned and unpoisoned parts.
+ *
+ * This is a no-op in builds without a poisoning method.
+ * See #MBEDTLS_TEST_MEMORY_CAN_POISON.
+ *
+ * \param buf   Pointer to the beginning of the memory area to unpoison.
+ * \param size  Size of the memory area in bytes.
+ */
+
+#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
+
+/** Thread-local variable used to enable memory poisoning. This is set and
+ *  unset in the test wrappers so that calls to PSA functions from the library
+ *  do not poison memory.
+ */
+extern _Thread_local unsigned int mbedtls_test_memory_poisoning_count;
+
+/** Poison a memory area so that any attempt to read or write from it will
+ * cause a runtime failure.
+ *
+ * The behavior is undefined if any part of the memory area is invalid.
+ */
+void mbedtls_test_memory_poison(const unsigned char *ptr, size_t size);
+#define MBEDTLS_TEST_MEMORY_POISON(ptr, size)    \
+    do { \
+        mbedtls_test_memory_poisoning_count++; \
+        mbedtls_test_memory_poison(ptr, size); \
+    } while (0)
+
+/** Undo the effect of mbedtls_test_memory_poison().
+ *
+ * This is a no-op if the given area is entirely valid, unpoisoned memory.
+ *
+ * The behavior is undefined if any part of the memory area is invalid,
+ * or if the memory area contains a mixture of poisoned and unpoisoned parts.
+ */
+void mbedtls_test_memory_unpoison(const unsigned char *ptr, size_t size);
+#define MBEDTLS_TEST_MEMORY_UNPOISON(ptr, size)    \
+    do { \
+        mbedtls_test_memory_unpoison(ptr, size); \
+        if (mbedtls_test_memory_poisoning_count != 0) { \
+            mbedtls_test_memory_poisoning_count--; \
+        } \
+    } while (0)
+
+#else /* MBEDTLS_TEST_MEMORY_CAN_POISON */
+#define MBEDTLS_TEST_MEMORY_POISON(ptr, size) ((void) (ptr), (void) (size))
+#define MBEDTLS_TEST_MEMORY_UNPOISON(ptr, size) ((void) (ptr), (void) (size))
+#endif /* MBEDTLS_TEST_MEMORY_CAN_POISON */
+
+#endif /* TEST_MEMORY_H */
diff --git a/tests/include/test/psa_crypto_helpers.h b/tests/include/test/psa_crypto_helpers.h
index 41d204d..7306d8e 100644
--- a/tests/include/test/psa_crypto_helpers.h
+++ b/tests/include/test/psa_crypto_helpers.h
@@ -16,7 +16,6 @@
 #include <psa/crypto.h>
 #endif
 
-
 #if defined(MBEDTLS_PSA_CRYPTO_C)
 /** Initialize the PSA Crypto subsystem. */
 #define PSA_INIT() PSA_ASSERT(psa_crypto_init())
diff --git a/tests/include/test/psa_exercise_key.h b/tests/include/test/psa_exercise_key.h
index 44f5c08..f6be307 100644
--- a/tests/include/test/psa_exercise_key.h
+++ b/tests/include/test/psa_exercise_key.h
@@ -123,6 +123,9 @@
  * \param input2            The first input to pass.
  * \param input2_length     The length of \p input2 in bytes.
  * \param capacity          The capacity to set.
+ * \param key_destroyable   If set to 1, a failure due to the key not existing
+ *                          or the key being destroyed mid-operation will only
+ *                          be reported if the error code is unexpected.
  *
  * \return                  \c 1 on success, \c 0 on failure.
  */
@@ -132,7 +135,7 @@
     psa_algorithm_t alg,
     const unsigned char *input1, size_t input1_length,
     const unsigned char *input2, size_t input2_length,
-    size_t capacity);
+    size_t capacity, int key_destroyable);
 
 /** Perform a key agreement using the given key pair against its public key
  * using psa_raw_key_agreement().
@@ -143,12 +146,15 @@
  *
  * \param alg               A key agreement algorithm compatible with \p key.
  * \param key               A key that allows key agreement with \p alg.
+ * \param key_destroyable   If set to 1, a failure due to the key not existing
+ *                          or the key being destroyed mid-operation will only
+ *                          be reported if the error code is unexpected.
  *
  * \return                  \c 1 on success, \c 0 on failure.
  */
 psa_status_t mbedtls_test_psa_raw_key_agreement_with_self(
     psa_algorithm_t alg,
-    mbedtls_svc_key_id_t key);
+    mbedtls_svc_key_id_t key, int key_destroyable);
 
 /** Perform a key agreement using the given key pair against its public key
  * using psa_key_derivation_raw_key().
@@ -162,12 +168,15 @@
  *                          \p key.
  * \param key               A key pair object that is suitable for a key
  *                          agreement with \p operation.
+ * \param key_destroyable   If set to 1, a failure due to the key not existing
+ *                          or the key being destroyed mid-operation will only
+ *                          be reported if the error code is unexpected.
  *
  * \return                  \c 1 on success, \c 0 on failure.
  */
 psa_status_t mbedtls_test_psa_key_agreement_with_self(
     psa_key_derivation_operation_t *operation,
-    mbedtls_svc_key_id_t key);
+    mbedtls_svc_key_id_t key, int key_destroyable);
 
 /** Perform sanity checks on the given key representation.
  *
@@ -209,18 +218,34 @@
  * ```
  * if( ! exercise_key( ... ) ) goto exit;
  * ```
+ * To use this function for multi-threaded tests where the key
+ * may be destroyed at any point: call this function with key_destroyable set
+ * to 1, while another thread calls psa_destroy_key on the same key;
+ * this will test whether destroying the key in use leads to any corruption.
  *
- * \param key       The key to exercise. It should be capable of performing
- *                  \p alg.
- * \param usage     The usage flags to assume.
- * \param alg       The algorithm to exercise.
+ * There cannot be a set of concurrent calls:
+ * `mbedtls_test_psa_exercise_key(ki,...)` such that each ki is a unique
+ * persistent key not loaded into any key slot, and i is greater than the
+ * number of free key slots.
+ * This is because such scenarios can lead to unsupported
+ * `PSA_ERROR_INSUFFICIENT_MEMORY` return codes.
+ *
+ *
+ * \param key               The key to exercise. It should be capable of performing
+ *                          \p alg.
+ * \param usage             The usage flags to assume.
+ * \param alg               The algorithm to exercise.
+ * \param key_destroyable   If set to 1, a failure due to the key not existing
+ *                          or the key being destroyed mid-operation will only
+ *                          be reported if the error code is unexpected.
  *
  * \retval 0 The key failed the smoke tests.
  * \retval 1 The key passed the smoke tests.
  */
 int mbedtls_test_psa_exercise_key(mbedtls_svc_key_id_t key,
                                   psa_key_usage_t usage,
-                                  psa_algorithm_t alg);
+                                  psa_algorithm_t alg,
+                                  int key_destroyable);
 
 psa_key_usage_t mbedtls_test_psa_usage_to_exercise(psa_key_type_t type,
                                                    psa_algorithm_t alg);
diff --git a/tests/include/test/psa_memory_poisoning_wrappers.h b/tests/include/test/psa_memory_poisoning_wrappers.h
new file mode 100644
index 0000000..3f30b65
--- /dev/null
+++ b/tests/include/test/psa_memory_poisoning_wrappers.h
@@ -0,0 +1,40 @@
+/** Support for memory poisoning wrappers for PSA functions.
+ *
+ *  The wrappers poison the input and output buffers of each function
+ *  before calling it, to ensure that it does not access the buffers
+ *  except by calling the approved buffer-copying functions.
+ *
+ * This header declares support functions. The wrappers themselves are
+ * decalred in the automatically generated file `test/psa_test_wrappers.h`.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_MEMORY_POISONING_WRAPPERS_H
+#define PSA_MEMORY_POISONING_WRAPPERS_H
+
+#include "psa/crypto.h"
+
+#include "test/memory.h"
+
+#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
+
+/**
+ * \brief         Setup the memory poisoning test hooks used by
+ *                psa_crypto_copy_input() and psa_crypto_copy_output() for
+ *                memory poisoning.
+ */
+void mbedtls_poison_test_hooks_setup(void);
+
+/**
+ * \brief         Teardown the memory poisoning test hooks used by
+ *                psa_crypto_copy_input() and psa_crypto_copy_output() for
+ *                memory poisoning.
+ */
+void mbedtls_poison_test_hooks_teardown(void);
+
+#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_TEST_MEMORY_CAN_POISON */
+
+#endif /* PSA_MEMORY_POISONING_WRAPPERS_H */
diff --git a/tests/include/test/psa_test_wrappers.h b/tests/include/test/psa_test_wrappers.h
new file mode 100644
index 0000000..ecf926e
--- /dev/null
+++ b/tests/include/test/psa_test_wrappers.h
@@ -0,0 +1,739 @@
+/* Automatically generated by generate_psa_wrappers.py, do not edit! */
+
+/* Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef TEST_PSA_TEST_WRAPPERS_H
+#define TEST_PSA_TEST_WRAPPERS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <mbedtls/build_info.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_TEST_HOOKS) && \
+    !defined(RECORD_PSA_STATUS_COVERAGE_LOG)
+
+#include <psa/crypto.h>
+
+#include <test/memory.h>
+#include <test/psa_crypto_helpers.h>
+#include <test/psa_test_wrappers.h>
+
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
+psa_status_t mbedtls_test_wrap_mbedtls_psa_inject_entropy(
+    const uint8_t *arg0_seed,
+    size_t arg1_seed_size);
+#define mbedtls_psa_inject_entropy(arg0_seed, arg1_seed_size) \
+    mbedtls_test_wrap_mbedtls_psa_inject_entropy(arg0_seed, arg1_seed_size)
+#endif /* defined(MBEDTLS_PSA_INJECT_ENTROPY) */
+
+#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
+psa_status_t mbedtls_test_wrap_mbedtls_psa_platform_get_builtin_key(
+    mbedtls_svc_key_id_t arg0_key_id,
+    psa_key_lifetime_t *arg1_lifetime,
+    psa_drv_slot_number_t *arg2_slot_number);
+#define mbedtls_psa_platform_get_builtin_key(arg0_key_id, arg1_lifetime, arg2_slot_number) \
+    mbedtls_test_wrap_mbedtls_psa_platform_get_builtin_key(arg0_key_id, arg1_lifetime, arg2_slot_number)
+#endif /* defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) */
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+psa_status_t mbedtls_test_wrap_mbedtls_psa_register_se_key(
+    const psa_key_attributes_t *arg0_attributes);
+#define mbedtls_psa_register_se_key(arg0_attributes) \
+    mbedtls_test_wrap_mbedtls_psa_register_se_key(arg0_attributes)
+#endif /* defined(MBEDTLS_PSA_CRYPTO_SE_C) */
+
+psa_status_t mbedtls_test_wrap_psa_aead_abort(
+    psa_aead_operation_t *arg0_operation);
+#define psa_aead_abort(arg0_operation) \
+    mbedtls_test_wrap_psa_aead_abort(arg0_operation)
+
+psa_status_t mbedtls_test_wrap_psa_aead_decrypt(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_nonce,
+    size_t arg3_nonce_length,
+    const uint8_t *arg4_additional_data,
+    size_t arg5_additional_data_length,
+    const uint8_t *arg6_ciphertext,
+    size_t arg7_ciphertext_length,
+    uint8_t *arg8_plaintext,
+    size_t arg9_plaintext_size,
+    size_t *arg10_plaintext_length);
+#define psa_aead_decrypt(arg0_key, arg1_alg, arg2_nonce, arg3_nonce_length, arg4_additional_data, arg5_additional_data_length, arg6_ciphertext, arg7_ciphertext_length, arg8_plaintext, arg9_plaintext_size, arg10_plaintext_length) \
+    mbedtls_test_wrap_psa_aead_decrypt(arg0_key, arg1_alg, arg2_nonce, arg3_nonce_length, arg4_additional_data, arg5_additional_data_length, arg6_ciphertext, arg7_ciphertext_length, arg8_plaintext, arg9_plaintext_size, arg10_plaintext_length)
+
+psa_status_t mbedtls_test_wrap_psa_aead_decrypt_setup(
+    psa_aead_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg);
+#define psa_aead_decrypt_setup(arg0_operation, arg1_key, arg2_alg) \
+    mbedtls_test_wrap_psa_aead_decrypt_setup(arg0_operation, arg1_key, arg2_alg)
+
+psa_status_t mbedtls_test_wrap_psa_aead_encrypt(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_nonce,
+    size_t arg3_nonce_length,
+    const uint8_t *arg4_additional_data,
+    size_t arg5_additional_data_length,
+    const uint8_t *arg6_plaintext,
+    size_t arg7_plaintext_length,
+    uint8_t *arg8_ciphertext,
+    size_t arg9_ciphertext_size,
+    size_t *arg10_ciphertext_length);
+#define psa_aead_encrypt(arg0_key, arg1_alg, arg2_nonce, arg3_nonce_length, arg4_additional_data, arg5_additional_data_length, arg6_plaintext, arg7_plaintext_length, arg8_ciphertext, arg9_ciphertext_size, arg10_ciphertext_length) \
+    mbedtls_test_wrap_psa_aead_encrypt(arg0_key, arg1_alg, arg2_nonce, arg3_nonce_length, arg4_additional_data, arg5_additional_data_length, arg6_plaintext, arg7_plaintext_length, arg8_ciphertext, arg9_ciphertext_size, arg10_ciphertext_length)
+
+psa_status_t mbedtls_test_wrap_psa_aead_encrypt_setup(
+    psa_aead_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg);
+#define psa_aead_encrypt_setup(arg0_operation, arg1_key, arg2_alg) \
+    mbedtls_test_wrap_psa_aead_encrypt_setup(arg0_operation, arg1_key, arg2_alg)
+
+psa_status_t mbedtls_test_wrap_psa_aead_finish(
+    psa_aead_operation_t *arg0_operation,
+    uint8_t *arg1_ciphertext,
+    size_t arg2_ciphertext_size,
+    size_t *arg3_ciphertext_length,
+    uint8_t *arg4_tag,
+    size_t arg5_tag_size,
+    size_t *arg6_tag_length);
+#define psa_aead_finish(arg0_operation, arg1_ciphertext, arg2_ciphertext_size, arg3_ciphertext_length, arg4_tag, arg5_tag_size, arg6_tag_length) \
+    mbedtls_test_wrap_psa_aead_finish(arg0_operation, arg1_ciphertext, arg2_ciphertext_size, arg3_ciphertext_length, arg4_tag, arg5_tag_size, arg6_tag_length)
+
+psa_status_t mbedtls_test_wrap_psa_aead_generate_nonce(
+    psa_aead_operation_t *arg0_operation,
+    uint8_t *arg1_nonce,
+    size_t arg2_nonce_size,
+    size_t *arg3_nonce_length);
+#define psa_aead_generate_nonce(arg0_operation, arg1_nonce, arg2_nonce_size, arg3_nonce_length) \
+    mbedtls_test_wrap_psa_aead_generate_nonce(arg0_operation, arg1_nonce, arg2_nonce_size, arg3_nonce_length)
+
+psa_status_t mbedtls_test_wrap_psa_aead_set_lengths(
+    psa_aead_operation_t *arg0_operation,
+    size_t arg1_ad_length,
+    size_t arg2_plaintext_length);
+#define psa_aead_set_lengths(arg0_operation, arg1_ad_length, arg2_plaintext_length) \
+    mbedtls_test_wrap_psa_aead_set_lengths(arg0_operation, arg1_ad_length, arg2_plaintext_length)
+
+psa_status_t mbedtls_test_wrap_psa_aead_set_nonce(
+    psa_aead_operation_t *arg0_operation,
+    const uint8_t *arg1_nonce,
+    size_t arg2_nonce_length);
+#define psa_aead_set_nonce(arg0_operation, arg1_nonce, arg2_nonce_length) \
+    mbedtls_test_wrap_psa_aead_set_nonce(arg0_operation, arg1_nonce, arg2_nonce_length)
+
+psa_status_t mbedtls_test_wrap_psa_aead_update(
+    psa_aead_operation_t *arg0_operation,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length,
+    uint8_t *arg3_output,
+    size_t arg4_output_size,
+    size_t *arg5_output_length);
+#define psa_aead_update(arg0_operation, arg1_input, arg2_input_length, arg3_output, arg4_output_size, arg5_output_length) \
+    mbedtls_test_wrap_psa_aead_update(arg0_operation, arg1_input, arg2_input_length, arg3_output, arg4_output_size, arg5_output_length)
+
+psa_status_t mbedtls_test_wrap_psa_aead_update_ad(
+    psa_aead_operation_t *arg0_operation,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length);
+#define psa_aead_update_ad(arg0_operation, arg1_input, arg2_input_length) \
+    mbedtls_test_wrap_psa_aead_update_ad(arg0_operation, arg1_input, arg2_input_length)
+
+psa_status_t mbedtls_test_wrap_psa_aead_verify(
+    psa_aead_operation_t *arg0_operation,
+    uint8_t *arg1_plaintext,
+    size_t arg2_plaintext_size,
+    size_t *arg3_plaintext_length,
+    const uint8_t *arg4_tag,
+    size_t arg5_tag_length);
+#define psa_aead_verify(arg0_operation, arg1_plaintext, arg2_plaintext_size, arg3_plaintext_length, arg4_tag, arg5_tag_length) \
+    mbedtls_test_wrap_psa_aead_verify(arg0_operation, arg1_plaintext, arg2_plaintext_size, arg3_plaintext_length, arg4_tag, arg5_tag_length)
+
+psa_status_t mbedtls_test_wrap_psa_asymmetric_decrypt(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    const uint8_t *arg4_salt,
+    size_t arg5_salt_length,
+    uint8_t *arg6_output,
+    size_t arg7_output_size,
+    size_t *arg8_output_length);
+#define psa_asymmetric_decrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_salt, arg5_salt_length, arg6_output, arg7_output_size, arg8_output_length) \
+    mbedtls_test_wrap_psa_asymmetric_decrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_salt, arg5_salt_length, arg6_output, arg7_output_size, arg8_output_length)
+
+psa_status_t mbedtls_test_wrap_psa_asymmetric_encrypt(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    const uint8_t *arg4_salt,
+    size_t arg5_salt_length,
+    uint8_t *arg6_output,
+    size_t arg7_output_size,
+    size_t *arg8_output_length);
+#define psa_asymmetric_encrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_salt, arg5_salt_length, arg6_output, arg7_output_size, arg8_output_length) \
+    mbedtls_test_wrap_psa_asymmetric_encrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_salt, arg5_salt_length, arg6_output, arg7_output_size, arg8_output_length)
+
+psa_status_t mbedtls_test_wrap_psa_cipher_abort(
+    psa_cipher_operation_t *arg0_operation);
+#define psa_cipher_abort(arg0_operation) \
+    mbedtls_test_wrap_psa_cipher_abort(arg0_operation)
+
+psa_status_t mbedtls_test_wrap_psa_cipher_decrypt(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    uint8_t *arg4_output,
+    size_t arg5_output_size,
+    size_t *arg6_output_length);
+#define psa_cipher_decrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_output, arg5_output_size, arg6_output_length) \
+    mbedtls_test_wrap_psa_cipher_decrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_output, arg5_output_size, arg6_output_length)
+
+psa_status_t mbedtls_test_wrap_psa_cipher_decrypt_setup(
+    psa_cipher_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg);
+#define psa_cipher_decrypt_setup(arg0_operation, arg1_key, arg2_alg) \
+    mbedtls_test_wrap_psa_cipher_decrypt_setup(arg0_operation, arg1_key, arg2_alg)
+
+psa_status_t mbedtls_test_wrap_psa_cipher_encrypt(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    uint8_t *arg4_output,
+    size_t arg5_output_size,
+    size_t *arg6_output_length);
+#define psa_cipher_encrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_output, arg5_output_size, arg6_output_length) \
+    mbedtls_test_wrap_psa_cipher_encrypt(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_output, arg5_output_size, arg6_output_length)
+
+psa_status_t mbedtls_test_wrap_psa_cipher_encrypt_setup(
+    psa_cipher_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg);
+#define psa_cipher_encrypt_setup(arg0_operation, arg1_key, arg2_alg) \
+    mbedtls_test_wrap_psa_cipher_encrypt_setup(arg0_operation, arg1_key, arg2_alg)
+
+psa_status_t mbedtls_test_wrap_psa_cipher_finish(
+    psa_cipher_operation_t *arg0_operation,
+    uint8_t *arg1_output,
+    size_t arg2_output_size,
+    size_t *arg3_output_length);
+#define psa_cipher_finish(arg0_operation, arg1_output, arg2_output_size, arg3_output_length) \
+    mbedtls_test_wrap_psa_cipher_finish(arg0_operation, arg1_output, arg2_output_size, arg3_output_length)
+
+psa_status_t mbedtls_test_wrap_psa_cipher_generate_iv(
+    psa_cipher_operation_t *arg0_operation,
+    uint8_t *arg1_iv,
+    size_t arg2_iv_size,
+    size_t *arg3_iv_length);
+#define psa_cipher_generate_iv(arg0_operation, arg1_iv, arg2_iv_size, arg3_iv_length) \
+    mbedtls_test_wrap_psa_cipher_generate_iv(arg0_operation, arg1_iv, arg2_iv_size, arg3_iv_length)
+
+psa_status_t mbedtls_test_wrap_psa_cipher_set_iv(
+    psa_cipher_operation_t *arg0_operation,
+    const uint8_t *arg1_iv,
+    size_t arg2_iv_length);
+#define psa_cipher_set_iv(arg0_operation, arg1_iv, arg2_iv_length) \
+    mbedtls_test_wrap_psa_cipher_set_iv(arg0_operation, arg1_iv, arg2_iv_length)
+
+psa_status_t mbedtls_test_wrap_psa_cipher_update(
+    psa_cipher_operation_t *arg0_operation,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length,
+    uint8_t *arg3_output,
+    size_t arg4_output_size,
+    size_t *arg5_output_length);
+#define psa_cipher_update(arg0_operation, arg1_input, arg2_input_length, arg3_output, arg4_output_size, arg5_output_length) \
+    mbedtls_test_wrap_psa_cipher_update(arg0_operation, arg1_input, arg2_input_length, arg3_output, arg4_output_size, arg5_output_length)
+
+psa_status_t mbedtls_test_wrap_psa_copy_key(
+    mbedtls_svc_key_id_t arg0_source_key,
+    const psa_key_attributes_t *arg1_attributes,
+    mbedtls_svc_key_id_t *arg2_target_key);
+#define psa_copy_key(arg0_source_key, arg1_attributes, arg2_target_key) \
+    mbedtls_test_wrap_psa_copy_key(arg0_source_key, arg1_attributes, arg2_target_key)
+
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_cipher_suite(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    psa_pake_cipher_suite_t *arg1_cipher_suite);
+#define psa_crypto_driver_pake_get_cipher_suite(arg0_inputs, arg1_cipher_suite) \
+    mbedtls_test_wrap_psa_crypto_driver_pake_get_cipher_suite(arg0_inputs, arg1_cipher_suite)
+
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_password(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    uint8_t *arg1_buffer,
+    size_t arg2_buffer_size,
+    size_t *arg3_buffer_length);
+#define psa_crypto_driver_pake_get_password(arg0_inputs, arg1_buffer, arg2_buffer_size, arg3_buffer_length) \
+    mbedtls_test_wrap_psa_crypto_driver_pake_get_password(arg0_inputs, arg1_buffer, arg2_buffer_size, arg3_buffer_length)
+
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_password_len(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    size_t *arg1_password_len);
+#define psa_crypto_driver_pake_get_password_len(arg0_inputs, arg1_password_len) \
+    mbedtls_test_wrap_psa_crypto_driver_pake_get_password_len(arg0_inputs, arg1_password_len)
+
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_peer(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    uint8_t *arg1_peer_id,
+    size_t arg2_peer_id_size,
+    size_t *arg3_peer_id_length);
+#define psa_crypto_driver_pake_get_peer(arg0_inputs, arg1_peer_id, arg2_peer_id_size, arg3_peer_id_length) \
+    mbedtls_test_wrap_psa_crypto_driver_pake_get_peer(arg0_inputs, arg1_peer_id, arg2_peer_id_size, arg3_peer_id_length)
+
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_peer_len(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    size_t *arg1_peer_len);
+#define psa_crypto_driver_pake_get_peer_len(arg0_inputs, arg1_peer_len) \
+    mbedtls_test_wrap_psa_crypto_driver_pake_get_peer_len(arg0_inputs, arg1_peer_len)
+
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_user(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    uint8_t *arg1_user_id,
+    size_t arg2_user_id_size,
+    size_t *arg3_user_id_len);
+#define psa_crypto_driver_pake_get_user(arg0_inputs, arg1_user_id, arg2_user_id_size, arg3_user_id_len) \
+    mbedtls_test_wrap_psa_crypto_driver_pake_get_user(arg0_inputs, arg1_user_id, arg2_user_id_size, arg3_user_id_len)
+
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_user_len(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    size_t *arg1_user_len);
+#define psa_crypto_driver_pake_get_user_len(arg0_inputs, arg1_user_len) \
+    mbedtls_test_wrap_psa_crypto_driver_pake_get_user_len(arg0_inputs, arg1_user_len)
+
+psa_status_t mbedtls_test_wrap_psa_crypto_init(void);
+#define psa_crypto_init() \
+    mbedtls_test_wrap_psa_crypto_init()
+
+psa_status_t mbedtls_test_wrap_psa_destroy_key(
+    mbedtls_svc_key_id_t arg0_key);
+#define psa_destroy_key(arg0_key) \
+    mbedtls_test_wrap_psa_destroy_key(arg0_key)
+
+psa_status_t mbedtls_test_wrap_psa_export_key(
+    mbedtls_svc_key_id_t arg0_key,
+    uint8_t *arg1_data,
+    size_t arg2_data_size,
+    size_t *arg3_data_length);
+#define psa_export_key(arg0_key, arg1_data, arg2_data_size, arg3_data_length) \
+    mbedtls_test_wrap_psa_export_key(arg0_key, arg1_data, arg2_data_size, arg3_data_length)
+
+psa_status_t mbedtls_test_wrap_psa_export_public_key(
+    mbedtls_svc_key_id_t arg0_key,
+    uint8_t *arg1_data,
+    size_t arg2_data_size,
+    size_t *arg3_data_length);
+#define psa_export_public_key(arg0_key, arg1_data, arg2_data_size, arg3_data_length) \
+    mbedtls_test_wrap_psa_export_public_key(arg0_key, arg1_data, arg2_data_size, arg3_data_length)
+
+psa_status_t mbedtls_test_wrap_psa_generate_key(
+    const psa_key_attributes_t *arg0_attributes,
+    mbedtls_svc_key_id_t *arg1_key);
+#define psa_generate_key(arg0_attributes, arg1_key) \
+    mbedtls_test_wrap_psa_generate_key(arg0_attributes, arg1_key)
+
+psa_status_t mbedtls_test_wrap_psa_generate_key_ext(
+    const psa_key_attributes_t *arg0_attributes,
+    const psa_key_production_parameters_t *arg1_params,
+    size_t arg2_params_data_length,
+    mbedtls_svc_key_id_t *arg3_key);
+#define psa_generate_key_ext(arg0_attributes, arg1_params, arg2_params_data_length, arg3_key) \
+    mbedtls_test_wrap_psa_generate_key_ext(arg0_attributes, arg1_params, arg2_params_data_length, arg3_key)
+
+psa_status_t mbedtls_test_wrap_psa_generate_random(
+    uint8_t *arg0_output,
+    size_t arg1_output_size);
+#define psa_generate_random(arg0_output, arg1_output_size) \
+    mbedtls_test_wrap_psa_generate_random(arg0_output, arg1_output_size)
+
+psa_status_t mbedtls_test_wrap_psa_get_key_attributes(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_key_attributes_t *arg1_attributes);
+#define psa_get_key_attributes(arg0_key, arg1_attributes) \
+    mbedtls_test_wrap_psa_get_key_attributes(arg0_key, arg1_attributes)
+
+psa_status_t mbedtls_test_wrap_psa_hash_abort(
+    psa_hash_operation_t *arg0_operation);
+#define psa_hash_abort(arg0_operation) \
+    mbedtls_test_wrap_psa_hash_abort(arg0_operation)
+
+psa_status_t mbedtls_test_wrap_psa_hash_clone(
+    const psa_hash_operation_t *arg0_source_operation,
+    psa_hash_operation_t *arg1_target_operation);
+#define psa_hash_clone(arg0_source_operation, arg1_target_operation) \
+    mbedtls_test_wrap_psa_hash_clone(arg0_source_operation, arg1_target_operation)
+
+psa_status_t mbedtls_test_wrap_psa_hash_compare(
+    psa_algorithm_t arg0_alg,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length,
+    const uint8_t *arg3_hash,
+    size_t arg4_hash_length);
+#define psa_hash_compare(arg0_alg, arg1_input, arg2_input_length, arg3_hash, arg4_hash_length) \
+    mbedtls_test_wrap_psa_hash_compare(arg0_alg, arg1_input, arg2_input_length, arg3_hash, arg4_hash_length)
+
+psa_status_t mbedtls_test_wrap_psa_hash_compute(
+    psa_algorithm_t arg0_alg,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length,
+    uint8_t *arg3_hash,
+    size_t arg4_hash_size,
+    size_t *arg5_hash_length);
+#define psa_hash_compute(arg0_alg, arg1_input, arg2_input_length, arg3_hash, arg4_hash_size, arg5_hash_length) \
+    mbedtls_test_wrap_psa_hash_compute(arg0_alg, arg1_input, arg2_input_length, arg3_hash, arg4_hash_size, arg5_hash_length)
+
+psa_status_t mbedtls_test_wrap_psa_hash_finish(
+    psa_hash_operation_t *arg0_operation,
+    uint8_t *arg1_hash,
+    size_t arg2_hash_size,
+    size_t *arg3_hash_length);
+#define psa_hash_finish(arg0_operation, arg1_hash, arg2_hash_size, arg3_hash_length) \
+    mbedtls_test_wrap_psa_hash_finish(arg0_operation, arg1_hash, arg2_hash_size, arg3_hash_length)
+
+psa_status_t mbedtls_test_wrap_psa_hash_setup(
+    psa_hash_operation_t *arg0_operation,
+    psa_algorithm_t arg1_alg);
+#define psa_hash_setup(arg0_operation, arg1_alg) \
+    mbedtls_test_wrap_psa_hash_setup(arg0_operation, arg1_alg)
+
+psa_status_t mbedtls_test_wrap_psa_hash_update(
+    psa_hash_operation_t *arg0_operation,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length);
+#define psa_hash_update(arg0_operation, arg1_input, arg2_input_length) \
+    mbedtls_test_wrap_psa_hash_update(arg0_operation, arg1_input, arg2_input_length)
+
+psa_status_t mbedtls_test_wrap_psa_hash_verify(
+    psa_hash_operation_t *arg0_operation,
+    const uint8_t *arg1_hash,
+    size_t arg2_hash_length);
+#define psa_hash_verify(arg0_operation, arg1_hash, arg2_hash_length) \
+    mbedtls_test_wrap_psa_hash_verify(arg0_operation, arg1_hash, arg2_hash_length)
+
+psa_status_t mbedtls_test_wrap_psa_import_key(
+    const psa_key_attributes_t *arg0_attributes,
+    const uint8_t *arg1_data,
+    size_t arg2_data_length,
+    mbedtls_svc_key_id_t *arg3_key);
+#define psa_import_key(arg0_attributes, arg1_data, arg2_data_length, arg3_key) \
+    mbedtls_test_wrap_psa_import_key(arg0_attributes, arg1_data, arg2_data_length, arg3_key)
+
+psa_status_t mbedtls_test_wrap_psa_key_derivation_abort(
+    psa_key_derivation_operation_t *arg0_operation);
+#define psa_key_derivation_abort(arg0_operation) \
+    mbedtls_test_wrap_psa_key_derivation_abort(arg0_operation)
+
+psa_status_t mbedtls_test_wrap_psa_key_derivation_get_capacity(
+    const psa_key_derivation_operation_t *arg0_operation,
+    size_t *arg1_capacity);
+#define psa_key_derivation_get_capacity(arg0_operation, arg1_capacity) \
+    mbedtls_test_wrap_psa_key_derivation_get_capacity(arg0_operation, arg1_capacity)
+
+psa_status_t mbedtls_test_wrap_psa_key_derivation_input_bytes(
+    psa_key_derivation_operation_t *arg0_operation,
+    psa_key_derivation_step_t arg1_step,
+    const uint8_t *arg2_data,
+    size_t arg3_data_length);
+#define psa_key_derivation_input_bytes(arg0_operation, arg1_step, arg2_data, arg3_data_length) \
+    mbedtls_test_wrap_psa_key_derivation_input_bytes(arg0_operation, arg1_step, arg2_data, arg3_data_length)
+
+psa_status_t mbedtls_test_wrap_psa_key_derivation_input_integer(
+    psa_key_derivation_operation_t *arg0_operation,
+    psa_key_derivation_step_t arg1_step,
+    uint64_t arg2_value);
+#define psa_key_derivation_input_integer(arg0_operation, arg1_step, arg2_value) \
+    mbedtls_test_wrap_psa_key_derivation_input_integer(arg0_operation, arg1_step, arg2_value)
+
+psa_status_t mbedtls_test_wrap_psa_key_derivation_input_key(
+    psa_key_derivation_operation_t *arg0_operation,
+    psa_key_derivation_step_t arg1_step,
+    mbedtls_svc_key_id_t arg2_key);
+#define psa_key_derivation_input_key(arg0_operation, arg1_step, arg2_key) \
+    mbedtls_test_wrap_psa_key_derivation_input_key(arg0_operation, arg1_step, arg2_key)
+
+psa_status_t mbedtls_test_wrap_psa_key_derivation_key_agreement(
+    psa_key_derivation_operation_t *arg0_operation,
+    psa_key_derivation_step_t arg1_step,
+    mbedtls_svc_key_id_t arg2_private_key,
+    const uint8_t *arg3_peer_key,
+    size_t arg4_peer_key_length);
+#define psa_key_derivation_key_agreement(arg0_operation, arg1_step, arg2_private_key, arg3_peer_key, arg4_peer_key_length) \
+    mbedtls_test_wrap_psa_key_derivation_key_agreement(arg0_operation, arg1_step, arg2_private_key, arg3_peer_key, arg4_peer_key_length)
+
+psa_status_t mbedtls_test_wrap_psa_key_derivation_output_bytes(
+    psa_key_derivation_operation_t *arg0_operation,
+    uint8_t *arg1_output,
+    size_t arg2_output_length);
+#define psa_key_derivation_output_bytes(arg0_operation, arg1_output, arg2_output_length) \
+    mbedtls_test_wrap_psa_key_derivation_output_bytes(arg0_operation, arg1_output, arg2_output_length)
+
+psa_status_t mbedtls_test_wrap_psa_key_derivation_output_key(
+    const psa_key_attributes_t *arg0_attributes,
+    psa_key_derivation_operation_t *arg1_operation,
+    mbedtls_svc_key_id_t *arg2_key);
+#define psa_key_derivation_output_key(arg0_attributes, arg1_operation, arg2_key) \
+    mbedtls_test_wrap_psa_key_derivation_output_key(arg0_attributes, arg1_operation, arg2_key)
+
+psa_status_t mbedtls_test_wrap_psa_key_derivation_output_key_ext(
+    const psa_key_attributes_t *arg0_attributes,
+    psa_key_derivation_operation_t *arg1_operation,
+    const psa_key_production_parameters_t *arg2_params,
+    size_t arg3_params_data_length,
+    mbedtls_svc_key_id_t *arg4_key);
+#define psa_key_derivation_output_key_ext(arg0_attributes, arg1_operation, arg2_params, arg3_params_data_length, arg4_key) \
+    mbedtls_test_wrap_psa_key_derivation_output_key_ext(arg0_attributes, arg1_operation, arg2_params, arg3_params_data_length, arg4_key)
+
+psa_status_t mbedtls_test_wrap_psa_key_derivation_set_capacity(
+    psa_key_derivation_operation_t *arg0_operation,
+    size_t arg1_capacity);
+#define psa_key_derivation_set_capacity(arg0_operation, arg1_capacity) \
+    mbedtls_test_wrap_psa_key_derivation_set_capacity(arg0_operation, arg1_capacity)
+
+psa_status_t mbedtls_test_wrap_psa_key_derivation_setup(
+    psa_key_derivation_operation_t *arg0_operation,
+    psa_algorithm_t arg1_alg);
+#define psa_key_derivation_setup(arg0_operation, arg1_alg) \
+    mbedtls_test_wrap_psa_key_derivation_setup(arg0_operation, arg1_alg)
+
+psa_status_t mbedtls_test_wrap_psa_mac_abort(
+    psa_mac_operation_t *arg0_operation);
+#define psa_mac_abort(arg0_operation) \
+    mbedtls_test_wrap_psa_mac_abort(arg0_operation)
+
+psa_status_t mbedtls_test_wrap_psa_mac_compute(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    uint8_t *arg4_mac,
+    size_t arg5_mac_size,
+    size_t *arg6_mac_length);
+#define psa_mac_compute(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_mac, arg5_mac_size, arg6_mac_length) \
+    mbedtls_test_wrap_psa_mac_compute(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_mac, arg5_mac_size, arg6_mac_length)
+
+psa_status_t mbedtls_test_wrap_psa_mac_sign_finish(
+    psa_mac_operation_t *arg0_operation,
+    uint8_t *arg1_mac,
+    size_t arg2_mac_size,
+    size_t *arg3_mac_length);
+#define psa_mac_sign_finish(arg0_operation, arg1_mac, arg2_mac_size, arg3_mac_length) \
+    mbedtls_test_wrap_psa_mac_sign_finish(arg0_operation, arg1_mac, arg2_mac_size, arg3_mac_length)
+
+psa_status_t mbedtls_test_wrap_psa_mac_sign_setup(
+    psa_mac_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg);
+#define psa_mac_sign_setup(arg0_operation, arg1_key, arg2_alg) \
+    mbedtls_test_wrap_psa_mac_sign_setup(arg0_operation, arg1_key, arg2_alg)
+
+psa_status_t mbedtls_test_wrap_psa_mac_update(
+    psa_mac_operation_t *arg0_operation,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length);
+#define psa_mac_update(arg0_operation, arg1_input, arg2_input_length) \
+    mbedtls_test_wrap_psa_mac_update(arg0_operation, arg1_input, arg2_input_length)
+
+psa_status_t mbedtls_test_wrap_psa_mac_verify(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    const uint8_t *arg4_mac,
+    size_t arg5_mac_length);
+#define psa_mac_verify(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_mac, arg5_mac_length) \
+    mbedtls_test_wrap_psa_mac_verify(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_mac, arg5_mac_length)
+
+psa_status_t mbedtls_test_wrap_psa_mac_verify_finish(
+    psa_mac_operation_t *arg0_operation,
+    const uint8_t *arg1_mac,
+    size_t arg2_mac_length);
+#define psa_mac_verify_finish(arg0_operation, arg1_mac, arg2_mac_length) \
+    mbedtls_test_wrap_psa_mac_verify_finish(arg0_operation, arg1_mac, arg2_mac_length)
+
+psa_status_t mbedtls_test_wrap_psa_mac_verify_setup(
+    psa_mac_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg);
+#define psa_mac_verify_setup(arg0_operation, arg1_key, arg2_alg) \
+    mbedtls_test_wrap_psa_mac_verify_setup(arg0_operation, arg1_key, arg2_alg)
+
+psa_status_t mbedtls_test_wrap_psa_pake_abort(
+    psa_pake_operation_t *arg0_operation);
+#define psa_pake_abort(arg0_operation) \
+    mbedtls_test_wrap_psa_pake_abort(arg0_operation)
+
+psa_status_t mbedtls_test_wrap_psa_pake_get_implicit_key(
+    psa_pake_operation_t *arg0_operation,
+    psa_key_derivation_operation_t *arg1_output);
+#define psa_pake_get_implicit_key(arg0_operation, arg1_output) \
+    mbedtls_test_wrap_psa_pake_get_implicit_key(arg0_operation, arg1_output)
+
+psa_status_t mbedtls_test_wrap_psa_pake_input(
+    psa_pake_operation_t *arg0_operation,
+    psa_pake_step_t arg1_step,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length);
+#define psa_pake_input(arg0_operation, arg1_step, arg2_input, arg3_input_length) \
+    mbedtls_test_wrap_psa_pake_input(arg0_operation, arg1_step, arg2_input, arg3_input_length)
+
+psa_status_t mbedtls_test_wrap_psa_pake_output(
+    psa_pake_operation_t *arg0_operation,
+    psa_pake_step_t arg1_step,
+    uint8_t *arg2_output,
+    size_t arg3_output_size,
+    size_t *arg4_output_length);
+#define psa_pake_output(arg0_operation, arg1_step, arg2_output, arg3_output_size, arg4_output_length) \
+    mbedtls_test_wrap_psa_pake_output(arg0_operation, arg1_step, arg2_output, arg3_output_size, arg4_output_length)
+
+psa_status_t mbedtls_test_wrap_psa_pake_set_password_key(
+    psa_pake_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_password);
+#define psa_pake_set_password_key(arg0_operation, arg1_password) \
+    mbedtls_test_wrap_psa_pake_set_password_key(arg0_operation, arg1_password)
+
+psa_status_t mbedtls_test_wrap_psa_pake_set_peer(
+    psa_pake_operation_t *arg0_operation,
+    const uint8_t *arg1_peer_id,
+    size_t arg2_peer_id_len);
+#define psa_pake_set_peer(arg0_operation, arg1_peer_id, arg2_peer_id_len) \
+    mbedtls_test_wrap_psa_pake_set_peer(arg0_operation, arg1_peer_id, arg2_peer_id_len)
+
+psa_status_t mbedtls_test_wrap_psa_pake_set_role(
+    psa_pake_operation_t *arg0_operation,
+    psa_pake_role_t arg1_role);
+#define psa_pake_set_role(arg0_operation, arg1_role) \
+    mbedtls_test_wrap_psa_pake_set_role(arg0_operation, arg1_role)
+
+psa_status_t mbedtls_test_wrap_psa_pake_set_user(
+    psa_pake_operation_t *arg0_operation,
+    const uint8_t *arg1_user_id,
+    size_t arg2_user_id_len);
+#define psa_pake_set_user(arg0_operation, arg1_user_id, arg2_user_id_len) \
+    mbedtls_test_wrap_psa_pake_set_user(arg0_operation, arg1_user_id, arg2_user_id_len)
+
+psa_status_t mbedtls_test_wrap_psa_pake_setup(
+    psa_pake_operation_t *arg0_operation,
+    const psa_pake_cipher_suite_t *arg1_cipher_suite);
+#define psa_pake_setup(arg0_operation, arg1_cipher_suite) \
+    mbedtls_test_wrap_psa_pake_setup(arg0_operation, arg1_cipher_suite)
+
+psa_status_t mbedtls_test_wrap_psa_purge_key(
+    mbedtls_svc_key_id_t arg0_key);
+#define psa_purge_key(arg0_key) \
+    mbedtls_test_wrap_psa_purge_key(arg0_key)
+
+psa_status_t mbedtls_test_wrap_psa_raw_key_agreement(
+    psa_algorithm_t arg0_alg,
+    mbedtls_svc_key_id_t arg1_private_key,
+    const uint8_t *arg2_peer_key,
+    size_t arg3_peer_key_length,
+    uint8_t *arg4_output,
+    size_t arg5_output_size,
+    size_t *arg6_output_length);
+#define psa_raw_key_agreement(arg0_alg, arg1_private_key, arg2_peer_key, arg3_peer_key_length, arg4_output, arg5_output_size, arg6_output_length) \
+    mbedtls_test_wrap_psa_raw_key_agreement(arg0_alg, arg1_private_key, arg2_peer_key, arg3_peer_key_length, arg4_output, arg5_output_size, arg6_output_length)
+
+psa_status_t mbedtls_test_wrap_psa_sign_hash(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_hash,
+    size_t arg3_hash_length,
+    uint8_t *arg4_signature,
+    size_t arg5_signature_size,
+    size_t *arg6_signature_length);
+#define psa_sign_hash(arg0_key, arg1_alg, arg2_hash, arg3_hash_length, arg4_signature, arg5_signature_size, arg6_signature_length) \
+    mbedtls_test_wrap_psa_sign_hash(arg0_key, arg1_alg, arg2_hash, arg3_hash_length, arg4_signature, arg5_signature_size, arg6_signature_length)
+
+psa_status_t mbedtls_test_wrap_psa_sign_hash_abort(
+    psa_sign_hash_interruptible_operation_t *arg0_operation);
+#define psa_sign_hash_abort(arg0_operation) \
+    mbedtls_test_wrap_psa_sign_hash_abort(arg0_operation)
+
+psa_status_t mbedtls_test_wrap_psa_sign_hash_complete(
+    psa_sign_hash_interruptible_operation_t *arg0_operation,
+    uint8_t *arg1_signature,
+    size_t arg2_signature_size,
+    size_t *arg3_signature_length);
+#define psa_sign_hash_complete(arg0_operation, arg1_signature, arg2_signature_size, arg3_signature_length) \
+    mbedtls_test_wrap_psa_sign_hash_complete(arg0_operation, arg1_signature, arg2_signature_size, arg3_signature_length)
+
+psa_status_t mbedtls_test_wrap_psa_sign_hash_start(
+    psa_sign_hash_interruptible_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg,
+    const uint8_t *arg3_hash,
+    size_t arg4_hash_length);
+#define psa_sign_hash_start(arg0_operation, arg1_key, arg2_alg, arg3_hash, arg4_hash_length) \
+    mbedtls_test_wrap_psa_sign_hash_start(arg0_operation, arg1_key, arg2_alg, arg3_hash, arg4_hash_length)
+
+psa_status_t mbedtls_test_wrap_psa_sign_message(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    uint8_t *arg4_signature,
+    size_t arg5_signature_size,
+    size_t *arg6_signature_length);
+#define psa_sign_message(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_signature, arg5_signature_size, arg6_signature_length) \
+    mbedtls_test_wrap_psa_sign_message(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_signature, arg5_signature_size, arg6_signature_length)
+
+psa_status_t mbedtls_test_wrap_psa_verify_hash(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_hash,
+    size_t arg3_hash_length,
+    const uint8_t *arg4_signature,
+    size_t arg5_signature_length);
+#define psa_verify_hash(arg0_key, arg1_alg, arg2_hash, arg3_hash_length, arg4_signature, arg5_signature_length) \
+    mbedtls_test_wrap_psa_verify_hash(arg0_key, arg1_alg, arg2_hash, arg3_hash_length, arg4_signature, arg5_signature_length)
+
+psa_status_t mbedtls_test_wrap_psa_verify_hash_abort(
+    psa_verify_hash_interruptible_operation_t *arg0_operation);
+#define psa_verify_hash_abort(arg0_operation) \
+    mbedtls_test_wrap_psa_verify_hash_abort(arg0_operation)
+
+psa_status_t mbedtls_test_wrap_psa_verify_hash_complete(
+    psa_verify_hash_interruptible_operation_t *arg0_operation);
+#define psa_verify_hash_complete(arg0_operation) \
+    mbedtls_test_wrap_psa_verify_hash_complete(arg0_operation)
+
+psa_status_t mbedtls_test_wrap_psa_verify_hash_start(
+    psa_verify_hash_interruptible_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg,
+    const uint8_t *arg3_hash,
+    size_t arg4_hash_length,
+    const uint8_t *arg5_signature,
+    size_t arg6_signature_length);
+#define psa_verify_hash_start(arg0_operation, arg1_key, arg2_alg, arg3_hash, arg4_hash_length, arg5_signature, arg6_signature_length) \
+    mbedtls_test_wrap_psa_verify_hash_start(arg0_operation, arg1_key, arg2_alg, arg3_hash, arg4_hash_length, arg5_signature, arg6_signature_length)
+
+psa_status_t mbedtls_test_wrap_psa_verify_message(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    const uint8_t *arg4_signature,
+    size_t arg5_signature_length);
+#define psa_verify_message(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_signature, arg5_signature_length) \
+    mbedtls_test_wrap_psa_verify_message(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_signature, arg5_signature_length)
+
+#endif /* defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_TEST_HOOKS) && \
+    !defined(RECORD_PSA_STATUS_COVERAGE_LOG) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TEST_PSA_TEST_WRAPPERS_H */
+
+/* End of automatically generated file. */
diff --git a/tests/include/test/ssl_helpers.h b/tests/include/test/ssl_helpers.h
index 5b071f7..77f85c4 100644
--- a/tests/include/test/ssl_helpers.h
+++ b/tests/include/test/ssl_helpers.h
@@ -78,6 +78,10 @@
 #undef MBEDTLS_SSL_TLS1_3_LABEL
 };
 
+#if defined(MBEDTLS_SSL_ALPN)
+#define MBEDTLS_TEST_MAX_ALPN_LIST_SIZE 10
+#endif
+
 typedef struct mbedtls_test_ssl_log_pattern {
     const char *pattern;
     size_t counter;
@@ -114,9 +118,13 @@
     void (*cli_log_fun)(void *, int, const char *, int, const char *);
     int resize_buffers;
     int early_data;
+    int max_early_data_size;
 #if defined(MBEDTLS_SSL_CACHE_C)
     mbedtls_ssl_cache_context *cache;
 #endif
+#if defined(MBEDTLS_SSL_ALPN)
+    const char *alpn_list[MBEDTLS_TEST_MAX_ALPN_LIST_SIZE];
+#endif
 } mbedtls_test_handshake_test_options;
 
 /*
@@ -196,6 +204,13 @@
 #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
 /*
+ * Random number generator aimed for TLS unitary tests. Its main purpose is to
+ * simplify the set-up of a random number generator for TLS
+ * unitary tests: no need to set up a good entropy source for example.
+ */
+int mbedtls_test_random(void *p_rng, unsigned char *output, size_t output_len);
+
+/*
  * This function can be passed to mbedtls to receive output logs from it. In
  * this case, it will count the instances of a mbedtls_test_ssl_log_pattern
  * in the received logged messages.
diff --git a/tests/opt-testcases/tls13-kex-modes.sh b/tests/opt-testcases/tls13-kex-modes.sh
index 4581bc5..bd4f877 100755
--- a/tests/opt-testcases/tls13-kex-modes.sh
+++ b/tests/opt-testcases/tls13-kex-modes.sh
@@ -23,7 +23,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -s "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -41,7 +41,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -78,7 +78,7 @@
             -S "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -s "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -96,7 +96,7 @@
             -s "found pre_shared_key extension" \
             -S "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -133,7 +133,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -151,7 +151,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -188,7 +188,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -206,7 +206,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -261,7 +261,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -280,7 +280,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -319,7 +319,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -338,7 +338,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -377,7 +377,7 @@
             -S "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -s "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -396,7 +396,7 @@
             -s "found pre_shared_key extension" \
             -S "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -435,7 +435,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -454,7 +454,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -493,7 +493,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -512,7 +512,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -550,8 +550,9 @@
             -s "found pre_shared_key extension" \
             -S "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
+            -s "No suitable PSK key exchange mode" \
             -S "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -572,7 +573,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -592,7 +593,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -633,7 +634,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -653,7 +654,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -694,7 +695,7 @@
             -S "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -733,8 +734,9 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
+            -s "No suitable PSK key exchange mode" \
             -S "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -754,7 +756,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -793,7 +795,7 @@
             -S "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -921,7 +923,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -s "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -938,7 +940,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -973,7 +975,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -990,7 +992,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -1025,7 +1027,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -1042,7 +1044,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -1078,7 +1080,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -1096,7 +1098,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -1133,7 +1135,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -1151,7 +1153,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -1188,7 +1190,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -1206,7 +1208,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -1243,7 +1245,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -1261,7 +1263,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -1299,7 +1301,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -1318,7 +1320,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -1357,7 +1359,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
@@ -1376,7 +1378,7 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -1413,8 +1415,9 @@
             -s "found pre_shared_key extension" \
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -S "Found PSK KEX MODE" \
+            -s "No suitable PSK key exchange mode" \
             -S "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -1433,7 +1436,7 @@
             -s "Found PSK_EPHEMERAL KEX MODE" \
             -s "Found PSK KEX MODE" \
             -s "Pre shared key found" \
-            -S "No matched PSK or ticket" \
+            -S "No usable PSK or ticket" \
             -S "key exchange mode: psk$"  \
             -S "key exchange mode: psk_ephemeral"  \
             -s "key exchange mode: ephemeral"
@@ -1457,8 +1460,10 @@
             -S "key exchange mode: ephemeral"
 
 requires_openssl_tls1_3_with_compatible_ephemeral
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
+                             PSA_WANT_ALG_ECDH PSA_WANT_ECC_SECP_R1_256
 run_test    "TLS 1.3: O->m: psk_ephemeral group(secp256r1) check, good" \
             "$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70" \
             "$O_NEXT_CLI -tls1_3 -msg  -allow_no_dhe_kex -groups P-256 \
@@ -1470,8 +1475,10 @@
             -S "key exchange mode: ephemeral"
 
 requires_openssl_tls1_3_with_compatible_ephemeral
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
+                             PSA_WANT_ALG_ECDH PSA_WANT_ECC_SECP_R1_384
 run_test    "TLS 1.3: O->m: psk_ephemeral group(secp384r1) check, good" \
             "$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70" \
             "$O_NEXT_CLI -tls1_3 -msg  -allow_no_dhe_kex -groups secp384r1 \
@@ -1483,8 +1490,10 @@
             -S "key exchange mode: ephemeral"
 
 requires_openssl_tls1_3_with_compatible_ephemeral
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
+                             PSA_WANT_ALG_ECDH PSA_WANT_ECC_SECP_R1_521
 run_test    "TLS 1.3: O->m: psk_ephemeral group(secp521r1) check, good" \
             "$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70" \
             "$O_NEXT_CLI -tls1_3 -msg  -allow_no_dhe_kex -groups secp521r1 \
@@ -1496,8 +1505,10 @@
             -S "key exchange mode: ephemeral"
 
 requires_openssl_tls1_3_with_compatible_ephemeral
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
+                             PSA_WANT_ALG_ECDH PSA_WANT_ECC_MONTGOMERY_255
 run_test    "TLS 1.3: O->m: psk_ephemeral group(x25519) check, good" \
             "$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70" \
             "$O_NEXT_CLI -tls1_3 -msg  -allow_no_dhe_kex -groups X25519 \
@@ -1509,8 +1520,10 @@
             -S "key exchange mode: ephemeral"
 
 requires_openssl_tls1_3_with_compatible_ephemeral
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
+                             PSA_WANT_ALG_ECDH PSA_WANT_ECC_MONTGOMERY_448
 run_test    "TLS 1.3: O->m: psk_ephemeral group(x448) check, good" \
             "$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_identity=Client_identity psk=6162636465666768696a6b6c6d6e6f70" \
             "$O_NEXT_CLI -tls1_3 -msg  -allow_no_dhe_kex -groups X448 \
@@ -1521,9 +1534,11 @@
             -s "key exchange mode: psk_ephemeral"  \
             -S "key exchange mode: ephemeral"
 
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
 requires_openssl_tls1_3_with_compatible_ephemeral
-requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
+                             PSA_WANT_ALG_ECDH PSA_WANT_ECC_SECP_R1_384
 run_test "TLS 1.3 O->m: psk_ephemeral group(secp256r1->secp384r1) check, good" \
          "$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_list=Client_identity,6162636465666768696a6b6c6d6e6f70,abc,dead,def,beef groups=secp384r1" \
          "$O_NEXT_CLI_NO_CERT -tls1_3 -msg -allow_no_dhe_kex -psk_identity Client_identity -psk 6162636465666768696a6b6c6d6e6f70 -groups P-256:P-384" \
@@ -1534,12 +1549,13 @@
          -s "key exchange mode: psk_ephemeral" \
          -S "key exchange mode: ephemeral"
 
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
 requires_gnutls_tls1_3
 requires_gnutls_next_no_ticket
 requires_gnutls_next_disable_tls13_compat
-requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-requires_config_enabled PSA_WANT_ALG_ECDH
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
+                             PSA_WANT_ALG_ECDH PSA_WANT_ECC_SECP_R1_384
 run_test "TLS 1.3 G->m: psk_ephemeral group(secp256r1->secp384r1) check, good" \
          "$P_SRV tls13_kex_modes=psk_ephemeral debug_level=5 psk_list=Client_identity,6162636465666768696a6b6c6d6e6f70,abc,dead,def,beef groups=secp384r1" \
          "$G_NEXT_CLI_NO_CERT --debug=4 --single-key-share --priority NORMAL:-VERS-ALL:-KX-ALL:+ECDHE-PSK:+DHE-PSK:+PSK:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP256R1:+GROUP-SECP384R1 --pskusername Client_identity --pskkey 6162636465666768696a6b6c6d6e6f70 localhost" \
@@ -1580,7 +1596,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket"
+            -s "No usable PSK or ticket"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_SSL_SRV_C
@@ -1665,7 +1681,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "ClientHello message misses mandatory extensions."
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@@ -1711,7 +1727,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "ClientHello message misses mandatory extensions."
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@@ -1769,7 +1785,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "ClientHello message misses mandatory extensions."
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@@ -1827,7 +1843,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket"
+            -s "No usable PSK or ticket"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_SSL_SRV_C
@@ -1870,7 +1886,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "ClientHello message misses mandatory extensions."
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@@ -1916,7 +1932,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_SSL_SRV_C
@@ -2047,7 +2063,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket"
+            -s "No usable PSK or ticket"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_SSL_SRV_C
@@ -2106,7 +2122,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "key exchange mode: ephemeral"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@@ -2152,7 +2168,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "ClientHello message misses mandatory extensions."
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@@ -2199,7 +2215,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "key exchange mode: ephemeral"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@@ -2288,7 +2304,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "ClientHello message misses mandatory extensions."
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@@ -2348,7 +2364,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket"
+            -s "No usable PSK or ticket"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_SSL_SRV_C
@@ -2392,7 +2408,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "ClientHello message misses mandatory extensions."
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@@ -2438,7 +2454,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket"
+            -s "No usable PSK or ticket"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_SSL_SRV_C
@@ -2485,7 +2501,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "ClientHello message misses mandatory extensions."
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@@ -2532,7 +2548,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "ClientHello message misses mandatory extensions."
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@@ -2595,7 +2611,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -c "Selected key exchange mode: ephemeral" \
             -c "HTTP/1.0 200 OK"
 
@@ -2643,7 +2659,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "ClientHello message misses mandatory extensions."
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
@@ -2690,7 +2706,7 @@
             -c "client hello, adding pre_shared_key extension, omitting PSK binder list" \
             -c "client hello, adding psk_key_exchange_modes extension" \
             -c "client hello, adding PSK binder list" \
-            -s "No matched PSK or ticket" \
+            -s "No usable PSK or ticket" \
             -s "key exchange mode: ephemeral"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
diff --git a/tests/opt-testcases/tls13-misc.sh b/tests/opt-testcases/tls13-misc.sh
index ad062dc..10bbf19 100755
--- a/tests/opt-testcases/tls13-misc.sh
+++ b/tests/opt-testcases/tls13-misc.sh
@@ -71,120 +71,6 @@
          -S "key exchange mode: ephemeral$" \
          -s "ticket is not authentic"
 
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
-                             MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Session resumption failure, ticket authentication failed." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=8 dummy_ticket=1" \
-         "$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "sent selected_identity:" \
-         -s "key exchange mode: ephemeral" \
-         -S "key exchange mode: psk_ephemeral" \
-         -S "key exchange mode: psk$" \
-         -s "ticket is not authentic" \
-         -S "ticket is expired" \
-         -S "Invalid ticket creation time" \
-         -S "Ticket age exceeds limitation" \
-         -S "Ticket age outside tolerance window"
-
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
-                             MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Session resumption failure, ticket expired." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=8 dummy_ticket=2" \
-         "$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "sent selected_identity:" \
-         -s "key exchange mode: ephemeral" \
-         -S "key exchange mode: psk_ephemeral" \
-         -S "key exchange mode: psk$" \
-         -S "ticket is not authentic" \
-         -s "ticket is expired" \
-         -S "Invalid ticket creation time" \
-         -S "Ticket age exceeds limitation" \
-         -S "Ticket age outside tolerance window"
-
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
-                             MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Session resumption failure, invalid start time." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=8 dummy_ticket=3" \
-         "$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "sent selected_identity:" \
-         -s "key exchange mode: ephemeral" \
-         -S "key exchange mode: psk_ephemeral" \
-         -S "key exchange mode: psk$" \
-         -S "ticket is not authentic" \
-         -S "ticket is expired" \
-         -s "Invalid ticket creation time" \
-         -S "Ticket age exceeds limitation" \
-         -S "Ticket age outside tolerance window"
-
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
-                             MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Session resumption failure, ticket expired. too old" \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=8 dummy_ticket=4" \
-         "$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "sent selected_identity:" \
-         -s "key exchange mode: ephemeral" \
-         -S "key exchange mode: psk_ephemeral" \
-         -S "key exchange mode: psk$" \
-         -S "ticket is not authentic" \
-         -S "ticket is expired" \
-         -S "Invalid ticket creation time" \
-         -s "Ticket age exceeds limitation" \
-         -S "Ticket age outside tolerance window"
-
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
-                             MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Session resumption failure, age outside tolerance window, too young." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=8 dummy_ticket=5" \
-         "$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "sent selected_identity:" \
-         -s "key exchange mode: ephemeral" \
-         -S "key exchange mode: psk_ephemeral" \
-         -S "key exchange mode: psk$" \
-         -S "ticket is not authentic" \
-         -S "ticket is expired" \
-         -S "Invalid ticket creation time" \
-         -S "Ticket age exceeds limitation" \
-         -s "Ticket age outside tolerance window"
-
-requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
-                             MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Session resumption failure, age outside tolerance window, too old." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=8 dummy_ticket=6" \
-         "$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "sent selected_identity:" \
-         -s "key exchange mode: ephemeral" \
-         -S "key exchange mode: psk_ephemeral" \
-         -S "key exchange mode: psk$" \
-         -S "ticket is not authentic" \
-         -S "ticket is expired" \
-         -S "Invalid ticket creation time" \
-         -S "Ticket age exceeds limitation" \
-         -s "Ticket age outside tolerance window"
-
 requires_gnutls_tls1_3
 requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C
 requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
@@ -252,286 +138,1084 @@
             0 \
             -s "key exchange mode: ephemeral$"
 
-requires_gnutls_tls1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption" \
+         "$P_SRV debug_level=2 crt_file=data_files/server5.crt key_file=data_files/server5.key" \
+         "$P_CLI reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session... ok" \
+         -c "HTTP/1.0 200 OK" \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption with servername" \
+         "$P_SRV debug_level=2 crt_file=data_files/server5.crt key_file=data_files/server5.key \
+            sni=localhost,data_files/server2.crt,data_files/server2.key,-,-,-,polarssl.example,data_files/server1-nospace.crt,data_files/server1.key,-,-,-" \
+         "$P_CLI server_name=localhost reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session... ok" \
+         -c "HTTP/1.0 200 OK" \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption with ticket max lifetime (7d)" \
+         "$P_SRV debug_level=2 crt_file=data_files/server5.crt key_file=data_files/server5.key ticket_timeout=604800 tickets=1" \
+         "$P_CLI reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session... ok" \
+         -c "HTTP/1.0 200 OK" \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_ciphersuite_enabled TLS1-3-AES-256-GCM-SHA384
+run_test "TLS 1.3 m->m: resumption with AES-256-GCM-SHA384 only" \
+         "$P_SRV debug_level=2 crt_file=data_files/server5.crt key_file=data_files/server5.key" \
+         "$P_CLI force_ciphersuite=TLS1-3-AES-256-GCM-SHA384 reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -c "Ciphersuite is TLS1-3-AES-256-GCM-SHA384" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session... ok" \
+         -c "HTTP/1.0 200 OK" \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite: 1302 - TLS1-3-AES-256-GCM-SHA384"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_EARLY_DATA MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption with early data" \
+         "$P_SRV debug_level=4 early_data=1 crt_file=data_files/server5.crt key_file=data_files/server5.key" \
+         "$P_CLI debug_level=3 early_data=1 reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -c "HTTP/1.0 200 OK" \
+         -c "received max_early_data_size" \
+         -c "NewSessionTicket: early_data(42) extension received." \
+         -c "ClientHello: early_data(42) extension exists." \
+         -c "EncryptedExtensions: early_data(42) extension received." \
+         -c "bytes of early data written" \
+         -C "0 bytes of early data written" \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite" \
+         -s "Sent max_early_data_size" \
+         -s "NewSessionTicket: early_data(42) extension exists." \
+         -s "ClientHello: early_data(42) extension exists." \
+         -s "EncryptedExtensions: early_data(42) extension exists." \
+         -s "early data bytes read"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_EARLY_DATA MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_ciphersuite_enabled TLS1-3-AES-256-GCM-SHA384
+run_test "TLS 1.3 m->m: resumption with early data, AES-256-GCM-SHA384 only" \
+         "$P_SRV debug_level=4 early_data=1 crt_file=data_files/server5.crt key_file=data_files/server5.key" \
+         "$P_CLI debug_level=3 force_ciphersuite=TLS1-3-AES-256-GCM-SHA384 early_data=1 reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -c "Ciphersuite is TLS1-3-AES-256-GCM-SHA384" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -c "HTTP/1.0 200 OK" \
+         -c "received max_early_data_size" \
+         -c "NewSessionTicket: early_data(42) extension received." \
+         -c "ClientHello: early_data(42) extension exists." \
+         -c "EncryptedExtensions: early_data(42) extension received." \
+         -c "bytes of early data written" \
+         -C "0 bytes of early data written" \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite: 1302 - TLS1-3-AES-256-GCM-SHA384" \
+         -s "Sent max_early_data_size" \
+         -s "NewSessionTicket: early_data(42) extension exists." \
+         -s "ClientHello: early_data(42) extension exists." \
+         -s "EncryptedExtensions: early_data(42) extension exists." \
+         -s "early data bytes read"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_EARLY_DATA MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption, early data cli-enabled/srv-default" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key" \
+         "$P_CLI debug_level=3 early_data=1 reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -c "HTTP/1.0 200 OK" \
+         -C "received max_early_data_size" \
+         -C "NewSessionTicket: early_data(42) extension received." \
+         -C "ClientHello: early_data(42) extension exists." \
+         -C "EncryptedExtensions: early_data(42) extension received." \
+         -c "0 bytes of early data written" \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite" \
+         -S "Sent max_early_data_size" \
+         -S "NewSessionTicket: early_data(42) extension exists." \
+         -S "ClientHello: early_data(42) extension exists." \
+         -S "EncryptedExtensions: early_data(42) extension exists." \
+         -S "early data bytes read"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_EARLY_DATA MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption, early data cli-enabled/srv-disabled" \
+         "$P_SRV debug_level=4 early_data=0 crt_file=data_files/server5.crt key_file=data_files/server5.key" \
+         "$P_CLI debug_level=3 early_data=1 reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -c "HTTP/1.0 200 OK" \
+         -C "received max_early_data_size" \
+         -C "NewSessionTicket: early_data(42) extension received." \
+         -C "ClientHello: early_data(42) extension exists." \
+         -C "EncryptedExtensions: early_data(42) extension received." \
+         -c "0 bytes of early data written" \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite" \
+         -S "Sent max_early_data_size" \
+         -S "NewSessionTicket: early_data(42) extension exists." \
+         -S "ClientHello: early_data(42) extension exists." \
+         -S "EncryptedExtensions: early_data(42) extension exists." \
+         -S "early data bytes read"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_EARLY_DATA MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption, early data cli-default/srv-enabled" \
+         "$P_SRV debug_level=4 early_data=1 crt_file=data_files/server5.crt key_file=data_files/server5.key" \
+         "$P_CLI debug_level=3 reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -c "HTTP/1.0 200 OK" \
+         -c "received max_early_data_size" \
+         -c "NewSessionTicket: early_data(42) extension received." \
+         -C "ClientHello: early_data(42) extension exists." \
+         -C "EncryptedExtensions: early_data(42) extension received." \
+         -C "bytes of early data written" \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite" \
+         -s "Sent max_early_data_size" \
+         -s "NewSessionTicket: early_data(42) extension exists." \
+         -S "ClientHello: early_data(42) extension exists." \
+         -S "EncryptedExtensions: early_data(42) extension exists." \
+         -S "early data bytes read"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_EARLY_DATA MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption, early data cli-disabled/srv-enabled" \
+         "$P_SRV debug_level=4 early_data=1 crt_file=data_files/server5.crt key_file=data_files/server5.key" \
+         "$P_CLI debug_level=3 early_data=0 reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -c "HTTP/1.0 200 OK" \
+         -c "received max_early_data_size" \
+         -c "NewSessionTicket: early_data(42) extension received." \
+         -C "ClientHello: early_data(42) extension exists." \
+         -C "EncryptedExtensions: early_data(42) extension received." \
+         -C "bytes of early data written" \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite" \
+         -s "Sent max_early_data_size" \
+         -s "NewSessionTicket: early_data(42) extension exists." \
+         -S "ClientHello: early_data(42) extension exists." \
+         -S "EncryptedExtensions: early_data(42) extension exists." \
+         -S "early data bytes read"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, ticket lifetime too long (7d + 1s)" \
+         "$P_SRV debug_level=2 crt_file=data_files/server5.crt key_file=data_files/server5.key ticket_timeout=604801 tickets=1" \
+         "$P_CLI reco_mode=1 reconnect=1" \
+         1 \
+         -c "Protocol is TLSv1.3" \
+         -C "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session... failed" \
+         -S "Protocol is TLSv1.3" \
+         -S "key exchange mode: psk" \
+         -S "Select PSK ciphersuite" \
+         -s "Ticket lifetime (604801) is greater than 7 days."
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, ticket lifetime=0" \
+         "$P_SRV debug_level=2 crt_file=data_files/server5.crt key_file=data_files/server5.key ticket_timeout=0 tickets=1" \
+         "$P_CLI debug_level=2 reco_mode=1 reconnect=1" \
+         1 \
+         -c "Protocol is TLSv1.3" \
+         -C "Saving session for reuse... ok" \
+         -c "Discard new session ticket" \
+         -c "Reconnecting with saved session... failed" \
+         -s "Protocol is TLSv1.3" \
+         -S "key exchange mode: psk" \
+         -S "Select PSK ciphersuite"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, servername check failed" \
+         "$P_SRV debug_level=2 crt_file=data_files/server5.crt key_file=data_files/server5.key \
+            sni=localhost,data_files/server2.crt,data_files/server2.key,-,-,-,polarssl.example,data_files/server1-nospace.crt,data_files/server1.key,-,-,-" \
+         "$P_CLI debug_level=4 server_name=localhost reco_server_name=remote reco_mode=1 reconnect=1" \
+         1 \
+         -c "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -c "Hostname mismatch the session ticket, disable session resumption." \
+         -s "Protocol is TLSv1.3" \
+         -S "key exchange mode: psk" \
+         -S "Select PSK ciphersuite"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, ticket auth failed." \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=8 dummy_ticket=1" \
+         "$P_CLI reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -s "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -S "key exchange mode: psk" \
+         -s "ticket is not authentic" \
+         -S "ticket is expired" \
+         -S "Invalid ticket creation time" \
+         -S "Ticket age exceeds limitation" \
+         -S "Ticket age outside tolerance window"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, ticket expired." \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=8 dummy_ticket=2" \
+         "$P_CLI reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -s "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -S "key exchange mode: psk" \
+         -S "ticket is not authentic" \
+         -s "ticket is expired" \
+         -S "Invalid ticket creation time" \
+         -S "Ticket age exceeds limitation" \
+         -S "Ticket age outside tolerance window"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, invalid creation time." \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=8 dummy_ticket=3" \
+         "$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -s "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -S "key exchange mode: psk" \
+         -S "ticket is not authentic" \
+         -S "ticket is expired" \
+         -s "Invalid ticket creation time" \
+         -S "Ticket age exceeds limitation" \
+         -S "Ticket age outside tolerance window"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, ticket expired, too old" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=8 dummy_ticket=4" \
+         "$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -s "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -S "key exchange mode: psk" \
+         -S "ticket is not authentic" \
+         -S "ticket is expired" \
+         -S "Invalid ticket creation time" \
+         -s "Ticket age exceeds limitation" \
+         -S "Ticket age outside tolerance window"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, age outside tolerance window, too young" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=8 dummy_ticket=5" \
+         "$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -s "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -S "key exchange mode: psk" \
+         -S "ticket is not authentic" \
+         -S "ticket is expired" \
+         -S "Invalid ticket creation time" \
+         -S "Ticket age exceeds limitation" \
+         -s "Ticket age outside tolerance window"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, age outside tolerance window, too old" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=8 dummy_ticket=6" \
+         "$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -s "Protocol is TLSv1.3" \
+         -c "Saving session for reuse... ok" \
+         -c "Reconnecting with saved session" \
+         -S "key exchange mode: psk" \
+         -S "ticket is not authentic" \
+         -S "ticket is expired" \
+         -S "Invalid ticket creation time" \
+         -S "Ticket age exceeds limitation" \
+         -s "Ticket age outside tolerance window"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_EARLY_DATA
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, cli/tkt kex modes psk/none" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=7" \
+         "$P_CLI debug_level=4 tls13_kex_modes=psk_or_ephemeral reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -S "key exchange mode: psk_ephemeral" \
+         -S "key exchange mode: psk$" \
+         -s "found matched identity" \
+         -s "No suitable PSK key exchange mode" \
+         -s "No usable PSK or ticket"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
+run_test "TLS 1.3 m->m: ephemeral over psk resumption, cli/tkt kex modes psk/psk" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=8" \
+         "$P_CLI debug_level=4 tls13_kex_modes=psk_or_ephemeral reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -S "key exchange mode: psk_ephemeral" \
+         -S "key exchange mode: psk$" \
+         -s "found matched identity" \
+         -S "No suitable PSK key exchange mode" \
+         -S "No usable PSK or ticket"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, cli/tkt kex modes psk/psk_ephemeral" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=9" \
+         "$P_CLI debug_level=4 tls13_kex_modes=psk_or_ephemeral reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -S "key exchange mode: psk_ephemeral" \
+         -S "key exchange mode: psk$" \
+         -s "found matched identity" \
+         -s "No suitable PSK key exchange mode" \
+         -s "No usable PSK or ticket"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
+run_test "TLS 1.3 m->m: ephemeral over psk resumption, cli/tkt kex modes psk/psk_all" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=10" \
+         "$P_CLI debug_level=4 tls13_kex_modes=psk_or_ephemeral reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -S "key exchange mode: psk_ephemeral" \
+         -S "key exchange mode: psk$" \
+         -s "found matched identity" \
+         -S "No suitable PSK key exchange mode" \
+         -S "No usable PSK or ticket"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, cli/tkt kex modes psk_ephemeral/none" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=7" \
+         "$P_CLI debug_level=4 tls13_kex_modes=ephemeral_all reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -S "key exchange mode: psk_ephemeral" \
+         -S "key exchange mode: psk$" \
+         -s "found matched identity" \
+         -s "No suitable PSK key exchange mode" \
+         -s "No usable PSK or ticket"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, cli/tkt kex modes psk_ephemeral/psk" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=8" \
+         "$P_CLI debug_level=4 tls13_kex_modes=ephemeral_all reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -S "key exchange mode: psk_ephemeral" \
+         -S "key exchange mode: psk$" \
+         -s "found matched identity" \
+         -s "No suitable PSK key exchange mode" \
+         -s "No usable PSK or ticket"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption, cli/tkt kex modes psk_ephemeral/psk_ephemeral" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=9" \
+         "$P_CLI debug_level=4 tls13_kex_modes=ephemeral_all reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -s "key exchange mode: psk_ephemeral" \
+         -S "key exchange mode: psk$" \
+         -s "found matched identity" \
+         -S "No suitable PSK key exchange mode" \
+         -S "No usable PSK or ticket"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption, cli/tkt kex modes psk_ephemeral/psk_all" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=10" \
+         "$P_CLI debug_level=4 tls13_kex_modes=ephemeral_all reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -s "key exchange mode: psk_ephemeral" \
+         -S "key exchange mode: psk$" \
+         -s "found matched identity" \
+         -S "No suitable PSK key exchange mode" \
+         -S "No usable PSK or ticket"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption fails, cli/tkt kex modes psk_all/none" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=7" \
+         "$P_CLI debug_level=4 tls13_kex_modes=all reconnect=1" \
+         0 \
+         -c "Pre-configured PSK number = 1" \
+         -S "sent selected_identity:" \
+         -s "key exchange mode: ephemeral" \
+         -S "key exchange mode: psk_ephemeral" \
+         -S "key exchange mode: psk$" \
+         -s "No suitable PSK key exchange mode" \
+         -s "No usable PSK or ticket"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: ephemeral over psk resumption, cli/tkt kex modes psk_all/psk" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=8" \
+         "$P_CLI debug_level=4 tls13_kex_modes=all reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -S "key exchange mode: psk_ephemeral" \
+         -S "key exchange mode: psk$" \
+         -s "found matched identity" \
+         -S "No suitable PSK key exchange mode" \
+         -S "No usable PSK or ticket"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption, cli/tkt kex modes psk_all/psk_ephemeral" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=9" \
+         "$P_CLI debug_level=4 tls13_kex_modes=all reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -s "key exchange mode: psk_ephemeral" \
+         -S "key exchange mode: psk$" \
+         -s "found matched identity" \
+         -S "No suitable PSK key exchange mode" \
+         -S "No usable PSK or ticket"
+
+requires_all_configs_enabled MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: resumption, cli/tkt kex modes psk_all/psk_all" \
+         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=10" \
+         "$P_CLI debug_level=4 tls13_kex_modes=all reconnect=1" \
+         0 \
+         -c "Protocol is TLSv1.3" \
+         -s "key exchange mode: ephemeral" \
+         -s "key exchange mode: psk_ephemeral" \
+         -S "key exchange mode: psk$" \
+         -s "found matched identity" \
+         -S "No suitable PSK key exchange mode" \
+         -S "No usable PSK or ticket"
+
+requires_openssl_tls1_3_with_compatible_ephemeral
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
 requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
-run_test    "TLS 1.3 m->G: EarlyData: basic check, good" \
-            "$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK \
-                         --earlydata --maxearlydata 16384 --disable-client-cert" \
-            "$P_CLI debug_level=4 early_data=1 reco_mode=1 reconnect=1 reco_delay=900" \
+run_test    "TLS 1.3 m->O: resumption" \
+            "$O_NEXT_SRV -msg -tls1_3 -no_resume_ephemeral -no_cache --num_tickets 1" \
+            "$P_CLI reco_mode=1 reconnect=1" \
             0 \
-            -c "received max_early_data_size: 16384" \
-            -c "Reconnecting with saved session" \
-            -c "NewSessionTicket: early_data(42) extension received." \
-            -c "ClientHello: early_data(42) extension exists." \
-            -c "EncryptedExtensions: early_data(42) extension received." \
-            -c "EncryptedExtensions: early_data(42) extension exists." \
-            -c "<= write EndOfEarlyData" \
-            -s "Parsing extension 'Early Data/42' (0 bytes)" \
-            -s "Sending extension Early Data/42 (0 bytes)" \
-            -s "END OF EARLY DATA (5) was received." \
-            -s "early data accepted"
+            -c "Protocol is TLSv1.3" \
+            -c "Saving session for reuse... ok" \
+            -c "Reconnecting with saved session... ok" \
+            -c "HTTP/1.0 200 ok"
 
-requires_gnutls_tls1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_EARLY_DATA
-requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
-run_test    "TLS 1.3 m->G: EarlyData: write early data, good" \
-            "$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK --earlydata --disable-client-cert" \
-            "$P_CLI debug_level=4 early_data=1 reco_mode=1 reconnect=1 reco_delay=900" \
-            0 \
-            -c "Reconnecting with saved session" \
-            -c "NewSessionTicket: early_data(42) extension received." \
-            -c "ClientHello: early_data(42) extension exists." \
-            -c "EncryptedExtensions: early_data(42) extension received." \
-            -c "EncryptedExtensions: early_data(42) extension exists." \
-            -c "<= write early_data" \
-            -c "<= write EndOfEarlyData" \
-            -s "Parsing extension 'Early Data/42' (0 bytes)" \
-            -s "Sending extension Early Data/42 (0 bytes)" \
-            -s "END OF EARLY DATA (5) was received." \
-            -s "early data accepted" \
-            -s "decrypted early data with length"
+requires_openssl_tls1_3_with_compatible_ephemeral
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_config_disabled MBEDTLS_SSL_SESSION_TICKETS
+run_test    "TLS 1.3 m->O: resumption fails, no ticket support" \
+            "$O_NEXT_SRV -msg -tls1_3 -no_resume_ephemeral -no_cache --num_tickets 1" \
+            "$P_CLI debug_level=3 reco_mode=1 reconnect=1" \
+            1 \
+            -c "Protocol is TLSv1.3" \
+            -C "Saving session for reuse... ok" \
+            -C "Reconnecting with saved session... ok" \
+            -c "Ignore NewSessionTicket, not supported."
 
-requires_gnutls_tls1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_EARLY_DATA
-requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
-run_test    "TLS 1.3 m->G: EarlyData: no early_data in NewSessionTicket, good" \
-            "$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK --disable-client-cert" \
-            "$P_CLI debug_level=4 early_data=1 reco_mode=1 reconnect=1" \
-            0 \
-            -c "Reconnecting with saved session" \
-            -C "NewSessionTicket: early_data(42) extension received." \
-            -c "ClientHello: early_data(42) extension does not exist." \
-            -C "EncryptedExtensions: early_data(42) extension received." \
-            -C "EncryptedExtensions: early_data(42) extension exists."
-
-#TODO: OpenSSL tests don't work now. It might be openssl options issue, cause GnuTLS has worked.
+# No early data m->O tests for the time being. The option -early_data is needed
+# to enable early data on OpenSSL server and it is not compatible with the
+# -www option we usually use for testing with OpenSSL server (see
+# O_NEXT_SRV_EARLY_DATA definition). In this configuration when running the
+# ephemeral then ticket based scenario we use for early data testing the first
+# handshake fails. The following skipped test is here to illustrate the kind
+# of testing we would like to do.
 skip_next_test
-requires_openssl_tls1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_EARLY_DATA
+requires_openssl_tls1_3_with_compatible_ephemeral
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_EARLY_DATA \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
 requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
-run_test    "TLS 1.3, ext PSK, early data" \
-            "$O_NEXT_SRV_EARLY_DATA -msg -debug -tls1_3 -psk_identity 0a0b0c -psk 010203 -allow_no_dhe_kex -nocert" \
-            "$P_CLI debug_level=5 tls13_kex_modes=psk early_data=1 psk=010203 psk_identity=0a0b0c" \
-             1 \
+run_test    "TLS 1.3 m->O: resumption with early data" \
+            "$O_NEXT_SRV_EARLY_DATA -msg -tls1_3 -no_resume_ephemeral -no_cache --num_tickets 1" \
+            "$P_CLI debug_level=3 early_data=1 reco_mode=1 reconnect=1" \
+             0 \
+            -c "Protocol is TLSv1.3" \
+            -c "Saving session for reuse... ok" \
             -c "Reconnecting with saved session" \
+            -c "HTTP/1.0 200 OK" \
+            -c "received max_early_data_size: 16384" \
             -c "NewSessionTicket: early_data(42) extension received." \
             -c "ClientHello: early_data(42) extension exists." \
             -c "EncryptedExtensions: early_data(42) extension received." \
-            -c "EncryptedExtensions: early_data(42) extension ( ignored )."
+            -c "bytes of early data written" \
+            -s "decrypted early data with length:"
 
-requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
-run_test "TLS 1.3 m->m: Resumption with ticket flags, psk/none." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=7" \
-         "$P_CLI debug_level=4 tls13_kex_modes=psk_or_ephemeral reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "sent selected_identity:" \
-         -s "key exchange mode: ephemeral" \
-         -S "key exchange mode: psk_ephemeral" \
-         -S "key exchange mode: psk$" \
-         -s "No suitable key exchange mode" \
-         -s "No matched PSK or ticket"
+run_test    "TLS 1.3 m->G: resumption" \
+            "$G_NEXT_SRV -d 5 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 --disable-client-cert" \
+            "$P_CLI reco_mode=1 reconnect=1" \
+            0 \
+            -c "Protocol is TLSv1.3" \
+            -c "Saving session for reuse... ok" \
+            -c "Reconnecting with saved session... ok" \
+            -c "HTTP/1.0 200 OK"
 
-requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_config_disabled MBEDTLS_SSL_SESSION_TICKETS
+run_test    "TLS 1.3 m->G: resumption fails, no ticket support" \
+            "$G_NEXT_SRV -d 5 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 --disable-client-cert" \
+            "$P_CLI debug_level=3 reco_mode=1 reconnect=1" \
+            1 \
+            -c "Protocol is TLSv1.3" \
+            -C "Saving session for reuse... ok" \
+            -C "Reconnecting with saved session... ok" \
+            -c "Ignore NewSessionTicket, not supported."
+
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C \
+                             MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
-run_test "TLS 1.3 m->m: Resumption with ticket flags, psk/psk." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=8" \
-         "$P_CLI debug_level=4 tls13_kex_modes=psk_or_ephemeral reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "No suitable key exchange mode" \
-         -s "found matched identity"
+requires_ciphersuite_enabled TLS1-3-AES-256-GCM-SHA384
+run_test    "TLS 1.3 m->G: resumption with AES-256-GCM-SHA384 only" \
+            "$G_NEXT_SRV -d 5 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 --disable-client-cert" \
+            "$P_CLI force_ciphersuite=TLS1-3-AES-256-GCM-SHA384 reco_mode=1 reconnect=1" \
+            0 \
+            -c "Protocol is TLSv1.3" \
+            -c "Ciphersuite is TLS1-3-AES-256-GCM-SHA384" \
+            -c "Saving session for reuse... ok" \
+            -c "Reconnecting with saved session... ok" \
+            -c "HTTP/1.0 200 OK"
 
-requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_EARLY_DATA \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
-run_test "TLS 1.3 m->m: Resumption with ticket flags, psk/psk_ephemeral." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=9" \
-         "$P_CLI debug_level=4 tls13_kex_modes=psk_or_ephemeral reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "sent selected_identity:" \
-         -s "key exchange mode: ephemeral" \
-         -S "key exchange mode: psk_ephemeral" \
-         -S "key exchange mode: psk$" \
-         -s "No suitable key exchange mode" \
-         -s "No matched PSK or ticket"
+run_test    "TLS 1.3 m->G: resumption with early data" \
+            "$G_NEXT_SRV -d 5 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 --disable-client-cert \
+                         --earlydata --maxearlydata 16384" \
+            "$P_CLI debug_level=3 early_data=1 reco_mode=1 reconnect=1" \
+            0 \
+            -c "Protocol is TLSv1.3" \
+            -c "Saving session for reuse... ok" \
+            -c "Reconnecting with saved session" \
+            -c "HTTP/1.0 200 OK" \
+            -c "received max_early_data_size: 16384" \
+            -c "NewSessionTicket: early_data(42) extension received." \
+            -c "ClientHello: early_data(42) extension exists." \
+            -c "EncryptedExtensions: early_data(42) extension received." \
+            -c "bytes of early data written" \
+            -s "decrypted early data with length:"
 
-requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_EARLY_DATA \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
-run_test "TLS 1.3 m->m: Resumption with ticket flags, psk/psk_all." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=10" \
-         "$P_CLI debug_level=4 tls13_kex_modes=psk_or_ephemeral reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "No suitable key exchange mode" \
-         -s "found matched identity"
+requires_ciphersuite_enabled TLS1-3-AES-256-GCM-SHA384
+run_test    "TLS 1.3 m->G: resumption with early data, AES-256-GCM-SHA384 only" \
+            "$G_NEXT_SRV -d 5 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 --disable-client-cert \
+                         --earlydata --maxearlydata 16384" \
+            "$P_CLI debug_level=3 force_ciphersuite=TLS1-3-AES-256-GCM-SHA384 early_data=1 reco_mode=1 reconnect=1" \
+            0 \
+            -c "Protocol is TLSv1.3" \
+            -c "Ciphersuite is TLS1-3-AES-256-GCM-SHA384" \
+            -c "Saving session for reuse... ok" \
+            -c "Reconnecting with saved session" \
+            -c "HTTP/1.0 200 OK" \
+            -c "received max_early_data_size: 16384" \
+            -c "NewSessionTicket: early_data(42) extension received." \
+            -c "ClientHello: early_data(42) extension exists." \
+            -c "EncryptedExtensions: early_data(42) extension received." \
+            -c "bytes of early data written" \
+            -s "decrypted early data with length:"
 
-requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Resumption with ticket flags, psk_ephemeral/none." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=7" \
-         "$P_CLI debug_level=4 tls13_kex_modes=ephemeral_all reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "sent selected_identity:" \
-         -s "key exchange mode: ephemeral" \
-         -S "key exchange mode: psk_ephemeral" \
-         -S "key exchange mode: psk$" \
-         -s "No suitable key exchange mode" \
-         -s "No matched PSK or ticket"
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_EARLY_DATA \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
+run_test    "TLS 1.3 m->G: resumption, early data cli-enabled/srv-disabled" \
+            "$G_NEXT_SRV -d 5 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:+ECDHE-PSK:+PSK --disable-client-cert" \
+            "$P_CLI debug_level=3 early_data=1 reco_mode=1 reconnect=1" \
+            0 \
+            -c "Protocol is TLSv1.3" \
+            -c "Saving session for reuse... ok" \
+            -c "Reconnecting with saved session" \
+            -c "HTTP/1.0 200 OK" \
+            -C "received max_early_data_size: 16384" \
+            -C "NewSessionTicket: early_data(42) extension received." \
 
-requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Resumption with ticket flags, psk_ephemeral/psk." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=8" \
-         "$P_CLI debug_level=4 tls13_kex_modes=ephemeral_all reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "sent selected_identity:" \
-         -s "key exchange mode: ephemeral" \
-         -S "key exchange mode: psk_ephemeral" \
-         -S "key exchange mode: psk$" \
-         -s "No suitable key exchange mode" \
-         -s "No matched PSK or ticket"
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_EARLY_DATA \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
+run_test    "TLS 1.3 m->G: resumption, early data cli-default/srv-enabled" \
+            "$G_NEXT_SRV -d 5 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 --disable-client-cert \
+                         --earlydata --maxearlydata 16384" \
+            "$P_CLI debug_level=3 reco_mode=1 reconnect=1" \
+            0 \
+            -c "Protocol is TLSv1.3" \
+            -c "Saving session for reuse... ok" \
+            -c "Reconnecting with saved session" \
+            -c "HTTP/1.0 200 OK" \
+            -c "received max_early_data_size: 16384" \
+            -c "NewSessionTicket: early_data(42) extension received." \
+            -C "ClientHello: early_data(42) extension exists." \
 
-requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Resumption with ticket flags, psk_ephemeral/psk_ephemeral." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=9" \
-         "$P_CLI debug_level=4 tls13_kex_modes=ephemeral_all reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "No suitable key exchange mode" \
-         -s "found matched identity" \
-         -s "key exchange mode: psk_ephemeral"
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_EARLY_DATA \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
+run_test    "TLS 1.3 m->G: resumption, early data cli-disabled/srv-enabled" \
+            "$G_NEXT_SRV -d 5 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 --disable-client-cert \
+                         --earlydata --maxearlydata 16384" \
+            "$P_CLI debug_level=3 early_data=0 reco_mode=1 reconnect=1" \
+            0 \
+            -c "Protocol is TLSv1.3" \
+            -c "Saving session for reuse... ok" \
+            -c "Reconnecting with saved session" \
+            -c "HTTP/1.0 200 OK" \
+            -c "received max_early_data_size: 16384" \
+            -c "NewSessionTicket: early_data(42) extension received." \
+            -C "ClientHello: early_data(42) extension exists." \
 
-requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+requires_openssl_tls1_3_with_compatible_ephemeral
+requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Resumption with ticket flags, psk_ephemeral/psk_all." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=10" \
-         "$P_CLI debug_level=4 tls13_kex_modes=ephemeral_all reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "No suitable key exchange mode" \
-         -s "found matched identity" \
-         -s "key exchange mode: psk_ephemeral"
+# https://github.com/openssl/openssl/issues/10714
+# Until now, OpenSSL client does not support reconnect.
+skip_next_test
+run_test    "TLS 1.3 O->m: resumption" \
+            "$P_SRV debug_level=2 tickets=1" \
+            "$O_NEXT_CLI -msg -debug -tls1_3 -reconnect" \
+            0 \
+            -s "Protocol is TLSv1.3" \
+            -s "key exchange mode: psk" \
+            -s "Select PSK ciphersuite"
 
-requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Resumption with ticket flags, psk_all/none." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=7" \
-         "$P_CLI debug_level=4 tls13_kex_modes=all reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "sent selected_identity:" \
-         -s "key exchange mode: ephemeral" \
-         -S "key exchange mode: psk_ephemeral" \
-         -S "key exchange mode: psk$" \
-         -s "No suitable key exchange mode" \
-         -s "No matched PSK or ticket"
+run_test    "TLS 1.3 G->m: resumption" \
+            "$P_SRV debug_level=2 tickets=1" \
+            "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 -V -r" \
+            0 \
+            -s "Protocol is TLSv1.3" \
+            -s "key exchange mode: psk" \
+            -s "Select PSK ciphersuite"
 
-requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Resumption with ticket flags, psk_all/psk." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=8" \
-         "$P_CLI debug_level=4 tls13_kex_modes=all reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "No suitable key exchange mode" \
-         -s "found matched identity"
-
-requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Resumption with ticket flags, psk_all/psk_ephemeral." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=9" \
-         "$P_CLI debug_level=4 tls13_kex_modes=all reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "No suitable key exchange mode" \
-         -s "found matched identity" \
-         -s "key exchange mode: psk_ephemeral"
-
-requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_CLI_C MBEDTLS_DEBUG_C \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 m->m: Resumption with ticket flags, psk_all/psk_all." \
-         "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key dummy_ticket=10" \
-         "$P_CLI debug_level=4 tls13_kex_modes=all reconnect=1" \
-         0 \
-         -c "Pre-configured PSK number = 1" \
-         -S "No suitable key exchange mode" \
-         -s "found matched identity" \
-         -s "key exchange mode: psk_ephemeral"
+requires_ciphersuite_enabled TLS1-3-AES-256-GCM-SHA384
+# Test the session resumption when the cipher suite for the original session is
+# TLS1-3-AES-256-GCM-SHA384. In that case, the PSK is 384 bits long and not
+# 256 bits long as with all the other TLS 1.3 cipher suites.
+run_test    "TLS 1.3 G->m: resumption with AES-256-GCM-SHA384 only" \
+            "$P_SRV debug_level=2 tickets=1" \
+            "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM -V -r" \
+            0 \
+            -s "Protocol is TLSv1.3" \
+            -s "key exchange mode: psk" \
+            -s "Select PSK ciphersuite: 1302 - TLS1-3-AES-256-GCM-SHA384"
 
 EARLY_DATA_INPUT_LEN_BLOCKS=$(( ( $( cat $EARLY_DATA_INPUT | wc -c ) + 31 ) / 32 ))
 EARLY_DATA_INPUT_LEN=$(( $EARLY_DATA_INPUT_LEN_BLOCKS * 32 ))
 
-requires_gnutls_next
-requires_all_configs_enabled MBEDTLS_SSL_EARLY_DATA MBEDTLS_SSL_SESSION_TICKETS \
-                             MBEDTLS_SSL_SRV_C MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_EARLY_DATA MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
 requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test "TLS 1.3 G->m: EarlyData: feature is enabled, good." \
-         "$P_SRV force_version=tls13 debug_level=4 max_early_data_size=$EARLY_DATA_INPUT_LEN" \
-         "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+GROUP-ALL:+KX-ALL \
-                      -d 10 -r --earlydata $EARLY_DATA_INPUT " \
+run_test "TLS 1.3 G->m: resumption with early data" \
+         "$P_SRV debug_level=4 tickets=1 early_data=1 max_early_data_size=$EARLY_DATA_INPUT_LEN" \
+         "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 -V -r \
+                      --earlydata $EARLY_DATA_INPUT" \
          0 \
-         -s "Sent max_early_data_size=$EARLY_DATA_INPUT_LEN"                \
-         -s "NewSessionTicket: early_data(42) extension exists."            \
-         -s "ClientHello: early_data(42) extension exists."                 \
-         -s "EncryptedExtensions: early_data(42) extension exists."         \
-         -s "$( head -1 $EARLY_DATA_INPUT )"                                \
-         -s "$( tail -1 $EARLY_DATA_INPUT )"                                \
-         -s "200 early data bytes read"                                     \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite" \
+         -s "Sent max_early_data_size=$EARLY_DATA_INPUT_LEN"        \
+         -s "NewSessionTicket: early_data(42) extension exists."    \
+         -s "ClientHello: early_data(42) extension exists."         \
+         -s "EncryptedExtensions: early_data(42) extension exists." \
+         -s "$( head -1 $EARLY_DATA_INPUT )"                        \
+         -s "$( tail -1 $EARLY_DATA_INPUT )"                        \
+         -s "200 early data bytes read"                             \
          -s "106 early data bytes read"
+
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_EARLY_DATA MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_ciphersuite_enabled TLS1-3-AES-256-GCM-SHA384
+run_test "TLS 1.3 G->m: resumption with early data, AES-256-GCM-SHA384 only" \
+         "$P_SRV debug_level=4 tickets=1 early_data=1 max_early_data_size=$EARLY_DATA_INPUT_LEN" \
+         "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM -V -r \
+                      --earlydata $EARLY_DATA_INPUT" \
+         0 \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite: 1302 - TLS1-3-AES-256-GCM-SHA384" \
+         -s "Sent max_early_data_size=$EARLY_DATA_INPUT_LEN"        \
+         -s "NewSessionTicket: early_data(42) extension exists."    \
+         -s "ClientHello: early_data(42) extension exists."         \
+         -s "EncryptedExtensions: early_data(42) extension exists." \
+         -s "$( head -1 $EARLY_DATA_INPUT )"                        \
+         -s "$( tail -1 $EARLY_DATA_INPUT )"                        \
+         -s "200 early data bytes read"                             \
+         -s "106 early data bytes read"
+
+# The Mbed TLS server does not allow early data for the ticket it sends but
+# the GnuTLS indicates early data anyway when resuming with the ticket and
+# sends early data. The Mbed TLS server does not expect early data in
+# association with the ticket thus it eventually fails the resumption
+# handshake. The GnuTLS client behavior is not compliant here with the TLS 1.3
+# specification and thus its behavior may change in following versions.
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_EARLY_DATA MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 G->m: resumption, early data cli-enabled/srv-default" \
+         "$P_SRV debug_level=4 tickets=1" \
+         "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 -V -r \
+                      --earlydata $EARLY_DATA_INPUT" \
+         1 \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite" \
+         -S "Sent max_early_data_size" \
+         -S "NewSessionTicket: early_data(42) extension exists." \
+         -s "ClientHello: early_data(42) extension exists." \
+         -s "EarlyData: rejected, feature disabled in server configuration." \
+         -S "EncryptedExtensions: early_data(42) extension exists." \
+         -s "EarlyData: deprotect and discard app data records" \
+         -s "EarlyData: Too much early data received"
+
+# The Mbed TLS server does not allow early data for the ticket it sends but
+# the GnuTLS indicates early data anyway when resuming with the ticket and
+# sends early data. The Mbed TLS server does not expect early data in
+# association with the ticket thus it eventually fails the resumption
+# handshake. The GnuTLS client behavior is not compliant here with the TLS 1.3
+# specification and thus its behavior may change in following versions.
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_EARLY_DATA MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 G->m: resumption, early data cli-enabled/srv-disabled" \
+         "$P_SRV debug_level=4 tickets=1 early_data=0" \
+         "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 -V -r \
+                      --earlydata $EARLY_DATA_INPUT" \
+         1 \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite" \
+         -S "Sent max_early_data_size" \
+         -S "NewSessionTicket: early_data(42) extension exists." \
+         -s "ClientHello: early_data(42) extension exists." \
+         -s "EarlyData: rejected, feature disabled in server configuration." \
+         -S "EncryptedExtensions: early_data(42) extension exists." \
+         -s "EarlyData: deprotect and discard app data records" \
+         -s "EarlyData: Too much early data received"
+
+requires_gnutls_tls1_3
+requires_all_configs_enabled MBEDTLS_SSL_SESSION_TICKETS MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_SRV_C MBEDTLS_SSL_EARLY_DATA MBEDTLS_DEBUG_C \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+run_test "TLS 1.3 G->m: resumption, early data cli-disabled/srv-enabled" \
+         "$P_SRV debug_level=4 tickets=1 early_data=1" \
+         "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 -V -r" \
+         0 \
+         -s "Protocol is TLSv1.3" \
+         -s "key exchange mode: psk" \
+         -s "Select PSK ciphersuite" \
+         -s "Sent max_early_data_size" \
+         -s "NewSessionTicket: early_data(42) extension exists." \
+         -S "ClientHello: early_data(42) extension exists." \
+         -S "EncryptedExtensions: early_data(42) extension exists."
+
+requires_all_configs_enabled MBEDTLS_SSL_EARLY_DATA MBEDTLS_SSL_SESSION_TICKETS \
+                             MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_DEBUG_C MBEDTLS_HAVE_TIME \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+run_test "TLS 1.3 m->m: Ephemeral over PSK kex with early data enabled" \
+         "$P_SRV force_version=tls13 debug_level=4 early_data=1 max_early_data_size=1024" \
+         "$P_CLI debug_level=4 early_data=1 tls13_kex_modes=psk_or_ephemeral reco_mode=1 reconnect=1" \
+         0 \
+         -s "key exchange mode: ephemeral" \
+         -S "key exchange mode: psk" \
+         -s "found matched identity" \
+         -s "EarlyData: rejected, not a session resumption" \
+         -C "EncryptedExtensions: early_data(42) extension exists."
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 34a7bc2..28009d5 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -44,7 +44,7 @@
 #     * GNUTLS_{CLI,SERV} = 3.4.10
 #     * GNUTLS_NEXT_{CLI,SERV} = 3.7.2
 #     * OPENSSL = 1.0.2g (without Debian/Ubuntu patches)
-#     * OPENSSL_NEXT = 1.1.1a
+#     * OPENSSL_NEXT = 3.1.2
 # See the invocation of check_tools below for details.
 #
 # This script must be invoked from the toplevel directory of a git
@@ -195,6 +195,10 @@
         export CC="clang"
     fi
 
+    if [ -n "${OPENSSL_3+set}" ]; then
+        export OPENSSL_NEXT="$OPENSSL_3"
+    fi
+
     # Include more verbose output for failing tests run by CMake or make
     export CTEST_OUTPUT_ON_FAILURE=1
 
@@ -900,8 +904,51 @@
     # Dynamic secure element support is a deprecated feature and needs to be disabled here.
     # This is done to have the same form of psa_key_attributes_s for libdriver and library.
     scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C
+
+    # If threading is enabled on the normal build, then we need to enable it in the drivers as well,
+    # otherwise we will end up running multithreaded tests without mutexes to protect them.
+    if scripts/config.py get MBEDTLS_THREADING_C; then
+        scripts/config.py -f "$CONFIG_TEST_DRIVER_H" set MBEDTLS_THREADING_C
+    fi
+
+    if scripts/config.py get MBEDTLS_THREADING_PTHREAD; then
+        scripts/config.py -f "$CONFIG_TEST_DRIVER_H" set MBEDTLS_THREADING_PTHREAD
+    fi
 }
 
+# Build the drivers library libtestdriver1.a (with ASan).
+#
+# Parameters:
+# 1. a space-separated list of things to accelerate;
+# 2. optional: a space-separate list of things to also support.
+# Here "things" are PSA_WANT_ symbols but with PSA_WANT_ removed.
+helper_libtestdriver1_make_drivers() {
+    loc_accel_flags=$( echo "$1 ${2-}" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
+    make CC=$ASAN_CC -C tests libtestdriver1.a CFLAGS=" $ASAN_CFLAGS $loc_accel_flags" LDFLAGS="$ASAN_CFLAGS"
+}
+
+# Build the main libraries, programs and tests,
+# linking to the drivers library (with ASan).
+#
+# Parameters:
+# 1. a space-separated list of things to accelerate;
+# *. remaining arguments if any are passed directly to make
+#    (examples: lib, -C tests test_suite_xxx, etc.)
+# Here "things" are PSA_WANT_ symbols but with PSA_WANT_ removed.
+helper_libtestdriver1_make_main() {
+    loc_accel_list=$1
+    shift
+
+    # we need flags both with and without the LIBTESTDRIVER1_ prefix
+    loc_accel_flags=$( echo "$loc_accel_list" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
+    loc_accel_flags="$loc_accel_flags $( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
+    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -I../tests/include -I../tests -I../../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS" "$@"
+}
+
+################################################################
+#### Configuration helpers
+################################################################
+
 # When called with no parameter this function disables all builtin curves.
 # The function optionally accepts 1 parameter: a space-separated list of the
 # curves that should be kept enabled.
@@ -955,35 +1002,6 @@
     echo "$loc_list"
 }
 
-# Build the drivers library libtestdriver1.a (with ASan).
-#
-# Parameters:
-# 1. a space-separated list of things to accelerate;
-# 2. optional: a space-separate list of things to also support.
-# Here "things" are PSA_WANT_ symbols but with PSA_WANT_ removed.
-helper_libtestdriver1_make_drivers() {
-    loc_accel_flags=$( echo "$1 ${2-}" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
-    make CC=$ASAN_CC -C tests libtestdriver1.a CFLAGS=" $ASAN_CFLAGS $loc_accel_flags" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# Build the main libraries, programs and tests,
-# linking to the drivers library (with ASan).
-#
-# Parameters:
-# 1. a space-separated list of things to accelerate;
-# *. remaining arguments if any are passed directly to make
-#    (examples: lib, -C tests test_suite_xxx, etc.)
-# Here "things" are PSA_WANT_ symbols but with PSA_WANT_ removed.
-helper_libtestdriver1_make_main() {
-    loc_accel_list=$1
-    shift
-
-    # we need flags both with and without the LIBTESTDRIVER1_ prefix
-    loc_accel_flags=$( echo "$loc_accel_list" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
-    loc_accel_flags="$loc_accel_flags $( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -I../tests/include -I../tests -I../../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS" "$@"
-}
-
 ################################################################
 #### Basic checks
 ################################################################
@@ -1081,7 +1099,7 @@
     grep 'depends_on' \
         tests/suites/test_suite_psa*.data tests/suites/test_suite_psa*.function |
         grep -Eo '!?MBEDTLS_[^: ]*' |
-        grep -v MBEDTLS_PSA_ |
+        grep -v -e MBEDTLS_PSA_ -e MBEDTLS_TEST_ |
         sort -u > $found
 
     # Expected ones with justification - keep in sorted order by ASCII table!
@@ -1100,6 +1118,8 @@
     echo "MBEDTLS_ECP_RESTARTABLE" >> $expected
     # No PSA equivalent - needed by some init tests
     echo "MBEDTLS_ENTROPY_NV_SEED" >> $expected
+    # No PSA equivalent - required to run threaded tests.
+    echo "MBEDTLS_THREADING_PTHREAD" >> $expected
 
     # Compare reality with expectation.
     # We want an exact match, to ensure the above list remains up-to-date.
@@ -1157,7 +1177,7 @@
     programs/test/selftest
 
     msg "test: metatests (GCC, ASan build)"
-    tests/scripts/run-metatests.sh any asan
+    tests/scripts/run-metatests.sh any asan poison
 
     msg "test: ssl-opt.sh (ASan build)" # ~ 1 min
     tests/ssl-opt.sh
@@ -1200,14 +1220,19 @@
     msg "test: main suites (inc. selftests) (full config, ASan build)"
     make test
 
-    msg "test: selftest (ASan build)" # ~ 10s
+    msg "test: selftest (full config, ASan build)" # ~ 10s
     programs/test/selftest
 
     msg "test: ssl-opt.sh (full config, ASan build)"
     tests/ssl-opt.sh
 
-    msg "test: compat.sh (full config, ASan build)"
-    tests/compat.sh
+    # Note: the next two invocations cover all compat.sh test cases.
+    # We should use the same here and in basic-build-test.sh.
+    msg "test: compat.sh: default version (full config, ASan build)"
+    tests/compat.sh -e 'ARIA\|CHACHA'
+
+    msg "test: compat.sh: next: ARIA, Chacha (full config, ASan build)"
+    env OPENSSL="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
 
     msg "test: context-info.sh (full config, ASan build)" # ~ 15 sec
     tests/context-info.sh
@@ -1221,19 +1246,24 @@
     CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
     make
 
-    msg "test: main suites (inc. selftests) (full config, ASan build)"
+    msg "test: main suites (inc. selftests) (full config, new bignum, ASan)"
     make test
 
-    msg "test: selftest (ASan build)" # ~ 10s
+    msg "test: selftest (full config, new bignum, ASan)" # ~ 10s
     programs/test/selftest
 
-    msg "test: ssl-opt.sh (full config, ASan build)"
+    msg "test: ssl-opt.sh (full config, new bignum, ASan)"
     tests/ssl-opt.sh
 
-    msg "test: compat.sh (full config, ASan build)"
-    tests/compat.sh
+    # Note: the next two invocations cover all compat.sh test cases.
+    # We should use the same here and in basic-build-test.sh.
+    msg "test: compat.sh: default version (full config, new bignum, ASan)"
+    tests/compat.sh -e 'ARIA\|CHACHA'
 
-    msg "test: context-info.sh (full config, ASan build)" # ~ 15 sec
+    msg "test: compat.sh: next: ARIA, Chacha (full config, new bignum, ASan)"
+    env OPENSSL="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
+
+    msg "test: context-info.sh (full config, new bignum, ASan)" # ~ 15 sec
     tests/context-info.sh
 }
 
@@ -1248,6 +1278,17 @@
     make test
 }
 
+component_test_psa_assume_exclusive_buffers () {
+    msg "build: full config + MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS, cmake, gcc, ASan"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+    make
+
+    msg "test: full config + MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS, cmake, gcc, ASan"
+    make test
+}
+
 # check_renamed_symbols HEADER LIB
 # Check that if HEADER contains '#define MACRO ...' then MACRO is not a symbol
 # name is LIB.
@@ -1273,25 +1314,76 @@
     check_renamed_symbols tests/include/spe/crypto_spe.h library/libmbedcrypto.a
 }
 
-component_test_psa_crypto_client () {
-    msg "build: default config - PSA_CRYPTO_C + PSA_CRYPTO_CLIENT, make"
+# Get a list of library-wise undefined symbols and ensure that they only
+# belong to psa_xxx() functions and not to mbedtls_yyy() ones.
+# This function is a common helper used by both:
+# - component_test_default_psa_crypto_client_without_crypto_provider
+# - component_build_full_psa_crypto_client_without_crypto_provider.
+common_check_mbedtls_missing_symbols() {
+    nm library/libmbedcrypto.a | grep ' [TRrDC] ' | grep -Eo '(mbedtls_|psa_).*' | sort -u > sym_def.txt
+    nm library/libmbedcrypto.a | grep ' U ' | grep -Eo '(mbedtls_|psa_).*' | sort -u > sym_undef.txt
+    comm sym_def.txt sym_undef.txt -13 > linking_errors.txt
+    not grep mbedtls_ linking_errors.txt
+
+    rm sym_def.txt sym_undef.txt linking_errors.txt
+}
+
+component_test_default_psa_crypto_client_without_crypto_provider () {
+    msg "build: default config - PSA_CRYPTO_C + PSA_CRYPTO_CLIENT"
+
     scripts/config.py unset MBEDTLS_PSA_CRYPTO_C
     scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C
+    scripts/config.py unset MBEDTLS_PSA_ITS_FILE_C
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
     scripts/config.py set MBEDTLS_PSA_CRYPTO_CLIENT
     scripts/config.py unset MBEDTLS_LMS_C
-    scripts/config.py unset MBEDTLS_LMS_PRIVATE
+
     make
 
-    msg "test: default config - PSA_CRYPTO_C + PSA_CRYPTO_CLIENT, make"
+    msg "check missing symbols: default config - PSA_CRYPTO_C + PSA_CRYPTO_CLIENT"
+    common_check_mbedtls_missing_symbols
+
+    msg "test: default config - PSA_CRYPTO_C + PSA_CRYPTO_CLIENT"
     make test
 }
 
-component_test_psa_crypto_rsa_no_genprime() {
-    msg "build: default config minus MBEDTLS_GENPRIME"
+component_build_full_psa_crypto_client_without_crypto_provider () {
+    msg "build: full config - PSA_CRYPTO_C"
+
+    # Use full config which includes USE_PSA and CRYPTO_CLIENT.
+    scripts/config.py full
+
+    scripts/config.py unset MBEDTLS_PSA_CRYPTO_C
+    scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C
+    # Dynamic secure element support is a deprecated feature and it is not
+    # available when CRYPTO_C and PSA_CRYPTO_STORAGE_C are disabled.
+    scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C
+
+    # Since there is no crypto provider in this build it is not possible to
+    # build all the test executables and progrems due to missing PSA functions
+    # at link time. Therefore we will just build libraries and we'll check
+    # that symbols of interest are there.
+    make lib
+
+    msg "check missing symbols: full config - PSA_CRYPTO_C"
+
+    common_check_mbedtls_missing_symbols
+
+    # Ensure that desired functions are included into the build (extend the
+    # following list as required).
+    grep mbedtls_pk_get_psa_attributes library/libmbedcrypto.a
+    grep mbedtls_pk_import_into_psa library/libmbedcrypto.a
+    grep mbedtls_pk_copy_from_psa library/libmbedcrypto.a
+}
+
+component_test_no_rsa_key_pair_generation() {
+    msg "build: default config minus PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE"
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
     scripts/config.py unset MBEDTLS_GENPRIME
+    scripts/config.py -f $CRYPTO_CONFIG_H unset PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE
     make
 
-    msg "test: default config minus MBEDTLS_GENPRIME"
+    msg "test: default config minus PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE"
     make test
 }
 
@@ -1542,6 +1634,23 @@
     make test
 }
 
+component_full_no_pkparse_pkwrite() {
+    msg "build: full without pkparse and pkwrite"
+
+    scripts/config.py crypto_full
+    scripts/config.py unset MBEDTLS_PK_PARSE_C
+    scripts/config.py unset MBEDTLS_PK_WRITE_C
+
+    make CFLAGS="$ASAN_CFLAGS" LDFLAGS="$ASAN_CFLAGS"
+
+    # Ensure that PK_[PARSE|WRITE]_C were not re-enabled accidentally (additive config).
+    not grep mbedtls_pk_parse_key library/pkparse.o
+    not grep mbedtls_pk_write_key_der library/pkwrite.o
+
+    msg "test: full without pkparse and pkwrite"
+    make test
+}
+
 component_test_crypto_full_md_light_only () {
     msg "build: crypto_full with only the light subset of MD"
     scripts/config.py crypto_full
@@ -1766,6 +1875,8 @@
     scripts/config.py unset MBEDTLS_GCM_C
     scripts/config.py unset MBEDTLS_CCM_C
     scripts/config.py unset MBEDTLS_CHACHAPOLY_C
+    #Disable TLS 1.3 (as no AEAD)
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
     # Disable CBC-legacy (controlled by MBEDTLS_CIPHER_MODE_CBC plus at least one block cipher (AES, ARIA, Camellia, DES))
     scripts/config.py unset MBEDTLS_CIPHER_MODE_CBC
     # Disable CBC-EtM (controlled by the same as CBC-legacy plus MBEDTLS_SSL_ENCRYPT_THEN_MAC)
@@ -1792,6 +1903,8 @@
     scripts/config.py unset MBEDTLS_GCM_C
     scripts/config.py unset MBEDTLS_CCM_C
     scripts/config.py unset MBEDTLS_CHACHAPOLY_C
+    #Disable TLS 1.3 (as no AEAD)
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
     # Disable CBC-legacy (controlled by MBEDTLS_CIPHER_MODE_CBC plus at least one block cipher (AES, ARIA, Camellia, DES))
     scripts/config.py unset MBEDTLS_CIPHER_MODE_CBC
     # Disable CBC-EtM (controlled by the same as CBC-legacy plus MBEDTLS_SSL_ENCRYPT_THEN_MAC)
@@ -1817,6 +1930,8 @@
     scripts/config.py unset MBEDTLS_GCM_C
     scripts/config.py unset MBEDTLS_CCM_C
     scripts/config.py unset MBEDTLS_CHACHAPOLY_C
+    #Disable TLS 1.3 (as no AEAD)
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
     # Enable CBC-legacy (controlled by MBEDTLS_CIPHER_MODE_CBC plus at least one block cipher (AES, ARIA, Camellia, DES))
     scripts/config.py set MBEDTLS_CIPHER_MODE_CBC
     # Disable CBC-EtM (controlled by the same as CBC-legacy plus MBEDTLS_SSL_ENCRYPT_THEN_MAC)
@@ -1844,6 +1959,8 @@
     scripts/config.py unset MBEDTLS_GCM_C
     scripts/config.py unset MBEDTLS_CCM_C
     scripts/config.py unset MBEDTLS_CHACHAPOLY_C
+    #Disable TLS 1.3 (as no AEAD)
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
     # Enable CBC-legacy (controlled by MBEDTLS_CIPHER_MODE_CBC plus at least one block cipher (AES, ARIA, Camellia, DES))
     scripts/config.py set MBEDTLS_CIPHER_MODE_CBC
     # Disable CBC-EtM (controlled by the same as CBC-legacy plus MBEDTLS_SSL_ENCRYPT_THEN_MAC)
@@ -1870,6 +1987,8 @@
     scripts/config.py unset MBEDTLS_GCM_C
     scripts/config.py unset MBEDTLS_CCM_C
     scripts/config.py unset MBEDTLS_CHACHAPOLY_C
+    #Disable TLS 1.3 (as no AEAD)
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
     # Enable CBC-legacy (controlled by MBEDTLS_CIPHER_MODE_CBC plus at least one block cipher (AES, ARIA, Camellia, DES))
     scripts/config.py set MBEDTLS_CIPHER_MODE_CBC
     # Enable CBC-EtM (controlled by the same as CBC-legacy plus MBEDTLS_SSL_ENCRYPT_THEN_MAC)
@@ -1897,6 +2016,8 @@
     scripts/config.py unset MBEDTLS_GCM_C
     scripts/config.py unset MBEDTLS_CCM_C
     scripts/config.py unset MBEDTLS_CHACHAPOLY_C
+    #Disable TLS 1.3 (as no AEAD)
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
     # Enable CBC-legacy (controlled by MBEDTLS_CIPHER_MODE_CBC plus at least one block cipher (AES, ARIA, Camellia, DES))
     scripts/config.py set MBEDTLS_CIPHER_MODE_CBC
     # Enable CBC-EtM (controlled by the same as CBC-legacy plus MBEDTLS_SSL_ENCRYPT_THEN_MAC)
@@ -1959,7 +2080,7 @@
     make test
 
     msg "test: metatests (clang, ASan)"
-    tests/scripts/run-metatests.sh any asan
+    tests/scripts/run-metatests.sh any asan poison
 
     msg "test: Everest ECDH context - ECDH-related part of ssl-opt.sh (ASan build)" # ~ 5s
     tests/ssl-opt.sh -f ECDH
@@ -2060,12 +2181,6 @@
 
     msg "test: ssl-opt.sh default, ECJPAKE, SSL async (full config)" # ~ 1s
     tests/ssl-opt.sh -f 'Default\|ECJPAKE\|SSL async private'
-
-    msg "test: compat.sh NULL (full config)" # ~ 2 min
-    tests/compat.sh -e '^$' -f 'NULL'
-
-    msg "test: compat.sh ARIA + ChachaPoly"
-    env OPENSSL="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
 }
 
 skip_suites_without_constant_flow () {
@@ -2188,6 +2303,11 @@
     scripts/config.py full
     scripts/config.py set MBEDTLS_THREADING_C
     scripts/config.py set MBEDTLS_THREADING_PTHREAD
+    # Self-tests do not currently use multiple threads.
+    scripts/config.py unset MBEDTLS_SELF_TEST
+
+    # The deprecated MBEDTLS_PSA_CRYPTO_SE_C interface is not thread safe.
+    scripts/config.py unset MBEDTLS_PSA_CRYPTO_SE_C
 
     CC=clang cmake -D CMAKE_BUILD_TYPE:String=TSan .
     make
@@ -2504,13 +2624,12 @@
     msg "test: ssl-opt.sh (full minus PSA crypto)"
     tests/ssl-opt.sh
 
-    msg "test: compat.sh default (full minus PSA crypto)"
-    tests/compat.sh
+    # Note: the next two invocations cover all compat.sh test cases.
+    # We should use the same here and in basic-build-test.sh.
+    msg "test: compat.sh: default version (full minus PSA crypto)"
+    tests/compat.sh -e 'ARIA\|CHACHA'
 
-    msg "test: compat.sh NULL (full minus PSA crypto)"
-    tests/compat.sh -f 'NULL'
-
-    msg "test: compat.sh ARIA + ChachaPoly (full minus PSA crypto)"
+    msg "test: compat.sh: next: ARIA, Chacha (full minus PSA crypto)"
     env OPENSSL="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
 }
 
@@ -2527,7 +2646,6 @@
 
     # Start from default config (no USE_PSA) + TLS 1.3
     helper_libtestdriver1_adjust_config "default"
-    scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3
 
     # Disable the module that's accelerated
     scripts/config.py unset MBEDTLS_ECDSA_C
@@ -2568,7 +2686,7 @@
     # Configure
     # ---------
 
-    # Start from default config (no TLS 1.3, no USE_PSA)
+    # Start from default config (no USE_PSA)
     helper_libtestdriver1_adjust_config "default"
 
     # Disable the module that's accelerated
@@ -3561,7 +3679,7 @@
     # Configure
     # ---------
 
-    # Start from default config (no TLS 1.3, no USE_PSA)
+    # Start from default config (no USE_PSA)
     helper_libtestdriver1_adjust_config "default"
 
     # Disable the things that are being accelerated
@@ -3596,26 +3714,6 @@
     make test
 }
 
-component_test_psa_crypto_config_accel_hash_keep_builtins () {
-    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated+builtin hash"
-    # This component ensures that all the test cases for
-    # md_psa_dynamic_dispatch with legacy+driver in test_suite_md are run.
-
-    loc_accel_list="ALG_MD5 ALG_RIPEMD160 ALG_SHA_1 \
-                    ALG_SHA_224 ALG_SHA_256 ALG_SHA_384 ALG_SHA_512 \
-                    ALG_SHA3_224 ALG_SHA3_256 ALG_SHA3_384 ALG_SHA3_512"
-
-    # Start from default config (no TLS 1.3, no USE_PSA)
-    helper_libtestdriver1_adjust_config "default"
-
-    helper_libtestdriver1_make_drivers "$loc_accel_list"
-
-    helper_libtestdriver1_make_main "$loc_accel_list"
-
-    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated+builtin hash"
-    make test
-}
-
 # Auxiliary function to build config for hashes with and without drivers
 config_psa_crypto_hash_use_psa () {
     driver_only="$1"
@@ -4069,255 +4167,6 @@
     make test
 }
 
-# This should be renamed to test and updated once the accelerator ECDH code is in place and ready to test.
-component_build_psa_accel_alg_ecdh() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_ECDH without MBEDTLS_ECDH_C"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py unset MBEDTLS_ECDH_C
-    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
-    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
-    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
-    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
-    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_ECDH -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator HMAC code is in place and ready to test.
-component_build_psa_accel_alg_hmac() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_HMAC"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_HMAC -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator HKDF code is in place and ready to test.
-component_build_psa_accel_alg_hkdf() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_HKDF without MBEDTLS_HKDF_C"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py unset MBEDTLS_HKDF_C
-    # Make sure to unset TLS1_3 since it requires HKDF_C and will not build properly without it.
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_HKDF -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator MD5 code is in place and ready to test.
-component_build_psa_accel_alg_md5() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_MD5 - other hashes"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RIPEMD160
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_224
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_256
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_384
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_512
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
-    scripts/config.py unset MBEDTLS_LMS_C
-    scripts/config.py unset MBEDTLS_LMS_PRIVATE
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_MD5 -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator RIPEMD160 code is in place and ready to test.
-component_build_psa_accel_alg_ripemd160() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_RIPEMD160 - other hashes"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_MD5
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_224
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_256
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_384
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_512
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
-    scripts/config.py unset MBEDTLS_LMS_C
-    scripts/config.py unset MBEDTLS_LMS_PRIVATE
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_RIPEMD160 -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator SHA1 code is in place and ready to test.
-component_build_psa_accel_alg_sha1() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_SHA_1 - other hashes"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_MD5
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RIPEMD160
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_224
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_256
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_384
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_512
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
-    scripts/config.py unset MBEDTLS_LMS_C
-    scripts/config.py unset MBEDTLS_LMS_PRIVATE
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_SHA_1 -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator SHA224 code is in place and ready to test.
-component_build_psa_accel_alg_sha224() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_SHA_224 - other hashes"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_MD5
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RIPEMD160
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_384
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_512
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_SHA_224 -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator SHA256 code is in place and ready to test.
-component_build_psa_accel_alg_sha256() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_SHA_256 - other hashes"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_MD5
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RIPEMD160
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_224
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_384
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_512
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_SHA_256 -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator SHA384 code is in place and ready to test.
-component_build_psa_accel_alg_sha384() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_SHA_384 - other hashes"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_MD5
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RIPEMD160
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_224
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_256
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
-    scripts/config.py unset MBEDTLS_LMS_C
-    scripts/config.py unset MBEDTLS_LMS_PRIVATE
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_SHA_384 -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator SHA512 code is in place and ready to test.
-component_build_psa_accel_alg_sha512() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_SHA_512 - other hashes"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_MD5
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RIPEMD160
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_224
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_256
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_SHA_384
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS
-    scripts/config.py unset MBEDTLS_LMS_C
-    scripts/config.py unset MBEDTLS_LMS_PRIVATE
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_SHA_512 -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator RSA code is in place and ready to test.
-component_build_psa_accel_alg_rsa_pkcs1v15_crypt() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_RSA_PKCS1V15_CRYPT + PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" set PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RSA_OAEP
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RSA_PSS
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator RSA code is in place and ready to test.
-component_build_psa_accel_alg_rsa_pkcs1v15_sign() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_RSA_PKCS1V15_SIGN + PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" set PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RSA_OAEP
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RSA_PSS
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator RSA code is in place and ready to test.
-component_build_psa_accel_alg_rsa_oaep() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_RSA_OAEP + PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" set PSA_WANT_ALG_RSA_OAEP 1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RSA_PSS
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_RSA_OAEP -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator RSA code is in place and ready to test.
-component_build_psa_accel_alg_rsa_pss() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_ALG_RSA_PSS + PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" set PSA_WANT_ALG_RSA_PSS 1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-    scripts/config.py -f "$CRYPTO_CONFIG_H" unset PSA_WANT_ALG_RSA_OAEP
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_RSA_PSS -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator RSA code is in place and ready to test.
-component_build_psa_accel_key_type_rsa_key_pair() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx + PSA_WANT_ALG_RSA_PSS"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" set PSA_WANT_ALG_RSA_PSS 1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" set PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" set PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" set PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" set PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-# This should be renamed to test and updated once the accelerator RSA code is in place and ready to test.
-component_build_psa_accel_key_type_rsa_public_key() {
-    msg "build: full - MBEDTLS_USE_PSA_CRYPTO + PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY + PSA_WANT_ALG_RSA_PSS"
-    scripts/config.py full
-    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
-    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py -f "$CRYPTO_CONFIG_H" set PSA_WANT_ALG_RSA_PSS 1
-    scripts/config.py -f "$CRYPTO_CONFIG_H" set PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    make CC=$ASAN_CC CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY -I../tests/include" LDFLAGS="$ASAN_CFLAGS"
-}
-
-
 support_build_tfm_armcc () {
     support_build_armcc
 }
@@ -4563,6 +4412,7 @@
 component_test_asan_remove_peer_certificate () {
     msg "build: default config with MBEDTLS_SSL_KEEP_PEER_CERTIFICATE disabled (ASan build)"
     scripts/config.py unset MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
     CC=$ASAN_CC cmake -D CMAKE_BUILD_TYPE:String=Asan .
     make
 
@@ -4767,6 +4617,26 @@
     not grep -q "AES note: built-in implementation." ./programs/test/selftest
 }
 
+component_test_sha3_variations() {
+    msg "sha3 loop unroll variations"
+
+    # define minimal config sufficient to test SHA3
+    cat > include/mbedtls/mbedtls_config.h << END
+        #define MBEDTLS_SELF_TEST
+        #define MBEDTLS_SHA3_C
+END
+
+    msg "all loops unrolled"
+    make clean
+    make -C tests test_suite_shax CFLAGS="-DMBEDTLS_SHA3_THETA_UNROLL=1 -DMBEDTLS_SHA3_PI_UNROLL=1 -DMBEDTLS_SHA3_CHI_UNROLL=1 -DMBEDTLS_SHA3_RHO_UNROLL=1"
+    ./tests/test_suite_shax
+
+    msg "all loops rolled up"
+    make clean
+    make -C tests test_suite_shax CFLAGS="-DMBEDTLS_SHA3_THETA_UNROLL=0 -DMBEDTLS_SHA3_PI_UNROLL=0 -DMBEDTLS_SHA3_CHI_UNROLL=0 -DMBEDTLS_SHA3_RHO_UNROLL=0"
+    ./tests/test_suite_shax
+}
+
 support_test_aesni_m32() {
     support_test_m32_no_asm && (lscpu | grep -qw aes)
 }
@@ -5758,8 +5628,24 @@
     (check_tools "$armc5_cc" "$armc6_cc" > /dev/null 2>&1)
 }
 
+component_test_tls12_only () {
+    msg "build: default config without MBEDTLS_SSL_PROTO_TLS1_3, cmake, gcc, ASan"
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+    make
+
+    msg "test: main suites (inc. selftests) (ASan build)"
+    make test
+
+    msg "test: ssl-opt.sh (ASan build)"
+    tests/ssl-opt.sh
+
+    msg "test: compat.sh (ASan build)"
+    tests/compat.sh
+}
+
 component_test_tls13_only () {
-    msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3, without MBEDTLS_SSL_PROTO_TLS1_2"
+    msg "build: default config without MBEDTLS_SSL_PROTO_TLS1_2"
     scripts/config.py set MBEDTLS_SSL_EARLY_DATA
     scripts/config.py set MBEDTLS_SSL_RECORD_SIZE_LIMIT
     make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'"
@@ -5896,34 +5782,43 @@
     tests/ssl-opt.sh
 }
 
-component_test_tls13 () {
-    msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3 enabled, without padding"
-    scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3
-    scripts/config.py set MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+component_test_tls13_no_padding () {
+    msg "build: default config plus early data minus padding"
     scripts/config.py set MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 1
     scripts/config.py set MBEDTLS_SSL_EARLY_DATA
     CC=$ASAN_CC cmake -D CMAKE_BUILD_TYPE:String=Asan .
     make
-    msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3 enabled, without padding"
+    msg "test: default config plus early data minus padding"
     make test
-    msg "ssl-opt.sh (TLS 1.3)"
+    msg "ssl-opt.sh (TLS 1.3 no padding)"
     tests/ssl-opt.sh
 }
 
 component_test_tls13_no_compatibility_mode () {
-    msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3 enabled, without padding"
-    scripts/config.py set   MBEDTLS_SSL_PROTO_TLS1_3
+    msg "build: default config plus early data minus middlebox compatibility mode"
     scripts/config.py unset MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
-    scripts/config.py set   MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 1
     scripts/config.py set   MBEDTLS_SSL_EARLY_DATA
     CC=$ASAN_CC cmake -D CMAKE_BUILD_TYPE:String=Asan .
     make
-    msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3 enabled, without padding"
+    msg "test: default config plus early data minus middlebox compatibility mode"
     make test
     msg "ssl-opt.sh (TLS 1.3 no compatibility mode)"
     tests/ssl-opt.sh
 }
 
+component_test_full_minus_session_tickets() {
+    msg "build: full config without session tickets"
+    scripts/config.py full
+    scripts/config.py unset MBEDTLS_SSL_SESSION_TICKETS
+    scripts/config.py unset MBEDTLS_SSL_EARLY_DATA
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+    make
+    msg "test: full config without session tickets"
+    make test
+    msg "ssl-opt.sh (full config without session tickets)"
+    tests/ssl-opt.sh
+}
+
 component_build_mingw () {
     msg "build: Windows cross build - mingw64, make (Link Library)" # ~ 30s
     make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra -maes -msse2 -mpclmul' WINDOWS_BUILD=1 lib programs
diff --git a/tests/scripts/basic-build-test.sh b/tests/scripts/basic-build-test.sh
index 5261754..d2e955f 100755
--- a/tests/scripts/basic-build-test.sh
+++ b/tests/scripts/basic-build-test.sh
@@ -103,11 +103,7 @@
 echo '################ compat.sh ################'
 {
     echo '#### compat.sh: Default versions'
-    sh compat.sh
-    echo
-
-    echo '#### compat.sh: null cipher'
-    sh compat.sh -e '^$' -f 'NULL'
+    sh compat.sh -e 'ARIA\|CHACHA'
     echo
 
     echo '#### compat.sh: next (ARIA, ChaCha)'
diff --git a/tests/scripts/check-generated-files.sh b/tests/scripts/check-generated-files.sh
index 3fe4e8c..2f20026 100755
--- a/tests/scripts/check-generated-files.sh
+++ b/tests/scripts/check-generated-files.sh
@@ -142,5 +142,10 @@
     # generate_visualc_files enumerates source files (library/*.c). It doesn't
     # care about their content, but the files must exist. So it must run after
     # the step that creates or updates these files.
-    check scripts/generate_visualc_files.pl visualc/VS2013
+    check scripts/generate_visualc_files.pl visualc/VS2017
 fi
+
+# Generated files that are present in the repository even in the development
+# branch. (This is intended to be temporary, until the generator scripts are
+# fully reviewed and the build scripts support a generated header file.)
+check tests/scripts/generate_psa_wrappers.py tests/include/test/psa_test_wrappers.h tests/src/psa_test_wrappers.c
diff --git a/tests/scripts/check_files.py b/tests/scripts/check_files.py
index 4483f55..d5a4b92 100755
--- a/tests/scripts/check_files.py
+++ b/tests/scripts/check_files.py
@@ -323,6 +323,7 @@
         ".make",
         ".pem", # some openssl dumps have tabs
         ".sln",
+        "/.gitmodules",
         "/Makefile",
         "/Makefile.inc",
         "/generate_visualc_files.pl",
@@ -469,6 +470,7 @@
         ]
 
     def setup_logger(self, log_file, level=logging.INFO):
+        """Log to log_file if provided, or to stderr if None."""
         self.logger = logging.getLogger()
         self.logger.setLevel(level)
         if log_file:
@@ -480,9 +482,19 @@
 
     @staticmethod
     def collect_files():
+        """Return the list of files to check.
+
+        These are the regular files commited into Git.
+        """
         bytes_output = subprocess.check_output(['git', 'ls-files', '-z'])
         bytes_filepaths = bytes_output.split(b'\0')[:-1]
         ascii_filepaths = map(lambda fp: fp.decode('ascii'), bytes_filepaths)
+        # Filter out directories. Normally Git doesn't list directories
+        # (it only knows about the files inside them), but there is
+        # at least one case where 'git ls-files' includes a directory:
+        # submodules. Just skip submodules (and any other directories).
+        ascii_filepaths = [fp for fp in ascii_filepaths
+                           if os.path.isfile(fp)]
         # Prepend './' to files in the top-level directory so that
         # something like `'/Makefile' in fp` matches in the top-level
         # directory as well as in subdirectories.
@@ -490,12 +502,17 @@
                 for fp in ascii_filepaths]
 
     def check_files(self):
+        """Check all files for all issues."""
         for issue_to_check in self.issues_to_check:
             for filepath in self.collect_files():
                 if issue_to_check.should_check_file(filepath):
                     issue_to_check.check_file_for_issue(filepath)
 
     def output_issues(self):
+        """Log the issues found and their locations.
+
+        Return 1 if there were issues, 0 otherwise.
+        """
         integrity_return_code = 0
         for issue_to_check in self.issues_to_check:
             if issue_to_check.files_with_issues:
diff --git a/tests/scripts/check_test_cases.py b/tests/scripts/check_test_cases.py
index 68e7e69..d67e678 100755
--- a/tests/scripts/check_test_cases.py
+++ b/tests/scripts/check_test_cases.py
@@ -16,6 +16,23 @@
 import subprocess
 import sys
 
+class ScriptOutputError(ValueError):
+    """A kind of ValueError that indicates we found
+    the script doesn't list test cases in an expected
+    pattern.
+    """
+
+    @property
+    def script_name(self):
+        return super().args[0]
+
+    @property
+    def idx(self):
+        return super().args[1]
+
+    @property
+    def line(self):
+        return super().args[2]
 
 class Results:
     """Store file and line information about errors or warnings in test suites."""
@@ -86,19 +103,27 @@
                                            data_file_name, line_number, line)
                 in_paragraph = True
 
-    def collect_from_script(self, file_name):
+    def collect_from_script(self, script_name):
         """Collect the test cases in a script by calling its listing test cases
 option"""
         descriptions = self.new_per_file_state() # pylint: disable=assignment-from-none
-        listed = subprocess.check_output(['sh', file_name, '--list-test-cases'])
+        listed = subprocess.check_output(['sh', script_name, '--list-test-cases'])
         # Assume test file is responsible for printing identical format of
         # test case description between --list-test-cases and its OUTCOME.CSV
         #
         # idx indicates the number of test case since there is no line number
         # in the script for each test case.
-        for idx, description in enumerate(listed.splitlines()):
+        for idx, line in enumerate(listed.splitlines()):
+            # We are expecting the script to list the test cases in
+            # `<suite_name>;<description>` pattern.
+            script_outputs = line.split(b';', 1)
+            if len(script_outputs) == 2:
+                suite_name, description = script_outputs
+            else:
+                raise ScriptOutputError(script_name, idx, line.decode("utf-8"))
+
             self.process_test_case(descriptions,
-                                   file_name,
+                                   suite_name.decode('utf-8'),
                                    idx,
                                    description.rstrip())
 
@@ -124,8 +149,7 @@
 
             for sh_file in ['ssl-opt.sh', 'compat.sh']:
                 sh_file = os.path.join(directory, sh_file)
-                if os.path.exists(sh_file):
-                    self.collect_from_script(sh_file)
+                self.collect_from_script(sh_file)
 
 class TestDescriptions(TestDescriptionExplorer):
     """Collect the available test cases."""
@@ -202,7 +226,12 @@
         return
     results = Results(options)
     checker = DescriptionChecker(results)
-    checker.walk_all()
+    try:
+        checker.walk_all()
+    except ScriptOutputError as e:
+        results.error(e.script_name, e.idx,
+                      '"{}" should be listed as "<suite_name>;<description>"',
+                      e.line)
     if (results.warnings or results.errors) and not options.quiet:
         sys.stderr.write('{}: {} errors, {} warnings\n'
                          .format(sys.argv[0], results.errors, results.warnings))
diff --git a/tests/scripts/generate_psa_wrappers.py b/tests/scripts/generate_psa_wrappers.py
new file mode 100755
index 0000000..07d1450
--- /dev/null
+++ b/tests/scripts/generate_psa_wrappers.py
@@ -0,0 +1,257 @@
+#!/usr/bin/env python3
+"""Generate wrapper functions for PSA function calls.
+"""
+
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+### WARNING: the code in this file has not been extensively reviewed yet.
+### We do not think it is harmful, but it may be below our normal standards
+### for robustness and maintainability.
+
+import argparse
+import itertools
+import os
+from typing import Iterator, List, Optional, Tuple
+
+import scripts_path #pylint: disable=unused-import
+from mbedtls_dev import build_tree
+from mbedtls_dev import c_parsing_helper
+from mbedtls_dev import c_wrapper_generator
+from mbedtls_dev import typing_util
+
+
+class BufferParameter:
+    """Description of an input or output buffer parameter sequence to a PSA function."""
+    #pylint: disable=too-few-public-methods
+
+    def __init__(self, i: int, is_output: bool,
+                 buffer_name: str, size_name: str) -> None:
+        """Initialize the parameter information.
+
+        i is the index of the function argument that is the pointer to the buffer.
+        The size is argument i+1. For a variable-size output, the actual length
+        goes in argument i+2.
+
+        buffer_name and size_names are the names of arguments i and i+1.
+        This class does not yet help with the output length.
+        """
+        self.index = i
+        self.buffer_name = buffer_name
+        self.size_name = size_name
+        self.is_output = is_output
+
+
+class PSAWrapperGenerator(c_wrapper_generator.Base):
+    """Generate a C source file containing wrapper functions for PSA Crypto API calls."""
+
+    _CPP_GUARDS = ('defined(MBEDTLS_PSA_CRYPTO_C) && ' +
+                   'defined(MBEDTLS_TEST_HOOKS) && \\\n    ' +
+                   '!defined(RECORD_PSA_STATUS_COVERAGE_LOG)')
+    _WRAPPER_NAME_PREFIX = 'mbedtls_test_wrap_'
+    _WRAPPER_NAME_SUFFIX = ''
+
+    def gather_data(self) -> None:
+        root_dir = build_tree.guess_mbedtls_root()
+        for header_name in ['crypto.h', 'crypto_extra.h']:
+            header_path = os.path.join(root_dir, 'include', 'psa', header_name)
+            c_parsing_helper.read_function_declarations(self.functions, header_path)
+
+    _SKIP_FUNCTIONS = frozenset([
+        'mbedtls_psa_external_get_random', # not a library function
+        'psa_get_key_domain_parameters', # client-side function
+        'psa_get_key_slot_number', # client-side function
+        'psa_key_derivation_verify_bytes', # not implemented yet
+        'psa_key_derivation_verify_key', # not implemented yet
+        'psa_set_key_domain_parameters', # client-side function
+    ])
+
+    def _skip_function(self, function: c_wrapper_generator.FunctionInfo) -> bool:
+        if function.return_type != 'psa_status_t':
+            return True
+        if function.name in self._SKIP_FUNCTIONS:
+            return True
+        return False
+
+    # PAKE stuff: not implemented yet
+    _PAKE_STUFF = frozenset([
+        'psa_crypto_driver_pake_inputs_t *',
+        'psa_pake_cipher_suite_t *',
+    ])
+
+    def _return_variable_name(self,
+                              function: c_wrapper_generator.FunctionInfo) -> str:
+        """The name of the variable that will contain the return value."""
+        if function.return_type == 'psa_status_t':
+            return 'status'
+        return super()._return_variable_name(function)
+
+    _FUNCTION_GUARDS = c_wrapper_generator.Base._FUNCTION_GUARDS.copy() \
+        #pylint: disable=protected-access
+    _FUNCTION_GUARDS.update({
+        'mbedtls_psa_register_se_key': 'defined(MBEDTLS_PSA_CRYPTO_SE_C)',
+        'mbedtls_psa_inject_entropy': 'defined(MBEDTLS_PSA_INJECT_ENTROPY)',
+        'mbedtls_psa_external_get_random': 'defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)',
+        'mbedtls_psa_platform_get_builtin_key': 'defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)',
+    })
+
+    @staticmethod
+    def _detect_buffer_parameters(arguments: List[c_parsing_helper.ArgumentInfo],
+                                  argument_names: List[str]) -> Iterator[BufferParameter]:
+        """Detect function arguments that are buffers (pointer, size [,length])."""
+        types = ['' if arg.suffix else arg.type for arg in arguments]
+        # pairs = list of (type_of_arg_N, type_of_arg_N+1)
+        # where each type_of_arg_X is the empty string if the type is an array
+        # or there is no argument X.
+        pairs = enumerate(itertools.zip_longest(types, types[1:], fillvalue=''))
+        for i, t01 in pairs:
+            if (t01[0] == 'const uint8_t *' or t01[0] == 'uint8_t *') and \
+               t01[1] == 'size_t':
+                yield BufferParameter(i, not t01[0].startswith('const '),
+                                      argument_names[i], argument_names[i+1])
+
+    @staticmethod
+    def _write_poison_buffer_parameter(out: typing_util.Writable,
+                                       param: BufferParameter,
+                                       poison: bool) -> None:
+        """Write poisoning or unpoisoning code for a buffer parameter.
+
+        Write poisoning code if poison is true, unpoisoning code otherwise.
+        """
+        out.write('    MBEDTLS_TEST_MEMORY_{}({}, {});\n'.format(
+            'POISON' if poison else 'UNPOISON',
+            param.buffer_name, param.size_name
+        ))
+
+    def _write_poison_buffer_parameters(self, out: typing_util.Writable,
+                                        buffer_parameters: List[BufferParameter],
+                                        poison: bool) -> None:
+        """Write poisoning or unpoisoning code for the buffer parameters.
+
+        Write poisoning code if poison is true, unpoisoning code otherwise.
+        """
+        if not buffer_parameters:
+            return
+        out.write('#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)\n')
+        for param in buffer_parameters:
+            self._write_poison_buffer_parameter(out, param, poison)
+        out.write('#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */\n')
+
+    @staticmethod
+    def _parameter_should_be_copied(function_name: str,
+                                    _buffer_name: Optional[str]) -> bool:
+        """Whether the specified buffer argument to a PSA function should be copied.
+        """
+        # False-positives that do not need buffer copying
+        if function_name in ('mbedtls_psa_inject_entropy',
+                             'psa_crypto_driver_pake_get_password',
+                             'psa_crypto_driver_pake_get_user',
+                             'psa_crypto_driver_pake_get_peer'):
+            return False
+
+        return True
+
+    def _write_function_call(self, out: typing_util.Writable,
+                             function: c_wrapper_generator.FunctionInfo,
+                             argument_names: List[str]) -> None:
+        buffer_parameters = list(
+            param
+            for param in self._detect_buffer_parameters(function.arguments,
+                                                        argument_names)
+            if self._parameter_should_be_copied(function.name,
+                                                function.arguments[param.index].name))
+        self._write_poison_buffer_parameters(out, buffer_parameters, True)
+        super()._write_function_call(out, function, argument_names)
+        self._write_poison_buffer_parameters(out, buffer_parameters, False)
+
+    def _write_prologue(self, out: typing_util.Writable, header: bool) -> None:
+        super()._write_prologue(out, header)
+        out.write("""
+#if {}
+
+#include <psa/crypto.h>
+
+#include <test/memory.h>
+#include <test/psa_crypto_helpers.h>
+#include <test/psa_test_wrappers.h>
+"""
+                  .format(self._CPP_GUARDS))
+
+    def _write_epilogue(self, out: typing_util.Writable, header: bool) -> None:
+        out.write("""
+#endif /* {} */
+"""
+                  .format(self._CPP_GUARDS))
+        super()._write_epilogue(out, header)
+
+
+class PSALoggingWrapperGenerator(PSAWrapperGenerator, c_wrapper_generator.Logging):
+    """Generate a C source file containing wrapper functions that log PSA Crypto API calls."""
+
+    def __init__(self, stream: str) -> None:
+        super().__init__()
+        self.set_stream(stream)
+
+    _PRINTF_TYPE_CAST = c_wrapper_generator.Logging._PRINTF_TYPE_CAST.copy()
+    _PRINTF_TYPE_CAST.update({
+        'mbedtls_svc_key_id_t': 'unsigned',
+        'psa_algorithm_t': 'unsigned',
+        'psa_drv_slot_number_t': 'unsigned long long',
+        'psa_key_derivation_step_t': 'int',
+        'psa_key_id_t': 'unsigned',
+        'psa_key_slot_number_t': 'unsigned long long',
+        'psa_key_lifetime_t': 'unsigned',
+        'psa_key_type_t': 'unsigned',
+        'psa_key_usage_flags_t': 'unsigned',
+        'psa_pake_role_t': 'int',
+        'psa_pake_step_t': 'int',
+        'psa_status_t': 'int',
+    })
+
+    def _printf_parameters(self, typ: str, var: str) -> Tuple[str, List[str]]:
+        if typ.startswith('const '):
+            typ = typ[6:]
+        if typ == 'uint8_t *':
+            # Skip buffers
+            return '', []
+        if typ.endswith('operation_t *'):
+            return '', []
+        if typ in self._PAKE_STUFF:
+            return '', []
+        if typ == 'psa_key_attributes_t *':
+            return (var + '={id=%u, lifetime=0x%08x, type=0x%08x, bits=%u, alg=%08x, usage=%08x}',
+                    ['(unsigned) psa_get_key_{}({})'.format(field, var)
+                     for field in ['id', 'lifetime', 'type', 'bits', 'algorithm', 'usage_flags']])
+        return super()._printf_parameters(typ, var)
+
+
+DEFAULT_C_OUTPUT_FILE_NAME = 'tests/src/psa_test_wrappers.c'
+DEFAULT_H_OUTPUT_FILE_NAME = 'tests/include/test/psa_test_wrappers.h'
+
+def main() -> None:
+    parser = argparse.ArgumentParser(description=globals()['__doc__'])
+    parser.add_argument('--log',
+                        help='Stream to log to (default: no logging code)')
+    parser.add_argument('--output-c',
+                        metavar='FILENAME',
+                        default=DEFAULT_C_OUTPUT_FILE_NAME,
+                        help=('Output .c file path (default: {}; skip .c output if empty)'
+                              .format(DEFAULT_C_OUTPUT_FILE_NAME)))
+    parser.add_argument('--output-h',
+                        metavar='FILENAME',
+                        default=DEFAULT_H_OUTPUT_FILE_NAME,
+                        help=('Output .h file path (default: {}; skip .h output if empty)'
+                              .format(DEFAULT_H_OUTPUT_FILE_NAME)))
+    options = parser.parse_args()
+    if options.log:
+        generator = PSALoggingWrapperGenerator(options.log) #type: PSAWrapperGenerator
+    else:
+        generator = PSAWrapperGenerator()
+    generator.gather_data()
+    if options.output_h:
+        generator.write_h_file(options.output_h)
+    if options.output_c:
+        generator.write_c_file(options.output_c)
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/scripts/generate_test_keys.py b/tests/scripts/generate_test_keys.py
new file mode 100755
index 0000000..0a67a78
--- /dev/null
+++ b/tests/scripts/generate_test_keys.py
@@ -0,0 +1,162 @@
+#!/usr/bin/env python3
+
+# Copyright The Mbed TLS Contributors
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+
+"""Module generating EC and RSA keys to be used in test_suite_pk instead of
+generating the required key at run time. This helps speeding up testing."""
+
+import os
+from typing import Iterator
+import re
+import scripts_path # pylint: disable=unused-import
+from mbedtls_dev.asymmetric_key_data import ASYMMETRIC_KEY_DATA
+
+OUTPUT_HEADER_FILE = os.path.dirname(os.path.abspath(__file__)) + "/../src/test_keys.h"
+BYTES_PER_LINE = 16
+
+def c_byte_array_literal_content(array_name: str, key_data: bytes) -> Iterator[str]:
+    yield 'const unsigned char '
+    yield array_name
+    yield '[] = {'
+    for index in range(0, len(key_data), BYTES_PER_LINE):
+        yield '\n   '
+        for b in key_data[index:index + BYTES_PER_LINE]:
+            yield ' {:#04x},'.format(b)
+    yield '\n};'
+
+def convert_der_to_c(array_name: str, key_data: bytes) -> str:
+    return ''.join(c_byte_array_literal_content(array_name, key_data))
+
+def get_key_type(key: str) -> str:
+    if re.match('PSA_KEY_TYPE_RSA_.*', key):
+        return "rsa"
+    elif re.match('PSA_KEY_TYPE_ECC_.*', key):
+        return "ec"
+    else:
+        print("Unhandled key type {}".format(key))
+        return "unknown"
+
+def get_ec_key_family(key: str) -> str:
+    match = re.search(r'.*\((.*)\)', key)
+    if match is None:
+        raise Exception("Unable to get EC family from {}".format(key))
+    return match.group(1)
+
+# Legacy EC group ID do not support all the key types that PSA does, so the
+# following dictionaries are used for:
+# - getting prefix/suffix for legacy curve names
+# - understand if the curve is supported in legacy symbols (MBEDTLS_ECP_DP_...)
+EC_NAME_CONVERSION = {
+    'PSA_ECC_FAMILY_SECP_K1': {
+        192: ('secp', 'k1'),
+        224: ('secp', 'k1'),
+        256: ('secp', 'k1')
+    },
+    'PSA_ECC_FAMILY_SECP_R1': {
+        192: ('secp', 'r1'),
+        224: ('secp', 'r1'),
+        256: ('secp', 'r1'),
+        384: ('secp', 'r1'),
+        521: ('secp', 'r1')
+    },
+    'PSA_ECC_FAMILY_BRAINPOOL_P_R1': {
+        256: ('bp', 'r1'),
+        384: ('bp', 'r1'),
+        512: ('bp', 'r1')
+    },
+    'PSA_ECC_FAMILY_MONTGOMERY': {
+        255: ('curve', '19'),
+        448: ('curve', '')
+    }
+}
+
+def get_ec_curve_name(priv_key: str, bits: int) -> str:
+    ec_family = get_ec_key_family(priv_key)
+    try:
+        prefix = EC_NAME_CONVERSION[ec_family][bits][0]
+        suffix = EC_NAME_CONVERSION[ec_family][bits][1]
+    except KeyError:
+        return ""
+    return prefix + str(bits) + suffix
+
+def get_look_up_table_entry(key_type: str, group_id_or_keybits: str,
+                            priv_array_name: str, pub_array_name: str) -> Iterator[str]:
+    if key_type == "ec":
+        yield "    {{ {}, 0,\n".format(group_id_or_keybits)
+    else:
+        yield "    {{ 0, {},\n".format(group_id_or_keybits)
+    yield "      {0}, sizeof({0}),\n".format(priv_array_name)
+    yield "      {0}, sizeof({0}) }},".format(pub_array_name)
+
+def main() -> None:
+    # Remove output file if already existing.
+    if os.path.exists(OUTPUT_HEADER_FILE):
+        os.remove(OUTPUT_HEADER_FILE)
+
+    output_file = open(OUTPUT_HEADER_FILE, 'at')
+    output_file.write(
+        "/*********************************************************************************\n" +
+        " * This file was automatically generated from tests/scripts/generate_test_keys.py.\n" +
+        " * Please do not edit it manually.\n" +
+        " *********************************************************************************/\n"
+    )
+
+    look_up_table = []
+
+    # Get a list of private keys only in order to get a single item for every
+    # (key type, key bits) pair. We know that ASYMMETRIC_KEY_DATA
+    # contains also the public counterpart.
+    priv_keys = [key for key in ASYMMETRIC_KEY_DATA if '_KEY_PAIR' in key]
+
+    for priv_key in priv_keys:
+        key_type = get_key_type(priv_key)
+        # Ignore keys which are not EC or RSA
+        if key_type == "unknown":
+            continue
+
+        pub_key = re.sub('_KEY_PAIR', '_PUBLIC_KEY', priv_key)
+
+        for bits in ASYMMETRIC_KEY_DATA[priv_key]:
+            if key_type == "ec":
+                curve = get_ec_curve_name(priv_key, bits)
+                # Ignore EC curves unsupported in legacy symbols
+                if curve == "":
+                    continue
+            # Create output array name
+            if key_type == "rsa":
+                array_name_base = "_".join(["test", key_type, str(bits)])
+            else:
+                array_name_base = "_".join(["test", key_type, curve])
+            array_name_priv = array_name_base + "_priv"
+            array_name_pub = array_name_base + "_pub"
+            # Convert bytearray to C array
+            c_array_priv = convert_der_to_c(array_name_priv, ASYMMETRIC_KEY_DATA[priv_key][bits])
+            c_array_pub = convert_der_to_c(array_name_pub, ASYMMETRIC_KEY_DATA[pub_key][bits])
+            # Write the C array to the output file
+            output_file.write(''.join(["\n", c_array_priv, "\n", c_array_pub, "\n"]))
+            # Update the lookup table
+            if key_type == "ec":
+                group_id_or_keybits = "MBEDTLS_ECP_DP_" + curve.upper()
+            else:
+                group_id_or_keybits = str(bits)
+            look_up_table.append(''.join(get_look_up_table_entry(key_type, group_id_or_keybits,
+                                                                 array_name_priv, array_name_pub)))
+    # Write the lookup table: the struct containing pointers to all the arrays we created above.
+    output_file.write("""
+struct predefined_key_element {
+    int group_id;  // EC group ID; 0 for RSA keys
+    int keybits;  // bits size of RSA key; 0 for EC keys
+    const unsigned char *priv_key;
+    size_t priv_key_len;
+    const unsigned char *pub_key;
+    size_t pub_key_len;
+};
+
+struct predefined_key_element predefined_keys[] = {
+""")
+    output_file.write("\n".join(look_up_table))
+    output_file.write("\n};\n")
+
+if __name__ == '__main__':
+    main()
diff --git a/tests/scripts/quiet/cmake b/tests/scripts/quiet/cmake
index 930931d..a34365b 100755
--- a/tests/scripts/quiet/cmake
+++ b/tests/scripts/quiet/cmake
@@ -12,8 +12,8 @@
 # export VERBOSE_LOGS=1
 
 # don't silence invocations containing these arguments
-export NO_SILENCE=" --version "
+NO_SILENCE=" --version "
 
-export TOOL="cmake"
+TOOL="cmake"
 
-exec "$(dirname "$0")/quiet.sh" "$@"
+. "$(dirname "$0")/quiet.sh"
diff --git a/tests/scripts/quiet/make b/tests/scripts/quiet/make
index d022551..920e5b8 100755
--- a/tests/scripts/quiet/make
+++ b/tests/scripts/quiet/make
@@ -12,8 +12,8 @@
 # export VERBOSE_LOGS=1
 
 # don't silence invocations containing these arguments
-export NO_SILENCE=" --version | test "
+NO_SILENCE=" --version | test "
 
-export TOOL="make"
+TOOL="make"
 
-exec "$(dirname "$0")/quiet.sh" "$@"
+. "$(dirname "$0")/quiet.sh"
diff --git a/tests/scripts/quiet/quiet.sh b/tests/scripts/quiet/quiet.sh
old mode 100755
new mode 100644
index 30ee569..0f26184
--- a/tests/scripts/quiet/quiet.sh
+++ b/tests/scripts/quiet/quiet.sh
@@ -22,9 +22,13 @@
 #              be silenced, e.g. " --version | test ". In this example, "make lib test" will
 #              not be silent, but "make lib" will be.
 
-# Locate original tool
-TOOL_WITH_PATH=$(dirname "$0")/$TOOL
-ORIGINAL_TOOL=$(type -ap "${TOOL}" | grep -v -Fx "$TOOL_WITH_PATH" | head -n1)
+# Identify path to original tool. There is an edge-case here where the quiet wrapper is on the path via
+# a symlink or relative path, but "type -ap" yields the wrapper with it's normalised path. We use
+# the -ef operator to compare paths, to avoid picking the wrapper in this case (to avoid infinitely
+# recursing).
+while IFS= read -r ORIGINAL_TOOL; do
+    if ! [[ $ORIGINAL_TOOL -ef "$0" ]]; then break; fi
+done < <(type -ap -- "$TOOL")
 
 print_quoted_args() {
     # similar to printf '%q' "$@"
diff --git a/tests/src/drivers/test_driver_key_management.c b/tests/src/drivers/test_driver_key_management.c
index 866b31e..2a87899 100644
--- a/tests/src/drivers/test_driver_key_management.c
+++ b/tests/src/drivers/test_driver_key_management.c
@@ -193,6 +193,7 @@
     uint8_t *key, size_t key_size, size_t *key_length)
 {
     ++mbedtls_test_driver_key_management_hooks.hits;
+    ++mbedtls_test_driver_key_management_hooks.hits_generate_key;
 
     if (mbedtls_test_driver_key_management_hooks.forced_status != PSA_SUCCESS) {
         return mbedtls_test_driver_key_management_hooks.forced_status;
diff --git a/tests/src/drivers/test_driver_pake.c b/tests/src/drivers/test_driver_pake.c
index a0b6c1c..52395e4 100644
--- a/tests/src/drivers/test_driver_pake.c
+++ b/tests/src/drivers/test_driver_pake.c
@@ -1,5 +1,5 @@
 /*
- * Test driver for MAC entry points.
+ * Test driver for PAKE entry points.
  */
 /*  Copyright The Mbed TLS Contributors
  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
diff --git a/tests/src/helpers.c b/tests/src/helpers.c
index 2433422..065d17d 100644
--- a/tests/src/helpers.c
+++ b/tests/src/helpers.c
@@ -13,6 +13,9 @@
 #include <test/psa_crypto_helpers.h>
 #endif
 
+#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C)
+#include <test/psa_memory_poisoning_wrappers.h>
+#endif
 #if defined(MBEDTLS_THREADING_C)
 #include "mbedtls/threading.h"
 #endif
@@ -314,6 +317,12 @@
 {
     int ret = 0;
 
+#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) \
+    && !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) \
+    && defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
+    mbedtls_poison_test_hooks_setup();
+#endif
+
 #if defined(MBEDTLS_PSA_INJECT_ENTROPY)
     /* Make sure that injected entropy is present. Otherwise
      * psa_crypto_init() will fail. This is not necessary for test suites
@@ -338,6 +347,11 @@
 
 void mbedtls_test_platform_teardown(void)
 {
+#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) \
+    && !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) \
+    &&  defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
+    mbedtls_poison_test_hooks_teardown();
+#endif
 #ifdef MBEDTLS_THREADING_C
     mbedtls_mutex_free(&mbedtls_test_info_mutex);
 #endif /* MBEDTLS_THREADING_C */
diff --git a/tests/src/psa_crypto_stubs.c b/tests/src/psa_crypto_stubs.c
new file mode 100644
index 0000000..81d7f4b
--- /dev/null
+++ b/tests/src/psa_crypto_stubs.c
@@ -0,0 +1,75 @@
+/** \file psa_crypto_stubs.c
+ *
+ * \brief Stub functions when MBEDTLS_PSA_CRYPTO_CLIENT is enabled but
+ *        MBEDTLS_PSA_CRYPTO_C is disabled.
+ */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <psa/crypto.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+
+psa_status_t psa_generate_random(uint8_t *output,
+                                 size_t output_size)
+{
+    (void) output;
+    (void) output_size;
+
+    return PSA_ERROR_COMMUNICATION_FAILURE;
+}
+
+psa_status_t psa_export_key(mbedtls_svc_key_id_t key,
+                            uint8_t *data,
+                            size_t data_size,
+                            size_t *data_length)
+{
+    (void) key;
+    (void) data;
+    (void) data_size;
+    (void) data_length;
+    return PSA_ERROR_COMMUNICATION_FAILURE;
+}
+
+psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key,
+                                   uint8_t *data,
+                                   size_t data_size,
+                                   size_t *data_length)
+{
+    (void) key;
+    (void) data;
+    (void) data_size;
+    (void) data_length;
+    return PSA_ERROR_COMMUNICATION_FAILURE;
+}
+
+psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key,
+                                    psa_key_attributes_t *attributes)
+{
+    (void) key;
+    (void) attributes;
+    return PSA_ERROR_COMMUNICATION_FAILURE;
+}
+
+psa_status_t psa_hash_abort(psa_hash_operation_t *operation)
+{
+    (void) operation;
+    return PSA_ERROR_COMMUNICATION_FAILURE;
+}
+
+psa_status_t psa_import_key(const psa_key_attributes_t *attributes,
+                            const uint8_t *data,
+                            size_t data_length,
+                            mbedtls_svc_key_id_t *key)
+{
+    (void) attributes;
+    (void) data;
+    (void) data_length;
+    (void) key;
+    return PSA_ERROR_COMMUNICATION_FAILURE;
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT && !MBEDTLS_PSA_CRYPTO_C */
diff --git a/tests/src/psa_exercise_key.c b/tests/src/psa_exercise_key.c
index 7b81052..937bd45 100644
--- a/tests/src/psa_exercise_key.c
+++ b/tests/src/psa_exercise_key.c
@@ -38,7 +38,8 @@
 }
 #endif
 
-static int check_key_attributes_sanity(mbedtls_svc_key_id_t key)
+static int check_key_attributes_sanity(mbedtls_svc_key_id_t key,
+                                       int key_destroyable)
 {
     int ok = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -46,8 +47,13 @@
     mbedtls_svc_key_id_t id;
     psa_key_type_t type;
     size_t bits;
-
-    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+    psa_status_t status = psa_get_key_attributes(key, &attributes);
+    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+        /* The key has been destroyed. */
+        psa_reset_key_attributes(&attributes);
+        return 1;
+    }
+    PSA_ASSERT(status);
     lifetime = psa_get_key_lifetime(&attributes);
     id = psa_get_key_id(&attributes);
     type = psa_get_key_type(&attributes);
@@ -66,17 +72,20 @@
             (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(id) <= PSA_KEY_ID_USER_MAX));
     }
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    /* randomly-generated 64-bit constant, should never appear in test data */
-    psa_key_slot_number_t slot_number = 0xec94d4a5058a1a21;
-    psa_status_t status = psa_get_key_slot_number(&attributes, &slot_number);
-    if (lifetime_is_dynamic_secure_element(lifetime)) {
-        /* Mbed TLS currently always exposes the slot number to
-         * applications. This is not mandated by the PSA specification
-         * and may change in future versions. */
-        TEST_EQUAL(status, 0);
-        TEST_ASSERT(slot_number != 0xec94d4a5058a1a21);
-    } else {
-        TEST_EQUAL(status, PSA_ERROR_INVALID_ARGUMENT);
+    /* MBEDTLS_PSA_CRYPTO_SE_C does not support thread safety. */
+    if (key_destroyable == 0) {
+        /* randomly-generated 64-bit constant, should never appear in test data */
+        psa_key_slot_number_t slot_number = 0xec94d4a5058a1a21;
+        status = psa_get_key_slot_number(&attributes, &slot_number);
+        if (lifetime_is_dynamic_secure_element(lifetime)) {
+            /* Mbed TLS currently always exposes the slot number to
+             * applications. This is not mandated by the PSA specification
+             * and may change in future versions. */
+            TEST_EQUAL(status, 0);
+            TEST_ASSERT(slot_number != 0xec94d4a5058a1a21);
+        } else {
+            TEST_EQUAL(status, PSA_ERROR_INVALID_ARGUMENT);
+        }
     }
 #endif
 
@@ -110,20 +119,27 @@
 
 static int exercise_mac_key(mbedtls_svc_key_id_t key,
                             psa_key_usage_t usage,
-                            psa_algorithm_t alg)
+                            psa_algorithm_t alg,
+                            int key_destroyable)
 {
     psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
     const unsigned char input[] = "foo";
     unsigned char mac[PSA_MAC_MAX_SIZE] = { 0 };
     size_t mac_length = sizeof(mac);
-
+    psa_status_t status = PSA_SUCCESS;
     /* Convert wildcard algorithm to exercisable algorithm */
     if (alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) {
         alg = PSA_ALG_TRUNCATED_MAC(alg, PSA_MAC_TRUNCATED_LENGTH(alg));
     }
 
     if (usage & PSA_KEY_USAGE_SIGN_HASH) {
-        PSA_ASSERT(psa_mac_sign_setup(&operation, key, alg));
+        status = psa_mac_sign_setup(&operation, key, alg);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            PSA_ASSERT(psa_mac_abort(&operation));
+            return 1;
+        }
+        PSA_ASSERT(status);
         PSA_ASSERT(psa_mac_update(&operation,
                                   input, sizeof(input)));
         PSA_ASSERT(psa_mac_sign_finish(&operation,
@@ -136,7 +152,13 @@
             (usage & PSA_KEY_USAGE_SIGN_HASH ?
              PSA_SUCCESS :
              PSA_ERROR_INVALID_SIGNATURE);
-        PSA_ASSERT(psa_mac_verify_setup(&operation, key, alg));
+        status = psa_mac_verify_setup(&operation, key, alg);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            PSA_ASSERT(psa_mac_abort(&operation));
+            return 1;
+        }
+        PSA_ASSERT(status);
         PSA_ASSERT(psa_mac_update(&operation,
                                   input, sizeof(input)));
         TEST_EQUAL(psa_mac_verify_finish(&operation, mac, mac_length),
@@ -152,7 +174,8 @@
 
 static int exercise_cipher_key(mbedtls_svc_key_id_t key,
                                psa_key_usage_t usage,
-                               psa_algorithm_t alg)
+                               psa_algorithm_t alg,
+                               int key_destroyable)
 {
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
     unsigned char iv[PSA_CIPHER_IV_MAX_SIZE] = { 0 };
@@ -164,13 +187,20 @@
     size_t ciphertext_length = sizeof(ciphertext);
     unsigned char decrypted[sizeof(ciphertext)];
     size_t part_length;
+    psa_status_t status = PSA_SUCCESS;
 
     PSA_ASSERT(psa_get_key_attributes(key, &attributes));
     key_type = psa_get_key_type(&attributes);
     iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
 
     if (usage & PSA_KEY_USAGE_ENCRYPT) {
-        PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
+        status = psa_cipher_encrypt_setup(&operation, key, alg);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            PSA_ASSERT(psa_cipher_abort(&operation));
+            return 1;
+        }
+        PSA_ASSERT(status);
         if (iv_length != 0) {
             PSA_ASSERT(psa_cipher_generate_iv(&operation,
                                               iv, sizeof(iv),
@@ -188,12 +218,17 @@
     }
 
     if (usage & PSA_KEY_USAGE_DECRYPT) {
-        psa_status_t status;
         int maybe_invalid_padding = 0;
         if (!(usage & PSA_KEY_USAGE_ENCRYPT)) {
             maybe_invalid_padding = !PSA_ALG_IS_STREAM_CIPHER(alg);
         }
-        PSA_ASSERT(psa_cipher_decrypt_setup(&operation, key, alg));
+        status = psa_cipher_decrypt_setup(&operation, key, alg);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            PSA_ASSERT(psa_cipher_abort(&operation));
+            return 1;
+        }
+        PSA_ASSERT(status);
         if (iv_length != 0) {
             PSA_ASSERT(psa_cipher_set_iv(&operation,
                                          iv, iv_length));
@@ -227,7 +262,8 @@
 
 static int exercise_aead_key(mbedtls_svc_key_id_t key,
                              psa_key_usage_t usage,
-                             psa_algorithm_t alg)
+                             psa_algorithm_t alg,
+                             int key_destroyable)
 {
     unsigned char nonce[PSA_AEAD_NONCE_MAX_SIZE] = { 0 };
     size_t nonce_length;
@@ -237,6 +273,7 @@
     unsigned char ciphertext[48] = "(wabblewebblewibblewobblewubble)";
     size_t ciphertext_length = sizeof(ciphertext);
     size_t plaintext_length = sizeof(ciphertext);
+    psa_status_t status = PSA_SUCCESS;
 
     /* Convert wildcard algorithm to exercisable algorithm */
     if (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) {
@@ -248,12 +285,17 @@
     nonce_length = PSA_AEAD_NONCE_LENGTH(key_type, alg);
 
     if (usage & PSA_KEY_USAGE_ENCRYPT) {
-        PSA_ASSERT(psa_aead_encrypt(key, alg,
-                                    nonce, nonce_length,
-                                    NULL, 0,
-                                    plaintext, sizeof(plaintext),
-                                    ciphertext, sizeof(ciphertext),
-                                    &ciphertext_length));
+        status = psa_aead_encrypt(key, alg,
+                                  nonce, nonce_length,
+                                  NULL, 0,
+                                  plaintext, sizeof(plaintext),
+                                  ciphertext, sizeof(ciphertext),
+                                  &ciphertext_length);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            return 1;
+        }
+        PSA_ASSERT(status);
     }
 
     if (usage & PSA_KEY_USAGE_DECRYPT) {
@@ -261,13 +303,17 @@
             (usage & PSA_KEY_USAGE_ENCRYPT ?
              PSA_SUCCESS :
              PSA_ERROR_INVALID_SIGNATURE);
-        TEST_EQUAL(psa_aead_decrypt(key, alg,
-                                    nonce, nonce_length,
-                                    NULL, 0,
-                                    ciphertext, ciphertext_length,
-                                    plaintext, sizeof(plaintext),
-                                    &plaintext_length),
-                   verify_status);
+        status = psa_aead_decrypt(key, alg,
+                                  nonce, nonce_length,
+                                  NULL, 0,
+                                  ciphertext, ciphertext_length,
+                                  plaintext, sizeof(plaintext),
+                                  &plaintext_length);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            return 1;
+        }
+        TEST_ASSERT(status == verify_status);
     }
 
     return 1;
@@ -291,7 +337,8 @@
 
 static int exercise_signature_key(mbedtls_svc_key_id_t key,
                                   psa_key_usage_t usage,
-                                  psa_algorithm_t alg)
+                                  psa_algorithm_t alg,
+                                  int key_destroyable)
 {
     /* If the policy allows signing with any hash, just pick one. */
     psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
@@ -305,6 +352,7 @@
         TEST_FAIL("No hash algorithm for hash-and-sign testing");
 #endif
     }
+    psa_status_t status = PSA_SUCCESS;
 
     if (usage & (PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH) &&
         PSA_ALG_IS_SIGN_HASH(alg)) {
@@ -321,10 +369,15 @@
         }
 
         if (usage & PSA_KEY_USAGE_SIGN_HASH) {
-            PSA_ASSERT(psa_sign_hash(key, alg,
-                                     payload, payload_length,
-                                     signature, sizeof(signature),
-                                     &signature_length));
+            status = psa_sign_hash(key, alg,
+                                   payload, payload_length,
+                                   signature, sizeof(signature),
+                                   &signature_length);
+            if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+                /* The key has been destroyed. */
+                return 1;
+            }
+            PSA_ASSERT(status);
         }
 
         if (usage & PSA_KEY_USAGE_VERIFY_HASH) {
@@ -332,10 +385,14 @@
                 (usage & PSA_KEY_USAGE_SIGN_HASH ?
                  PSA_SUCCESS :
                  PSA_ERROR_INVALID_SIGNATURE);
-            TEST_EQUAL(psa_verify_hash(key, alg,
-                                       payload, payload_length,
-                                       signature, signature_length),
-                       verify_status);
+            status = psa_verify_hash(key, alg,
+                                     payload, payload_length,
+                                     signature, signature_length);
+            if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+                /* The key has been destroyed. */
+                return 1;
+            }
+            TEST_ASSERT(status == verify_status);
         }
     }
 
@@ -346,10 +403,15 @@
         size_t signature_length = sizeof(signature);
 
         if (usage & PSA_KEY_USAGE_SIGN_MESSAGE) {
-            PSA_ASSERT(psa_sign_message(key, alg,
-                                        message, message_length,
-                                        signature, sizeof(signature),
-                                        &signature_length));
+            status = psa_sign_message(key, alg,
+                                      message, message_length,
+                                      signature, sizeof(signature),
+                                      &signature_length);
+            if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+                /* The key has been destroyed. */
+                return 1;
+            }
+            PSA_ASSERT(status);
         }
 
         if (usage & PSA_KEY_USAGE_VERIFY_MESSAGE) {
@@ -357,10 +419,14 @@
                 (usage & PSA_KEY_USAGE_SIGN_MESSAGE ?
                  PSA_SUCCESS :
                  PSA_ERROR_INVALID_SIGNATURE);
-            TEST_EQUAL(psa_verify_message(key, alg,
-                                          message, message_length,
-                                          signature, signature_length),
-                       verify_status);
+            status = psa_verify_message(key, alg,
+                                        message, message_length,
+                                        signature, signature_length);
+            if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+                /* The key has been destroyed. */
+                return 1;
+            }
+            TEST_ASSERT(status == verify_status);
         }
     }
 
@@ -372,7 +438,8 @@
 
 static int exercise_asymmetric_encryption_key(mbedtls_svc_key_id_t key,
                                               psa_key_usage_t usage,
-                                              psa_algorithm_t alg)
+                                              psa_algorithm_t alg,
+                                              int key_destroyable)
 {
     unsigned char plaintext[PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE] =
         "Hello, world...";
@@ -380,22 +447,30 @@
         "(wabblewebblewibblewobblewubble)";
     size_t ciphertext_length = sizeof(ciphertext);
     size_t plaintext_length = 16;
-
+    psa_status_t status = PSA_SUCCESS;
     if (usage & PSA_KEY_USAGE_ENCRYPT) {
-        PSA_ASSERT(psa_asymmetric_encrypt(key, alg,
-                                          plaintext, plaintext_length,
-                                          NULL, 0,
-                                          ciphertext, sizeof(ciphertext),
-                                          &ciphertext_length));
+        status = psa_asymmetric_encrypt(key, alg,
+                                        plaintext, plaintext_length,
+                                        NULL, 0,
+                                        ciphertext, sizeof(ciphertext),
+                                        &ciphertext_length);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            return 1;
+        }
+        PSA_ASSERT(status);
     }
 
     if (usage & PSA_KEY_USAGE_DECRYPT) {
-        psa_status_t status =
-            psa_asymmetric_decrypt(key, alg,
-                                   ciphertext, ciphertext_length,
-                                   NULL, 0,
-                                   plaintext, sizeof(plaintext),
-                                   &plaintext_length);
+        status = psa_asymmetric_decrypt(key, alg,
+                                        ciphertext, ciphertext_length,
+                                        NULL, 0,
+                                        plaintext, sizeof(plaintext),
+                                        &plaintext_length);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            return 1;
+        }
         TEST_ASSERT(status == PSA_SUCCESS ||
                     ((usage & PSA_KEY_USAGE_ENCRYPT) == 0 &&
                      (status == PSA_ERROR_INVALID_ARGUMENT ||
@@ -414,16 +489,22 @@
     psa_algorithm_t alg,
     const unsigned char *input1, size_t input1_length,
     const unsigned char *input2, size_t input2_length,
-    size_t capacity)
+    size_t capacity, int key_destroyable)
 {
     PSA_ASSERT(psa_key_derivation_setup(operation, alg));
+    psa_status_t status = PSA_SUCCESS;
     if (PSA_ALG_IS_HKDF(alg)) {
         PSA_ASSERT(psa_key_derivation_input_bytes(operation,
                                                   PSA_KEY_DERIVATION_INPUT_SALT,
                                                   input1, input1_length));
-        PSA_ASSERT(psa_key_derivation_input_key(operation,
-                                                PSA_KEY_DERIVATION_INPUT_SECRET,
-                                                key));
+        status = psa_key_derivation_input_key(operation,
+                                              PSA_KEY_DERIVATION_INPUT_SECRET,
+                                              key);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            return 1;
+        }
+        PSA_ASSERT(status);
         PSA_ASSERT(psa_key_derivation_input_bytes(operation,
                                                   PSA_KEY_DERIVATION_INPUT_INFO,
                                                   input2,
@@ -432,13 +513,23 @@
         PSA_ASSERT(psa_key_derivation_input_bytes(operation,
                                                   PSA_KEY_DERIVATION_INPUT_SALT,
                                                   input1, input1_length));
-        PSA_ASSERT(psa_key_derivation_input_key(operation,
-                                                PSA_KEY_DERIVATION_INPUT_SECRET,
-                                                key));
+        status = psa_key_derivation_input_key(operation,
+                                              PSA_KEY_DERIVATION_INPUT_SECRET,
+                                              key);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            return 1;
+        }
+        PSA_ASSERT(status);
     } else if (PSA_ALG_IS_HKDF_EXPAND(alg)) {
-        PSA_ASSERT(psa_key_derivation_input_key(operation,
-                                                PSA_KEY_DERIVATION_INPUT_SECRET,
-                                                key));
+        status = psa_key_derivation_input_key(operation,
+                                              PSA_KEY_DERIVATION_INPUT_SECRET,
+                                              key);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            return 1;
+        }
+        PSA_ASSERT(status);
         PSA_ASSERT(psa_key_derivation_input_bytes(operation,
                                                   PSA_KEY_DERIVATION_INPUT_INFO,
                                                   input2,
@@ -448,9 +539,14 @@
         PSA_ASSERT(psa_key_derivation_input_bytes(operation,
                                                   PSA_KEY_DERIVATION_INPUT_SEED,
                                                   input1, input1_length));
-        PSA_ASSERT(psa_key_derivation_input_key(operation,
-                                                PSA_KEY_DERIVATION_INPUT_SECRET,
-                                                key));
+        status = psa_key_derivation_input_key(operation,
+                                              PSA_KEY_DERIVATION_INPUT_SECRET,
+                                              key);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            return 1;
+        }
+        PSA_ASSERT(status);
         PSA_ASSERT(psa_key_derivation_input_bytes(operation,
                                                   PSA_KEY_DERIVATION_INPUT_LABEL,
                                                   input2, input2_length));
@@ -462,9 +558,14 @@
                                                   PSA_KEY_DERIVATION_INPUT_SALT,
                                                   input2,
                                                   input2_length));
-        PSA_ASSERT(psa_key_derivation_input_key(operation,
-                                                PSA_KEY_DERIVATION_INPUT_PASSWORD,
-                                                key));
+        status = psa_key_derivation_input_key(operation,
+                                              PSA_KEY_DERIVATION_INPUT_PASSWORD,
+                                              key);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            return 1;
+        }
+        PSA_ASSERT(status);
     } else if (alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
         PSA_ASSERT(psa_key_derivation_input_bytes(operation,
                                                   PSA_KEY_DERIVATION_INPUT_SECRET,
@@ -486,7 +587,8 @@
 
 static int exercise_key_derivation_key(mbedtls_svc_key_id_t key,
                                        psa_key_usage_t usage,
-                                       psa_algorithm_t alg)
+                                       psa_algorithm_t alg,
+                                       int key_destroyable)
 {
     psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
     unsigned char input1[] = "Input 1";
@@ -500,14 +602,20 @@
         if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, key, alg,
                                                         input1, input1_length,
                                                         input2, input2_length,
-                                                        capacity)) {
+                                                        capacity, key_destroyable)) {
             goto exit;
         }
 
-        PSA_ASSERT(psa_key_derivation_output_bytes(&operation,
-                                                   output,
-                                                   capacity));
-        PSA_ASSERT(psa_key_derivation_abort(&operation));
+        psa_status_t status = psa_key_derivation_output_bytes(&operation,
+                                                              output,
+                                                              capacity);
+        if (key_destroyable && status == PSA_ERROR_BAD_STATE) {
+            /* The key has been destroyed. */
+            PSA_ASSERT(psa_key_derivation_abort(&operation));
+        } else {
+            PSA_ASSERT(status);
+            PSA_ASSERT(psa_key_derivation_abort(&operation));
+        }
     }
 
     return 1;
@@ -520,31 +628,45 @@
  * private key against its own public key. */
 psa_status_t mbedtls_test_psa_key_agreement_with_self(
     psa_key_derivation_operation_t *operation,
-    mbedtls_svc_key_id_t key)
+    mbedtls_svc_key_id_t key, int key_destroyable)
 {
     psa_key_type_t private_key_type;
     psa_key_type_t public_key_type;
     size_t key_bits;
     uint8_t *public_key = NULL;
     size_t public_key_length;
-    /* Return GENERIC_ERROR if something other than the final call to
-     * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
-     * but it's good enough: callers will report it as a failed test anyway. */
-    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+    psa_status_t status = psa_get_key_attributes(key, &attributes);
+    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+        /* The key has been destroyed. */
+        psa_reset_key_attributes(&attributes);
+        return PSA_SUCCESS;
+    }
+    PSA_ASSERT(status);
+
     private_key_type = psa_get_key_type(&attributes);
     key_bits = psa_get_key_bits(&attributes);
     public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(private_key_type);
     public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(public_key_type, key_bits);
     TEST_CALLOC(public_key, public_key_length);
-    PSA_ASSERT(psa_export_public_key(key, public_key, public_key_length,
-                                     &public_key_length));
+    status = psa_export_public_key(key, public_key, public_key_length,
+                                   &public_key_length);
+    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+        /* The key has been destroyed. */
+        status = PSA_SUCCESS;
+        goto exit;
+    }
+    PSA_ASSERT(status);
 
     status = psa_key_derivation_key_agreement(
         operation, PSA_KEY_DERIVATION_INPUT_SECRET, key,
         public_key, public_key_length);
+    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+        /* The key has been destroyed. */
+        status = PSA_SUCCESS;
+        goto exit;
+    }
 exit:
     /*
      * Key attributes may have been returned by psa_get_key_attributes()
@@ -560,7 +682,8 @@
  * private key against its own public key. */
 psa_status_t mbedtls_test_psa_raw_key_agreement_with_self(
     psa_algorithm_t alg,
-    mbedtls_svc_key_id_t key)
+    mbedtls_svc_key_id_t key,
+    int key_destroyable)
 {
     psa_key_type_t private_key_type;
     psa_key_type_t public_key_type;
@@ -569,25 +692,39 @@
     size_t public_key_length;
     uint8_t output[1024];
     size_t output_length;
-    /* Return GENERIC_ERROR if something other than the final call to
-     * psa_key_derivation_key_agreement fails. This isn't fully satisfactory,
-     * but it's good enough: callers will report it as a failed test anyway. */
-    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+    psa_status_t status = psa_get_key_attributes(key, &attributes);
+    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+        /* The key has been destroyed. */
+        psa_reset_key_attributes(&attributes);
+        return PSA_SUCCESS;
+    }
+    PSA_ASSERT(status);
+
     private_key_type = psa_get_key_type(&attributes);
     key_bits = psa_get_key_bits(&attributes);
     public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(private_key_type);
     public_key_length = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(public_key_type, key_bits);
     TEST_CALLOC(public_key, public_key_length);
-    PSA_ASSERT(psa_export_public_key(key,
-                                     public_key, public_key_length,
-                                     &public_key_length));
+    status = psa_export_public_key(key,
+                                   public_key, public_key_length,
+                                   &public_key_length);
+    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+        /* The key has been destroyed. */
+        status = PSA_SUCCESS;
+        goto exit;
+    }
+    PSA_ASSERT(status);
 
     status = psa_raw_key_agreement(alg, key,
                                    public_key, public_key_length,
                                    output, sizeof(output), &output_length);
+    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+        /* The key has been destroyed. */
+        status = PSA_SUCCESS;
+        goto exit;
+    }
     if (status == PSA_SUCCESS) {
         TEST_ASSERT(output_length <=
                     PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(private_key_type,
@@ -609,14 +746,16 @@
 
 static int exercise_raw_key_agreement_key(mbedtls_svc_key_id_t key,
                                           psa_key_usage_t usage,
-                                          psa_algorithm_t alg)
+                                          psa_algorithm_t alg,
+                                          int key_destroyable)
 {
     int ok = 0;
 
     if (usage & PSA_KEY_USAGE_DERIVE) {
         /* We need two keys to exercise key agreement. Exercise the
          * private key against its own public key. */
-        PSA_ASSERT(mbedtls_test_psa_raw_key_agreement_with_self(alg, key));
+        PSA_ASSERT(mbedtls_test_psa_raw_key_agreement_with_self(alg, key,
+                                                                key_destroyable));
     }
     ok = 1;
 
@@ -626,7 +765,8 @@
 
 static int exercise_key_agreement_key(mbedtls_svc_key_id_t key,
                                       psa_key_usage_t usage,
-                                      psa_algorithm_t alg)
+                                      psa_algorithm_t alg,
+                                      int key_destroyable)
 {
     psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
     unsigned char input[1] = { 0 };
@@ -657,7 +797,12 @@
            hash length. Otherwise test should fail with INVALID_ARGUMENT. */
         if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
             psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-            PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+            psa_status_t status = psa_get_key_attributes(key, &attributes);
+            if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+                /* The key has been destroyed. */
+                ok = 1;
+            }
+            PSA_ASSERT(status);
             size_t key_bits = psa_get_key_bits(&attributes);
             psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg);
 
@@ -666,7 +811,8 @@
             }
         }
 
-        TEST_EQUAL(mbedtls_test_psa_key_agreement_with_self(&operation, key),
+        TEST_EQUAL(mbedtls_test_psa_key_agreement_with_self(&operation, key,
+                                                            key_destroyable),
                    expected_key_agreement_status);
 
         if (expected_key_agreement_status != PSA_SUCCESS) {
@@ -857,7 +1003,8 @@
 }
 
 static int exercise_export_key(mbedtls_svc_key_id_t key,
-                               psa_key_usage_t usage)
+                               psa_key_usage_t usage,
+                               int key_destroyable)
 {
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     uint8_t *exported = NULL;
@@ -865,25 +1012,31 @@
     size_t exported_length = 0;
     int ok = 0;
 
-    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+    psa_status_t status = psa_get_key_attributes(key, &attributes);
+    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+        /* The key has been destroyed. */
+        psa_reset_key_attributes(&attributes);
+        return 1;
+    }
+    PSA_ASSERT(status);
 
     exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
         psa_get_key_type(&attributes),
         psa_get_key_bits(&attributes));
     TEST_CALLOC(exported, exported_size);
 
-    if ((usage & PSA_KEY_USAGE_EXPORT) == 0 &&
-        !PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(&attributes))) {
-        TEST_EQUAL(psa_export_key(key, exported,
-                                  exported_size, &exported_length),
-                   PSA_ERROR_NOT_PERMITTED);
+    status = psa_export_key(key, exported, exported_size, &exported_length);
+    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+        /* The key has been destroyed. */
+        ok = 1;
+        goto exit;
+    } else if ((usage & PSA_KEY_USAGE_EXPORT) == 0 &&
+               !PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(&attributes))) {
+        TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
         ok = 1;
         goto exit;
     }
-
-    PSA_ASSERT(psa_export_key(key,
-                              exported, exported_size,
-                              &exported_length));
+    PSA_ASSERT(status);
     ok = mbedtls_test_psa_exported_key_sanity_check(
         psa_get_key_type(&attributes), psa_get_key_bits(&attributes),
         exported, exported_length);
@@ -899,7 +1052,8 @@
     return ok;
 }
 
-static int exercise_export_public_key(mbedtls_svc_key_id_t key)
+static int exercise_export_public_key(mbedtls_svc_key_id_t key,
+                                      int key_destroyable)
 {
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_type_t public_type;
@@ -908,16 +1062,27 @@
     size_t exported_length = 0;
     int ok = 0;
 
-    PSA_ASSERT(psa_get_key_attributes(key, &attributes));
+    psa_status_t status = psa_get_key_attributes(key, &attributes);
+    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+        /* The key has been destroyed. */
+        psa_reset_key_attributes(&attributes);
+        return 1;
+    }
+    PSA_ASSERT(status);
     if (!PSA_KEY_TYPE_IS_ASYMMETRIC(psa_get_key_type(&attributes))) {
         exported_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
             psa_get_key_type(&attributes),
             psa_get_key_bits(&attributes));
         TEST_CALLOC(exported, exported_size);
 
-        TEST_EQUAL(psa_export_public_key(key, exported,
-                                         exported_size, &exported_length),
-                   PSA_ERROR_INVALID_ARGUMENT);
+        status = psa_export_public_key(key, exported,
+                                       exported_size, &exported_length);
+        if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+            /* The key has been destroyed. */
+            ok = 1;
+            goto exit;
+        }
+        TEST_EQUAL(status, PSA_ERROR_INVALID_ARGUMENT);
         ok = 1;
         goto exit;
     }
@@ -928,9 +1093,14 @@
                                                       psa_get_key_bits(&attributes));
     TEST_CALLOC(exported, exported_size);
 
-    PSA_ASSERT(psa_export_public_key(key,
-                                     exported, exported_size,
-                                     &exported_length));
+    status = psa_export_public_key(key, exported,
+                                   exported_size, &exported_length);
+    if (key_destroyable && status == PSA_ERROR_INVALID_HANDLE) {
+        /* The key has been destroyed. */
+        ok = 1;
+        goto exit;
+    }
+    PSA_ASSERT(status);
     ok = mbedtls_test_psa_exported_key_sanity_check(
         public_type, psa_get_key_bits(&attributes),
         exported, exported_length);
@@ -948,38 +1118,43 @@
 
 int mbedtls_test_psa_exercise_key(mbedtls_svc_key_id_t key,
                                   psa_key_usage_t usage,
-                                  psa_algorithm_t alg)
+                                  psa_algorithm_t alg,
+                                  int key_destroyable)
 {
     int ok = 0;
 
-    if (!check_key_attributes_sanity(key)) {
+    if (!check_key_attributes_sanity(key, key_destroyable)) {
         return 0;
     }
 
     if (alg == 0) {
         ok = 1; /* If no algorithm, do nothing (used for raw data "keys"). */
     } else if (PSA_ALG_IS_MAC(alg)) {
-        ok = exercise_mac_key(key, usage, alg);
+        ok = exercise_mac_key(key, usage, alg, key_destroyable);
     } else if (PSA_ALG_IS_CIPHER(alg)) {
-        ok = exercise_cipher_key(key, usage, alg);
+        ok = exercise_cipher_key(key, usage, alg, key_destroyable);
     } else if (PSA_ALG_IS_AEAD(alg)) {
-        ok = exercise_aead_key(key, usage, alg);
+        ok = exercise_aead_key(key, usage, alg, key_destroyable);
     } else if (PSA_ALG_IS_SIGN(alg)) {
-        ok = exercise_signature_key(key, usage, alg);
+        ok = exercise_signature_key(key, usage, alg, key_destroyable);
     } else if (PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg)) {
-        ok = exercise_asymmetric_encryption_key(key, usage, alg);
+        ok = exercise_asymmetric_encryption_key(key, usage, alg,
+                                                key_destroyable);
     } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) {
-        ok = exercise_key_derivation_key(key, usage, alg);
+        ok = exercise_key_derivation_key(key, usage, alg, key_destroyable);
     } else if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {
-        ok = exercise_raw_key_agreement_key(key, usage, alg);
+        ok = exercise_raw_key_agreement_key(key, usage, alg, key_destroyable);
     } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) {
-        ok = exercise_key_agreement_key(key, usage, alg);
+        ok = exercise_key_agreement_key(key, usage, alg, key_destroyable);
     } else {
         TEST_FAIL("No code to exercise this category of algorithm");
     }
 
-    ok = ok && exercise_export_key(key, usage);
-    ok = ok && exercise_export_public_key(key);
+    ok = ok && exercise_export_key(key,
+                                   usage,
+                                   key_destroyable);
+    ok = ok && exercise_export_public_key(key,
+                                          key_destroyable);
 
 exit:
     return ok;
diff --git a/tests/src/psa_memory_poisoning_wrappers.c b/tests/src/psa_memory_poisoning_wrappers.c
new file mode 100644
index 0000000..05cba18
--- /dev/null
+++ b/tests/src/psa_memory_poisoning_wrappers.c
@@ -0,0 +1,31 @@
+/** Helper functions for memory poisoning in tests.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#include "test/memory.h"
+
+#include "psa_crypto_invasive.h"
+
+#if defined(MBEDTLS_TEST_HOOKS)  && defined(MBEDTLS_PSA_CRYPTO_C) \
+    && defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
+
+void mbedtls_poison_test_hooks_setup(void)
+{
+    psa_input_pre_copy_hook = mbedtls_test_memory_unpoison;
+    psa_input_post_copy_hook = mbedtls_test_memory_poison;
+    psa_output_pre_copy_hook = mbedtls_test_memory_unpoison;
+    psa_output_post_copy_hook = mbedtls_test_memory_poison;
+}
+
+void mbedtls_poison_test_hooks_teardown(void)
+{
+    psa_input_pre_copy_hook = NULL;
+    psa_input_post_copy_hook = NULL;
+    psa_output_pre_copy_hook = NULL;
+    psa_output_post_copy_hook = NULL;
+}
+
+#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C &&
+          MBEDTLS_TEST_MEMORY_CAN_POISON */
diff --git a/tests/src/psa_test_wrappers.c b/tests/src/psa_test_wrappers.c
new file mode 100644
index 0000000..809f1cd
--- /dev/null
+++ b/tests/src/psa_test_wrappers.c
@@ -0,0 +1,1321 @@
+/* Automatically generated by generate_psa_wrappers.py, do not edit! */
+
+/* Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <mbedtls/build_info.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_TEST_HOOKS) && \
+    !defined(RECORD_PSA_STATUS_COVERAGE_LOG)
+
+#include <psa/crypto.h>
+
+#include <test/memory.h>
+#include <test/psa_crypto_helpers.h>
+#include <test/psa_test_wrappers.h>
+
+/* Wrapper for mbedtls_psa_inject_entropy */
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
+psa_status_t mbedtls_test_wrap_mbedtls_psa_inject_entropy(
+    const uint8_t *arg0_seed,
+    size_t arg1_seed_size)
+{
+    psa_status_t status = (mbedtls_psa_inject_entropy)(arg0_seed, arg1_seed_size);
+    return status;
+}
+#endif /* defined(MBEDTLS_PSA_INJECT_ENTROPY) */
+
+/* Wrapper for mbedtls_psa_platform_get_builtin_key */
+#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
+psa_status_t mbedtls_test_wrap_mbedtls_psa_platform_get_builtin_key(
+    mbedtls_svc_key_id_t arg0_key_id,
+    psa_key_lifetime_t *arg1_lifetime,
+    psa_drv_slot_number_t *arg2_slot_number)
+{
+    psa_status_t status = (mbedtls_psa_platform_get_builtin_key)(arg0_key_id, arg1_lifetime, arg2_slot_number);
+    return status;
+}
+#endif /* defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) */
+
+/* Wrapper for mbedtls_psa_register_se_key */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+psa_status_t mbedtls_test_wrap_mbedtls_psa_register_se_key(
+    const psa_key_attributes_t *arg0_attributes)
+{
+    psa_status_t status = (mbedtls_psa_register_se_key)(arg0_attributes);
+    return status;
+}
+#endif /* defined(MBEDTLS_PSA_CRYPTO_SE_C) */
+
+/* Wrapper for psa_aead_abort */
+psa_status_t mbedtls_test_wrap_psa_aead_abort(
+    psa_aead_operation_t *arg0_operation)
+{
+    psa_status_t status = (psa_aead_abort)(arg0_operation);
+    return status;
+}
+
+/* Wrapper for psa_aead_decrypt */
+psa_status_t mbedtls_test_wrap_psa_aead_decrypt(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_nonce,
+    size_t arg3_nonce_length,
+    const uint8_t *arg4_additional_data,
+    size_t arg5_additional_data_length,
+    const uint8_t *arg6_ciphertext,
+    size_t arg7_ciphertext_length,
+    uint8_t *arg8_plaintext,
+    size_t arg9_plaintext_size,
+    size_t *arg10_plaintext_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_nonce, arg3_nonce_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_additional_data, arg5_additional_data_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg6_ciphertext, arg7_ciphertext_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg8_plaintext, arg9_plaintext_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_aead_decrypt)(arg0_key, arg1_alg, arg2_nonce, arg3_nonce_length, arg4_additional_data, arg5_additional_data_length, arg6_ciphertext, arg7_ciphertext_length, arg8_plaintext, arg9_plaintext_size, arg10_plaintext_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_nonce, arg3_nonce_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_additional_data, arg5_additional_data_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg6_ciphertext, arg7_ciphertext_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg8_plaintext, arg9_plaintext_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_aead_decrypt_setup */
+psa_status_t mbedtls_test_wrap_psa_aead_decrypt_setup(
+    psa_aead_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg)
+{
+    psa_status_t status = (psa_aead_decrypt_setup)(arg0_operation, arg1_key, arg2_alg);
+    return status;
+}
+
+/* Wrapper for psa_aead_encrypt */
+psa_status_t mbedtls_test_wrap_psa_aead_encrypt(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_nonce,
+    size_t arg3_nonce_length,
+    const uint8_t *arg4_additional_data,
+    size_t arg5_additional_data_length,
+    const uint8_t *arg6_plaintext,
+    size_t arg7_plaintext_length,
+    uint8_t *arg8_ciphertext,
+    size_t arg9_ciphertext_size,
+    size_t *arg10_ciphertext_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_nonce, arg3_nonce_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_additional_data, arg5_additional_data_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg6_plaintext, arg7_plaintext_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg8_ciphertext, arg9_ciphertext_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_aead_encrypt)(arg0_key, arg1_alg, arg2_nonce, arg3_nonce_length, arg4_additional_data, arg5_additional_data_length, arg6_plaintext, arg7_plaintext_length, arg8_ciphertext, arg9_ciphertext_size, arg10_ciphertext_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_nonce, arg3_nonce_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_additional_data, arg5_additional_data_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg6_plaintext, arg7_plaintext_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg8_ciphertext, arg9_ciphertext_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_aead_encrypt_setup */
+psa_status_t mbedtls_test_wrap_psa_aead_encrypt_setup(
+    psa_aead_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg)
+{
+    psa_status_t status = (psa_aead_encrypt_setup)(arg0_operation, arg1_key, arg2_alg);
+    return status;
+}
+
+/* Wrapper for psa_aead_finish */
+psa_status_t mbedtls_test_wrap_psa_aead_finish(
+    psa_aead_operation_t *arg0_operation,
+    uint8_t *arg1_ciphertext,
+    size_t arg2_ciphertext_size,
+    size_t *arg3_ciphertext_length,
+    uint8_t *arg4_tag,
+    size_t arg5_tag_size,
+    size_t *arg6_tag_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_ciphertext, arg2_ciphertext_size);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_tag, arg5_tag_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_aead_finish)(arg0_operation, arg1_ciphertext, arg2_ciphertext_size, arg3_ciphertext_length, arg4_tag, arg5_tag_size, arg6_tag_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_ciphertext, arg2_ciphertext_size);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_tag, arg5_tag_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_aead_generate_nonce */
+psa_status_t mbedtls_test_wrap_psa_aead_generate_nonce(
+    psa_aead_operation_t *arg0_operation,
+    uint8_t *arg1_nonce,
+    size_t arg2_nonce_size,
+    size_t *arg3_nonce_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_nonce, arg2_nonce_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_aead_generate_nonce)(arg0_operation, arg1_nonce, arg2_nonce_size, arg3_nonce_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_nonce, arg2_nonce_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_aead_set_lengths */
+psa_status_t mbedtls_test_wrap_psa_aead_set_lengths(
+    psa_aead_operation_t *arg0_operation,
+    size_t arg1_ad_length,
+    size_t arg2_plaintext_length)
+{
+    psa_status_t status = (psa_aead_set_lengths)(arg0_operation, arg1_ad_length, arg2_plaintext_length);
+    return status;
+}
+
+/* Wrapper for psa_aead_set_nonce */
+psa_status_t mbedtls_test_wrap_psa_aead_set_nonce(
+    psa_aead_operation_t *arg0_operation,
+    const uint8_t *arg1_nonce,
+    size_t arg2_nonce_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_nonce, arg2_nonce_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_aead_set_nonce)(arg0_operation, arg1_nonce, arg2_nonce_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_nonce, arg2_nonce_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_aead_update */
+psa_status_t mbedtls_test_wrap_psa_aead_update(
+    psa_aead_operation_t *arg0_operation,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length,
+    uint8_t *arg3_output,
+    size_t arg4_output_size,
+    size_t *arg5_output_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg3_output, arg4_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_aead_update)(arg0_operation, arg1_input, arg2_input_length, arg3_output, arg4_output_size, arg5_output_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg3_output, arg4_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_aead_update_ad */
+psa_status_t mbedtls_test_wrap_psa_aead_update_ad(
+    psa_aead_operation_t *arg0_operation,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_aead_update_ad)(arg0_operation, arg1_input, arg2_input_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_aead_verify */
+psa_status_t mbedtls_test_wrap_psa_aead_verify(
+    psa_aead_operation_t *arg0_operation,
+    uint8_t *arg1_plaintext,
+    size_t arg2_plaintext_size,
+    size_t *arg3_plaintext_length,
+    const uint8_t *arg4_tag,
+    size_t arg5_tag_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_plaintext, arg2_plaintext_size);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_tag, arg5_tag_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_aead_verify)(arg0_operation, arg1_plaintext, arg2_plaintext_size, arg3_plaintext_length, arg4_tag, arg5_tag_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_plaintext, arg2_plaintext_size);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_tag, arg5_tag_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_asymmetric_decrypt */
+psa_status_t mbedtls_test_wrap_psa_asymmetric_decrypt(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    const uint8_t *arg4_salt,
+    size_t arg5_salt_length,
+    uint8_t *arg6_output,
+    size_t arg7_output_size,
+    size_t *arg8_output_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_salt, arg5_salt_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg6_output, arg7_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_asymmetric_decrypt)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_salt, arg5_salt_length, arg6_output, arg7_output_size, arg8_output_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_salt, arg5_salt_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg6_output, arg7_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_asymmetric_encrypt */
+psa_status_t mbedtls_test_wrap_psa_asymmetric_encrypt(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    const uint8_t *arg4_salt,
+    size_t arg5_salt_length,
+    uint8_t *arg6_output,
+    size_t arg7_output_size,
+    size_t *arg8_output_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_salt, arg5_salt_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg6_output, arg7_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_asymmetric_encrypt)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_salt, arg5_salt_length, arg6_output, arg7_output_size, arg8_output_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_salt, arg5_salt_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg6_output, arg7_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_cipher_abort */
+psa_status_t mbedtls_test_wrap_psa_cipher_abort(
+    psa_cipher_operation_t *arg0_operation)
+{
+    psa_status_t status = (psa_cipher_abort)(arg0_operation);
+    return status;
+}
+
+/* Wrapper for psa_cipher_decrypt */
+psa_status_t mbedtls_test_wrap_psa_cipher_decrypt(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    uint8_t *arg4_output,
+    size_t arg5_output_size,
+    size_t *arg6_output_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_output, arg5_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_cipher_decrypt)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_output, arg5_output_size, arg6_output_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_output, arg5_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_cipher_decrypt_setup */
+psa_status_t mbedtls_test_wrap_psa_cipher_decrypt_setup(
+    psa_cipher_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg)
+{
+    psa_status_t status = (psa_cipher_decrypt_setup)(arg0_operation, arg1_key, arg2_alg);
+    return status;
+}
+
+/* Wrapper for psa_cipher_encrypt */
+psa_status_t mbedtls_test_wrap_psa_cipher_encrypt(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    uint8_t *arg4_output,
+    size_t arg5_output_size,
+    size_t *arg6_output_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_output, arg5_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_cipher_encrypt)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_output, arg5_output_size, arg6_output_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_output, arg5_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_cipher_encrypt_setup */
+psa_status_t mbedtls_test_wrap_psa_cipher_encrypt_setup(
+    psa_cipher_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg)
+{
+    psa_status_t status = (psa_cipher_encrypt_setup)(arg0_operation, arg1_key, arg2_alg);
+    return status;
+}
+
+/* Wrapper for psa_cipher_finish */
+psa_status_t mbedtls_test_wrap_psa_cipher_finish(
+    psa_cipher_operation_t *arg0_operation,
+    uint8_t *arg1_output,
+    size_t arg2_output_size,
+    size_t *arg3_output_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_output, arg2_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_cipher_finish)(arg0_operation, arg1_output, arg2_output_size, arg3_output_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_output, arg2_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_cipher_generate_iv */
+psa_status_t mbedtls_test_wrap_psa_cipher_generate_iv(
+    psa_cipher_operation_t *arg0_operation,
+    uint8_t *arg1_iv,
+    size_t arg2_iv_size,
+    size_t *arg3_iv_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_iv, arg2_iv_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_cipher_generate_iv)(arg0_operation, arg1_iv, arg2_iv_size, arg3_iv_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_iv, arg2_iv_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_cipher_set_iv */
+psa_status_t mbedtls_test_wrap_psa_cipher_set_iv(
+    psa_cipher_operation_t *arg0_operation,
+    const uint8_t *arg1_iv,
+    size_t arg2_iv_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_iv, arg2_iv_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_cipher_set_iv)(arg0_operation, arg1_iv, arg2_iv_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_iv, arg2_iv_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_cipher_update */
+psa_status_t mbedtls_test_wrap_psa_cipher_update(
+    psa_cipher_operation_t *arg0_operation,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length,
+    uint8_t *arg3_output,
+    size_t arg4_output_size,
+    size_t *arg5_output_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg3_output, arg4_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_cipher_update)(arg0_operation, arg1_input, arg2_input_length, arg3_output, arg4_output_size, arg5_output_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg3_output, arg4_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_copy_key */
+psa_status_t mbedtls_test_wrap_psa_copy_key(
+    mbedtls_svc_key_id_t arg0_source_key,
+    const psa_key_attributes_t *arg1_attributes,
+    mbedtls_svc_key_id_t *arg2_target_key)
+{
+    psa_status_t status = (psa_copy_key)(arg0_source_key, arg1_attributes, arg2_target_key);
+    return status;
+}
+
+/* Wrapper for psa_crypto_driver_pake_get_cipher_suite */
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_cipher_suite(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    psa_pake_cipher_suite_t *arg1_cipher_suite)
+{
+    psa_status_t status = (psa_crypto_driver_pake_get_cipher_suite)(arg0_inputs, arg1_cipher_suite);
+    return status;
+}
+
+/* Wrapper for psa_crypto_driver_pake_get_password */
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_password(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    uint8_t *arg1_buffer,
+    size_t arg2_buffer_size,
+    size_t *arg3_buffer_length)
+{
+    psa_status_t status = (psa_crypto_driver_pake_get_password)(arg0_inputs, arg1_buffer, arg2_buffer_size, arg3_buffer_length);
+    return status;
+}
+
+/* Wrapper for psa_crypto_driver_pake_get_password_len */
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_password_len(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    size_t *arg1_password_len)
+{
+    psa_status_t status = (psa_crypto_driver_pake_get_password_len)(arg0_inputs, arg1_password_len);
+    return status;
+}
+
+/* Wrapper for psa_crypto_driver_pake_get_peer */
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_peer(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    uint8_t *arg1_peer_id,
+    size_t arg2_peer_id_size,
+    size_t *arg3_peer_id_length)
+{
+    psa_status_t status = (psa_crypto_driver_pake_get_peer)(arg0_inputs, arg1_peer_id, arg2_peer_id_size, arg3_peer_id_length);
+    return status;
+}
+
+/* Wrapper for psa_crypto_driver_pake_get_peer_len */
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_peer_len(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    size_t *arg1_peer_len)
+{
+    psa_status_t status = (psa_crypto_driver_pake_get_peer_len)(arg0_inputs, arg1_peer_len);
+    return status;
+}
+
+/* Wrapper for psa_crypto_driver_pake_get_user */
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_user(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    uint8_t *arg1_user_id,
+    size_t arg2_user_id_size,
+    size_t *arg3_user_id_len)
+{
+    psa_status_t status = (psa_crypto_driver_pake_get_user)(arg0_inputs, arg1_user_id, arg2_user_id_size, arg3_user_id_len);
+    return status;
+}
+
+/* Wrapper for psa_crypto_driver_pake_get_user_len */
+psa_status_t mbedtls_test_wrap_psa_crypto_driver_pake_get_user_len(
+    const psa_crypto_driver_pake_inputs_t *arg0_inputs,
+    size_t *arg1_user_len)
+{
+    psa_status_t status = (psa_crypto_driver_pake_get_user_len)(arg0_inputs, arg1_user_len);
+    return status;
+}
+
+/* Wrapper for psa_crypto_init */
+psa_status_t mbedtls_test_wrap_psa_crypto_init(void)
+{
+    psa_status_t status = (psa_crypto_init)();
+    return status;
+}
+
+/* Wrapper for psa_destroy_key */
+psa_status_t mbedtls_test_wrap_psa_destroy_key(
+    mbedtls_svc_key_id_t arg0_key)
+{
+    psa_status_t status = (psa_destroy_key)(arg0_key);
+    return status;
+}
+
+/* Wrapper for psa_export_key */
+psa_status_t mbedtls_test_wrap_psa_export_key(
+    mbedtls_svc_key_id_t arg0_key,
+    uint8_t *arg1_data,
+    size_t arg2_data_size,
+    size_t *arg3_data_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_data, arg2_data_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_export_key)(arg0_key, arg1_data, arg2_data_size, arg3_data_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_data, arg2_data_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_export_public_key */
+psa_status_t mbedtls_test_wrap_psa_export_public_key(
+    mbedtls_svc_key_id_t arg0_key,
+    uint8_t *arg1_data,
+    size_t arg2_data_size,
+    size_t *arg3_data_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_data, arg2_data_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_export_public_key)(arg0_key, arg1_data, arg2_data_size, arg3_data_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_data, arg2_data_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_generate_key */
+psa_status_t mbedtls_test_wrap_psa_generate_key(
+    const psa_key_attributes_t *arg0_attributes,
+    mbedtls_svc_key_id_t *arg1_key)
+{
+    psa_status_t status = (psa_generate_key)(arg0_attributes, arg1_key);
+    return status;
+}
+
+/* Wrapper for psa_generate_key_ext */
+psa_status_t mbedtls_test_wrap_psa_generate_key_ext(
+    const psa_key_attributes_t *arg0_attributes,
+    const psa_key_production_parameters_t *arg1_params,
+    size_t arg2_params_data_length,
+    mbedtls_svc_key_id_t *arg3_key)
+{
+    psa_status_t status = (psa_generate_key_ext)(arg0_attributes, arg1_params, arg2_params_data_length, arg3_key);
+    return status;
+}
+
+/* Wrapper for psa_generate_random */
+psa_status_t mbedtls_test_wrap_psa_generate_random(
+    uint8_t *arg0_output,
+    size_t arg1_output_size)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg0_output, arg1_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_generate_random)(arg0_output, arg1_output_size);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg0_output, arg1_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_get_key_attributes */
+psa_status_t mbedtls_test_wrap_psa_get_key_attributes(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_key_attributes_t *arg1_attributes)
+{
+    psa_status_t status = (psa_get_key_attributes)(arg0_key, arg1_attributes);
+    return status;
+}
+
+/* Wrapper for psa_hash_abort */
+psa_status_t mbedtls_test_wrap_psa_hash_abort(
+    psa_hash_operation_t *arg0_operation)
+{
+    psa_status_t status = (psa_hash_abort)(arg0_operation);
+    return status;
+}
+
+/* Wrapper for psa_hash_clone */
+psa_status_t mbedtls_test_wrap_psa_hash_clone(
+    const psa_hash_operation_t *arg0_source_operation,
+    psa_hash_operation_t *arg1_target_operation)
+{
+    psa_status_t status = (psa_hash_clone)(arg0_source_operation, arg1_target_operation);
+    return status;
+}
+
+/* Wrapper for psa_hash_compare */
+psa_status_t mbedtls_test_wrap_psa_hash_compare(
+    psa_algorithm_t arg0_alg,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length,
+    const uint8_t *arg3_hash,
+    size_t arg4_hash_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg3_hash, arg4_hash_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_hash_compare)(arg0_alg, arg1_input, arg2_input_length, arg3_hash, arg4_hash_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg3_hash, arg4_hash_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_hash_compute */
+psa_status_t mbedtls_test_wrap_psa_hash_compute(
+    psa_algorithm_t arg0_alg,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length,
+    uint8_t *arg3_hash,
+    size_t arg4_hash_size,
+    size_t *arg5_hash_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg3_hash, arg4_hash_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_hash_compute)(arg0_alg, arg1_input, arg2_input_length, arg3_hash, arg4_hash_size, arg5_hash_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg3_hash, arg4_hash_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_hash_finish */
+psa_status_t mbedtls_test_wrap_psa_hash_finish(
+    psa_hash_operation_t *arg0_operation,
+    uint8_t *arg1_hash,
+    size_t arg2_hash_size,
+    size_t *arg3_hash_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_hash, arg2_hash_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_hash_finish)(arg0_operation, arg1_hash, arg2_hash_size, arg3_hash_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_hash, arg2_hash_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_hash_setup */
+psa_status_t mbedtls_test_wrap_psa_hash_setup(
+    psa_hash_operation_t *arg0_operation,
+    psa_algorithm_t arg1_alg)
+{
+    psa_status_t status = (psa_hash_setup)(arg0_operation, arg1_alg);
+    return status;
+}
+
+/* Wrapper for psa_hash_update */
+psa_status_t mbedtls_test_wrap_psa_hash_update(
+    psa_hash_operation_t *arg0_operation,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_hash_update)(arg0_operation, arg1_input, arg2_input_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_hash_verify */
+psa_status_t mbedtls_test_wrap_psa_hash_verify(
+    psa_hash_operation_t *arg0_operation,
+    const uint8_t *arg1_hash,
+    size_t arg2_hash_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_hash, arg2_hash_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_hash_verify)(arg0_operation, arg1_hash, arg2_hash_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_hash, arg2_hash_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_import_key */
+psa_status_t mbedtls_test_wrap_psa_import_key(
+    const psa_key_attributes_t *arg0_attributes,
+    const uint8_t *arg1_data,
+    size_t arg2_data_length,
+    mbedtls_svc_key_id_t *arg3_key)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_data, arg2_data_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_import_key)(arg0_attributes, arg1_data, arg2_data_length, arg3_key);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_data, arg2_data_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_key_derivation_abort */
+psa_status_t mbedtls_test_wrap_psa_key_derivation_abort(
+    psa_key_derivation_operation_t *arg0_operation)
+{
+    psa_status_t status = (psa_key_derivation_abort)(arg0_operation);
+    return status;
+}
+
+/* Wrapper for psa_key_derivation_get_capacity */
+psa_status_t mbedtls_test_wrap_psa_key_derivation_get_capacity(
+    const psa_key_derivation_operation_t *arg0_operation,
+    size_t *arg1_capacity)
+{
+    psa_status_t status = (psa_key_derivation_get_capacity)(arg0_operation, arg1_capacity);
+    return status;
+}
+
+/* Wrapper for psa_key_derivation_input_bytes */
+psa_status_t mbedtls_test_wrap_psa_key_derivation_input_bytes(
+    psa_key_derivation_operation_t *arg0_operation,
+    psa_key_derivation_step_t arg1_step,
+    const uint8_t *arg2_data,
+    size_t arg3_data_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_data, arg3_data_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_key_derivation_input_bytes)(arg0_operation, arg1_step, arg2_data, arg3_data_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_data, arg3_data_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_key_derivation_input_integer */
+psa_status_t mbedtls_test_wrap_psa_key_derivation_input_integer(
+    psa_key_derivation_operation_t *arg0_operation,
+    psa_key_derivation_step_t arg1_step,
+    uint64_t arg2_value)
+{
+    psa_status_t status = (psa_key_derivation_input_integer)(arg0_operation, arg1_step, arg2_value);
+    return status;
+}
+
+/* Wrapper for psa_key_derivation_input_key */
+psa_status_t mbedtls_test_wrap_psa_key_derivation_input_key(
+    psa_key_derivation_operation_t *arg0_operation,
+    psa_key_derivation_step_t arg1_step,
+    mbedtls_svc_key_id_t arg2_key)
+{
+    psa_status_t status = (psa_key_derivation_input_key)(arg0_operation, arg1_step, arg2_key);
+    return status;
+}
+
+/* Wrapper for psa_key_derivation_key_agreement */
+psa_status_t mbedtls_test_wrap_psa_key_derivation_key_agreement(
+    psa_key_derivation_operation_t *arg0_operation,
+    psa_key_derivation_step_t arg1_step,
+    mbedtls_svc_key_id_t arg2_private_key,
+    const uint8_t *arg3_peer_key,
+    size_t arg4_peer_key_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg3_peer_key, arg4_peer_key_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_key_derivation_key_agreement)(arg0_operation, arg1_step, arg2_private_key, arg3_peer_key, arg4_peer_key_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg3_peer_key, arg4_peer_key_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_key_derivation_output_bytes */
+psa_status_t mbedtls_test_wrap_psa_key_derivation_output_bytes(
+    psa_key_derivation_operation_t *arg0_operation,
+    uint8_t *arg1_output,
+    size_t arg2_output_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_output, arg2_output_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_key_derivation_output_bytes)(arg0_operation, arg1_output, arg2_output_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_output, arg2_output_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_key_derivation_output_key */
+psa_status_t mbedtls_test_wrap_psa_key_derivation_output_key(
+    const psa_key_attributes_t *arg0_attributes,
+    psa_key_derivation_operation_t *arg1_operation,
+    mbedtls_svc_key_id_t *arg2_key)
+{
+    psa_status_t status = (psa_key_derivation_output_key)(arg0_attributes, arg1_operation, arg2_key);
+    return status;
+}
+
+/* Wrapper for psa_key_derivation_output_key_ext */
+psa_status_t mbedtls_test_wrap_psa_key_derivation_output_key_ext(
+    const psa_key_attributes_t *arg0_attributes,
+    psa_key_derivation_operation_t *arg1_operation,
+    const psa_key_production_parameters_t *arg2_params,
+    size_t arg3_params_data_length,
+    mbedtls_svc_key_id_t *arg4_key)
+{
+    psa_status_t status = (psa_key_derivation_output_key_ext)(arg0_attributes, arg1_operation, arg2_params, arg3_params_data_length, arg4_key);
+    return status;
+}
+
+/* Wrapper for psa_key_derivation_set_capacity */
+psa_status_t mbedtls_test_wrap_psa_key_derivation_set_capacity(
+    psa_key_derivation_operation_t *arg0_operation,
+    size_t arg1_capacity)
+{
+    psa_status_t status = (psa_key_derivation_set_capacity)(arg0_operation, arg1_capacity);
+    return status;
+}
+
+/* Wrapper for psa_key_derivation_setup */
+psa_status_t mbedtls_test_wrap_psa_key_derivation_setup(
+    psa_key_derivation_operation_t *arg0_operation,
+    psa_algorithm_t arg1_alg)
+{
+    psa_status_t status = (psa_key_derivation_setup)(arg0_operation, arg1_alg);
+    return status;
+}
+
+/* Wrapper for psa_mac_abort */
+psa_status_t mbedtls_test_wrap_psa_mac_abort(
+    psa_mac_operation_t *arg0_operation)
+{
+    psa_status_t status = (psa_mac_abort)(arg0_operation);
+    return status;
+}
+
+/* Wrapper for psa_mac_compute */
+psa_status_t mbedtls_test_wrap_psa_mac_compute(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    uint8_t *arg4_mac,
+    size_t arg5_mac_size,
+    size_t *arg6_mac_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_mac, arg5_mac_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_mac_compute)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_mac, arg5_mac_size, arg6_mac_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_mac, arg5_mac_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_mac_sign_finish */
+psa_status_t mbedtls_test_wrap_psa_mac_sign_finish(
+    psa_mac_operation_t *arg0_operation,
+    uint8_t *arg1_mac,
+    size_t arg2_mac_size,
+    size_t *arg3_mac_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_mac, arg2_mac_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_mac_sign_finish)(arg0_operation, arg1_mac, arg2_mac_size, arg3_mac_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_mac, arg2_mac_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_mac_sign_setup */
+psa_status_t mbedtls_test_wrap_psa_mac_sign_setup(
+    psa_mac_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg)
+{
+    psa_status_t status = (psa_mac_sign_setup)(arg0_operation, arg1_key, arg2_alg);
+    return status;
+}
+
+/* Wrapper for psa_mac_update */
+psa_status_t mbedtls_test_wrap_psa_mac_update(
+    psa_mac_operation_t *arg0_operation,
+    const uint8_t *arg1_input,
+    size_t arg2_input_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_input, arg2_input_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_mac_update)(arg0_operation, arg1_input, arg2_input_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_input, arg2_input_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_mac_verify */
+psa_status_t mbedtls_test_wrap_psa_mac_verify(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    const uint8_t *arg4_mac,
+    size_t arg5_mac_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_mac, arg5_mac_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_mac_verify)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_mac, arg5_mac_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_mac, arg5_mac_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_mac_verify_finish */
+psa_status_t mbedtls_test_wrap_psa_mac_verify_finish(
+    psa_mac_operation_t *arg0_operation,
+    const uint8_t *arg1_mac,
+    size_t arg2_mac_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_mac, arg2_mac_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_mac_verify_finish)(arg0_operation, arg1_mac, arg2_mac_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_mac, arg2_mac_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_mac_verify_setup */
+psa_status_t mbedtls_test_wrap_psa_mac_verify_setup(
+    psa_mac_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg)
+{
+    psa_status_t status = (psa_mac_verify_setup)(arg0_operation, arg1_key, arg2_alg);
+    return status;
+}
+
+/* Wrapper for psa_pake_abort */
+psa_status_t mbedtls_test_wrap_psa_pake_abort(
+    psa_pake_operation_t *arg0_operation)
+{
+    psa_status_t status = (psa_pake_abort)(arg0_operation);
+    return status;
+}
+
+/* Wrapper for psa_pake_get_implicit_key */
+psa_status_t mbedtls_test_wrap_psa_pake_get_implicit_key(
+    psa_pake_operation_t *arg0_operation,
+    psa_key_derivation_operation_t *arg1_output)
+{
+    psa_status_t status = (psa_pake_get_implicit_key)(arg0_operation, arg1_output);
+    return status;
+}
+
+/* Wrapper for psa_pake_input */
+psa_status_t mbedtls_test_wrap_psa_pake_input(
+    psa_pake_operation_t *arg0_operation,
+    psa_pake_step_t arg1_step,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_pake_input)(arg0_operation, arg1_step, arg2_input, arg3_input_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_pake_output */
+psa_status_t mbedtls_test_wrap_psa_pake_output(
+    psa_pake_operation_t *arg0_operation,
+    psa_pake_step_t arg1_step,
+    uint8_t *arg2_output,
+    size_t arg3_output_size,
+    size_t *arg4_output_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_output, arg3_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_pake_output)(arg0_operation, arg1_step, arg2_output, arg3_output_size, arg4_output_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_output, arg3_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_pake_set_password_key */
+psa_status_t mbedtls_test_wrap_psa_pake_set_password_key(
+    psa_pake_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_password)
+{
+    psa_status_t status = (psa_pake_set_password_key)(arg0_operation, arg1_password);
+    return status;
+}
+
+/* Wrapper for psa_pake_set_peer */
+psa_status_t mbedtls_test_wrap_psa_pake_set_peer(
+    psa_pake_operation_t *arg0_operation,
+    const uint8_t *arg1_peer_id,
+    size_t arg2_peer_id_len)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_peer_id, arg2_peer_id_len);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_pake_set_peer)(arg0_operation, arg1_peer_id, arg2_peer_id_len);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_peer_id, arg2_peer_id_len);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_pake_set_role */
+psa_status_t mbedtls_test_wrap_psa_pake_set_role(
+    psa_pake_operation_t *arg0_operation,
+    psa_pake_role_t arg1_role)
+{
+    psa_status_t status = (psa_pake_set_role)(arg0_operation, arg1_role);
+    return status;
+}
+
+/* Wrapper for psa_pake_set_user */
+psa_status_t mbedtls_test_wrap_psa_pake_set_user(
+    psa_pake_operation_t *arg0_operation,
+    const uint8_t *arg1_user_id,
+    size_t arg2_user_id_len)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_user_id, arg2_user_id_len);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_pake_set_user)(arg0_operation, arg1_user_id, arg2_user_id_len);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_user_id, arg2_user_id_len);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_pake_setup */
+psa_status_t mbedtls_test_wrap_psa_pake_setup(
+    psa_pake_operation_t *arg0_operation,
+    const psa_pake_cipher_suite_t *arg1_cipher_suite)
+{
+    psa_status_t status = (psa_pake_setup)(arg0_operation, arg1_cipher_suite);
+    return status;
+}
+
+/* Wrapper for psa_purge_key */
+psa_status_t mbedtls_test_wrap_psa_purge_key(
+    mbedtls_svc_key_id_t arg0_key)
+{
+    psa_status_t status = (psa_purge_key)(arg0_key);
+    return status;
+}
+
+/* Wrapper for psa_raw_key_agreement */
+psa_status_t mbedtls_test_wrap_psa_raw_key_agreement(
+    psa_algorithm_t arg0_alg,
+    mbedtls_svc_key_id_t arg1_private_key,
+    const uint8_t *arg2_peer_key,
+    size_t arg3_peer_key_length,
+    uint8_t *arg4_output,
+    size_t arg5_output_size,
+    size_t *arg6_output_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_peer_key, arg3_peer_key_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_output, arg5_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_raw_key_agreement)(arg0_alg, arg1_private_key, arg2_peer_key, arg3_peer_key_length, arg4_output, arg5_output_size, arg6_output_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_peer_key, arg3_peer_key_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_output, arg5_output_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_sign_hash */
+psa_status_t mbedtls_test_wrap_psa_sign_hash(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_hash,
+    size_t arg3_hash_length,
+    uint8_t *arg4_signature,
+    size_t arg5_signature_size,
+    size_t *arg6_signature_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_hash, arg3_hash_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_signature, arg5_signature_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_sign_hash)(arg0_key, arg1_alg, arg2_hash, arg3_hash_length, arg4_signature, arg5_signature_size, arg6_signature_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_hash, arg3_hash_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_signature, arg5_signature_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_sign_hash_abort */
+psa_status_t mbedtls_test_wrap_psa_sign_hash_abort(
+    psa_sign_hash_interruptible_operation_t *arg0_operation)
+{
+    psa_status_t status = (psa_sign_hash_abort)(arg0_operation);
+    return status;
+}
+
+/* Wrapper for psa_sign_hash_complete */
+psa_status_t mbedtls_test_wrap_psa_sign_hash_complete(
+    psa_sign_hash_interruptible_operation_t *arg0_operation,
+    uint8_t *arg1_signature,
+    size_t arg2_signature_size,
+    size_t *arg3_signature_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg1_signature, arg2_signature_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_sign_hash_complete)(arg0_operation, arg1_signature, arg2_signature_size, arg3_signature_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg1_signature, arg2_signature_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_sign_hash_start */
+psa_status_t mbedtls_test_wrap_psa_sign_hash_start(
+    psa_sign_hash_interruptible_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg,
+    const uint8_t *arg3_hash,
+    size_t arg4_hash_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg3_hash, arg4_hash_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_sign_hash_start)(arg0_operation, arg1_key, arg2_alg, arg3_hash, arg4_hash_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg3_hash, arg4_hash_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_sign_message */
+psa_status_t mbedtls_test_wrap_psa_sign_message(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    uint8_t *arg4_signature,
+    size_t arg5_signature_size,
+    size_t *arg6_signature_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_signature, arg5_signature_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_sign_message)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_signature, arg5_signature_size, arg6_signature_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_signature, arg5_signature_size);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_verify_hash */
+psa_status_t mbedtls_test_wrap_psa_verify_hash(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_hash,
+    size_t arg3_hash_length,
+    const uint8_t *arg4_signature,
+    size_t arg5_signature_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_hash, arg3_hash_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_signature, arg5_signature_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_verify_hash)(arg0_key, arg1_alg, arg2_hash, arg3_hash_length, arg4_signature, arg5_signature_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_hash, arg3_hash_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_signature, arg5_signature_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_verify_hash_abort */
+psa_status_t mbedtls_test_wrap_psa_verify_hash_abort(
+    psa_verify_hash_interruptible_operation_t *arg0_operation)
+{
+    psa_status_t status = (psa_verify_hash_abort)(arg0_operation);
+    return status;
+}
+
+/* Wrapper for psa_verify_hash_complete */
+psa_status_t mbedtls_test_wrap_psa_verify_hash_complete(
+    psa_verify_hash_interruptible_operation_t *arg0_operation)
+{
+    psa_status_t status = (psa_verify_hash_complete)(arg0_operation);
+    return status;
+}
+
+/* Wrapper for psa_verify_hash_start */
+psa_status_t mbedtls_test_wrap_psa_verify_hash_start(
+    psa_verify_hash_interruptible_operation_t *arg0_operation,
+    mbedtls_svc_key_id_t arg1_key,
+    psa_algorithm_t arg2_alg,
+    const uint8_t *arg3_hash,
+    size_t arg4_hash_length,
+    const uint8_t *arg5_signature,
+    size_t arg6_signature_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg3_hash, arg4_hash_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg5_signature, arg6_signature_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_verify_hash_start)(arg0_operation, arg1_key, arg2_alg, arg3_hash, arg4_hash_length, arg5_signature, arg6_signature_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg3_hash, arg4_hash_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg5_signature, arg6_signature_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+/* Wrapper for psa_verify_message */
+psa_status_t mbedtls_test_wrap_psa_verify_message(
+    mbedtls_svc_key_id_t arg0_key,
+    psa_algorithm_t arg1_alg,
+    const uint8_t *arg2_input,
+    size_t arg3_input_length,
+    const uint8_t *arg4_signature,
+    size_t arg5_signature_length)
+{
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_POISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_POISON(arg4_signature, arg5_signature_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    psa_status_t status = (psa_verify_message)(arg0_key, arg1_alg, arg2_input, arg3_input_length, arg4_signature, arg5_signature_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg2_input, arg3_input_length);
+    MBEDTLS_TEST_MEMORY_UNPOISON(arg4_signature, arg5_signature_length);
+#endif /* !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS) */
+    return status;
+}
+
+#endif /* defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_TEST_HOOKS) && \
+    !defined(RECORD_PSA_STATUS_COVERAGE_LOG) */
+
+/* End of automatically generated file. */
diff --git a/tests/src/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c
index 5d4cb1c..255849f 100644
--- a/tests/src/test_helpers/ssl_helpers.c
+++ b/tests/src/test_helpers/ssl_helpers.c
@@ -12,9 +12,7 @@
 #include "mbedtls/psa_util.h"
 
 #if defined(MBEDTLS_SSL_TLS_C)
-#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
-static int rng_seed = 0xBEEF;
-static int rng_get(void *p_rng, unsigned char *output, size_t output_len)
+int mbedtls_test_random(void *p_rng, unsigned char *output, size_t output_len)
 {
     (void) p_rng;
     for (size_t i = 0; i < output_len; i++) {
@@ -23,7 +21,6 @@
 
     return 0;
 }
-#endif
 
 void mbedtls_test_ssl_log_analyzer(void *ctx, int level,
                                    const char *file, int line,
@@ -46,6 +43,8 @@
     mbedtls_test_handshake_test_options *opts)
 {
 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+    static int rng_seed = 0xBEEF;
+
     srand(rng_seed);
     rng_seed += 0xD0;
 #endif
@@ -68,6 +67,7 @@
     opts->legacy_renegotiation = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION;
     opts->resize_buffers = 1;
     opts->early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED;
+    opts->max_early_data_size = -1;
 #if defined(MBEDTLS_SSL_CACHE_C)
     TEST_CALLOC(opts->cache, 1);
     mbedtls_ssl_cache_init(opts->cache);
@@ -755,7 +755,7 @@
 
     mbedtls_ssl_init(&(ep->ssl));
     mbedtls_ssl_config_init(&(ep->conf));
-    mbedtls_ssl_conf_rng(&(ep->conf), rng_get, NULL);
+    mbedtls_ssl_conf_rng(&(ep->conf), mbedtls_test_random, NULL);
 
     TEST_ASSERT(mbedtls_ssl_conf_get_user_data_p(&ep->conf) == NULL);
     TEST_EQUAL(mbedtls_ssl_conf_get_user_data_n(&ep->conf), 0);
@@ -826,6 +826,19 @@
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
     mbedtls_ssl_conf_early_data(&(ep->conf), options->early_data);
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (endpoint_type == MBEDTLS_SSL_IS_SERVER &&
+        (options->max_early_data_size >= 0)) {
+        mbedtls_ssl_conf_max_early_data_size(&(ep->conf),
+                                             options->max_early_data_size);
+    }
+#endif
+#if defined(MBEDTLS_SSL_ALPN)
+    /* check that alpn_list contains at least one valid entry */
+    if (options->alpn_list[0] != NULL) {
+        mbedtls_ssl_conf_alpn_protocols(&(ep->conf), options->alpn_list);
+    }
+#endif
 #endif
 
 #if defined(MBEDTLS_SSL_CACHE_C) && defined(MBEDTLS_SSL_SRV_C)
@@ -1778,24 +1791,33 @@
     session->endpoint = endpoint_type == MBEDTLS_SSL_IS_CLIENT ?
                         MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER;
     session->ciphersuite = 0xabcd;
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
     session->ticket_age_add = 0x87654321;
     session->ticket_flags = 0x7;
-
     session->resumption_key_len = 32;
     memset(session->resumption_key, 0x99, sizeof(session->resumption_key));
-
-#if defined(MBEDTLS_SSL_EARLY_DATA)
-    session->max_early_data_size = 0x87654321;
 #endif
 
-#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+#if defined(MBEDTLS_SSL_SRV_C)
     if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
-        session->ticket_creation_time = mbedtls_ms_time() - 42;
-    }
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+        int ret = mbedtls_ssl_session_set_ticket_alpn(session, "ALPNExample");
+        if (ret != 0) {
+            return -1;
+        }
 #endif
+#if defined(MBEDTLS_HAVE_TIME)
+        session->ticket_creation_time = mbedtls_ms_time() - 42;
+#endif
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+    }
+#endif /* MBEDTLS_SSL_SRV_C */
 
 #if defined(MBEDTLS_SSL_CLI_C)
     if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 #if defined(MBEDTLS_HAVE_TIME)
         session->ticket_reception_time = mbedtls_ms_time() - 40;
 #endif
@@ -1809,9 +1831,22 @@
             }
             memset(session->ticket, 33, ticket_len);
         }
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+        char hostname[] = "hostname example";
+        session->hostname = mbedtls_calloc(1, sizeof(hostname));
+        if (session->hostname == NULL) {
+            return -1;
+        }
+        memcpy(session->hostname, hostname, sizeof(hostname));
+#endif
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
     }
 #endif /* MBEDTLS_SSL_CLI_C */
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    session->max_early_data_size = 0x87654321;
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
 #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
     session->record_size_limit = 2048;
 #endif
diff --git a/tests/src/test_keys.h b/tests/src/test_keys.h
new file mode 100644
index 0000000..ec54fe4
--- /dev/null
+++ b/tests/src/test_keys.h
@@ -0,0 +1,799 @@
+/*********************************************************************************
+ * This file was automatically generated from tests/scripts/generate_test_keys.py.
+ * Please do not edit it manually.
+ *********************************************************************************/
+
+const unsigned char test_ec_secp192k1_priv[] = {
+    0x29, 0x7a, 0xc1, 0x72, 0x2c, 0xca, 0xc7, 0x58, 0x9e, 0xcb, 0x24, 0x0d, 0xc7, 0x19, 0x84, 0x25,
+    0x38, 0xca, 0x97, 0x4b, 0xeb, 0x79, 0xf2, 0x28,
+};
+const unsigned char test_ec_secp192k1_pub[] = {
+    0x04, 0x26, 0xb7, 0xbb, 0x38, 0xda, 0x64, 0x9a, 0xc2, 0x13, 0x8f, 0xc0, 0x50, 0xc6, 0x54, 0x8b,
+    0x32, 0x55, 0x3d, 0xab, 0x68, 0xaf, 0xeb, 0xc3, 0x61, 0x05, 0xd3, 0x25, 0xb7, 0x55, 0x38, 0xc1,
+    0x23, 0x23, 0xcb, 0x07, 0x64, 0x78, 0x9e, 0xcb, 0x99, 0x26, 0x71, 0xbe, 0xb2, 0xb6, 0xbe, 0xf2,
+    0xf5,
+};
+
+const unsigned char test_ec_secp256k1_priv[] = {
+    0x7f, 0xa0, 0x6f, 0xa0, 0x2d, 0x0e, 0x91, 0x1b, 0x9a, 0x47, 0xfd, 0xc1, 0x7d, 0x2d, 0x96, 0x2c,
+    0xa0, 0x1e, 0x2f, 0x31, 0xd6, 0x0c, 0x62, 0x12, 0xd0, 0xed, 0x7e, 0x3b, 0xba, 0x23, 0xa7, 0xb9,
+};
+const unsigned char test_ec_secp256k1_pub[] = {
+    0x04, 0x5c, 0x39, 0x15, 0x45, 0x79, 0xef, 0xd6, 0x67, 0xad, 0xc7, 0x3a, 0x81, 0x01, 0x5a, 0x79,
+    0x7d, 0x2c, 0x86, 0x82, 0xcd, 0xfb, 0xd3, 0xc3, 0x55, 0x3c, 0x4a, 0x18, 0x5d, 0x48, 0x1c, 0xdc,
+    0x50, 0xe4, 0x2a, 0x0e, 0x1c, 0xbc, 0x3c, 0xa2, 0x9a, 0x32, 0xa6, 0x45, 0xe9, 0x27, 0xf5, 0x4b,
+    0xea, 0xed, 0x14, 0xc9, 0xdb, 0xbf, 0x82, 0x79, 0xd7, 0x25, 0xf5, 0x49, 0x5c, 0xa9, 0x24, 0xb2,
+    0x4d,
+};
+
+const unsigned char test_ec_secp192r1_priv[] = {
+    0xd8, 0x3b, 0x57, 0xa5, 0x9c, 0x51, 0x35, 0x8d, 0x9c, 0x8b, 0xbb, 0x89, 0x8a, 0xff, 0x50, 0x7f,
+    0x44, 0xdd, 0x14, 0xcf, 0x16, 0x91, 0x71, 0x90,
+};
+const unsigned char test_ec_secp192r1_pub[] = {
+    0x04, 0xe3, 0x5f, 0xcb, 0xee, 0x11, 0xce, 0xc3, 0x15, 0x4f, 0x80, 0xa1, 0xa6, 0x1d, 0xf7, 0xd7,
+    0x61, 0x2d, 0xe4, 0xf2, 0xfd, 0x70, 0xc5, 0x60, 0x8d, 0x0e, 0xe3, 0xa4, 0xa1, 0xa5, 0x71, 0x94,
+    0x71, 0xad, 0xb3, 0x39, 0x66, 0xdd, 0x9b, 0x03, 0x5f, 0xdb, 0x77, 0x4f, 0xee, 0xba, 0x94, 0xb0,
+    0x4c,
+};
+
+const unsigned char test_ec_secp224r1_priv[] = {
+    0x87, 0x2f, 0x20, 0x3b, 0x3a, 0xd3, 0x5b, 0x7f, 0x2e, 0xcc, 0x80, 0x3c, 0x3a, 0x0e, 0x1e, 0x0b,
+    0x1e, 0xd6, 0x1c, 0xc1, 0xaf, 0xe7, 0x1b, 0x18, 0x9c, 0xd4, 0xc9, 0x95,
+};
+const unsigned char test_ec_secp224r1_pub[] = {
+    0x04, 0x6f, 0x00, 0xea, 0xda, 0xa9, 0x49, 0xfe, 0xe3, 0xe9, 0xe1, 0xc7, 0xfa, 0x12, 0x47, 0xee,
+    0xce, 0xc8, 0x6a, 0x0d, 0xce, 0x46, 0x41, 0x8b, 0x9b, 0xd3, 0x11, 0x7b, 0x98, 0x1d, 0x4b, 0xd0,
+    0xae, 0x7a, 0x99, 0x0d, 0xe9, 0x12, 0xf9, 0xd0, 0x60, 0xd6, 0xcb, 0x53, 0x1a, 0x42, 0xd2, 0x2e,
+    0x39, 0x4a, 0xc2, 0x9e, 0x81, 0x80, 0x4b, 0xf1, 0x60,
+};
+
+const unsigned char test_ec_secp256r1_priv[] = {
+    0x49, 0xc9, 0xa8, 0xc1, 0x8c, 0x4b, 0x88, 0x56, 0x38, 0xc4, 0x31, 0xcf, 0x1d, 0xf1, 0xc9, 0x94,
+    0x13, 0x16, 0x09, 0xb5, 0x80, 0xd4, 0xfd, 0x43, 0xa0, 0xca, 0xb1, 0x7d, 0xb2, 0xf1, 0x3e, 0xee,
+};
+const unsigned char test_ec_secp256r1_pub[] = {
+    0x04, 0x77, 0x72, 0x65, 0x6f, 0x81, 0x4b, 0x39, 0x92, 0x79, 0xd5, 0xe1, 0xf1, 0x78, 0x1f, 0xac,
+    0x6f, 0x09, 0x9a, 0x3c, 0x5c, 0xa1, 0xb0, 0xe3, 0x53, 0x51, 0x83, 0x4b, 0x08, 0xb6, 0x5e, 0x0b,
+    0x57, 0x25, 0x90, 0xcd, 0xaf, 0x8f, 0x76, 0x93, 0x61, 0xbc, 0xf3, 0x4a, 0xcf, 0xc1, 0x1e, 0x5e,
+    0x07, 0x4e, 0x84, 0x26, 0xbd, 0xde, 0x04, 0xbe, 0x6e, 0x65, 0x39, 0x45, 0x44, 0x96, 0x17, 0xde,
+    0x45,
+};
+
+const unsigned char test_ec_secp384r1_priv[] = {
+    0x3f, 0x5d, 0x8d, 0x9b, 0xe2, 0x80, 0xb5, 0x69, 0x6c, 0xc5, 0xcc, 0x9f, 0x94, 0xcf, 0x8a, 0xf7,
+    0xe6, 0xb6, 0x1d, 0xd6, 0x59, 0x2b, 0x2a, 0xb2, 0xb3, 0xa4, 0xc6, 0x07, 0x45, 0x04, 0x17, 0xec,
+    0x32, 0x7d, 0xcd, 0xca, 0xed, 0x7c, 0x10, 0x05, 0x3d, 0x71, 0x9a, 0x05, 0x74, 0xf0, 0xa7, 0x6a,
+};
+const unsigned char test_ec_secp384r1_pub[] = {
+    0x04, 0xd9, 0xc6, 0x62, 0xb5, 0x0b, 0xa2, 0x9c, 0xa4, 0x79, 0x90, 0x45, 0x0e, 0x04, 0x3a, 0xea,
+    0xf4, 0xf0, 0xc6, 0x9b, 0x15, 0x67, 0x6d, 0x11, 0x2f, 0x62, 0x2a, 0x71, 0xc9, 0x30, 0x59, 0xaf,
+    0x99, 0x96, 0x91, 0xc5, 0x68, 0x0d, 0x2b, 0x44, 0xd1, 0x11, 0x57, 0x9d, 0xb1, 0x2f, 0x4a, 0x41,
+    0x3a, 0x2e, 0xd5, 0xc4, 0x5f, 0xcf, 0xb6, 0x7b, 0x5b, 0x63, 0xe0, 0x0b, 0x91, 0xeb, 0xe5, 0x9d,
+    0x09, 0xa6, 0xb1, 0xac, 0x2c, 0x0c, 0x42, 0x82, 0xaa, 0x12, 0x31, 0x7e, 0xd5, 0x91, 0x4f, 0x99,
+    0x9b, 0xc4, 0x88, 0xbb, 0x13, 0x2e, 0x83, 0x42, 0xcc, 0x36, 0xf2, 0xca, 0x5e, 0x33, 0x79, 0xc7,
+    0x47,
+};
+
+const unsigned char test_ec_secp521r1_priv[] = {
+    0x01, 0xb1, 0xb6, 0xad, 0x07, 0xbb, 0x79, 0xe7, 0x32, 0x0d, 0xa5, 0x98, 0x60, 0xea, 0x28, 0xe0,
+    0x55, 0x28, 0x4f, 0x60, 0x58, 0xf2, 0x79, 0xde, 0x66, 0x6e, 0x06, 0xd4, 0x35, 0xd2, 0xaf, 0x7b,
+    0xda, 0x28, 0xd9, 0x9f, 0xa4, 0x7b, 0x7d, 0xd0, 0x96, 0x3e, 0x16, 0xb0, 0x07, 0x30, 0x78, 0xee,
+    0x8b, 0x8a, 0x38, 0xd9, 0x66, 0xa5, 0x82, 0xf4, 0x6d, 0x19, 0xff, 0x95, 0xdf, 0x3a, 0xd9, 0x68,
+    0x5a, 0xae,
+};
+const unsigned char test_ec_secp521r1_pub[] = {
+    0x04, 0x00, 0x1d, 0xe1, 0x42, 0xd5, 0x4f, 0x69, 0xeb, 0x03, 0x8e, 0xe4, 0xb7, 0xaf, 0x9d, 0x3c,
+    0xa0, 0x77, 0x36, 0xfd, 0x9c, 0xf7, 0x19, 0xeb, 0x35, 0x4d, 0x69, 0x87, 0x9e, 0xe7, 0xf3, 0xc1,
+    0x36, 0xfb, 0x0f, 0xbf, 0x9f, 0x08, 0xf8, 0x6b, 0xe5, 0xfa, 0x12, 0x8e, 0xc1, 0xa0, 0x51, 0xd3,
+    0xe6, 0xc6, 0x43, 0xe8, 0x5a, 0xda, 0x8f, 0xfa, 0xcf, 0x36, 0x63, 0xc2, 0x60, 0xbd, 0x2c, 0x84,
+    0x4b, 0x6f, 0x56, 0x00, 0xce, 0xe8, 0xe4, 0x8a, 0x9e, 0x65, 0xd0, 0x9c, 0xad, 0xd8, 0x9f, 0x23,
+    0x5d, 0xee, 0x05, 0xf3, 0xb8, 0xa6, 0x46, 0xbe, 0x71, 0x5f, 0x1f, 0x67, 0xd5, 0xb4, 0x34, 0xe0,
+    0xff, 0x23, 0xa1, 0xfc, 0x07, 0xef, 0x77, 0x40, 0x19, 0x3e, 0x40, 0xee, 0xff, 0x6f, 0x3b, 0xcd,
+    0xfd, 0x76, 0x5a, 0xa9, 0x15, 0x50, 0x33, 0x52, 0x4f, 0xe4, 0xf2, 0x05, 0xf5, 0x44, 0x4e, 0x29,
+    0x2c, 0x4c, 0x2f, 0x6a, 0xc1,
+};
+
+const unsigned char test_ec_bp256r1_priv[] = {
+    0x21, 0x61, 0xd6, 0xf2, 0xdb, 0x76, 0x52, 0x6f, 0xa6, 0x2c, 0x16, 0xf3, 0x56, 0xa8, 0x0f, 0x01,
+    0xf3, 0x2f, 0x77, 0x67, 0x84, 0xb3, 0x6a, 0xa9, 0x97, 0x99, 0xa8, 0xb7, 0x66, 0x20, 0x80, 0xff,
+};
+const unsigned char test_ec_bp256r1_pub[] = {
+    0x04, 0x76, 0x8c, 0x8c, 0xae, 0x4a, 0xbc, 0xa6, 0x30, 0x6d, 0xb0, 0xed, 0x81, 0xb0, 0xc4, 0xa6,
+    0x21, 0x5c, 0x37, 0x80, 0x66, 0xec, 0x6d, 0x61, 0x6c, 0x14, 0x6e, 0x13, 0xf1, 0xc7, 0xdf, 0x80,
+    0x9b, 0x96, 0xab, 0x69, 0x11, 0xc2, 0x7d, 0x8a, 0x02, 0x33, 0x9f, 0x09, 0x26, 0x84, 0x0e, 0x55,
+    0x23, 0x6d, 0x3d, 0x1e, 0xfb, 0xe2, 0x66, 0x9d, 0x09, 0x0e, 0x4c, 0x4c, 0x66, 0x0f, 0xad, 0xa9,
+    0x1d,
+};
+
+const unsigned char test_ec_bp384r1_priv[] = {
+    0x3d, 0xd9, 0x2e, 0x75, 0x0d, 0x90, 0xd7, 0xd3, 0x9f, 0xc1, 0x88, 0x5c, 0xd8, 0xad, 0x12, 0xea,
+    0x94, 0x41, 0xf2, 0x2b, 0x93, 0x34, 0xb4, 0xd9, 0x65, 0x20, 0x2a, 0xdb, 0x14, 0x48, 0xce, 0x24,
+    0xc5, 0x80, 0x8a, 0x85, 0xdd, 0x9a, 0xfc, 0x22, 0x9a, 0xf0, 0xa3, 0x12, 0x4f, 0x75, 0x5b, 0xcb,
+};
+const unsigned char test_ec_bp384r1_pub[] = {
+    0x04, 0x71, 0x9f, 0x9d, 0x09, 0x3a, 0x62, 0x7e, 0x0d, 0x35, 0x03, 0x85, 0xc6, 0x61, 0xce, 0xbf,
+    0x00, 0xc6, 0x19, 0x23, 0x56, 0x6f, 0xe9, 0x00, 0x6a, 0x31, 0x07, 0xaf, 0x1d, 0x87, 0x1b, 0xc6,
+    0xbb, 0x68, 0x98, 0x5f, 0xd7, 0x22, 0xea, 0x32, 0xbe, 0x31, 0x6f, 0x8e, 0x78, 0x3b, 0x7c, 0xd1,
+    0x95, 0x77, 0x85, 0xf6, 0x6c, 0xfc, 0x0c, 0xb1, 0x95, 0xdd, 0x5c, 0x99, 0xa8, 0xe7, 0xab, 0xaa,
+    0x84, 0x85, 0x53, 0xa5, 0x84, 0xdf, 0xd2, 0xb4, 0x8e, 0x76, 0xd4, 0x45, 0xfe, 0x00, 0xdd, 0x8b,
+    0xe5, 0x90, 0x96, 0xd8, 0x77, 0xd4, 0x69, 0x6d, 0x23, 0xb4, 0xbc, 0x8d, 0xb1, 0x47, 0x24, 0xe6,
+    0x6a,
+};
+
+const unsigned char test_ec_bp512r1_priv[] = {
+    0x37, 0x2c, 0x97, 0x78, 0xf6, 0x9f, 0x72, 0x6c, 0xbc, 0xa3, 0xf4, 0xa2, 0x68, 0xf1, 0x6b, 0x4d,
+    0x61, 0x7d, 0x10, 0x28, 0x0d, 0x79, 0xa6, 0xa0, 0x29, 0xcd, 0x51, 0x87, 0x9f, 0xe1, 0x01, 0x29,
+    0x34, 0xdf, 0xe5, 0x39, 0x54, 0x55, 0x33, 0x7d, 0xf6, 0x90, 0x6d, 0xc7, 0xd6, 0xd2, 0xee, 0xa4,
+    0xdb, 0xb2, 0x06, 0x5c, 0x02, 0x28, 0xf7, 0x3b, 0x3e, 0xd7, 0x16, 0x48, 0x0e, 0x7d, 0x71, 0xd2,
+};
+const unsigned char test_ec_bp512r1_pub[] = {
+    0x04, 0x38, 0xb7, 0xec, 0x92, 0xb6, 0x1c, 0x5c, 0x6c, 0x7f, 0xbc, 0x28, 0xa4, 0xec, 0x75, 0x9d,
+    0x48, 0xfc, 0xd4, 0xe2, 0xe3, 0x74, 0xde, 0xfd, 0x5c, 0x49, 0x68, 0xa5, 0x4d, 0xbe, 0xf7, 0x51,
+    0x0e, 0x51, 0x78, 0x86, 0xfb, 0xfc, 0x38, 0xea, 0x39, 0xaa, 0x52, 0x93, 0x59, 0xd7, 0x0a, 0x71,
+    0x56, 0xc3, 0x5d, 0x3c, 0xba, 0xc7, 0xce, 0x77, 0x6b, 0xdb, 0x25, 0x1d, 0xd6, 0x4b, 0xce, 0x71,
+    0x23, 0x44, 0x24, 0xee, 0x70, 0x49, 0xee, 0xd0, 0x72, 0xf0, 0xdb, 0xc4, 0xd7, 0x99, 0x96, 0xe1,
+    0x75, 0xd5, 0x57, 0xe2, 0x63, 0x76, 0x3a, 0xe9, 0x70, 0x95, 0xc0, 0x81, 0xe7, 0x3e, 0x7d, 0xb2,
+    0xe3, 0x8a, 0xdc, 0x3d, 0x4c, 0x9a, 0x04, 0x87, 0xb1, 0xed, 0xe8, 0x76, 0xdc, 0x1f, 0xca, 0x61,
+    0xc9, 0x02, 0xe9, 0xa1, 0xd8, 0x72, 0x2b, 0x86, 0x12, 0x92, 0x8f, 0x18, 0xa2, 0x48, 0x45, 0x59,
+    0x1a,
+};
+
+const unsigned char test_ec_curve25519_priv[] = {
+    0x70, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45,
+    0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a, 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x6a,
+};
+const unsigned char test_ec_curve25519_pub[] = {
+    0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b, 0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a,
+    0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38, 0x1a, 0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 0x4e, 0x6a,
+};
+
+const unsigned char test_ec_curve448_priv[] = {
+    0xe4, 0xe4, 0x9f, 0x52, 0x68, 0x6f, 0x9e, 0xe3, 0xb6, 0x38, 0x52, 0x8f, 0x72, 0x1f, 0x15, 0x96,
+    0x19, 0x6f, 0xfd, 0x0a, 0x1c, 0xdd, 0xb6, 0x4c, 0x3f, 0x21, 0x6f, 0x06, 0x54, 0x18, 0x05, 0xcf,
+    0xeb, 0x1a, 0x28, 0x6d, 0xc7, 0x80, 0x18, 0x09, 0x5c, 0xdf, 0xec, 0x05, 0x0e, 0x80, 0x07, 0xb5,
+    0xf4, 0x90, 0x89, 0x62, 0xba, 0x20, 0xd6, 0xc1,
+};
+const unsigned char test_ec_curve448_pub[] = {
+    0xc0, 0xd3, 0xa5, 0xa2, 0xb4, 0x16, 0xa5, 0x73, 0xdc, 0x99, 0x09, 0xf9, 0x2f, 0x13, 0x4a, 0xc0,
+    0x13, 0x23, 0xab, 0x8f, 0x8e, 0x36, 0x80, 0x4e, 0x57, 0x85, 0x88, 0xba, 0x2d, 0x09, 0xfe, 0x7c,
+    0x3e, 0x73, 0x7f, 0x77, 0x1c, 0xa1, 0x12, 0x82, 0x5b, 0x54, 0x8a, 0x0f, 0xfd, 0xed, 0x6d, 0x6a,
+    0x2f, 0xd0, 0x9a, 0x3e, 0x77, 0xde, 0xc3, 0x0e,
+};
+
+const unsigned char test_rsa_1024_priv[] = {
+    0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xaf, 0x05, 0x7d, 0x39, 0x6e,
+    0xe8, 0x4f, 0xb7, 0x5f, 0xdb, 0xb5, 0xc2, 0xb1, 0x3c, 0x7f, 0xe5, 0xa6, 0x54, 0xaa, 0x8a, 0xa2,
+    0x47, 0x0b, 0x54, 0x1e, 0xe1, 0xfe, 0xb0, 0xb1, 0x2d, 0x25, 0xc7, 0x97, 0x11, 0x53, 0x12, 0x49,
+    0xe1, 0x12, 0x96, 0x28, 0x04, 0x2d, 0xbb, 0xb6, 0xc1, 0x20, 0xd1, 0x44, 0x35, 0x24, 0xef, 0x4c,
+    0x0e, 0x6e, 0x1d, 0x89, 0x56, 0xee, 0xb2, 0x07, 0x7a, 0xf1, 0x23, 0x49, 0xdd, 0xee, 0xe5, 0x44,
+    0x83, 0xbc, 0x06, 0xc2, 0xc6, 0x19, 0x48, 0xcd, 0x02, 0xb2, 0x02, 0xe7, 0x96, 0xae, 0xbd, 0x94,
+    0xd3, 0xa7, 0xcb, 0xf8, 0x59, 0xc2, 0xc1, 0x81, 0x9c, 0x32, 0x4c, 0xb8, 0x2b, 0x9c, 0xd3, 0x4e,
+    0xde, 0x26, 0x3a, 0x2a, 0xbf, 0xfe, 0x47, 0x33, 0xf0, 0x77, 0x86, 0x9e, 0x86, 0x60, 0xf7, 0xd6,
+    0x83, 0x4d, 0xa5, 0x3d, 0x69, 0x0e, 0xf7, 0x98, 0x5f, 0x6b, 0xc3, 0x02, 0x03, 0x01, 0x00, 0x01,
+    0x02, 0x81, 0x81, 0x00, 0x87, 0x4b, 0xf0, 0xff, 0xc2, 0xf2, 0xa7, 0x1d, 0x14, 0x67, 0x1d, 0xdd,
+    0x01, 0x71, 0xc9, 0x54, 0xd7, 0xfd, 0xbf, 0x50, 0x28, 0x1e, 0x4f, 0x6d, 0x99, 0xea, 0x0e, 0x1e,
+    0xbc, 0xf8, 0x2f, 0xaa, 0x58, 0xe7, 0xb5, 0x95, 0xff, 0xb2, 0x93, 0xd1, 0xab, 0xe1, 0x7f, 0x11,
+    0x0b, 0x37, 0xc4, 0x8c, 0xc0, 0xf3, 0x6c, 0x37, 0xe8, 0x4d, 0x87, 0x66, 0x21, 0xd3, 0x27, 0xf6,
+    0x4b, 0xbe, 0x08, 0x45, 0x7d, 0x3e, 0xc4, 0x09, 0x8b, 0xa2, 0xfa, 0x0a, 0x31, 0x9f, 0xba, 0x41,
+    0x1c, 0x28, 0x41, 0xed, 0x7b, 0xe8, 0x31, 0x96, 0xa8, 0xcd, 0xf9, 0xda, 0xa5, 0xd0, 0x06, 0x94,
+    0xbc, 0x33, 0x5f, 0xc4, 0xc3, 0x22, 0x17, 0xfe, 0x04, 0x88, 0xbc, 0xe9, 0xcb, 0x72, 0x02, 0xe5,
+    0x94, 0x68, 0xb1, 0xea, 0xd1, 0x19, 0x00, 0x04, 0x77, 0xdb, 0x2c, 0xa7, 0x97, 0xfa, 0xc1, 0x9e,
+    0xda, 0x3f, 0x58, 0xc1, 0x02, 0x41, 0x00, 0xe2, 0xab, 0x76, 0x08, 0x41, 0xbb, 0x9d, 0x30, 0xa8,
+    0x1d, 0x22, 0x2d, 0xe1, 0xeb, 0x73, 0x81, 0xd8, 0x22, 0x14, 0x40, 0x7f, 0x1b, 0x97, 0x5c, 0xbb,
+    0xfe, 0x4e, 0x1a, 0x94, 0x67, 0xfd, 0x98, 0xad, 0xbd, 0x78, 0xf6, 0x07, 0x83, 0x6c, 0xa5, 0xbe,
+    0x19, 0x28, 0xb9, 0xd1, 0x60, 0xd9, 0x7f, 0xd4, 0x5c, 0x12, 0xd6, 0xb5, 0x2e, 0x2c, 0x98, 0x71,
+    0xa1, 0x74, 0xc6, 0x6b, 0x48, 0x81, 0x13, 0x02, 0x41, 0x00, 0xc5, 0xab, 0x27, 0x60, 0x21, 0x59,
+    0xae, 0x7d, 0x6f, 0x20, 0xc3, 0xc2, 0xee, 0x85, 0x1e, 0x46, 0xdc, 0x11, 0x2e, 0x68, 0x9e, 0x28,
+    0xd5, 0xfc, 0xbb, 0xf9, 0x90, 0xa9, 0x9e, 0xf8, 0xa9, 0x0b, 0x8b, 0xb4, 0x4f, 0xd3, 0x64, 0x67,
+    0xe7, 0xfc, 0x17, 0x89, 0xce, 0xb6, 0x63, 0xab, 0xda, 0x33, 0x86, 0x52, 0xc3, 0xc7, 0x3f, 0x11,
+    0x17, 0x74, 0x90, 0x2e, 0x84, 0x05, 0x65, 0x92, 0x70, 0x91, 0x02, 0x41, 0x00, 0xb6, 0xcd, 0xbd,
+    0x35, 0x4f, 0x7d, 0xf5, 0x79, 0xa6, 0x3b, 0x48, 0xb3, 0x64, 0x3e, 0x35, 0x3b, 0x84, 0x89, 0x87,
+    0x77, 0xb4, 0x8b, 0x15, 0xf9, 0x4e, 0x0b, 0xfc, 0x05, 0x67, 0xa6, 0xae, 0x59, 0x11, 0xd5, 0x7a,
+    0xd6, 0x40, 0x9c, 0xf7, 0x64, 0x7b, 0xf9, 0x62, 0x64, 0xe9, 0xbd, 0x87, 0xeb, 0x95, 0xe2, 0x63,
+    0xb7, 0x11, 0x0b, 0x9a, 0x1f, 0x9f, 0x94, 0xac, 0xce, 0xd0, 0xfa, 0xfa, 0x4d, 0x02, 0x40, 0x71,
+    0x19, 0x5e, 0xec, 0x37, 0xe8, 0xd2, 0x57, 0xde, 0xcf, 0xc6, 0x72, 0xb0, 0x7a, 0xe6, 0x39, 0xf1,
+    0x0c, 0xbb, 0x9b, 0x0c, 0x73, 0x9d, 0x0c, 0x80, 0x99, 0x68, 0xd6, 0x44, 0xa9, 0x4e, 0x3f, 0xd6,
+    0xed, 0x92, 0x87, 0x07, 0x7a, 0x14, 0x58, 0x3f, 0x37, 0x90, 0x58, 0xf7, 0x6a, 0x8a, 0xec, 0xd4,
+    0x3c, 0x62, 0xdc, 0x8c, 0x0f, 0x41, 0x76, 0x66, 0x50, 0xd7, 0x25, 0x27, 0x5a, 0xc4, 0xa1, 0x02,
+    0x41, 0x00, 0xbb, 0x32, 0xd1, 0x33, 0xed, 0xc2, 0xe0, 0x48, 0xd4, 0x63, 0x38, 0x8b, 0x7b, 0xe9,
+    0xcb, 0x4b, 0xe2, 0x9f, 0x4b, 0x62, 0x50, 0xbe, 0x60, 0x3e, 0x70, 0xe3, 0x64, 0x75, 0x01, 0xc9,
+    0x7d, 0xdd, 0xe2, 0x0a, 0x4e, 0x71, 0xbe, 0x95, 0xfd, 0x5e, 0x71, 0x78, 0x4e, 0x25, 0xac, 0xa4,
+    0xba, 0xf2, 0x5b, 0xe5, 0x73, 0x8a, 0xae, 0x59, 0xbb, 0xfe, 0x1c, 0x99, 0x77, 0x81, 0x44, 0x7a,
+    0x2b, 0x24,
+};
+const unsigned char test_rsa_1024_pub[] = {
+    0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xaf, 0x05, 0x7d, 0x39, 0x6e, 0xe8, 0x4f, 0xb7, 0x5f,
+    0xdb, 0xb5, 0xc2, 0xb1, 0x3c, 0x7f, 0xe5, 0xa6, 0x54, 0xaa, 0x8a, 0xa2, 0x47, 0x0b, 0x54, 0x1e,
+    0xe1, 0xfe, 0xb0, 0xb1, 0x2d, 0x25, 0xc7, 0x97, 0x11, 0x53, 0x12, 0x49, 0xe1, 0x12, 0x96, 0x28,
+    0x04, 0x2d, 0xbb, 0xb6, 0xc1, 0x20, 0xd1, 0x44, 0x35, 0x24, 0xef, 0x4c, 0x0e, 0x6e, 0x1d, 0x89,
+    0x56, 0xee, 0xb2, 0x07, 0x7a, 0xf1, 0x23, 0x49, 0xdd, 0xee, 0xe5, 0x44, 0x83, 0xbc, 0x06, 0xc2,
+    0xc6, 0x19, 0x48, 0xcd, 0x02, 0xb2, 0x02, 0xe7, 0x96, 0xae, 0xbd, 0x94, 0xd3, 0xa7, 0xcb, 0xf8,
+    0x59, 0xc2, 0xc1, 0x81, 0x9c, 0x32, 0x4c, 0xb8, 0x2b, 0x9c, 0xd3, 0x4e, 0xde, 0x26, 0x3a, 0x2a,
+    0xbf, 0xfe, 0x47, 0x33, 0xf0, 0x77, 0x86, 0x9e, 0x86, 0x60, 0xf7, 0xd6, 0x83, 0x4d, 0xa5, 0x3d,
+    0x69, 0x0e, 0xf7, 0x98, 0x5f, 0x6b, 0xc3, 0x02, 0x03, 0x01, 0x00, 0x01,
+};
+
+const unsigned char test_rsa_1026_priv[] = {
+    0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x02, 0xd0, 0x96, 0x61, 0xfc, 0x74,
+    0x22, 0x4b, 0xa7, 0xbe, 0x79, 0x07, 0xab, 0xef, 0x4f, 0x5e, 0x8b, 0xcc, 0x26, 0x4a, 0x80, 0x2c,
+    0x97, 0x8f, 0x7e, 0xaa, 0x58, 0x55, 0xad, 0xa0, 0x54, 0x36, 0xd7, 0x5d, 0xb7, 0x68, 0xd2, 0x0f,
+    0x68, 0x59, 0x5d, 0xbc, 0xc3, 0xd7, 0x25, 0xb1, 0x38, 0xe8, 0x0b, 0x24, 0x7e, 0x44, 0xa4, 0x16,
+    0x3a, 0x05, 0x42, 0xfa, 0xb6, 0x12, 0xac, 0xbb, 0xde, 0x45, 0xf2, 0xe9, 0x38, 0x94, 0xaa, 0x25,
+    0x3b, 0xdd, 0xef, 0x6a, 0x7b, 0xec, 0xdc, 0x9c, 0xc2, 0x9a, 0x99, 0xba, 0xcf, 0x48, 0xdc, 0x6e,
+    0x38, 0xdb, 0x7a, 0x33, 0xe9, 0xac, 0x92, 0x4c, 0x52, 0x0f, 0xc6, 0xbe, 0x7d, 0x6e, 0x56, 0x46,
+    0xc1, 0xd6, 0x7f, 0xb8, 0xb2, 0xb9, 0x7a, 0xc6, 0x0b, 0xee, 0xcc, 0x3b, 0xb8, 0xe7, 0x5b, 0xed,
+    0x83, 0x15, 0xaa, 0x3f, 0xe4, 0x6f, 0x74, 0x8a, 0x66, 0xd6, 0xef, 0x02, 0x03, 0x01, 0x00, 0x01,
+    0x02, 0x81, 0x80, 0x6a, 0x4a, 0x34, 0x6b, 0xeb, 0xa9, 0x7f, 0x65, 0x5f, 0xe8, 0x34, 0x64, 0x7d,
+    0x29, 0x44, 0xf5, 0xf4, 0x08, 0x15, 0xe7, 0x30, 0x2c, 0xaf, 0x02, 0xed, 0x17, 0x98, 0x93, 0xc2,
+    0xd9, 0x89, 0x39, 0x5d, 0x5e, 0x87, 0x7c, 0xac, 0xbf, 0x24, 0xa7, 0x7a, 0x07, 0x9d, 0x3d, 0xb7,
+    0x15, 0x80, 0xcc, 0xdb, 0xf6, 0x30, 0x23, 0xd0, 0x0f, 0x80, 0xe5, 0x2f, 0x5c, 0x1a, 0x07, 0x16,
+    0xb3, 0x23, 0xb7, 0xbf, 0xcb, 0xdc, 0x8a, 0x17, 0x81, 0xc4, 0x4c, 0x41, 0x53, 0xe3, 0xda, 0x22,
+    0x8d, 0x17, 0xb2, 0xdc, 0x78, 0xeb, 0x1f, 0x44, 0xcf, 0xf6, 0x0f, 0xe1, 0x15, 0x08, 0x08, 0xa6,
+    0xe3, 0x8b, 0xa2, 0x47, 0x0a, 0xee, 0x2e, 0x94, 0x8a, 0x68, 0x98, 0xdd, 0xad, 0xea, 0x56, 0xd9,
+    0x47, 0x09, 0x27, 0xac, 0xa8, 0xd9, 0x4a, 0x03, 0x38, 0xc1, 0x1a, 0x8e, 0x95, 0x71, 0x5b, 0x5f,
+    0x94, 0xe0, 0x11, 0x02, 0x41, 0x01, 0xf5, 0x41, 0x85, 0x34, 0xc3, 0x62, 0x36, 0xfc, 0x9f, 0xd3,
+    0x89, 0x34, 0xd7, 0xc0, 0x6d, 0xfe, 0xd3, 0x82, 0x91, 0x51, 0xcc, 0xab, 0x56, 0xb6, 0x33, 0x0c,
+    0x64, 0x1f, 0x77, 0x96, 0xa7, 0x19, 0x24, 0xcf, 0x81, 0x19, 0xca, 0x26, 0xe1, 0x86, 0xec, 0xd3,
+    0x06, 0x8d, 0x66, 0x07, 0xa0, 0x52, 0x60, 0xdb, 0x48, 0x57, 0x65, 0x19, 0x80, 0x43, 0x68, 0x91,
+    0xad, 0xde, 0x9e, 0xb9, 0x2a, 0xb7, 0x02, 0x41, 0x01, 0x70, 0x04, 0x2f, 0xbd, 0xba, 0xba, 0x1e,
+    0x10, 0x2b, 0x7f, 0x7f, 0x1d, 0xc9, 0xd9, 0x40, 0xcf, 0xdc, 0xd8, 0x5d, 0xd0, 0xea, 0x65, 0xf5,
+    0x43, 0xc6, 0x43, 0x2e, 0x9c, 0x54, 0x80, 0x72, 0x4b, 0xb4, 0x9b, 0x1e, 0x5f, 0x80, 0xca, 0x2b,
+    0x9f, 0x84, 0xcd, 0x66, 0x44, 0xbf, 0xb2, 0xe3, 0xd0, 0x96, 0x80, 0x90, 0xb8, 0x9f, 0x53, 0x4d,
+    0xc2, 0x95, 0x1e, 0x60, 0x6d, 0xb9, 0x09, 0xdd, 0x89, 0x02, 0x41, 0x01, 0x4b, 0x6c, 0x1a, 0xeb,
+    0x1c, 0x14, 0xa0, 0x4e, 0xc0, 0x4e, 0x59, 0x75, 0xfb, 0x01, 0x5c, 0xb9, 0x14, 0x98, 0x4c, 0x05,
+    0x4d, 0xd2, 0x2b, 0xef, 0x24, 0x29, 0x99, 0x39, 0xc5, 0x14, 0x73, 0x3f, 0x88, 0xbb, 0x3a, 0x9d,
+    0x16, 0xb0, 0x46, 0x85, 0xb3, 0xa8, 0x83, 0xb8, 0x92, 0x31, 0x90, 0xab, 0x67, 0x27, 0x15, 0xd9,
+    0xd3, 0x1a, 0xdd, 0x57, 0xb4, 0x98, 0x3d, 0xe1, 0xe8, 0x08, 0x7e, 0x59, 0x02, 0x41, 0x01, 0x17,
+    0xbf, 0x76, 0xf3, 0x08, 0xb0, 0x56, 0x0e, 0x00, 0xa2, 0xc8, 0x64, 0x42, 0x7d, 0xcd, 0x50, 0xb5,
+    0x16, 0x1c, 0x2a, 0xa5, 0x23, 0xa0, 0x0f, 0x46, 0xf4, 0xe6, 0xc7, 0x9b, 0x4c, 0x90, 0x95, 0x8f,
+    0xd2, 0xa2, 0x82, 0x02, 0x8a, 0xac, 0x22, 0x74, 0x77, 0x16, 0x98, 0x88, 0x08, 0x5a, 0x38, 0xc3,
+    0x4f, 0x33, 0xb3, 0xc4, 0x19, 0x34, 0xf1, 0x07, 0x1d, 0xb2, 0x3b, 0x75, 0xff, 0x53, 0xd1, 0x02,
+    0x41, 0x01, 0x20, 0xa4, 0x28, 0xb4, 0xe0, 0xc4, 0xa6, 0xf2, 0x02, 0x92, 0x0f, 0xd4, 0x9c, 0xc9,
+    0x88, 0x6e, 0x6b, 0x67, 0x19, 0xd4, 0x0a, 0x3a, 0xd0, 0x60, 0x4f, 0x5d, 0x5e, 0xfd, 0x5e, 0xf6,
+    0x97, 0x3a, 0x57, 0x3a, 0xb3, 0x24, 0xf3, 0x8e, 0xcb, 0x8e, 0x66, 0x9a, 0x69, 0x34, 0x15, 0x97,
+    0x08, 0x1e, 0x24, 0x0b, 0x6a, 0xe4, 0xe2, 0x71, 0x48, 0x87, 0xdd, 0x78, 0xda, 0xda, 0xeb, 0x0b,
+    0x92, 0x16,
+};
+const unsigned char test_rsa_1026_pub[] = {
+    0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x02, 0xd0, 0x96, 0x61, 0xfc, 0x74, 0x22, 0x4b, 0xa7, 0xbe,
+    0x79, 0x07, 0xab, 0xef, 0x4f, 0x5e, 0x8b, 0xcc, 0x26, 0x4a, 0x80, 0x2c, 0x97, 0x8f, 0x7e, 0xaa,
+    0x58, 0x55, 0xad, 0xa0, 0x54, 0x36, 0xd7, 0x5d, 0xb7, 0x68, 0xd2, 0x0f, 0x68, 0x59, 0x5d, 0xbc,
+    0xc3, 0xd7, 0x25, 0xb1, 0x38, 0xe8, 0x0b, 0x24, 0x7e, 0x44, 0xa4, 0x16, 0x3a, 0x05, 0x42, 0xfa,
+    0xb6, 0x12, 0xac, 0xbb, 0xde, 0x45, 0xf2, 0xe9, 0x38, 0x94, 0xaa, 0x25, 0x3b, 0xdd, 0xef, 0x6a,
+    0x7b, 0xec, 0xdc, 0x9c, 0xc2, 0x9a, 0x99, 0xba, 0xcf, 0x48, 0xdc, 0x6e, 0x38, 0xdb, 0x7a, 0x33,
+    0xe9, 0xac, 0x92, 0x4c, 0x52, 0x0f, 0xc6, 0xbe, 0x7d, 0x6e, 0x56, 0x46, 0xc1, 0xd6, 0x7f, 0xb8,
+    0xb2, 0xb9, 0x7a, 0xc6, 0x0b, 0xee, 0xcc, 0x3b, 0xb8, 0xe7, 0x5b, 0xed, 0x83, 0x15, 0xaa, 0x3f,
+    0xe4, 0x6f, 0x74, 0x8a, 0x66, 0xd6, 0xef, 0x02, 0x03, 0x01, 0x00, 0x01,
+};
+
+const unsigned char test_rsa_1028_priv[] = {
+    0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x0e, 0x62, 0xa7, 0x6f, 0x0e, 0x0b,
+    0x59, 0x68, 0x3a, 0x7e, 0xbf, 0x7c, 0xbf, 0xd3, 0x7b, 0x1d, 0x17, 0x81, 0xd8, 0xf1, 0xb9, 0x00,
+    0x60, 0x4b, 0x50, 0x7f, 0x0f, 0x04, 0xc7, 0x2a, 0x3d, 0x34, 0x0d, 0x06, 0x7b, 0xcd, 0x53, 0xbe,
+    0xa3, 0xca, 0xff, 0x4e, 0x4a, 0xe6, 0x94, 0xf0, 0xb6, 0xd8, 0xf5, 0x91, 0xa4, 0x16, 0x7f, 0xbf,
+    0x7f, 0x37, 0x2a, 0xb5, 0x7e, 0x83, 0xa6, 0x9a, 0x3f, 0x26, 0xf4, 0x47, 0xbc, 0xf5, 0x82, 0xbc,
+    0x96, 0x21, 0xa3, 0x0a, 0x3b, 0x44, 0xd6, 0xb4, 0x3e, 0x98, 0x6d, 0x1a, 0x86, 0x7b, 0x07, 0x48,
+    0x9e, 0x4f, 0x9b, 0xfc, 0xad, 0xaa, 0x82, 0xa2, 0x78, 0x2d, 0xc2, 0x72, 0x9a, 0x63, 0x1f, 0xb1,
+    0xfb, 0x9f, 0xfb, 0x79, 0x4b, 0x4e, 0x53, 0xc7, 0x62, 0x39, 0xe0, 0x4d, 0x4a, 0x8f, 0x80, 0x35,
+    0x25, 0x88, 0xdb, 0x29, 0x46, 0x2d, 0xde, 0x18, 0x23, 0x7c, 0xf5, 0x02, 0x03, 0x01, 0x00, 0x01,
+    0x02, 0x81, 0x81, 0x01, 0xcf, 0xa0, 0x42, 0x2e, 0x3b, 0xb6, 0x0c, 0x15, 0xef, 0x2e, 0x96, 0xdb,
+    0x44, 0x99, 0xe7, 0x89, 0xf5, 0xd6, 0x34, 0xea, 0x64, 0x56, 0x7b, 0x2c, 0xdd, 0x6e, 0x2b, 0xdd,
+    0x12, 0x1f, 0x85, 0xed, 0xcc, 0xde, 0xe9, 0xb4, 0xed, 0x17, 0x8c, 0x5f, 0x33, 0x81, 0x61, 0x01,
+    0xa7, 0xc3, 0x71, 0x51, 0x8b, 0x3e, 0x23, 0xf9, 0xfd, 0xc7, 0x1b, 0x90, 0x24, 0x2c, 0xd3, 0x10,
+    0xb6, 0xb3, 0x14, 0x28, 0xb0, 0xb6, 0x4e, 0xb9, 0x59, 0x6b, 0xe0, 0xcc, 0x04, 0x4c, 0xc8, 0x50,
+    0x48, 0x98, 0x2f, 0x90, 0xb7, 0x06, 0xe6, 0x6c, 0xcd, 0xd3, 0x9a, 0xd5, 0xa1, 0xa7, 0xb6, 0x4c,
+    0xf0, 0x34, 0xea, 0xc0, 0xc3, 0x5d, 0x7a, 0xce, 0x93, 0xf2, 0xbc, 0xd3, 0xce, 0x24, 0x3b, 0xd8,
+    0xf8, 0x3b, 0x46, 0xf5, 0x09, 0xca, 0x2f, 0x80, 0x50, 0x63, 0x00, 0x2a, 0xf2, 0xbb, 0x2d, 0x88,
+    0xb6, 0xee, 0x36, 0xa9, 0x02, 0x41, 0x03, 0xf0, 0x88, 0x6d, 0x29, 0x77, 0x52, 0x6f, 0x3f, 0x3f,
+    0x6a, 0x07, 0x56, 0x00, 0x23, 0x2c, 0xe3, 0x00, 0x85, 0x17, 0x27, 0x6d, 0xd3, 0x72, 0x1d, 0xee,
+    0x08, 0xfd, 0x6c, 0x99, 0x9f, 0xc9, 0x76, 0xb9, 0xe8, 0xdd, 0x2b, 0xc1, 0x43, 0x38, 0x5f, 0xa4,
+    0xb4, 0x87, 0x35, 0xce, 0x81, 0xc6, 0x6b, 0x50, 0x1d, 0x71, 0x29, 0xee, 0x78, 0x60, 0xcf, 0xbe,
+    0xf2, 0x3b, 0x5d, 0xa9, 0x1e, 0x6c, 0x2d, 0x02, 0x41, 0x03, 0xa6, 0xc8, 0x73, 0x4a, 0xac, 0xe5,
+    0x9d, 0x5f, 0x38, 0x6f, 0x97, 0xde, 0x45, 0x0f, 0x8a, 0x12, 0xd6, 0x3a, 0xe6, 0xac, 0x15, 0xd3,
+    0x36, 0xe0, 0x10, 0xc9, 0xfc, 0xf0, 0x3a, 0x32, 0xf0, 0x61, 0x18, 0x81, 0xac, 0x6c, 0xd8, 0xb3,
+    0xf9, 0x89, 0x92, 0x5c, 0x0f, 0x02, 0x5a, 0xf2, 0x6c, 0xf2, 0x6a, 0xeb, 0xd7, 0xd9, 0xb0, 0x4e,
+    0xb5, 0x03, 0x04, 0x8d, 0xca, 0x2f, 0x50, 0x3c, 0x28, 0xe9, 0x02, 0x41, 0x01, 0x9b, 0x30, 0x04,
+    0x51, 0xc3, 0xb4, 0x78, 0x66, 0xf1, 0x13, 0xe9, 0xa9, 0xc6, 0xa4, 0x90, 0xc8, 0x7c, 0x8d, 0xc6,
+    0xc2, 0xec, 0xa4, 0x29, 0x02, 0xca, 0xea, 0x1f, 0x69, 0x07, 0xb9, 0x7e, 0x0a, 0x4a, 0x02, 0x07,
+    0x2a, 0xaf, 0xc1, 0x18, 0x5a, 0xe6, 0x6c, 0x34, 0x34, 0x5b, 0xdd, 0xcd, 0x68, 0x33, 0x61, 0xcd,
+    0xa1, 0xaa, 0xf8, 0xa9, 0x80, 0x09, 0xf9, 0xf8, 0xfa, 0x56, 0xd9, 0x70, 0x81, 0x02, 0x40, 0x1b,
+    0xcc, 0xa8, 0x49, 0x17, 0x3d, 0x38, 0xe1, 0xe5, 0x0e, 0xc4, 0x88, 0x72, 0xab, 0x54, 0xa2, 0xdc,
+    0xc6, 0x21, 0xa8, 0x0a, 0x7a, 0x1e, 0x8e, 0xa9, 0x51, 0x28, 0x79, 0x88, 0x71, 0x8d, 0x5e, 0x85,
+    0xd9, 0x0d, 0x64, 0xab, 0x49, 0x26, 0xe9, 0xa5, 0x75, 0xa1, 0x68, 0xa3, 0x85, 0xc4, 0x21, 0xad,
+    0x76, 0x58, 0x13, 0xfc, 0x3f, 0x4a, 0xf8, 0xcd, 0x00, 0xde, 0x7b, 0x6b, 0xba, 0x6e, 0x49, 0x02,
+    0x41, 0x03, 0x6d, 0xcf, 0x69, 0xf6, 0xe5, 0x48, 0xc8, 0xac, 0xfb, 0x53, 0x6f, 0xb6, 0xcd, 0x18,
+    0x6f, 0x8b, 0x8f, 0x20, 0xd3, 0x13, 0x36, 0x1d, 0x04, 0x47, 0xc1, 0xb5, 0xe3, 0x80, 0xf4, 0x11,
+    0x3e, 0x57, 0x8b, 0x31, 0xe8, 0x67, 0xdd, 0xa4, 0x7d, 0x44, 0xad, 0x37, 0x61, 0xe7, 0x93, 0xf7,
+    0x25, 0x03, 0x1b, 0x8d, 0x37, 0x9f, 0x38, 0x9d, 0xe2, 0x77, 0xa9, 0xa0, 0x13, 0x76, 0x51, 0xdf,
+    0x54, 0x8a,
+};
+const unsigned char test_rsa_1028_pub[] = {
+    0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x0e, 0x62, 0xa7, 0x6f, 0x0e, 0x0b, 0x59, 0x68, 0x3a, 0x7e,
+    0xbf, 0x7c, 0xbf, 0xd3, 0x7b, 0x1d, 0x17, 0x81, 0xd8, 0xf1, 0xb9, 0x00, 0x60, 0x4b, 0x50, 0x7f,
+    0x0f, 0x04, 0xc7, 0x2a, 0x3d, 0x34, 0x0d, 0x06, 0x7b, 0xcd, 0x53, 0xbe, 0xa3, 0xca, 0xff, 0x4e,
+    0x4a, 0xe6, 0x94, 0xf0, 0xb6, 0xd8, 0xf5, 0x91, 0xa4, 0x16, 0x7f, 0xbf, 0x7f, 0x37, 0x2a, 0xb5,
+    0x7e, 0x83, 0xa6, 0x9a, 0x3f, 0x26, 0xf4, 0x47, 0xbc, 0xf5, 0x82, 0xbc, 0x96, 0x21, 0xa3, 0x0a,
+    0x3b, 0x44, 0xd6, 0xb4, 0x3e, 0x98, 0x6d, 0x1a, 0x86, 0x7b, 0x07, 0x48, 0x9e, 0x4f, 0x9b, 0xfc,
+    0xad, 0xaa, 0x82, 0xa2, 0x78, 0x2d, 0xc2, 0x72, 0x9a, 0x63, 0x1f, 0xb1, 0xfb, 0x9f, 0xfb, 0x79,
+    0x4b, 0x4e, 0x53, 0xc7, 0x62, 0x39, 0xe0, 0x4d, 0x4a, 0x8f, 0x80, 0x35, 0x25, 0x88, 0xdb, 0x29,
+    0x46, 0x2d, 0xde, 0x18, 0x23, 0x7c, 0xf5, 0x02, 0x03, 0x01, 0x00, 0x01,
+};
+
+const unsigned char test_rsa_1030_priv[] = {
+    0x30, 0x82, 0x02, 0x5f, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x2b, 0x7c, 0xd1, 0x97, 0xf5, 0x79,
+    0x6d, 0x1f, 0x8e, 0x57, 0x6b, 0x2b, 0x37, 0x72, 0x3f, 0xd9, 0x21, 0x08, 0x14, 0xef, 0x1c, 0x19,
+    0x95, 0xf9, 0x89, 0x9d, 0x50, 0x05, 0x8f, 0x37, 0x9d, 0x23, 0x9c, 0x66, 0x87, 0x8e, 0x92, 0x2f,
+    0x34, 0xc6, 0xae, 0x36, 0x72, 0xc8, 0x59, 0x8f, 0xcd, 0x5d, 0x47, 0xb7, 0x64, 0xd2, 0xec, 0x15,
+    0x6e, 0x13, 0x4d, 0x03, 0xcf, 0x6a, 0x94, 0xd3, 0x8d, 0x2e, 0xa8, 0xbc, 0x76, 0xdb, 0xbc, 0x60,
+    0xc4, 0xb9, 0x74, 0x21, 0x90, 0x90, 0xea, 0xf2, 0x87, 0x49, 0x7d, 0x7d, 0xcf, 0x7f, 0x11, 0x9c,
+    0xfa, 0x86, 0x74, 0x96, 0xf7, 0xe9, 0x1c, 0x12, 0xb5, 0xd5, 0x52, 0xe1, 0xd1, 0x46, 0x1a, 0x80,
+    0xdb, 0xe9, 0xa5, 0x9d, 0xb3, 0xb0, 0x16, 0xc6, 0xc0, 0x14, 0x1c, 0x3b, 0x2a, 0x0e, 0x22, 0x60,
+    0x89, 0xb8, 0x55, 0xcb, 0x88, 0xef, 0x65, 0x64, 0x08, 0xbd, 0x89, 0x02, 0x03, 0x01, 0x00, 0x01,
+    0x02, 0x81, 0x81, 0x02, 0x10, 0xd5, 0xff, 0x53, 0x1c, 0xac, 0xb2, 0x2f, 0x8c, 0xf7, 0xdd, 0x1f,
+    0xd9, 0xfb, 0x03, 0x76, 0xf3, 0x64, 0x7f, 0x2e, 0x9a, 0xb3, 0xdf, 0x9c, 0x89, 0xb9, 0xad, 0x3c,
+    0x98, 0xe6, 0x8b, 0x89, 0xad, 0xeb, 0x29, 0x90, 0x1d, 0xd2, 0xf2, 0xcf, 0x2a, 0xc1, 0xf8, 0x17,
+    0x72, 0x62, 0x78, 0x83, 0x0e, 0xc8, 0xa8, 0xd0, 0xfd, 0xd1, 0x9d, 0x49, 0x6e, 0xc6, 0xbc, 0x68,
+    0x36, 0x71, 0x17, 0x47, 0x86, 0xb7, 0xd6, 0xa8, 0xe8, 0x22, 0xfa, 0x71, 0xd6, 0x5a, 0xd3, 0x5a,
+    0xbb, 0xdf, 0x0e, 0x6e, 0x55, 0xff, 0x2c, 0x18, 0x21, 0xb6, 0x2b, 0xc6, 0x30, 0x19, 0x21, 0x60,
+    0xe5, 0xc9, 0xb3, 0xdc, 0xaf, 0xc6, 0x5a, 0xe6, 0xb2, 0xa0, 0x88, 0xfb, 0xc5, 0x59, 0x1d, 0xa5,
+    0x8a, 0x45, 0xdd, 0x7a, 0x30, 0x96, 0x0f, 0x7d, 0x3d, 0xef, 0x75, 0xb8, 0x0c, 0xdf, 0x73, 0x24,
+    0x73, 0x60, 0xe8, 0xfb, 0x02, 0x41, 0x07, 0x2e, 0x37, 0x1a, 0x3b, 0xa8, 0x61, 0xe7, 0x8e, 0x3e,
+    0xb9, 0x31, 0x30, 0x65, 0xfa, 0xab, 0x0a, 0x97, 0x21, 0x6e, 0x95, 0x44, 0xbf, 0xc2, 0xd5, 0xb4,
+    0x03, 0x84, 0x4b, 0x43, 0x27, 0x37, 0x05, 0x75, 0x5a, 0x85, 0xaa, 0x0b, 0xaf, 0x71, 0x14, 0x77,
+    0x0c, 0xfe, 0xca, 0x20, 0xbc, 0xa1, 0x7a, 0xc1, 0x9b, 0xc4, 0xcb, 0xba, 0x10, 0x6a, 0x33, 0xb3,
+    0xdd, 0xdc, 0xa0, 0xfb, 0x53, 0x5f, 0x33, 0x02, 0x41, 0x06, 0x0e, 0x6a, 0xf3, 0x7a, 0xb4, 0xea,
+    0x11, 0xf5, 0x2b, 0x93, 0x44, 0xe7, 0x16, 0x0e, 0xb2, 0xa5, 0x3f, 0x10, 0x75, 0xe1, 0x22, 0x9a,
+    0x7f, 0x10, 0xa3, 0x01, 0xde, 0x33, 0x59, 0xf5, 0x3e, 0x98, 0x1e, 0xa0, 0xe1, 0x7d, 0xf0, 0xfb,
+    0x38, 0x0f, 0x08, 0x9e, 0x5c, 0x37, 0xdd, 0x40, 0xda, 0xa2, 0x9e, 0xef, 0xd2, 0x05, 0xf5, 0xc8,
+    0x7b, 0x38, 0xf8, 0xfe, 0xf6, 0x36, 0xb5, 0x7b, 0xa0, 0x53, 0x02, 0x41, 0x02, 0x3a, 0x5d, 0xd0,
+    0x9e, 0xf8, 0x35, 0x40, 0xb3, 0x0b, 0x55, 0x4d, 0x24, 0xf6, 0x4f, 0x9c, 0x28, 0xd2, 0x12, 0x06,
+    0x8c, 0xfc, 0x62, 0xff, 0xe2, 0x6d, 0x53, 0xb6, 0x05, 0xe0, 0x55, 0x57, 0xa6, 0x32, 0xee, 0x9e,
+    0x90, 0xcf, 0xc5, 0x65, 0x31, 0xf3, 0x6a, 0xad, 0xd8, 0x2b, 0xe6, 0x3b, 0xb8, 0xaa, 0x40, 0x5a,
+    0x04, 0xd8, 0xbb, 0xe5, 0x28, 0x1b, 0xc4, 0x58, 0x83, 0xfe, 0xd7, 0xb4, 0xaf, 0x02, 0x41, 0x04,
+    0x1d, 0xe6, 0xdb, 0xad, 0x4c, 0xaf, 0x54, 0x17, 0xa9, 0x50, 0x49, 0x65, 0x20, 0x1c, 0x4b, 0x99,
+    0x82, 0x7d, 0xe8, 0xf3, 0x69, 0xf7, 0x45, 0x6a, 0x84, 0xb3, 0xef, 0x5c, 0x4e, 0xc9, 0x23, 0x8c,
+    0x7a, 0x3d, 0x78, 0x2a, 0x89, 0x15, 0xeb, 0xec, 0x64, 0x3a, 0x69, 0x8b, 0x5b, 0xee, 0x0a, 0xf0,
+    0xc2, 0x43, 0x59, 0x2b, 0xce, 0x00, 0x42, 0xaa, 0xde, 0xaf, 0x49, 0xa4, 0xb4, 0xc6, 0xdd, 0x9b,
+    0x02, 0x41, 0x05, 0xd3, 0x2d, 0xee, 0x95, 0x2b, 0x50, 0x3b, 0x53, 0x6f, 0xce, 0xcf, 0x19, 0xec,
+    0x08, 0x23, 0x6a, 0x9c, 0xd9, 0x45, 0xc4, 0x95, 0x51, 0xbf, 0x99, 0xf1, 0x5b, 0x67, 0x4f, 0xc2,
+    0x1a, 0xa1, 0x99, 0xf4, 0xc4, 0x21, 0x1f, 0x0f, 0x00, 0x07, 0xc4, 0x17, 0xc1, 0xfb, 0x41, 0x55,
+    0x32, 0x6a, 0x21, 0x42, 0xfc, 0xa4, 0x54, 0xbb, 0xd3, 0x8d, 0x6d, 0xbc, 0x6c, 0xaa, 0x7a, 0xc3,
+    0x35, 0xa1, 0x7c,
+};
+const unsigned char test_rsa_1030_pub[] = {
+    0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x2b, 0x7c, 0xd1, 0x97, 0xf5, 0x79, 0x6d, 0x1f, 0x8e, 0x57,
+    0x6b, 0x2b, 0x37, 0x72, 0x3f, 0xd9, 0x21, 0x08, 0x14, 0xef, 0x1c, 0x19, 0x95, 0xf9, 0x89, 0x9d,
+    0x50, 0x05, 0x8f, 0x37, 0x9d, 0x23, 0x9c, 0x66, 0x87, 0x8e, 0x92, 0x2f, 0x34, 0xc6, 0xae, 0x36,
+    0x72, 0xc8, 0x59, 0x8f, 0xcd, 0x5d, 0x47, 0xb7, 0x64, 0xd2, 0xec, 0x15, 0x6e, 0x13, 0x4d, 0x03,
+    0xcf, 0x6a, 0x94, 0xd3, 0x8d, 0x2e, 0xa8, 0xbc, 0x76, 0xdb, 0xbc, 0x60, 0xc4, 0xb9, 0x74, 0x21,
+    0x90, 0x90, 0xea, 0xf2, 0x87, 0x49, 0x7d, 0x7d, 0xcf, 0x7f, 0x11, 0x9c, 0xfa, 0x86, 0x74, 0x96,
+    0xf7, 0xe9, 0x1c, 0x12, 0xb5, 0xd5, 0x52, 0xe1, 0xd1, 0x46, 0x1a, 0x80, 0xdb, 0xe9, 0xa5, 0x9d,
+    0xb3, 0xb0, 0x16, 0xc6, 0xc0, 0x14, 0x1c, 0x3b, 0x2a, 0x0e, 0x22, 0x60, 0x89, 0xb8, 0x55, 0xcb,
+    0x88, 0xef, 0x65, 0x64, 0x08, 0xbd, 0x89, 0x02, 0x03, 0x01, 0x00, 0x01,
+};
+
+const unsigned char test_rsa_1536_priv[] = {
+    0x30, 0x82, 0x03, 0x7b, 0x02, 0x01, 0x00, 0x02, 0x81, 0xc1, 0x00, 0xc8, 0x70, 0xfe, 0xb6, 0xca,
+    0x6b, 0x1d, 0x2b, 0xd9, 0xf2, 0xdd, 0x99, 0xe2, 0x0f, 0x1f, 0xe2, 0xd7, 0xe5, 0x19, 0x2d, 0xe6,
+    0x62, 0x22, 0x9d, 0xbe, 0x16, 0x2b, 0xd1, 0xba, 0x66, 0x33, 0x6a, 0x71, 0x82, 0x90, 0x3c, 0xa0,
+    0xb7, 0x27, 0x96, 0xcd, 0x44, 0x1c, 0x83, 0xd2, 0x4b, 0xcd, 0xc3, 0xe9, 0xa2, 0xf5, 0xe4, 0x39,
+    0x9c, 0x8a, 0x04, 0x3f, 0x1c, 0x3d, 0xdf, 0x04, 0x75, 0x4a, 0x66, 0xd4, 0xcf, 0xe7, 0xb3, 0x67,
+    0x1a, 0x37, 0xdd, 0x31, 0xa9, 0xb4, 0xc1, 0x3b, 0xfe, 0x06, 0xee, 0x90, 0xf9, 0xd9, 0x4d, 0xda,
+    0xa0, 0x6d, 0xe6, 0x7a, 0x52, 0xac, 0x86, 0x3e, 0x68, 0xf7, 0x56, 0x73, 0x6c, 0xeb, 0x01, 0x44,
+    0x05, 0xa6, 0x16, 0x05, 0x79, 0x64, 0x0f, 0x83, 0x1d, 0xdd, 0xcc, 0xc3, 0x4a, 0xd0, 0xb0, 0x50,
+    0x70, 0xe3, 0xf9, 0x95, 0x4a, 0x58, 0xd1, 0x81, 0x58, 0x13, 0xe1, 0xb8, 0x3b, 0xca, 0xdb, 0xa8,
+    0x14, 0x78, 0x9c, 0x87, 0xf1, 0xef, 0x2b, 0xa5, 0xd7, 0x38, 0xb7, 0x93, 0xec, 0x45, 0x6a, 0x67,
+    0x36, 0x0e, 0xea, 0x1b, 0x5f, 0xaf, 0x1c, 0x7c, 0xc7, 0xbf, 0x24, 0xf3, 0xb2, 0xa9, 0xd0, 0xf8,
+    0x95, 0x8b, 0x10, 0x96, 0xe0, 0xf0, 0xc3, 0x35, 0xf8, 0x88, 0x8d, 0x0c, 0x63, 0xa5, 0x1c, 0x3c,
+    0x03, 0x37, 0x21, 0x4f, 0xa3, 0xf5, 0xef, 0xdf, 0x6d, 0xcc, 0x35, 0x02, 0x03, 0x01, 0x00, 0x01,
+    0x02, 0x81, 0xc0, 0x6d, 0x2d, 0x67, 0x00, 0x47, 0x97, 0x3a, 0x87, 0x75, 0x2a, 0x9d, 0x5b, 0xc1,
+    0x4f, 0x3d, 0xae, 0x00, 0xac, 0xb0, 0x1f, 0x59, 0x3a, 0xa0, 0xe2, 0x4c, 0xf4, 0xa4, 0x9f, 0x93,
+    0x29, 0x31, 0xde, 0x4b, 0xbf, 0xb3, 0x32, 0xe2, 0xd3, 0x80, 0x83, 0xda, 0x80, 0xbc, 0x0b, 0x6d,
+    0x53, 0x8e, 0xdb, 0xa4, 0x79, 0xf7, 0xf7, 0x7d, 0x0d, 0xef, 0xfb, 0x4a, 0x28, 0xe6, 0xe6, 0x7f,
+    0xf6, 0x27, 0x35, 0x85, 0xbb, 0x4c, 0xd8, 0x62, 0x53, 0x5c, 0x94, 0x66, 0x05, 0xab, 0x08, 0x09,
+    0xd6, 0x5f, 0x0e, 0x38, 0xf7, 0x6e, 0x4e, 0xc2, 0xc3, 0xd9, 0xb8, 0xcd, 0x6e, 0x14, 0xbc, 0xf6,
+    0x67, 0x94, 0x38, 0x92, 0xcd, 0x4b, 0x34, 0xcc, 0x64, 0x20, 0xa4, 0x39, 0xab, 0xbf, 0x3d, 0x7d,
+    0x35, 0xef, 0x73, 0x97, 0x6d, 0xd6, 0xf9, 0xcb, 0xde, 0x35, 0xa5, 0x1f, 0xa5, 0x21, 0x3f, 0x01,
+    0x07, 0xf8, 0x3e, 0x34, 0x25, 0x83, 0x5d, 0x16, 0xd3, 0xc9, 0x14, 0x6f, 0xc9, 0xe3, 0x6c, 0xe7,
+    0x5a, 0x09, 0xbb, 0x66, 0xcd, 0xff, 0x21, 0xdd, 0x5a, 0x77, 0x68, 0x99, 0xf1, 0xcb, 0x07, 0xe2,
+    0x82, 0xcc, 0xa2, 0x7b, 0xe4, 0x65, 0x10, 0xe9, 0xc7, 0x99, 0xf0, 0xd8, 0xdb, 0x27, 0x5a, 0x6b,
+    0xe0, 0x85, 0xd9, 0xf3, 0xf8, 0x03, 0x21, 0x8e, 0xe3, 0x38, 0x42, 0x65, 0xbf, 0xb1, 0xa3, 0x64,
+    0x0e, 0x8c, 0xa1, 0x02, 0x61, 0x00, 0xe6, 0x84, 0x8c, 0x31, 0xd4, 0x66, 0xff, 0xfe, 0xfc, 0x54,
+    0x7e, 0x3a, 0x3b, 0x0d, 0x37, 0x85, 0xde, 0x6f, 0x78, 0xb0, 0xdd, 0x12, 0x61, 0x08, 0x43, 0x51,
+    0x2e, 0x49, 0x56, 0x11, 0xa0, 0x67, 0x55, 0x09, 0xb1, 0x65, 0x0b, 0x27, 0x41, 0x50, 0x09, 0x83,
+    0x8d, 0xd8, 0xe6, 0x8e, 0xec, 0x6e, 0x75, 0x30, 0x55, 0x3b, 0x63, 0x7d, 0x60, 0x24, 0x24, 0x64,
+    0x3b, 0x33, 0xe8, 0xbc, 0x5b, 0x76, 0x2e, 0x17, 0x99, 0xbc, 0x79, 0xd5, 0x6b, 0x13, 0x25, 0x1d,
+    0x36, 0xd4, 0xf2, 0x01, 0xda, 0x21, 0x82, 0x41, 0x6c, 0xe1, 0x35, 0x74, 0xe8, 0x82, 0x78, 0xff,
+    0x04, 0x46, 0x7a, 0xd6, 0x02, 0xd9, 0x02, 0x61, 0x00, 0xde, 0x99, 0x4f, 0xdf, 0x18, 0x1f, 0x02,
+    0xbe, 0x2b, 0xf9, 0xe5, 0xf5, 0xe4, 0xe5, 0x17, 0xa9, 0x49, 0x93, 0xb8, 0x27, 0xd1, 0xea, 0xf6,
+    0x09, 0x03, 0x3e, 0x3a, 0x6a, 0x6f, 0x23, 0x96, 0xae, 0x7c, 0x44, 0xe9, 0xeb, 0x59, 0x4c, 0xf1,
+    0x04, 0x4c, 0xb3, 0xad, 0x32, 0xea, 0x25, 0x8f, 0x0c, 0x82, 0x96, 0x3b, 0x27, 0xbb, 0x65, 0x0e,
+    0xd2, 0x00, 0xcd, 0xe8, 0x2c, 0xb9, 0x93, 0x37, 0x4b, 0xe3, 0x4b, 0xe5, 0xb1, 0xc7, 0xea, 0xd5,
+    0x44, 0x6a, 0x2b, 0x82, 0xa4, 0x48, 0x6e, 0x8c, 0x18, 0x10, 0xa0, 0xb0, 0x15, 0x51, 0x60, 0x9f,
+    0xb0, 0x84, 0x1d, 0x47, 0x4b, 0xad, 0xa8, 0x02, 0xbd, 0x02, 0x60, 0x76, 0xdd, 0xae, 0x75, 0x1b,
+    0x73, 0xa9, 0x59, 0xd0, 0xbf, 0xb8, 0xff, 0x49, 0xe7, 0xfc, 0xd3, 0x78, 0xe9, 0xbe, 0x30, 0x65,
+    0x2e, 0xce, 0xfe, 0x35, 0xc8, 0x2c, 0xb8, 0x00, 0x3b, 0xc2, 0x9c, 0xc6, 0x0a, 0xe3, 0x80, 0x99,
+    0x09, 0xba, 0xf2, 0x0c, 0x95, 0xdb, 0x95, 0x16, 0xfe, 0x68, 0x08, 0x65, 0x41, 0x71, 0x11, 0xd8,
+    0xb1, 0x93, 0xdb, 0xcf, 0x30, 0x28, 0x1f, 0x12, 0x49, 0xde, 0x57, 0xc8, 0x58, 0xbf, 0x1b, 0xa3,
+    0x2f, 0x5b, 0xb1, 0x59, 0x98, 0x00, 0xe8, 0x39, 0x8a, 0x9e, 0xf2, 0x5c, 0x7a, 0x64, 0x2c, 0x95,
+    0x26, 0x1d, 0xa6, 0xf9, 0xc1, 0x76, 0x70, 0xe9, 0x72, 0x65, 0xb1, 0x02, 0x60, 0x73, 0x24, 0x82,
+    0xb8, 0x37, 0xd5, 0xf2, 0xa9, 0x44, 0x3e, 0x23, 0xc1, 0xaa, 0x01, 0x06, 0xd8, 0x3e, 0x82, 0xf6,
+    0xc3, 0x42, 0x46, 0x73, 0xb5, 0xfd, 0xc3, 0x76, 0x9c, 0x0f, 0x99, 0x2d, 0x1c, 0x5c, 0x93, 0x99,
+    0x1c, 0x70, 0x38, 0xe8, 0x82, 0xfc, 0xda, 0x04, 0x41, 0x4d, 0xf4, 0xd7, 0xa5, 0xf4, 0xf6, 0x98,
+    0xea, 0xd8, 0x78, 0x51, 0xce, 0x37, 0x34, 0x4b, 0x60, 0xb7, 0x2d, 0x7b, 0x70, 0xf9, 0xc6, 0x0c,
+    0xae, 0x85, 0x66, 0xe7, 0xa2, 0x57, 0xf8, 0xe1, 0xbe, 0xf0, 0xe8, 0x9d, 0xf6, 0xe4, 0xc2, 0xf9,
+    0xd2, 0x4d, 0x21, 0xd9, 0xf8, 0x88, 0x9e, 0x4c, 0x7e, 0xcc, 0xf9, 0x17, 0x51, 0x02, 0x60, 0x09,
+    0x05, 0x0d, 0x94, 0x49, 0x3d, 0xa8, 0xf0, 0x0a, 0x4d, 0xdb, 0xe9, 0xc8, 0x00, 0xaf, 0xe3, 0xd4,
+    0x4b, 0x43, 0xf7, 0x8a, 0x48, 0x94, 0x1a, 0x79, 0xb2, 0x81, 0x4a, 0x1f, 0x0b, 0x81, 0xa1, 0x8a,
+    0x8b, 0x23, 0x47, 0x64, 0x2a, 0x03, 0xb2, 0x79, 0x98, 0xf5, 0xa1, 0x8d, 0xe9, 0xab, 0xc9, 0xae,
+    0x0e, 0x54, 0xab, 0x82, 0x94, 0xfe, 0xac, 0x66, 0xdc, 0x87, 0xe8, 0x54, 0xcc, 0xe6, 0xf7, 0x27,
+    0x8a, 0xc2, 0x71, 0x0c, 0xb5, 0x87, 0x8b, 0x59, 0x2f, 0xfe, 0xb1, 0xf4, 0xf0, 0xa1, 0x85, 0x3e,
+    0x4e, 0x8d, 0x1d, 0x05, 0x61, 0xb6, 0xef, 0xcc, 0x83, 0x1a, 0x29, 0x6c, 0xf7, 0xee, 0xaf,
+};
+const unsigned char test_rsa_1536_pub[] = {
+    0x30, 0x81, 0xc9, 0x02, 0x81, 0xc1, 0x00, 0xc8, 0x70, 0xfe, 0xb6, 0xca, 0x6b, 0x1d, 0x2b, 0xd9,
+    0xf2, 0xdd, 0x99, 0xe2, 0x0f, 0x1f, 0xe2, 0xd7, 0xe5, 0x19, 0x2d, 0xe6, 0x62, 0x22, 0x9d, 0xbe,
+    0x16, 0x2b, 0xd1, 0xba, 0x66, 0x33, 0x6a, 0x71, 0x82, 0x90, 0x3c, 0xa0, 0xb7, 0x27, 0x96, 0xcd,
+    0x44, 0x1c, 0x83, 0xd2, 0x4b, 0xcd, 0xc3, 0xe9, 0xa2, 0xf5, 0xe4, 0x39, 0x9c, 0x8a, 0x04, 0x3f,
+    0x1c, 0x3d, 0xdf, 0x04, 0x75, 0x4a, 0x66, 0xd4, 0xcf, 0xe7, 0xb3, 0x67, 0x1a, 0x37, 0xdd, 0x31,
+    0xa9, 0xb4, 0xc1, 0x3b, 0xfe, 0x06, 0xee, 0x90, 0xf9, 0xd9, 0x4d, 0xda, 0xa0, 0x6d, 0xe6, 0x7a,
+    0x52, 0xac, 0x86, 0x3e, 0x68, 0xf7, 0x56, 0x73, 0x6c, 0xeb, 0x01, 0x44, 0x05, 0xa6, 0x16, 0x05,
+    0x79, 0x64, 0x0f, 0x83, 0x1d, 0xdd, 0xcc, 0xc3, 0x4a, 0xd0, 0xb0, 0x50, 0x70, 0xe3, 0xf9, 0x95,
+    0x4a, 0x58, 0xd1, 0x81, 0x58, 0x13, 0xe1, 0xb8, 0x3b, 0xca, 0xdb, 0xa8, 0x14, 0x78, 0x9c, 0x87,
+    0xf1, 0xef, 0x2b, 0xa5, 0xd7, 0x38, 0xb7, 0x93, 0xec, 0x45, 0x6a, 0x67, 0x36, 0x0e, 0xea, 0x1b,
+    0x5f, 0xaf, 0x1c, 0x7c, 0xc7, 0xbf, 0x24, 0xf3, 0xb2, 0xa9, 0xd0, 0xf8, 0x95, 0x8b, 0x10, 0x96,
+    0xe0, 0xf0, 0xc3, 0x35, 0xf8, 0x88, 0x8d, 0x0c, 0x63, 0xa5, 0x1c, 0x3c, 0x03, 0x37, 0x21, 0x4f,
+    0xa3, 0xf5, 0xef, 0xdf, 0x6d, 0xcc, 0x35, 0x02, 0x03, 0x01, 0x00, 0x01,
+};
+
+const unsigned char test_rsa_2048_priv[] = {
+    0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xf7, 0xbb, 0x6b, 0x8e,
+    0xab, 0x40, 0x49, 0x1c, 0xd6, 0x44, 0x55, 0xec, 0x04, 0xd4, 0xed, 0x8d, 0xb5, 0x05, 0x1a, 0x97,
+    0x38, 0xfc, 0x7a, 0xf7, 0x3f, 0xf3, 0xb0, 0x97, 0x51, 0x1c, 0xce, 0x40, 0xaa, 0xf7, 0x65, 0x37,
+    0xb1, 0x35, 0x35, 0x04, 0x42, 0x79, 0x86, 0xb7, 0xb2, 0xb5, 0x3a, 0x96, 0x4a, 0x69, 0x37, 0xb5,
+    0x58, 0xec, 0x0d, 0x1d, 0xea, 0x27, 0x4a, 0xf2, 0xb8, 0xff, 0xf2, 0xf0, 0x94, 0xc2, 0x43, 0xfa,
+    0x57, 0x72, 0x66, 0xa7, 0x9d, 0xb0, 0xc2, 0x6f, 0xfe, 0x30, 0x41, 0x6d, 0x23, 0xef, 0x05, 0xdd,
+    0x5f, 0xec, 0xab, 0x41, 0x3e, 0xbb, 0xb4, 0xf8, 0x52, 0x6a, 0xe7, 0x20, 0xa9, 0x45, 0x84, 0x22,
+    0x6b, 0x37, 0xd9, 0x2e, 0xf4, 0x63, 0xfc, 0x73, 0x6c, 0xb3, 0x8e, 0x53, 0x0e, 0x74, 0x88, 0xd9,
+    0x16, 0x2f, 0x57, 0x26, 0x80, 0x7b, 0xc5, 0x43, 0x13, 0x8a, 0x2d, 0x25, 0x8a, 0xdb, 0x4d, 0x68,
+    0x02, 0x21, 0xc2, 0x53, 0x23, 0x81, 0xcc, 0xfa, 0x81, 0xbc, 0x89, 0xbc, 0x3d, 0x7b, 0x84, 0x03,
+    0x9c, 0x2d, 0xf4, 0x1c, 0xe3, 0xec, 0x8d, 0xb9, 0x1c, 0x23, 0x80, 0xe7, 0x81, 0xba, 0x3a, 0xa9,
+    0xe2, 0x3b, 0x74, 0xed, 0x99, 0x73, 0xd4, 0x90, 0x8e, 0xfc, 0xa4, 0x7a, 0xa8, 0xd9, 0xb7, 0xb0,
+    0xa4, 0x42, 0x32, 0x97, 0xa4, 0x04, 0x42, 0x7c, 0x3f, 0x3c, 0xd6, 0xe0, 0x78, 0x2e, 0x45, 0x53,
+    0x88, 0x0f, 0x06, 0xba, 0x39, 0xa6, 0x4f, 0x4a, 0x7b, 0x0e, 0xef, 0x92, 0x1a, 0x60, 0x50, 0xa2,
+    0x07, 0xce, 0xfa, 0xdc, 0xf0, 0x73, 0x94, 0xa3, 0xe1, 0x8e, 0xa9, 0x15, 0xdc, 0x84, 0x97, 0xe7,
+    0xae, 0x61, 0xfc, 0x31, 0x62, 0xf6, 0x2f, 0x50, 0x65, 0xa6, 0x92, 0xaf, 0x07, 0x72, 0x66, 0xf7,
+    0x36, 0x0c, 0x20, 0x76, 0xce, 0xbe, 0xaf, 0x14, 0xcb, 0x22, 0xc1, 0xed, 0x02, 0x03, 0x01, 0x00,
+    0x01, 0x02, 0x82, 0x01, 0x00, 0x00, 0xb8, 0x96, 0x2d, 0xce, 0x60, 0x4b, 0xc6, 0x2e, 0x76, 0x78,
+    0xf4, 0x8c, 0xa8, 0x0c, 0xff, 0xf4, 0x56, 0xad, 0x36, 0xe2, 0xf6, 0xd3, 0x29, 0xcc, 0x91, 0x1a,
+    0x42, 0xba, 0x7c, 0xf5, 0xb9, 0xb8, 0xf5, 0xaa, 0xe1, 0x00, 0x5e, 0x4a, 0x06, 0xf6, 0xe5, 0x91,
+    0x27, 0x90, 0x38, 0xd8, 0x50, 0x8f, 0x2b, 0x62, 0xba, 0xdf, 0xa5, 0x22, 0x3d, 0xa3, 0xcc, 0x94,
+    0xfa, 0x83, 0x60, 0xd5, 0x55, 0x6f, 0x6d, 0x68, 0x52, 0xbe, 0x75, 0xea, 0x08, 0x13, 0x5c, 0xac,
+    0x18, 0x34, 0xda, 0x71, 0x9a, 0x4e, 0x78, 0x37, 0xe1, 0x66, 0xd1, 0xd2, 0xc6, 0xc8, 0x16, 0xb6,
+    0x46, 0x61, 0xc1, 0x07, 0x66, 0xb0, 0x2f, 0x70, 0x5c, 0xc4, 0x48, 0x9f, 0x94, 0x74, 0x28, 0x25,
+    0x58, 0x35, 0xa9, 0x09, 0x21, 0x43, 0x41, 0xc2, 0x13, 0x35, 0xae, 0x12, 0x18, 0x1d, 0xd8, 0x1e,
+    0x61, 0x1d, 0x59, 0xb1, 0xdb, 0x70, 0x66, 0x7b, 0xeb, 0xd7, 0xe9, 0x2b, 0x71, 0xe1, 0xd3, 0x88,
+    0x31, 0x8d, 0x3e, 0xc1, 0x4d, 0x61, 0x6f, 0x72, 0xc2, 0x31, 0xf6, 0x72, 0x7a, 0x18, 0x3e, 0x68,
+    0x18, 0x28, 0x5b, 0xd6, 0x5f, 0x65, 0x72, 0xca, 0xdc, 0x90, 0x12, 0x24, 0x88, 0x21, 0xb2, 0xd0,
+    0xae, 0x6c, 0xed, 0xd3, 0x0c, 0xa4, 0x40, 0xd4, 0xd3, 0x4c, 0xd7, 0x7e, 0x2c, 0xf6, 0xb4, 0x0e,
+    0xd2, 0xc7, 0xd8, 0x56, 0xb3, 0x0d, 0x47, 0x47, 0x33, 0xfc, 0xe0, 0xfb, 0x69, 0x5c, 0x3e, 0x65,
+    0x30, 0xc0, 0x79, 0xae, 0xd9, 0x55, 0xe4, 0x07, 0x30, 0x55, 0xf2, 0x65, 0x5d, 0x4b, 0x67, 0x1e,
+    0x29, 0x1f, 0xde, 0x40, 0x0f, 0x2f, 0x06, 0xd0, 0xb3, 0x3f, 0x87, 0xd2, 0x61, 0xe0, 0xad, 0x3d,
+    0xae, 0x48, 0xa9, 0x13, 0x84, 0x1b, 0x34, 0xcf, 0xed, 0x03, 0x79, 0x0f, 0xca, 0xee, 0x00, 0xde,
+    0x2e, 0x90, 0xfb, 0x96, 0x21, 0x02, 0x81, 0x81, 0x00, 0xfc, 0xbe, 0x89, 0xcd, 0x1a, 0xa3, 0x19,
+    0xe4, 0x9e, 0xf4, 0xf7, 0x21, 0x49, 0xbf, 0x06, 0xda, 0x57, 0xdc, 0xc6, 0x4d, 0x3d, 0xe6, 0x05,
+    0xe9, 0xff, 0x3e, 0x76, 0xfc, 0x66, 0xf4, 0xb1, 0xe2, 0x87, 0x82, 0x45, 0xff, 0xd7, 0x19, 0x90,
+    0x51, 0x1b, 0x17, 0xe9, 0x7f, 0x33, 0x81, 0x88, 0x89, 0xa8, 0xc2, 0x1b, 0x55, 0x27, 0xfd, 0x18,
+    0x13, 0x27, 0xaf, 0xfe, 0x88, 0xf9, 0xbb, 0xa6, 0x70, 0xc4, 0xe6, 0xf1, 0xe6, 0x30, 0x9b, 0xd0,
+    0x32, 0x30, 0x74, 0xe4, 0xcb, 0xcf, 0x23, 0xdc, 0xe3, 0xc1, 0x9b, 0x8d, 0x54, 0x95, 0xf5, 0x6a,
+    0x93, 0x05, 0x9b, 0xa7, 0x41, 0x4f, 0x28, 0xed, 0x1e, 0xc9, 0x06, 0xad, 0x18, 0xc6, 0x3d, 0xe1,
+    0x14, 0x8a, 0xbc, 0xfe, 0x9b, 0xe7, 0x98, 0x60, 0x00, 0xf4, 0x25, 0xe5, 0x80, 0xb7, 0x0e, 0x43,
+    0xe4, 0x8e, 0x24, 0xfa, 0x9d, 0x51, 0xaa, 0xae, 0x4d, 0x02, 0x81, 0x81, 0x00, 0xfa, 0xec, 0x5a,
+    0x7b, 0xed, 0x2e, 0x53, 0xcf, 0xca, 0x1e, 0x16, 0x7d, 0xb4, 0x64, 0x1d, 0xb5, 0xa0, 0x0f, 0xe2,
+    0xc3, 0x28, 0x12, 0x54, 0x23, 0xd5, 0x94, 0x78, 0x9f, 0x3e, 0xc0, 0x72, 0xc6, 0x23, 0xe7, 0xaf,
+    0xbd, 0xee, 0x00, 0x89, 0xfd, 0x26, 0x30, 0x76, 0x51, 0xf6, 0xd3, 0x61, 0x1a, 0x88, 0xaf, 0x28,
+    0xc3, 0x45, 0x85, 0xd5, 0xcb, 0x71, 0x3a, 0x65, 0x0c, 0x35, 0x93, 0x3f, 0x58, 0x94, 0x4d, 0xb9,
+    0xbd, 0x15, 0xba, 0x9f, 0xc2, 0x8b, 0x07, 0xe6, 0x70, 0x5b, 0x7b, 0x3e, 0xf1, 0xcc, 0xb4, 0x8d,
+    0x21, 0xa5, 0x35, 0x69, 0xc8, 0xb8, 0x4c, 0x44, 0x4b, 0x61, 0xea, 0x5c, 0x6e, 0x67, 0xb5, 0x4f,
+    0x0a, 0xfd, 0x85, 0x2f, 0xfb, 0x8c, 0x92, 0xa1, 0x11, 0xfa, 0xb8, 0x67, 0x72, 0x63, 0xee, 0xb8,
+    0x0c, 0xf1, 0xa3, 0x40, 0x3b, 0x4a, 0x9a, 0x20, 0x97, 0x76, 0x94, 0x72, 0x21, 0x02, 0x81, 0x80,
+    0x2f, 0xf9, 0x9a, 0xfe, 0xab, 0xc7, 0xb9, 0xea, 0x83, 0xa1, 0xcc, 0x27, 0x2d, 0x70, 0x6d, 0x44,
+    0x94, 0xd8, 0xfb, 0x6b, 0x3e, 0x0c, 0xa3, 0xa2, 0xbf, 0x28, 0x84, 0x3d, 0x74, 0xed, 0x8d, 0xb6,
+    0x8a, 0x32, 0x58, 0x47, 0x2f, 0xf5, 0x52, 0x47, 0x92, 0xf4, 0xff, 0x05, 0x7e, 0x29, 0x60, 0x59,
+    0x81, 0x07, 0x17, 0x59, 0x1a, 0xb6, 0x18, 0x13, 0xca, 0xbc, 0xc5, 0x7c, 0x0a, 0xab, 0x6b, 0xf4,
+    0x8b, 0xeb, 0xaa, 0x8f, 0x1f, 0x3a, 0xf4, 0x52, 0x12, 0x90, 0x9d, 0xbd, 0x72, 0x1c, 0x44, 0x99,
+    0x96, 0xee, 0x87, 0xed, 0x3e, 0x69, 0xcf, 0x49, 0x09, 0x0f, 0x7a, 0xb8, 0x12, 0xe6, 0x99, 0xdb,
+    0xf6, 0x1c, 0xa6, 0x4e, 0xc5, 0x92, 0x89, 0x5e, 0xf4, 0xd6, 0xdb, 0x1d, 0x8c, 0xe0, 0x87, 0x98,
+    0xa6, 0xbf, 0x6a, 0xc8, 0xfb, 0xf6, 0x61, 0x3c, 0xc9, 0x1e, 0x8b, 0xd3, 0xc0, 0xe4, 0xbd, 0x21,
+    0x02, 0x81, 0x81, 0x00, 0xb2, 0x9b, 0x34, 0x59, 0x0b, 0xdd, 0xb3, 0x08, 0xaf, 0xec, 0xb4, 0xc3,
+    0xab, 0x78, 0xab, 0xf1, 0x11, 0x4a, 0xdd, 0x75, 0x5e, 0x7b, 0x95, 0x6a, 0xa0, 0x67, 0x7b, 0x68,
+    0x96, 0xa9, 0x33, 0xc9, 0x37, 0xdb, 0x7d, 0xab, 0xaa, 0xd2, 0xb5, 0x65, 0xfd, 0x1d, 0xf7, 0xca,
+    0xa5, 0xef, 0x96, 0x29, 0xe5, 0xeb, 0x10, 0x0f, 0xd6, 0xd7, 0xc9, 0xf3, 0x72, 0xd8, 0x46, 0xfe,
+    0xe6, 0xcf, 0xb6, 0x02, 0x5e, 0x25, 0xe9, 0x34, 0xdf, 0x57, 0xa4, 0xca, 0x3c, 0x5e, 0x56, 0x37,
+    0xd9, 0xd6, 0x23, 0x5a, 0xc8, 0x04, 0x28, 0x85, 0x2f, 0x6c, 0x92, 0xac, 0xae, 0x0a, 0x93, 0x7e,
+    0x38, 0xe7, 0x31, 0xfd, 0xe0, 0x52, 0x1d, 0x3e, 0x4c, 0x70, 0xd6, 0x53, 0xae, 0x9e, 0xdc, 0x89,
+    0xc8, 0xb6, 0x23, 0xe4, 0x37, 0x9f, 0xbf, 0x60, 0x6f, 0x4b, 0x6d, 0xb8, 0x06, 0x85, 0x28, 0xf7,
+    0xc7, 0x0f, 0x29, 0x21, 0x02, 0x81, 0x80, 0x0e, 0xd4, 0x7a, 0xe0, 0x5b, 0x27, 0x5a, 0x23, 0xa7,
+    0xdf, 0xe3, 0xff, 0xb7, 0x27, 0xe3, 0xa2, 0x68, 0xe6, 0x26, 0xa5, 0x9d, 0x40, 0x1d, 0x2d, 0x84,
+    0x6d, 0xe2, 0x69, 0x54, 0xff, 0x54, 0xfc, 0x9e, 0xd9, 0x3a, 0x9a, 0xf3, 0x3f, 0xac, 0x2c, 0x96,
+    0x7a, 0x18, 0xe0, 0xf8, 0x61, 0x45, 0x08, 0x3e, 0x39, 0x92, 0x34, 0x54, 0xbc, 0x10, 0xda, 0x5f,
+    0x49, 0x37, 0xe8, 0x36, 0xb9, 0x98, 0x51, 0x95, 0x6b, 0xff, 0xb3, 0x01, 0xce, 0x9e, 0x06, 0x78,
+    0x97, 0x86, 0x69, 0x32, 0x13, 0xfc, 0xde, 0x6d, 0x5f, 0x29, 0x33, 0xd5, 0x2b, 0xb2, 0x9d, 0xc3,
+    0x40, 0xea, 0x01, 0x12, 0x57, 0x78, 0x8d, 0x3c, 0x57, 0x75, 0xeb, 0x65, 0x69, 0x23, 0x0a, 0xaf,
+    0xbf, 0x08, 0x75, 0x2d, 0x40, 0xa8, 0x41, 0x9d, 0xe7, 0x1b, 0x01, 0xd4, 0x92, 0x7e, 0x27, 0xc1,
+    0x07, 0x9c, 0xaa, 0xda, 0x05, 0x68, 0xb1,
+};
+const unsigned char test_rsa_2048_pub[] = {
+    0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xf7, 0xbb, 0x6b, 0x8e, 0xab, 0x40, 0x49,
+    0x1c, 0xd6, 0x44, 0x55, 0xec, 0x04, 0xd4, 0xed, 0x8d, 0xb5, 0x05, 0x1a, 0x97, 0x38, 0xfc, 0x7a,
+    0xf7, 0x3f, 0xf3, 0xb0, 0x97, 0x51, 0x1c, 0xce, 0x40, 0xaa, 0xf7, 0x65, 0x37, 0xb1, 0x35, 0x35,
+    0x04, 0x42, 0x79, 0x86, 0xb7, 0xb2, 0xb5, 0x3a, 0x96, 0x4a, 0x69, 0x37, 0xb5, 0x58, 0xec, 0x0d,
+    0x1d, 0xea, 0x27, 0x4a, 0xf2, 0xb8, 0xff, 0xf2, 0xf0, 0x94, 0xc2, 0x43, 0xfa, 0x57, 0x72, 0x66,
+    0xa7, 0x9d, 0xb0, 0xc2, 0x6f, 0xfe, 0x30, 0x41, 0x6d, 0x23, 0xef, 0x05, 0xdd, 0x5f, 0xec, 0xab,
+    0x41, 0x3e, 0xbb, 0xb4, 0xf8, 0x52, 0x6a, 0xe7, 0x20, 0xa9, 0x45, 0x84, 0x22, 0x6b, 0x37, 0xd9,
+    0x2e, 0xf4, 0x63, 0xfc, 0x73, 0x6c, 0xb3, 0x8e, 0x53, 0x0e, 0x74, 0x88, 0xd9, 0x16, 0x2f, 0x57,
+    0x26, 0x80, 0x7b, 0xc5, 0x43, 0x13, 0x8a, 0x2d, 0x25, 0x8a, 0xdb, 0x4d, 0x68, 0x02, 0x21, 0xc2,
+    0x53, 0x23, 0x81, 0xcc, 0xfa, 0x81, 0xbc, 0x89, 0xbc, 0x3d, 0x7b, 0x84, 0x03, 0x9c, 0x2d, 0xf4,
+    0x1c, 0xe3, 0xec, 0x8d, 0xb9, 0x1c, 0x23, 0x80, 0xe7, 0x81, 0xba, 0x3a, 0xa9, 0xe2, 0x3b, 0x74,
+    0xed, 0x99, 0x73, 0xd4, 0x90, 0x8e, 0xfc, 0xa4, 0x7a, 0xa8, 0xd9, 0xb7, 0xb0, 0xa4, 0x42, 0x32,
+    0x97, 0xa4, 0x04, 0x42, 0x7c, 0x3f, 0x3c, 0xd6, 0xe0, 0x78, 0x2e, 0x45, 0x53, 0x88, 0x0f, 0x06,
+    0xba, 0x39, 0xa6, 0x4f, 0x4a, 0x7b, 0x0e, 0xef, 0x92, 0x1a, 0x60, 0x50, 0xa2, 0x07, 0xce, 0xfa,
+    0xdc, 0xf0, 0x73, 0x94, 0xa3, 0xe1, 0x8e, 0xa9, 0x15, 0xdc, 0x84, 0x97, 0xe7, 0xae, 0x61, 0xfc,
+    0x31, 0x62, 0xf6, 0x2f, 0x50, 0x65, 0xa6, 0x92, 0xaf, 0x07, 0x72, 0x66, 0xf7, 0x36, 0x0c, 0x20,
+    0x76, 0xce, 0xbe, 0xaf, 0x14, 0xcb, 0x22, 0xc1, 0xed, 0x02, 0x03, 0x01, 0x00, 0x01,
+};
+
+const unsigned char test_rsa_4096_priv[] = {
+    0x30, 0x82, 0x09, 0x29, 0x02, 0x01, 0x00, 0x02, 0x82, 0x02, 0x01, 0x00, 0xcc, 0x87, 0x25, 0xf6,
+    0xb3, 0x8d, 0x5d, 0x01, 0xae, 0xeb, 0x07, 0xd3, 0x6e, 0x03, 0xde, 0x4d, 0x31, 0xa0, 0x26, 0x1c,
+    0xe7, 0x4f, 0xe1, 0x1a, 0x89, 0x5e, 0xcf, 0xd1, 0x3d, 0x16, 0x8a, 0xee, 0x93, 0x2a, 0xf1, 0x35,
+    0xff, 0xbb, 0x84, 0x98, 0x77, 0x27, 0x38, 0x97, 0x08, 0x1f, 0x3f, 0x75, 0x93, 0xc1, 0x4a, 0xe8,
+    0x2b, 0xc2, 0x66, 0xc1, 0x05, 0x44, 0xf7, 0x26, 0xae, 0x1c, 0xcf, 0x13, 0x3d, 0x8a, 0x40, 0x18,
+    0xd3, 0x80, 0xdf, 0xa2, 0x52, 0x51, 0xc0, 0x11, 0x10, 0x7b, 0x75, 0x13, 0xa9, 0x43, 0x34, 0x6a,
+    0xa0, 0xe0, 0xde, 0xc1, 0x1d, 0x8d, 0x7f, 0xa2, 0x56, 0x44, 0x65, 0x3c, 0x11, 0x8d, 0xaa, 0xbc,
+    0xe6, 0xd4, 0x1f, 0x06, 0x6f, 0x66, 0x21, 0x76, 0x88, 0x01, 0x47, 0x80, 0x55, 0x78, 0x0e, 0x91,
+    0xb6, 0x8e, 0xa3, 0xc9, 0x58, 0x56, 0xd1, 0x72, 0xa8, 0x90, 0x32, 0xb3, 0x9c, 0x82, 0x4e, 0x8b,
+    0x7d, 0xc1, 0xa3, 0xf8, 0xae, 0xe4, 0xf6, 0xb3, 0x68, 0xba, 0xa3, 0xcd, 0x68, 0xf5, 0x0d, 0x52,
+    0x68, 0x01, 0x17, 0xe9, 0xb9, 0x13, 0xd7, 0xf8, 0xc8, 0x52, 0xa0, 0xd1, 0x00, 0x8e, 0x8b, 0x87,
+    0xa5, 0xc9, 0x7e, 0x37, 0xaf, 0xc1, 0x1a, 0x08, 0x05, 0x50, 0x55, 0x7b, 0x8b, 0x4d, 0xcb, 0xd8,
+    0xe1, 0x92, 0xed, 0x33, 0x66, 0xd8, 0x3a, 0x09, 0xd2, 0x7c, 0x77, 0xe1, 0x50, 0xf6, 0x68, 0x55,
+    0xb5, 0xdc, 0xfd, 0xb2, 0xdf, 0x15, 0x1b, 0xd7, 0xf4, 0x44, 0x25, 0x0e, 0xaf, 0x6f, 0xe3, 0xf2,
+    0x36, 0x82, 0x6c, 0x81, 0xfa, 0x84, 0x81, 0x01, 0xbf, 0xaa, 0xd5, 0x35, 0xff, 0xb5, 0x22, 0xd6,
+    0xff, 0x97, 0xc9, 0xdd, 0x1e, 0x43, 0xb8, 0x2c, 0xce, 0x29, 0x21, 0xd1, 0x53, 0xc1, 0x54, 0x50,
+    0xc4, 0x72, 0x4f, 0xfd, 0x3e, 0xfd, 0xca, 0x57, 0x8e, 0x01, 0x36, 0x50, 0xa0, 0x3a, 0x5c, 0xf5,
+    0x01, 0xfc, 0x58, 0x60, 0x0f, 0xb5, 0xc8, 0x60, 0xc0, 0xef, 0x0c, 0xfe, 0x0a, 0xc0, 0x71, 0x2d,
+    0x44, 0x13, 0x13, 0xdc, 0xa4, 0x1a, 0x4d, 0x7d, 0x41, 0x1e, 0x6c, 0x83, 0xb2, 0x15, 0x17, 0x49,
+    0xd2, 0x8b, 0xe4, 0x69, 0x2f, 0x62, 0x37, 0x3d, 0xb0, 0x7e, 0x4a, 0x79, 0x05, 0x1c, 0x56, 0x82,
+    0xec, 0x20, 0xd4, 0x91, 0xc4, 0xcf, 0xc7, 0xbc, 0x14, 0x0f, 0x35, 0xfa, 0x15, 0xe5, 0xa1, 0xfa,
+    0x75, 0x6d, 0x65, 0xb8, 0xef, 0x93, 0xad, 0xdf, 0x4c, 0x47, 0xc4, 0xa3, 0x5b, 0x18, 0x4f, 0x22,
+    0xa1, 0xef, 0x08, 0x99, 0x48, 0xf9, 0x46, 0xf6, 0xfa, 0xeb, 0x64, 0x70, 0xf2, 0x67, 0x46, 0xe6,
+    0x58, 0xcf, 0x9b, 0x41, 0x77, 0x41, 0x78, 0x42, 0xe6, 0xd3, 0x73, 0x55, 0x80, 0x89, 0xaf, 0xf7,
+    0x21, 0xb9, 0x30, 0xe9, 0xec, 0x61, 0xb4, 0xf6, 0xa0, 0x2c, 0x05, 0x2c, 0x69, 0x24, 0xd3, 0x9a,
+    0x5b, 0xbb, 0x15, 0xed, 0x11, 0x06, 0xc4, 0x01, 0x0f, 0x4d, 0xd6, 0x9c, 0x79, 0xd0, 0x42, 0xc8,
+    0xb3, 0x16, 0x61, 0xb1, 0xee, 0x48, 0x6b, 0xc6, 0x9d, 0xb5, 0xf2, 0xf0, 0x7a, 0x50, 0xd8, 0x5b,
+    0x20, 0x69, 0x9d, 0x60, 0x13, 0x15, 0x62, 0x5b, 0xb8, 0x69, 0x62, 0x9c, 0x7f, 0x4c, 0x5d, 0x48,
+    0xb2, 0x11, 0xd0, 0x97, 0xf4, 0x38, 0xac, 0xec, 0x95, 0x97, 0x3a, 0x38, 0xd4, 0x21, 0x09, 0x0a,
+    0xf0, 0xf1, 0x34, 0x84, 0xe4, 0xe9, 0x4b, 0x8c, 0xb5, 0xef, 0xc1, 0x85, 0x07, 0xf4, 0xb9, 0x31,
+    0xdf, 0x39, 0x98, 0x7f, 0xfb, 0x28, 0x30, 0x29, 0x3e, 0x4d, 0xa3, 0x81, 0xaa, 0xf7, 0x0b, 0x32,
+    0x92, 0x95, 0x2e, 0xf9, 0x34, 0xe2, 0xb4, 0x0f, 0xde, 0xbb, 0xa3, 0xd9, 0x70, 0x1b, 0x76, 0xe1,
+    0xbe, 0x54, 0x82, 0x74, 0xb2, 0x60, 0x2d, 0x88, 0x85, 0x37, 0x48, 0x2d, 0x02, 0x03, 0x01, 0x00,
+    0x01, 0x02, 0x82, 0x02, 0x00, 0x1a, 0x94, 0x3e, 0x9c, 0x00, 0x89, 0xf0, 0xaa, 0x01, 0x16, 0x04,
+    0x8a, 0x96, 0xab, 0xb4, 0x86, 0x32, 0x1a, 0x86, 0x91, 0x6f, 0x82, 0xfb, 0x35, 0x24, 0x60, 0x78,
+    0x9f, 0xcf, 0xb1, 0x40, 0x05, 0x50, 0x85, 0x3e, 0x5a, 0xfe, 0xdc, 0x9a, 0xd6, 0xe8, 0x77, 0x25,
+    0x9c, 0xc4, 0xfe, 0xb0, 0x93, 0xc2, 0x4b, 0x96, 0x85, 0x34, 0xf8, 0x9a, 0xbb, 0x5f, 0x48, 0xae,
+    0xd8, 0xad, 0x3c, 0x4b, 0xb1, 0xcb, 0xa7, 0xcd, 0x7c, 0x1c, 0x72, 0x4d, 0x3d, 0xae, 0x36, 0x77,
+    0x00, 0x10, 0xb5, 0x06, 0x8a, 0x33, 0x4f, 0x2b, 0x3e, 0xe7, 0x20, 0xc9, 0xf9, 0xed, 0x32, 0x00,
+    0x01, 0xf3, 0xf5, 0x87, 0xf5, 0x66, 0x2f, 0x93, 0x9e, 0x60, 0x5d, 0xf5, 0x19, 0x34, 0x3d, 0x60,
+    0xc0, 0x63, 0x5c, 0xcd, 0x32, 0xb1, 0x88, 0xbc, 0x55, 0xf5, 0xd4, 0x34, 0x17, 0x3c, 0x9e, 0x6d,
+    0xb2, 0x19, 0x93, 0x41, 0xaf, 0x83, 0x39, 0x90, 0xe5, 0x02, 0x46, 0xf9, 0x9c, 0xdd, 0xf7, 0x9d,
+    0xd2, 0xc3, 0x5b, 0xab, 0xe1, 0x4c, 0x10, 0x3a, 0x76, 0xb8, 0xd2, 0xd9, 0x8d, 0x73, 0x52, 0x8f,
+    0x98, 0xc2, 0x49, 0xb0, 0xa1, 0xf0, 0x91, 0x55, 0xb3, 0x1f, 0x59, 0x9f, 0xc8, 0x33, 0x54, 0x24,
+    0x22, 0xa2, 0x34, 0x26, 0x23, 0xbb, 0xbe, 0xf4, 0xac, 0x7e, 0xe6, 0x05, 0xe2, 0xcd, 0xec, 0xf0,
+    0x1f, 0xea, 0x25, 0x68, 0x3b, 0xd4, 0xf6, 0x6c, 0xa9, 0x24, 0xcc, 0xef, 0x00, 0x41, 0x8a, 0xdf,
+    0xf7, 0x30, 0xc4, 0x71, 0x4f, 0x66, 0xff, 0xa2, 0xaf, 0x0d, 0xa3, 0xe5, 0xdf, 0x7f, 0x53, 0x9c,
+    0x63, 0x42, 0x89, 0xfc, 0x12, 0xbc, 0x24, 0x09, 0x3e, 0xc8, 0xf0, 0xec, 0x18, 0x0a, 0xf0, 0x90,
+    0x7c, 0xec, 0x1e, 0xbe, 0xc9, 0x11, 0xfa, 0x18, 0x0f, 0xb5, 0xf3, 0xc8, 0x0e, 0xd8, 0x52, 0x89,
+    0x6a, 0xd6, 0xe6, 0xb3, 0xec, 0xcb, 0x44, 0xde, 0x62, 0x19, 0x3d, 0x52, 0x11, 0x8c, 0xab, 0x2b,
+    0x17, 0x10, 0x71, 0xd5, 0xfd, 0xaa, 0x7c, 0x42, 0x88, 0xfc, 0x77, 0x66, 0xd5, 0x77, 0x74, 0xf4,
+    0xbe, 0x46, 0x15, 0x1b, 0xb9, 0x0a, 0xce, 0x7c, 0x10, 0xc2, 0x15, 0xf6, 0x2e, 0xd2, 0x6e, 0x52,
+    0xe6, 0x12, 0x24, 0x36, 0xf5, 0x32, 0xbd, 0x54, 0xfc, 0x08, 0x27, 0x2a, 0xdb, 0x21, 0x6a, 0x2d,
+    0xb4, 0x33, 0xd5, 0x69, 0x9c, 0x40, 0xad, 0x58, 0xfa, 0xa2, 0x66, 0x08, 0x98, 0xff, 0xcc, 0xfc,
+    0x98, 0x00, 0x2f, 0x8b, 0xb0, 0x36, 0x1b, 0x4c, 0xf9, 0xed, 0x6e, 0x93, 0xc1, 0xca, 0x96, 0xd3,
+    0x4a, 0x1e, 0xf4, 0x04, 0x60, 0xf8, 0x59, 0x18, 0xcf, 0xde, 0x4a, 0x81, 0x93, 0xb5, 0x1e, 0xce,
+    0xa4, 0xb3, 0x90, 0x3c, 0xae, 0x92, 0x4a, 0x8f, 0xad, 0x5f, 0x83, 0x08, 0x95, 0x4c, 0x9f, 0x19,
+    0xa7, 0x59, 0x7b, 0xf0, 0xa7, 0x51, 0x26, 0xa5, 0x57, 0xe4, 0x9f, 0x8b, 0xbd, 0x31, 0xfc, 0x4e,
+    0x85, 0x56, 0xf2, 0x30, 0x64, 0x0b, 0xf3, 0x62, 0x04, 0xc6, 0xcf, 0x3d, 0x56, 0xdc, 0xa5, 0xa4,
+    0x1d, 0x86, 0x03, 0x07, 0xba, 0x67, 0x05, 0xa6, 0x98, 0x68, 0x11, 0x00, 0xa3, 0x27, 0xf9, 0x17,
+    0x39, 0xc4, 0x86, 0xc4, 0x70, 0xba, 0x71, 0xd0, 0x3d, 0x28, 0x53, 0x14, 0xb0, 0xd7, 0xd0, 0x40,
+    0x08, 0xe0, 0x3f, 0x2a, 0x2b, 0x85, 0xe7, 0xc2, 0x43, 0xd6, 0xfd, 0x9b, 0x97, 0xa0, 0x21, 0x68,
+    0xc0, 0x69, 0xec, 0x57, 0x2d, 0x3f, 0x0c, 0xa1, 0x5e, 0xbc, 0xb1, 0x73, 0x9f, 0x3a, 0x0b, 0x3c,
+    0x14, 0x7a, 0x88, 0xe0, 0xb7, 0x4f, 0x45, 0xa0, 0x07, 0xae, 0x92, 0x7d, 0x6f, 0x82, 0x2b, 0xf5,
+    0x0b, 0x87, 0xb1, 0xe9, 0x3f, 0xe7, 0xd9, 0x18, 0x0b, 0xc6, 0xbc, 0x12, 0xbd, 0xe6, 0xc8, 0x07,
+    0x0d, 0x10, 0xc9, 0x73, 0x31, 0x02, 0x82, 0x01, 0x01, 0x00, 0xf5, 0x0e, 0xbc, 0xea, 0xc9, 0xd3,
+    0xc6, 0x44, 0x82, 0xa8, 0xc2, 0x65, 0xd6, 0x36, 0x54, 0x61, 0xaa, 0x4a, 0x31, 0xa6, 0xa7, 0x63,
+    0x3a, 0x24, 0xc8, 0xe3, 0x47, 0x94, 0xec, 0xdf, 0xca, 0xb1, 0xd6, 0xb5, 0x2f, 0xb6, 0xa5, 0xf3,
+    0x80, 0x55, 0xcc, 0x32, 0xd6, 0xa6, 0x1b, 0x88, 0x95, 0x50, 0xde, 0x27, 0xb3, 0xd0, 0xbd, 0x68,
+    0xb6, 0xd4, 0xfd, 0xa0, 0x41, 0x59, 0x8a, 0xb9, 0x88, 0x87, 0x14, 0x39, 0x88, 0x57, 0x68, 0x06,
+    0xb1, 0xc4, 0x87, 0x20, 0x79, 0x49, 0x02, 0x95, 0x2e, 0xbe, 0x1b, 0xf0, 0xde, 0xf6, 0x5a, 0x0e,
+    0x6f, 0x94, 0x06, 0x70, 0x56, 0xe6, 0x86, 0x4f, 0xa2, 0x88, 0x2e, 0x3a, 0x16, 0xf2, 0x46, 0x28,
+    0x20, 0x93, 0xd0, 0x37, 0x63, 0x90, 0x78, 0x18, 0x2d, 0xd0, 0xa6, 0xeb, 0x21, 0xd3, 0xba, 0xd0,
+    0x63, 0x79, 0x01, 0xa2, 0x68, 0xb1, 0x4c, 0x63, 0x2c, 0x9d, 0x0b, 0x16, 0x90, 0xed, 0x88, 0xab,
+    0xdd, 0xe0, 0x3f, 0x52, 0x82, 0x47, 0xaa, 0x2e, 0x41, 0x55, 0x7d, 0x08, 0x65, 0xad, 0x34, 0xe5,
+    0x3f, 0xf5, 0x3a, 0xe0, 0xe5, 0xde, 0xa1, 0x95, 0xd9, 0x3f, 0xe6, 0x5c, 0x25, 0x87, 0x1f, 0x6f,
+    0x23, 0xad, 0xf3, 0x4b, 0x6e, 0x96, 0x0c, 0x29, 0x78, 0xf2, 0xb7, 0x47, 0x5d, 0xaf, 0xce, 0x6c,
+    0xbb, 0x26, 0xa5, 0x39, 0x34, 0xd2, 0x6c, 0x19, 0x3d, 0x67, 0xf3, 0x2d, 0xe9, 0x10, 0x35, 0xee,
+    0xb8, 0x90, 0x22, 0xbe, 0xb7, 0xd5, 0xdf, 0x78, 0x4a, 0xc2, 0x0c, 0xa6, 0xab, 0x91, 0xbf, 0x6b,
+    0x77, 0x5b, 0x6c, 0x94, 0x16, 0xf6, 0x05, 0xb4, 0x84, 0x17, 0x36, 0xcb, 0xfb, 0xd2, 0x2a, 0xd9,
+    0x8a, 0xb2, 0xe8, 0x42, 0x84, 0x57, 0xe0, 0x79, 0x3f, 0x5a, 0xf4, 0x0e, 0x55, 0x0b, 0x48, 0x76,
+    0x5d, 0x59, 0xe6, 0xe1, 0xb4, 0xa4, 0xa1, 0xf5, 0x71, 0xf1, 0x02, 0x82, 0x01, 0x01, 0x00, 0xd5,
+    0xa9, 0x1d, 0x4d, 0x44, 0xbb, 0x9b, 0x73, 0xc1, 0xfe, 0x02, 0x48, 0x92, 0x5e, 0x2c, 0x0e, 0xc1,
+    0xde, 0x51, 0x39, 0x0b, 0xd8, 0xa7, 0x3b, 0x45, 0x3d, 0xa5, 0x1a, 0xe2, 0x93, 0x25, 0xae, 0x76,
+    0x57, 0x08, 0x9f, 0xd4, 0xee, 0x4a, 0x2f, 0xd9, 0x6e, 0x34, 0x5b, 0x57, 0xf6, 0x72, 0xd7, 0xd4,
+    0x84, 0xfd, 0xe9, 0x91, 0x89, 0xab, 0x0a, 0x63, 0x65, 0xbf, 0x2b, 0x38, 0x68, 0x0d, 0x6b, 0xb9,
+    0x47, 0xf4, 0xb2, 0x17, 0xbe, 0x66, 0x03, 0x23, 0xc2, 0x6b, 0x86, 0xd6, 0x43, 0xae, 0x68, 0x6d,
+    0x82, 0xe3, 0x6e, 0xc0, 0x0c, 0xfd, 0x03, 0x89, 0x42, 0x44, 0x3c, 0xaa, 0x04, 0xa0, 0xf9, 0x1e,
+    0x68, 0xec, 0x71, 0x79, 0x35, 0xb4, 0x5e, 0x79, 0x03, 0x11, 0xbe, 0x56, 0x44, 0x0d, 0x71, 0x76,
+    0x94, 0x95, 0x94, 0x68, 0x8e, 0xd1, 0xdd, 0x5c, 0x91, 0x03, 0xc5, 0x7c, 0x15, 0x8d, 0x05, 0xe4,
+    0xc3, 0x7b, 0x98, 0xd8, 0x18, 0x98, 0x03, 0x07, 0x44, 0xa6, 0x4f, 0x6e, 0xbd, 0xbf, 0x75, 0x0a,
+    0xab, 0x79, 0x75, 0x7e, 0x34, 0xda, 0xc4, 0x22, 0x16, 0x3e, 0xa7, 0xc0, 0xf4, 0x2b, 0x97, 0x71,
+    0x0c, 0x86, 0x19, 0x78, 0xb2, 0x41, 0x00, 0x38, 0x5a, 0xad, 0x72, 0x7e, 0x5f, 0x38, 0x36, 0xa7,
+    0x4e, 0xa4, 0xbf, 0x1d, 0x36, 0xef, 0x2a, 0x5e, 0xdf, 0x9c, 0x9e, 0x8f, 0x99, 0x6e, 0xf3, 0x19,
+    0x13, 0x48, 0x45, 0x0e, 0xa9, 0xf1, 0xd4, 0xa6, 0x3d, 0xb2, 0x9c, 0xb0, 0x6f, 0x63, 0xe5, 0xba,
+    0xdb, 0x18, 0xe4, 0xd4, 0x0f, 0x51, 0x12, 0xb6, 0x58, 0xd1, 0xcc, 0x23, 0xcb, 0x65, 0x38, 0x8a,
+    0xca, 0x03, 0xd1, 0x41, 0xa6, 0xbc, 0x5f, 0xbd, 0x94, 0x29, 0xfe, 0x33, 0xd3, 0x40, 0xd3, 0xe8,
+    0x5b, 0xfa, 0x84, 0x89, 0x08, 0xd6, 0x0b, 0x56, 0x2f, 0x89, 0x4e, 0x8a, 0x33, 0x7d, 0xfd, 0x02,
+    0x82, 0x01, 0x01, 0x00, 0xc4, 0x95, 0x0f, 0x0d, 0x95, 0xdc, 0x51, 0xd7, 0x91, 0xad, 0x09, 0x4d,
+    0x22, 0x3b, 0x31, 0x13, 0xab, 0xc4, 0x9a, 0xf1, 0xe2, 0xa3, 0x61, 0xf8, 0x32, 0x42, 0xc8, 0xa0,
+    0x7a, 0x28, 0xc8, 0x74, 0x43, 0x15, 0xd3, 0xf1, 0xc4, 0x4c, 0x82, 0xed, 0xd0, 0xc2, 0x13, 0x98,
+    0xea, 0xcb, 0x75, 0x64, 0x8a, 0xe1, 0xf4, 0x88, 0x85, 0xf9, 0x23, 0x79, 0xd6, 0xff, 0xa0, 0x8c,
+    0xd1, 0x11, 0x26, 0xa9, 0x9d, 0x9a, 0xcd, 0x79, 0xb8, 0x94, 0x6e, 0x34, 0x86, 0x65, 0x91, 0x85,
+    0xf5, 0x11, 0x71, 0x8e, 0xc5, 0xe1, 0x43, 0x2b, 0x02, 0x71, 0x44, 0x26, 0xcd, 0xc7, 0x7e, 0x9e,
+    0xac, 0xad, 0xe3, 0x67, 0x35, 0x16, 0x1a, 0x64, 0x3d, 0xcd, 0x60, 0xdc, 0xd2, 0x92, 0x2c, 0x47,
+    0xaf, 0x5f, 0x4e, 0x19, 0x6c, 0x5d, 0x81, 0x24, 0x55, 0x5f, 0x67, 0xfc, 0xa1, 0x48, 0x04, 0x8d,
+    0xfe, 0x06, 0x2c, 0xba, 0xca, 0x33, 0x4f, 0x0d, 0x8d, 0xae, 0xb9, 0x6d, 0x73, 0xbe, 0x9f, 0x8e,
+    0x17, 0xc1, 0xc5, 0x5d, 0x6b, 0xd0, 0xb9, 0xa7, 0xe9, 0x9f, 0xe1, 0xdf, 0xba, 0x5c, 0xc1, 0x6a,
+    0x07, 0xdb, 0xaa, 0x8c, 0x6d, 0x22, 0x0c, 0x64, 0xc9, 0xdd, 0xa1, 0x14, 0xa0, 0xf0, 0x29, 0x05,
+    0x2b, 0x3a, 0x75, 0xb0, 0xd7, 0x3f, 0xe3, 0xb2, 0xed, 0x78, 0x21, 0xe5, 0xcd, 0x73, 0x07, 0xa1,
+    0xa9, 0x5f, 0xd1, 0xf7, 0xba, 0x87, 0x60, 0xc8, 0x45, 0x4b, 0x7c, 0x38, 0xfb, 0xf6, 0x5c, 0x88,
+    0xb0, 0x1c, 0xd2, 0x73, 0xba, 0x2c, 0x55, 0xc3, 0xb4, 0x77, 0xe4, 0x26, 0xae, 0x02, 0x5a, 0x2c,
+    0xff, 0xc4, 0xa0, 0x95, 0xf2, 0xba, 0x4e, 0x07, 0x79, 0xa2, 0x4b, 0x76, 0x5b, 0x85, 0x48, 0x9f,
+    0x2a, 0x0e, 0x79, 0xb9, 0x5f, 0xc0, 0xc3, 0x8e, 0x2a, 0x91, 0xf1, 0x2e, 0xf6, 0x5c, 0xa7, 0x49,
+    0xce, 0x36, 0x94, 0x31, 0x02, 0x82, 0x01, 0x00, 0x2a, 0xa4, 0x8e, 0x0c, 0x95, 0xe3, 0x3b, 0xab,
+    0x66, 0xd4, 0x63, 0x70, 0x48, 0x86, 0x33, 0x14, 0xde, 0xec, 0x98, 0x19, 0x62, 0x9b, 0xe3, 0x04,
+    0x99, 0x55, 0x2c, 0x56, 0xa9, 0x51, 0xe4, 0xfb, 0x64, 0xf3, 0x09, 0xed, 0x9c, 0x79, 0xd2, 0xa4,
+    0xaa, 0x28, 0xac, 0x9a, 0x6e, 0x7b, 0xe9, 0x7f, 0xda, 0x12, 0x90, 0xfa, 0xc4, 0xe9, 0x4d, 0x11,
+    0xcd, 0xb4, 0xc8, 0xea, 0xbf, 0x5f, 0x45, 0x0e, 0x72, 0xf4, 0x41, 0x8a, 0x29, 0xe2, 0xfe, 0x49,
+    0x32, 0x21, 0xe3, 0x84, 0x0d, 0xcf, 0x84, 0x47, 0xa3, 0x53, 0xb4, 0x40, 0xae, 0x63, 0xe9, 0x3b,
+    0x83, 0x71, 0x8e, 0x5c, 0xed, 0x31, 0xef, 0x4e, 0xc9, 0x1a, 0xf7, 0xd5, 0xcd, 0xf3, 0x42, 0x04,
+    0x78, 0xf2, 0x7b, 0xe0, 0x19, 0x27, 0x8b, 0xe7, 0x51, 0x5b, 0x66, 0x5f, 0x30, 0x5f, 0x10, 0xd3,
+    0xb5, 0x5d, 0xdb, 0xfa, 0xd6, 0x41, 0x16, 0xdc, 0x4e, 0x44, 0x15, 0xae, 0xf3, 0xb2, 0x34, 0xe4,
+    0xa5, 0xd6, 0xb5, 0xba, 0xb4, 0xc7, 0x7a, 0x26, 0xc9, 0xf2, 0x5f, 0x53, 0x6b, 0xd4, 0xf0, 0xb4,
+    0xa4, 0x78, 0xfc, 0x18, 0x4f, 0x12, 0x6c, 0x80, 0xd5, 0x37, 0x42, 0xac, 0x62, 0xc2, 0x70, 0xe6,
+    0xb2, 0x58, 0xa6, 0xb5, 0x6b, 0x33, 0x65, 0xec, 0xc2, 0x87, 0x97, 0xa9, 0xed, 0x12, 0xc1, 0xb9,
+    0x1b, 0x26, 0x56, 0x03, 0xef, 0x75, 0x18, 0x07, 0xbc, 0xc1, 0x74, 0x73, 0x13, 0xf2, 0x27, 0x29,
+    0xe1, 0xe3, 0xfe, 0x79, 0xf7, 0x5c, 0xc3, 0xfb, 0x5d, 0xc7, 0xcc, 0xb8, 0x1e, 0xfa, 0xcf, 0x9b,
+    0x84, 0x79, 0x45, 0xa6, 0x10, 0x9e, 0xcf, 0x9c, 0xf1, 0x56, 0x50, 0x5c, 0xbb, 0x55, 0xa3, 0xd3,
+    0x17, 0xeb, 0x32, 0x56, 0x61, 0xd1, 0x8f, 0xe6, 0xbb, 0x41, 0x60, 0x46, 0x83, 0x73, 0x18, 0x05,
+    0x3b, 0x36, 0x51, 0x99, 0x33, 0x4c, 0x03, 0xa1, 0x02, 0x82, 0x01, 0x01, 0x00, 0xee, 0x63, 0x70,
+    0x60, 0x30, 0xa4, 0xec, 0xe9, 0xfe, 0x3b, 0xdd, 0xcf, 0xc4, 0x9f, 0x5a, 0x83, 0xf3, 0x7f, 0x63,
+    0xeb, 0xcb, 0x29, 0xdb, 0xdc, 0x99, 0x9f, 0x6f, 0xf5, 0x4b, 0x59, 0x6f, 0x11, 0x5c, 0xf1, 0xec,
+    0xa0, 0x99, 0x90, 0x10, 0x8a, 0x43, 0x95, 0x18, 0xe9, 0x96, 0xf6, 0x89, 0xfd, 0xde, 0x89, 0xb2,
+    0xc6, 0x7e, 0xdc, 0x04, 0xbf, 0x8e, 0x36, 0x67, 0x34, 0xc2, 0xae, 0x30, 0x17, 0xec, 0x14, 0xe0,
+    0x42, 0x05, 0x0e, 0x7c, 0x65, 0x68, 0x40, 0x14, 0x6c, 0xa0, 0x48, 0x39, 0x4d, 0xce, 0xbe, 0x90,
+    0xdd, 0x21, 0x95, 0x34, 0x9b, 0xba, 0xd3, 0x06, 0x56, 0x90, 0x31, 0xb2, 0xef, 0x6e, 0x91, 0x71,
+    0xd2, 0xae, 0x77, 0x97, 0xc8, 0x84, 0x4e, 0x54, 0x83, 0x94, 0xca, 0x3b, 0x76, 0x8d, 0x84, 0x96,
+    0xe9, 0x9e, 0xf6, 0x3a, 0xbb, 0x59, 0xb0, 0xff, 0x7f, 0xc7, 0x0e, 0xb5, 0x31, 0x53, 0xdd, 0x0f,
+    0x59, 0x01, 0x8a, 0x27, 0x5a, 0xcb, 0xa7, 0x01, 0xf2, 0xc7, 0x6a, 0x15, 0xc8, 0x94, 0xf5, 0x34,
+    0x61, 0xfe, 0xdf, 0x65, 0xbc, 0x25, 0xc2, 0xc5, 0xce, 0xc3, 0x96, 0xe5, 0x56, 0xa1, 0xa9, 0x19,
+    0xbc, 0x7a, 0x05, 0x63, 0x93, 0xd5, 0x06, 0x44, 0x12, 0x6d, 0xcd, 0xef, 0x92, 0x56, 0x64, 0x2e,
+    0x65, 0xa6, 0x04, 0x3c, 0xbc, 0xe9, 0x49, 0x7e, 0x19, 0x2c, 0xf2, 0xcb, 0x33, 0x64, 0x8e, 0x11,
+    0x7f, 0x41, 0xdb, 0xf0, 0x19, 0x00, 0xac, 0xb9, 0x3b, 0x0c, 0x78, 0xdd, 0xf3, 0x1f, 0x38, 0x1f,
+    0x4d, 0xb3, 0xf9, 0xcc, 0xbb, 0xb6, 0x90, 0x93, 0xda, 0xbf, 0x2e, 0x89, 0xdb, 0xbc, 0x0c, 0xb7,
+    0x2f, 0x20, 0xc0, 0x05, 0xa2, 0x51, 0x9e, 0x3a, 0x87, 0x41, 0x46, 0x49, 0x5d, 0x7a, 0xac, 0xf3,
+    0x41, 0x6a, 0x42, 0x2e, 0x56, 0x09, 0x86, 0xf2, 0x2f, 0x39, 0x45, 0x6e, 0x7f,
+};
+const unsigned char test_rsa_4096_pub[] = {
+    0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xcc, 0x87, 0x25, 0xf6, 0xb3, 0x8d, 0x5d,
+    0x01, 0xae, 0xeb, 0x07, 0xd3, 0x6e, 0x03, 0xde, 0x4d, 0x31, 0xa0, 0x26, 0x1c, 0xe7, 0x4f, 0xe1,
+    0x1a, 0x89, 0x5e, 0xcf, 0xd1, 0x3d, 0x16, 0x8a, 0xee, 0x93, 0x2a, 0xf1, 0x35, 0xff, 0xbb, 0x84,
+    0x98, 0x77, 0x27, 0x38, 0x97, 0x08, 0x1f, 0x3f, 0x75, 0x93, 0xc1, 0x4a, 0xe8, 0x2b, 0xc2, 0x66,
+    0xc1, 0x05, 0x44, 0xf7, 0x26, 0xae, 0x1c, 0xcf, 0x13, 0x3d, 0x8a, 0x40, 0x18, 0xd3, 0x80, 0xdf,
+    0xa2, 0x52, 0x51, 0xc0, 0x11, 0x10, 0x7b, 0x75, 0x13, 0xa9, 0x43, 0x34, 0x6a, 0xa0, 0xe0, 0xde,
+    0xc1, 0x1d, 0x8d, 0x7f, 0xa2, 0x56, 0x44, 0x65, 0x3c, 0x11, 0x8d, 0xaa, 0xbc, 0xe6, 0xd4, 0x1f,
+    0x06, 0x6f, 0x66, 0x21, 0x76, 0x88, 0x01, 0x47, 0x80, 0x55, 0x78, 0x0e, 0x91, 0xb6, 0x8e, 0xa3,
+    0xc9, 0x58, 0x56, 0xd1, 0x72, 0xa8, 0x90, 0x32, 0xb3, 0x9c, 0x82, 0x4e, 0x8b, 0x7d, 0xc1, 0xa3,
+    0xf8, 0xae, 0xe4, 0xf6, 0xb3, 0x68, 0xba, 0xa3, 0xcd, 0x68, 0xf5, 0x0d, 0x52, 0x68, 0x01, 0x17,
+    0xe9, 0xb9, 0x13, 0xd7, 0xf8, 0xc8, 0x52, 0xa0, 0xd1, 0x00, 0x8e, 0x8b, 0x87, 0xa5, 0xc9, 0x7e,
+    0x37, 0xaf, 0xc1, 0x1a, 0x08, 0x05, 0x50, 0x55, 0x7b, 0x8b, 0x4d, 0xcb, 0xd8, 0xe1, 0x92, 0xed,
+    0x33, 0x66, 0xd8, 0x3a, 0x09, 0xd2, 0x7c, 0x77, 0xe1, 0x50, 0xf6, 0x68, 0x55, 0xb5, 0xdc, 0xfd,
+    0xb2, 0xdf, 0x15, 0x1b, 0xd7, 0xf4, 0x44, 0x25, 0x0e, 0xaf, 0x6f, 0xe3, 0xf2, 0x36, 0x82, 0x6c,
+    0x81, 0xfa, 0x84, 0x81, 0x01, 0xbf, 0xaa, 0xd5, 0x35, 0xff, 0xb5, 0x22, 0xd6, 0xff, 0x97, 0xc9,
+    0xdd, 0x1e, 0x43, 0xb8, 0x2c, 0xce, 0x29, 0x21, 0xd1, 0x53, 0xc1, 0x54, 0x50, 0xc4, 0x72, 0x4f,
+    0xfd, 0x3e, 0xfd, 0xca, 0x57, 0x8e, 0x01, 0x36, 0x50, 0xa0, 0x3a, 0x5c, 0xf5, 0x01, 0xfc, 0x58,
+    0x60, 0x0f, 0xb5, 0xc8, 0x60, 0xc0, 0xef, 0x0c, 0xfe, 0x0a, 0xc0, 0x71, 0x2d, 0x44, 0x13, 0x13,
+    0xdc, 0xa4, 0x1a, 0x4d, 0x7d, 0x41, 0x1e, 0x6c, 0x83, 0xb2, 0x15, 0x17, 0x49, 0xd2, 0x8b, 0xe4,
+    0x69, 0x2f, 0x62, 0x37, 0x3d, 0xb0, 0x7e, 0x4a, 0x79, 0x05, 0x1c, 0x56, 0x82, 0xec, 0x20, 0xd4,
+    0x91, 0xc4, 0xcf, 0xc7, 0xbc, 0x14, 0x0f, 0x35, 0xfa, 0x15, 0xe5, 0xa1, 0xfa, 0x75, 0x6d, 0x65,
+    0xb8, 0xef, 0x93, 0xad, 0xdf, 0x4c, 0x47, 0xc4, 0xa3, 0x5b, 0x18, 0x4f, 0x22, 0xa1, 0xef, 0x08,
+    0x99, 0x48, 0xf9, 0x46, 0xf6, 0xfa, 0xeb, 0x64, 0x70, 0xf2, 0x67, 0x46, 0xe6, 0x58, 0xcf, 0x9b,
+    0x41, 0x77, 0x41, 0x78, 0x42, 0xe6, 0xd3, 0x73, 0x55, 0x80, 0x89, 0xaf, 0xf7, 0x21, 0xb9, 0x30,
+    0xe9, 0xec, 0x61, 0xb4, 0xf6, 0xa0, 0x2c, 0x05, 0x2c, 0x69, 0x24, 0xd3, 0x9a, 0x5b, 0xbb, 0x15,
+    0xed, 0x11, 0x06, 0xc4, 0x01, 0x0f, 0x4d, 0xd6, 0x9c, 0x79, 0xd0, 0x42, 0xc8, 0xb3, 0x16, 0x61,
+    0xb1, 0xee, 0x48, 0x6b, 0xc6, 0x9d, 0xb5, 0xf2, 0xf0, 0x7a, 0x50, 0xd8, 0x5b, 0x20, 0x69, 0x9d,
+    0x60, 0x13, 0x15, 0x62, 0x5b, 0xb8, 0x69, 0x62, 0x9c, 0x7f, 0x4c, 0x5d, 0x48, 0xb2, 0x11, 0xd0,
+    0x97, 0xf4, 0x38, 0xac, 0xec, 0x95, 0x97, 0x3a, 0x38, 0xd4, 0x21, 0x09, 0x0a, 0xf0, 0xf1, 0x34,
+    0x84, 0xe4, 0xe9, 0x4b, 0x8c, 0xb5, 0xef, 0xc1, 0x85, 0x07, 0xf4, 0xb9, 0x31, 0xdf, 0x39, 0x98,
+    0x7f, 0xfb, 0x28, 0x30, 0x29, 0x3e, 0x4d, 0xa3, 0x81, 0xaa, 0xf7, 0x0b, 0x32, 0x92, 0x95, 0x2e,
+    0xf9, 0x34, 0xe2, 0xb4, 0x0f, 0xde, 0xbb, 0xa3, 0xd9, 0x70, 0x1b, 0x76, 0xe1, 0xbe, 0x54, 0x82,
+    0x74, 0xb2, 0x60, 0x2d, 0x88, 0x85, 0x37, 0x48, 0x2d, 0x02, 0x03, 0x01, 0x00, 0x01,
+};
+
+struct predefined_key_element {
+    int group_id;  // EC group ID; 0 for RSA keys
+    int keybits;  // bits size of RSA key; 0 for EC keys
+    const unsigned char *priv_key;
+    size_t priv_key_len;
+    const unsigned char *pub_key;
+    size_t pub_key_len;
+};
+
+struct predefined_key_element predefined_keys[] = {
+    { MBEDTLS_ECP_DP_SECP192K1, 0,
+      test_ec_secp192k1_priv, sizeof(test_ec_secp192k1_priv),
+      test_ec_secp192k1_pub, sizeof(test_ec_secp192k1_pub) },
+    { MBEDTLS_ECP_DP_SECP256K1, 0,
+      test_ec_secp256k1_priv, sizeof(test_ec_secp256k1_priv),
+      test_ec_secp256k1_pub, sizeof(test_ec_secp256k1_pub) },
+    { MBEDTLS_ECP_DP_SECP192R1, 0,
+      test_ec_secp192r1_priv, sizeof(test_ec_secp192r1_priv),
+      test_ec_secp192r1_pub, sizeof(test_ec_secp192r1_pub) },
+    { MBEDTLS_ECP_DP_SECP224R1, 0,
+      test_ec_secp224r1_priv, sizeof(test_ec_secp224r1_priv),
+      test_ec_secp224r1_pub, sizeof(test_ec_secp224r1_pub) },
+    { MBEDTLS_ECP_DP_SECP256R1, 0,
+      test_ec_secp256r1_priv, sizeof(test_ec_secp256r1_priv),
+      test_ec_secp256r1_pub, sizeof(test_ec_secp256r1_pub) },
+    { MBEDTLS_ECP_DP_SECP384R1, 0,
+      test_ec_secp384r1_priv, sizeof(test_ec_secp384r1_priv),
+      test_ec_secp384r1_pub, sizeof(test_ec_secp384r1_pub) },
+    { MBEDTLS_ECP_DP_SECP521R1, 0,
+      test_ec_secp521r1_priv, sizeof(test_ec_secp521r1_priv),
+      test_ec_secp521r1_pub, sizeof(test_ec_secp521r1_pub) },
+    { MBEDTLS_ECP_DP_BP256R1, 0,
+      test_ec_bp256r1_priv, sizeof(test_ec_bp256r1_priv),
+      test_ec_bp256r1_pub, sizeof(test_ec_bp256r1_pub) },
+    { MBEDTLS_ECP_DP_BP384R1, 0,
+      test_ec_bp384r1_priv, sizeof(test_ec_bp384r1_priv),
+      test_ec_bp384r1_pub, sizeof(test_ec_bp384r1_pub) },
+    { MBEDTLS_ECP_DP_BP512R1, 0,
+      test_ec_bp512r1_priv, sizeof(test_ec_bp512r1_priv),
+      test_ec_bp512r1_pub, sizeof(test_ec_bp512r1_pub) },
+    { MBEDTLS_ECP_DP_CURVE25519, 0,
+      test_ec_curve25519_priv, sizeof(test_ec_curve25519_priv),
+      test_ec_curve25519_pub, sizeof(test_ec_curve25519_pub) },
+    { MBEDTLS_ECP_DP_CURVE448, 0,
+      test_ec_curve448_priv, sizeof(test_ec_curve448_priv),
+      test_ec_curve448_pub, sizeof(test_ec_curve448_pub) },
+    { 0, 1024,
+      test_rsa_1024_priv, sizeof(test_rsa_1024_priv),
+      test_rsa_1024_pub, sizeof(test_rsa_1024_pub) },
+    { 0, 1026,
+      test_rsa_1026_priv, sizeof(test_rsa_1026_priv),
+      test_rsa_1026_pub, sizeof(test_rsa_1026_pub) },
+    { 0, 1028,
+      test_rsa_1028_priv, sizeof(test_rsa_1028_priv),
+      test_rsa_1028_pub, sizeof(test_rsa_1028_pub) },
+    { 0, 1030,
+      test_rsa_1030_priv, sizeof(test_rsa_1030_priv),
+      test_rsa_1030_pub, sizeof(test_rsa_1030_pub) },
+    { 0, 1536,
+      test_rsa_1536_priv, sizeof(test_rsa_1536_priv),
+      test_rsa_1536_pub, sizeof(test_rsa_1536_pub) },
+    { 0, 2048,
+      test_rsa_2048_priv, sizeof(test_rsa_2048_priv),
+      test_rsa_2048_pub, sizeof(test_rsa_2048_pub) },
+    { 0, 4096,
+      test_rsa_4096_priv, sizeof(test_rsa_4096_priv),
+      test_rsa_4096_pub, sizeof(test_rsa_4096_pub) },
+};
diff --git a/tests/src/test_memory.c b/tests/src/test_memory.c
new file mode 100644
index 0000000..ac9dde6
--- /dev/null
+++ b/tests/src/test_memory.c
@@ -0,0 +1,60 @@
+/**
+ * \file memory.c
+ *
+ * \brief   Helper functions related to testing memory management.
+ */
+
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include <test/helpers.h>
+#include <test/macros.h>
+#include <test/memory.h>
+
+#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
+#include <sanitizer/asan_interface.h>
+#include <stdint.h>
+#endif
+
+#if defined(MBEDTLS_TEST_MEMORY_CAN_POISON)
+
+_Thread_local unsigned int mbedtls_test_memory_poisoning_count = 0;
+
+static void align_for_asan(const unsigned char **p_ptr, size_t *p_size)
+{
+    uintptr_t start = (uintptr_t) *p_ptr;
+    uintptr_t end = start + (uintptr_t) *p_size;
+    /* ASan can only poison regions with 8-byte alignment, and only poisons a
+     * region if it's fully within the requested range. We want to poison the
+     * whole requested region and don't mind a few extra bytes. Therefore,
+     * align start down to an 8-byte boundary, and end up to an 8-byte
+     * boundary. */
+    start = start & ~(uintptr_t) 7;
+    end = (end + 7) & ~(uintptr_t) 7;
+    *p_ptr = (const unsigned char *) start;
+    *p_size = end - start;
+}
+
+void mbedtls_test_memory_poison(const unsigned char *ptr, size_t size)
+{
+    if (mbedtls_test_memory_poisoning_count == 0) {
+        return;
+    }
+    if (size == 0) {
+        return;
+    }
+    align_for_asan(&ptr, &size);
+    __asan_poison_memory_region(ptr, size);
+}
+
+void mbedtls_test_memory_unpoison(const unsigned char *ptr, size_t size)
+{
+    if (size == 0) {
+        return;
+    }
+    align_for_asan(&ptr, &size);
+    __asan_unpoison_memory_region(ptr, size);
+}
+#endif /* Memory poisoning */
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index fd2fc0a..3549a7b 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -1629,7 +1629,7 @@
     fi
 
     if [ "$LIST_TESTS" -gt 0 ]; then
-        printf "%s\n" "$NAME"
+        printf "%s\n" "${TEST_SUITE_NAME:-ssl-opt};$NAME"
         return
     fi
 
@@ -2047,64 +2047,6 @@
             -s "Protocol is DTLSv1.2" \
             -s "Ciphersuite is TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256"
 
-# GnuTLS can be setup to send a ClientHello containing a supported versions
-# extension proposing TLS 1.2 (preferred) and then TLS 1.3. In that case,
-# a TLS 1.3 and TLS 1.2 capable server is supposed to negotiate TLS 1.2 and
-# to indicate in the ServerHello that it downgrades from TLS 1.3. The GnuTLS
-# client then detects the downgrade indication and aborts the handshake even
-# if TLS 1.2 was its preferred version. Keeping the test even if the
-# handshake fails eventually as it exercices parts of the Mbed TLS
-# implementation that are otherwise not exercised.
-requires_gnutls_tls1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_SRV_C
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
-run_test    "Server selecting TLS 1.2 over TLS 1.3" \
-            "$P_SRV crt_file=data_files/server5.crt key_file=data_files/server5.key" \
-            "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.3" \
-            1 \
-            -c "Detected downgrade to TLS 1.2 from TLS 1.3"
-
-requires_gnutls_tls1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_SRV_C
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_3
-requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
-run_test    "Server selecting TLS 1.2" \
-            "$P_SRV crt_file=data_files/server5.crt key_file=data_files/server5.key" \
-            "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.3" \
-            0 \
-            -s "Protocol is TLSv1.2" \
-            -c "HTTP/1.0 200 OK"
-
-requires_gnutls_tls1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_SRV_C
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
-requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
-run_test    "Server selecting TLS 1.3, over TLS 1.2 if supported" \
-            "$P_SRV crt_file=data_files/server5.crt key_file=data_files/server5.key" \
-            "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:%DISABLE_TLS13_COMPAT_MODE" \
-            0 \
-            -s "Protocol is TLSv1.3" \
-            -c "HTTP/1.0 200 OK"
-
-requires_gnutls_tls1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_SRV_C
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
-requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
-requires_config_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
-run_test    "Server selecting TLS 1.3, over TLS 1.2 if supported - compat mode enabled" \
-            "$P_SRV crt_file=data_files/server5.crt key_file=data_files/server5.key" \
-            "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2" \
-            0 \
-            -s "Protocol is TLSv1.3" \
-            -c "HTTP/1.0 200 OK"
-
 requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
 run_test    "TLS client auth: required" \
             "$P_SRV auth_mode=required" \
@@ -3789,6 +3731,7 @@
 
 # Tests for Session Tickets
 
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: basic" \
             "$P_SRV debug_level=3 tickets=1" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -3803,6 +3746,7 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: manual rotation" \
             "$P_SRV debug_level=3 tickets=1 ticket_rotate=1" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -3817,6 +3761,7 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: cache disabled" \
             "$P_SRV debug_level=3 tickets=1 cache_max=0" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -3831,6 +3776,7 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: timeout" \
             "$P_SRV debug_level=3 tickets=1 cache_max=0 ticket_timeout=1" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1 reco_delay=2000" \
@@ -3845,6 +3791,7 @@
             -S "a session has been resumed" \
             -C "a session has been resumed"
 
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: session copy" \
             "$P_SRV debug_level=3 tickets=1 cache_max=0" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1 reco_mode=0" \
@@ -3860,6 +3807,7 @@
             -c "a session has been resumed"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: openssl server" \
             "$O_SRV -tls1_2" \
             "$P_CLI debug_level=3 tickets=1 reconnect=1" \
@@ -3870,6 +3818,7 @@
             -c "a session has been resumed"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: openssl client" \
             "$P_SRV debug_level=3 tickets=1" \
             "( $O_CLI -sess_out $SESSION; \
@@ -3883,6 +3832,7 @@
             -s "a session has been resumed"
 
 requires_cipher_enabled "AES" "GCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: AES-128-GCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=AES-128-GCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -3898,6 +3848,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "AES" "GCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: AES-192-GCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=AES-192-GCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -3913,6 +3864,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "AES" "CCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: AES-128-CCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=AES-128-CCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -3928,6 +3880,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "AES" "CCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: AES-192-CCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=AES-192-CCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -3943,6 +3896,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "AES" "CCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: AES-256-CCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=AES-256-CCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -3958,6 +3912,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "CAMELLIA" "CCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: CAMELLIA-128-CCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=CAMELLIA-128-CCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -3973,6 +3928,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "CAMELLIA" "CCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: CAMELLIA-192-CCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=CAMELLIA-192-CCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -3988,6 +3944,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "CAMELLIA" "CCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: CAMELLIA-256-CCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=CAMELLIA-256-CCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -4003,6 +3960,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "ARIA" "GCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: ARIA-128-GCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=ARIA-128-GCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -4018,6 +3976,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "ARIA" "GCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: ARIA-192-GCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=ARIA-192-GCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -4033,6 +3992,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "ARIA" "GCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: ARIA-256-GCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=ARIA-256-GCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -4048,6 +4008,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "ARIA" "CCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: ARIA-128-CCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=ARIA-128-CCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -4063,6 +4024,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "ARIA" "CCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: ARIA-192-CCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=ARIA-192-CCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -4078,6 +4040,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "ARIA" "CCM"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: ARIA-256-CCM" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=ARIA-256-CCM" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -4093,6 +4056,7 @@
             -c "a session has been resumed"
 
 requires_cipher_enabled "CHACHA20"
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets: CHACHA20-POLY1305" \
             "$P_SRV debug_level=3 tickets=1 ticket_aead=CHACHA20-POLY1305" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -4110,6 +4074,7 @@
 # Tests for Session Tickets with DTLS
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets, DTLS: basic" \
             "$P_SRV debug_level=3 dtls=1 tickets=1" \
             "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1 skip_close_notify=1" \
@@ -4125,6 +4090,7 @@
             -c "a session has been resumed"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets, DTLS: cache disabled" \
             "$P_SRV debug_level=3 dtls=1 tickets=1 cache_max=0" \
             "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1 skip_close_notify=1" \
@@ -4140,6 +4106,7 @@
             -c "a session has been resumed"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets, DTLS: timeout" \
             "$P_SRV debug_level=3 dtls=1 tickets=1 cache_max=0 ticket_timeout=1" \
             "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1 skip_close_notify=1 reco_delay=2000" \
@@ -4155,6 +4122,7 @@
             -C "a session has been resumed"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets, DTLS: session copy" \
             "$P_SRV debug_level=3 dtls=1 tickets=1 cache_max=0" \
             "$P_CLI debug_level=3 dtls=1 tickets=1 reconnect=1 skip_close_notify=1 reco_mode=0" \
@@ -4170,6 +4138,7 @@
             -c "a session has been resumed"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets, DTLS: openssl server" \
             "$O_SRV -dtls" \
             "$P_CLI dtls=1 debug_level=3 tickets=1 reconnect=1" \
@@ -4183,6 +4152,7 @@
 # probability with OpenSSL 1.0.2g on the CI, see #5012.
 requires_openssl_next
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using tickets, DTLS: openssl client" \
             "$P_SRV dtls=1 debug_level=3 tickets=1" \
             "( $O_NEXT_CLI -dtls -sess_out $SESSION; \
@@ -4198,6 +4168,7 @@
 # Tests for Session Resume based on session-ID and cache
 
 requires_config_enabled MBEDTLS_SSL_CACHE_C
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using cache: tickets enabled on client" \
             "$P_SRV debug_level=3 tickets=0" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=1 reconnect=1" \
@@ -4213,6 +4184,7 @@
             -c "a session has been resumed"
 
 requires_config_enabled MBEDTLS_SSL_CACHE_C
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using cache: tickets enabled on server" \
             "$P_SRV debug_level=3 tickets=1" \
             "$P_CLI force_version=tls12 debug_level=3 tickets=0 reconnect=1" \
@@ -4304,6 +4276,7 @@
             -c "a session has been resumed"
 
 requires_config_enabled MBEDTLS_SSL_CACHE_C
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using cache: openssl client" \
             "$P_SRV force_version=tls12 debug_level=3 tickets=0" \
             "( $O_CLI -sess_out $SESSION; \
@@ -4353,6 +4326,7 @@
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 requires_config_enabled MBEDTLS_SSL_CACHE_C
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using cache, DTLS: tickets enabled on client" \
             "$P_SRV dtls=1 debug_level=3 tickets=0" \
             "$P_CLI dtls=1 debug_level=3 tickets=1 reconnect=1 skip_close_notify=1" \
@@ -4369,6 +4343,7 @@
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 requires_config_enabled MBEDTLS_SSL_CACHE_C
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using cache, DTLS: tickets enabled on server" \
             "$P_SRV dtls=1 debug_level=3 tickets=1" \
             "$P_CLI dtls=1 debug_level=3 tickets=0 reconnect=1 skip_close_notify=1" \
@@ -4454,6 +4429,7 @@
 requires_openssl_next
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 requires_config_enabled MBEDTLS_SSL_CACHE_C
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Session resume using cache, DTLS: openssl client" \
             "$P_SRV dtls=1 debug_level=3 tickets=0" \
             "( $O_NEXT_CLI -dtls -sess_out $SESSION; \
@@ -6714,6 +6690,7 @@
             -c "Read from server: .* bytes read"
 
 requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Non-blocking I/O: ticket" \
             "$P_SRV nbio=2 tickets=1 auth_mode=none" \
             "$P_CLI nbio=2 tickets=1" \
@@ -6723,6 +6700,7 @@
             -c "Read from server: .* bytes read"
 
 requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Non-blocking I/O: ticket + client auth" \
             "$P_SRV nbio=2 tickets=1 auth_mode=required" \
             "$P_CLI nbio=2 tickets=1" \
@@ -6732,6 +6710,7 @@
             -c "Read from server: .* bytes read"
 
 requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Non-blocking I/O: TLS 1.2 + ticket + client auth + resume" \
             "$P_SRV nbio=2 tickets=1 auth_mode=required" \
             "$P_CLI force_version=tls12 nbio=2 tickets=1 reconnect=1" \
@@ -6743,6 +6722,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
 requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Non-blocking I/O: TLS 1.3 + ticket + client auth + resume" \
             "$P_SRV nbio=2 tickets=1 auth_mode=required" \
             "$P_CLI nbio=2 tickets=1 reconnect=1" \
@@ -6752,6 +6732,7 @@
             -c "Read from server: .* bytes read"
 
 requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Non-blocking I/O: TLS 1.2 + ticket + resume" \
             "$P_SRV nbio=2 tickets=1 auth_mode=none" \
             "$P_CLI force_version=tls12 nbio=2 tickets=1 reconnect=1" \
@@ -6763,6 +6744,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
 requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Non-blocking I/O: TLS 1.3 + ticket + resume" \
             "$P_SRV nbio=2 tickets=1 auth_mode=none" \
             "$P_CLI nbio=2 tickets=1 reconnect=1" \
@@ -6801,6 +6783,7 @@
             -c "Read from server: .* bytes read"
 
 requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Event-driven I/O: ticket" \
             "$P_SRV event=1 tickets=1 auth_mode=none" \
             "$P_CLI event=1 tickets=1" \
@@ -6810,6 +6793,7 @@
             -c "Read from server: .* bytes read"
 
 requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Event-driven I/O: ticket + client auth" \
             "$P_SRV event=1 tickets=1 auth_mode=required" \
             "$P_CLI event=1 tickets=1" \
@@ -6819,6 +6803,7 @@
             -c "Read from server: .* bytes read"
 
 requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Event-driven I/O: TLS 1.2 + ticket + client auth + resume" \
             "$P_SRV event=1 tickets=1 auth_mode=required" \
             "$P_CLI force_version=tls12 event=1 tickets=1 reconnect=1" \
@@ -6830,6 +6815,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
 requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Event-driven I/O: TLS 1.3 + ticket + client auth + resume" \
             "$P_SRV event=1 tickets=1 auth_mode=required" \
             "$P_CLI event=1 tickets=1 reconnect=1" \
@@ -6839,6 +6825,7 @@
             -c "Read from server: .* bytes read"
 
 requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Event-driven I/O: TLS 1.2 + ticket + resume" \
             "$P_SRV event=1 tickets=1 auth_mode=none" \
             "$P_CLI force_version=tls12 event=1 tickets=1 reconnect=1" \
@@ -6850,6 +6837,7 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
 requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Event-driven I/O: TLS 1.3 + ticket + resume" \
             "$P_SRV event=1 tickets=1 auth_mode=none" \
             "$P_CLI event=1 tickets=1 reconnect=1" \
@@ -6882,6 +6870,7 @@
             -c "Read from server: .* bytes read"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Event-driven I/O, DTLS: ticket" \
             "$P_SRV dtls=1 event=1 tickets=1 auth_mode=none" \
             "$P_CLI dtls=1 event=1 tickets=1" \
@@ -6889,6 +6878,7 @@
             -c "Read from server: .* bytes read"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Event-driven I/O, DTLS: ticket + client auth" \
             "$P_SRV dtls=1 event=1 tickets=1 auth_mode=required" \
             "$P_CLI dtls=1 event=1 tickets=1" \
@@ -6896,6 +6886,7 @@
             -c "Read from server: .* bytes read"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Event-driven I/O, DTLS: ticket + client auth + resume" \
             "$P_SRV dtls=1 event=1 tickets=1 auth_mode=required" \
             "$P_CLI dtls=1 event=1 tickets=1 reconnect=1 skip_close_notify=1" \
@@ -6903,6 +6894,7 @@
             -c "Read from server: .* bytes read"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "Event-driven I/O, DTLS: ticket + resume" \
             "$P_SRV dtls=1 event=1 tickets=1 auth_mode=none" \
             "$P_CLI dtls=1 event=1 tickets=1 reconnect=1 skip_close_notify=1" \
@@ -6929,39 +6921,470 @@
             0 \
             -c "Read from server: .* bytes read"
 
-# Tests for version negotiation
+# Tests for version negotiation. Some information to ease the understanding
+# of the version negotiation test titles below:
+# . 1.2/1.3 means that only TLS 1.2/TLS 1.3 is enabled.
+# . 1.2+1.3 means that both TLS 1.2 and TLS 1.3 are enabled.
+# . 1.2+(1.3)/(1.2)+1.3 means that TLS 1.2/1.3 is enabled and that
+#   TLS 1.3/1.2 may be enabled or not.
+# . max=1.2 means that both TLS 1.2 and TLS 1.3 are enabled at build time but
+#   TLS 1.3 is disabled at runtime (maximum negotiable version is TLS 1.2).
+# . min=1.3 means that both TLS 1.2 and TLS 1.3 are enabled at build time but
+#   TLS 1.2 is disabled at runtime (minimum negotiable version is TLS 1.3).
 
-run_test    "Version check: all -> 1.2" \
+# Tests for version negotiation, MbedTLS client and server
+
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Version nego m->m: cli 1.2, srv 1.2 -> 1.2" \
             "$P_SRV" \
-            "$P_CLI force_version=tls12" \
+            "$P_CLI" \
             0 \
             -S "mbedtls_ssl_handshake returned" \
             -C "mbedtls_ssl_handshake returned" \
             -s "Protocol is TLSv1.2" \
             -c "Protocol is TLSv1.2"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-run_test    "Not supported version check: cli TLS 1.0" \
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Version nego m->m: cli max=1.2, srv max=1.2 -> 1.2" \
+            "$P_SRV max_version=tls12" \
+            "$P_CLI max_version=tls12" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -C "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.2" \
+            -c "Protocol is TLSv1.2"
+
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "Version nego m->m: cli 1.3, srv 1.3 -> 1.3" \
+            "$P_SRV" \
+            "$P_CLI" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -C "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3" \
+            -c "Protocol is TLSv1.3"
+
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+run_test    "Version nego m->m: cli min=1.3, srv min=1.3 -> 1.3" \
+            "$P_SRV min_version=tls13" \
+            "$P_CLI min_version=tls13" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -C "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3" \
+            -c "Protocol is TLSv1.3"
+
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+run_test    "Version nego m->m: cli 1.2+1.3, srv 1.2+1.3 -> 1.3" \
+            "$P_SRV" \
+            "$P_CLI" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -C "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3" \
+            -c "Protocol is TLSv1.3"
+
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+run_test    "Version nego m->m: cli 1.2+1.3, srv min=1.3 -> 1.3" \
+            "$P_SRV min_version=tls13" \
+            "$P_CLI" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -C "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3" \
+            -c "Protocol is TLSv1.3"
+
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Version nego m->m: cli 1.2+1.3, srv max=1.2 -> 1.2" \
+            "$P_SRV max_version=tls12" \
+            "$P_CLI" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -C "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.2" \
+            -c "Protocol is TLSv1.2"
+
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Version nego m->m: cli max=1.2, srv 1.2+1.3 -> 1.2" \
+            "$P_SRV" \
+            "$P_CLI max_version=tls12" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -C "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.2" \
+            -c "Protocol is TLSv1.2"
+
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+run_test    "Version nego m->m: cli min=1.3, srv 1.2+1.3 -> 1.3" \
+            "$P_SRV" \
+            "$P_CLI min_version=tls13" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -C "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3" \
+            -c "Protocol is TLSv1.3"
+
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+run_test    "Not supported version m->m: cli max=1.2, srv min=1.3" \
+            "$P_SRV min_version=tls13" \
+            "$P_CLI max_version=tls12" \
+            1 \
+            -s "Handshake protocol not within min/max boundaries" \
+            -S "Protocol is TLSv1.2" \
+            -C "Protocol is TLSv1.2" \
+            -S "Protocol is TLSv1.3" \
+            -C "Protocol is TLSv1.3"
+
+requires_all_configs_enabled MBEDTLS_SSL_CLI_C MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+run_test    "Not supported version m->m: cli min=1.3, srv max=1.2" \
+            "$P_SRV max_version=tls12" \
+            "$P_CLI min_version=tls13" \
+            1 \
+            -s "The handshake negotiation failed" \
+            -S "Protocol is TLSv1.2" \
+            -C "Protocol is TLSv1.2" \
+            -S "Protocol is TLSv1.3" \
+            -C "Protocol is TLSv1.3"
+
+# Tests of version negotiation on server side against GnuTLS client
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C MBEDTLS_SSL_PROTO_TLS1_2
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Server version nego G->m: cli 1.2, srv 1.2+(1.3) -> 1.2" \
+            "$P_SRV" \
+            "$G_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.2"
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Server version nego G->m: cli 1.2, srv max=1.2 -> 1.2" \
+            "$P_SRV max_version=tls12" \
+            "$G_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.2"
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+run_test    "Server version nego G->m: cli 1.3, srv (1.2)+1.3 -> 1.3" \
+            "$P_SRV" \
+            "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3"
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+run_test    "Server version nego G->m: cli 1.3, srv min=1.3 -> 1.3" \
+            "$P_SRV min_version=tls13" \
+            "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3"
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+run_test    "Server version nego G->m: cli 1.2+1.3, srv (1.2)+1.3 -> 1.3" \
+            "$P_SRV" \
+            "$G_NEXT_CLI localhost --priority=NORMAL" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3"
+
+requires_gnutls_next_disable_tls13_compat
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+run_test    "Server version nego G->m (no compat): cli 1.2+1.3, srv (1.2)+1.3 -> 1.3" \
+            "$P_SRV" \
+            "$G_NEXT_CLI localhost --priority=NORMAL:%DISABLE_TLS13_COMPAT_MODE" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3"
+
+# GnuTLS can be setup to send a ClientHello containing a supported versions
+# extension proposing TLS 1.2 (preferred) and then TLS 1.3. In that case,
+# a TLS 1.3 and TLS 1.2 capable server is supposed to negotiate TLS 1.2 and
+# to indicate in the ServerHello that it downgrades from TLS 1.3. The GnuTLS
+# client then detects the downgrade indication and aborts the handshake even
+# if TLS 1.2 was its preferred version. Keeping the test even if the
+# handshake fails eventually as it exercices parts of the Mbed TLS
+# implementation that are otherwise not exercised.
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+run_test    "Server version nego G->m: cli 1.2+1.3 (1.2 preferred!), srv 1.2+1.3 -> 1.2" \
+            "$P_SRV" \
+            "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.3" \
+            1 \
+            -c "Detected downgrade to TLS 1.2 from TLS 1.3"
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+run_test    "Server version nego G->m: cli 1.2+1.3, srv min=1.3 -> 1.3" \
+            "$P_SRV min_version=tls13" \
+            "$G_NEXT_CLI localhost --priority=NORMAL" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3"
+
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Server version nego G->m: cli 1.2+1.3, srv 1.2 -> 1.2" \
+            "$P_SRV" \
+            "$G_NEXT_CLI localhost --priority=NORMAL" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.2"
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Server version nego G->m: cli 1.2+1.3, max=1.2 -> 1.2" \
+            "$P_SRV max_version=tls12" \
+            "$G_NEXT_CLI localhost --priority=NORMAL" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.2"
+
+requires_config_enabled MBEDTLS_SSL_SRV_C
+run_test    "Not supported version G->m: cli 1.0, (1.2)+(1.3)" \
             "$P_SRV" \
             "$G_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.0" \
             1 \
             -s "Handshake protocol not within min/max boundaries" \
-            -c "Error in protocol version" \
-            -S "Protocol is TLSv1.0" \
-            -C "Handshake was completed"
+            -S "Protocol is TLSv1.0"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-run_test    "Not supported version check: cli TLS 1.1" \
+requires_config_enabled MBEDTLS_SSL_SRV_C
+run_test    "Not supported version G->m: cli 1.1, (1.2)+(1.3)" \
             "$P_SRV" \
             "$G_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.1" \
             1 \
             -s "Handshake protocol not within min/max boundaries" \
-            -c "Error in protocol version" \
-            -S "Protocol is TLSv1.1" \
-            -C "Handshake was completed"
+            -S "Protocol is TLSv1.1"
+
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "Not supported version G->m: cli 1.2, srv 1.3" \
+            "$P_SRV" \
+            "$G_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2" \
+            1 \
+            -s "Handshake protocol not within min/max boundaries" \
+            -S "Protocol is TLSv1.2"
+
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_3
+run_test    "Not supported version G->m: cli 1.3, srv 1.2" \
+            "$P_SRV" \
+            "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3" \
+            1 \
+            -S "Handshake protocol not within min/max boundaries" \
+            -s "The handshake negotiation failed" \
+            -S "Protocol is TLSv1.3"
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+run_test    "Not supported version G->m: cli 1.2, srv min=1.3" \
+            "$P_SRV min_version=tls13" \
+            "$G_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.2" \
+            1 \
+            -s "Handshake protocol not within min/max boundaries" \
+            -S "Protocol is TLSv1.2"
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+run_test    "Not supported version G->m: cli 1.3, srv max=1.2" \
+            "$P_SRV max_version=tls12" \
+            "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3" \
+            1 \
+            -S "Handshake protocol not within min/max boundaries" \
+            -s "The handshake negotiation failed" \
+            -S "Protocol is TLSv1.3"
+
+# Tests of version negotiation on server side against OpenSSL client
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C MBEDTLS_SSL_PROTO_TLS1_2
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Server version nego O->m: cli 1.2, srv 1.2+(1.3) -> 1.2" \
+            "$P_SRV" \
+            "$O_NEXT_CLI -tls1_2" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.2"
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Server version nego O->m: cli 1.2, srv max=1.2 -> 1.2" \
+            "$P_SRV max_version=tls12" \
+            "$O_NEXT_CLI -tls1_2" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.2"
+
+requires_openssl_tls1_3_with_compatible_ephemeral
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+run_test    "Server version nego O->m: cli 1.3, srv (1.2)+1.3 -> 1.3" \
+            "$P_SRV" \
+            "$O_NEXT_CLI -tls1_3" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3"
+
+requires_openssl_tls1_3_with_compatible_ephemeral
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+run_test    "Server version nego O->m: cli 1.3, srv min=1.3 -> 1.3" \
+            "$P_SRV min_version=tls13" \
+            "$O_NEXT_CLI -tls1_3" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3"
+
+requires_openssl_tls1_3_with_compatible_ephemeral
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+run_test    "Server version nego O->m: cli 1.2+1.3, srv (1.2)+1.3 -> 1.3" \
+            "$P_SRV" \
+            "$O_NEXT_CLI" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3"
+
+requires_openssl_tls1_3_with_compatible_ephemeral
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+run_test    "Server version nego O->m (no compat): cli 1.2+1.3, srv (1.2)+1.3 -> 1.3" \
+            "$P_SRV" \
+            "$O_NEXT_CLI -no_middlebox" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3"
+
+requires_openssl_tls1_3_with_compatible_ephemeral
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3 \
+                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
+                             MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE
+run_test    "Server version nego O->m: cli 1.2+1.3, srv min=1.3 -> 1.3" \
+            "$P_SRV min_version=tls13" \
+            "$O_NEXT_CLI" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.3"
+
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Server version nego O->m: cli 1.2+1.3, srv 1.2 -> 1.2" \
+            "$P_SRV" \
+            "$O_NEXT_CLI" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.2"
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Server version nego O->m: cli 1.2+1.3, srv max=1.2 -> 1.2" \
+            "$P_SRV max_version=tls12" \
+            "$O_NEXT_CLI" \
+            0 \
+            -S "mbedtls_ssl_handshake returned" \
+            -s "Protocol is TLSv1.2"
+
+requires_config_enabled MBEDTLS_SSL_SRV_C
+run_test    "Not supported version O->m: cli 1.0, srv (1.2)+(1.3)" \
+            "$P_SRV" \
+            "$O_CLI -tls1" \
+            1 \
+            -s "Handshake protocol not within min/max boundaries" \
+            -S "Protocol is TLSv1.0"
+
+requires_config_enabled MBEDTLS_SSL_SRV_C
+run_test    "Not supported version O->m: cli 1.1, srv (1.2)+(1.3)" \
+            "$P_SRV" \
+            "$O_CLI -tls1_1" \
+            1 \
+            -s "Handshake protocol not within min/max boundaries" \
+            -S "Protocol is TLSv1.1"
+
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "Not supported version O->m: cli 1.2, srv 1.3" \
+            "$P_SRV" \
+            "$O_NEXT_CLI -tls1_2" \
+            1 \
+            -s "Handshake protocol not within min/max boundaries" \
+            -S "Protocol is TLSv1.2"
+
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_3
+run_test    "Not supported version O->m: cli 1.3, srv 1.2" \
+            "$P_SRV" \
+            "$O_NEXT_CLI -tls1_3" \
+            1 \
+            -S "Handshake protocol not within min/max boundaries" \
+            -s "The handshake negotiation failed" \
+            -S "Protocol is TLSv1.3"
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+run_test    "Not supported version O->m: cli 1.2, srv min=1.3" \
+            "$P_SRV min_version=tls13" \
+            "$O_NEXT_CLI -tls1_2" \
+            1 \
+            -s "Handshake protocol not within min/max boundaries" \
+            -S "Protocol is TLSv1.2"
+
+requires_all_configs_enabled MBEDTLS_SSL_SRV_C \
+                             MBEDTLS_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_3
+run_test    "Not supported version O->m: cli 1.3, srv max=1.2" \
+            "$P_SRV max_version=tls12" \
+            "$O_NEXT_CLI -tls1_3" \
+            1 \
+            -S "Handshake protocol not within min/max boundaries" \
+            -s "The handshake negotiation failed" \
+            -S "Protocol is TLSv1.3"
+
+# Tests of version negotiation on client side against GnuTLS and OpenSSL server
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-run_test    "Not supported version check: srv max TLS 1.0" \
+run_test    "Not supported version: srv max TLS 1.0" \
             "$G_SRV --priority=NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0" \
             "$P_CLI" \
             1 \
@@ -6971,7 +7394,7 @@
             -C "Protocol is TLSv1.0"
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-run_test    "Not supported version check: srv max TLS 1.1" \
+run_test    "Not supported version: srv max TLS 1.1" \
             "$G_SRV --priority=NORMAL:-VERS-TLS-ALL:+VERS-TLS1.1" \
             "$P_CLI" \
             1 \
@@ -6980,6 +7403,88 @@
             -S "Version: TLS1.1" \
             -C "Protocol is TLSv1.1"
 
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_DEBUG_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
+skip_handshake_stage_check
+requires_gnutls_tls1_3
+run_test    "TLS 1.3: Not supported version:gnutls: srv max TLS 1.0" \
+            "$G_NEXT_SRV --priority=NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0 -d 4" \
+            "$P_CLI debug_level=4" \
+            1 \
+            -s "Client's version: 3.3" \
+            -S "Version: TLS1.0" \
+            -C "Protocol is TLSv1.0"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_DEBUG_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
+skip_handshake_stage_check
+requires_gnutls_tls1_3
+run_test    "TLS 1.3: Not supported version:gnutls: srv max TLS 1.1" \
+            "$G_NEXT_SRV --priority=NORMAL:-VERS-TLS-ALL:+VERS-TLS1.1 -d 4" \
+            "$P_CLI debug_level=4" \
+            1 \
+            -s "Client's version: 3.3" \
+            -S "Version: TLS1.1" \
+            -C "Protocol is TLSv1.1"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_DEBUG_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
+skip_handshake_stage_check
+requires_gnutls_tls1_3
+run_test    "TLS 1.3: Not supported version:gnutls: srv max TLS 1.2" \
+            "$G_NEXT_SRV --priority=NORMAL:-VERS-TLS-ALL:+VERS-TLS1.2 -d 4" \
+            "$P_CLI force_version=tls13 debug_level=4" \
+            1 \
+            -s "Client's version: 3.3" \
+            -c "is a fatal alert message (msg 40)" \
+            -S "Version: TLS1.2" \
+            -C "Protocol is TLSv1.2"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_DEBUG_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
+skip_handshake_stage_check
+requires_openssl_next
+run_test    "TLS 1.3: Not supported version:openssl: srv max TLS 1.0" \
+            "$O_NEXT_SRV -msg -tls1" \
+            "$P_CLI debug_level=4" \
+            1 \
+            -s "fatal protocol_version" \
+            -c "is a fatal alert message (msg 70)" \
+            -S "Version: TLS1.0" \
+            -C "Protocol  : TLSv1.0"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_DEBUG_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
+skip_handshake_stage_check
+requires_openssl_next
+run_test    "TLS 1.3: Not supported version:openssl: srv max TLS 1.1" \
+            "$O_NEXT_SRV -msg -tls1_1" \
+            "$P_CLI debug_level=4" \
+            1 \
+            -s "fatal protocol_version" \
+            -c "is a fatal alert message (msg 70)" \
+            -S "Version: TLS1.1" \
+            -C "Protocol  : TLSv1.1"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_DEBUG_C
+requires_config_enabled MBEDTLS_SSL_CLI_C
+skip_handshake_stage_check
+requires_openssl_next
+run_test    "TLS 1.3: Not supported version:openssl: srv max TLS 1.2" \
+            "$O_NEXT_SRV -msg -tls1_2" \
+            "$P_CLI force_version=tls13 debug_level=4" \
+            1 \
+            -s "fatal protocol_version" \
+            -c "is a fatal alert message (msg 70)" \
+            -S "Version: TLS1.2" \
+            -C "Protocol  : TLSv1.2"
+
 # Tests for ALPN extension
 
 requires_key_exchange_with_cert_in_tls12_or_tls13_enabled
@@ -7211,7 +7716,7 @@
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
 run_test    "keyUsage cli 1.3: DigitalSignature+KeyEncipherment, RSA: OK" \
             "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server2.key \
-             -cert data_files/server2.ku-ds_ke.crt" \
+             -cert data_files/server2-sha256.ku-ds_ke.crt" \
             "$P_CLI debug_level=3" \
             0 \
             -C "bad certificate (usage extensions)" \
@@ -7223,7 +7728,7 @@
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
 run_test    "keyUsage cli 1.3: KeyEncipherment, RSA: fail" \
             "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server2.key \
-             -cert data_files/server2.ku-ke.crt" \
+             -cert data_files/server2-sha256.ku-ke.crt" \
             "$P_CLI debug_level=1" \
             1 \
             -c "bad certificate (usage extensions)" \
@@ -7235,7 +7740,7 @@
                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
 run_test    "keyUsage cli 1.3: KeyAgreement, RSA: fail" \
             "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server2.key \
-             -cert data_files/server2.ku-ka.crt" \
+             -cert data_files/server2-sha256.ku-ka.crt" \
             "$P_CLI debug_level=1" \
             1 \
             -c "bad certificate (usage extensions)" \
@@ -7334,7 +7839,7 @@
 run_test    "keyUsage cli-auth 1.3: RSA, DigitalSignature: OK" \
             "$P_SRV debug_level=1 force_version=tls13 auth_mode=optional" \
             "$O_NEXT_CLI_NO_CERT -key data_files/server2.key \
-             -cert data_files/server2.ku-ds.crt" \
+             -cert data_files/server2-sha256.ku-ds.crt" \
             0 \
             -s "Verifying peer X.509 certificate... ok" \
             -S "bad certificate (usage extensions)" \
@@ -7346,7 +7851,7 @@
 run_test    "keyUsage cli-auth 1.3: RSA, KeyEncipherment: fail (soft)" \
             "$P_SRV debug_level=1 force_version=tls13 auth_mode=optional" \
             "$O_NEXT_CLI_NO_CERT -key data_files/server2.key \
-             -cert data_files/server2.ku-ke.crt" \
+             -cert data_files/server2-sha256.ku-ke.crt" \
             0 \
             -s "bad certificate (usage extensions)" \
             -S "Processing of the Certificate handshake message failed"
@@ -11342,6 +11847,7 @@
 
 requires_certificate_authentication
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "DTLS reordering: Buffer out-of-order CCS message on client"\
             -p "$P_PXY delay_srv=NewSessionTicket" \
             "$P_SRV dgram_packing=0 cookies=0 dtls=1 debug_level=2 \
@@ -11462,6 +11968,7 @@
 
 client_needs_more_time 2
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "DTLS proxy: 3d, FS, ticket" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=1 auth_mode=none" \
@@ -11472,6 +11979,7 @@
 
 client_needs_more_time 2
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "DTLS proxy: 3d, max handshake (FS, ticket + client auth)" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 tickets=1 auth_mode=required" \
@@ -11482,6 +11990,7 @@
 
 client_needs_more_time 2
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
 run_test    "DTLS proxy: 3d, max handshake, nbio" \
             -p "$P_PXY drop=5 delay=5 duplicate=5" \
             "$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 nbio=2 tickets=1 \
@@ -11700,6 +12209,30 @@
             -s "ECDH/FFDH group: " \
             -s "selected signature algorithm ecdsa_secp256r1_sha256"
 
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Establish TLS 1.2 then TLS 1.3 session" \
+            "$P_SRV" \
+            "( $P_CLI force_version=tls12; \
+               $P_CLI force_version=tls13 )" \
+            0 \
+            -s "Protocol is TLSv1.2" \
+            -s "Protocol is TLSv1.3" \
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+requires_any_configs_enabled $TLS1_2_KEY_EXCHANGES_WITH_CERT
+run_test    "Establish TLS 1.3 then TLS 1.2 session" \
+            "$P_SRV" \
+            "( $P_CLI force_version=tls13; \
+               $P_CLI force_version=tls12 )" \
+            0 \
+            -s "Protocol is TLSv1.3" \
+            -s "Protocol is TLSv1.2" \
+
 requires_openssl_tls1_3_with_compatible_ephemeral
 requires_config_enabled MBEDTLS_DEBUG_C
 requires_config_enabled MBEDTLS_SSL_CLI_C
@@ -11866,103 +12399,6 @@
             -s "HTTP/1.0 200 OK" \
             -s "Application Layer Protocol is h2"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-skip_handshake_stage_check
-requires_gnutls_tls1_3
-run_test    "TLS 1.3: Not supported version check:gnutls: srv max TLS 1.0" \
-            "$G_NEXT_SRV --priority=NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0 -d 4" \
-            "$P_CLI debug_level=4" \
-            1 \
-            -s "Client's version: 3.3" \
-            -S "Version: TLS1.0" \
-            -C "Protocol is TLSv1.0"
-
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-skip_handshake_stage_check
-requires_gnutls_tls1_3
-run_test    "TLS 1.3: Not supported version check:gnutls: srv max TLS 1.1" \
-            "$G_NEXT_SRV --priority=NORMAL:-VERS-TLS-ALL:+VERS-TLS1.1 -d 4" \
-            "$P_CLI debug_level=4" \
-            1 \
-            -s "Client's version: 3.3" \
-            -S "Version: TLS1.1" \
-            -C "Protocol is TLSv1.1"
-
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-skip_handshake_stage_check
-requires_gnutls_tls1_3
-run_test    "TLS 1.3: Not supported version check:gnutls: srv max TLS 1.2" \
-            "$G_NEXT_SRV --priority=NORMAL:-VERS-TLS-ALL:+VERS-TLS1.2 -d 4" \
-            "$P_CLI force_version=tls13 debug_level=4" \
-            1 \
-            -s "Client's version: 3.3" \
-            -c "is a fatal alert message (msg 40)" \
-            -S "Version: TLS1.2" \
-            -C "Protocol is TLSv1.2"
-
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-skip_handshake_stage_check
-requires_openssl_next
-run_test    "TLS 1.3: Not supported version check:openssl: srv max TLS 1.0" \
-            "$O_NEXT_SRV -msg -tls1" \
-            "$P_CLI debug_level=4" \
-            1 \
-            -s "fatal protocol_version" \
-            -c "is a fatal alert message (msg 70)" \
-            -S "Version: TLS1.0" \
-            -C "Protocol  : TLSv1.0"
-
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-skip_handshake_stage_check
-requires_openssl_next
-run_test    "TLS 1.3: Not supported version check:openssl: srv max TLS 1.1" \
-            "$O_NEXT_SRV -msg -tls1_1" \
-            "$P_CLI debug_level=4" \
-            1 \
-            -s "fatal protocol_version" \
-            -c "is a fatal alert message (msg 70)" \
-            -S "Version: TLS1.1" \
-            -C "Protocol  : TLSv1.1"
-
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-skip_handshake_stage_check
-requires_openssl_next
-run_test    "TLS 1.3: Not supported version check:openssl: srv max TLS 1.2" \
-            "$O_NEXT_SRV -msg -tls1_2" \
-            "$P_CLI force_version=tls13 debug_level=4" \
-            1 \
-            -s "fatal protocol_version" \
-            -c "is a fatal alert message (msg 70)" \
-            -S "Version: TLS1.2" \
-            -C "Protocol  : TLSv1.2"
-
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
-requires_config_enabled MBEDTLS_SSL_CLI_C
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
-requires_config_enabled MBEDTLS_SSL_SRV_C
-run_test "TLS 1.3 m->m: Not supported version check: cli TLS 1.2 only, srv TLS 1.3 only, fail" \
-         "$P_SRV debug_level=4 max_version=tls13 min_version=tls13" \
-         "$P_CLI debug_level=4 max_version=tls12 min_version=tls12" \
-         1 \
-         -c "The SSL configuration is tls12 only"                   \
-         -c "supported_versions(43) extension does not exist."      \
-         -c "A fatal alert message was received from our peer"      \
-         -s "The SSL configuration is tls13 only"                   \
-         -s "TLS 1.2 not supported."
-
 requires_openssl_tls1_3_with_compatible_ephemeral
 requires_config_enabled MBEDTLS_DEBUG_C
 requires_config_enabled MBEDTLS_SSL_CLI_C
@@ -13414,125 +13850,6 @@
             -c "no suitable signature algorithm"
 
 requires_openssl_tls1_3_with_compatible_ephemeral
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test    "TLS 1.3: NewSessionTicket: Basic check, m->O" \
-            "$O_NEXT_SRV -msg -tls1_3 -no_resume_ephemeral -no_cache --num_tickets 4" \
-            "$P_CLI debug_level=1 reco_mode=1 reconnect=1" \
-            0 \
-            -c "Protocol is TLSv1.3" \
-            -c "got new session ticket." \
-            -c "Saving session for reuse... ok" \
-            -c "Reconnecting with saved session" \
-            -c "HTTP/1.0 200 ok"
-
-requires_gnutls_tls1_3
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test    "TLS 1.3: NewSessionTicket: Basic check, m->G" \
-            "$G_NEXT_SRV -d 10 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 --disable-client-cert" \
-            "$P_CLI debug_level=1 reco_mode=1 reconnect=1" \
-            0 \
-            -c "Protocol is TLSv1.3" \
-            -c "got new session ticket." \
-            -c "Saving session for reuse... ok" \
-            -c "Reconnecting with saved session" \
-            -c "HTTP/1.0 200 OK" \
-            -s "This is a resumed session"
-
-requires_openssl_tls1_3_with_compatible_ephemeral
-requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
-requires_config_enabled MBEDTLS_SSL_SRV_C
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-# https://github.com/openssl/openssl/issues/10714
-# Until now, OpenSSL client does not support reconnect.
-skip_next_test
-run_test    "TLS 1.3: NewSessionTicket: Basic check, O->m" \
-            "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=4" \
-            "$O_NEXT_CLI -msg -debug -tls1_3 -reconnect" \
-            0 \
-            -s "=> write NewSessionTicket msg" \
-            -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET" \
-            -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH"
-
-requires_gnutls_tls1_3
-requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
-requires_config_enabled MBEDTLS_SSL_SRV_C
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test    "TLS 1.3: NewSessionTicket: Basic check, G->m" \
-            "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=4" \
-            "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 -V -r" \
-            0 \
-            -c "Connecting again- trying to resume previous session" \
-            -c "NEW SESSION TICKET (4) was received" \
-            -s "=> write NewSessionTicket msg" \
-            -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET" \
-            -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH" \
-            -s "key exchange mode: ephemeral" \
-            -s "key exchange mode: psk_ephemeral" \
-            -s "found pre_shared_key extension"
-
-requires_gnutls_tls1_3
-requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
-requires_config_enabled MBEDTLS_SSL_SRV_C
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-# Test the session resumption when the cipher suite for the original session is
-# TLS1-3-AES-256-GCM-SHA384. In that case, the PSK is 384 bits long and not
-# 256 bits long as with all the other TLS 1.3 cipher suites.
-requires_ciphersuite_enabled TLS1-3-AES-256-GCM-SHA384
-run_test    "TLS 1.3: NewSessionTicket: Basic check with AES-256-GCM only, G->m" \
-            "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 tickets=4" \
-            "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM -V -r" \
-            0 \
-            -c "Connecting again- trying to resume previous session" \
-            -c "NEW SESSION TICKET (4) was received" \
-            -s "Ciphersuite is TLS1-3-AES-256-GCM-SHA384" \
-            -s "=> write NewSessionTicket msg" \
-            -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET" \
-            -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH" \
-            -s "key exchange mode: ephemeral" \
-            -s "key exchange mode: psk_ephemeral" \
-            -s "found pre_shared_key extension"
-
-requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
-requires_config_enabled MBEDTLS_SSL_SRV_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test    "TLS 1.3: NewSessionTicket: Basic check, m->m" \
-            "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=4" \
-            "$P_CLI debug_level=4 reco_mode=1 reconnect=1" \
-            0 \
-            -c "Protocol is TLSv1.3" \
-            -c "got new session ticket ( 3 )" \
-            -c "Saving session for reuse... ok" \
-            -c "Reconnecting with saved session" \
-            -c "HTTP/1.0 200 OK"    \
-            -s "=> write NewSessionTicket msg" \
-            -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET" \
-            -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH" \
-            -s "key exchange mode: ephemeral" \
-            -s "key exchange mode: psk_ephemeral" \
-            -s "found pre_shared_key extension"
-
-requires_openssl_tls1_3_with_compatible_ephemeral
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 requires_config_enabled MBEDTLS_DEBUG_C
 requires_config_enabled MBEDTLS_SSL_CLI_C
@@ -13563,51 +13880,6 @@
             -c "Protocol is TLSv1.2" \
             -c "HTTP/1.0 200 [Oo][Kk]"
 
-requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
-requires_config_enabled MBEDTLS_SSL_SRV_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test    "TLS 1.3: NewSessionTicket: servername check, m->m" \
-            "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=4 \
-            sni=localhost,data_files/server2.crt,data_files/server2.key,-,-,-,polarssl.example,data_files/server1-nospace.crt,data_files/server1.key,-,-,-" \
-            "$P_CLI debug_level=4 server_name=localhost reco_mode=1 reconnect=1" \
-            0 \
-            -c "Protocol is TLSv1.3" \
-            -c "got new session ticket." \
-            -c "Saving session for reuse... ok" \
-            -c "Reconnecting with saved session" \
-            -c "HTTP/1.0 200 OK"    \
-            -s "=> write NewSessionTicket msg" \
-            -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET" \
-            -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH" \
-            -s "key exchange mode: ephemeral" \
-            -s "key exchange mode: psk_ephemeral" \
-            -s "found pre_shared_key extension"
-
-requires_config_enabled MBEDTLS_SSL_SESSION_TICKETS
-requires_config_enabled MBEDTLS_SSL_SRV_C
-requires_config_enabled MBEDTLS_SSL_CLI_C
-requires_config_enabled MBEDTLS_DEBUG_C
-requires_all_configs_enabled MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED \
-                             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-run_test    "TLS 1.3: NewSessionTicket: servername negative check, m->m" \
-            "$P_SRV debug_level=4 crt_file=data_files/server5.crt key_file=data_files/server5.key tickets=4 \
-            sni=localhost,data_files/server2.crt,data_files/server2.key,-,-,-,polarssl.example,data_files/server1-nospace.crt,data_files/server1.key,-,-,-" \
-            "$P_CLI debug_level=4 server_name=localhost reco_server_name=remote reco_mode=1 reconnect=1" \
-            1 \
-            -c "Protocol is TLSv1.3" \
-            -c "got new session ticket." \
-            -c "Saving session for reuse... ok" \
-            -c "Reconnecting with saved session" \
-            -c "Hostname mismatch the session ticket, disable session resumption."    \
-            -s "=> write NewSessionTicket msg" \
-            -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET" \
-            -s "server state: MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH"
-
 requires_config_enabled MBEDTLS_SSL_SRV_C
 requires_config_enabled MBEDTLS_DEBUG_C
 requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
diff --git a/tests/suites/test_suite_bignum.function b/tests/suites/test_suite_bignum.function
index 50be2d2..f3a64e1 100644
--- a/tests/suites/test_suite_bignum.function
+++ b/tests/suites/test_suite_bignum.function
@@ -966,6 +966,45 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void mpi_exp_mod_min_RR(char *input_A, char *input_E,
+                        char *input_N, char *input_X,
+                        int exp_result)
+{
+    mbedtls_mpi A, E, N, RR, Z, X;
+    int res;
+    mbedtls_mpi_init(&A); mbedtls_mpi_init(&E); mbedtls_mpi_init(&N);
+    mbedtls_mpi_init(&RR); mbedtls_mpi_init(&Z); mbedtls_mpi_init(&X);
+
+    TEST_EQUAL(mbedtls_test_read_mpi(&A, input_A), 0);
+    TEST_EQUAL(mbedtls_test_read_mpi(&E, input_E), 0);
+    TEST_EQUAL(mbedtls_test_read_mpi(&N, input_N), 0);
+    TEST_EQUAL(mbedtls_test_read_mpi(&X, input_X), 0);
+
+    TEST_EQUAL(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N), 0);
+    TEST_EQUAL(mbedtls_mpi_shrink(&RR, 0), 0);
+    /* The objective of this test is to check that exp_mod defends
+     * against a smaller RR. */
+    TEST_LE_U(RR.n, N.n - 1);
+
+    res = mbedtls_mpi_exp_mod(&Z, &A, &E, &N, &RR);
+    /* We know that exp_mod internally needs RR to be as large as N.
+     * Validate that it is the case now, otherwise there was probably
+     * a buffer overread. */
+    TEST_EQUAL(RR.n, N.n);
+
+    TEST_EQUAL(res, exp_result);
+    if (res == 0) {
+        TEST_EQUAL(sign_is_valid(&Z), 1);
+        TEST_EQUAL(mbedtls_mpi_cmp_mpi(&Z, &X), 0);
+    }
+
+exit:
+    mbedtls_mpi_free(&A); mbedtls_mpi_free(&E); mbedtls_mpi_free(&N);
+    mbedtls_mpi_free(&RR); mbedtls_mpi_free(&Z); mbedtls_mpi_free(&X);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void mpi_exp_mod(char *input_A, char *input_E,
                  char *input_N, char *input_X,
                  int exp_result)
diff --git a/tests/suites/test_suite_bignum.misc.data b/tests/suites/test_suite_bignum.misc.data
index c53e42a..eb55dbe 100644
--- a/tests/suites/test_suite_bignum.misc.data
+++ b/tests/suites/test_suite_bignum.misc.data
@@ -1362,6 +1362,9 @@
 Test mbedtls_mpi_exp_mod: 10 ^ 0 (1 limb) mod 9
 mpi_exp_mod:"0a":"00":"09":"1":0
 
+Test mbedtls_mpi_exp_mod: -3 ^ 3 mod 27
+mpi_exp_mod:"-3":"3":"1b":"1b":0
+
 Test mbedtls_mpi_exp_mod: MAX_SIZE exponent
 mpi_exp_mod_size:2:MBEDTLS_MPI_MAX_SIZE:10:"":0
 
@@ -1391,6 +1394,14 @@
 depends_on:MPI_MAX_BITS_LARGER_THAN_792
 mpi_exp_mod:"-9f13012cd92aa72fb86ac8879d2fde4f7fd661aaae43a00971f081cc60ca277059d5c37e89652e2af2585d281d66ef6a9d38a117e9608e9e7574cd142dc55278838a2161dd56db9470d4c1da2d5df15a908ee2eb886aaa890f23be16de59386663a12f1afbb325431a3e835e3fd89b98b96a6f77382f458ef9a37e1f84a03045c8676ab55291a94c2228ea15448ee96b626b998":"40a54d1b9e86789f06d9607fb158672d64867665c73ee9abb545fc7a785634b354c7bae5b962ce8040cf45f2c1f3d3659b2ee5ede17534c8fc2ec85c815e8df1fe7048d12c90ee31b88a68a081f17f0d8ce5f4030521e9400083bcea73a429031d4ca7949c2000d597088e0c39a6014d8bf962b73bb2e8083bd0390a4e00b9b3":"eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3":"21acc7199e1b90f9b4844ffe12c19f00ec548c5d32b21c647d48b6015d8eb9ec9db05b4f3d44db4227a2b5659c1a7cceb9d5fa8fa60376047953ce7397d90aaeb7465e14e820734f84aa52ad0fc66701bcbb991d57715806a11531268e1e83dd48288c72b424a6287e9ce4e5cc4db0dd67614aecc23b0124a5776d36e5c89483":0
 
+Test mbedtls_mpi_exp_mod (N.n=3, RR.n=1 on 32 bit)
+depends_on:MBEDTLS_HAVE_INT32
+mpi_exp_mod_min_RR:"10":"2":"10000000100000001":"100":0
+
+Test mbedtls_mpi_exp_mod (N.n=3, RR.n=1 on 64 bit)
+depends_on:MBEDTLS_HAVE_INT64
+mpi_exp_mod_min_RR:"10":"2":"100000000000000010000000000000001":"100":0
+
 Base test GCD #1
 mpi_gcd:"2b5":"261":"15"
 
diff --git a/tests/suites/test_suite_debug.function b/tests/suites/test_suite_debug.function
index eeefc95..70e7bad 100644
--- a/tests/suites/test_suite_debug.function
+++ b/tests/suites/test_suite_debug.function
@@ -2,6 +2,7 @@
 #include "debug_internal.h"
 #include "string.h"
 #include "mbedtls/pk.h"
+#include <test/ssl_helpers.h>
 
 struct buffer_data {
     char buf[2000];
@@ -65,11 +66,12 @@
     memset(buffer.buf, 0, 2000);
     buffer.ptr = buffer.buf;
 
-    mbedtls_ssl_config_defaults(&conf,
-                                MBEDTLS_SSL_IS_CLIENT,
-                                MBEDTLS_SSL_TRANSPORT_STREAM,
-                                MBEDTLS_SSL_PRESET_DEFAULT);
-
+    TEST_EQUAL(mbedtls_ssl_config_defaults(&conf,
+                                           MBEDTLS_SSL_IS_CLIENT,
+                                           MBEDTLS_SSL_TRANSPORT_STREAM,
+                                           MBEDTLS_SSL_PRESET_DEFAULT),
+               0);
+    mbedtls_ssl_conf_rng(&conf, mbedtls_test_random, NULL);
     mbedtls_ssl_conf_dbg(&conf, string_debug, &buffer);
 
     TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
@@ -103,11 +105,12 @@
     memset(buffer.buf, 0, 2000);
     buffer.ptr = buffer.buf;
 
-    mbedtls_ssl_config_defaults(&conf,
-                                MBEDTLS_SSL_IS_CLIENT,
-                                MBEDTLS_SSL_TRANSPORT_STREAM,
-                                MBEDTLS_SSL_PRESET_DEFAULT);
-
+    TEST_EQUAL(mbedtls_ssl_config_defaults(&conf,
+                                           MBEDTLS_SSL_IS_CLIENT,
+                                           MBEDTLS_SSL_TRANSPORT_STREAM,
+                                           MBEDTLS_SSL_PRESET_DEFAULT),
+               0);
+    mbedtls_ssl_conf_rng(&conf, mbedtls_test_random, NULL);
     mbedtls_ssl_conf_dbg(&conf, string_debug, &buffer);
 
     TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
@@ -138,11 +141,12 @@
     memset(buffer.buf, 0, 2000);
     buffer.ptr = buffer.buf;
 
-    mbedtls_ssl_config_defaults(&conf,
-                                MBEDTLS_SSL_IS_CLIENT,
-                                MBEDTLS_SSL_TRANSPORT_STREAM,
-                                MBEDTLS_SSL_PRESET_DEFAULT);
-
+    TEST_EQUAL(mbedtls_ssl_config_defaults(&conf,
+                                           MBEDTLS_SSL_IS_CLIENT,
+                                           MBEDTLS_SSL_TRANSPORT_STREAM,
+                                           MBEDTLS_SSL_PRESET_DEFAULT),
+               0);
+    mbedtls_ssl_conf_rng(&conf, mbedtls_test_random, NULL);
     mbedtls_ssl_conf_dbg(&conf, string_debug, &buffer);
 
     TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
@@ -175,11 +179,12 @@
     memset(buffer.buf, 0, 2000);
     buffer.ptr = buffer.buf;
 
-    mbedtls_ssl_config_defaults(&conf,
-                                MBEDTLS_SSL_IS_CLIENT,
-                                MBEDTLS_SSL_TRANSPORT_STREAM,
-                                MBEDTLS_SSL_PRESET_DEFAULT);
-
+    TEST_EQUAL(mbedtls_ssl_config_defaults(&conf,
+                                           MBEDTLS_SSL_IS_CLIENT,
+                                           MBEDTLS_SSL_TRANSPORT_STREAM,
+                                           MBEDTLS_SSL_PRESET_DEFAULT),
+               0);
+    mbedtls_ssl_conf_rng(&conf, mbedtls_test_random, NULL);
     mbedtls_ssl_conf_dbg(&conf, string_debug, &buffer);
 
     TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
@@ -214,11 +219,12 @@
     memset(buffer.buf, 0, 2000);
     buffer.ptr = buffer.buf;
 
-    mbedtls_ssl_config_defaults(&conf,
-                                MBEDTLS_SSL_IS_CLIENT,
-                                MBEDTLS_SSL_TRANSPORT_STREAM,
-                                MBEDTLS_SSL_PRESET_DEFAULT);
-
+    TEST_EQUAL(mbedtls_ssl_config_defaults(&conf,
+                                           MBEDTLS_SSL_IS_CLIENT,
+                                           MBEDTLS_SSL_TRANSPORT_STREAM,
+                                           MBEDTLS_SSL_PRESET_DEFAULT),
+               0);
+    mbedtls_ssl_conf_rng(&conf, mbedtls_test_random, NULL);
     mbedtls_ssl_conf_dbg(&conf, string_debug, &buffer);
 
     TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index 989235d..9a3781f 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -8,23 +8,23 @@
 depends_on:MBEDTLS_RSA_C
 valid_parameters_pkwrite:"308204a20201000282010100a9021f3d406ad555538bfd36ee82652e15615e89bfb8e84590dbee881652d3f143504796125964876bfd2be046f973beddcf92e1915bed66a06f8929794580d0836ad54143775f397c09044782b0573970eda3ec15191ea8330847c10542a9fd4cc3b4dfdd061f4d1051406773130f40f86d81255f0ab153c6307e1539acf95aee7f929ea6055be7139785b52392d9d42406d50925897507dda61a8f3f0919bead652c64eb959bdcfe415e17a6da6c5b69cc02ba142c16249c4adccdd0f7526773f12da023fd7ef431ca2d70ca890b04db2ea64f706e9ecebd5889e253599e6e5a9265e2883f0c9419a3dde5e89d9513ed29dbab7012dc5aca6b17ab528254b10203010001028201001689f5e89142ae18a6ffb0513715a4b0b4a13b9e5b3729a2bd62d738c6e15cea7bf3a4d85ab2193a0628c9452bb1f0c1af8b132789df1c95e72778bf5330f5b0d915d242d5e0818e85001ed5fa93d1ce13455deb0a15438562e8e3c8d60ec1e4c9ebff9f2b36b9cde9332cc79f0d17a7ae79cc1353cd75409ad9b4b6d7ee3d82af6f3207656cf2ac98947c15c398db0cebf8dc3eef5398269480cdd09411b960273ae3f364da09af849f24aa87346c58618ea91d9d6cd1d3932c80dbfc1f0a4166a9036911999ca27761079f0ce02db02c1c909ff9b4278578d7bb1b54b2b7082fc9e864b6b394e331c0d11a9a68255565b6dd477f4119c5809839520700711102818100d7db987ad86de6a9b0749fb5da80bacde3bebd72dcc83f60a27db74f927ac3661386577bfce5b4a00ad024682401d6aad29713c8e223b53415305ca07559821099b187fdd1bad3dc4dec9da96f5fa6128331e8f7d89f1e1a788698d1a27256dc7cd392f04e531a9e38e7265bf4fd7eec01e7835e9b1a0dd8923e440381be1c2702818100c87025fff7a493c623404966fbc8b32ed164ca620ad1a0ad11ef42fd12118456017856a8b42e5d4ad36104e9dc9f8a2f3003c3957ffddb20e2f4e3fc3cf2cdddae01f57a56de4fd24b91ab6d3e5cc0e8af0473659594a6bbfdaacf958f19c8d508eac12d8977616af6877106288093d37904a139220c1bc278ea56edc086976702818043e708685c7cf5fa9b4f948e1856366d5e1f3a694f9a8e954f884c89f3823ac5798ee12657bfcaba2dac9c47464c6dc2fecc17a531be19da706fee336bb6e47b645dbc71d3eff9856bddeb1ac9b644ffbdd58d7ba9e1240f1faaf797ba8a4d58becbaf85789e1bd979fcfccc209d3db7f0416bc9eef09b3a6d86b8ce8199d4310281804f4b86ccffe49d0d8ace98fb63ea9f708b284ba483d130b6a75cb76cb4e4372d6b41774f20912319420ca4cbfc1b25a8cb5f01d6381f6ebc50ed3ef08010327f5ba2acc1ac7220b3fa6f7399314db2879b0db0b5647abd87abb01295815a5b086491b2c0d81c616ed67ef8a8ce0727f446711d7323d4147b5828a52143c43b4b028180540756beba83c20a0bda11d6dec706a71744ff28090cec079dffb507d82828038fe657f61496a20317f779cb683ce8196c29a6fe28839a282eef4de57773be56808b0c3e2ac7747e2b200b2fbf20b55258cd24622a1ce0099de098ab0855106ae087f08b0c8c346d81619400c1b4838e33ed9ff90f05db8fccf8fb7ab881ca12"
 
-PK utils: RSA Minimum key
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_utils:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS:MBEDTLS_RSA_GEN_KEY_MIN_BITS:(MBEDTLS_RSA_GEN_KEY_MIN_BITS + 7) / 8:"RSA"
+PK utils: RSA 1024-bit
+depends_on:MBEDTLS_RSA_C
+pk_utils:MBEDTLS_PK_RSA:RSA_KEY_SIZE:RSA_KEY_SIZE:(RSA_KEY_SIZE + 7) / 8:"RSA"
 
-# mbedtls_rsa_gen_key() only supports even sizes, so we don't test min+1,
-# min+3, etc.
-PK utils: RSA Minimum key + 2 bits
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_utils:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 2:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 2:(MBEDTLS_RSA_GEN_KEY_MIN_BITS + 2 + 7) / 8:"RSA"
+# In the following 3 test cases we test a few different sizes that are not a
+# multiple of 8 and for which we have test data.
+PK utils: RSA 1026-bits
+depends_on:MBEDTLS_RSA_C
+pk_utils:MBEDTLS_PK_RSA:RSA_KEY_SIZE + 2:RSA_KEY_SIZE + 2:(RSA_KEY_SIZE + 2 + 7) / 8:"RSA"
 
-PK utils: RSA Minimum key + 4 bits
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_utils:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 4:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 4:(MBEDTLS_RSA_GEN_KEY_MIN_BITS + 4 + 7) / 8:"RSA"
+PK utils: RSA 1028-bits
+depends_on:MBEDTLS_RSA_C
+pk_utils:MBEDTLS_PK_RSA:RSA_KEY_SIZE + 4:RSA_KEY_SIZE + 4:(RSA_KEY_SIZE + 4 + 7) / 8:"RSA"
 
-PK utils: RSA Minimum key + 6 bits
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_utils:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 6:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 6:(MBEDTLS_RSA_GEN_KEY_MIN_BITS + 6 + 7) / 8:"RSA"
+PK utils: RSA 1030-bits
+depends_on:MBEDTLS_RSA_C
+pk_utils:MBEDTLS_PK_RSA:RSA_KEY_SIZE + 6:RSA_KEY_SIZE + 6:(RSA_KEY_SIZE + 6 + 7) / 8:"RSA"
 
 PK utils: ECKEY SECP192R1
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_ECP_HAVE_SECP192R1
@@ -63,7 +63,7 @@
 pk_psa_utils:0
 
 PK PSA utilities: RSA setup/free, info functions, unsupported operations
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_psa_utils:1
 
 PK can do ext: ECDSA(ANY)/NONE, invalid check STREAM_CIPHER
@@ -159,147 +159,147 @@
 pk_can_do_ext:1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_KEY_USAGE_DERIVE|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_ECDH:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):256:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_DERIVE:1
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, check not allowed COPY usage
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_COPY:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check STREAM_CIPHER
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_STREAM_CIPHER:PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check ECDSA(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check ECDH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_ECDH:PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check RSA_PKCS1V15_CRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, invalid check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/NONE, check non-present usage
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_DERIVE:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(SHA256)/NONE, check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: NONE, RSA_PKCS1V15_SIGN(ANY), check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: NONE, RSA_PKCS1V15_SIGN(SHA256), check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: RSA_PKCS1V15_SIGN(SHA256)/NONE, invalid check RSA_PKCS1V15_SIGN(ANY)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(SHA1)/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_1):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PSS(ANY)/NONE, invalid check STREAM_CIPHER
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_STREAM_CIPHER:PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PSS(ANY)/NONE, invalid check ECDSA(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PSS(ANY)/NONE, invalid check RSA_PKCS1V15_CRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PSS(ANY)/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PSS(ANY)/NONE, check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: RSA_PSS(SHA256)/NONE, check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: NONE, RSA_PSS(ANY), check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: NONE, RSA_PSS(SHA256), check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: RSA_PSS(SHA256)/NONE, invalid check RSA_PSS(ANY)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PSS(SHA1)/NONE, invalid check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_1):PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_SIGN_RAW/NONE, check RSA_PKCS1V15_SIGN_RAW
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: RSA_PKCS1V15_SIGN_RAW/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0
 
 PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check STREAM_CIPHER
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_STREAM_CIPHER:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
 
 PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check ECDSA(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
 
 PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check ECDH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_ECDH:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
 
 PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
 
 PK can do ext: RSA_PKCS1V15_CRYPT/NONE, invalid check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:0
 
 PK can do ext: RSA_PKCS1V15_CRYPT/NONE, check RSA_PKCS1V15_CRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_NONE:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:1
 
 PK can do ext: RSA_PKCS1V15_CRYPT/RSA_PSS(ANY), check RSA_PKCS1V15_CRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:1
 
 PK can do ext: RSA_PKCS1V15_CRYPT/RSA_PSS(ANY), check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_DECRYPT:1
 
 PK can do ext: RSA_PKCS1V15_CRYPT/RSA_PSS(ANY), check non allowed ENCRYPT usage
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_ENCRYPT|PSA_KEY_USAGE_DECRYPT|PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_ENCRYPT:0
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/RSA_PSS(ANY), check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: RSA_PKCS1V15_SIGN(ANY)/RSA_PSS(ANY), check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:1:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH):1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: MBEDTLS_PK_ECKEY, check ECDSA(SHA256)
@@ -311,19 +311,19 @@
 pk_can_do_ext:0:MBEDTLS_PK_ECKEY:0:0:0:MBEDTLS_ECP_DP_SECP256R1:PSA_ALG_ECDH:PSA_KEY_USAGE_DERIVE:1
 
 PK can do ext: MBEDTLS_PK_RSA, check RSA_PKCS1V15_SIGN(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:0:MBEDTLS_PK_RSA:0:0:0:1024:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 PK can do ext: MBEDTLS_PK_RSA, check PSA_ALG_RSA_PKCS1V15_CRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:0:MBEDTLS_PK_RSA:0:0:0:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:1
 
 PK can do ext: MBEDTLS_PK_RSA, check invalid PSA_KEY_USAGE_ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:0:MBEDTLS_PK_RSA:0:0:0:1024:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_ENCRYPT:0
 
 PK can do ext: MBEDTLS_PK_RSA, check RSA_PSS(SHA256)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_can_do_ext:0:MBEDTLS_PK_RSA:0:0:0:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:1
 
 RSA verify test vector: PKCS1v1.5 (explicit), SHA1, good
@@ -435,24 +435,28 @@
 pk_sign_verify:MBEDTLS_PK_ECKEY_DH:MBEDTLS_ECP_DP_SECP192R1:0:0:MBEDTLS_ERR_PK_TYPE_MISMATCH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 RSA sign-verify, PKCS1v1.5, SHA1
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_GENPRIME:MBEDTLS_RSA_GEN_KEY_MIN_BITS >= 512:MBEDTLS_MD_CAN_SHA1
-pk_sign_verify:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS:MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_SHA1:0:0
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA1
+pk_sign_verify:MBEDTLS_PK_RSA:RSA_KEY_SIZE:MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_SHA1:0:0
 
 RSA sign-verify, PKCS1v2.1, SHA1
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_GENPRIME:MBEDTLS_RSA_GEN_KEY_MIN_BITS >= 512:MBEDTLS_MD_CAN_SHA1
-pk_sign_verify:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS:MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA1:0:0
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA1
+pk_sign_verify:MBEDTLS_PK_RSA:RSA_KEY_SIZE:MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA1:0:0
 
 RSA sign-verify, PKCS1v1.5, SHA256
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_GENPRIME:MBEDTLS_RSA_GEN_KEY_MIN_BITS >= 512:MBEDTLS_MD_CAN_SHA256
-pk_sign_verify:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS:MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_SHA256:0:0
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA256
+pk_sign_verify:MBEDTLS_PK_RSA:RSA_KEY_SIZE:MBEDTLS_RSA_PKCS_V15:MBEDTLS_MD_SHA256:0:0
 
 RSA sign-verify, PKCS1v2.1, SHA256
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_GENPRIME:MBEDTLS_RSA_GEN_KEY_MIN_BITS >= 512:MBEDTLS_MD_CAN_SHA256
-pk_sign_verify:MBEDTLS_PK_RSA:MBEDTLS_RSA_GEN_KEY_MIN_BITS:MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA256:0:0
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
+pk_sign_verify:MBEDTLS_PK_RSA:RSA_KEY_SIZE:MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA256:0:0
 
-RSA encrypt-decrypt test
+RSA encrypt-decrypt test PKCS1 v1.5
 depends_on:MBEDTLS_PKCS1_V15
-pk_rsa_encrypt_decrypt_test:"4E636AF98E40F3ADCFCCB698F4E80B9F":2048:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":"3":0
+pk_rsa_encrypt_decrypt_test:"4E636AF98E40F3ADCFCCB698F4E80B9F":2048:MBEDTLS_RSA_PKCS_V15:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":"3":0
+
+RSA encrypt-decrypt test PKCS1 v2.1
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA1
+pk_rsa_encrypt_decrypt_test:"4E636AF98E40F3ADCFCCB698F4E80B9F":2048:MBEDTLS_RSA_PKCS_V21:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":"3":0
 
 RSA decrypt test vector - PKCS1v1.5
 depends_on:MBEDTLS_PKCS1_V15
@@ -478,13 +482,17 @@
 depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA1
 pk_rsa_decrypt_test_vec:"28818cb14236ad18f4527e7f1f7633e96cef021bc3234475d7f61e88702b6335b42a352ed3f3267ac7c3e9ba4af17e45096c63eefd8d9a7cb42dfc52fffb2f5b8afb305b46312c2eb50634123b4437a2287ac57b7509d59a583fb741989a49f32625e9267b4641a6607b7303d35c68489db53c8d387b620d0d46a852e72ea43c":1024:MBEDTLS_RSA_PKCS_V21:MBEDTLS_MD_SHA1:"eecfae81b1b9b3c908810b10a1b5600199eb9f44aef4fda493b81a9e3d84f632124ef0236e5d1e3b7e28fae7aa040a2d5b252176459d1f397541ba2a58fb6599":"c97fb1f027f453f6341233eaaad1d9353f6c42d08866b1d05a0f2035028b9d869840b41666b42e92ea0da3b43204b5cfce3352524d0416a5a441e700af461503":"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":"11":"d436e99569fd32a7c8a05bbc90d32c49":MBEDTLS_ERR_RSA_INVALID_PADDING
 
-RSA Opaque decrypt test vector #1
+RSA Opaque PCKS1 v1.5 - decrypt test vector #1
 depends_on:MBEDTLS_PKCS1_V15
-pk_wrap_rsa_decrypt_test_vec:"a42eda41e56235e666e7faaa77100197f657288a1bf183e4820f0c37ce2c456b960278d6003e0bbcd4be4a969f8e8fd9231e1f492414f00ed09844994c86ec32db7cde3bec7f0c3dbf6ae55baeb2712fa609f5fc3207a824eb3dace31849cd6a6084318523912bccb84cf42e3c6d6d1685131d69bb545acec827d2b0dfdd5568b7dcc4f5a11d6916583fefa689d367f8c9e1d95dcd2240895a9470b0c1730f97cd6e8546860bd254801769f54be96e16362ddcbf34d56035028890199e0f48db38642cb66a4181e028a6443a404fea284ce02b4614b683367d40874e505611d23142d49f06feea831d52d347b13610b413c4efc43a6de9f0b08d2a951dc503b6":2048:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":"3":"4E636AF98E40F3ADCFCCB698F4E80B9F":0
+pk_wrap_rsa_decrypt_test_vec:"a42eda41e56235e666e7faaa77100197f657288a1bf183e4820f0c37ce2c456b960278d6003e0bbcd4be4a969f8e8fd9231e1f492414f00ed09844994c86ec32db7cde3bec7f0c3dbf6ae55baeb2712fa609f5fc3207a824eb3dace31849cd6a6084318523912bccb84cf42e3c6d6d1685131d69bb545acec827d2b0dfdd5568b7dcc4f5a11d6916583fefa689d367f8c9e1d95dcd2240895a9470b0c1730f97cd6e8546860bd254801769f54be96e16362ddcbf34d56035028890199e0f48db38642cb66a4181e028a6443a404fea284ce02b4614b683367d40874e505611d23142d49f06feea831d52d347b13610b413c4efc43a6de9f0b08d2a951dc503b6":2048:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":"3":MBEDTLS_RSA_PKCS_V15:"4E636AF98E40F3ADCFCCB698F4E80B9F":0
 
-RSA Opaque decrypt test vector #2
+RSA Opaque PCKS1 v2.1 - decrypt test vector #1
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA1
+pk_wrap_rsa_decrypt_test_vec:"1253e04dc0a5397bb44a7ab87e9bf2a039a33d1e996fc82a94ccd30074c95df763722017069e5268da5d1c0b4f872cf653c11df82314a67968dfeae28def04bb6d84b1c31d654a1970e5783bd6eb96a024c2ca2f4a90fe9f2ef5c9c140e5bb48da9536ad8700c84fc9130adea74e558d51a74ddf85d8b50de96838d6063e0955":1024:"eecfae81b1b9b3c908810b10a1b5600199eb9f44aef4fda493b81a9e3d84f632124ef0236e5d1e3b7e28fae7aa040a2d5b252176459d1f397541ba2a58fb6599":"c97fb1f027f453f6341233eaaad1d9353f6c42d08866b1d05a0f2035028b9d869840b41666b42e92ea0da3b43204b5cfce3352524d0416a5a441e700af461503":"bbf82f090682ce9c2338ac2b9da871f7368d07eed41043a440d6b6f07454f51fb8dfbaaf035c02ab61ea48ceeb6fcd4876ed520d60e1ec4619719d8a5b8b807fafb8e0a3dfc737723ee6b4b7d93a2584ee6a649d060953748834b2454598394ee0aab12d7b61a51f527a9a41f6c1687fe2537298ca2a8f5946f8e5fd091dbdcb":"11":MBEDTLS_RSA_PKCS_V21:"d436e99569fd32a7c8a05bbc90d32c49":0
+
+RSA Opaque PCKS1 v1.5 - decrypt test vector #2
 depends_on:MBEDTLS_PKCS1_V15
-pk_wrap_rsa_decrypt_test_vec:"a42eda41e56235e666e7faaa77100197f657288a1bf183e4820f0c37ce2c456b960278d6003e0bbcd4be4a969f8e8fd9231e1f492414f00ed09844994c86ec32db7cde3bec7f0c3dbf6ae55baeb2712fa609f5fc3207a824eb3dace31849cd6a6084318523912bccb84cf42e3c6d6d1685131d69bb545acec827d2b0dfdd5568b7dcc4f5a11d6916583fefa689d367f8c9e1d95dcd2240895a9470b0c1730f97cd6e8546860bd254801769f54be96e16362ddcbf34d56035028890199e0f48db38642cb66a4181e028a6443a404feb284ce02b4614b683367d40874e505611d23142d49f06feea831d52d347b13610b413c4efc43a6de9f0b08d2a951dc503b6":2048:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":"3":"4E636AF98E40F3ADCFCCB698F4E80B9F":MBEDTLS_ERR_RSA_INVALID_PADDING
+pk_wrap_rsa_decrypt_test_vec:"a42eda41e56235e666e7faaa77100197f657288a1bf183e4820f0c37ce2c456b960278d6003e0bbcd4be4a969f8e8fd9231e1f492414f00ed09844994c86ec32db7cde3bec7f0c3dbf6ae55baeb2712fa609f5fc3207a824eb3dace31849cd6a6084318523912bccb84cf42e3c6d6d1685131d69bb545acec827d2b0dfdd5568b7dcc4f5a11d6916583fefa689d367f8c9e1d95dcd2240895a9470b0c1730f97cd6e8546860bd254801769f54be96e16362ddcbf34d56035028890199e0f48db38642cb66a4181e028a6443a404feb284ce02b4614b683367d40874e505611d23142d49f06feea831d52d347b13610b413c4efc43a6de9f0b08d2a951dc503b6":2048:"e79a373182bfaa722eb035f772ad2a9464bd842de59432c18bbab3a7dfeae318c9b915ee487861ab665a40bd6cda560152578e8579016c929df99fea05b4d64efca1d543850bc8164b40d71ed7f3fa4105df0fb9b9ad2a18ce182c8a4f4f975bea9aa0b9a1438a27a28e97ac8330ef37383414d1bd64607d6979ac050424fd17":"c6749cbb0db8c5a177672d4728a8b22392b2fc4d3b8361d5c0d5055a1b4e46d821f757c24eef2a51c561941b93b3ace7340074c058c9bb48e7e7414f42c41da4cccb5c2ba91deb30c586b7fb18af12a52995592ad139d3be429add6547e044becedaf31fa3b39421e24ee034fbf367d11f6b8f88ee483d163b431e1654ad3e89":"b38ac65c8141f7f5c96e14470e851936a67bf94cc6821a39ac12c05f7c0b06d9e6ddba2224703b02e25f31452f9c4a8417b62675fdc6df46b94813bc7b9769a892c482b830bfe0ad42e46668ace68903617faf6681f4babf1cc8e4b0420d3c7f61dc45434c6b54e2c3ee0fc07908509d79c9826e673bf8363255adb0add2401039a7bcd1b4ecf0fbe6ec8369d2da486eec59559dd1d54c9b24190965eafbdab203b35255765261cd0909acf93c3b8b8428cbb448de4715d1b813d0c94829c229543d391ce0adab5351f97a3810c1f73d7b1458b97daed4209c50e16d064d2d5bfda8c23893d755222793146d0a78c3d64f35549141486c3b0961a7b4c1a2034f":"3":MBEDTLS_RSA_PKCS_V15:"4E636AF98E40F3ADCFCCB698F4E80B9F":MBEDTLS_ERR_RSA_INVALID_PADDING
 
 EC nocrypt
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS
@@ -499,7 +507,7 @@
 pk_ec_nocrypt:MBEDTLS_PK_ECDSA
 
 RSA_ALT consistency
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_GENPRIME:MBEDTLS_RSA_GEN_KEY_MIN_BITS >= 512
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_rsa_alt:
 
 Verify ext RSA #1 (PKCS1 v2.1, salt_len = ANY, OK)
@@ -644,67 +652,71 @@
 
 PSA wrapped sign: SECP256R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_SECP256R1
-pk_psa_sign:MBEDTLS_ECP_DP_SECP256R1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256
+pk_psa_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:0
 
 PSA wrapped sign: SECP384R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_SECP384R1
-pk_psa_sign:MBEDTLS_ECP_DP_SECP384R1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):384
+pk_psa_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):384:0
 
 PSA wrapped sign: SECP521R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_SECP521R1
-pk_psa_sign:MBEDTLS_ECP_DP_SECP521R1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):521
+pk_psa_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):521:0
 
 PSA wrapped sign: SECP192K1
 depends_on:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_SECP192K1
-pk_psa_sign:MBEDTLS_ECP_DP_SECP192K1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):192
+pk_psa_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):192:0
 
 ## Currently buggy: https://github.com/ARMmbed/mbed-crypto/issues/336
 # PSA wrapped sign: SECP224K1
 # depends_on:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_SECP224K1
-# pk_psa_sign:MBEDTLS_ECP_DP_SECP224K1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):224
+# pk_psa_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):224:0
 
 PSA wrapped sign: SECP256K1
 depends_on:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_SECP256K1
-pk_psa_sign:MBEDTLS_ECP_DP_SECP256K1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):256
+pk_psa_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):256:0
 
 PSA wrapped sign: BP256R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_BP256R1
-pk_psa_sign:MBEDTLS_ECP_DP_BP256R1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):256
+pk_psa_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):256:0
 
 PSA wrapped sign: BP384R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_BP384R1
-pk_psa_sign:MBEDTLS_ECP_DP_BP384R1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):384
+pk_psa_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):384:0
 
 PSA wrapped sign: BP512R1
 depends_on:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_ECP_HAVE_BP512R1
-pk_psa_sign:MBEDTLS_ECP_DP_BP512R1:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):512
+pk_psa_sign:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_BRAINPOOL_P_R1):512:0
 
 PSA wrapped sign: RSA PKCS1 v1.5
-depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_GENPRIME:MBEDTLS_PK_WRITE_C
-pk_psa_sign:1024:PSA_KEY_TYPE_RSA_KEY_PAIR:1024
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
+pk_psa_sign:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:MBEDTLS_RSA_PKCS_V15
+
+PSA wrapped sign: RSA PKCS1 v2.1
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
+pk_psa_sign:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:MBEDTLS_RSA_PKCS_V21
 
 PK sign ext: RSA2048, PK_RSA, MD_SHA256
-depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:MBEDTLS_RSA_GEN_KEY_MIN_BITS <= 2048
+depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C
 pk_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSA:MBEDTLS_MD_SHA256
 
 PK sign ext: RSA2048, PK_RSASSA_PSS, MD_SHA256
-depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:MBEDTLS_RSA_GEN_KEY_MIN_BITS <= 2048
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C
 pk_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA256
 
 PK sign ext: RSA2048, PK_RSA, MD_SHA384
-depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C:MBEDTLS_RSA_GEN_KEY_MIN_BITS <= 2048
+depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C
 pk_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSA:MBEDTLS_MD_SHA384
 
 PK sign ext: RSA2048, PK_RSASSA_PSS, MD_SHA384
-depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C:MBEDTLS_RSA_GEN_KEY_MIN_BITS <= 2048
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C
 pk_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA384
 
 PK sign ext: RSA2048, PK_RSA, MD_SHA512
-depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C:MBEDTLS_RSA_GEN_KEY_MIN_BITS <= 2048
+depends_on:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C
 pk_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSA:MBEDTLS_MD_SHA512
 
 PK sign ext: RSA2048, PK_RSASSA_PSS, MD_SHA512
-depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C:MBEDTLS_RSA_GEN_KEY_MIN_BITS <= 2048
+depends_on:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C
 pk_sign_ext:MBEDTLS_PK_RSA:2048:MBEDTLS_PK_RSASSA_PSS:MBEDTLS_MD_SHA512
 
 PK sign ext: SECP256R1, PK_ECDSA, MD_SHA256
@@ -750,136 +762,136 @@
 
 # Bad usage due to not specifying sign/crypt/derive.
 PSA attributes for pk: RSA usage=0 (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # Bad usage due to not specifying sign/crypt/derive.
 PSA attributes for pk: RSA usage=EXPORT (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_EXPORT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # This usage could make sense, but is not currently supported.
 PSA attributes for pk: RSA usage=DECRYPT|EXPORT (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_EXPORT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # Bad usage due to specifying more than one of sign/crypt/derive.
 PSA attributes for pk: RSA usage=DECRYPT|SIGN_MESSAGE (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # This usage could make sense, but is not currently supported.
 PSA attributes for pk: RSA usage=SIGN_MESSAGE|SIGN_HASH (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # This usage could make sense, but is not currently supported.
 PSA attributes for pk: RSA usage=SIGN_MESSAGE|VERIFY_MESSAGE (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: RSA v15 pair DECRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_DECRYPT:1:PSA_ALG_RSA_PKCS1V15_CRYPT
 
 PSA attributes for pk: RSA v21 SHA-256 pair DECRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA256:FROM_PAIR:PSA_KEY_USAGE_DECRYPT:1:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
 
 PSA attributes for pk: RSA v21 SHA-512 pair DECRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA512:FROM_PAIR:PSA_KEY_USAGE_DECRYPT:1:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512)
 
 PSA attributes for pk: RSA v15 pair->public ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_PKCS1V15_CRYPT
 
 PSA attributes for pk: RSA v21 SHA-256 pair->public ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA256:FROM_PAIR:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
 
 PSA attributes for pk: RSA v21 SHA-512 pair->public ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA512:FROM_PAIR:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512)
 
 PSA attributes for pk: RSA v15 public ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_PKCS1V15_CRYPT
 
 PSA attributes for pk: RSA v21 SHA-256 public ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA256:FROM_PUBLIC:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
 
 PSA attributes for pk: RSA v21 SHA-512 public ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_SHA512:FROM_PUBLIC:PSA_KEY_USAGE_ENCRYPT:0:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512)
 
 PSA attributes for pk: RSA v15 public DECRYPT (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: RSA v15 pair SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_SIGN_MESSAGE:1:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v21 SHA-256 pair SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:FROM_PAIR:PSA_KEY_USAGE_SIGN_MESSAGE:1:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v15 pair SIGN_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_SIGN_HASH:1:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v21 SHA-256 pair SIGN_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:FROM_PAIR:PSA_KEY_USAGE_SIGN_HASH:1:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v15 pair->public VERIFY_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v21 SHA-256 pair->public VERIFY_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:FROM_PAIR:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v15 pair->public VERIFY_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v21 SHA-256 pair->public VERIFY_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:FROM_PAIR:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v15 public VERIFY_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v21 SHA-256 public VERIFY_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_MESSAGE:0:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v15 public VERIFY_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v21 SHA-256 public VERIFY_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V21
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21
 pk_rsa_v21_get_psa_attributes:MBEDTLS_MD_NONE:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_HASH:0:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
 
 PSA attributes for pk: RSA v15 public SIGN_MESSAGE (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: RSA v15 public SIGN_HASH (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: RSA v15 pair DERIVE (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: RSA v15 public DERIVE (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_PKCS1_V15
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15
 pk_get_psa_attributes_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: ECKEY pair DECRYPT (bad)
@@ -1051,164 +1063,164 @@
 pk_get_psa_attributes_fail:MBEDTLS_PK_ECKEY_DH:FROM_PUBLIC:PSA_KEY_USAGE_VERIFY_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA attributes for pk: opaque RSA pair, 0 & SIGN_MESSAGE (bad policy)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:0:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:0:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque RSA pair, SIGN_MESSAGE & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque RSA pair, SIGN|VERIFY & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA attributes for pk: opaque RSA pair, SIGN|DECRYPT & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT
 
 # For a PK_OPAQUE key with a key pair type output,
 # mbedtls_pk_import_into_psa() requires the key to be copyable or exportable.
 # Try all combinations of COPY/not, EXPORT/not.
 PSA attributes for pk: opaque RSA pair, SIGN|... & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque RSA pair, SIGN|EXPORT|... & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque RSA pair, SIGN|COPY|... & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque RSA pair, SIGN|COPY|EXPORT... & SIGN_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque RSA pair, SIGN_MESSAGE & SIGN_HASH (bad policy)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 # For a PK_OPAQUE key, mbedtls_pk_get_psa_attributes() ignores the input
 # key's algorithm policy. Just this time, test with a few different algorithms.
 PSA attributes for pk: opaque RSA pair, SIGN_HASH & SIGN_HASH [0]
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_NONE:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque RSA pair, SIGN_HASH & SIGN_HASH [raw]
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque RSA pair, SIGN_HASH & SIGN_HASH [v15]
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque RSA pair, SIGN_HASH & SIGN_HASH [PSS]
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque RSA pair, 0 & DECRYPT (bad policy)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:0:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:0:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque RSA pair, DECRYPT & DECRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:0:1:PSA_KEY_USAGE_DECRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:0:1:PSA_KEY_USAGE_DECRYPT
 
 PSA attributes for pk: opaque RSA pair, DECRYPT|... & DECRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DECRYPT:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque RSA pair, ... & DERIVE (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque RSA pair, ... & EXPORT (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_EXPORT:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_EXPORT:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque RSA pair->public, VERIFY_MESSAGE & VERIFY_MESSAGE
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_VERIFY_MESSAGE:0:0:PSA_KEY_USAGE_VERIFY_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_VERIFY_MESSAGE:0:0:PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA attributes for pk: opaque RSA pair->public, VERIFY_HASH & VERIFY_HASH
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_VERIFY_HASH:0:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_USAGE_VERIFY_HASH:0:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA attributes for pk: opaque RSA pair->public, ENCRYPT & ENCRYPT
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_ENCRYPT:0:0:PSA_KEY_USAGE_ENCRYPT
+depends_on:MBEDTLS_RSA_C
+pk_get_psa_attributes_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_KEY_USAGE_ENCRYPT:0:0:PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque ECC pair, 0 & SIGN_MESSAGE (bad policy)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:0:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_SIGN_MESSAGE:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque ECC pair, SIGN_MESSAGE & SIGN_MESSAGE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque ECC pair, SIGN|VERIFY & SIGN_MESSAGE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA attributes for pk: opaque ECC pair, SIGN|DECRYPT & SIGN_MESSAGE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_DECRYPT
 
 PSA attributes for pk: opaque ECC pair, SIGN|... & SIGN_MESSAGE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_SIGN_MESSAGE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT
 
 PSA attributes for pk: opaque ECC pair, SIGN_HASH & SIGN_HASH
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_SIGN_HASH:0:1:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE
 
 PSA attributes for pk: opaque ECC pair, ... & DERIVE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_KEY_USAGE_DERIVE:0:1:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DERIVE
 
 PSA attributes for pk: opaque ECC pair, ... & DECRYPT (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque ECC pair, ... & EXPORT (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_DECRYPT | PSA_KEY_USAGE_ENCRYPT:PSA_ALG_ECDH:PSA_KEY_USAGE_EXPORT:MBEDTLS_ERR_PK_TYPE_MISMATCH:1:0
 
 PSA attributes for pk: opaque ECC pair->public, VERIFY_MESSAGE & VERIFY_MESSAGE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_VERIFY_MESSAGE:0:0:PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA attributes for pk: opaque ECC pair->public, VERIFY_HASH & VERIFY_HASH
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_VERIFY_HASH:0:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE
 
 PSA attributes for pk: opaque ECC pair->public, ENCRYPT & ENCRYPT (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256
+depends_on:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PK_HAVE_ECC_KEYS
 pk_get_psa_attributes_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_ECDSA_ANY:PSA_KEY_USAGE_ENCRYPT:MBEDTLS_ERR_PK_TYPE_MISMATCH:0:0
 
 PSA import into PSA: RSA pair to ECC (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: RSA public to RSA pair (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
+depends_on:MBEDTLS_RSA_C
 pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_TYPE_RSA_KEY_PAIR:0:MBEDTLS_ERR_RSA_BAD_INPUT_DATA
 
 # MBEDTLS_ERR_PK_INVALID_ALG is the error that results from our translation
 # of PSA errors. In this case MBEDTLS_ERR_PK_TYPE_MISMATCH would probably
 # be more appropriate. (Applies to all the RSA "different bits" test cases.)
 PSA import into PSA: RSA pair to different bits (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 8:MBEDTLS_ERR_PK_INVALID_ALG
+depends_on:MBEDTLS_RSA_C
+pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE + 8:MBEDTLS_ERR_PK_INVALID_ALG
 
 PSA import into PSA: RSA public to different bits (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 8:MBEDTLS_ERR_PK_INVALID_ALG
+depends_on:MBEDTLS_RSA_C
+pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PUBLIC:PSA_KEY_TYPE_RSA_PUBLIC_KEY:RSA_KEY_SIZE + 8:MBEDTLS_ERR_PK_INVALID_ALG
 
 PSA import into PSA: RSA private to public, different bits (bad)
-depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME
-pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 8:MBEDTLS_ERR_PK_INVALID_ALG
+depends_on:MBEDTLS_RSA_C
+pk_import_into_psa_fail:MBEDTLS_PK_RSA:FROM_PAIR:PSA_KEY_TYPE_RSA_PUBLIC_KEY:RSA_KEY_SIZE + 8:MBEDTLS_ERR_PK_INVALID_ALG
 
 PSA import into PSA: ECKEY pair to RSA (bad)
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE
@@ -1306,148 +1318,357 @@
 depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PK_CAN_ECDSA_SOME
 pk_import_into_psa_fail:MBEDTLS_PK_ECDSA:FROM_PUBLIC:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):0:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
+PSA import into PSA: transparent -> volatile pair
+pk_import_into_psa_lifetime:0:0:1:0:0
+
+PSA import into PSA: transparent -> persistent pair
+pk_import_into_psa_lifetime:0:0:1:0:1
+
+PSA import into PSA: transparent -> volatile public
+pk_import_into_psa_lifetime:0:0:1:1:0
+
+PSA import into PSA: transparent -> persistent public
+pk_import_into_psa_lifetime:0:0:1:1:1
+
+PSA import into PSA: opaque volatile [export] -> volatile pair
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:0:1:0:0
+
+PSA import into PSA: opaque volatile [export] -> persistent pair
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:0:1:0:1
+
+PSA import into PSA: opaque volatile [export] -> volatile public
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:0:1:1:0
+
+PSA import into PSA: opaque volatile [export] -> persistent public
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:0:1:1:1
+
+PSA import into PSA: opaque volatile [copy] -> volatile pair
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:0:0:0:0
+
+PSA import into PSA: opaque volatile [copy] -> persistent pair
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:0:0:0:1
+
+PSA import into PSA: opaque volatile [copy] -> volatile public
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:0:0:1:0
+
+PSA import into PSA: opaque volatile [copy] -> persistent public
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:0:0:1:1
+
+PSA import into PSA: opaque persistent [export] -> volatile pair
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:1:1:0:0
+
+PSA import into PSA: opaque persistent [export] -> persistent pair
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:1:1:0:1
+
+PSA import into PSA: opaque persistent [export] -> volatile public
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:1:1:1:0
+
+PSA import into PSA: opaque persistent [export] -> persistent public
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:1:1:1:1
+
+PSA import into PSA: opaque persistent [copy] -> volatile pair
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:1:0:0:0
+
+PSA import into PSA: opaque persistent [copy] -> persistent pair
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:1:0:0:1
+
+PSA import into PSA: opaque persistent [copy] -> volatile public
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:1:0:1:0
+
+PSA import into PSA: opaque persistent [copy] -> persistent public
+depends_on:MBEDTLS_USE_PSA_CRYPTO
+pk_import_into_psa_lifetime:1:1:0:1:1
+
 PSA import into PSA: opaque RSA, COPY (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 PSA import into PSA: opaque RSA, EXPORT (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 PSA import into PSA: opaque RSA, no COPY/EXPORT (bad)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:MBEDTLS_ERR_PK_TYPE_MISMATCH
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # Detail that isn't precisely documented: since this copies the key,
 # the new key has the intersection of the usage flags.
 PSA import into PSA: opaque RSA, COPY|EXPORT, different usage (restricted)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 # Detail that isn't precisely documented: since this copies the key,
 # the new key has the intersection of the usage flags.
 PSA import into PSA: opaque RSA, COPY, different usage (restricted)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 # Detail that isn't precisely documented: since this exports the key,
 # the new key has all the requested usage flags.
 PSA import into PSA: opaque RSA, EXPORT, different usage (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 PSA import into PSA: opaque RSA, COPY|EXPORT, different algorithm (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
 
 PSA import into PSA: opaque RSA, COPY, different algorithm (bad)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):MBEDTLS_ERR_PK_TYPE_MISMATCH
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque RSA, EXPORT, different algorithm (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256):0
 
 PSA import into PSA: opaque RSA, implicit bits (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 PSA import into PSA: opaque RSA, different bits (bad)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:MBEDTLS_ERR_PK_TYPE_MISMATCH
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE + 8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque RSA, different type (bad)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:PSA_KEY_TYPE_HMAC:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:PSA_KEY_TYPE_HMAC:RSA_KEY_SIZE:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque RSA to public (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_PUBLIC_KEY:RSA_KEY_SIZE:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 PSA import into PSA: opaque RSA to public, implicit bits (ok)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_PUBLIC_KEY:0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:0
 
 # MBEDTLS_ERR_PK_INVALID_ALG is the error that results from our translation
 # of PSA errors. In this case MBEDTLS_ERR_PK_TYPE_MISMATCH would probably
 # be more appropriate.
 PSA import into PSA: opaque RSA to public, different bits (bad)
-depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:MBEDTLS_RSA_GEN_KEY_MIN_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_RSA_GEN_KEY_MIN_BITS + 8:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:MBEDTLS_ERR_PK_INVALID_ALG
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+pk_import_into_psa_opaque:PSA_KEY_TYPE_RSA_KEY_PAIR:RSA_KEY_SIZE:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_KEY_TYPE_RSA_PUBLIC_KEY:RSA_KEY_SIZE + 8:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:MBEDTLS_ERR_PK_INVALID_ALG
 
 PSA import into PSA: opaque ECC, COPY (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 PSA import into PSA: opaque ECC, EXPORT (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 PSA import into PSA: opaque ECC, no COPY/EXPORT (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 # Detail that isn't precisely documented: since this copies the key,
 # the new key has the intersection of the usage flags.
 PSA import into PSA: opaque ECC, COPY|EXPORT, different usage (restricted)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 # Detail that isn't precisely documented: since this copies the key,
 # the new key has the intersection of the usage flags.
 PSA import into PSA: opaque ECC, COPY, different usage (restricted)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 # Detail that isn't precisely documented: since this exports the key,
 # the new key has all the requested usage flags.
 PSA import into PSA: opaque ECC, EXPORT, different usage (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 PSA import into PSA: opaque ECC, COPY|EXPORT, different algorithm (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0
 
 PSA import into PSA: opaque ECC, COPY, different algorithm (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque ECC, EXPORT, different algorithm (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):0
 
 PSA import into PSA: opaque ECC, implicit bits (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):0:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 PSA import into PSA: opaque ECC, different bits (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS + 8:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque ECC, different type (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:PSA_KEY_TYPE_HMAC:MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque ECC, different family (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
 
 PSA import into PSA: opaque ECC to public (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 PSA import into PSA: opaque ECC to public, implicit bits (ok)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):0:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):0
 
 # MBEDTLS_ERR_PK_INVALID_ALG is the error that results from our translation
 # of PSA errors. In this case MBEDTLS_ERR_PK_TYPE_MISMATCH would probably
 # be more appropriate.
 PSA import into PSA: opaque ECC to public, different bits (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS + 8:PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE:PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):MBEDTLS_ERR_PK_INVALID_ALG
 
 PSA import into PSA: opaque ECC to public, different family (bad)
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES:PSA_WANT_ALG_ECDSA
+depends_on:MBEDTLS_TEST_PSA_ECC_HAVE_TWO_FAMILIES:PSA_WANT_ALG_ECDSA
 pk_import_into_psa_opaque:PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:PSA_KEY_TYPE_ECC_PUBLIC_KEY(MBEDTLS_TEST_PSA_ECC_ANOTHER_FAMILY):MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS:PSA_KEY_USAGE_COPY | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE:0:MBEDTLS_ERR_PK_TYPE_MISMATCH
+
+Copy from PSA: use wrong parameters
+pk_copy_from_psa_fail:
+
+# The following test is only possible for RSA keys and not for EC ones:
+# - for the former it is possible to have an accelerated RSA key in PSA while
+#   having RSA_C disabled. Since RSA path is guarded by RSA_C in mbedtls_pk_copy_from_psa(),
+#   any attempt to copy that key will fail.
+# - for the latter instead the guard is PK_HAVE_ECC_KEYS which is enabled as soon
+#   as there is any curve supported either builtin or in a driver. In a scenario
+#   in which a certain EC key is only available through a driver and not as
+#   builtin mbedtls_pk_copy_from_psa() uses functions that will all succeed
+#   and therefore it will succeed.
+Copy from PSA: accelerated key only, not available as built-in
+pk_copy_from_psa_builtin_fail:
+
+Copy from PSA: valid EC (SECP_R1_256 + ECDSA + ANY_HASH)
+depends_on:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_MD_ALG_FOR_TEST
+pk_copy_from_psa_success:"587CF7C57EB7C6254CBF80CC59846521B4FBCBA8BC4B362A9B043F0DEB49CCA1":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_ECDSA(PSA_ALG_ANY_HASH)
+
+Copy from PSA: valid EC (SECP_R1_256 + ECDSA + SHA_256)
+depends_on:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_MD_CAN_SHA256
+pk_copy_from_psa_success:"587CF7C57EB7C6254CBF80CC59846521B4FBCBA8BC4B362A9B043F0DEB49CCA1":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_ECDSA(PSA_ALG_SHA_256)
+
+Copy from PSA: valid EC (SECP_R1_256 + ECDSA + SHA_512)
+depends_on:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_MD_CAN_SHA512
+pk_copy_from_psa_success:"587CF7C57EB7C6254CBF80CC59846521B4FBCBA8BC4B362A9B043F0DEB49CCA1":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_ECDSA(PSA_ALG_SHA_512)
+
+Copy from PSA: valid EC (SECP_R1_256 + DET_ECDSA + ANY_HASH)
+depends_on:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_MD_ALG_FOR_TEST
+pk_copy_from_psa_success:"587CF7C57EB7C6254CBF80CC59846521B4FBCBA8BC4B362A9B043F0DEB49CCA1":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH)
+
+Copy from PSA: valid EC (SECP_R1_256 + DET_ECDSA + SHA_256)
+depends_on:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_MD_CAN_SHA256
+pk_copy_from_psa_success:"587CF7C57EB7C6254CBF80CC59846521B4FBCBA8BC4B362A9B043F0DEB49CCA1":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)
+
+Copy from PSA: valid EC (SECP_R1_256 + DET_ECDSA + SHA_512)
+depends_on:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_MD_CAN_SHA512
+pk_copy_from_psa_success:"587CF7C57EB7C6254CBF80CC59846521B4FBCBA8BC4B362A9B043F0DEB49CCA1":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_512)
+
+Copy from PSA: valid EC (SECP_R1_256 + ECDSA_ANY)
+depends_on:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_MD_ALG_FOR_TEST
+pk_copy_from_psa_success:"587CF7C57EB7C6254CBF80CC59846521B4FBCBA8BC4B362A9B043F0DEB49CCA1":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_ECDSA_ANY
+
+Copy from PSA: valid EC (SECP_R1_521 + ECDSA + SHA_256)
+depends_on:MBEDTLS_ECP_HAVE_SECP521R1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_MD_CAN_SHA256
+pk_copy_from_psa_success:"005dbb8e12240a62932b88cdd93c31cdd8873a2c15e40cc3c9f8e695b77fae015a44fe5267ef7868cb28cfb9579282fe060de44fe6de26f74a0d94afdaa870befbc5":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_ECDSA(PSA_ALG_SHA_256)
+
+Copy from PSA: valid EC (SECP_K1_256 + ECDSA + SHA_256)
+depends_on:MBEDTLS_ECP_HAVE_SECP256K1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_MD_CAN_SHA256
+pk_copy_from_psa_success:"7154f04fcc79ac9df1652dcf99031610592b2b27f74f5985690a987357ba0428":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_K1):PSA_ALG_ECDSA(PSA_ALG_SHA_256)
+
+# The key's algorithm only allows ECDH, but pk_copy_from_psa() ignores this information
+# when building the PK context.
+Copy from PSA: valid EC, wrong alg (SECP_R1_256 + ECDH)
+depends_on:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_MD_CAN_SHA256
+pk_copy_from_psa_success:"587CF7C57EB7C6254CBF80CC59846521B4FBCBA8BC4B362A9B043F0DEB49CCA1":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_ECDH
+
+# The key's algorithm is absolutely wrong for an EC key, but pk_copy_from_psa()
+# ignores this information when building the PK context.
+Copy from PSA: valid EC, wrong alg (SECP_R1_256 + CMAC)
+depends_on:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_PK_CAN_ECDSA_SIGN:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_MD_CAN_SHA256
+pk_copy_from_psa_success:"587CF7C57EB7C6254CBF80CC59846521B4FBCBA8BC4B362A9B043F0DEB49CCA1":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):PSA_ALG_CMAC
+
+Copy from PSA: valid RSA (PKCS1V15_SIGN + ANY_HASH)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_MD_ALG_FOR_TEST
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH)
+
+Copy from PSA: valid RSA (PKCS1V15_SIGN + SHA_256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA256
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256)
+
+Copy from PSA: valid RSA (PKCS1V15_SIGN + SHA_512)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA512
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_512)
+
+Copy from PSA: valid RSA (PKCS1V15_CRYPT)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_MD_ALG_FOR_TEST
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PKCS1V15_CRYPT
+
+Copy from PSA: valid RSA (OAEP + SHA_256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256)
+
+Copy from PSA: valid RSA (OAEP + SHA_512)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_512)
+
+Copy from PSA: valid RSA (PSS_ANY_SALT + ANY_HASH)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_ALG_FOR_TEST
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH)
+
+Copy from PSA: valid RSA (PSS_ANY_SALT + SHA_256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256)
+
+Copy from PSA: valid RSA (PSS_ANY_SALT + SHA_512)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_512)
+
+Copy from PSA: valid RSA (PSS + ANY_HASH)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_ALG_FOR_TEST
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH)
+
+Copy from PSA: valid RSA (PSS + SHA_256)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA256
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256)
+
+Copy from PSA: valid RSA (PSS + SHA_512)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_MD_CAN_SHA512
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_RSA_PSS(PSA_ALG_SHA_512)
+
+Copy from PSA: valid RSA, PSA_ALG_NONE
+depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_ALG_FOR_TEST
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_NONE
+
+# Key's algorithm is wrong for an RSA key, but pk_copy_from_psa() accepts
+# it anyway.
+Copy from PSA: valid RSA, wrong alg (CMAC)
+depends_on:MBEDTLS_RSA_C:MBEDTLS_MD_ALG_FOR_TEST
+pk_copy_from_psa_success:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_ALG_CMAC
+
+Copy from PSA: non-exportable -> public, RSA
+depends_on:MBEDTLS_RSA_C
+pk_copy_public_from_psa:"308204a40201000282010100ef24d80f6b7a0f62ab2f750a8370c1c39781abe2f7ae5cbc698ebbc51067af68c8b02e5bfafe0b296a2fdca8ee5327bf3370bd26c529d173c4356d8ad51f606ac730e3be509d8535c9c51927222d6c4e770efec4d9b0bd11410e5e2e01e093700d358aab8292297483c65870ea6d4ca9299f4347790f6223480732726a97b34bb4d53cb3f188e3c97115b029fa9a2cce4c6d935977a90737ac8b2a2c5691ad928b22681ca05ee38ddba2278c854f51281c5e4856090aca59bf719a167e63bb932580ae2b599e1a297194696e637a919bc9d2caf214e59d46ed1a12e591b608f2031744111551430d9ac39082957ae1ce03a88068896701e6ce19a83890ff5761020301000102820100706fb53a02c13fcc9749d7d09a9e002c12e6bfc715c6a00961e3defab74cd896fe8c7f2f75e1cda3aa2e58a400718e65822d0671dd0f5d4ffdb7550a8a4b974c7cdccaa72745f864a2ba0daa6d9247b2d89d6f41644c89883c3b2222a5754e3cc7a91dcaa7b84acf6249763998aeccf558016e638352ad44835006f2ee94e691d0070ce561677f2a22a12f357bd762c57f80f1f4921f0f26b3ed758478d11086c182874355ef5039e8d854291b9ce7f8b284ec81f141b7255313507f5ea159d6b1c0ee176e7743d3c65d536e1e4aaf24089c1e00c8021012b8846a4971a0695030504ace362077e8b2fcb4fbdd70bfb734a3fe7d9e1a25bdd0cb0f2fcb56ecc502818100f8fdfbac1c033911b5a184980d081f700f4d450cebf18cbdc68f160a5abd580e6f8f5800fd0b60521dbe2d549e82617afe70d2ad004c2f45405d94e4418e8c2b8da6bcaa407bbfa5477b5a6fceccfcb99f51c6c16bd17202d997bdcaec83b870e3e101acc05e0754020ec207ef5ec9934ac81cd617af72cd94b2bb400eb2078302818100f5dfe74a548c04950178f50130d5aadbe5d1f4b52527c0bfad9aa0d73731fb24219cb5ea5c4b4fa56133d5ea9225fa7d0ccc9bdcc78b77303a2e73c17e9a46b9b09020604496a849f069d0d87713e06a5d374271b2629f5ba220506b606a101828d20da9fcfa3a7e75b135987260be6d37622fc3f4bf4fd2dfd9655da5ff0c4b02818100d4d797c959f0cf59fa1f65ceec64e32ad189c5daf3ddf9e747d28c8eb15e65e5812bd19896b6a0d1d126fe6cf54a92b5a6c71ef04feed001acb1d253044f2c3716d14f396201e6a30c65bfbb0fd65ebaf61bdb80ffff7c2c3f80dcf69813491907531231700770d0392a1066e411ecd201fce9d98149b32355572b85e889faad028181009d898bc165709d52f7b18f91e6bf508d3ab08ed12df04da0c2d40b7039ce4d72b61299c082c8424cdd7dfff71f13346ec12fac42069cc68e6108f86427012485bfaa6904258e3e5fb9a9a305bf2e3e21087eea94bcce51fabd63650397affd85ed49c1358480b3cfe90ad5234b4dcf555d220d26c9ff765ecfcc94152fd1be070281804bf77b4bae8386772de830cc75f2d1d4b8221b3f817208e08c002ac0549902677e4f0e7bce5ba1b3da74fbbe138758e6853b4a5b7bf0672bc1170c64fa502a5e24e3472db433b4e30761eab6ebb9e207235fd88b97b1b30e14f364b628219d6e17056543a4e29a4de1e41ad37927ce23d0442623744bc35a1874296960029044":PSA_KEY_TYPE_RSA_KEY_PAIR
+
+Copy from PSA: non-exportable -> public, SECP_R1_256
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_ECP_HAVE_SECP256R1
+pk_copy_public_from_psa:"587CF7C57EB7C6254CBF80CC59846521B4FBCBA8BC4B362A9B043F0DEB49CCA1":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1)
+
+Copy from PSA: non-exportable -> public, Curve25519
+depends_on:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_ECP_HAVE_CURVE25519
+pk_copy_public_from_psa:"a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY)
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 3d75ad0..ad7da32 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -1,5 +1,6 @@
 /* BEGIN_HEADER */
 #include "mbedtls/pk.h"
+#include "mbedtls/psa_util.h"
 #include "pk_internal.h"
 
 /* For error codes */
@@ -8,6 +9,7 @@
 #include "mbedtls/ecp.h"
 #include "mbedtls/error.h"
 #include "mbedtls/rsa.h"
+#include "rsa_internal.h"
 #include "pk_internal.h"
 
 #include <limits.h>
@@ -19,13 +21,12 @@
 #include "psa/crypto.h"
 #include "mbedtls/psa_util.h"
 
+#include "pkwrite.h"
+
 #include <test/psa_exercise_key.h>
 
-/* Used for properly sizing the key buffer in pk_genkey_ec() */
-#include "psa_util_internal.h"
-
-#define RSA_KEY_SIZE   MBEDTLS_RSA_GEN_KEY_MIN_BITS
-#define RSA_KEY_LEN   (MBEDTLS_RSA_GEN_KEY_MIN_BITS/8)
+/* Needed for the definition of MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE. */
+#include "pkwrite.h"
 
 #if defined(MBEDTLS_RSA_C) ||                                           \
     defined(MBEDTLS_PK_RSA_ALT_SUPPORT) ||                              \
@@ -39,8 +40,7 @@
  * - The build has built-in ECC and ECDSA signature.
  */
 #if (defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_PK_WRITE_C) && \
-    ((defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)) || \
-    defined(MBEDTLS_PK_CAN_ECDSA_SIGN))) || \
+    (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_CAN_ECDSA_SIGN))) || \
     (defined(MBEDTLS_ECP_C) && defined(MBEDTLS_PK_CAN_ECDSA_SIGN))
 #define MBEDTLS_TEST_PK_PSA_SIGN
 #endif
@@ -167,123 +167,203 @@
 #define MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS 0
 #endif
 
-#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
-static int pk_genkey_ec(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id)
-{
-    psa_status_t status;
-    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
-    size_t curve_bits;
-    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(grp_id, &curve_bits);
-    int ret;
-
-    if (curve == 0) {
-        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-    }
-
-    psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
-    psa_set_key_bits(&key_attr, curve_bits);
-    psa_key_usage_t usage = PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY;
-    psa_algorithm_t sign_alg = 0;
-    psa_algorithm_t derive_alg = 0;
-    if (mbedtls_pk_get_type(pk) != MBEDTLS_PK_ECDSA) {
-        usage |= PSA_KEY_USAGE_DERIVE;
-        derive_alg = PSA_ALG_ECDH;
-    }
-    if (mbedtls_pk_get_type(pk) != MBEDTLS_PK_ECKEY_DH &&
-        curve != PSA_ECC_FAMILY_MONTGOMERY) {
-        usage |= PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE;
-#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
-        sign_alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH);
-#else
-        sign_alg = PSA_ALG_ECDSA(PSA_ALG_ANY_HASH);
+/* Get an available MD alg to be used in sign/verify tests. */
+#if defined(MBEDTLS_MD_CAN_SHA1)
+#define MBEDTLS_MD_ALG_FOR_TEST         MBEDTLS_MD_SHA1
+#elif defined(MBEDTLS_MD_CAN_SHA224)
+#define MBEDTLS_MD_ALG_FOR_TEST         MBEDTLS_MD_SHA224
+#elif defined(MBEDTLS_MD_CAN_SHA256)
+#define MBEDTLS_MD_ALG_FOR_TEST         MBEDTLS_MD_SHA256
+#elif defined(MBEDTLS_MD_CAN_SHA384)
+#define MBEDTLS_MD_ALG_FOR_TEST         MBEDTLS_MD_SHA384
+#elif defined(MBEDTLS_MD_CAN_SHA512)
+#define MBEDTLS_MD_ALG_FOR_TEST         MBEDTLS_MD_SHA512
 #endif
-    }
-    if (derive_alg != 0) {
-        psa_set_key_algorithm(&key_attr, derive_alg);
-        if (sign_alg != 0) {
-            psa_set_key_enrollment_algorithm(&key_attr, sign_alg);
-        }
-    } else {
-        psa_set_key_algorithm(&key_attr, sign_alg);
-    }
-    psa_set_key_usage_flags(&key_attr, usage);
 
-    status = psa_generate_key(&key_attr, &pk->priv_id);
-    if (status != PSA_SUCCESS) {
-        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-    }
+#include <../src/test_keys.h>
 
-    status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw),
-                                   &pk->pub_raw_len);
-    if (status != PSA_SUCCESS) {
-        ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-        goto exit;
-    }
+/* Define an RSA key size we know it's present in predefined_key[] array. */
+#define RSA_KEY_SIZE   1024
+#define RSA_KEY_LEN   (RSA_KEY_SIZE/8)
 
-    pk->ec_family = curve;
-    pk->ec_bits = curve_bits;
-
-    return 0;
-
-exit:
-    status = psa_destroy_key(pk->priv_id);
-    return (ret != 0) ? ret : psa_pk_status_to_mbedtls(status);
-}
-#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
-
-/** Generate a key of the desired type.
- *
- * \param pk               The PK object to fill. It must have been initialized
- *                         with mbedtls_pk_setup().
- * \param curve_or_keybits - For RSA keys, the key size in bits.
- *                         - For EC keys, the curve (\c MBEDTLS_ECP_DP_xxx).
- *
- * \return                 The status from the underlying type-specific key
- *                         generation function.
- * \return                 -1 if the key type is not recognized.
- */
-static int pk_genkey(mbedtls_pk_context *pk, int curve_or_keybits)
+static int get_predefined_key_data(int is_ec, int group_id_or_keybits,
+                                   const unsigned char **key, size_t *key_len,
+                                   const unsigned char **pub_key, size_t *pub_key_len)
 {
-    (void) pk;
-    (void) curve_or_keybits;
+    size_t i;
+    struct predefined_key_element *predefined_key = NULL;
 
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)
-    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA) {
-        return mbedtls_rsa_gen_key(mbedtls_pk_rsa(*pk),
-                                   mbedtls_test_rnd_std_rand, NULL,
-                                   curve_or_keybits, 3);
-    }
-#endif
-#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
-    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY ||
-        mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY_DH ||
-        mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECDSA) {
-        int ret;
-
-#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
-        ret = pk_genkey_ec(pk, curve_or_keybits);
-        if (ret != 0) {
-            return ret;
+    for (i = 0; i < ARRAY_LENGTH(predefined_keys); i++) {
+        if (is_ec) {
+            if (group_id_or_keybits == predefined_keys[i].group_id) {
+                predefined_key = &predefined_keys[i];
+            }
+        } else if (group_id_or_keybits == predefined_keys[i].keybits) {
+            predefined_key = &predefined_keys[i];
         }
+    }
 
+    if (predefined_key != NULL) {
+        *key = predefined_key->priv_key;
+        *key_len = predefined_key->priv_key_len;
+        if (pub_key != NULL) {
+            *pub_key = predefined_key->pub_key;
+            *pub_key_len = predefined_key->pub_key_len;
+        }
         return 0;
-#else
-        ret = mbedtls_ecp_group_load(&mbedtls_pk_ec_rw(*pk)->grp, curve_or_keybits);
-        if (ret != 0) {
-            return ret;
-        }
-        return mbedtls_ecp_gen_keypair(&mbedtls_pk_ec_rw(*pk)->grp,
-                                       &mbedtls_pk_ec_rw(*pk)->d,
-                                       &mbedtls_pk_ec_rw(*pk)->Q,
-                                       mbedtls_test_rnd_std_rand, NULL);
-#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
-
     }
-#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
-    return -1;
+
+    TEST_FAIL("Unsupported key");
+    /* "exit" label is to make the compiler happy. */
+exit:
+    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
 }
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
+psa_status_t pk_psa_import_key(const unsigned char *key_data, size_t key_len,
+                               psa_key_type_t type, psa_key_usage_t usage,
+                               psa_algorithm_t alg, mbedtls_svc_key_id_t *key)
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status;
+
+    *key = MBEDTLS_SVC_KEY_ID_INIT;
+
+    /* Note: psa_import_key() automatically determines the key's bit length
+     * from the provided key data. That's why psa_set_key_bits() is not used below. */
+    psa_set_key_usage_flags(&attributes, usage);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, type);
+    status = psa_import_key(&attributes, key_data, key_len, key);
+
+    return status;
+}
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+/** Setup the provided PK context.
+ *
+ * Predefined keys used for the setup are taken from "test/src/test_keys.h"
+ * which is automatically generated using "tests/scripts/generate_test_keys.py".
+ *
+ * \param pk               The PK object to fill. It must  have been initialized
+ *                         (mbedtls_pk_init()), but not setup (mbedtls_pk_setup()).
+ * \param pk_type          mbedtls_pk_type_t to use in the PK context.
+ * \param curve_or_keybits - For RSA keys, the key size in bits.
+ *                         - For EC keys, the curve (\c MBEDTLS_ECP_DP_xxx).
+ *
+ * \return                 0 on success or a negative value otherwise.
+ */
+static int pk_setup(mbedtls_pk_context *pk, mbedtls_pk_type_t pk_type, int curve_or_keybits)
+{
+    const unsigned char *key_data = NULL;
+    const unsigned char *pub_key_data = NULL;
+    size_t key_data_len = 0;
+    size_t pub_key_data_len = 0;
+    int ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+
+    TEST_EQUAL(mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(pk_type)), 0);
+
+    if (pk_type == MBEDTLS_PK_RSA) {
+#if defined(MBEDTLS_RSA_C)
+        TEST_EQUAL(get_predefined_key_data(0, curve_or_keybits, &key_data, &key_data_len,
+                                           NULL, 0), 0);
+        TEST_EQUAL(mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key_data, key_data_len), 0);
+#else /* MBEDTLS_RSA_C */
+        TEST_FAIL("RSA keys not supported.");
+#endif /* MBEDTLS_RSA_C */
+    } else {
+        TEST_EQUAL(get_predefined_key_data(1, curve_or_keybits, &key_data, &key_data_len,
+                                           &pub_key_data, &pub_key_data_len), 0);
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+        pk->ec_family = mbedtls_ecc_group_to_psa(curve_or_keybits, &pk->ec_bits);
+        TEST_EQUAL(pk_psa_import_key(key_data, key_data_len,
+                                     PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family),
+                                     PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH |
+                                     PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE |
+                                     PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_COPY |
+                                     PSA_KEY_USAGE_EXPORT,
+                                     MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH),
+                                     &pk->priv_id), 0);
+        memcpy(pk->pub_raw, pub_key_data, pub_key_data_len);
+        pk->pub_raw_len = pub_key_data_len;
+#elif defined(MBEDTLS_ECP_C)
+        TEST_EQUAL(mbedtls_ecp_read_key(curve_or_keybits, mbedtls_pk_ec_rw(*pk),
+                                        key_data, key_data_len), 0);
+        TEST_EQUAL(mbedtls_ecp_point_read_binary(&(mbedtls_pk_ec_rw(*pk)->grp),
+                                                 &(mbedtls_pk_ec_rw(*pk)->Q),
+                                                 pub_key_data, pub_key_data_len), 0);
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */
+        TEST_FAIL("EC keys not supported.");
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */
+    }
+    /* Override pk_info. */
+    pk->pk_info = mbedtls_pk_info_from_type(pk_type);
+    ret = 0;
+
+exit:
+    return ret;
+}
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+/** Create a PSA key of the desired type and properties.
+ *
+ * - For RSA and EC keys predefined key data is used (as in the pk_setup() above).
+ * - Other key types (ex: DH) are generated at runtime.
+ *
+ * \param type                  PSA key type.
+ * \param bits                  PSA key bit size.
+ * \param usage                 PSA key usage flags.
+ * \param alg                   PSA key primary algorithm.
+ * \param enrollment_alg        PSA key enrollment algorithm.
+ * \param persistent_key_id     PSA key ID for persistent keys. Set to PSA_KEY_ID_NULL
+ *                              for volatile keys.
+ * \param[out] key              Identifier of the "generated" (actually imported) PSA key.
+ */
+psa_status_t pk_psa_setup(psa_key_type_t type, size_t bits,
+                          psa_key_usage_t usage, psa_algorithm_t alg,
+                          psa_algorithm_t enrollment_alg,
+                          mbedtls_svc_key_id_t persistent_key_id,
+                          mbedtls_svc_key_id_t *key)
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    const unsigned char *key_data = NULL;
+    size_t key_data_size = 0;
+
+    *key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_set_key_usage_flags(&attributes, usage);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_enrollment_algorithm(&attributes, enrollment_alg);
+    psa_set_key_type(&attributes, type);
+    psa_set_key_bits(&attributes, bits);
+    if (!mbedtls_svc_key_id_is_null(persistent_key_id)) {
+        psa_set_key_id(&attributes, persistent_key_id);
+    }
+
+    /* For EC and RSA keys we use predefined keys in order to:
+     * - speed up testing and
+     * - ease requirements/dependencies on test cases.
+     * For other keys (ex: DH) psa_generate_key() is used instead. */
+    if (PSA_KEY_TYPE_IS_RSA(type)) {
+        TEST_EQUAL(get_predefined_key_data(0, bits, &key_data, &key_data_size, NULL, 0), 0);
+    } else if (PSA_KEY_TYPE_IS_ECC(type)) {
+#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+        mbedtls_ecp_group_id grp_id;
+        grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type), bits);
+        TEST_EQUAL(get_predefined_key_data(1, grp_id, &key_data, &key_data_size, NULL, 0), 0);
+#else /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
+        TEST_FAIL("EC keys are not supported");
+#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
+    } else {
+        return psa_generate_key(&attributes, key);
+    }
+
+    status = psa_import_key(&attributes, key_data, key_data_size, key);
+
+exit:
+    return status;
+}
+
 static psa_key_usage_t pk_get_psa_attributes_implied_usage(
     psa_key_usage_t expected_usage)
 {
@@ -307,6 +387,83 @@
     expected_usage |= PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY;
     return expected_usage;
 }
+
+#define RSA_WRITE_PUBKEY_MAX_SIZE                                       \
+    PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)
+#define ECP_WRITE_PUBKEY_MAX_SIZE                                       \
+    PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
+static int pk_public_same(const mbedtls_pk_context *pk1,
+                          const mbedtls_pk_context *pk2)
+{
+    int ok = 0;
+
+    mbedtls_pk_type_t type = mbedtls_pk_get_type(pk1);
+    TEST_EQUAL(type, mbedtls_pk_get_type(pk2));
+
+    switch (type) {
+#if defined(MBEDTLS_RSA_C)
+        case MBEDTLS_PK_RSA:
+        {
+            const mbedtls_rsa_context *rsa1 = mbedtls_pk_rsa(*pk1);
+            const mbedtls_rsa_context *rsa2 = mbedtls_pk_rsa(*pk2);
+            TEST_EQUAL(mbedtls_rsa_get_padding_mode(rsa1),
+                       mbedtls_rsa_get_padding_mode(rsa2));
+            TEST_EQUAL(mbedtls_rsa_get_md_alg(rsa1),
+                       mbedtls_rsa_get_md_alg(rsa2));
+            unsigned char buf1[RSA_WRITE_PUBKEY_MAX_SIZE];
+            unsigned char *p1 = buf1 + sizeof(buf1);
+            int len1 = mbedtls_rsa_write_pubkey(rsa1, buf1, &p1);
+            TEST_LE_U(0, len1);
+            unsigned char buf2[RSA_WRITE_PUBKEY_MAX_SIZE];
+            unsigned char *p2 = buf2 + sizeof(buf2);
+            int len2 = mbedtls_rsa_write_pubkey(rsa2, buf2, &p2);
+            TEST_LE_U(0, len2);
+            TEST_MEMORY_COMPARE(p1, len1, p2, len2);
+            break;
+        }
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+        {
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+            TEST_MEMORY_COMPARE(pk1->pub_raw, pk1->pub_raw_len,
+                                pk2->pub_raw, pk2->pub_raw_len);
+            TEST_EQUAL(pk1->ec_family, pk2->ec_family);
+            TEST_EQUAL(pk1->ec_bits, pk2->ec_bits);
+
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+            const mbedtls_ecp_keypair *ec1 = mbedtls_pk_ec_ro(*pk1);
+            const mbedtls_ecp_keypair *ec2 = mbedtls_pk_ec_ro(*pk2);
+            TEST_EQUAL(mbedtls_ecp_keypair_get_group_id(ec1),
+                       mbedtls_ecp_keypair_get_group_id(ec2));
+            unsigned char buf1[ECP_WRITE_PUBKEY_MAX_SIZE];
+            size_t len1 = 99999991;
+            TEST_EQUAL(mbedtls_ecp_write_public_key(
+                           ec1, MBEDTLS_ECP_PF_UNCOMPRESSED,
+                           &len1, buf1, sizeof(buf1)), 0);
+            unsigned char buf2[ECP_WRITE_PUBKEY_MAX_SIZE];
+            size_t len2 = 99999992;
+            TEST_EQUAL(mbedtls_ecp_write_public_key(
+                           ec2, MBEDTLS_ECP_PF_UNCOMPRESSED,
+                           &len2, buf2, sizeof(buf2)), 0);
+            TEST_MEMORY_COMPARE(buf1, len1, buf2, len2);
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+        }
+        break;
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+        default:
+            TEST_FAIL("Unsupported pk type in pk_public_same");
+    }
+
+    ok = 1;
+
+exit:
+    return ok;
+}
 #endif /* MBEDTLS_PSA_CRYPTO_C */
 
 #if defined(MBEDTLS_RSA_C)
@@ -348,32 +505,18 @@
     if (pk_type == MBEDTLS_PK_NONE) {
         return 0;
     }
-    TEST_EQUAL(mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(pk_type)), 0);
 
     switch (pk_type) {
 #if defined(MBEDTLS_RSA_C)
         case MBEDTLS_PK_RSA:
         {
             *psa_type = PSA_KEY_TYPE_RSA_KEY_PAIR;
-            mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
-            if (want_pair) {
-#if defined(MBEDTLS_GENPRIME)
-                TEST_EQUAL(mbedtls_rsa_gen_key(
-                               rsa,
-                               mbedtls_test_rnd_std_rand, NULL,
-                               MBEDTLS_RSA_GEN_KEY_MIN_BITS, 65537), 0);
-#else
-                TEST_FAIL("I don't know how to create an RSA key pair in this configuration.");
-#endif
-            } else {
-                unsigned char N[PSA_BITS_TO_BYTES(MBEDTLS_RSA_GEN_KEY_MIN_BITS)] = { 0xff };
-                N[sizeof(N) - 1] = 0x03;
-                const unsigned char E[1] = { 0x03 };
-                TEST_EQUAL(mbedtls_rsa_import_raw(rsa,
-                                                  N, sizeof(N),
-                                                  NULL, 0, NULL, 0, NULL, 0,
-                                                  E, sizeof(E)), 0);
-                TEST_EQUAL(mbedtls_rsa_complete(rsa), 0);
+            TEST_EQUAL(pk_setup(pk, pk_type, RSA_KEY_SIZE), 0);
+            if (!want_pair) {
+                mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
+                mbedtls_mpi_free(&rsa->D);
+                mbedtls_mpi_free(&rsa->P);
+                mbedtls_mpi_free(&rsa->Q);
             }
             break;
         }
@@ -387,7 +530,7 @@
             mbedtls_ecp_group_id grp_id = MBEDTLS_TEST_ECP_DP_ONE_CURVE;
             size_t bits;
             *psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(mbedtls_ecc_group_to_psa(grp_id, &bits));
-            TEST_EQUAL(pk_genkey(pk, grp_id), 0);
+            TEST_EQUAL(pk_setup(pk, pk_type, grp_id), 0);
             if (!want_pair) {
 #if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
                 psa_key_attributes_t pub_attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -423,54 +566,76 @@
 exit:
     return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
 }
-#endif
+#endif /* MBEDTLS_PSA_CRYPTO_C */
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-
-/*
- * Generate an ECC key using PSA and return the key identifier of that key,
- * or 0 if the key generation failed.
- * The key uses NIST P-256 and is usable for signing with SHA-256.
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+/* Create a new PSA key which will contain only the public part of the private
+ * key which is provided in input. For this new key:
+ * - Type is the public counterpart of the private key.
+ * - Usage is the copied from the original private key, but the PSA_KEY_USAGE_EXPORT
+ *   flag is removed. This is to prove that mbedtls_pk_copy_from_psa() doesn't
+ *   require the key to have the EXPORT flag.
+ * - Algorithm is copied from the original key pair.
  */
-mbedtls_svc_key_id_t pk_psa_genkey_ecc(void)
+static mbedtls_svc_key_id_t psa_pub_key_from_priv(mbedtls_svc_key_id_t priv_id)
 {
-    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    const psa_key_type_t type =
-        PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
-    const size_t bits = 256;
+    psa_key_type_t type;
+    psa_algorithm_t alg;
+    psa_key_usage_t usage;
+    unsigned char pub_key_buf[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
+    size_t pub_key_len;
+    mbedtls_svc_key_id_t pub_key = MBEDTLS_SVC_KEY_ID_INIT;
 
-    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
-    psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
+    /* Get attributes from the private key. */
+    PSA_ASSERT(psa_get_key_attributes(priv_id, &attributes));
+    type = psa_get_key_type(&attributes);
+    usage = psa_get_key_usage_flags(&attributes);
+    alg = psa_get_key_algorithm(&attributes);
+    psa_reset_key_attributes(&attributes);
+
+    /* Export the public key and then import it in a new slot. */
+    PSA_ASSERT(psa_export_public_key(priv_id, pub_key_buf, sizeof(pub_key_buf), &pub_key_len));
+
+    /* Notes:
+     * - psa_import_key() automatically determines the key's bit length
+     *   from the provided key data. That's why psa_set_key_bits() is not used
+     *   below.
+     */
+    type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type);
+    usage &= ~PSA_KEY_USAGE_EXPORT;
     psa_set_key_type(&attributes, type);
-    psa_set_key_bits(&attributes, bits);
-    PSA_ASSERT(psa_generate_key(&attributes, &key));
+    psa_set_key_usage_flags(&attributes, usage);
+    psa_set_key_algorithm(&attributes, alg);
+
+    PSA_ASSERT(psa_import_key(&attributes, pub_key_buf, pub_key_len, &pub_key));
 
 exit:
-    return key;
+    psa_reset_key_attributes(&attributes);
+    return pub_key;
 }
 
-/*
- * Generate an RSA key using PSA and return the key identifier of that key,
- * or 0 if the key generation failed.
- */
-mbedtls_svc_key_id_t pk_psa_genkey_rsa(void)
+/* Create a copy of a PSA key with same usage and algorithm policy and destroy
+ * the original one. */
+mbedtls_svc_key_id_t psa_copy_and_destroy(mbedtls_svc_key_id_t orig_key_id)
 {
-    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    const psa_key_type_t type = PSA_KEY_TYPE_RSA_KEY_PAIR;
-    const size_t bits = 1024;
+    psa_key_attributes_t orig_attr = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_attributes_t new_attr = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t new_key_id = MBEDTLS_SVC_KEY_ID_INIT;
 
-    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
-    psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_SIGN_RAW);
-    psa_set_key_type(&attributes, type);
-    psa_set_key_bits(&attributes, bits);
-    PSA_ASSERT(psa_generate_key(&attributes, &key));
+    PSA_ASSERT(psa_get_key_attributes(orig_key_id, &orig_attr));
+    psa_set_key_usage_flags(&new_attr, psa_get_key_usage_flags(&orig_attr));
+    psa_set_key_algorithm(&new_attr, psa_get_key_algorithm(&orig_attr));
+
+    PSA_ASSERT(psa_copy_key(orig_key_id, &new_attr, &new_key_id));
+    psa_destroy_key(orig_key_id);
 
 exit:
-    return key;
+    psa_reset_key_attributes(&orig_attr);
+    psa_reset_key_attributes(&new_attr);
+    return new_key_id;
 }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_PSA_CRYPTO_C */
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -504,11 +669,15 @@
     mbedtls_pk_init(&pk);
 
     if (key_is_rsa) {
-        bitlen = 1024; /* hardcoded in genkey() */
-        key = pk_psa_genkey_rsa();
+        bitlen = 1024;
+        PSA_ASSERT(pk_psa_setup(PSA_KEY_TYPE_RSA_KEY_PAIR, 1024, PSA_KEY_USAGE_SIGN_HASH,
+                                PSA_ALG_RSA_PKCS1V15_SIGN_RAW, PSA_ALG_NONE,
+                                MBEDTLS_SVC_KEY_ID_INIT, &key));
     } else {
-        bitlen = 256; /* hardcoded in genkey() */
-        key = pk_psa_genkey_ecc();
+        bitlen = 256;
+        PSA_ASSERT(pk_psa_setup(PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 256,
+                                PSA_KEY_USAGE_SIGN_HASH, PSA_ALG_ECDSA(PSA_ALG_SHA_256),
+                                PSA_ALG_NONE, MBEDTLS_SVC_KEY_ID_INIT, &key));
     }
     if (mbedtls_svc_key_id_is_null(key)) {
         goto exit;
@@ -593,16 +762,8 @@
     USE_PSA_INIT();
 
     if (opaque_key == 1) {
-        psa_set_key_usage_flags(&attributes, key_usage);
-        psa_set_key_algorithm(&attributes, key_alg);
-        if (key_alg2 != 0) {
-            psa_set_key_enrollment_algorithm(&attributes, key_alg2);
-        }
-        psa_set_key_type(&attributes, key_type);
-        psa_set_key_bits(&attributes, curve_or_keybits);
-
-        PSA_ASSERT(psa_generate_key(&attributes, &key));
-
+        PSA_ASSERT(pk_psa_setup(key_type, curve_or_keybits, key_usage,
+                                key_alg, key_alg2, MBEDTLS_SVC_KEY_ID_INIT, &key));
         if (mbedtls_svc_key_id_is_null(key)) {
             goto exit;
         }
@@ -611,9 +772,7 @@
 
         TEST_EQUAL(mbedtls_pk_get_type(&pk), MBEDTLS_PK_OPAQUE);
     } else {
-        TEST_EQUAL(mbedtls_pk_setup(&pk,
-                                    mbedtls_pk_info_from_type(key_type)), 0);
-        TEST_EQUAL(pk_genkey(&pk, curve_or_keybits), 0);
+        TEST_EQUAL(pk_setup(&pk, key_type, curve_or_keybits), 0);
         TEST_EQUAL(mbedtls_pk_get_type(&pk), key_type);
     }
 
@@ -815,8 +974,7 @@
     mbedtls_pk_init(&pk);
     USE_PSA_INIT();
 
-    TEST_ASSERT(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(type)) == 0);
-    TEST_ASSERT(pk_genkey(&pk, curve_or_keybits) == 0);
+    TEST_ASSERT(pk_setup(&pk, type, curve_or_keybits) == 0);
 
     TEST_ASSERT((int) mbedtls_pk_get_type(&pk) == type);
     TEST_ASSERT(mbedtls_pk_can_do(&pk, type));
@@ -837,6 +995,7 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     mbedtls_svc_key_id_t opaque_key_id = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t opaque_key_attr = PSA_KEY_ATTRIBUTES_INIT;
+    int is_ec_key = 0;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
     mbedtls_pk_init(&pub);
@@ -873,16 +1032,22 @@
     }
 #endif
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if (mbedtls_pk_get_type(&prv) == MBEDTLS_PK_ECKEY) {
-        /* Turn the prv PK context into an opaque one.*/
-        TEST_EQUAL(mbedtls_pk_get_psa_attributes(&prv, PSA_KEY_USAGE_SIGN_HASH,
-                                                 &opaque_key_attr), 0);
-        TEST_EQUAL(mbedtls_pk_import_into_psa(&prv, &opaque_key_attr, &opaque_key_id), 0);
-        mbedtls_pk_free(&prv);
-        mbedtls_pk_init(&prv);
-        TEST_EQUAL(mbedtls_pk_setup_opaque(&prv, opaque_key_id), 0);
+    is_ec_key = (mbedtls_pk_get_type(&prv) == MBEDTLS_PK_ECKEY);
+    /* Turn the prv PK context into an opaque one.*/
+    TEST_EQUAL(mbedtls_pk_get_psa_attributes(&prv, PSA_KEY_USAGE_SIGN_HASH,
+                                             &opaque_key_attr), 0);
+    TEST_EQUAL(mbedtls_pk_import_into_psa(&prv, &opaque_key_attr, &opaque_key_id), 0);
+    mbedtls_pk_free(&prv);
+    mbedtls_pk_init(&prv);
+    TEST_EQUAL(mbedtls_pk_setup_opaque(&prv, opaque_key_id), 0);
+    /* Test check_pair() between the opaque key we just created and the public PK counterpart.
+     * Note: opaque EC keys support check_pair(), whereas RSA ones do not. */
+    if (is_ec_key) {
         TEST_EQUAL(mbedtls_pk_check_pair(&pub, &prv, mbedtls_test_rnd_std_rand,
                                          NULL), ret);
+    } else {
+        TEST_EQUAL(mbedtls_pk_check_pair(&pub, &prv, mbedtls_test_rnd_std_rand,
+                                         NULL), MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE);
     }
 #endif
 
@@ -1177,8 +1342,7 @@
     memset(hash, 0x2a, sizeof(hash));
     memset(sig, 0, sizeof(sig));
 
-    TEST_ASSERT(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(type)) == 0);
-    TEST_ASSERT(pk_genkey(&pk, curve_or_keybits) == 0);
+    TEST_ASSERT(pk_setup(&pk, type, curve_or_keybits) == 0);
 
 #if defined(MBEDTLS_RSA_C)
     if (type == MBEDTLS_PK_RSA) {
@@ -1250,7 +1414,7 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_RSA_C */
-void pk_rsa_encrypt_decrypt_test(data_t *message, int mod,
+void pk_rsa_encrypt_decrypt_test(data_t *message, int mod, int padding,
                                  char *input_P, char *input_Q,
                                  char *input_N, char *input_E,
                                  int ret)
@@ -1265,7 +1429,7 @@
     mbedtls_pk_init(&pk);
     mbedtls_mpi_init(&N); mbedtls_mpi_init(&P);
     mbedtls_mpi_init(&Q); mbedtls_mpi_init(&E);
-    USE_PSA_INIT();
+    MD_OR_USE_PSA_INIT();
 
     memset(&rnd_info,  0, sizeof(mbedtls_test_rnd_pseudo_info));
     memset(output,     0, sizeof(output));
@@ -1275,6 +1439,7 @@
     /* init pk-rsa context */
     TEST_ASSERT(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == 0);
     rsa = mbedtls_pk_rsa(pk);
+    mbedtls_rsa_set_padding(rsa, padding, MBEDTLS_MD_SHA1);
 
     /* load public key */
     rsa->len = (mod + 7) / 8;
@@ -1294,6 +1459,7 @@
     TEST_ASSERT(mbedtls_pk_setup(&pk,
                                  mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == 0);
     rsa = mbedtls_pk_rsa(pk);
+    mbedtls_rsa_set_padding(rsa, padding, MBEDTLS_MD_SHA1);
 
     /* load public key */
     TEST_ASSERT(mbedtls_test_read_mpi(&N, input_N) == 0);
@@ -1323,7 +1489,7 @@
     mbedtls_mpi_free(&N); mbedtls_mpi_free(&P);
     mbedtls_mpi_free(&Q); mbedtls_mpi_free(&E);
     mbedtls_pk_free(&pk);
-    USE_PSA_DONE();
+    MD_OR_USE_PSA_DONE();
 }
 /* END_CASE */
 
@@ -1393,6 +1559,7 @@
 void pk_wrap_rsa_decrypt_test_vec(data_t *cipher, int mod,
                                   char *input_P, char *input_Q,
                                   char *input_N, char *input_E,
+                                  int padding_mode,
                                   data_t *clear, int ret)
 {
     unsigned char output[256];
@@ -1427,6 +1594,11 @@
     TEST_EQUAL(mbedtls_rsa_get_len(rsa), (mod + 7) / 8);
     TEST_EQUAL(mbedtls_rsa_complete(rsa), 0);
 
+    /* Set padding mode */
+    if (padding_mode == MBEDTLS_RSA_PKCS_V21) {
+        TEST_EQUAL(mbedtls_rsa_set_padding(rsa, padding_mode, MBEDTLS_MD_SHA1), 0);
+    }
+
     /* Turn PK context into an opaque one. */
     TEST_EQUAL(mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_DECRYPT, &key_attr), 0);
     TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &key_attr, &key_id), 0);
@@ -1563,9 +1735,7 @@
     memset(test, 0, sizeof(test));
 
     /* Initialize PK RSA context with random key */
-    TEST_ASSERT(mbedtls_pk_setup(&rsa,
-                                 mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == 0);
-    TEST_ASSERT(pk_genkey(&rsa, RSA_KEY_SIZE) == 0);
+    TEST_ASSERT(pk_setup(&rsa, MBEDTLS_PK_RSA, RSA_KEY_SIZE) == 0);
 
     /* Extract key to the raw rsa context */
     TEST_ASSERT(mbedtls_rsa_copy(&raw, mbedtls_pk_rsa(rsa)) == 0);
@@ -1633,75 +1803,86 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_MD_CAN_SHA256:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_TEST_PK_PSA_SIGN */
-void pk_psa_sign(int curve_or_keybits, int psa_type, int expected_bits)
+/* BEGIN_CASE depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_TEST_PK_PSA_SIGN */
+void pk_psa_sign(int psa_type, int bits, int rsa_padding)
 {
     mbedtls_pk_context pk;
     unsigned char hash[32];
     unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
-    unsigned char pkey_legacy[200];
-    unsigned char pkey_psa[200];
-    unsigned char *pkey_legacy_start, *pkey_psa_start;
-    size_t sig_len, klen_legacy, klen_psa;
-    int ret;
+    unsigned char legacy_pub_key[MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE];
+    unsigned char opaque_pub_key[MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE];
+    size_t sig_len, legacy_pub_key_len, opaque_pub_key_len;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_WRITE_C)
+    int ret;
+#endif /* MBEDTLS_RSA_C || MBEDTLS_PK_WRITE_C */
+#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
+    mbedtls_ecp_group_id ecp_grp_id;
+#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
 
     /*
-     * This tests making signatures with a wrapped PSA key:
-     * - generate a fresh ECP/RSA legacy PK context
-     * - wrap it in a PK context and make a signature this way
-     * - extract the public key
-     * - parse it to a PK context and verify the signature this way
+     * Following checks are perfomed:
+     * - create an RSA/EC opaque context;
+     * - sign with opaque context for both EC and RSA keys;
+     * - [EC only] verify with opaque context;
+     * - verify that public keys of opaque and non-opaque contexts match;
+     * - verify with non-opaque context.
      */
 
     mbedtls_pk_init(&pk);
     USE_PSA_INIT();
 
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)
+    /* Create the legacy EC/RSA PK context. */
+#if defined(MBEDTLS_RSA_C)
     if (PSA_KEY_TYPE_IS_RSA(psa_type)) {
-        /* Create legacy RSA public/private key in PK context. */
-        TEST_ASSERT(mbedtls_pk_setup(&pk,
-                                     mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) == 0);
-        TEST_ASSERT(mbedtls_rsa_gen_key(mbedtls_pk_rsa(pk),
-                                        mbedtls_test_rnd_std_rand, NULL,
-                                        curve_or_keybits, 3) == 0);
-    } else
-#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */
+        TEST_EQUAL(pk_setup(&pk, MBEDTLS_PK_RSA, bits), 0);
+        TEST_EQUAL(mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk), rsa_padding, MBEDTLS_MD_NONE), 0);
+    }
+#else /* MBEDTLS_RSA_C */
+    (void) rsa_padding;
+#endif /* MBEDTLS_RSA_C */
 #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
     if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(psa_type)) {
-        mbedtls_ecp_group_id grpid = curve_or_keybits;
-
-        /* Create legacy EC public/private key in PK context. */
-        TEST_ASSERT(mbedtls_pk_setup(&pk,
-                                     mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) == 0);
-        TEST_ASSERT(pk_genkey(&pk, grpid) == 0);
-    } else
-#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
-    {
-        (void) curve_or_keybits;
-        TEST_ASSUME(!"Opaque PK key not supported in this configuration");
+        ecp_grp_id = mbedtls_ecc_group_from_psa(psa_type, bits);
+        TEST_ASSERT(pk_setup(&pk, MBEDTLS_PK_ECKEY, ecp_grp_id) == 0);
     }
+#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
 
-    /* Export underlying public key for re-importing in a legacy context. */
-#if defined(MBEDTLS_PK_WRITE_C)
-    ret = mbedtls_pk_write_pubkey_der(&pk, pkey_legacy,
-                                      sizeof(pkey_legacy));
+    /* Export public key from the non-opaque PK context we just created. */
+#if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_PK_WRITE_C)
+    ret = mbedtls_pk_write_pubkey_der(&pk, legacy_pub_key, sizeof(legacy_pub_key));
     TEST_ASSERT(ret >= 0);
-    klen_legacy = (size_t) ret;
-    /* mbedtls_pk_write_pubkey_der() writes backwards in the data buffer. */
-    pkey_legacy_start = pkey_legacy + sizeof(pkey_legacy) - klen_legacy;
-#else
-    ret = mbedtls_ecp_point_write_binary(&(mbedtls_pk_ec_ro(pk)->grp),
-                                         &(mbedtls_pk_ec_ro(pk)->Q),
-                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
-                                         &klen_legacy, pkey_legacy,
-                                         sizeof(pkey_legacy));
-    TEST_EQUAL(ret, 0);
-    pkey_legacy_start = pkey_legacy;
-#endif /* MBEDTLS_PK_WRITE_C */
+    legacy_pub_key_len = (size_t) ret;
+    /* mbedtls_pk_write_pubkey_der() writes backwards in the data buffer so we
+     * shift data back to the beginning of the buffer. */
+    memmove(legacy_pub_key,
+            legacy_pub_key + sizeof(legacy_pub_key) - legacy_pub_key_len,
+            legacy_pub_key_len);
+#else /* MBEDTLS_PK_PARSE_C && MBEDTLS_PK_WRITE_C */
+#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
+    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(psa_type)) {
+        TEST_EQUAL(mbedtls_ecp_point_write_binary(&(mbedtls_pk_ec_ro(pk)->grp),
+                                                  &(mbedtls_pk_ec_ro(pk)->Q),
+                                                  MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                                  &legacy_pub_key_len, legacy_pub_key,
+                                                  sizeof(legacy_pub_key)), 0);
+    }
+#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
+#if defined(MBEDTLS_RSA_C)
+    if (PSA_KEY_TYPE_IS_RSA(psa_type)) {
+        unsigned char *end = legacy_pub_key + sizeof(legacy_pub_key);
+        ret = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(pk), legacy_pub_key, &end);
+        legacy_pub_key_len = (size_t) ret;
+        TEST_ASSERT(legacy_pub_key_len > 0);
+        /* mbedtls_rsa_write_pubkey() writes data backward in the buffer so
+         * we shift that to the origin of the buffer instead. */
+        memmove(legacy_pub_key, end, legacy_pub_key_len);
+    }
+#endif /* MBEDTLS_RSA_C */
+#endif /* MBEDTLS_PK_PARSE_C && MBEDTLS_PK_WRITE_C */
 
-    /* Turn PK context into an opaque one. */
+    /* Turn the PK context into an opaque one. */
     TEST_EQUAL(mbedtls_pk_get_psa_attributes(&pk, PSA_KEY_USAGE_SIGN_HASH, &attributes), 0);
     TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &attributes, &key_id), 0);
     mbedtls_pk_free(&pk);
@@ -1710,13 +1891,12 @@
 
     PSA_ASSERT(psa_get_key_attributes(key_id, &attributes));
     TEST_EQUAL(psa_get_key_type(&attributes), (psa_key_type_t) psa_type);
-    TEST_EQUAL(psa_get_key_bits(&attributes), (size_t) expected_bits);
-    TEST_EQUAL(psa_get_key_lifetime(&attributes),
-               PSA_KEY_LIFETIME_VOLATILE);
+    TEST_EQUAL(psa_get_key_bits(&attributes), (size_t) bits);
+    TEST_EQUAL(psa_get_key_lifetime(&attributes), PSA_KEY_LIFETIME_VOLATILE);
 
+    /* Sign with the opaque context. */
     memset(hash, 0x2a, sizeof(hash));
     memset(sig, 0, sizeof(sig));
-
     TEST_ASSERT(mbedtls_pk_sign(&pk, MBEDTLS_MD_SHA256,
                                 hash, sizeof(hash), sig, sizeof(sig), &sig_len,
                                 NULL, NULL) == 0);
@@ -1726,56 +1906,60 @@
                                       hash, sizeof(hash), sig, sig_len) == 0);
     }
 
-    /* Export underlying public key for re-importing in a psa context. */
-#if defined(MBEDTLS_PK_WRITE_C)
-    ret = mbedtls_pk_write_pubkey_der(&pk, pkey_psa,
-                                      sizeof(pkey_psa));
+    /* Export public key from the opaque PK context. */
+#if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_PK_WRITE_C)
+    ret = mbedtls_pk_write_pubkey_der(&pk, opaque_pub_key, sizeof(opaque_pub_key));
     TEST_ASSERT(ret >= 0);
-    klen_psa = (size_t) ret;
+    opaque_pub_key_len = (size_t) ret;
     /* mbedtls_pk_write_pubkey_der() writes backwards in the data buffer. */
-    pkey_psa_start = pkey_psa + sizeof(pkey_psa) - klen_psa;
-#else
-    psa_status_t status;
+    memmove(opaque_pub_key,
+            opaque_pub_key + sizeof(opaque_pub_key) - opaque_pub_key_len,
+            opaque_pub_key_len);
+#else /* MBEDTLS_PK_PARSE_C && MBEDTLS_PK_WRITE_C */
+    TEST_EQUAL(psa_export_public_key(key_id, opaque_pub_key, sizeof(opaque_pub_key),
+                                     &opaque_pub_key_len), PSA_SUCCESS);
+#endif /* MBEDTLS_PK_PARSE_C && MBEDTLS_PK_WRITE_C */
 
-    status = psa_export_public_key(key_id, pkey_psa, sizeof(pkey_psa),
-                                   &klen_psa);
-    TEST_EQUAL(status, PSA_SUCCESS);
-    pkey_psa_start = pkey_psa;
-#endif /* MBEDTLS_PK_WRITE_C */
+    /* Check that the public keys of opaque and non-opaque PK contexts match. */
+    TEST_EQUAL(opaque_pub_key_len, legacy_pub_key_len);
+    TEST_MEMORY_COMPARE(opaque_pub_key, opaque_pub_key_len, legacy_pub_key, legacy_pub_key_len);
 
-    TEST_ASSERT(klen_psa == klen_legacy);
-    TEST_ASSERT(memcmp(pkey_psa_start, pkey_legacy_start, klen_psa) == 0);
-
+    /* Destroy the opaque PK context and the wrapped PSA key. */
     mbedtls_pk_free(&pk);
     TEST_ASSERT(PSA_SUCCESS == psa_destroy_key(key_id));
 
+    /* Create a new non-opaque PK context to verify the signature. */
     mbedtls_pk_init(&pk);
+#if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_PK_WRITE_C)
+    TEST_EQUAL(mbedtls_pk_parse_public_key(&pk, legacy_pub_key, legacy_pub_key_len), 0);
+#else /* MBEDTLS_PK_PARSE_C && MBEDTLS_PK_WRITE_C */
+#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
+    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(psa_type)) {
+        TEST_EQUAL(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)), 0);
+        TEST_EQUAL(mbedtls_ecp_group_load(&(mbedtls_pk_ec_rw(pk)->grp), ecp_grp_id), 0);
+        TEST_EQUAL(mbedtls_ecp_point_read_binary(&(mbedtls_pk_ec_ro(pk)->grp),
+                                                 &(mbedtls_pk_ec_rw(pk)->Q),
+                                                 legacy_pub_key, legacy_pub_key_len), 0);
+    }
+#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
+#if defined(MBEDTLS_RSA_C)
+    if (PSA_KEY_TYPE_IS_RSA(psa_type)) {
+        TEST_EQUAL(mbedtls_pk_setup(&pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)), 0);
+        TEST_EQUAL(mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(pk), legacy_pub_key,
+                                            legacy_pub_key_len), 0);
+    }
+#endif /* MBEDTLS_RSA_C */
+#endif /* MBEDTLS_PK_PARSE_C && MBEDTLS_PK_WRITE_C */
 
-    /* If we used "pk_write" previously, then we go for a "pk_parse" here;
-     * otherwise if we went for "ecp_point_write_binary" then we'll go
-     * for a "ecp_point_read_binary" here. This allows to drop dependencies
-     * on "PK_WRITE" and "PK_PARSE" if required */
-#if defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_PK_PARSE_C)
-    TEST_EQUAL(mbedtls_pk_parse_public_key(&pk, pkey_legacy_start,
-                                           klen_legacy), 0);
-#else
-    TEST_EQUAL(mbedtls_pk_setup(&pk,
-                                mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)), 0);
-    TEST_EQUAL(mbedtls_ecp_group_load(
-                   &(mbedtls_pk_ec_rw(pk)->grp),
-                   (mbedtls_ecp_group_id) curve_or_keybits), 0);
-    TEST_EQUAL(mbedtls_ecp_point_read_binary(&(mbedtls_pk_ec_ro(pk)->grp),
-                                             &(mbedtls_pk_ec_rw(pk)->Q),
-                                             pkey_legacy_start, klen_legacy), 0);
-#endif
+#if defined(MBEDTLS_RSA_C)
+    if (PSA_KEY_TYPE_IS_RSA(psa_type)) {
+        TEST_EQUAL(mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk), rsa_padding, MBEDTLS_MD_NONE), 0);
+    }
+#endif /* MBEDTLS_RSA_C */
     TEST_ASSERT(mbedtls_pk_verify(&pk, MBEDTLS_MD_SHA256,
                                   hash, sizeof(hash), sig, sig_len) == 0);
 
 exit:
-    /*
-     * Key attributes may have been returned by psa_get_key_attributes()
-     * thus reset them as required.
-     */
     psa_reset_key_attributes(&attributes);
 
     mbedtls_pk_free(&pk);
@@ -1783,7 +1967,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_GENPRIME */
+/* BEGIN_CASE */
 void pk_sign_ext(int pk_type, int curve_or_keybits, int key_pk_type, int md_alg)
 {
     mbedtls_pk_context pk;
@@ -1799,9 +1983,7 @@
     mbedtls_pk_init(&pk);
     MD_OR_USE_PSA_INIT();
 
-    TEST_EQUAL(mbedtls_pk_setup(&pk,
-                                mbedtls_pk_info_from_type(pk_type)), 0);
-    TEST_EQUAL(pk_genkey(&pk, curve_or_keybits), 0);
+    TEST_EQUAL(pk_setup(&pk, pk_type, curve_or_keybits), 0);
 
     TEST_EQUAL(mbedtls_pk_sign_ext(key_pk_type, &pk, md_alg, hash, hash_len,
                                    sig, sizeof(sig), &sig_len,
@@ -1821,7 +2003,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_RSA_C:MBEDTLS_GENPRIME:MBEDTLS_USE_PSA_CRYPTO */
+/* BEGIN_CASE depends_on:MBEDTLS_RSA_C:MBEDTLS_USE_PSA_CRYPTO */
 void pk_psa_wrap_sign_ext(int pk_type, int key_bits, int key_pk_type, int md_alg)
 {
     mbedtls_pk_context pk;
@@ -1843,18 +2025,16 @@
 
     /* Create legacy RSA public/private key in PK context. */
     mbedtls_pk_init(&pk);
-    TEST_EQUAL(mbedtls_pk_setup(&pk,
-                                mbedtls_pk_info_from_type(pk_type)), 0);
-    TEST_EQUAL(mbedtls_rsa_gen_key(mbedtls_pk_rsa(pk),
-                                   mbedtls_test_rnd_std_rand, NULL,
-                                   key_bits, 3), 0);
+    TEST_EQUAL(pk_setup(&pk, pk_type, key_bits), 0);
 
     if (key_pk_type == MBEDTLS_PK_RSASSA_PSS) {
         mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk), MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_NONE);
     }
 
-    /* Export underlying public key for re-importing in a legacy context. */
-    ret = mbedtls_pk_write_pubkey_der(&pk, pkey, sizeof(pkey));
+    /* Export underlying public key for re-importing in a legacy context.
+     * Note: mbedtls_rsa_write_key() writes backwards in the data buffer. */
+    pkey_start = pkey + sizeof(pkey);
+    ret = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(pk), pkey, &pkey_start);
     TEST_ASSERT(ret >= 0);
 
     pkey_len = (size_t) ret;
@@ -1871,15 +2051,45 @@
     memset(hash, 0x2a, sizeof(hash));
     memset(sig, 0, sizeof(sig));
 
+#if defined(MBEDTLS_PKCS1_V21)
+    /* Check that trying to use the wrong pk_type in sign_ext() results in a failure.
+     * The PSA key was setup to use PKCS1 v1.5 signature algorithm, but here we try
+     * to use it for PSS (PKCS1 v2.1) and it should fail. */
+    if (key_pk_type == MBEDTLS_PK_RSA) {
+        TEST_EQUAL(mbedtls_pk_sign_ext(MBEDTLS_PK_RSASSA_PSS, &pk, md_alg, hash, hash_len,
+                                       sig, sizeof(sig), &sig_len,
+                                       mbedtls_test_rnd_std_rand, NULL),
+                   MBEDTLS_ERR_RSA_BAD_INPUT_DATA);
+    }
+#endif /* MBEDTLS_PKCS1_V21 */
+
+    /* Perform sign_ext() with the correct pk_type. */
     TEST_EQUAL(mbedtls_pk_sign_ext(key_pk_type, &pk, md_alg, hash, hash_len,
                                    sig, sizeof(sig), &sig_len,
                                    mbedtls_test_rnd_std_rand, NULL), 0);
 
+    /* verify_ext() is not supported when using an opaque context. */
+    if (key_pk_type == MBEDTLS_PK_RSASSA_PSS) {
+        mbedtls_pk_rsassa_pss_options pss_opts = {
+            .mgf1_hash_id = md_alg,
+            .expected_salt_len = MBEDTLS_RSA_SALT_LEN_ANY,
+        };
+        TEST_EQUAL(mbedtls_pk_verify_ext(key_pk_type, &pss_opts, &pk, md_alg,
+                                         hash, hash_len, sig, sig_len),
+                   MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE);
+    } else {
+        TEST_EQUAL(mbedtls_pk_verify_ext(key_pk_type, NULL, &pk, md_alg,
+                                         hash, hash_len, sig, sig_len),
+                   MBEDTLS_ERR_PK_TYPE_MISMATCH);
+    }
+
     mbedtls_pk_free(&pk);
     TEST_EQUAL(PSA_SUCCESS, psa_destroy_key(key_id));
 
     mbedtls_pk_init(&pk);
-    TEST_EQUAL(mbedtls_pk_parse_public_key(&pk, pkey_start, pkey_len), 0);
+    TEST_EQUAL(mbedtls_pk_setup(&pk,
+                                mbedtls_pk_info_from_type(pk_type)), 0);
+    TEST_EQUAL(mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(pk), pkey_start, pkey_len), 0);
 
     if (key_pk_type == MBEDTLS_PK_RSASSA_PSS) {
         rsassa_pss_options.mgf1_hash_id = md_alg;
@@ -1959,7 +2169,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21:MBEDTLS_GENPRIME */
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V21 */
 void pk_rsa_v21_get_psa_attributes(int md_type, int from_pair,
                                    int usage_arg,
                                    int to_pair, int expected_alg)
@@ -2033,6 +2243,93 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_TEST_PSA_ECC_AT_LEAST_ONE_CURVE:MBEDTLS_PSA_CRYPTO_STORAGE_C */
+void pk_import_into_psa_lifetime(int from_opaque,
+                                 int from_persistent, /* when from opaque */
+                                 int from_exportable, /* when from opaque */
+                                 int to_public,
+                                 int to_persistent)
+{
+    mbedtls_pk_context pk;
+    mbedtls_pk_init(&pk);
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t old_key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    mbedtls_svc_key_id_t new_key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    mbedtls_svc_key_id_t expected_key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_lifetime_t expected_lifetime = PSA_KEY_LIFETIME_VOLATILE;
+
+    PSA_INIT();
+
+    if (from_opaque) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        psa_key_type_t from_psa_type =
+            PSA_KEY_TYPE_ECC_KEY_PAIR(MBEDTLS_TEST_PSA_ECC_ONE_FAMILY);
+        psa_key_usage_t psa_key_usage =
+            (from_exportable ? PSA_KEY_USAGE_EXPORT : PSA_KEY_USAGE_COPY) |
+            PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH;
+        mbedtls_svc_key_id_t persistent_key_id = MBEDTLS_SVC_KEY_ID_INIT;
+
+        if (from_persistent) {
+            persistent_key_id = mbedtls_svc_key_id_make(0, 1);
+        }
+
+        PSA_ASSERT(pk_psa_setup(from_psa_type, MBEDTLS_TEST_PSA_ECC_ONE_CURVE_BITS,
+                                psa_key_usage, PSA_ALG_ECDH, PSA_ALG_NONE,
+                                persistent_key_id, &old_key_id));
+        TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, old_key_id), 0);
+        psa_reset_key_attributes(&attributes);
+#else
+        (void) from_persistent;
+        (void) from_exportable;
+        TEST_FAIL("Attempted to test opaque key without opaque key support");
+#endif
+    } else {
+        psa_key_type_t psa_type_according_to_setup;
+        TEST_EQUAL(pk_setup_for_type(MBEDTLS_PK_ECKEY, 1,
+                                     &pk, &psa_type_according_to_setup), 0);
+    }
+
+    if (to_persistent) {
+        expected_key_id = mbedtls_svc_key_id_make(42, 2);
+        psa_set_key_id(&attributes, expected_key_id);
+        /* psa_set_key_id() sets the lifetime to PERSISTENT */
+        expected_lifetime = PSA_KEY_LIFETIME_PERSISTENT;
+    }
+
+    psa_key_usage_t to_usage =
+        to_public ? PSA_KEY_USAGE_VERIFY_HASH : PSA_KEY_USAGE_SIGN_HASH;
+    TEST_EQUAL(mbedtls_pk_get_psa_attributes(&pk, to_usage,
+                                             &attributes), 0);
+    /* mbedtls_pk_get_psa_attributes() is specified to not modify
+     * the persistence attributes. */
+    TEST_EQUAL(psa_get_key_lifetime(&attributes), expected_lifetime);
+    TEST_EQUAL(MBEDTLS_SVC_KEY_ID_GET_KEY_ID(psa_get_key_id(&attributes)),
+               MBEDTLS_SVC_KEY_ID_GET_KEY_ID(expected_key_id));
+
+    TEST_EQUAL(mbedtls_pk_import_into_psa(&pk, &attributes, &new_key_id), 0);
+    if (!mbedtls_test_key_consistency_psa_pk(new_key_id, &pk)) {
+        goto exit;
+    }
+
+    PSA_ASSERT(psa_get_key_attributes(new_key_id, &attributes));
+    TEST_EQUAL(psa_get_key_lifetime(&attributes), expected_lifetime);
+    /* Here expected_key_id=0 for a volatile key, but we expect
+     * attributes to contain a dynamically assigned key id which we
+     * can't predict. */
+    if (to_persistent) {
+        TEST_ASSERT(mbedtls_svc_key_id_equal(psa_get_key_id(&attributes),
+                                             expected_key_id));
+    }
+
+exit:
+    mbedtls_pk_free(&pk);
+    psa_reset_key_attributes(&attributes);
+    psa_destroy_key(old_key_id);
+    psa_destroy_key(new_key_id);
+    PSA_DONE();
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_USE_PSA_CRYPTO */
 void pk_get_psa_attributes_opaque(int from_type_arg, int from_bits_arg,
                                   int from_usage_arg, int from_alg_arg,
@@ -2054,13 +2351,8 @@
 
     PSA_INIT();
 
-    psa_set_key_type(&attributes, from_type);
-    psa_set_key_bits(&attributes, bits);
-    psa_set_key_usage_flags(&attributes, from_usage);
-    psa_set_key_algorithm(&attributes, alg);
-    psa_set_key_enrollment_algorithm(&attributes, 42);
-    //TODO: test with persistent key
-    PSA_ASSERT(psa_generate_key(&attributes, &old_key_id));
+    PSA_ASSERT(pk_psa_setup(from_type, bits, from_usage, alg, 42,
+                            MBEDTLS_SVC_KEY_ID_INIT, &old_key_id));
     TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, old_key_id), 0);
 
     psa_key_type_t expected_psa_type =
@@ -2152,11 +2444,8 @@
 
     PSA_INIT();
 
-    psa_set_key_type(&from_attributes, from_type);
-    psa_set_key_bits(&from_attributes, from_bits);
-    psa_set_key_usage_flags(&from_attributes, from_usage);
-    psa_set_key_algorithm(&from_attributes, from_alg);
-    PSA_ASSERT(psa_generate_key(&from_attributes, &from_key_id));
+    PSA_ASSERT(pk_psa_setup(from_type, from_bits, from_usage, from_alg, PSA_ALG_NONE,
+                            MBEDTLS_SVC_KEY_ID_INIT, &from_key_id));
     TEST_EQUAL(mbedtls_pk_setup_opaque(&pk, from_key_id), 0);
 
     psa_set_key_type(&to_attributes, to_type);
@@ -2199,3 +2488,213 @@
     PSA_DONE();
 }
 /* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C*/
+void pk_copy_from_psa_fail(void)
+{
+    mbedtls_pk_context pk_ctx;
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+
+    mbedtls_pk_init(&pk_ctx);
+    PSA_INIT();
+
+    /* Null pk pointer. */
+    TEST_EQUAL(mbedtls_pk_copy_from_psa(key_id, NULL),
+               MBEDTLS_ERR_PK_BAD_INPUT_DATA);
+    TEST_EQUAL(mbedtls_pk_copy_public_from_psa(key_id, NULL),
+               MBEDTLS_ERR_PK_BAD_INPUT_DATA);
+
+    /* Invalid key ID. */
+    TEST_EQUAL(mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_make(0, 0), &pk_ctx),
+               MBEDTLS_ERR_PK_BAD_INPUT_DATA);
+    TEST_EQUAL(mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_make(0, 0), &pk_ctx),
+               MBEDTLS_ERR_PK_BAD_INPUT_DATA);
+
+#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)
+    pk_psa_setup(PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919), 2048,
+                 PSA_KEY_USAGE_EXPORT, PSA_ALG_NONE, PSA_ALG_NONE,
+                 MBEDTLS_SVC_KEY_ID_INIT, &key_id);
+    TEST_EQUAL(mbedtls_pk_copy_from_psa(key_id, &pk_ctx), MBEDTLS_ERR_PK_BAD_INPUT_DATA);
+    TEST_EQUAL(mbedtls_pk_copy_public_from_psa(key_id, &pk_ctx), MBEDTLS_ERR_PK_BAD_INPUT_DATA);
+    psa_destroy_key(key_id);
+#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && defined(PSA_WANT_ECC_SECP_R1_256)
+    /* Generate an EC key which cannot be exported. */
+    PSA_ASSERT(pk_psa_setup(PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 256,
+                            0, PSA_ALG_NONE, PSA_ALG_NONE, MBEDTLS_SVC_KEY_ID_INIT, &key_id));
+    TEST_EQUAL(mbedtls_pk_copy_from_psa(key_id, &pk_ctx), MBEDTLS_ERR_PK_TYPE_MISMATCH);
+    psa_destroy_key(key_id);
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS && PSA_WANT_ECC_SECP_R1_256 */
+
+exit:
+    mbedtls_pk_free(&pk_ctx);
+    psa_destroy_key(key_id);
+    PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN:MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC:!MBEDTLS_RSA_C */
+void pk_copy_from_psa_builtin_fail()
+{
+    mbedtls_pk_context pk_ctx;
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+
+    mbedtls_pk_init(&pk_ctx);
+    PSA_INIT();
+
+    PSA_ASSERT(pk_psa_setup(PSA_KEY_TYPE_RSA_KEY_PAIR,
+                            PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS,
+                            PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT,
+                            PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_SHA_256),
+                            PSA_ALG_NONE,
+                            MBEDTLS_SVC_KEY_ID_INIT, &key_id));
+    TEST_EQUAL(mbedtls_pk_copy_from_psa(key_id, &pk_ctx), MBEDTLS_ERR_PK_BAD_INPUT_DATA);
+exit:
+    mbedtls_pk_free(&pk_ctx);
+    psa_destroy_key(key_id);
+    PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C*/
+void pk_copy_from_psa_success(data_t *priv_key_data, int key_type_arg,
+                              int key_alg_arg)
+{
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t key_alg = key_alg_arg;
+    psa_key_usage_t key_usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH |
+                                PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY;
+    mbedtls_pk_context pk_priv, pk_priv_copy_public, pk_pub, pk_pub_copy_public;
+    mbedtls_svc_key_id_t priv_key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    mbedtls_svc_key_id_t pub_key_id = MBEDTLS_SVC_KEY_ID_INIT;
+
+    mbedtls_pk_init(&pk_priv);
+    mbedtls_pk_init(&pk_priv_copy_public);
+    mbedtls_pk_init(&pk_pub);
+    mbedtls_pk_init(&pk_pub_copy_public);
+    PSA_INIT();
+
+    if (key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+        key_usage |= PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
+    }
+
+    /* Create both a private key and its public counterpart in PSA. */
+    PSA_ASSERT(pk_psa_import_key(priv_key_data->x, priv_key_data->len,
+                                 key_type, key_usage, key_alg, &priv_key_id));
+    pub_key_id = psa_pub_key_from_priv(priv_key_id);
+
+    /* Create 4 PK contexts starting from the PSA keys we just created. */
+    TEST_EQUAL(mbedtls_pk_copy_from_psa(priv_key_id, &pk_priv), 0);
+    TEST_EQUAL(mbedtls_pk_copy_public_from_psa(priv_key_id, &pk_priv_copy_public), 0);
+    TEST_EQUAL(mbedtls_pk_copy_from_psa(pub_key_id, &pk_pub), 0);
+    TEST_EQUAL(mbedtls_pk_copy_public_from_psa(pub_key_id, &pk_pub_copy_public), 0);
+
+    /* Destroy both PSA keys to prove that generated PK contexts are independent
+     * from them. */
+    priv_key_id = psa_copy_and_destroy(priv_key_id);
+    pub_key_id = psa_copy_and_destroy(pub_key_id);
+
+    /* - Check that the generated PK contexts are of the correct type.
+     * - [Only for RSA] check that the padding mode is correct.
+     */
+    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {
+        TEST_EQUAL(mbedtls_pk_get_type(&pk_priv), MBEDTLS_PK_ECKEY);
+        TEST_EQUAL(mbedtls_pk_get_type(&pk_pub), MBEDTLS_PK_ECKEY);
+    } else {
+        TEST_EQUAL(mbedtls_pk_get_type(&pk_priv), MBEDTLS_PK_RSA);
+        TEST_EQUAL(mbedtls_pk_get_type(&pk_pub), MBEDTLS_PK_RSA);
+#if defined(MBEDTLS_RSA_C)
+        mbedtls_rsa_context *rsa_priv = mbedtls_pk_rsa(pk_priv);
+        mbedtls_rsa_context *rsa_pub = mbedtls_pk_rsa(pk_pub);
+        if (PSA_ALG_IS_RSA_OAEP(key_alg) || PSA_ALG_IS_RSA_PSS(key_alg)) {
+            TEST_EQUAL(mbedtls_rsa_get_padding_mode(rsa_priv), MBEDTLS_RSA_PKCS_V21);
+            TEST_EQUAL(mbedtls_rsa_get_padding_mode(rsa_pub), MBEDTLS_RSA_PKCS_V21);
+        } else {
+            TEST_EQUAL(mbedtls_rsa_get_padding_mode(rsa_priv), MBEDTLS_RSA_PKCS_V15);
+            TEST_EQUAL(mbedtls_rsa_get_padding_mode(rsa_pub), MBEDTLS_RSA_PKCS_V15);
+        }
+#endif /* MBEDTLS_RSA_C */
+    }
+
+    /* Check that generated private/public PK contexts form a valid private/public key pair. */
+    TEST_EQUAL(mbedtls_pk_check_pair(&pk_pub, &pk_priv, mbedtls_test_rnd_std_rand, NULL), 0);
+
+    /* Check consistency between copied PSA keys and generated PK contexts. */
+    TEST_EQUAL(mbedtls_test_key_consistency_psa_pk(priv_key_id, &pk_priv), 1);
+    TEST_EQUAL(mbedtls_test_key_consistency_psa_pk(priv_key_id, &pk_pub), 1);
+    TEST_EQUAL(mbedtls_test_key_consistency_psa_pk(pub_key_id, &pk_priv), 1);
+    TEST_EQUAL(mbedtls_test_key_consistency_psa_pk(pub_key_id, &pk_pub), 1);
+
+    /* Test that the keys from mbedtls_pk_copy_public_from_psa() are identical
+     * to the public keys from mbedtls_pk_copy_from_psa(). */
+    mbedtls_test_set_step(1);
+    TEST_ASSERT(pk_public_same(&pk_pub, &pk_priv_copy_public));
+    mbedtls_test_set_step(2);
+    TEST_ASSERT(pk_public_same(&pk_pub, &pk_pub_copy_public));
+
+exit:
+    mbedtls_pk_free(&pk_priv);
+    mbedtls_pk_free(&pk_priv_copy_public);
+    mbedtls_pk_free(&pk_pub);
+    mbedtls_pk_free(&pk_pub_copy_public);
+    psa_destroy_key(priv_key_id);
+    psa_destroy_key(pub_key_id);
+    PSA_DONE();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_C*/
+void pk_copy_public_from_psa(data_t *priv_key_data, int key_type_arg)
+{
+    psa_key_type_t key_type = key_type_arg;
+    mbedtls_pk_context pk_from_exportable;
+    mbedtls_pk_init(&pk_from_exportable);
+    mbedtls_pk_context pk_from_non_exportable;
+    mbedtls_pk_init(&pk_from_non_exportable);
+    mbedtls_pk_context pk_private;
+    mbedtls_pk_init(&pk_private);
+    mbedtls_svc_key_id_t non_exportable_key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    mbedtls_svc_key_id_t exportable_key_id = MBEDTLS_SVC_KEY_ID_INIT;
+
+    PSA_INIT();
+
+    PSA_ASSERT(pk_psa_import_key(priv_key_data->x, priv_key_data->len,
+                                 key_type,
+                                 PSA_KEY_USAGE_EXPORT,
+                                 PSA_ALG_NONE,
+                                 &exportable_key_id));
+    PSA_ASSERT(pk_psa_import_key(priv_key_data->x, priv_key_data->len,
+                                 key_type,
+                                 0,
+                                 PSA_ALG_NONE,
+                                 &non_exportable_key_id));
+
+    TEST_EQUAL(mbedtls_pk_copy_public_from_psa(exportable_key_id,
+                                               &pk_from_exportable), 0);
+    TEST_EQUAL(mbedtls_pk_copy_public_from_psa(non_exportable_key_id,
+                                               &pk_from_non_exportable), 0);
+
+    /* Check that the non-exportable key really is non-exportable */
+    TEST_EQUAL(mbedtls_pk_copy_from_psa(non_exportable_key_id, &pk_private),
+               MBEDTLS_ERR_PK_TYPE_MISMATCH);
+
+    psa_destroy_key(exportable_key_id);
+    psa_destroy_key(non_exportable_key_id);
+
+    /* The goal of this test function is mostly to check that
+     * mbedtls_pk_copy_public_from_psa works with a non-exportable key pair.
+     * We check that the resulting key is the same as for an exportable
+     * key pair. We rely on pk_copy_from_psa_success tests to validate that
+     * the result is correct. */
+    TEST_ASSERT(pk_public_same(&pk_from_non_exportable, &pk_from_exportable));
+
+exit:
+    mbedtls_pk_free(&pk_from_non_exportable);
+    mbedtls_pk_free(&pk_from_exportable);
+    mbedtls_pk_free(&pk_private);
+    psa_destroy_key(exportable_key_id);
+    psa_destroy_key(non_exportable_key_id);
+    PSA_DONE();
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_pkparse.data b/tests/suites/test_suite_pkparse.data
index 1650f51..d170e1e 100644
--- a/tests/suites/test_suite_pkparse.data
+++ b/tests/suites/test_suite_pkparse.data
@@ -914,21 +914,23 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_MD_CAN_SHA384:MBEDTLS_PKCS5_C:MBEDTLS_CIPHER_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
 pk_parse_keyfile_rsa:"data_files/rsa_pkcs8_pbes2_pbkdf2_2048_aes256cbc_sha384.der":"PolarSSLTest":0
 
-Parse RSA Key #100.1 (512-bit)
-depends_on:MBEDTLS_PEM_C
-pk_parse_keyfile_rsa:"data_files/rsa512.key":"":0
+# Test keys with non-word-aligned sizes.
+# We use sizes that are large enough to exercise PKCS#1 v1.5 signature with
+# the largest supported hashes (SHA-512 and SHA3-512.)
+Parse RSA Key #100 (768-bit)
+pk_parse_keyfile_rsa:"data_files/rsa_pkcs1_768_clear.der":"":0
 
-Parse RSA Key #100.1 (521-bit)
-depends_on:MBEDTLS_PEM_C
-pk_parse_keyfile_rsa:"data_files/rsa521.key":"":0
+Parse RSA Key #100 (769-bit)
+pk_parse_keyfile_rsa:"data_files/rsa_pkcs1_769_clear.der":"":0
 
-Parse RSA Key #100.1 (522-bit)
-depends_on:MBEDTLS_PEM_C
-pk_parse_keyfile_rsa:"data_files/rsa522.key":"":0
+Parse RSA Key #100 (770-bit)
+pk_parse_keyfile_rsa:"data_files/rsa_pkcs1_770_clear.der":"":0
 
-Parse RSA Key #100.1 (528-bit)
-depends_on:MBEDTLS_PEM_C
-pk_parse_keyfile_rsa:"data_files/rsa528.key":"":0
+Parse RSA Key #100 (776-bit)
+pk_parse_keyfile_rsa:"data_files/rsa_pkcs1_776_clear.der":"":0
+
+Parse RSA Key #100 (784-bit)
+pk_parse_keyfile_rsa:"data_files/rsa_pkcs1_784_clear.der":"":0
 
 Parse Public RSA Key #1 (PKCS#8 wrapped)
 depends_on:MBEDTLS_PEM_PARSE_C
diff --git a/tests/suites/test_suite_pkparse.function b/tests/suites/test_suite_pkparse.function
index 7dc8413..63ff092 100644
--- a/tests/suites/test_suite_pkparse.function
+++ b/tests/suites/test_suite_pkparse.function
@@ -47,7 +47,19 @@
     int ok = 0;
 
     TEST_EQUAL(mbedtls_pk_get_psa_attributes(ctx, usage_flag, &attributes), 0);
-    TEST_EQUAL(mbedtls_pk_import_into_psa(ctx, &attributes, &psa_key), 0);
+    int ret = mbedtls_pk_import_into_psa(ctx, &attributes, &psa_key);
+    if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_RSA &&
+        mbedtls_pk_get_bitlen(ctx) % 8 != 0 &&
+        ret == MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) {
+        /* There is a historical limitation with support for RSA keys in PSA:
+         * only byte-aligned sizes are supported.
+         * https://github.com/Mbed-TLS/mbedtls/issues/9048
+         * For now, for such keys, treat not-supported from PSA as a success.
+         */
+        ok = 1;
+        goto exit;
+    }
+    TEST_EQUAL(ret, 0);
     if (!mbedtls_test_key_consistency_psa_pk(psa_key, ctx)) {
         goto exit;
     }
@@ -57,7 +69,7 @@
     if (mbedtls_test_can_exercise_psa_algorithm(exercise_alg)) {
         TEST_ASSERT(mbedtls_test_psa_exercise_key(psa_key,
                                                   exercise_usage,
-                                                  exercise_alg));
+                                                  exercise_alg, 0));
     }
 
     mbedtls_test_set_step((unsigned long) -1);
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index c55af03..4f29a7a 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -2736,6 +2736,11 @@
 depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
 cipher_verify_output_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":16
 
+# Encrypt 48 bytes total, initially 16. This forces both calls to update() to output data.
+PSA symmetric encrypt/decrypt multipart: AES-CBC-nopad, 48 bytes, good
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES
+cipher_verify_output_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a6bc1bee22e409f96e93d7e117393172a6bc1bee22e409f96e93d7e117393172a":16
+
 PSA symmetric encrypt/decrypt multipart: AES-CBC-PKCS#7, 16 bytes
 depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES
 cipher_verify_output_multipart:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a":16
@@ -4278,6 +4283,50 @@
 depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
 import_and_exercise_key:"c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0":PSA_KEY_TYPE_DERIVE:192:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256)
 
+PSA concurrently import/exercise same key: RSA keypair, PKCS#1 v1.5 raw
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT
+concurrently_use_same_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:100
+
+PSA concurrently import/exercise same key: RSA keypair, PSS-SHA-256
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT
+concurrently_use_same_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):100
+
+PSA concurrently import/exercise same key: RSA keypair, PSS-any-salt-SHA-256
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT
+concurrently_use_same_persistent_key:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):100
+
+PSA concurrently import/exercise same key: RSA public key, PKCS#1 v1.5 raw
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+concurrently_use_same_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:100
+
+PSA concurrently import/exercise same key: RSA public key, PSS-SHA-256
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+concurrently_use_same_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):100
+
+PSA concurrently import/exercise same key: RSA public key, PSS-any-salt-SHA-256
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+concurrently_use_same_persistent_key:"30818902818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc30203010001":PSA_KEY_TYPE_RSA_PUBLIC_KEY:1024:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):100
+
+PSA concurrently import/exercise same key: ECP SECP256R1 keypair, ECDSA
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT:PSA_WANT_ECC_SECP_R1_256
+concurrently_use_same_persistent_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_ECDSA_ANY:100
+
+PSA concurrently import/exercise same key: ECP SECP256R1 keypair, deterministic ECDSA
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT:PSA_WANT_ECC_SECP_R1_256
+concurrently_use_same_persistent_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):100
+
+PSA concurrently import/exercise same key: ECP SECP256R1 keypair, ECDH
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT:PSA_WANT_ECC_SECP_R1_256
+concurrently_use_same_persistent_key:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_ALG_ECDH:100
+
+PSA concurrently import/exercise same key: HKDF SHA-256
+depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
+concurrently_use_same_persistent_key:"c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0":PSA_KEY_TYPE_DERIVE:192:PSA_ALG_HKDF(PSA_ALG_SHA_256):100
+
+PSA concurrently import/exercise same key: TLS 1.2 PRF SHA-256
+depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
+concurrently_use_same_persistent_key:"c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0":PSA_KEY_TYPE_DERIVE:192:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):100
+
 PSA sign hash: RSA PKCS#1 v1.5, raw
 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT
 sign_hash_deterministic:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_ALG_RSA_PKCS1V15_SIGN_RAW:"616263":"2c7744983f023ac7bb1c55529d83ed11a76a7898a1bb5ce191375a4aa7495a633d27879ff58eba5a57371c34feb1180e8b850d552476ebb5634df620261992f12ebee9097041dbbea85a42d45b344be5073ceb772ffc604954b9158ba81ec3dc4d9d65e3ab7aa318165f38c36f841f1c69cb1cfa494aa5cbb4d6c0efbafb043a"
@@ -7532,6 +7581,150 @@
 depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_ECDH
 generate_key_ext:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:0:"2a":PSA_ERROR_INVALID_ARGUMENT
 
+PSA concurrent key generation: bad type (RSA public key)
+depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RSA_PUBLIC_KEY:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT:0:8:5
+
+PSA concurrent key generation: raw data, 0 bits: invalid argument
+depends_on:MBEDTLS_THREADING_PTHREAD
+# The spec allows either INVALID_ARGUMENT or NOT_SUPPORTED
+concurrently_generate_keys:PSA_KEY_TYPE_RAW_DATA:0:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT:0:8:5
+
+PSA concurrent key generation: raw data, 7 bits: invalid argument
+depends_on:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RAW_DATA:7:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT:0:8:5
+
+PSA concurrent key generation: raw data, 8 bits
+depends_on:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RAW_DATA:8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation- raw data, 9 bits: invalid argument
+depends_on:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RAW_DATA:9:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT:0:8:5
+
+PSA concurrent key generation: raw data, (MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8 bits
+depends_on:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RAW_DATA:(MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: raw data, (2 * MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8 bits
+depends_on:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RAW_DATA:(2 * MBEDTLS_CTR_DRBG_MAX_REQUEST + 1) * 8:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: raw data, 65528 bits (large key, ok if it fits)
+depends_on:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RAW_DATA:65528:PSA_KEY_USAGE_EXPORT:0:PSA_SUCCESS:1:8:5
+
+PSA concurrent key generation: raw data, 65536 bits (not supported)
+depends_on:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RAW_DATA:65536:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED:0:8:5
+
+PSA concurrent key generation: AES, 128 bits, CTR
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: AES, 128 bits, GCM
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_GCM:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: DES, 64 bits, CBC-nopad
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_DES:64:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: DES, 128 bits, CBC-nopad
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_DES:128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: DES, 192 bits, CBC-nopad
+depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_DES:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_DES:192:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CBC_NO_PADDING:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: invalid key size: AES, 64 bits
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_AES:64:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CTR:PSA_ERROR_INVALID_ARGUMENT:0:8:5
+
+PSA concurrent key generation: RSA, minimum allowed key size, good, sign (PKCS#1 v1.5)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS > 128:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: RSA, 1032 bits, good, sign (PKCS#1 v1.5)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS <= 1032:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RSA_KEY_PAIR:1032:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: RSA, 1024 bits, good, sign (PSS SHA-256)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS <= 1024:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PSS(PSA_ALG_SHA_256):PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: RSA, 1024 bits, good, sign (PSS-any-salt SHA-256)
+depends_on:PSA_WANT_ALG_RSA_PSS:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS <= 1024:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_SHA_256):PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: RSA, minimum allowed key size, good, encrypt (PKCS#1 v1.5)
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS >= 256:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS <= 2048:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: RSA, 1024 bits, good, encrypt (OAEP SHA-256)
+depends_on:PSA_WANT_ALG_RSA_OAEP:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS <= 1024:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256):PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: RSA, 0 bits: invalid
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_THREADING_PTHREAD
+# The spec allows either INVALID_ARGUMENT or NOT_SUPPORTED
+concurrently_generate_keys:PSA_KEY_TYPE_RSA_KEY_PAIR:0:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_INVALID_ARGUMENT:0:8:5
+
+PSA concurrent key generation: RSA, size not multiple of 8: not supported
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS + 62:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_NOT_SUPPORTED:0:8:5
+
+PSA concurrent key generation: RSA, size not multiple of 2: not supported
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS + 63:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_NOT_SUPPORTED:0:8:5
+
+PSA concurrent key generation: RSA, maximum size exceeded
+depends_on:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_RSA_KEY_PAIR:PSA_VENDOR_RSA_MAX_KEY_BITS+8:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_RSA_PKCS1V15_CRYPT:PSA_ERROR_NOT_SUPPORTED:0:8:5
+
+PSA concurrent key generation: ECC, SECP256R1, good
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):256:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: ECC, SECP256R1, incorrect bit size
+depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_THREADING_PTHREAD
+# INVALID_ARGUMENT would make more sense, but our code as currently structured
+# doesn't fully relate the curve with its size.
+concurrently_generate_keys:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):128:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:PSA_ERROR_NOT_SUPPORTED:0:8:5
+
+PSA concurrent key generation: ECC, Curve25519, good
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_MONTGOMERY_255:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):255:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: ECC, Curve448, good
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE:PSA_WANT_ECC_MONTGOMERY_448:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY):448:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_DERIVE:PSA_ALG_ECDH:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: FFDH, 2048 bits, good
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE:PSA_WANT_DH_RFC7919_2048:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919):2048:PSA_KEY_USAGE_EXPORT:PSA_ALG_FFDH:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: FFDH, 3072 bits, good
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE:PSA_WANT_DH_RFC7919_3072:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919):3072:PSA_KEY_USAGE_EXPORT:PSA_ALG_FFDH:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: FFDH, 4096 bits, good
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE:PSA_WANT_DH_RFC7919_4096:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919):4096:PSA_KEY_USAGE_EXPORT:PSA_ALG_FFDH:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: FFDH, 6144 bits, good
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE:PSA_WANT_DH_RFC7919_6144:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919):6144:PSA_KEY_USAGE_EXPORT:PSA_ALG_FFDH:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: FFDH, 8192 bits, good
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE:PSA_WANT_DH_RFC7919_8192:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919):8192:PSA_KEY_USAGE_EXPORT:PSA_ALG_FFDH:PSA_SUCCESS:0:8:5
+
+PSA concurrent key generation: FFDH, 1024 bits, invalid bits
+depends_on:PSA_WANT_ALG_FFDH:PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE:MBEDTLS_THREADING_PTHREAD
+concurrently_generate_keys:PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919):1024:PSA_KEY_USAGE_EXPORT:PSA_ALG_FFDH:PSA_ERROR_NOT_SUPPORTED:0:8:5
+
 Key production parameters initializers
 key_production_parameters_init:
 
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 09874a1..0c8552b 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -15,7 +15,6 @@
 #include "psa/crypto.h"
 #include "psa_crypto_slot_management.h"
 
-/* For psa_can_do_hash() */
 #include "psa_crypto_core.h"
 
 #include "test/asn1_helpers.h"
@@ -28,6 +27,10 @@
 #define TEST_DRIVER_LOCATION 0x7fffff
 #endif
 
+#if defined(MBEDTLS_THREADING_PTHREAD)
+#include "mbedtls/threading.h"
+#endif
+
 /* If this comes up, it's a bug in the test code or in the test data. */
 #define UNUSED 0xdeadbeef
 
@@ -743,37 +746,37 @@
             /* Server first round Output */
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_g1_len));
+                                       buffer_length - buffer0_off, &s_g1_len));
             TEST_EQUAL(s_g1_len, expected_size_key_share);
             s_g1_off = buffer0_off;
             buffer0_off += s_g1_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x1_pk_len));
+                                       buffer_length - buffer0_off, &s_x1_pk_len));
             TEST_EQUAL(s_x1_pk_len, expected_size_zk_public);
             s_x1_pk_off = buffer0_off;
             buffer0_off += s_x1_pk_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x1_pr_len));
+                                       buffer_length - buffer0_off, &s_x1_pr_len));
             TEST_LE_U(s_x1_pr_len, max_expected_size_zk_proof);
             s_x1_pr_off = buffer0_off;
             buffer0_off += s_x1_pr_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_g2_len));
+                                       buffer_length - buffer0_off, &s_g2_len));
             TEST_EQUAL(s_g2_len, expected_size_key_share);
             s_g2_off = buffer0_off;
             buffer0_off += s_g2_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x2_pk_len));
+                                       buffer_length - buffer0_off, &s_x2_pk_len));
             TEST_EQUAL(s_x2_pk_len, expected_size_zk_public);
             s_x2_pk_off = buffer0_off;
             buffer0_off += s_x2_pk_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x2_pr_len));
+                                       buffer_length - buffer0_off, &s_x2_pr_len));
             TEST_LE_U(s_x2_pr_len, max_expected_size_zk_proof);
             s_x2_pr_off = buffer0_off;
             buffer0_off += s_x2_pr_len;
@@ -863,37 +866,37 @@
             /* Client first round Output */
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_g1_len));
+                                       buffer_length - buffer1_off, &c_g1_len));
             TEST_EQUAL(c_g1_len, expected_size_key_share);
             c_g1_off = buffer1_off;
             buffer1_off += c_g1_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x1_pk_len));
+                                       buffer_length - buffer1_off, &c_x1_pk_len));
             TEST_EQUAL(c_x1_pk_len, expected_size_zk_public);
             c_x1_pk_off = buffer1_off;
             buffer1_off += c_x1_pk_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x1_pr_len));
+                                       buffer_length - buffer1_off, &c_x1_pr_len));
             TEST_LE_U(c_x1_pr_len, max_expected_size_zk_proof);
             c_x1_pr_off = buffer1_off;
             buffer1_off += c_x1_pr_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_g2_len));
+                                       buffer_length - buffer1_off, &c_g2_len));
             TEST_EQUAL(c_g2_len, expected_size_key_share);
             c_g2_off = buffer1_off;
             buffer1_off += c_g2_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x2_pk_len));
+                                       buffer_length - buffer1_off, &c_x2_pk_len));
             TEST_EQUAL(c_x2_pk_len, expected_size_zk_public);
             c_x2_pk_off = buffer1_off;
             buffer1_off += c_x2_pk_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x2_pr_len));
+                                       buffer_length - buffer1_off, &c_x2_pr_len));
             TEST_LE_U(c_x2_pr_len, max_expected_size_zk_proof);
             c_x2_pr_off = buffer1_off;
             buffer1_off += c_x2_pr_len;
@@ -1041,19 +1044,19 @@
 
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_a_len));
+                                       buffer_length - buffer0_off, &s_a_len));
             TEST_EQUAL(s_a_len, expected_size_key_share);
             s_a_off = buffer0_off;
             buffer0_off += s_a_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x2s_pk_len));
+                                       buffer_length - buffer0_off, &s_x2s_pk_len));
             TEST_EQUAL(s_x2s_pk_len, expected_size_zk_public);
             s_x2s_pk_off = buffer0_off;
             buffer0_off += s_x2s_pk_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x2s_pr_len));
+                                       buffer_length - buffer0_off, &s_x2s_pr_len));
             TEST_LE_U(s_x2s_pr_len, max_expected_size_zk_proof);
             s_x2s_pr_off = buffer0_off;
             buffer0_off += s_x2s_pr_len;
@@ -1106,19 +1109,19 @@
 
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_a_len));
+                                       buffer_length - buffer1_off, &c_a_len));
             TEST_EQUAL(c_a_len, expected_size_key_share);
             c_a_off = buffer1_off;
             buffer1_off += c_a_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x2s_pk_len));
+                                       buffer_length - buffer1_off, &c_x2s_pk_len));
             TEST_EQUAL(c_x2s_pk_len, expected_size_zk_public);
             c_x2s_pk_off = buffer1_off;
             buffer1_off += c_x2s_pk_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x2s_pr_len));
+                                       buffer_length - buffer1_off, &c_x2s_pr_len));
             TEST_LE_U(c_x2s_pr_len, max_expected_size_zk_proof);
             c_x2s_pr_off = buffer1_off;
             buffer1_off += c_x2s_pr_len;
@@ -1333,6 +1336,186 @@
     return 0;
 }
 
+#if defined(MBEDTLS_THREADING_PTHREAD)
+
+typedef struct same_key_context {
+    data_t *data;
+    mbedtls_svc_key_id_t key;
+    psa_key_attributes_t *attributes;
+    int type;
+    int bits;
+    /* The following two parameters are used to ensure that when multiple
+     * threads attempt to load/destroy the key, exactly one thread succeeds. */
+    int key_loaded;
+    mbedtls_threading_mutex_t MBEDTLS_PRIVATE(key_loaded_mutex);
+}
+same_key_context;
+
+/* Attempt to import the key in ctx. This handles any valid error codes
+ * and reports an error for any invalid codes. This function also insures
+ * that once imported by some thread, all threads can use the key. */
+void *thread_import_key(void *ctx)
+{
+    mbedtls_svc_key_id_t returned_key_id;
+    same_key_context *skc = (struct same_key_context *) ctx;
+    psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    /* Import the key, exactly one thread must succeed. */
+    psa_status_t status = psa_import_key(skc->attributes, skc->data->x,
+                                         skc->data->len, &returned_key_id);
+    switch (status) {
+        case PSA_SUCCESS:
+            if (mbedtls_mutex_lock(&skc->key_loaded_mutex) == 0) {
+                if (skc->key_loaded) {
+                    mbedtls_mutex_unlock(&skc->key_loaded_mutex);
+                    /* More than one thread has succeeded, report a failure. */
+                    TEST_FAIL("The same key has been loaded into the key store multiple times.");
+                }
+                skc->key_loaded = 1;
+                mbedtls_mutex_unlock(&skc->key_loaded_mutex);
+            }
+            break;
+        case PSA_ERROR_INSUFFICIENT_MEMORY:
+            /* If all of the key slots are reserved when a thread
+             * locks the mutex to reserve a new slot, it will return
+             * PSA_ERROR_INSUFFICIENT_MEMORY; this is correct behaviour.
+             * There is a chance for this to occur here when the number of
+             * threads running this function is larger than the number of
+             * free key slots. Each thread reserves an empty key slot,
+             * unlocks the mutex, then relocks it to finalize key creation.
+             * It is at that point where the thread sees that the key
+             * already exists, releases the reserved slot,
+             * and returns PSA_ERROR_ALREADY_EXISTS.
+             * There is no guarantee that the key is loaded upon this return
+             * code, so we can't test the key information. Just stop this
+             * thread from executing, note that this is not an error. */
+            goto exit;
+            break;
+        case PSA_ERROR_ALREADY_EXISTS:
+            /* The key has been loaded by a different thread. */
+            break;
+        default:
+            PSA_ASSERT(status);
+    }
+    /* At this point the key must exist, test the key information. */
+    status = psa_get_key_attributes(skc->key, &got_attributes);
+    if (status == PSA_ERROR_INSUFFICIENT_MEMORY) {
+        /* This is not a test failure. The following sequence of events
+         * causes this to occur:
+         * 1: This thread successfuly imports a persistent key skc->key.
+         * 2: N threads reserve an empty key slot in psa_import_key,
+         *    where N is equal to the number of free key slots.
+         * 3: A final thread attempts to reserve an empty key slot, kicking
+         *    skc->key (which has no registered readers) out of its slot.
+         * 4: This thread calls psa_get_key_attributes(skc->key,...):
+         *    it sees that skc->key is not in a slot, attempts to load it and
+         *    finds that there are no free slots.
+         * This thread returns PSA_ERROR_INSUFFICIENT_MEMORY.
+         *
+         * The PSA spec allows this behaviour, it is an unavoidable consequence
+         * of allowing persistent keys to be kicked out of the key store while
+         * they are still valid. */
+        goto exit;
+    }
+    PSA_ASSERT(status);
+    TEST_EQUAL(psa_get_key_type(&got_attributes), skc->type);
+    TEST_EQUAL(psa_get_key_bits(&got_attributes), skc->bits);
+
+exit:
+    /* Key attributes may have been returned by psa_get_key_attributes(),
+     * reset them as required. */
+    psa_reset_key_attributes(&got_attributes);
+    return NULL;
+}
+
+void *thread_use_and_destroy_key(void *ctx)
+{
+    same_key_context *skc = (struct same_key_context *) ctx;
+
+    /* Do something with the key according
+     * to its type and permitted usage. */
+    TEST_ASSERT(mbedtls_test_psa_exercise_key(skc->key,
+                                              skc->attributes->policy.usage,
+                                              skc->attributes->policy.alg, 1));
+
+    psa_status_t status = psa_destroy_key(skc->key);
+    if (status == PSA_SUCCESS) {
+        if (mbedtls_mutex_lock(&skc->key_loaded_mutex) == 0) {
+            /* Ensure that we are the only thread to succeed. */
+            if (skc->key_loaded != 1) {
+                mbedtls_mutex_unlock(&skc->key_loaded_mutex);
+                TEST_FAIL("The same key has been destroyed multiple times.");
+            }
+            skc->key_loaded = 0;
+            mbedtls_mutex_unlock(&skc->key_loaded_mutex);
+        }
+    } else {
+        TEST_EQUAL(status, PSA_ERROR_INVALID_HANDLE);
+    }
+
+exit:
+    return NULL;
+}
+
+typedef struct generate_key_context {
+    psa_key_type_t type;
+    psa_key_usage_t usage;
+    size_t bits;
+    psa_algorithm_t alg;
+    psa_status_t expected_status;
+    psa_key_attributes_t *attributes;
+    int is_large_key;
+    int reps;
+}
+generate_key_context;
+void *thread_generate_key(void *ctx)
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
+    generate_key_context *gkc = (struct generate_key_context *) ctx;
+
+    /* If there are race conditions, it is likely the case that they do not
+     * arise every time the code runs. We repeat the code to increase the
+     * chance that any race conditions will be hit. */
+    for (int n = 0; n < gkc->reps; n++) {
+        /* Generate a key */
+        psa_status_t status = psa_generate_key(gkc->attributes, &key);
+
+        if (gkc->is_large_key > 0) {
+            TEST_ASSUME(status != PSA_ERROR_INSUFFICIENT_MEMORY);
+        }
+
+        TEST_EQUAL(status, gkc->expected_status);
+        if (gkc->expected_status != PSA_SUCCESS) {
+            PSA_ASSERT(psa_destroy_key(key));
+            goto exit;
+        }
+
+        /* Test the key information */
+        PSA_ASSERT(psa_get_key_attributes(key, &got_attributes));
+        TEST_EQUAL(psa_get_key_type(&got_attributes), gkc->type);
+        TEST_EQUAL(psa_get_key_bits(&got_attributes), gkc->bits);
+
+        /* Do something with the key according
+         * to its type and permitted usage. */
+        if (!mbedtls_test_psa_exercise_key(key, gkc->usage, gkc->alg, 0)) {
+            psa_destroy_key(key);
+            goto exit;
+        }
+        psa_reset_key_attributes(&got_attributes);
+
+        PSA_ASSERT(psa_destroy_key(key));
+    }
+exit:
+    /*
+     * Key attributes may have been returned by psa_get_key_attributes()
+     * thus reset them as required.
+     */
+    psa_reset_key_attributes(&got_attributes);
+    return NULL;
+}
+#endif /* MBEDTLS_THREADING_PTHREAD */
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -1651,7 +1834,7 @@
      * this doesn't directly validate the implementation, but it still helps
      * by cross-validating the test data with the sanity check code. */
     if (!psa_key_lifetime_is_external(lifetime)) {
-        if (!mbedtls_test_psa_exercise_key(key, usage_arg, 0)) {
+        if (!mbedtls_test_psa_exercise_key(key, usage_arg, 0, 0)) {
             goto exit;
         }
     }
@@ -1760,6 +1943,78 @@
 }
 /* END_CASE */
 
+
+#if defined(MBEDTLS_THREADING_PTHREAD)
+/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD:MBEDTLS_PSA_CRYPTO_STORAGE_C */
+void concurrently_use_same_persistent_key(data_t *data,
+                                          int type_arg,
+                                          int bits_arg,
+                                          int alg_arg,
+                                          int thread_count_arg)
+{
+    size_t thread_count = (size_t) thread_count_arg;
+    mbedtls_test_thread_t *threads = NULL;
+    mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make(1, 1);
+    same_key_context skc;
+    skc.data = data;
+    skc.key = key_id;
+    skc.type = type_arg;
+    skc.bits = bits_arg;
+    skc.key_loaded = 0;
+    mbedtls_mutex_init(&skc.key_loaded_mutex);
+    psa_key_usage_t usage = mbedtls_test_psa_usage_to_exercise(skc.type, alg_arg);
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_id(&attributes, key_id);
+    psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT);
+    psa_set_key_usage_flags(&attributes, usage);
+    psa_set_key_algorithm(&attributes, alg_arg);
+    psa_set_key_type(&attributes, type_arg);
+    psa_set_key_bits(&attributes, bits_arg);
+    skc.attributes = &attributes;
+
+    TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count);
+
+    /* Test that when multiple threads import the same key,
+     * exactly one thread succeeds and the rest fail with valid errors.
+     * Also test that all threads can use the key as soon as it has been
+     * imported. */
+    for (size_t i = 0; i < thread_count; i++) {
+        TEST_EQUAL(
+            mbedtls_test_thread_create(&threads[i], thread_import_key,
+                                       (void *) &skc), 0);
+    }
+
+    /* Join threads. */
+    for (size_t i = 0; i < thread_count; i++) {
+        TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0);
+    }
+
+    /* Test that when multiple threads use and destroy a key no corruption
+     * occurs, and exactly one thread succeeds when destroying the key. */
+    for (size_t i = 0; i < thread_count; i++) {
+        TEST_EQUAL(
+            mbedtls_test_thread_create(&threads[i], thread_use_and_destroy_key,
+                                       (void *) &skc), 0);
+    }
+
+    /* Join threads. */
+    for (size_t i = 0; i < thread_count; i++) {
+        TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0);
+    }
+    /* Ensure that one thread succeeded in destroying the key. */
+    TEST_ASSERT(!skc.key_loaded);
+exit:
+    psa_reset_key_attributes(&attributes);
+    mbedtls_mutex_free(&skc.key_loaded_mutex);
+    mbedtls_free(threads);
+    PSA_DONE();
+}
+/* END_CASE */
+#endif
+
 /* BEGIN_CASE */
 void import_and_exercise_key(data_t *data,
                              int type_arg,
@@ -1789,7 +2044,7 @@
     TEST_EQUAL(psa_get_key_bits(&got_attributes), bits);
 
     /* Do something with the key according to its type and permitted usage. */
-    if (!mbedtls_test_psa_exercise_key(key, usage, alg)) {
+    if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) {
         goto exit;
     }
 
@@ -2426,7 +2681,7 @@
                               &key));
 
     PSA_ASSERT(psa_key_derivation_setup(&operation, exercise_alg));
-    status = mbedtls_test_psa_key_agreement_with_self(&operation, key);
+    status = mbedtls_test_psa_key_agreement_with_self(&operation, key, 0);
 
     TEST_EQUAL(status, expected_status);
 
@@ -2465,10 +2720,10 @@
     TEST_EQUAL(psa_get_key_algorithm(&got_attributes), alg);
     TEST_EQUAL(psa_get_key_enrollment_algorithm(&got_attributes), alg2);
 
-    if (!mbedtls_test_psa_exercise_key(key, usage, alg)) {
+    if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) {
         goto exit;
     }
-    if (!mbedtls_test_psa_exercise_key(key, usage, alg2)) {
+    if (!mbedtls_test_psa_exercise_key(key, usage, alg2, 0)) {
         goto exit;
     }
 
@@ -2508,7 +2763,7 @@
     PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
                               &key));
 
-    status = mbedtls_test_psa_raw_key_agreement_with_self(exercise_alg, key);
+    status = mbedtls_test_psa_raw_key_agreement_with_self(exercise_alg, key, 0);
 
     TEST_EQUAL(status, expected_status);
 
@@ -2599,10 +2854,10 @@
     }
 
     if (!psa_key_lifetime_is_external(target_lifetime)) {
-        if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg)) {
+        if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg, 0)) {
             goto exit;
         }
-        if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg2)) {
+        if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg2, 0)) {
             goto exit;
         }
     }
@@ -4694,7 +4949,8 @@
     PSA_ASSERT(psa_cipher_update(&operation1,
                                  input->x + first_part_size,
                                  input->len - first_part_size,
-                                 output1, output1_buffer_size,
+                                 output1 + output1_length,
+                                 output1_buffer_size - output1_length,
                                  &function_output_length));
     TEST_LE_U(function_output_length,
               PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type,
@@ -4740,7 +4996,8 @@
     PSA_ASSERT(psa_cipher_update(&operation2,
                                  output1 + first_part_size,
                                  output1_length - first_part_size,
-                                 output2, output2_buffer_size,
+                                 output2 + output2_length,
+                                 output2_buffer_size - output2_length,
                                  &function_output_length));
     TEST_LE_U(function_output_length,
               PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type,
@@ -5208,7 +5465,9 @@
     psa_key_type_t key_type = key_type_arg;
     psa_algorithm_t alg = alg_arg;
     psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
-    uint8_t nonce_buffer[PSA_AEAD_NONCE_MAX_SIZE];
+    /* Some tests try to get more than the maximum nonce length,
+     * so allocate double. */
+    uint8_t nonce_buffer[PSA_AEAD_NONCE_MAX_SIZE * 2];
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_status_t status = PSA_ERROR_GENERIC_ERROR;
     psa_status_t expected_status = expected_status_arg;
@@ -8617,7 +8876,7 @@
                 // When taking a private key as secret input, use key agreement
                 // to add the shared secret to the derivation
                 TEST_EQUAL(mbedtls_test_psa_key_agreement_with_self(
-                               &operation, keys[i]),
+                               &operation, keys[i], 0),
                            expected_statuses[i]);
             } else {
                 TEST_EQUAL(psa_key_derivation_input_key(&operation, steps[i],
@@ -8716,7 +8975,7 @@
     if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, key, alg,
                                                     input1, input1_length,
                                                     input2, input2_length,
-                                                    capacity)) {
+                                                    capacity, 0)) {
         goto exit;
     }
 
@@ -9035,7 +9294,7 @@
     if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, key, alg,
                                                     input1->x, input1->len,
                                                     input2->x, input2->len,
-                                                    requested_capacity)) {
+                                                    requested_capacity, 0)) {
         goto exit;
     }
 
@@ -9152,7 +9411,7 @@
     if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, base_key, alg,
                                                     input1->x, input1->len,
                                                     input2->x, input2->len,
-                                                    capacity)) {
+                                                    capacity, 0)) {
         goto exit;
     }
 
@@ -9169,7 +9428,7 @@
     TEST_EQUAL(psa_get_key_bits(&got_attributes), derived_bits);
 
     /* Exercise the derived key. */
-    if (!mbedtls_test_psa_exercise_key(derived_key, derived_usage, derived_alg)) {
+    if (!mbedtls_test_psa_exercise_key(derived_key, derived_usage, derived_alg, 0)) {
         goto exit;
     }
 
@@ -9222,7 +9481,7 @@
     if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, base_key, alg,
                                                     input1->x, input1->len,
                                                     input2->x, input2->len,
-                                                    capacity)) {
+                                                    capacity, 0)) {
         goto exit;
     }
 
@@ -9235,7 +9494,7 @@
     if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, base_key, alg,
                                                     input1->x, input1->len,
                                                     input2->x, input2->len,
-                                                    capacity)) {
+                                                    capacity, 0)) {
         goto exit;
     }
 
@@ -9306,7 +9565,7 @@
             &operation, base_key, alg,
             input1->x, input1->len,
             input2->x, input2->len,
-            PSA_KEY_DERIVATION_UNLIMITED_CAPACITY) == 0) {
+            PSA_KEY_DERIVATION_UNLIMITED_CAPACITY, 0) == 0) {
         goto exit;
     }
 
@@ -9371,7 +9630,7 @@
             &operation, base_key, alg,
             input1->x, input1->len,
             input2->x, input2->len,
-            PSA_KEY_DERIVATION_UNLIMITED_CAPACITY) == 0) {
+            PSA_KEY_DERIVATION_UNLIMITED_CAPACITY, 0) == 0) {
         goto exit;
     }
 
@@ -9435,7 +9694,7 @@
     if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, base_key, alg,
                                                     input1->x, input1->len,
                                                     input2->x, input2->len,
-                                                    SIZE_MAX)) {
+                                                    SIZE_MAX, 0)) {
         goto exit;
     }
 
@@ -9783,6 +10042,59 @@
 }
 /* END_CASE */
 
+#if defined MBEDTLS_THREADING_PTHREAD
+
+/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD */
+void concurrently_generate_keys(int type_arg,
+                                int bits_arg,
+                                int usage_arg,
+                                int alg_arg,
+                                int expected_status_arg,
+                                int is_large_key_arg,
+                                int arg_thread_count,
+                                int reps_arg)
+{
+    size_t thread_count = (size_t) arg_thread_count;
+    mbedtls_test_thread_t *threads = NULL;
+    generate_key_context gkc;
+    gkc.type = type_arg;
+    gkc.usage = usage_arg;
+    gkc.bits = bits_arg;
+    gkc.alg = alg_arg;
+    gkc.expected_status = expected_status_arg;
+    gkc.is_large_key = is_large_key_arg;
+    gkc.reps = reps_arg;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    PSA_ASSERT(psa_crypto_init());
+
+    psa_set_key_usage_flags(&attributes, usage_arg);
+    psa_set_key_algorithm(&attributes, alg_arg);
+    psa_set_key_type(&attributes, type_arg);
+    psa_set_key_bits(&attributes, bits_arg);
+    gkc.attributes = &attributes;
+
+    TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count);
+
+    /* Split threads to generate key then destroy key. */
+    for (size_t i = 0; i < thread_count; i++) {
+        TEST_EQUAL(
+            mbedtls_test_thread_create(&threads[i], thread_generate_key,
+                                       (void *) &gkc), 0);
+    }
+
+    /* Join threads. */
+    for (size_t i = 0; i < thread_count; i++) {
+        TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0);
+    }
+
+exit:
+    mbedtls_free(threads);
+    PSA_DONE();
+}
+/* END_CASE */
+#endif
+
 /* BEGIN_CASE */
 void generate_key(int type_arg,
                   int bits_arg,
@@ -9824,7 +10136,7 @@
     TEST_EQUAL(psa_get_key_bits(&got_attributes), bits);
 
     /* Do something with the key according to its type and permitted usage. */
-    if (!mbedtls_test_psa_exercise_key(key, usage, alg)) {
+    if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) {
         goto exit;
     }
 
@@ -9894,7 +10206,7 @@
 #endif
 
     /* Do something with the key according to its type and permitted usage. */
-    if (!mbedtls_test_psa_exercise_key(key, usage, alg)) {
+    if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) {
         goto exit;
     }
 
@@ -10045,7 +10357,7 @@
     }
 
     /* Do something with the key according to its type and permitted usage. */
-    if (!mbedtls_test_psa_exercise_key(key, usage_flags, alg)) {
+    if (!mbedtls_test_psa_exercise_key(key, usage_flags, alg, 0)) {
         goto exit;
     }
 
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data
index 37c15ee..54e0892 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data
@@ -238,10 +238,11 @@
 generate_ec_key:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_SUCCESS
 
 generate_ec_key through transparent driver: in-driver
+depends_on:MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE
 generate_ec_key:PSA_SUCCESS:"":PSA_SUCCESS
 
 generate_ec_key through transparent driver: fallback
-depends_on:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE
+depends_on:MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE:MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256
 generate_ec_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_SUCCESS
 
 generate_ec_key through transparent driver: fallback not available
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
index 032fa47..e7925dd 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
@@ -57,7 +57,7 @@
             /* Server first round Output */
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_g1_len));
+                                       buffer_length - buffer0_off, &s_g1_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_EQUAL(s_g1_len, expected_size_key_share);
@@ -65,7 +65,7 @@
             buffer0_off += s_g1_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x1_pk_len));
+                                       buffer_length - buffer0_off, &s_x1_pk_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_EQUAL(s_x1_pk_len, expected_size_zk_public);
@@ -73,7 +73,7 @@
             buffer0_off += s_x1_pk_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x1_pr_len));
+                                       buffer_length - buffer0_off, &s_x1_pr_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_LE_U(s_x1_pr_len, max_expected_size_zk_proof);
@@ -81,7 +81,7 @@
             buffer0_off += s_x1_pr_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_g2_len));
+                                       buffer_length - buffer0_off, &s_g2_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_EQUAL(s_g2_len, expected_size_key_share);
@@ -89,7 +89,7 @@
             buffer0_off += s_g2_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x2_pk_len));
+                                       buffer_length - buffer0_off, &s_x2_pk_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_EQUAL(s_x2_pk_len, expected_size_zk_public);
@@ -97,7 +97,7 @@
             buffer0_off += s_x2_pk_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x2_pr_len));
+                                       buffer_length - buffer0_off, &s_x2_pr_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_LE_U(s_x2_pr_len, max_expected_size_zk_proof);
@@ -154,7 +154,7 @@
             /* Client first round Output */
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_g1_len));
+                                       buffer_length - buffer1_off, &c_g1_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_EQUAL(c_g1_len, expected_size_key_share);
@@ -162,7 +162,7 @@
             buffer1_off += c_g1_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x1_pk_len));
+                                       buffer_length - buffer1_off, &c_x1_pk_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_EQUAL(c_x1_pk_len, expected_size_zk_public);
@@ -170,7 +170,7 @@
             buffer1_off += c_x1_pk_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x1_pr_len));
+                                       buffer_length - buffer1_off, &c_x1_pr_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_LE_U(c_x1_pr_len, max_expected_size_zk_proof);
@@ -178,7 +178,7 @@
             buffer1_off += c_x1_pr_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_g2_len));
+                                       buffer_length - buffer1_off, &c_g2_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_EQUAL(c_g2_len, expected_size_key_share);
@@ -186,7 +186,7 @@
             buffer1_off += c_g2_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x2_pk_len));
+                                       buffer_length - buffer1_off, &c_x2_pk_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_EQUAL(c_x2_pk_len, expected_size_zk_public);
@@ -194,7 +194,7 @@
             buffer1_off += c_x2_pk_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x2_pr_len));
+                                       buffer_length - buffer1_off, &c_x2_pr_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_LE_U(c_x2_pr_len, max_expected_size_zk_proof);
@@ -290,7 +290,7 @@
 
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_a_len));
+                                       buffer_length - buffer0_off, &s_a_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_EQUAL(s_a_len, expected_size_key_share);
@@ -298,7 +298,7 @@
             buffer0_off += s_a_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x2s_pk_len));
+                                       buffer_length - buffer0_off, &s_x2s_pk_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_EQUAL(s_x2s_pk_len, expected_size_zk_public);
@@ -306,7 +306,7 @@
             buffer0_off += s_x2s_pk_len;
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x2s_pr_len));
+                                       buffer_length - buffer0_off, &s_x2s_pr_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_LE_U(s_x2s_pr_len, max_expected_size_zk_proof);
@@ -341,7 +341,7 @@
 
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_a_len));
+                                       buffer_length - buffer1_off, &c_a_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_EQUAL(c_a_len, expected_size_key_share);
@@ -349,7 +349,7 @@
             buffer1_off += c_a_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x2s_pk_len));
+                                       buffer_length - buffer1_off, &c_x2s_pk_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_EQUAL(c_x2s_pk_len, expected_size_zk_public);
@@ -357,7 +357,7 @@
             buffer1_off += c_x2s_pk_len;
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x2s_pr_len));
+                                       buffer_length - buffer1_off, &c_x2s_pr_len));
             TEST_EQUAL(mbedtls_test_driver_pake_hooks.hits.total,
                        pake_in_driver ? pake_expected_hit_count++ : pake_expected_hit_count);
             TEST_LE_U(c_x2s_pr_len, max_expected_size_zk_proof);
@@ -748,7 +748,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_ECDSA:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
 void generate_ec_key(int force_status_arg,
                      data_t *fake_output,
                      int expected_status_arg)
@@ -782,13 +782,14 @@
                 fake_output->len;
     }
 
-    mbedtls_test_driver_key_management_hooks.hits = 0;
-    mbedtls_test_driver_key_management_hooks.forced_status = force_status;
-
     PSA_ASSERT(psa_crypto_init());
 
+    mbedtls_test_driver_key_management_hooks.hits = 0;
+    mbedtls_test_driver_key_management_hooks.hits_generate_key = 0;
+    mbedtls_test_driver_key_management_hooks.forced_status = force_status;
+
     actual_status = psa_generate_key(&attributes, &key);
-    TEST_EQUAL(mbedtls_test_driver_key_management_hooks.hits, 1);
+    TEST_EQUAL(mbedtls_test_driver_key_management_hooks.hits_generate_key, 1);
     TEST_EQUAL(actual_status, expected_status);
 
     if (actual_status == PSA_SUCCESS) {
@@ -1495,14 +1496,7 @@
         output, output_buffer_size, &function_output_length);
     TEST_EQUAL(mbedtls_test_driver_cipher_hooks.hits_encrypt, 1);
     TEST_EQUAL(status, PSA_ERROR_GENERIC_ERROR);
-    /*
-     * Check that the output buffer is still in the same state.
-     * This will fail if the output buffer is used by the core to pass the IV
-     * it generated to the driver (and is not restored).
-     */
-    for (size_t i = 0; i < output_buffer_size; i++) {
-        TEST_EQUAL(output[i], 0xa5);
-    }
+
     mbedtls_test_driver_cipher_hooks.hits = 0;
 
     /* Test setup call, encrypt */
@@ -1566,14 +1560,6 @@
     TEST_EQUAL(mbedtls_test_driver_cipher_hooks.hits_set_iv, 1);
     TEST_EQUAL(status, mbedtls_test_driver_cipher_hooks.forced_status_set_iv);
     mbedtls_test_driver_cipher_hooks.forced_status_set_iv = PSA_SUCCESS;
-    /*
-     * Check that the output buffer is still in the same state.
-     * This will fail if the output buffer is used by the core to pass the IV
-     * it generated to the driver (and is not restored).
-     */
-    for (size_t i = 0; i < 16; i++) {
-        TEST_EQUAL(output[i], 0xa5);
-    }
     /* Failure should prevent further operations from executing on the driver */
     mbedtls_test_driver_cipher_hooks.hits = 0;
     status = psa_cipher_update(&operation,
diff --git a/tests/suites/test_suite_psa_crypto_init.data b/tests/suites/test_suite_psa_crypto_init.data
index 8c5b41d..147d03f 100644
--- a/tests/suites/test_suite_psa_crypto_init.data
+++ b/tests/suites/test_suite_psa_crypto_init.data
@@ -10,6 +10,9 @@
 PSA deinit twice
 deinit_without_init:1
 
+PSA threaded init checks
+psa_threaded_init:100
+
 No random without init
 validate_module_init_generate_random:0
 
diff --git a/tests/suites/test_suite_psa_crypto_init.function b/tests/suites/test_suite_psa_crypto_init.function
index 7a43432..9ff33a6 100644
--- a/tests/suites/test_suite_psa_crypto_init.function
+++ b/tests/suites/test_suite_psa_crypto_init.function
@@ -1,6 +1,7 @@
 /* BEGIN_HEADER */
 #include <stdint.h>
 
+#include "psa_crypto_core.h"
 /* Some tests in this module configure entropy sources. */
 #include "psa_crypto_invasive.h"
 
@@ -112,6 +113,59 @@
 
 #endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
 
+#if defined MBEDTLS_THREADING_PTHREAD
+
+typedef struct {
+    int do_init;
+} thread_psa_init_ctx_t;
+
+static void *thread_psa_init_function(void *ctx)
+{
+    thread_psa_init_ctx_t *init_context = (thread_psa_init_ctx_t *) ctx;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    uint8_t random[10] = { 0 };
+
+    if (init_context->do_init) {
+        PSA_ASSERT(psa_crypto_init());
+    }
+
+    /* If this is a test only thread, then we can assume PSA is being started
+     * up on another thread and thus we cannot know whether the following tests
+     * will be successful or not. These checks are still useful, however even
+     * without checking the return codes as they may show up race conditions on
+     * the flags they check under TSAN.*/
+
+    /* Test getting if drivers are initialised. */
+    int can_do = psa_can_do_hash(PSA_ALG_NONE);
+
+    if (init_context->do_init) {
+        TEST_ASSERT(can_do == 1);
+    }
+
+#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+
+    /* Test getting global_data.rng_state. */
+    status = mbedtls_psa_crypto_configure_entropy_sources(NULL, NULL);
+
+    if (init_context->do_init) {
+        /* Bad state due to entropy sources already being setup in
+         * psa_crypto_init() */
+        TEST_EQUAL(status, PSA_ERROR_BAD_STATE);
+    }
+#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
+
+    /* Test using the PSA RNG ony if we know PSA is up and running. */
+    if (init_context->do_init) {
+        status = psa_generate_random(random, sizeof(random));
+
+        TEST_EQUAL(status, PSA_SUCCESS);
+    }
+
+exit:
+    return NULL;
+}
+#endif /* defined MBEDTLS_THREADING_PTHREAD */
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -154,6 +208,67 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD */
+void psa_threaded_init(int arg_thread_count)
+{
+    thread_psa_init_ctx_t init_context;
+    thread_psa_init_ctx_t init_context_2;
+
+    size_t thread_count = (size_t) arg_thread_count;
+    mbedtls_test_thread_t *threads = NULL;
+
+    TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count);
+
+    init_context.do_init = 1;
+
+    /* Test initialising PSA and testing certain protected globals on multiple
+     * threads. */
+    for (size_t i = 0; i < thread_count; i++) {
+        TEST_EQUAL(
+            mbedtls_test_thread_create(&threads[i],
+                                       thread_psa_init_function,
+                                       (void *) &init_context),
+            0);
+    }
+
+    for (size_t i = 0; i < thread_count; i++) {
+        TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0);
+    }
+
+    PSA_DONE();
+
+    init_context_2.do_init = 0;
+
+    /* Test initialising PSA whilst also testing flags on other threads. */
+    for (size_t i = 0; i < thread_count; i++) {
+
+        if (i & 1) {
+
+            TEST_EQUAL(
+                mbedtls_test_thread_create(&threads[i],
+                                           thread_psa_init_function,
+                                           (void *) &init_context),
+                0);
+        } else {
+            TEST_EQUAL(
+                mbedtls_test_thread_create(&threads[i],
+                                           thread_psa_init_function,
+                                           (void *) &init_context_2),
+                0);
+        }
+    }
+
+    for (size_t i = 0; i < thread_count; i++) {
+        TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0);
+    }
+exit:
+
+    PSA_DONE();
+
+    mbedtls_free(threads);
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void validate_module_init_generate_random(int count)
 {
diff --git a/tests/suites/test_suite_psa_crypto_memory.data b/tests/suites/test_suite_psa_crypto_memory.data
new file mode 100644
index 0000000..2a828f5
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_memory.data
@@ -0,0 +1,62 @@
+PSA input buffer copy: straightforward copy
+copy_input:20:20:PSA_SUCCESS
+
+PSA input buffer copy: copy buffer larger than required
+copy_input:10:20:PSA_SUCCESS
+
+PSA input buffer copy: copy buffer too small
+copy_input:20:10:PSA_ERROR_CORRUPTION_DETECTED
+
+PSA input buffer copy: zero-length source buffer
+copy_input:0:10:PSA_SUCCESS
+
+PSA input buffer copy: zero-length both buffers
+copy_input:0:0:PSA_SUCCESS
+
+PSA output buffer copy: straightforward copy
+copy_output:20:20:PSA_SUCCESS
+
+PSA output buffer copy: output buffer larger than required
+copy_output:10:20:PSA_SUCCESS
+
+PSA output buffer copy: output buffer too small
+copy_output:20:10:PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA output buffer copy: zero-length source buffer
+copy_output:0:10:PSA_SUCCESS
+
+PSA output buffer copy: zero-length both buffers
+copy_output:0:0:PSA_SUCCESS
+
+PSA crypto local input alloc
+local_input_alloc:200:PSA_SUCCESS
+
+PSA crypto local input alloc, NULL buffer
+local_input_alloc:0:PSA_SUCCESS
+
+PSA crypto local input free
+local_input_free:200
+
+PSA crypto local input free, NULL buffer
+local_input_free:0
+
+PSA crypto local input round-trip
+local_input_round_trip
+
+PSA crypto local output alloc
+local_output_alloc:200:PSA_SUCCESS
+
+PSA crypto local output alloc, NULL buffer
+local_output_alloc:0:PSA_SUCCESS
+
+PSA crypto local output free
+local_output_free:200:0:PSA_SUCCESS
+
+PSA crypto local output free, NULL buffer
+local_output_free:0:0:PSA_SUCCESS
+
+PSA crypto local output free, NULL original buffer
+local_output_free:200:1:PSA_ERROR_CORRUPTION_DETECTED
+
+PSA crypto local output round-trip
+local_output_round_trip
diff --git a/tests/suites/test_suite_psa_crypto_memory.function b/tests/suites/test_suite_psa_crypto_memory.function
new file mode 100644
index 0000000..55c0092
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_memory.function
@@ -0,0 +1,258 @@
+/* BEGIN_HEADER */
+#include <stdint.h>
+
+#include "common.h"
+
+#include "psa/crypto.h"
+
+#include "psa_crypto_core.h"
+#include "psa_crypto_invasive.h"
+
+#include "test/psa_crypto_helpers.h"
+#include "test/memory.h"
+
+/* Helper to fill a buffer with a data pattern. The pattern is not
+ * important, it just allows a basic check that the correct thing has
+ * been written, in a way that will detect an error in offset. */
+static void fill_buffer_pattern(uint8_t *buffer, size_t len)
+{
+    for (size_t i = 0; i < len; i++) {
+        buffer[i] = (uint8_t) (i % 256);
+    }
+}
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_TEST_HOOKS
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void copy_input(int src_len, int dst_len, psa_status_t exp_status)
+{
+    uint8_t *src_buffer = NULL;
+    uint8_t *dst_buffer = NULL;
+    psa_status_t status;
+
+    TEST_CALLOC(src_buffer, src_len);
+    TEST_CALLOC(dst_buffer, dst_len);
+
+    fill_buffer_pattern(src_buffer, src_len);
+
+    status = psa_crypto_copy_input(src_buffer, src_len, dst_buffer, dst_len);
+    TEST_EQUAL(status, exp_status);
+
+    if (exp_status == PSA_SUCCESS) {
+        MBEDTLS_TEST_MEMORY_UNPOISON(src_buffer, src_len);
+        /* Note: We compare the first src_len bytes of each buffer, as this is what was copied. */
+        TEST_MEMORY_COMPARE(src_buffer, src_len, dst_buffer, src_len);
+    }
+
+exit:
+    mbedtls_free(src_buffer);
+    mbedtls_free(dst_buffer);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void copy_output(int src_len, int dst_len, psa_status_t exp_status)
+{
+    uint8_t *src_buffer = NULL;
+    uint8_t *dst_buffer = NULL;
+    psa_status_t status;
+
+    TEST_CALLOC(src_buffer, src_len);
+    TEST_CALLOC(dst_buffer, dst_len);
+
+    fill_buffer_pattern(src_buffer, src_len);
+
+    status = psa_crypto_copy_output(src_buffer, src_len, dst_buffer, dst_len);
+    TEST_EQUAL(status, exp_status);
+
+    if (exp_status == PSA_SUCCESS) {
+        MBEDTLS_TEST_MEMORY_UNPOISON(dst_buffer, dst_len);
+        /* Note: We compare the first src_len bytes of each buffer, as this is what was copied. */
+        TEST_MEMORY_COMPARE(src_buffer, src_len, dst_buffer, src_len);
+    }
+
+exit:
+    mbedtls_free(src_buffer);
+    mbedtls_free(dst_buffer);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void local_input_alloc(int input_len, psa_status_t exp_status)
+{
+    uint8_t *input = NULL;
+    psa_crypto_local_input_t local_input;
+    psa_status_t status;
+
+    local_input.buffer = NULL;
+
+    TEST_CALLOC(input, input_len);
+    fill_buffer_pattern(input, input_len);
+
+    status = psa_crypto_local_input_alloc(input, input_len, &local_input);
+    TEST_EQUAL(status, exp_status);
+
+    if (exp_status == PSA_SUCCESS) {
+        MBEDTLS_TEST_MEMORY_UNPOISON(input, input_len);
+        if (input_len != 0) {
+            TEST_ASSERT(local_input.buffer != input);
+        }
+        TEST_MEMORY_COMPARE(input, input_len,
+                            local_input.buffer, local_input.length);
+    }
+
+exit:
+    mbedtls_free(local_input.buffer);
+    mbedtls_free(input);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void local_input_free(int input_len)
+{
+    psa_crypto_local_input_t local_input;
+
+    local_input.buffer = NULL;
+    local_input.length = input_len;
+    TEST_CALLOC(local_input.buffer, local_input.length);
+
+    psa_crypto_local_input_free(&local_input);
+
+    TEST_ASSERT(local_input.buffer == NULL);
+    TEST_EQUAL(local_input.length, 0);
+
+exit:
+    mbedtls_free(local_input.buffer);
+    local_input.buffer = NULL;
+    local_input.length = 0;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void local_input_round_trip()
+{
+    psa_crypto_local_input_t local_input;
+    uint8_t input[200];
+    psa_status_t status;
+
+    fill_buffer_pattern(input, sizeof(input));
+
+    status = psa_crypto_local_input_alloc(input, sizeof(input), &local_input);
+    TEST_EQUAL(status, PSA_SUCCESS);
+
+    MBEDTLS_TEST_MEMORY_UNPOISON(input, sizeof(input));
+    TEST_MEMORY_COMPARE(local_input.buffer, local_input.length,
+                        input, sizeof(input));
+    TEST_ASSERT(local_input.buffer != input);
+
+    psa_crypto_local_input_free(&local_input);
+    TEST_ASSERT(local_input.buffer == NULL);
+    TEST_EQUAL(local_input.length, 0);
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void local_output_alloc(int output_len, psa_status_t exp_status)
+{
+    uint8_t *output = NULL;
+    psa_crypto_local_output_t local_output;
+    psa_status_t status;
+
+    local_output.buffer = NULL;
+
+    TEST_CALLOC(output, output_len);
+
+    status = psa_crypto_local_output_alloc(output, output_len, &local_output);
+    TEST_EQUAL(status, exp_status);
+
+    if (exp_status == PSA_SUCCESS) {
+        TEST_ASSERT(local_output.original == output);
+        TEST_EQUAL(local_output.length, output_len);
+    }
+
+exit:
+    mbedtls_free(local_output.buffer);
+    local_output.original = NULL;
+    local_output.buffer = NULL;
+    local_output.length = 0;
+    mbedtls_free(output);
+    output = NULL;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void local_output_free(int output_len, int original_is_null,
+                       psa_status_t exp_status)
+{
+    uint8_t *output = NULL;
+    uint8_t *buffer_copy_for_comparison = NULL;
+    psa_crypto_local_output_t local_output = PSA_CRYPTO_LOCAL_OUTPUT_INIT;
+    psa_status_t status;
+
+    if (!original_is_null) {
+        TEST_CALLOC(output, output_len);
+    }
+    TEST_CALLOC(buffer_copy_for_comparison, output_len);
+    TEST_CALLOC(local_output.buffer, output_len);
+    local_output.length = output_len;
+    local_output.original = output;
+
+    if (local_output.length != 0) {
+        fill_buffer_pattern(local_output.buffer, local_output.length);
+        memcpy(buffer_copy_for_comparison, local_output.buffer, local_output.length);
+    }
+
+    status = psa_crypto_local_output_free(&local_output);
+    TEST_EQUAL(status, exp_status);
+
+    if (exp_status == PSA_SUCCESS) {
+        MBEDTLS_TEST_MEMORY_UNPOISON(output, output_len);
+        TEST_ASSERT(local_output.buffer == NULL);
+        TEST_EQUAL(local_output.length, 0);
+        TEST_MEMORY_COMPARE(buffer_copy_for_comparison, output_len,
+                            output, output_len);
+    }
+
+exit:
+    mbedtls_free(output);
+    mbedtls_free(buffer_copy_for_comparison);
+    mbedtls_free(local_output.buffer);
+    local_output.length = 0;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void local_output_round_trip()
+{
+    psa_crypto_local_output_t local_output;
+    uint8_t output[200];
+    uint8_t *buffer_copy_for_comparison = NULL;
+    psa_status_t status;
+
+    status = psa_crypto_local_output_alloc(output, sizeof(output), &local_output);
+    TEST_EQUAL(status, PSA_SUCCESS);
+    TEST_ASSERT(local_output.buffer != output);
+
+    /* Simulate the function generating output */
+    fill_buffer_pattern(local_output.buffer, local_output.length);
+
+    TEST_CALLOC(buffer_copy_for_comparison, local_output.length);
+    memcpy(buffer_copy_for_comparison, local_output.buffer, local_output.length);
+
+    psa_crypto_local_output_free(&local_output);
+    TEST_ASSERT(local_output.buffer == NULL);
+    TEST_EQUAL(local_output.length, 0);
+
+    MBEDTLS_TEST_MEMORY_UNPOISON(output, sizeof(output));
+    /* Check that the buffer was correctly copied back */
+    TEST_MEMORY_COMPARE(output, sizeof(output),
+                        buffer_copy_for_comparison, sizeof(output));
+
+exit:
+    mbedtls_free(buffer_copy_for_comparison);
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_psa_crypto_op_fail.function b/tests/suites/test_suite_psa_crypto_op_fail.function
index 20942bf..9878237 100644
--- a/tests/suites/test_suite_psa_crypto_op_fail.function
+++ b/tests/suites/test_suite_psa_crypto_op_fail.function
@@ -359,9 +359,9 @@
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
     uint8_t public_key[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE] = { 0 };
-    size_t public_key_length = SIZE_MAX;
+    size_t public_key_length = 0;
     uint8_t output[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE] = { 0 };
-    size_t length = SIZE_MAX;
+    size_t length = 0;
     psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
 
     PSA_INIT();
diff --git a/tests/suites/test_suite_psa_crypto_pake.data b/tests/suites/test_suite_psa_crypto_pake.data
index baebded..49e97a9 100644
--- a/tests/suites/test_suite_psa_crypto_pake.data
+++ b/tests/suites/test_suite_psa_crypto_pake.data
@@ -211,19 +211,19 @@
 ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND2_SERVER_ZK_PROOF:PSA_ERROR_DATA_INVALID:1
 
 PSA PAKE: inject ERR_INJECT_EXTRA_OUTPUT
-depends_on:MBEDTLS_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
 ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_EXTRA_OUTPUT:PSA_ERROR_BAD_STATE:0
 
 PSA PAKE: inject ERR_INJECT_EXTRA_INPUT
-depends_on:MBEDTLS_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
 ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:1:"abcdef":ERR_INJECT_EXTRA_INPUT:PSA_ERROR_BAD_STATE:0
 
 PSA PAKE: inject ERR_INJECT_EXTRA_OUTPUT_AT_END
-depends_on:MBEDTLS_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
 ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:1:"abcdef":ERR_INJECT_EXTRA_OUTPUT_AT_END:PSA_ERROR_BAD_STATE:1
 
 PSA PAKE: inject ERR_INJECT_EXTRA_INPUT_AT_END
-depends_on:MBEDTLS_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
 ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_EXTRA_INPUT_AT_END:PSA_ERROR_BAD_STATE:1
 
 PSA PAKE: ecjpake size macros
diff --git a/tests/suites/test_suite_psa_crypto_pake.function b/tests/suites/test_suite_psa_crypto_pake.function
index fed2c41..1cc69a7 100644
--- a/tests/suites/test_suite_psa_crypto_pake.function
+++ b/tests/suites/test_suite_psa_crypto_pake.function
@@ -147,7 +147,7 @@
             /* Server first round Output */
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_g1_len));
+                                       buffer_length - buffer0_off, &s_g1_len));
             TEST_EQUAL(s_g1_len, expected_size_key_share);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART1,
@@ -156,7 +156,7 @@
 
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x1_pk_len));
+                                       buffer_length - buffer0_off, &s_x1_pk_len));
             TEST_EQUAL(s_x1_pk_len, expected_size_zk_public);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND1_SERVER_ZK_PUBLIC_PART1,
@@ -165,7 +165,7 @@
 
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x1_pr_len));
+                                       buffer_length - buffer0_off, &s_x1_pr_len));
             TEST_LE_U(s_x1_pr_len, max_expected_size_zk_proof);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART1,
@@ -174,7 +174,7 @@
 
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_g2_len));
+                                       buffer_length - buffer0_off, &s_g2_len));
             TEST_EQUAL(s_g2_len, expected_size_key_share);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART2,
@@ -183,7 +183,7 @@
 
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x2_pk_len));
+                                       buffer_length - buffer0_off, &s_x2_pk_len));
             TEST_EQUAL(s_x2_pk_len, expected_size_zk_public);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND1_SERVER_ZK_PUBLIC_PART2,
@@ -192,7 +192,7 @@
 
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x2_pr_len));
+                                       buffer_length - buffer0_off, &s_x2_pr_len));
             TEST_LE_U(s_x2_pr_len, max_expected_size_zk_proof);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART2,
@@ -203,7 +203,7 @@
             DO_ROUND_CONDITIONAL_CHECK_FAILURE(
                 ERR_INJECT_EXTRA_OUTPUT,
                 psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
-                                buffer0 + s_g2_off, 512 - s_g2_off, &extra_output_len));
+                                buffer0 + s_g2_off, buffer_length - s_g2_off, &extra_output_len));
             (void) extra_output_len;
             /*
              * When injecting errors in inputs, the implementation is
@@ -260,7 +260,7 @@
             /* Client first round Output */
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_g1_len));
+                                       buffer_length - buffer1_off, &c_g1_len));
             TEST_EQUAL(c_g1_len, expected_size_key_share);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND1_CLIENT_KEY_SHARE_PART1,
@@ -269,7 +269,7 @@
 
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x1_pk_len));
+                                       buffer_length - buffer1_off, &c_x1_pk_len));
             TEST_EQUAL(c_x1_pk_len, expected_size_zk_public);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND1_CLIENT_ZK_PUBLIC_PART1,
@@ -278,7 +278,7 @@
 
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x1_pr_len));
+                                       buffer_length - buffer1_off, &c_x1_pr_len));
             TEST_LE_U(c_x1_pr_len, max_expected_size_zk_proof);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND1_CLIENT_ZK_PROOF_PART1,
@@ -287,7 +287,7 @@
 
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_g2_len));
+                                       buffer_length - buffer1_off, &c_g2_len));
             TEST_EQUAL(c_g2_len, expected_size_key_share);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND1_CLIENT_KEY_SHARE_PART2,
@@ -296,7 +296,7 @@
 
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x2_pk_len));
+                                       buffer_length - buffer1_off, &c_x2_pk_len));
             TEST_EQUAL(c_x2_pk_len, expected_size_zk_public);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND1_CLIENT_ZK_PUBLIC_PART2,
@@ -305,7 +305,7 @@
 
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x2_pr_len));
+                                       buffer_length - buffer1_off, &c_x2_pr_len));
             TEST_LE_U(c_x2_pr_len, max_expected_size_zk_proof);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND1_CLIENT_ZK_PROOF_PART2,
@@ -391,7 +391,7 @@
 
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_a_len));
+                                       buffer_length - buffer0_off, &s_a_len));
             TEST_EQUAL(s_a_len, expected_size_key_share);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND2_SERVER_KEY_SHARE,
@@ -400,7 +400,7 @@
 
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x2s_pk_len));
+                                       buffer_length - buffer0_off, &s_x2s_pk_len));
             TEST_EQUAL(s_x2s_pk_len, expected_size_zk_public);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND2_SERVER_ZK_PUBLIC,
@@ -409,7 +409,7 @@
 
             PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer0 + buffer0_off,
-                                       512 - buffer0_off, &s_x2s_pr_len));
+                                       buffer_length - buffer0_off, &s_x2s_pr_len));
             TEST_LE_U(s_x2s_pr_len, max_expected_size_zk_proof);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND2_SERVER_ZK_PROOF,
@@ -445,7 +445,7 @@
 
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_a_len));
+                                       buffer_length - buffer1_off, &c_a_len));
             TEST_EQUAL(c_a_len, expected_size_key_share);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND2_CLIENT_KEY_SHARE,
@@ -454,7 +454,7 @@
 
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PUBLIC,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x2s_pk_len));
+                                       buffer_length - buffer1_off, &c_x2s_pk_len));
             TEST_EQUAL(c_x2s_pk_len, expected_size_zk_public);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND2_CLIENT_ZK_PUBLIC,
@@ -463,7 +463,7 @@
 
             PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PROOF,
                                        buffer1 + buffer1_off,
-                                       512 - buffer1_off, &c_x2s_pr_len));
+                                       buffer_length - buffer1_off, &c_x2s_pr_len));
             TEST_LE_U(c_x2s_pr_len, max_expected_size_zk_proof);
             DO_ROUND_CONDITIONAL_INJECT(
                 ERR_INJECT_ROUND2_CLIENT_ZK_PROOF,
@@ -475,7 +475,7 @@
                 DO_ROUND_CONDITIONAL_CHECK_FAILURE(
                     ERR_INJECT_EXTRA_OUTPUT_AT_END,
                     psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
-                                    buffer1 + c_a_off, 512 - c_a_off,
+                                    buffer1 + c_a_off, buffer_length - c_a_off,
                                     &extra_output_at_end_len));
                 (void) extra_output_at_end_len;
             }
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.function b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
index e3681ba..37a72d9 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal.function
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
@@ -13,6 +13,19 @@
 #include "psa/internal_trusted_storage.h"
 #endif
 
+/* Same in library/psa_crypto.c */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) ||          \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) ||  \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
+#define BUILTIN_ALG_ANY_HKDF 1
+#endif
+#if defined(BUILTIN_ALG_ANY_HKDF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) || \
+    defined(PSA_HAVE_SOFT_PBKDF2)
+#define AT_LEAST_ONE_BUILTIN_KDF
+#endif
 
 /****************************************************************/
 /* Test driver helpers */
@@ -720,7 +733,7 @@
                                         buffer, sizeof(buffer), NULL, 0,
                                         buffer, sizeof(buffer), &length));
 
-#if defined(PSA_WANT_ALG_SHA_256)
+#if defined(PSA_WANT_ALG_SHA_256) && defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
     /* Try the key in a plain key derivation. */
     PSA_ASSERT(psa_key_derivation_setup(&derivation_operation,
                                         PSA_ALG_HKDF(PSA_ALG_SHA_256)));
@@ -753,7 +766,9 @@
                          alg, key, buffer, length,
                          buffer, sizeof(buffer), &length));
     }
-#endif /* PSA_WANT_ALG_SHA_256 */
+#else
+    (void) derivation_operation;
+#endif /* PSA_WANT_ALG_SHA_256 && MBEDTLS_PSA_BUILTIN_ALG_HKDF */
 
     ok = 1;
 
diff --git a/tests/suites/test_suite_psa_crypto_storage_format.function b/tests/suites/test_suite_psa_crypto_storage_format.function
index bb1e2c6..efaaba5 100644
--- a/tests/suites/test_suite_psa_crypto_storage_format.function
+++ b/tests/suites/test_suite_psa_crypto_storage_format.function
@@ -187,7 +187,7 @@
         TEST_ASSERT(mbedtls_test_psa_exercise_key(
                         key_id,
                         psa_get_key_usage_flags(expected_attributes),
-                        psa_get_key_algorithm(expected_attributes)));
+                        psa_get_key_algorithm(expected_attributes), 0));
     }
 
 
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index 385682a..c96b4ad 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -117,7 +117,7 @@
 move_handshake_to_state:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:MBEDTLS_SSL_SERVER_HELLO:1
 
 TLS 1.2:Move client handshake to SERVER_CERTIFICATE
-depends_on:MBEDTLS_SSP_PROTO_TLS1_2:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY
+depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY
 move_handshake_to_state:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:MBEDTLS_SSL_SERVER_CERTIFICATE:1
 
 TLS 1.2:Move client handshake to SERVER_KEY_EXCHANGE
@@ -930,37 +930,45 @@
 ssl_session_serialize_version_check:0:0:0:1:0:MBEDTLS_SSL_VERSION_TLS1_2
 
 TLS 1.3: CLI: session serialization: Wrong major version
-depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SESSION_TICKETS
 ssl_session_serialize_version_check:1:0:0:0:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3
 
 TLS 1.3: CLI: session serialization: Wrong minor version
-depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SESSION_TICKETS
 ssl_session_serialize_version_check:0:1:0:0:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3
 
 TLS 1.3: CLI: session serialization: Wrong patch version
-depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SESSION_TICKETS
 ssl_session_serialize_version_check:0:0:1:0:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3
 
 TLS 1.3: CLI: session serialization: Wrong config
-depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SESSION_TICKETS
 ssl_session_serialize_version_check:0:0:0:1:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3
 
 TLS 1.3: SRV: session serialization: Wrong major version
-depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SRV_C
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_SESSION_TICKETS
 ssl_session_serialize_version_check:1:0:0:0:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3
 
 TLS 1.3: SRV: session serialization: Wrong minor version
-depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SRV_C
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_SESSION_TICKETS
 ssl_session_serialize_version_check:0:1:0:0:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3
 
 TLS 1.3: SRV: session serialization: Wrong patch version
-depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SRV_C
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_SESSION_TICKETS
 ssl_session_serialize_version_check:0:0:1:0:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3
 
 TLS 1.3: SRV: session serialization: Wrong config
-depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SRV_C
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_SESSION_TICKETS
 ssl_session_serialize_version_check:0:0:0:1:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3
 
+Test Session id & Ciphersuite accessors TLS 1.2
+depends_on:MBEDTLS_SSL_PROTO_TLS1_2
+ssl_session_id_accessors_check:MBEDTLS_SSL_VERSION_TLS1_2
+
+Test Session id & Ciphersuite accessors TLS 1.3
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3
+ssl_session_id_accessors_check:MBEDTLS_SSL_VERSION_TLS1_3
+
 Record crypt, AES-128-CBC, 1.2, SHA-384
 depends_on:MBEDTLS_SSL_HAVE_AES:MBEDTLS_SSL_HAVE_CBC:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_MD_CAN_SHA384
 ssl_crypt_record:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_MD_SHA384:0:0:MBEDTLS_SSL_VERSION_TLS1_2:0:0
@@ -2963,7 +2971,7 @@
 ssl_serialize_session_save_load:1023:"data_files/server5.crt":0:MBEDTLS_SSL_VERSION_TLS1_2
 
 TLS 1.3: CLI: Session serialization, save-load: no ticket
-depends_on:MBEDTLS_SSL_PROTO_TLS1_3
+depends_on:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_PROTO_TLS1_3
 ssl_serialize_session_save_load:0:"":MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3
 
 TLS 1.3: CLI: Session serialization, save-load: small ticket
@@ -3083,7 +3091,7 @@
 ssl_serialize_session_load_buf_size:1023:"data_files/server5.crt":0:MBEDTLS_SSL_VERSION_TLS1_2
 
 TLS 1.3: CLI: Session serialization, load buffer size: no ticket
-depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_CLI_C
 ssl_serialize_session_load_buf_size:0:"":MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3
 
 TLS 1.3: CLI: Session serialization, load buffer size: small ticket
@@ -3095,7 +3103,7 @@
 ssl_serialize_session_load_buf_size:1023:"":MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3
 
 TLS 1.3: SRV: Session serialization, load buffer size
-depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SRV_C
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SESSION_TICKETS:MBEDTLS_SSL_SRV_C
 ssl_serialize_session_load_buf_size:0:"":MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3
 
 Test configuration of groups for DHE through mbedtls_ssl_conf_curves()
@@ -3286,17 +3294,33 @@
 TLS 1.3 read early data, discard after HRR
 tls13_read_early_data:TEST_EARLY_DATA_HRR
 
-TLS 1.3 cli, early data status, early data accepted
-tls13_cli_early_data_status:TEST_EARLY_DATA_ACCEPTED
+TLS 1.3 cli, early data, same ALPN
+depends_on:MBEDTLS_SSL_ALPN
+tls13_read_early_data:TEST_EARLY_DATA_SAME_ALPN
 
-TLS 1.3 cli, early data status, no early data indication
-tls13_cli_early_data_status:TEST_EARLY_DATA_NO_INDICATION_SENT
+TLS 1.3 cli, early data, different ALPN
+depends_on:MBEDTLS_SSL_ALPN
+tls13_read_early_data:TEST_EARLY_DATA_DIFF_ALPN
 
-TLS 1.3 cli, early data status, server rejects early data
-tls13_cli_early_data_status:TEST_EARLY_DATA_SERVER_REJECTS
+TLS 1.3 cli, early data, no initial ALPN
+depends_on:MBEDTLS_SSL_ALPN
+tls13_read_early_data:TEST_EARLY_DATA_NO_INITIAL_ALPN
 
-TLS 1.3 cli, early data status, hello retry request
-tls13_cli_early_data_status:TEST_EARLY_DATA_HRR
+TLS 1.3 cli, early data, no later ALPN
+depends_on:MBEDTLS_SSL_ALPN
+tls13_read_early_data:TEST_EARLY_DATA_NO_LATER_ALPN
+
+TLS 1.3 cli, early data state, early data accepted
+tls13_cli_early_data_state:TEST_EARLY_DATA_ACCEPTED
+
+TLS 1.3 cli, early data state, no early data indication
+tls13_cli_early_data_state:TEST_EARLY_DATA_NO_INDICATION_SENT
+
+TLS 1.3 cli, early data state, server rejects early data
+tls13_cli_early_data_state:TEST_EARLY_DATA_SERVER_REJECTS
+
+TLS 1.3 cli, early data state, hello retry request
+tls13_cli_early_data_state:TEST_EARLY_DATA_HRR
 
 TLS 1.3 write early data, early data accepted
 tls13_write_early_data:TEST_EARLY_DATA_ACCEPTED
@@ -3309,3 +3333,51 @@
 
 TLS 1.3 write early data, hello retry request
 tls13_write_early_data:TEST_EARLY_DATA_HRR
+
+TLS 1.3 cli, maximum early data size, default size
+tls13_cli_max_early_data_size:-1
+
+TLS 1.3 cli, maximum early data size, zero
+tls13_cli_max_early_data_size:0
+
+TLS 1.3 cli, maximum early data size, very small but not 0
+tls13_cli_max_early_data_size:3
+
+TLS 1.3 cli, maximum early data size, 93
+tls13_cli_max_early_data_size:93
+
+TLS 1.3 srv, max early data size, dflt, wsz=96
+tls13_srv_max_early_data_size:TEST_EARLY_DATA_ACCEPTED:-1:96
+
+TLS 1.3 srv, max early data size, dflt, wsz=128
+tls13_srv_max_early_data_size:TEST_EARLY_DATA_ACCEPTED:-1:128
+
+TLS 1.3 srv, max early data size, 3, wsz=2
+tls13_srv_max_early_data_size:TEST_EARLY_DATA_ACCEPTED:3:2
+
+TLS 1.3 srv, max early data size, 3, wsz=3
+tls13_srv_max_early_data_size:TEST_EARLY_DATA_ACCEPTED:3:3
+
+TLS 1.3 srv, max early data size, 98, wsz=23
+tls13_srv_max_early_data_size:TEST_EARLY_DATA_ACCEPTED:98:23
+
+TLS 1.3 srv, max early data size, 98, wsz=49
+tls13_srv_max_early_data_size:TEST_EARLY_DATA_ACCEPTED:98:49
+
+TLS 1.3 srv, max early data size, server rejects, dflt, wsz=128
+tls13_srv_max_early_data_size:TEST_EARLY_DATA_SERVER_REJECTS:-1:128
+
+TLS 1.3 srv, max early data size, server rejects, 3, wsz=3
+tls13_srv_max_early_data_size:TEST_EARLY_DATA_SERVER_REJECTS:3:3
+
+TLS 1.3 srv, max early data size, server rejects, 98, wsz=49
+tls13_srv_max_early_data_size:TEST_EARLY_DATA_SERVER_REJECTS:98:49
+
+TLS 1.3 srv, max early data size, HRR, dflt, wsz=128
+tls13_srv_max_early_data_size:TEST_EARLY_DATA_HRR:-1:128
+
+TLS 1.3 srv, max early data size, HRR, 3, wsz=3
+tls13_srv_max_early_data_size:TEST_EARLY_DATA_HRR:3:3
+
+TLS 1.3 srv, max early data size, HRR, 98, wsz=49
+tls13_srv_max_early_data_size:TEST_EARLY_DATA_HRR:97:0
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index d327828..840af7d 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -17,6 +17,51 @@
 #define TEST_EARLY_DATA_NO_INDICATION_SENT 1
 #define TEST_EARLY_DATA_SERVER_REJECTS 2
 #define TEST_EARLY_DATA_HRR 3
+#define TEST_EARLY_DATA_SAME_ALPN 4
+#define TEST_EARLY_DATA_DIFF_ALPN 5
+#define TEST_EARLY_DATA_NO_INITIAL_ALPN 6
+#define TEST_EARLY_DATA_NO_LATER_ALPN 7
+
+#if (!defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \
+    defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) && \
+    defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_DEBUG_C) && \
+    defined(MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE) && \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) && \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED) && \
+    defined(MBEDTLS_MD_CAN_SHA256) && \
+    defined(MBEDTLS_ECP_HAVE_SECP256R1) && defined(MBEDTLS_ECP_HAVE_SECP384R1) && \
+    defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+/*
+ * Test function to write early data for negative tests where
+ * mbedtls_ssl_write_early_data() cannot be used.
+ */
+static int write_early_data(mbedtls_ssl_context *ssl,
+                            unsigned char *buf, size_t len)
+{
+    int ret = mbedtls_ssl_get_max_out_record_payload(ssl);
+
+    TEST_ASSERT(ret > 0);
+    TEST_LE_U(len, (size_t) ret);
+
+    ret = mbedtls_ssl_flush_output(ssl);
+    TEST_EQUAL(ret, 0);
+    TEST_EQUAL(ssl->out_left, 0);
+
+    ssl->out_msglen = len;
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA;
+    if (len > 0) {
+        memcpy(ssl->out_msg, buf, len);
+    }
+
+    ret = mbedtls_ssl_write_record(ssl, 1);
+    TEST_EQUAL(ret, 0);
+
+    ret = len;
+
+exit:
+    return ret;
+}
+#endif
 
 /* END_HEADER */
 
@@ -1131,6 +1176,8 @@
                                             MBEDTLS_SSL_IS_CLIENT,
                                             MBEDTLS_SSL_TRANSPORT_DATAGRAM,
                                             MBEDTLS_SSL_PRESET_DEFAULT) == 0);
+    mbedtls_ssl_conf_rng(&conf, mbedtls_test_random, NULL);
+
     TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
 
     /* Read previous record numbers */
@@ -2046,7 +2093,7 @@
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
-        TEST_ASSERT(original.ciphersuite == restored.ciphersuite);
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
         TEST_ASSERT(original.ticket_age_add == restored.ticket_age_add);
         TEST_ASSERT(original.ticket_flags == restored.ticket_flags);
         TEST_ASSERT(original.resumption_key_len == restored.resumption_key_len);
@@ -2057,14 +2104,24 @@
                                restored.resumption_key,
                                original.resumption_key_len) == 0);
         }
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-#if defined(MBEDTLS_SSL_EARLY_DATA)
-        TEST_ASSERT(
-            original.max_early_data_size == restored.max_early_data_size);
+#if defined(MBEDTLS_SSL_SRV_C)
+        if (endpoint_type == MBEDTLS_SSL_IS_SERVER) {
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+            TEST_ASSERT(original.ticket_alpn != NULL);
+            TEST_ASSERT(restored.ticket_alpn != NULL);
+            TEST_MEMORY_COMPARE(original.ticket_alpn, strlen(original.ticket_alpn),
+                                restored.ticket_alpn, strlen(restored.ticket_alpn));
 #endif
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+        }
+#endif /* MBEDTLS_SSL_SRV_C */
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_SSL_CLI_C)
         if (endpoint_type == MBEDTLS_SSL_IS_CLIENT) {
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 #if defined(MBEDTLS_HAVE_TIME)
             TEST_ASSERT(original.ticket_reception_time == restored.ticket_reception_time);
 #endif
@@ -2077,12 +2134,23 @@
                                    restored.ticket,
                                    original.ticket_len) == 0);
             }
-
-        }
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+            TEST_ASSERT(original.hostname != NULL);
+            TEST_ASSERT(restored.hostname != NULL);
+            TEST_MEMORY_COMPARE(original.hostname, strlen(original.hostname),
+                                restored.hostname, strlen(restored.hostname));
 #endif
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+        }
+#endif /* MBEDTLS_SSL_CLI_C */
     }
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    TEST_ASSERT(
+        original.max_early_data_size == restored.max_early_data_size);
+#endif
+
 #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
     TEST_ASSERT(original.record_size_limit == restored.record_size_limit);
 #endif
@@ -2353,7 +2421,7 @@
      * corrupt them bit-by-bit. */
     for (cur_byte = 0; cur_byte < sizeof(should_corrupt_byte); cur_byte++) {
         int cur_bit;
-        unsigned char * const byte = &serialized_session[cur_byte];
+        unsigned char *const byte = &serialized_session[cur_byte];
 
         if (should_corrupt_byte[cur_byte] == 0) {
             continue;
@@ -2379,6 +2447,54 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE */
+void ssl_session_id_accessors_check(int tls_version)
+{
+    mbedtls_ssl_session session;
+    int ciphersuite_id;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+
+    mbedtls_ssl_session_init(&session);
+    USE_PSA_INIT();
+
+    switch (tls_version) {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        case MBEDTLS_SSL_VERSION_TLS1_3:
+            ciphersuite_id = MBEDTLS_TLS1_3_AES_128_GCM_SHA256;
+            TEST_ASSERT(mbedtls_test_ssl_tls13_populate_session(
+                            &session, 0, MBEDTLS_SSL_IS_SERVER) == 0);
+            break;
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        case MBEDTLS_SSL_VERSION_TLS1_2:
+            ciphersuite_id = MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256;
+            TEST_ASSERT(mbedtls_test_ssl_tls12_populate_session(
+                            &session, 0, MBEDTLS_SSL_IS_SERVER, NULL) == 0);
+
+            break;
+#endif
+        default:
+            /* should never happen */
+            TEST_ASSERT(0);
+            break;
+    }
+    TEST_ASSERT(*mbedtls_ssl_session_get_id(&session) == session.id);
+    TEST_ASSERT(mbedtls_ssl_session_get_id_len(&session) == session.id_len);
+    /* mbedtls_test_ssl_tls1x_populate_session sets a mock suite-id of 0xabcd */
+    TEST_ASSERT(mbedtls_ssl_session_get_ciphersuite_id(&session) == 0xabcd);
+
+    /* Test setting a reference id for tls1.3 and tls1.2 */
+    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
+    if (ciphersuite_info != NULL) {
+        TEST_ASSERT(mbedtls_ssl_ciphersuite_get_id(ciphersuite_info) == ciphersuite_id);
+    }
+
+exit:
+    mbedtls_ssl_session_free(&session);
+    USE_PSA_DONE();
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:!MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA256 */
 void mbedtls_endpoint_sanity(int endpoint_type)
 {
@@ -2879,6 +2995,7 @@
     mbedtls_ssl_conf_transport(&conf, transport);
     mbedtls_ssl_conf_min_tls_version(&conf, min_tls_version);
     mbedtls_ssl_conf_max_tls_version(&conf, max_tls_version);
+    mbedtls_ssl_conf_rng(&conf, mbedtls_test_random, NULL);
 
     TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == expected_ssl_setup_result);
     TEST_EQUAL(mbedtls_ssl_conf_get_endpoint(
@@ -2920,6 +3037,8 @@
     mbedtls_ssl_init(&ssl);
     MD_OR_USE_PSA_INIT();
 
+    mbedtls_ssl_conf_rng(&conf, mbedtls_test_random, NULL);
+
     TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
 
     TEST_ASSERT(ssl.handshake != NULL && ssl.handshake->group_list != NULL);
@@ -2951,6 +3070,7 @@
     mbedtls_ssl_config conf;
     mbedtls_ssl_config_init(&conf);
 
+    mbedtls_ssl_conf_rng(&conf, mbedtls_test_random, NULL);
     mbedtls_ssl_conf_max_tls_version(&conf, MBEDTLS_SSL_VERSION_TLS1_2);
     mbedtls_ssl_conf_min_tls_version(&conf, MBEDTLS_SSL_VERSION_TLS1_2);
 
@@ -3059,6 +3179,7 @@
                                            MBEDTLS_SSL_TRANSPORT_DATAGRAM,
                                            MBEDTLS_SSL_PRESET_DEFAULT),
                0);
+    mbedtls_ssl_conf_rng(&conf, mbedtls_test_random, NULL);
 
     TEST_EQUAL(mbedtls_ssl_setup(&ssl, &conf), 0);
     TEST_EQUAL(mbedtls_ssl_check_dtls_clihlo_cookie(&ssl, ssl.cli_id,
@@ -3113,6 +3234,7 @@
                                             MBEDTLS_SSL_TRANSPORT_STREAM,
                                             MBEDTLS_SSL_PRESET_DEFAULT)
                 == 0);
+    mbedtls_ssl_conf_rng(&conf, mbedtls_test_random, NULL);
 
     TEST_ASSERT(mbedtls_ssl_setup(&ssl, &conf) == 0);
 
@@ -3371,6 +3493,7 @@
                                            MBEDTLS_SSL_IS_CLIENT,
                                            MBEDTLS_SSL_TRANSPORT_STREAM,
                                            MBEDTLS_SSL_PRESET_DEFAULT), 0);
+    mbedtls_ssl_conf_rng(&conf, mbedtls_test_random, NULL);
 
     TEST_EQUAL(mbedtls_ssl_setup(&ssl, &conf), 0);
 
@@ -3622,6 +3745,19 @@
     server_options.group_list = group_list;
     server_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED;
 
+#if defined(MBEDTLS_SSL_ALPN)
+    switch (scenario) {
+        case TEST_EARLY_DATA_SAME_ALPN:
+        case TEST_EARLY_DATA_DIFF_ALPN:
+        case TEST_EARLY_DATA_NO_LATER_ALPN:
+            client_options.alpn_list[0] = "ALPNExample";
+            client_options.alpn_list[1] = NULL;
+            server_options.alpn_list[0] = "ALPNExample";
+            server_options.alpn_list[1] = NULL;
+            break;
+    }
+#endif
+
     ret = mbedtls_test_get_tls13_ticket(&client_options, &server_options,
                                         &saved_session);
     TEST_EQUAL(ret, 0);
@@ -3650,6 +3786,33 @@
                 "EarlyData: Ignore application message before 2nd ClientHello";
             server_options.group_list = group_list + 1;
             break;
+#if defined(MBEDTLS_SSL_ALPN)
+        case TEST_EARLY_DATA_SAME_ALPN:
+            client_options.alpn_list[0] = "ALPNExample";
+            client_options.alpn_list[1] = NULL;
+            server_options.alpn_list[0] = "ALPNExample";
+            server_options.alpn_list[1] = NULL;
+            break;
+        case TEST_EARLY_DATA_DIFF_ALPN:
+        case TEST_EARLY_DATA_NO_INITIAL_ALPN:
+            client_options.alpn_list[0] = "ALPNExample2";
+            client_options.alpn_list[1] = NULL;
+            server_options.alpn_list[0] = "ALPNExample2";
+            server_options.alpn_list[1] = NULL;
+            mbedtls_debug_set_threshold(3);
+            server_pattern.pattern =
+                "EarlyData: rejected, the selected ALPN is different "
+                "from the one associated with the pre-shared key.";
+            break;
+        case TEST_EARLY_DATA_NO_LATER_ALPN:
+            client_options.alpn_list[0] = NULL;
+            server_options.alpn_list[0] = NULL;
+            mbedtls_debug_set_threshold(3);
+            server_pattern.pattern =
+                "EarlyData: rejected, the selected ALPN is different "
+                "from the one associated with the pre-shared key.";
+            break;
+#endif
 
         default:
             TEST_FAIL("Unknown scenario.");
@@ -3688,8 +3851,8 @@
                                        (unsigned char *) early_data,
                                        early_data_len);
 
-    if (client_ep.ssl.early_data_status !=
-        MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) {
+    if (client_ep.ssl.early_data_state !=
+        MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) {
         TEST_EQUAL(ret, early_data_len);
     } else {
         TEST_EQUAL(ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
@@ -3701,6 +3864,9 @@
 
     switch (scenario) {
         case TEST_EARLY_DATA_ACCEPTED:
+#if defined(MBEDTLS_SSL_ALPN)
+        case TEST_EARLY_DATA_SAME_ALPN:
+#endif
             TEST_EQUAL(ret, MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA);
             TEST_EQUAL(server_ep.ssl.handshake->early_data_accepted, 1);
             TEST_EQUAL(mbedtls_ssl_read_early_data(&(server_ep.ssl),
@@ -3715,6 +3881,11 @@
 
         case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
         case TEST_EARLY_DATA_HRR:
+#if defined(MBEDTLS_SSL_ALPN)
+        case TEST_EARLY_DATA_DIFF_ALPN:
+        case TEST_EARLY_DATA_NO_INITIAL_ALPN:
+        case TEST_EARLY_DATA_NO_LATER_ALPN:
+#endif
             TEST_EQUAL(ret, 0);
             TEST_EQUAL(server_ep.ssl.handshake->early_data_accepted, 0);
             TEST_EQUAL(server_pattern.counter, 1);
@@ -3740,7 +3911,7 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:MBEDTLS_MD_CAN_SHA256:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_SSL_SESSION_TICKETS */
-void tls13_cli_early_data_status(int scenario)
+void tls13_cli_early_data_state(int scenario)
 {
     int ret = -1;
     mbedtls_test_ssl_endpoint client_ep, server_ep;
@@ -3752,6 +3923,7 @@
         MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1,
         MBEDTLS_SSL_IANA_TLS_GROUP_NONE
     };
+    uint8_t client_random[MBEDTLS_CLIENT_HELLO_RANDOM_LEN];
 
     mbedtls_platform_zeroize(&client_ep, sizeof(client_ep));
     mbedtls_platform_zeroize(&server_ep, sizeof(server_ep));
@@ -3853,17 +4025,17 @@
                     case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */
                     case TEST_EARLY_DATA_NO_INDICATION_SENT: /* Intentional fallthrough */
                     case TEST_EARLY_DATA_SERVER_REJECTS:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_IDLE);
                         break;
 
                     case TEST_EARLY_DATA_HRR:
                         if (!client_ep.ssl.handshake->hello_retry_request_flag) {
-                            TEST_EQUAL(client_ep.ssl.early_data_status,
-                                       MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN);
+                            TEST_EQUAL(client_ep.ssl.early_data_state,
+                                       MBEDTLS_SSL_EARLY_DATA_STATE_IDLE);
                         } else {
-                            TEST_EQUAL(client_ep.ssl.early_data_status,
-                                       MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
+                            TEST_EQUAL(client_ep.ssl.early_data_state,
+                                       MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED);
                         }
                         break;
 
@@ -3876,22 +4048,29 @@
                 switch (scenario) {
                     case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */
                     case TEST_EARLY_DATA_SERVER_REJECTS:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE);
                         break;
 
                     case TEST_EARLY_DATA_NO_INDICATION_SENT:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT);
                         break;
 
                     case TEST_EARLY_DATA_HRR:
                         if (!client_ep.ssl.handshake->hello_retry_request_flag) {
-                            TEST_EQUAL(client_ep.ssl.early_data_status,
-                                       MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE);
+                            TEST_EQUAL(client_ep.ssl.early_data_state,
+                                       MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE);
+                            memcpy(client_random,
+                                   client_ep.ssl.handshake->randbytes,
+                                   MBEDTLS_CLIENT_HELLO_RANDOM_LEN);
                         } else {
-                            TEST_EQUAL(client_ep.ssl.early_data_status,
-                                       MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
+                            TEST_EQUAL(client_ep.ssl.early_data_state,
+                                       MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED);
+                            TEST_MEMORY_COMPARE(client_random,
+                                                MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
+                                                client_ep.ssl.handshake->randbytes,
+                                                MBEDTLS_CLIENT_HELLO_RANDOM_LEN);
                         }
                         break;
 
@@ -3904,18 +4083,18 @@
                 switch (scenario) {
                     case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */
                     case TEST_EARLY_DATA_SERVER_REJECTS:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE);
                         break;
 
                     case TEST_EARLY_DATA_NO_INDICATION_SENT:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT);
                         break;
 
                     case TEST_EARLY_DATA_HRR:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED);
                         break;
 
                     default:
@@ -3926,19 +4105,19 @@
             case MBEDTLS_SSL_SERVER_FINISHED:
                 switch (scenario) {
                     case TEST_EARLY_DATA_ACCEPTED:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED);
                         break;
 
                     case TEST_EARLY_DATA_NO_INDICATION_SENT:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT);
                         break;
 
                     case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
                     case TEST_EARLY_DATA_HRR:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED);
                         break;
 
                     default:
@@ -3948,26 +4127,26 @@
 
             case MBEDTLS_SSL_END_OF_EARLY_DATA:
                 TEST_EQUAL(scenario, TEST_EARLY_DATA_ACCEPTED);
-                TEST_EQUAL(client_ep.ssl.early_data_status,
-                           MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED);
+                TEST_EQUAL(client_ep.ssl.early_data_state,
+                           MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED);
                 break;
 
             case MBEDTLS_SSL_CLIENT_CERTIFICATE:
                 switch (scenario) {
                     case TEST_EARLY_DATA_ACCEPTED:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED);
                         break;
 
                     case TEST_EARLY_DATA_NO_INDICATION_SENT:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT);
                         break;
 
                     case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
                     case TEST_EARLY_DATA_HRR:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED);
                         break;
 
                     default:
@@ -3978,19 +4157,19 @@
             case MBEDTLS_SSL_CLIENT_FINISHED:
                 switch (scenario) {
                     case TEST_EARLY_DATA_ACCEPTED:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED);
                         break;
 
                     case TEST_EARLY_DATA_NO_INDICATION_SENT:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT);
                         break;
 
                     case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
                     case TEST_EARLY_DATA_HRR:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED);
                         break;
 
                     default:
@@ -4004,8 +4183,8 @@
                     case TEST_EARLY_DATA_ACCEPTED: /* Intentional fallthrough */
                     case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
                     case TEST_EARLY_DATA_HRR:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_SENT);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT);
                         break;
 
                     default:
@@ -4015,21 +4194,21 @@
 
             case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO:
                 TEST_ASSERT(scenario == TEST_EARLY_DATA_HRR);
-                TEST_EQUAL(client_ep.ssl.early_data_status,
-                           MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
+                TEST_EQUAL(client_ep.ssl.early_data_state,
+                           MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED);
                 break;
 
             case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED:
                 switch (scenario) {
                     case TEST_EARLY_DATA_NO_INDICATION_SENT:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT);
                         break;
 
                     case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
                     case TEST_EARLY_DATA_HRR:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED);
                         break;
 
                     default:
@@ -4043,19 +4222,19 @@
             case MBEDTLS_SSL_HANDSHAKE_OVER:
                 switch (scenario) {
                     case TEST_EARLY_DATA_ACCEPTED:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED);
                         break;
 
                     case TEST_EARLY_DATA_NO_INDICATION_SENT:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT);
                         break;
 
                     case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
                     case TEST_EARLY_DATA_HRR:
-                        TEST_EQUAL(client_ep.ssl.early_data_status,
-                                   MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED);
+                        TEST_EQUAL(client_ep.ssl.early_data_state,
+                                   MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED);
                         break;
 
                     default:
@@ -4075,7 +4254,7 @@
             break;
 
         case TEST_EARLY_DATA_NO_INDICATION_SENT:
-            TEST_EQUAL(ret, MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT);
+            TEST_EQUAL(ret, MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED);
             break;
 
         case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
@@ -4159,6 +4338,10 @@
             break;
 
         case TEST_EARLY_DATA_HRR:
+            /*
+             * Remove server support for the group negotiated in
+             * mbedtls_test_get_tls13_ticket() forcing a HelloRetryRequest.
+             */
             server_options.group_list = group_list + 1;
             break;
 
@@ -4448,3 +4631,407 @@
     PSA_DONE();
 }
 /* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_DEBUG_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:MBEDTLS_MD_CAN_SHA256:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_SSL_SESSION_TICKETS */
+void tls13_cli_max_early_data_size(int max_early_data_size_arg)
+{
+    int ret = -1;
+    mbedtls_test_ssl_endpoint client_ep, server_ep;
+    mbedtls_test_handshake_test_options client_options;
+    mbedtls_test_handshake_test_options server_options;
+    mbedtls_ssl_session saved_session;
+    unsigned char *buf = NULL;
+    uint32_t buf_size = 64;
+    uint32_t max_early_data_size;
+    uint32_t written_early_data_size = 0;
+    uint32_t read_early_data_size = 0;
+
+    mbedtls_platform_zeroize(&client_ep, sizeof(client_ep));
+    mbedtls_platform_zeroize(&server_ep, sizeof(server_ep));
+    mbedtls_test_init_handshake_options(&client_options);
+    mbedtls_test_init_handshake_options(&server_options);
+    mbedtls_ssl_session_init(&saved_session);
+
+    PSA_INIT();
+    TEST_CALLOC(buf, buf_size);
+
+    /*
+     * Run first handshake to get a ticket from the server.
+     */
+
+    client_options.pk_alg = MBEDTLS_PK_ECDSA;
+    client_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED;
+    server_options.pk_alg = MBEDTLS_PK_ECDSA;
+    server_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED;
+    server_options.max_early_data_size = max_early_data_size_arg;
+
+    ret = mbedtls_test_get_tls13_ticket(&client_options, &server_options,
+                                        &saved_session);
+    TEST_EQUAL(ret, 0);
+
+    /*
+     * Prepare for handshake with the ticket.
+     */
+    ret = mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT,
+                                         &client_options, NULL, NULL, NULL);
+    TEST_EQUAL(ret, 0);
+
+    ret = mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER,
+                                         &server_options, NULL, NULL, NULL);
+    TEST_EQUAL(ret, 0);
+
+    mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf,
+                                        mbedtls_test_ticket_write,
+                                        mbedtls_test_ticket_parse,
+                                        NULL);
+
+    max_early_data_size = saved_session.max_early_data_size;
+    /*
+     * (max_early_data_size + 1024) for the size of the socket buffers for the
+     * server one to be able to contain the maximum number of early data bytes
+     * plus the first flight of client messages. Needed because we cannot
+     * initiate the handshake on server side before doing all the calls to
+     * mbedtls_ssl_write_early_data() we want to test. See below for more
+     * information.
+     */
+    ret = mbedtls_test_mock_socket_connect(&(client_ep.socket),
+                                           &(server_ep.socket),
+                                           max_early_data_size + 1024);
+    TEST_EQUAL(ret, 0);
+
+    /* If our server is configured with max_early_data_size equal to zero, it
+     * does not set the MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA flag for
+     * the tickets it creates. To be able to test early data with a ticket
+     * allowing early data in its flags but with max_early_data_size equal to
+     * zero (case supported by our client) tweak the ticket flags here.
+     */
+    if (max_early_data_size == 0) {
+        saved_session.ticket_flags |= MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA;
+    }
+
+    ret = mbedtls_ssl_set_session(&(client_ep.ssl), &saved_session);
+    TEST_EQUAL(ret, 0);
+
+    while (written_early_data_size < max_early_data_size) {
+        uint32_t remaining = max_early_data_size - written_early_data_size;
+
+        for (size_t i = 0; i < buf_size; i++) {
+            buf[i] = (unsigned char) (written_early_data_size + i);
+        }
+
+        ret = mbedtls_ssl_write_early_data(&(client_ep.ssl),
+                                           buf,
+                                           buf_size);
+
+        if (buf_size <= remaining) {
+            TEST_EQUAL(ret, buf_size);
+        } else {
+            TEST_EQUAL(ret, remaining);
+        }
+        written_early_data_size += buf_size;
+    }
+    TEST_EQUAL(client_ep.ssl.total_early_data_size, max_early_data_size);
+
+    ret = mbedtls_ssl_write_early_data(&(client_ep.ssl), buf, 1);
+    TEST_EQUAL(ret, MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA);
+    TEST_EQUAL(client_ep.ssl.total_early_data_size, max_early_data_size);
+    TEST_EQUAL(client_ep.ssl.early_data_state,
+               MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE);
+
+    /*
+     * Now, check data on server side. It is not done in the previous loop as
+     * in the first call to mbedtls_ssl_handshake(), the server ends up sending
+     * its Finished message and then in the following call to
+     * mbedtls_ssl_write_early_data() we go past the early data writing window
+     * and we cannot test multiple calls to the API is this writing window.
+     */
+    while (read_early_data_size < max_early_data_size) {
+        ret = mbedtls_ssl_handshake(&(server_ep.ssl));
+        TEST_EQUAL(ret, MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA);
+
+        ret = mbedtls_ssl_read_early_data(&(server_ep.ssl),
+                                          buf,
+                                          buf_size);
+        TEST_ASSERT(ret > 0);
+
+        for (size_t i = 0; i < (size_t) ret; i++) {
+            TEST_EQUAL(buf[i], (unsigned char) (read_early_data_size + i));
+        }
+
+        read_early_data_size += ret;
+    }
+    TEST_EQUAL(read_early_data_size, max_early_data_size);
+
+    ret = mbedtls_ssl_handshake(&(server_ep.ssl));
+    TEST_EQUAL(ret, MBEDTLS_ERR_SSL_WANT_READ);
+
+    TEST_ASSERT(mbedtls_test_move_handshake_to_state(
+                    &(client_ep.ssl), &(server_ep.ssl), MBEDTLS_SSL_HANDSHAKE_OVER)
+                ==  0);
+
+exit:
+    mbedtls_test_ssl_endpoint_free(&client_ep, NULL);
+    mbedtls_test_ssl_endpoint_free(&server_ep, NULL);
+    mbedtls_test_free_handshake_options(&client_options);
+    mbedtls_test_free_handshake_options(&server_options);
+    mbedtls_ssl_session_free(&saved_session);
+    mbedtls_free(buf);
+    PSA_DONE();
+}
+/* END_CASE */
+
+/*
+ * The !MBEDTLS_SSL_PROTO_TLS1_2 dependency of tls13_early_data() below is
+ * a temporary workaround to not run the test in Windows-2013 where there is
+ * an issue with mbedtls_vsnprintf().
+ */
+/* BEGIN_CASE depends_on:!MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_DEBUG_C:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED:MBEDTLS_MD_CAN_SHA256:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_PK_CAN_ECDSA_VERIFY:MBEDTLS_SSL_SESSION_TICKETS */
+void tls13_srv_max_early_data_size(int scenario, int max_early_data_size_arg, int write_size_arg)
+{
+    int ret = -1;
+    mbedtls_test_ssl_endpoint client_ep, server_ep;
+    mbedtls_test_handshake_test_options client_options;
+    mbedtls_test_handshake_test_options server_options;
+    mbedtls_ssl_session saved_session;
+    mbedtls_test_ssl_log_pattern server_pattern = { NULL, 0 };
+    uint16_t group_list[3] = {
+        MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1,
+        MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1,
+        MBEDTLS_SSL_IANA_TLS_GROUP_NONE
+    };
+    char pattern[128];
+    unsigned char *buf_write = NULL;
+    uint32_t write_size = (uint32_t) write_size_arg;
+    unsigned char *buf_read = NULL;
+    uint32_t read_size;
+    uint32_t expanded_early_data_chunk_size = 0;
+    uint32_t written_early_data_size = 0;
+    uint32_t max_early_data_size;
+
+    mbedtls_platform_zeroize(&client_ep, sizeof(client_ep));
+    mbedtls_platform_zeroize(&server_ep, sizeof(server_ep));
+    mbedtls_test_init_handshake_options(&client_options);
+    mbedtls_test_init_handshake_options(&server_options);
+    mbedtls_ssl_session_init(&saved_session);
+    PSA_INIT();
+
+    TEST_CALLOC(buf_write, write_size);
+
+    /*
+     * Allocate a smaller buffer for early data reading to exercise the reading
+     * of data in one record in multiple calls.
+     */
+    read_size = (write_size / 2) + 1;
+    TEST_CALLOC(buf_read, read_size);
+
+    /*
+     * Run first handshake to get a ticket from the server.
+     */
+
+    client_options.pk_alg = MBEDTLS_PK_ECDSA;
+    client_options.group_list = group_list;
+    client_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED;
+    server_options.pk_alg = MBEDTLS_PK_ECDSA;
+    server_options.group_list = group_list;
+    server_options.early_data = MBEDTLS_SSL_EARLY_DATA_ENABLED;
+    server_options.max_early_data_size = max_early_data_size_arg;
+
+    ret = mbedtls_test_get_tls13_ticket(&client_options, &server_options,
+                                        &saved_session);
+    TEST_EQUAL(ret, 0);
+
+    /*
+     * Prepare for handshake with the ticket.
+     */
+    server_options.srv_log_fun = mbedtls_test_ssl_log_analyzer;
+    server_options.srv_log_obj = &server_pattern;
+    server_pattern.pattern = pattern;
+
+    switch (scenario) {
+        case TEST_EARLY_DATA_ACCEPTED:
+            break;
+
+        case TEST_EARLY_DATA_SERVER_REJECTS:
+            server_options.early_data = MBEDTLS_SSL_EARLY_DATA_DISABLED;
+            ret = mbedtls_snprintf(pattern, sizeof(pattern),
+                                   "EarlyData: deprotect and discard app data records.");
+            TEST_ASSERT(ret < (int) sizeof(pattern));
+            mbedtls_debug_set_threshold(3);
+            break;
+
+        case TEST_EARLY_DATA_HRR:
+            /*
+             * Remove server support for the group negotiated in
+             * mbedtls_test_get_tls13_ticket() forcing an HelloRetryRequest.
+             */
+            server_options.group_list = group_list + 1;
+            ret = mbedtls_snprintf(
+                pattern, sizeof(pattern),
+                "EarlyData: Ignore application message before 2nd ClientHello");
+            TEST_ASSERT(ret < (int) sizeof(pattern));
+            mbedtls_debug_set_threshold(3);
+            break;
+
+        default:
+            TEST_FAIL("Unknown scenario.");
+    }
+
+    ret = mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT,
+                                         &client_options, NULL, NULL, NULL);
+    TEST_EQUAL(ret, 0);
+
+    ret = mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER,
+                                         &server_options, NULL, NULL, NULL);
+    TEST_EQUAL(ret, 0);
+
+    mbedtls_ssl_conf_session_tickets_cb(&server_ep.conf,
+                                        mbedtls_test_ticket_write,
+                                        mbedtls_test_ticket_parse,
+                                        NULL);
+
+    ret = mbedtls_test_mock_socket_connect(&(client_ep.socket),
+                                           &(server_ep.socket), 1024);
+    TEST_EQUAL(ret, 0);
+
+    max_early_data_size = saved_session.max_early_data_size;
+
+    ret = mbedtls_ssl_set_session(&(client_ep.ssl), &saved_session);
+    TEST_EQUAL(ret, 0);
+
+    /*
+     * Start an handshake based on the ticket up to the point where early data
+     * can be sent from client side. Then send in a loop as much early data as
+     * possible without going over the maximum permitted size for the ticket.
+     * Finally, do a last writting to go past that maximum permitted size and
+     * check that we detect it.
+     */
+    TEST_EQUAL(mbedtls_test_move_handshake_to_state(
+                   &(client_ep.ssl), &(server_ep.ssl),
+                   MBEDTLS_SSL_SERVER_HELLO), 0);
+
+    TEST_ASSERT(client_ep.ssl.early_data_state !=
+                MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT);
+
+    ret = mbedtls_ssl_handshake(&(server_ep.ssl));
+    TEST_EQUAL(ret, MBEDTLS_ERR_SSL_WANT_READ);
+
+    /*
+     * Write and if possible read as much as possible chunks of write_size
+     * bytes data without getting over the max_early_data_size limit.
+     */
+    do {
+        uint32_t read_early_data_size = 0;
+
+        /*
+         * The contents of the early data are not very important, write a
+         * pattern that varies byte-by-byte and is different for every chunk of
+         * early data.
+         */
+        if ((written_early_data_size + write_size) > max_early_data_size) {
+            break;
+        }
+
+        /*
+         * If the server rejected early data, base the determination of when
+         * to stop the loop on the expanded size (padding and encryption
+         * expansion) of early data on server side and the number of early data
+         * received so far by the server (multiple of the expanded size).
+         */
+        if ((expanded_early_data_chunk_size != 0) &&
+            ((server_ep.ssl.total_early_data_size +
+              expanded_early_data_chunk_size) > max_early_data_size)) {
+            break;
+        }
+
+        for (size_t i = 0; i < write_size; i++) {
+            buf_write[i] = (unsigned char) (written_early_data_size + i);
+        }
+
+        ret = write_early_data(&(client_ep.ssl), buf_write, write_size);
+        TEST_EQUAL(ret, write_size);
+        written_early_data_size += write_size;
+
+        switch (scenario) {
+            case TEST_EARLY_DATA_ACCEPTED:
+                while (read_early_data_size < write_size) {
+                    ret = mbedtls_ssl_handshake(&(server_ep.ssl));
+                    TEST_EQUAL(ret, MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA);
+
+                    ret = mbedtls_ssl_read_early_data(&(server_ep.ssl),
+                                                      buf_read, read_size);
+                    TEST_ASSERT(ret > 0);
+
+                    TEST_MEMORY_COMPARE(buf_read, ret,
+                                        buf_write + read_early_data_size, ret);
+                    read_early_data_size += ret;
+
+                    TEST_EQUAL(server_ep.ssl.total_early_data_size,
+                               written_early_data_size);
+                }
+                break;
+
+            case TEST_EARLY_DATA_SERVER_REJECTS: /* Intentional fallthrough */
+            case TEST_EARLY_DATA_HRR:
+                ret = mbedtls_ssl_handshake(&(server_ep.ssl));
+                /*
+                 * In this write loop we try to always stay below the
+                 * max_early_data_size limit but if max_early_data_size is very
+                 * small we may exceed the max_early_data_size limit on the
+                 * first write. In TEST_EARLY_DATA_SERVER_REJECTS/
+                 * TEST_EARLY_DATA_HRR scenario, this is for sure the case if
+                 * max_early_data_size is smaller than the smallest possible
+                 * inner content/protected record. Take into account this
+                 * possibility here but only for max_early_data_size values
+                 * that are close to write_size. Below, '1' is for the inner
+                 * type byte and '16' is to take into account some AEAD
+                 * expansion (tag, ...).
+                 */
+                if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) {
+                    if (scenario == TEST_EARLY_DATA_SERVER_REJECTS) {
+                        TEST_LE_U(max_early_data_size,
+                                  write_size + 1 +
+                                  MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY);
+                    } else {
+                        TEST_LE_U(max_early_data_size,
+                                  write_size + 1 + 16 +
+                                  MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY);
+                    }
+                    goto exit;
+                }
+
+                TEST_ASSERT(ret == MBEDTLS_ERR_SSL_WANT_READ);
+
+                TEST_EQUAL(server_pattern.counter, 1);
+                server_pattern.counter = 0;
+                if (expanded_early_data_chunk_size == 0) {
+                    expanded_early_data_chunk_size = server_ep.ssl.total_early_data_size;
+                }
+                break;
+        }
+        TEST_LE_U(server_ep.ssl.total_early_data_size, max_early_data_size);
+    } while (1);
+
+    mbedtls_debug_set_threshold(3);
+    ret = write_early_data(&(client_ep.ssl), buf_write, write_size);
+    TEST_EQUAL(ret, write_size);
+
+    ret = mbedtls_snprintf(pattern, sizeof(pattern),
+                           "EarlyData: Too much early data received");
+    TEST_ASSERT(ret < (int) sizeof(pattern));
+
+    ret = mbedtls_ssl_handshake(&(server_ep.ssl));
+    TEST_EQUAL(ret, MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);
+    TEST_EQUAL(server_pattern.counter, 1);
+
+exit:
+    mbedtls_test_ssl_endpoint_free(&client_ep, NULL);
+    mbedtls_test_ssl_endpoint_free(&server_ep, NULL);
+    mbedtls_test_free_handshake_options(&client_options);
+    mbedtls_test_free_handshake_options(&server_options);
+    mbedtls_ssl_session_free(&saved_session);
+    mbedtls_free(buf_write);
+    mbedtls_free(buf_read);
+    mbedtls_debug_set_threshold(0);
+    PSA_DONE();
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_test_helpers.data b/tests/suites/test_suite_test_helpers.data
new file mode 100644
index 0000000..1d221d7
--- /dev/null
+++ b/tests/suites/test_suite_test_helpers.data
@@ -0,0 +1,23 @@
+Memory poison+unpoison: offset=0 len=42
+memory_poison_unpoison:0:42
+
+Memory poison+unpoison: offset=0 len=1
+memory_poison_unpoison:0:1
+
+Memory poison+unpoison: offset=0 len=2
+memory_poison_unpoison:0:2
+
+Memory poison+unpoison: offset=1 len=1
+memory_poison_unpoison:1:1
+
+Memory poison+unpoison: offset=1 len=2
+memory_poison_unpoison:1:2
+
+Memory poison+unpoison: offset=7 len=1
+memory_poison_unpoison:7:1
+
+Memory poison+unpoison: offset=7 len=2
+memory_poison_unpoison:7:2
+
+Memory poison+unpoison: offset=0 len=0
+memory_poison_unpoison:0:0
diff --git a/tests/suites/test_suite_test_helpers.function b/tests/suites/test_suite_test_helpers.function
new file mode 100644
index 0000000..8c5d5ad
--- /dev/null
+++ b/tests/suites/test_suite_test_helpers.function
@@ -0,0 +1,40 @@
+/* BEGIN_HEADER */
+
+/* Test some parts of the test framework. */
+
+#include <test/helpers.h>
+#include <test/memory.h>
+
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES */
+
+/* END_DEPENDENCIES */
+
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_MEMORY_CAN_POISON */
+/* Test that poison+unpoison leaves the memory accessible. */
+/* We can't test that poisoning makes the memory inaccessible:
+ * there's no sane way to catch an Asan/Valgrind complaint.
+ * That negative testing is done in programs/test/metatest.c. */
+void memory_poison_unpoison(int align, int size)
+{
+    unsigned char *buf = NULL;
+    const size_t buffer_size = align + size;
+    TEST_CALLOC(buf, buffer_size);
+
+    for (size_t i = 0; i < buffer_size; i++) {
+        buf[i] = (unsigned char) (i & 0xff);
+    }
+
+    const unsigned char *start = buf == NULL ? NULL : buf + align;
+    mbedtls_test_memory_poison(start, (size_t) size);
+    mbedtls_test_memory_unpoison(start, (size_t) size);
+
+    for (size_t i = 0; i < buffer_size; i++) {
+        TEST_EQUAL(buf[i], (unsigned char) (i & 0xff));
+    }
+
+exit:
+    mbedtls_free(buf);
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data
index 6290331..0edee96 100644
--- a/tests/suites/test_suite_version.data
+++ b/tests/suites/test_suite_version.data
@@ -1,8 +1,8 @@
 Check compile time library version
-check_compiletime_version:"3.5.2"
+check_compiletime_version:"3.6.0"
 
 Check runtime library version
-check_runtime_version:"3.5.2"
+check_runtime_version:"3.6.0"
 
 Check for MBEDTLS_VERSION_C
 check_feature:"MBEDTLS_VERSION_C":0
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 754660c..500c676 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -239,71 +239,71 @@
 x509_parse_san:"data_files/server5-tricky-ip-san-malformed-len.crt.der":"":MBEDTLS_ERR_X509_BAD_INPUT_DATA
 
 X509 CRL information #1
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_expired.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-20 10\:24\:19\nnext update   \: 2011-02-20 11\:24\:19\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA1\n"
 
 X509 CRL Information MD5 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_MD5:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_MD5:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_md5.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with MD5\n"
 
 X509 CRL Information SHA1 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA1:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_sha1.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA1\n"
 
 X509 CRL Information SHA224 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA224:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA224:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_sha224.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA-224\n"
 
 X509 CRL Information SHA256 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_sha256.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA-256\n"
 
 X509 CRL Information SHA384 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA384:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_sha384.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA-384\n"
 
 X509 CRL Information SHA512 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C
 mbedtls_x509_crl_info:"data_files/parse_input/crl_sha512.pem":"CRL version   \: 1\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2011-02-12 14\:44\:07\nnext update   \: 2011-04-13 14\:44\:07\nRevoked certificates\:\nserial number\: 01 revocation date\: 2011-02-12 14\:44\:07\nserial number\: 03 revocation date\: 2011-02-12 14\:44\:07\nsigned using  \: RSA with SHA-512\n"
 
 X509 CRL information RSA-PSS, SHA1 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA1:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA1
 mbedtls_x509_crl_info:"data_files/parse_input/crl-rsa-pss-sha1.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2014-01-20 13\:46\:35\nnext update   \: 2024-01-18 13\:46\:35\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nserial number\: 16 revocation date\: 2014-01-20 13\:43\:05\nsigned using  \: RSASSA-PSS (SHA1, MGF1-SHA1, 0xEA)\n"
 
 X509 CRL information RSA-PSS, SHA224 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA224:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA224
 mbedtls_x509_crl_info:"data_files/parse_input/crl-rsa-pss-sha224.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2014-01-20 13\:56\:06\nnext update   \: 2024-01-18 13\:56\:06\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nserial number\: 16 revocation date\: 2014-01-20 13\:43\:05\nsigned using  \: RSASSA-PSS (SHA224, MGF1-SHA224, 0xE2)\n"
 
 X509 CRL information RSA-PSS, SHA256 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA256:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA256
 mbedtls_x509_crl_info:"data_files/parse_input/crl-rsa-pss-sha256.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2014-01-20 13\:56\:16\nnext update   \: 2024-01-18 13\:56\:16\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nserial number\: 16 revocation date\: 2014-01-20 13\:43\:05\nsigned using  \: RSASSA-PSS (SHA256, MGF1-SHA256, 0xDE)\n"
 
 X509 CRL information RSA-PSS, SHA384 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA384:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA384
 mbedtls_x509_crl_info:"data_files/parse_input/crl-rsa-pss-sha384.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2014-01-20 13\:56\:28\nnext update   \: 2024-01-18 13\:56\:28\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nserial number\: 16 revocation date\: 2014-01-20 13\:43\:05\nsigned using  \: RSASSA-PSS (SHA384, MGF1-SHA384, 0xCE)\n"
 
 X509 CRL information RSA-PSS, SHA512 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA512:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA512
 mbedtls_x509_crl_info:"data_files/parse_input/crl-rsa-pss-sha512.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=PolarSSL Test CA\nthis update   \: 2014-01-20 13\:56\:38\nnext update   \: 2024-01-18 13\:56\:38\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nserial number\: 16 revocation date\: 2014-01-20 13\:43\:05\nsigned using  \: RSASSA-PSS (SHA512, MGF1-SHA512, 0xBE)\n"
 
 X509 CRL Information EC, SHA1 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA1:MBEDTLS_PK_CAN_ECDSA_SOME:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA1:MBEDTLS_PK_CAN_ECDSA_SOME
 mbedtls_x509_crl_info:"data_files/parse_input/crl-ec-sha1.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-09-24 16\:31\:08\nnext update   \: 2023-09-22 16\:31\:08\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nsigned using  \: ECDSA with SHA1\n"
 
 X509 CRL Information EC, SHA224 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA224:MBEDTLS_PK_CAN_ECDSA_SOME:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA224:MBEDTLS_PK_CAN_ECDSA_SOME
 mbedtls_x509_crl_info:"data_files/parse_input/crl-ec-sha224.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-09-24 16\:31\:08\nnext update   \: 2023-09-22 16\:31\:08\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nsigned using  \: ECDSA with SHA224\n"
 
 X509 CRL Information EC, SHA256 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_PK_CAN_ECDSA_SOME:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_PK_CAN_ECDSA_SOME
 mbedtls_x509_crl_info:"data_files/parse_input/crl-ec-sha256.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-09-24 16\:31\:08\nnext update   \: 2023-09-22 16\:31\:08\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nsigned using  \: ECDSA with SHA256\n"
 
 X509 CRL Information EC, SHA384 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA384:MBEDTLS_PK_CAN_ECDSA_SOME:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA384:MBEDTLS_PK_CAN_ECDSA_SOME
 mbedtls_x509_crl_info:"data_files/parse_input/crl-ec-sha384.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-09-24 16\:31\:08\nnext update   \: 2023-09-22 16\:31\:08\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nsigned using  \: ECDSA with SHA384\n"
 
 X509 CRL Information EC, SHA512 Digest
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA512:MBEDTLS_PK_CAN_ECDSA_SOME:!MBEDTLS_X509_REMOVE_INFO
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA512:MBEDTLS_PK_CAN_ECDSA_SOME
 mbedtls_x509_crl_info:"data_files/parse_input/crl-ec-sha512.pem":"CRL version   \: 2\nissuer name   \: C=NL, O=PolarSSL, CN=Polarssl Test EC CA\nthis update   \: 2013-09-24 16\:31\:08\nnext update   \: 2023-09-22 16\:31\:08\nRevoked certificates\:\nserial number\: 0A revocation date\: 2013-09-24 16\:28\:38\nsigned using  \: ECDSA with SHA512\n"
 
 X509 CRL Malformed Input (trailing spaces at end of file)
@@ -330,8 +330,8 @@
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA224:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
 mbedtls_x509_csr_info:"data_files/parse_input/server1.req.sha224":"CSR version   \: 1\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Server 1\nsigned using  \: RSA with SHA-224\nRSA key size  \: 2048 bits\n"
 
-X509 CSR Information RSA with SHA-256
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:MBEDTS_X509_INFO
+X509 CSR Information RSA with SHA256
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
 mbedtls_x509_csr_info:"data_files/parse_input/server1.req.sha256":"CSR version   \: 1\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Server 1\nsigned using  \: RSA with SHA-256\nRSA key size  \: 2048 bits\n"
 
 X509 CSR Information RSA with SHA384
@@ -342,8 +342,8 @@
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA512:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
 mbedtls_x509_csr_info:"data_files/parse_input/server1.req.sha512":"CSR version   \: 1\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Server 1\nsigned using  \: RSA with SHA-512\nRSA key size  \: 2048 bits\n"
 
-X509 CSR Information RSA with SHA-256, containing commas
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:MBEDTS_X509_INFO
+X509 CSR Information RSA with SHA256, containing commas
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
 mbedtls_x509_csr_info:"data_files/parse_input/server1.req.commas.sha256":"CSR version   \: 1\nsubject name  \: C=NL, O=PolarSSL\\, Commas, CN=PolarSSL Server 1\nsigned using  \: RSA with SHA-256\nRSA key size  \: 2048 bits\n"
 
 X509 CSR Information EC with SHA1
@@ -386,8 +386,8 @@
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_X509_RSASSA_PSS_SUPPORT:MBEDTLS_MD_CAN_SHA512:!MBEDTLS_X509_REMOVE_INFO
 mbedtls_x509_csr_info:"data_files/parse_input/server9.req.sha512":"CSR version   \: 1\nsubject name  \: C=NL, O=PolarSSL, CN=localhost\nsigned using  \: RSASSA-PSS (SHA512, MGF1-SHA512, 0x3E)\nRSA key size  \: 1024 bits\n\nkey usage         \: Digital Signature, Non Repudiation, Key Encipherment\n"
 
-X509 CSR Information RSA with SHA-256 - Microsoft header
-depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C
+X509 CSR Information RSA with SHA256 - Microsoft header
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_MD_CAN_SHA256:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
 mbedtls_x509_csr_info:"data_files/parse_input/server1-ms.req.sha256":"CSR version   \: 1\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Server 1\nsigned using  \: RSA with SHA-256\nRSA key size  \: 2048 bits\n"
 
 X509 CSR Information v3 extensions #1 (all)
diff --git a/visualc/VS2013/.gitignore b/visualc/VS2017/.gitignore
similarity index 100%
rename from visualc/VS2013/.gitignore
rename to visualc/VS2017/.gitignore