Merge pull request #8924 from Ryan-Everett-arm/threading-same-key-tests

Add testing for concurrently loading/using/destroying the same key
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/CMakeLists.txt b/CMakeLists.txt
index 179c3f6..e37ca2c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -283,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)
diff --git a/ChangeLog.d/8709.txt b/ChangeLog.d/8709.txt
new file mode 100644
index 0000000..e0bea44
--- /dev/null
+++ b/ChangeLog.d/8709.txt
@@ -0,0 +1,4 @@
+Features
+   * 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.
diff --git a/ChangeLog.d/add_ssl_session_accessors.txt b/ChangeLog.d/add_ssl_session_accessors.txt
new file mode 100644
index 0000000..516a3bf
--- /dev/null
+++ b/ChangeLog.d/add_ssl_session_accessors.txt
@@ -0,0 +1,6 @@
+Features
+   * 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
diff --git a/ChangeLog.d/fix-new-rn-on-hrr.txt b/ChangeLog.d/fix-new-rn-on-hrr.txt
new file mode 100644
index 0000000..1b4f5e6
--- /dev/null
+++ b/ChangeLog.d/fix-new-rn-on-hrr.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * In TLS 1.3 clients, fix an interoperability problem due to the client
+     generating a new random after a HelloRetryRequest. Fixes #8669.
diff --git a/Makefile b/Makefile
index 885948c..47a3895 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
diff --git a/README.md b/README.md
index 2505d8f..8bb0b60 100644
--- a/README.md
+++ b/README.md
@@ -54,6 +54,10 @@
 * Microsoft Visual Studio 2013 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.
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/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/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index 7cf4153..feb2054 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -3201,6 +3201,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
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index d83152c..fde302f 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -458,7 +458,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,7 +479,7 @@
                           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.
@@ -639,7 +639,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/ssl.h b/include/mbedtls/ssl.h
index 9a66663..57d7bc6 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    */
@@ -2721,6 +2696,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.)
  *
@@ -5340,8 +5352,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/library/CMakeLists.txt b/library/CMakeLists.txt
index 47ecf17..835604f 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
diff --git a/library/Makefile b/library/Makefile
index d11a98d..52d7944 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"
 
@@ -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/cmac.c b/library/cmac.c
index cd3bd3a..c4f0b54 100644
--- a/library/cmac.c
+++ b/library/cmac.c
@@ -224,6 +224,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 &&
@@ -291,6 +295,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..ec3741b 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,136 @@
         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 */
+    {
+        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
@@ -1017,7 +1156,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;
@@ -1183,7 +1322,10 @@
 
     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_algorithm_t psa_alg, sign_alg;
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+        psa_algorithm_t psa_enrollment_alg;
+#endif /* MBEDTLS_PSA_CRYPTO_C */
         psa_status_t status;
 
         status = psa_get_key_attributes(ctx->priv_id, &key_attr);
@@ -1191,16 +1333,22 @@
             return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
         }
         psa_alg = psa_get_key_algorithm(&key_attr);
+#if defined(MBEDTLS_PSA_CRYPTO_C)
         psa_enrollment_alg = psa_get_key_enrollment_algorithm(&key_attr);
+#endif /* MBEDTLS_PSA_CRYPTO_C */
         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)) {
+        }
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+        else if (PSA_ALG_IS_RSA_PSS(psa_enrollment_alg)) {
             sign_alg = psa_enrollment_alg;
-        } else {
+        }
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+        else {
             /* The opaque key has no RSA PSS algorithm associated. */
             return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
         }
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..256863a 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);
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/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/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/ssl_client.c b/library/ssl_client.c
index 8892acf..345e608 100644
--- a/library/ssl_client.c
+++ b/library/ssl_client.c
@@ -792,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 883b988..a8807f6 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -2153,6 +2153,57 @@
 
 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 */
@@ -2801,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 4949306..b07cd96 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -6097,21 +6097,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);
@@ -6133,8 +6133,8 @@
          * 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;
         }
 
@@ -6152,8 +6152,8 @@
         }
     }
 
-    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;
     }
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 1bfd180..ac8e0ea 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1096,7 +1096,7 @@
 
 #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;
@@ -3750,9 +3750,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) {
@@ -3771,6 +3778,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)
@@ -3813,13 +3829,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)
@@ -3894,16 +3923,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)
@@ -4060,6 +4114,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
@@ -4070,6 +4131,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) (                                                      \
@@ -4086,7 +4148,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,
@@ -4161,8 +4225,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;
@@ -4852,6 +4920,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));
 }
 
@@ -9798,4 +9871,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_tls13_client.c b/library/ssl_tls13_client.c
index 88d6c9e..7fcc394 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -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_server.c b/library/ssl_tls13_server.c
index 887c5c6..2c30da8 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -467,7 +467,14 @@
 
 #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;
 }
@@ -3137,6 +3144,15 @@
 
     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,
@@ -3266,20 +3282,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/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/test/metatest.c b/programs/test/metatest.c
index 5a45f71..5cd09bf 100644
--- a/programs/test/metatest.c
+++ b/programs/test/metatest.c
@@ -70,6 +70,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 */
@@ -285,6 +320,9 @@
  */
 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 },
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/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/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..a101ffd 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -125,7 +125,7 @@
 print_test_case() {
     for i in $3; do
         uniform_title $1 $2 $i
-        echo $TITLE
+        echo "compat;$TITLE"
     done
 }
 
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 21071bd..acfcf5c 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -1285,19 +1285,67 @@
     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 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_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_psa_crypto_rsa_no_genprime() {
     msg "build: default config minus MBEDTLS_GENPRIME"
     scripts/config.py unset MBEDTLS_GENPRIME
@@ -1554,6 +1602,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
@@ -2203,6 +2268,9 @@
     # 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
 
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/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/psa_crypto_stubs.c b/tests/src/psa_crypto_stubs.c
index f3ca850..81d7f4b 100644
--- a/tests/src/psa_crypto_stubs.c
+++ b/tests/src/psa_crypto_stubs.c
@@ -22,4 +22,54 @@
     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/test_helpers/ssl_helpers.c b/tests/src/test_helpers/ssl_helpers.c
index 56e03f1..963938f 100644
--- a/tests/src/test_helpers/ssl_helpers.c
+++ b/tests/src/test_helpers/ssl_helpers.c
@@ -1793,7 +1793,13 @@
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
     session->max_early_data_size = 0x87654321;
-#endif
+#if defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C)
+    int ret = mbedtls_ssl_session_set_ticket_alpn(session, "ALPNExample");
+    if (ret != 0) {
+        return -1;
+    }
+#endif /* MBEDTLS_SSL_ALPN && MBEDTLS_SSL_SRV_C */
+#endif /* MBEDTLS_SSL_EARLY_DATA */
 
 #if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
     if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index fd2fc0a..0e86368 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
 
@@ -13532,6 +13532,61 @@
             -s "key exchange mode: psk_ephemeral" \
             -s "found pre_shared_key extension"
 
+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: NewSessionTicket: Ticket lifetime max value (7d)" \
+            "$P_SRV debug_level=1 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 "HTTP/1.0 200 OK" \
+            -c "got new session ticket" \
+            -c "Reconnecting with saved session... ok" \
+            -s "Protocol is TLSv1.3" \
+            -S "Ticket lifetime (604800) 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: NewSessionTicket: Ticket lifetime too long (7d + 1s)" \
+            "$P_SRV debug_level=1 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 "HTTP/1.0 200 OK" \
+            -C "got new session ticket" \
+            -C "Reconnecting with saved session... ok" \
+            -S "Protocol is TLSv1.3" \
+            -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: NewSessionTicket: 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 "HTTP/1.0 200 OK" \
+            -c "Discard new session ticket" \
+            -C "got new session ticket" \
+            -c "Reconnecting with saved session... failed" \
+            -s "Protocol is TLSv1.3" \
+            -s "<= write new session ticket"
+
 requires_openssl_tls1_3_with_compatible_ephemeral
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 requires_config_enabled MBEDTLS_DEBUG_C
diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data
index 989235d..561297c 100644
--- a/tests/suites/test_suite_pk.data
+++ b/tests/suites/test_suite_pk.data
@@ -450,9 +450,13 @@
 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
 
-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
@@ -1451,3 +1455,136 @@
 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
 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..089202b 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>
@@ -167,6 +169,19 @@
 #define MBEDTLS_TEST_PSA_ECC_ANOTHER_CURVE_BITS 0
 #endif
 
+/* 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 defined(MBEDTLS_PK_USE_PSA_EC_DATA)
 static int pk_genkey_ec(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id)
 {
@@ -307,6 +322,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)
@@ -425,7 +517,110 @@
 }
 #endif
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#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.
+ */
+static mbedtls_svc_key_id_t psa_pub_key_from_priv(mbedtls_svc_key_id_t priv_id)
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    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;
+
+    /* 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_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:
+    psa_reset_key_attributes(&attributes);
+    return pub_key;
+}
+
+/* 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)
+{
+    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_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:
+    psa_reset_key_attributes(&orig_attr);
+    psa_reset_key_attributes(&new_attr);
+    return new_key_id;
+}
+
+psa_status_t pk_psa_import_key(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;
+}
+
+psa_status_t pk_psa_genkey_generic(psa_key_type_t type, size_t bits,
+                                   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;
+
+    psa_set_key_usage_flags(&attributes, usage);
+    psa_set_key_algorithm(&attributes, alg);
+    psa_set_key_type(&attributes, type);
+    psa_set_key_bits(&attributes, bits);
+    status = psa_generate_key(&attributes, key);
+
+    return status;
+}
 
 /*
  * Generate an ECC key using PSA and return the key identifier of that key,
@@ -435,18 +630,11 @@
 mbedtls_svc_key_id_t pk_psa_genkey_ecc(void)
 {
     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_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
-    psa_set_key_algorithm(&attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
-    psa_set_key_type(&attributes, type);
-    psa_set_key_bits(&attributes, bits);
-    PSA_ASSERT(psa_generate_key(&attributes, &key));
+    pk_psa_genkey_generic(PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 256,
+                          PSA_KEY_USAGE_SIGN_HASH, PSA_ALG_ECDSA(PSA_ALG_SHA_256),
+                          &key);
 
-exit:
     return key;
 }
 
@@ -457,20 +645,13 @@
 mbedtls_svc_key_id_t pk_psa_genkey_rsa(void)
 {
     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_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));
+    pk_psa_genkey_generic(PSA_KEY_TYPE_RSA_KEY_PAIR, 1024, PSA_KEY_USAGE_SIGN_HASH,
+                          PSA_ALG_RSA_PKCS1V15_SIGN_RAW, &key);
 
-exit:
     return key;
 }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_PSA_CRYPTO_C */
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -1250,7 +1431,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 +1446,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 +1456,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 +1476,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 +1506,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 */
 
@@ -1853,8 +2036,10 @@
         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;
@@ -1879,7 +2064,9 @@
     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;
@@ -2199,3 +2386,332 @@
     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)
+    /* Generate a key type that is not handled by the PK module. */
+    PSA_ASSERT(pk_psa_genkey_generic(PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919), 2048,
+                                     PSA_KEY_USAGE_EXPORT, PSA_ALG_NONE, &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) && \
+    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
+    /* Generate an EC key which cannot be exported. */
+    PSA_ASSERT(pk_psa_genkey_generic(PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1), 256,
+                                     0, PSA_ALG_NONE, &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 &&
+          PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
+
+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_genkey_generic(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),
+                                     &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;
+    unsigned char *in_buf = NULL;
+    size_t in_buf_len = MBEDTLS_MD_MAX_SIZE;
+    unsigned char out_buf[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
+    unsigned char out_buf2[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
+    size_t out_buf_len, out_buf2_len;
+
+    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);
+
+    /* Destoy 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);
+
+    /* Test #1:
+     * - 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 */
+    }
+
+    /* Test #2: check that the 2 generated 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);
+
+    /* Get the MD alg to be used for the tests below from the provided key policy. */
+    mbedtls_md_type_t md_for_test = MBEDTLS_MD_ALG_FOR_TEST; /* Default */
+    if ((PSA_ALG_GET_HASH(key_alg) != PSA_ALG_NONE) &&
+        (PSA_ALG_GET_HASH(key_alg) != PSA_ALG_ANY_HASH)) {
+        md_for_test = mbedtls_md_type_from_psa_alg(key_alg);
+    }
+    /* Use also the same MD algorithm for PSA sign/verify checks. This is helpful
+     * for the cases in which the key policy algorithm is ANY_HASH type. */
+    psa_algorithm_t psa_alg_for_test =
+        (key_alg & ~PSA_ALG_HASH_MASK) |
+        (mbedtls_md_psa_alg_from_type(md_for_test) & PSA_ALG_HASH_MASK);
+
+    in_buf_len = mbedtls_md_get_size_from_type(md_for_test);
+    TEST_CALLOC(in_buf, in_buf_len);
+    memset(in_buf, 0x1, in_buf_len);
+
+    /* Test #3: sign/verify with the following pattern:
+     * - Sign using the PK context generated from the private key.
+     * - Verify from the same PK context used for signature.
+     * - Verify with the PK context generated using public key.
+     * - Verify using the public PSA key directly.
+     */
+
+    /* Edge cases: in a build with RSA key support but not RSA padding modes,
+     * or with ECDSA verify support but not signature, the signature might be
+     * impossible. */
+    int pk_can_sign = 0;
+#if defined(MBEDTLS_PKCS1_V15)
+    if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(key_alg) || key_alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
+        pk_can_sign = 1;
+    }
+#endif
+#if defined(MBEDTLS_PKCS1_V21)
+    if (PSA_ALG_IS_RSA_PSS(key_alg) || PSA_ALG_IS_RSA_OAEP(key_alg)) {
+        pk_can_sign = 1;
+    }
+#endif
+#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
+    if (PSA_ALG_IS_ECDSA(key_alg) || PSA_ALG_IS_DETERMINISTIC_ECDSA(key_alg)) {
+        pk_can_sign = 1;
+    }
+#endif
+    if (pk_can_sign) {
+        TEST_EQUAL(mbedtls_pk_sign(&pk_priv, md_for_test, in_buf, in_buf_len,
+                                   out_buf, sizeof(out_buf), &out_buf_len,
+                                   mbedtls_test_rnd_std_rand, NULL), 0);
+
+        TEST_EQUAL(mbedtls_pk_verify(&pk_priv, md_for_test, in_buf, in_buf_len,
+                                     out_buf, out_buf_len), 0);
+        TEST_EQUAL(mbedtls_pk_verify(&pk_pub, md_for_test, in_buf, in_buf_len,
+                                     out_buf, out_buf_len), 0);
+    }
+
+    if (PSA_ALG_IS_HASH_AND_SIGN(key_alg)) {
+#if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
+        /* ECDSA signature requires PK->PSA format conversion. */
+        if (PSA_ALG_IS_ECDSA(key_alg)) {
+            TEST_EQUAL(mbedtls_ecdsa_der_to_raw(mbedtls_pk_get_bitlen(&pk_pub),
+                                                out_buf, out_buf_len, out_buf,
+                                                sizeof(out_buf), &out_buf_len), 0);
+        }
+#endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */
+        PSA_ASSERT(psa_verify_hash(pub_key_id, psa_alg_for_test, in_buf, in_buf_len,
+                                   out_buf, out_buf_len));
+    }
+
+    /* Test #4: check sign/verify interoperability also in the opposite direction:
+     * sign with PSA and verify with PK. Key's policy must include a valid hash
+     * algorithm (not any).
+     */
+    if (PSA_ALG_IS_HASH_AND_SIGN(key_alg)) {
+        PSA_ASSERT(psa_sign_hash(priv_key_id, psa_alg_for_test, in_buf, in_buf_len,
+                                 out_buf, sizeof(out_buf), &out_buf_len));
+#if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
+        /*  ECDSA signature requires PSA->PK format conversion */
+        if (PSA_ALG_IS_ECDSA(key_alg)) {
+            TEST_EQUAL(mbedtls_ecdsa_raw_to_der(mbedtls_pk_get_bitlen(&pk_pub),
+                                                out_buf, out_buf_len, out_buf,
+                                                sizeof(out_buf), &out_buf_len), 0);
+        }
+#endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */
+        TEST_EQUAL(mbedtls_pk_verify(&pk_pub, md_for_test, in_buf, in_buf_len,
+                                     out_buf, out_buf_len), 0);
+    }
+
+    /* Test #5: in case of RSA key pair try also encryption/decryption. */
+    if (PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(key_alg)) {
+        /* Encrypt with the public key only PK context. */
+        TEST_EQUAL(mbedtls_pk_encrypt(&pk_pub, in_buf, in_buf_len,
+                                      out_buf, &out_buf_len, sizeof(out_buf),
+                                      mbedtls_test_rnd_std_rand, NULL), 0);
+
+        /* Decrypt with key pair PK context and compare with original data. */
+        TEST_EQUAL(mbedtls_pk_decrypt(&pk_priv, out_buf, out_buf_len,
+                                      out_buf2, &out_buf2_len, sizeof(out_buf2),
+                                      mbedtls_test_rnd_std_rand, NULL), 0);
+        TEST_MEMORY_COMPARE(in_buf, in_buf_len, out_buf2, out_buf2_len);
+
+        if (PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(key_alg)) {
+            /* Decrypt with PSA private key directly and compare with original data. */
+            PSA_ASSERT(psa_asymmetric_decrypt(priv_key_id, key_alg, out_buf, out_buf_len,
+                                              NULL, 0,
+                                              out_buf2, sizeof(out_buf2), &out_buf2_len));
+            TEST_MEMORY_COMPARE(in_buf, in_buf_len, out_buf2, out_buf2_len);
+
+            /* Encrypt with PSA public key directly, decrypt with public key PK context
+             * and compare with original data. */
+            PSA_ASSERT(psa_asymmetric_encrypt(pub_key_id, key_alg, in_buf, in_buf_len,
+                                              NULL, 0,
+                                              out_buf, sizeof(out_buf), &out_buf_len));
+            TEST_EQUAL(mbedtls_pk_decrypt(&pk_priv, out_buf, out_buf_len,
+                                          out_buf2, &out_buf2_len, sizeof(out_buf2),
+                                          mbedtls_test_rnd_std_rand, NULL), 0);
+            TEST_MEMORY_COMPARE(in_buf, in_buf_len, out_buf2, out_buf2_len);
+        }
+    }
+
+    /* Test that the keys from mbedtls_pk_copy_public_from_psa() are identical
+     * to the public key 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_free(in_buf);
+    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_ssl.data b/tests/suites/test_suite_ssl.data
index e95aada..0ecf65c 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -961,6 +961,14 @@
 depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SRV_C
 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
@@ -3286,17 +3294,17 @@
 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 state, early data accepted
+tls13_cli_early_data_state:TEST_EARLY_DATA_ACCEPTED
 
-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 state, no early data indication
+tls13_cli_early_data_state:TEST_EARLY_DATA_NO_INDICATION_SENT
 
-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 state, server rejects early data
+tls13_cli_early_data_state:TEST_EARLY_DATA_SERVER_REJECTS
 
-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 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
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 0c9ccf1..2fe4997 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -2104,6 +2104,14 @@
 #if defined(MBEDTLS_SSL_EARLY_DATA)
         TEST_ASSERT(
             original.max_early_data_size == restored.max_early_data_size);
+#if defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C)
+        if (endpoint_type == MBEDTLS_SSL_IS_SERVER) {
+            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
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
@@ -2396,7 +2404,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;
@@ -2422,6 +2430,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)
 {
@@ -3738,8 +3794,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);
@@ -3790,7 +3846,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;
@@ -3802,6 +3858,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));
@@ -3903,17 +3960,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;
 
@@ -3926,22 +3983,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;
 
@@ -3954,18 +4018,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:
@@ -3976,19 +4040,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:
@@ -3998,26 +4062,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:
@@ -4028,19 +4092,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:
@@ -4054,8 +4118,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:
@@ -4065,21 +4129,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:
@@ -4093,19 +4157,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:
@@ -4125,7 +4189,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 */
@@ -4606,8 +4670,8 @@
     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_status,
-               MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE);
+    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
@@ -4780,8 +4844,8 @@
                    &(client_ep.ssl), &(server_ep.ssl),
                    MBEDTLS_SSL_SERVER_HELLO), 0);
 
-    TEST_ASSERT(client_ep.ssl.early_data_status !=
-                MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT);
+    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);