Merge pull request #3695 from gilles-peskine-arm/psa-unified-driver-specs-20200918

PSA unified driver specification: key validation and transparent key import
diff --git a/.gitignore b/.gitignore
index ee2cd46..39cdc4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,4 +54,5 @@
 /GSYMS
 /GTAGS
 /TAGS
+/cscope*.out
 /tags
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5af4c81..ac24bf4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,9 +14,13 @@
 #     CMake files. It is related to ZLIB support which is planned to be removed.
 #     When the support is removed, the associated include_directories command
 #     will be removed as well as this note.
+# - MBEDTLS_TARGET_PREFIX: CMake targets are designed to be alterable by calling
+#   CMake in order to avoid target name clashes, via the use of
+#   MBEDTLS_TARGET_PREFIX. The value of this variable is prefixed to the
+#   mbedtls, mbedx509, mbedcrypto and apidoc targets.
 #
 
-cmake_minimum_required(VERSION 2.6)
+cmake_minimum_required(VERSION 2.8.12)
 if(TEST_CPP)
     project("mbed TLS" C CXX)
 else()
@@ -112,9 +116,12 @@
     endif()
 endif()
 
-set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}
-    CACHE STRING "Choose the type of build: None Debug Release Coverage ASan ASanDbg MemSan MemSanDbg Check CheckFull"
-    FORCE)
+# If this is the root project add longer list of available CMAKE_BUILD_TYPE values
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
+    set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}
+        CACHE STRING "Choose the type of build: None Debug Release Coverage ASan ASanDbg MemSan MemSanDbg Check CheckFull"
+        FORCE)
+endif()
 
 # Create a symbolic link from ${base_name} in the binary directory
 # to the corresponding path in the source directory.
@@ -273,7 +280,7 @@
     add_subdirectory(programs)
 endif()
 
-ADD_CUSTOM_TARGET(apidoc
+ADD_CUSTOM_TARGET(${MBEDTLS_TARGET_PREFIX}apidoc
     COMMAND doxygen mbedtls.doxyfile
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doxygen)
 
diff --git a/ChangeLog.d/00README.md b/ChangeLog.d/00README.md
index b559e23..d2ea73d 100644
--- a/ChangeLog.d/00README.md
+++ b/ChangeLog.d/00README.md
@@ -3,6 +3,29 @@
 This directory contains changelog entries that have not yet been merged
 to the changelog file ([`../ChangeLog`](../ChangeLog)).
 
+## What requires a changelog entry?
+
+Write a changelog entry if there is a user-visible change. This includes:
+
+* Bug fixes in the library or in sample programs: fixing a security hole,
+  fixing broken behavior, fixing the build in some configuration or on some
+  platform, etc.
+* New features in the library, new sample programs, or new platform support.
+* Changes in existing behavior. These should be rare. Changes in features
+  that are documented as experimental may or may not be announced, depending
+  on the extent of the change and how widely we expect the feature to be used.
+
+We generally don't include changelog entries for:
+
+* Documentation improvements.
+* Performance improvements, unless they are particularly significant.
+* Changes to parts of the code base that users don't interact with directly,
+  such as test code and test data.
+
+Until Mbed TLS 2.24.0, we required changelog entries in more cases.
+Looking at older changelog entries is good practice for how to write a
+changelog entry, but not for deciding whether to write one.
+
 ## Changelog entry file format
 
 A changelog entry file must have the extension `*.txt` and must have the
@@ -33,8 +56,7 @@
     Bugfix
     Changes
 
-Use “Changes” for anything that doesn't fit in the other categories, such as
-performance, documentation and test improvements.
+Use “Changes” for anything that doesn't fit in the other categories.
 
 ## How to write a changelog entry
 
@@ -49,8 +71,7 @@
 Mbed TLS issue. Add other external references such as CVE numbers where
 applicable.
 
-Credit the author of the contribution if the contribution is not a member of
-the Mbed TLS development team. Also credit bug reporters where applicable.
+Credit bug reporters where applicable.
 
 **Explain why, not how**. Remember that the audience is the users of the
 library, not its developers. In particular, for a bug fix, explain the
diff --git a/ChangeLog.d/_GNU_SOURCE-redefined.txt b/ChangeLog.d/_GNU_SOURCE-redefined.txt
new file mode 100644
index 0000000..59c8a15
--- /dev/null
+++ b/ChangeLog.d/_GNU_SOURCE-redefined.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix the build when the macro _GNU_SOURCE is defined to a non-empty value.
+     Fix #3432.
diff --git a/ChangeLog.d/add_MBEDTLS_TARGET_PREFIX_to_cmake.txt b/ChangeLog.d/add_MBEDTLS_TARGET_PREFIX_to_cmake.txt
new file mode 100644
index 0000000..533f309
--- /dev/null
+++ b/ChangeLog.d/add_MBEDTLS_TARGET_PREFIX_to_cmake.txt
@@ -0,0 +1,6 @@
+Features
+   * Add MBEDTLS_TARGET_PREFIX CMake variable, which is prefixed to the mbedtls,
+     mbedcrypto, mbedx509 and apidoc CMake target names. This can be used by
+     external CMake projects that include this one to avoid CMake target name
+     clashes.  The default value of this variable is "", so default target names
+     are unchanged.
diff --git a/ChangeLog.d/add_export_public_key_driver.txt b/ChangeLog.d/add_export_public_key_driver.txt
new file mode 100644
index 0000000..a9bffbc
--- /dev/null
+++ b/ChangeLog.d/add_export_public_key_driver.txt
@@ -0,0 +1,3 @@
+Features
+    * Implementation of the export_public_key interface for PSA Crypto
+      accelerator drivers, as defined in #3493. Contributed in #3786.
diff --git a/ChangeLog.d/aes-zeroize-pointer.txt b/ChangeLog.d/aes-zeroize-pointer.txt
new file mode 100644
index 0000000..ccc6dc1
--- /dev/null
+++ b/ChangeLog.d/aes-zeroize-pointer.txt
@@ -0,0 +1,5 @@
+Changes
+   * Remove the zeroization of a pointer variable in AES rounds. It was valid
+     but spurious and misleading since it looked like a mistaken attempt to
+     zeroize the pointed-to buffer. Reported by Antonio de la Piedra, CEA
+     Leti, France.
diff --git a/ChangeLog.d/android-socklen_t.txt b/ChangeLog.d/android-socklen_t.txt
new file mode 100644
index 0000000..d795a52
--- /dev/null
+++ b/ChangeLog.d/android-socklen_t.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Use socklen_t on Android and other POSIX-compliant system
+
diff --git a/ChangeLog.d/arc4random_buf-implicit.txt b/ChangeLog.d/arc4random_buf-implicit.txt
new file mode 100644
index 0000000..81c245e
--- /dev/null
+++ b/ChangeLog.d/arc4random_buf-implicit.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Make arc4random_buf available on NetBSD and OpenBSD when _POSIX_C_SOURCE is
+     defined. Fix contributed in #3571.
diff --git a/ChangeLog.d/bugfix_3524.txt b/ChangeLog.d/bugfix_3524.txt
new file mode 100644
index 0000000..e038340
--- /dev/null
+++ b/ChangeLog.d/bugfix_3524.txt
@@ -0,0 +1,3 @@
+Bugfix
+  * Include the psa_constant_names generated source code in the source tree
+    instead of generating it at build time. Fixes #3524.
diff --git a/ChangeLog.d/bugfix_3794.txt b/ChangeLog.d/bugfix_3794.txt
new file mode 100644
index 0000000..a483ea7
--- /dev/null
+++ b/ChangeLog.d/bugfix_3794.txt
@@ -0,0 +1,4 @@
+Bugfix
+  * Fix handling of EOF against 0xff bytes and on platforms with
+    unsigned chars.  Fixes a build failure on platforms where char is
+    unsigned.  Fixes #3794.
diff --git a/ChangeLog.d/comment_typo_in_mbedtls_ssl_set_bio.txt b/ChangeLog.d/comment_typo_in_mbedtls_ssl_set_bio.txt
deleted file mode 100644
index 2f94c16..0000000
--- a/ChangeLog.d/comment_typo_in_mbedtls_ssl_set_bio.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Changes
-   * Fix comment typo in documentation of mbedtls_ssl_set_bio.
diff --git a/ChangeLog.d/ecb_iv_fix.txt b/ChangeLog.d/ecb_iv_fix.txt
new file mode 100644
index 0000000..ae2ae25
--- /dev/null
+++ b/ChangeLog.d/ecb_iv_fix.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Correct the default IV size for mbedtls_cipher_info_t structures using
+     MBEDTLS_MODE_ECB to 0, since ECB mode ciphers don't use IVs.
diff --git a/ChangeLog.d/ecp_curve_list.txt b/ChangeLog.d/ecp_curve_list.txt
new file mode 100644
index 0000000..55745d3
--- /dev/null
+++ b/ChangeLog.d/ecp_curve_list.txt
@@ -0,0 +1,5 @@
+Bugfix
+   * mbedtls_ecp_curve_list() now lists Curve25519 and Curve448 under the names
+     "x25519" and "x448". These curves support ECDH but not ECDSA. If you need
+     only the curves that support ECDSA, filter the list with
+     mbedtls_ecdsa_can_do().
diff --git a/ChangeLog.d/error-include-string.txt b/ChangeLog.d/error-include-string.txt
new file mode 100644
index 0000000..0a12c7b
--- /dev/null
+++ b/ChangeLog.d/error-include-string.txt
@@ -0,0 +1,2 @@
+Bugfix
+   * Fix conditions for including string.h in error.c. Fixes #3866.
diff --git a/ChangeLog.d/feature-dtls-srtp.txt b/ChangeLog.d/feature-dtls-srtp.txt
new file mode 100644
index 0000000..8b9186b
--- /dev/null
+++ b/ChangeLog.d/feature-dtls-srtp.txt
@@ -0,0 +1,2 @@
+Features
+* Add support for DTLS-SRTP as defined in RFC 5764. Contributed by Johan Pascal, improved by Ron Eldor.
diff --git a/ChangeLog.d/fix-rsa-blinding.txt b/ChangeLog.d/fix-rsa-blinding.txt
new file mode 100644
index 0000000..a13572c
--- /dev/null
+++ b/ChangeLog.d/fix-rsa-blinding.txt
@@ -0,0 +1,6 @@
+Bugfix
+   * Fix rsa_prepare_blinding() to retry when the blinding value is not
+     invertible (mod N), instead of returning MBEDTLS_ERR_RSA_RNG_FAILED. This
+     addresses a regression but is rare in practice (approx. 1 in 2/sqrt(N)).
+     Found by Synopsys Coverity, fix contributed by Peter Kolbus (Garmin).
+     Fixes #3647.
diff --git a/ChangeLog.d/fix-typo.txt b/ChangeLog.d/fix-typo.txt
deleted file mode 100644
index 8e961d2..0000000
--- a/ChangeLog.d/fix-typo.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Changes
-   * Fixes a typo in the example code located in
-     program/pkey/ecdh_curve25519.c
diff --git a/ChangeLog.d/fix_ccm_add_length_check.txt b/ChangeLog.d/fix_ccm_add_length_check.txt
new file mode 100644
index 0000000..259399f
--- /dev/null
+++ b/ChangeLog.d/fix_ccm_add_length_check.txt
@@ -0,0 +1,5 @@
+Bugfix
+   * Fix an off-by-one error in the additional data length check for
+     CCM, which allowed encryption with a non-standard length field.
+     Fixes #3719.
+
diff --git a/ChangeLog.d/minimum_cmake_version_PR3802.txt b/ChangeLog.d/minimum_cmake_version_PR3802.txt
new file mode 100644
index 0000000..549f9b1
--- /dev/null
+++ b/ChangeLog.d/minimum_cmake_version_PR3802.txt
@@ -0,0 +1,3 @@
+Requirement changes
+* Update the minimum required CMake version to 2.8.12.
+* This silences a warning on CMake 3.19.0. #3801
diff --git a/ChangeLog.d/psa-openless.txt b/ChangeLog.d/psa-openless.txt
new file mode 100644
index 0000000..2e40cdf
--- /dev/null
+++ b/ChangeLog.d/psa-openless.txt
@@ -0,0 +1,17 @@
+Features
+   * In the PSA API, it is no longer necessary to open persistent keys:
+     operations now accept the key identifier. The type psa_key_handle_t is now
+     identical to psa_key_id_t instead of being platform-defined. This bridges
+     the last major gap to compliance with the PSA Cryptography specification
+     version 1.0.0. Opening persistent keys is still supported for backward
+     compatibility, but will be deprecated and later removed in future
+     releases.
+
+Bugfix
+   * psa_set_key_id() now also sets the lifetime to persistent for keys located
+     in a secure element.
+   * Attempting to create a volatile key with a non-zero key identifier now
+     fails. Previously the key identifier was just ignored when creating a
+     volatile key.
+   * Attempting to create or register a key with a key identifier in the vendor
+     range now fails.
diff --git a/ChangeLog.d/psa_error_invalid_argument_for_invalid_cipher_input_sizes.txt b/ChangeLog.d/psa_error_invalid_argument_for_invalid_cipher_input_sizes.txt
new file mode 100644
index 0000000..85c363b
--- /dev/null
+++ b/ChangeLog.d/psa_error_invalid_argument_for_invalid_cipher_input_sizes.txt
@@ -0,0 +1,4 @@
+Bugfix
+   * Consistently return PSA_ERROR_INVALID_ARGUMENT on invalid cipher input
+     sizes (instead of PSA_ERROR_BAD_STATE in some cases) to make the
+     psa_cipher_* functions compliant with the PSA Crypto API specification.
diff --git a/ChangeLog.d/psa_generate_key-curve25519.txt b/ChangeLog.d/psa_generate_key-curve25519.txt
new file mode 100644
index 0000000..24b6fcf
--- /dev/null
+++ b/ChangeLog.d/psa_generate_key-curve25519.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix psa_generate_key() returning an error when asked to generate
+     an ECC key pair on Curve25519 or secp244k1.
diff --git a/ChangeLog.d/support-ecdh-kdf-with-ecdh-key.txt b/ChangeLog.d/support-ecdh-kdf-with-ecdh-key.txt
new file mode 100644
index 0000000..6660dc3
--- /dev/null
+++ b/ChangeLog.d/support-ecdh-kdf-with-ecdh-key.txt
@@ -0,0 +1,6 @@
+Features
+   * In PSA, allow using a key declared with a base key agreement algorithm
+     in combined key agreement and derivation operations, as long as the key
+     agreement algorithm in use matches the algorithm the key was declared with.
+     This is currently non-standard behaviour, but expected to make it into a
+     future revision of the PSA Crypto standard.
diff --git a/ChangeLog.d/support-key-agreement-and-derivation-output-as-key.txt b/ChangeLog.d/support-key-agreement-and-derivation-output-as-key.txt
new file mode 100644
index 0000000..3f61481
--- /dev/null
+++ b/ChangeLog.d/support-key-agreement-and-derivation-output-as-key.txt
@@ -0,0 +1,4 @@
+Bugfix
+   * Fix psa_key_derivation_output_key() to allow the output of a combined key
+     agreement and subsequent key derivation operation to be used as a key
+     inside of the PSA Crypto core.
diff --git a/ChangeLog.d/systematically_store_bit_size_3740.txt b/ChangeLog.d/systematically_store_bit_size_3740.txt
new file mode 100644
index 0000000..9e63bbc
--- /dev/null
+++ b/ChangeLog.d/systematically_store_bit_size_3740.txt
@@ -0,0 +1,5 @@
+Changes
+   * The PSA persistent storage format is updated to always store the key bits
+     attribute. No automatic upgrade path is provided. Previously stored keys
+     must be erased, or manually upgraded based on the key storage format
+     specification (docs/architecture/mbed-crypto-storage-specification.md). #3740
diff --git a/Makefile b/Makefile
index d00183e..9344e71 100644
--- a/Makefile
+++ b/Makefile
@@ -45,6 +45,7 @@
 
 uninstall:
 	rm -rf $(DESTDIR)/include/mbedtls
+	rm -rf $(DESTDIR)/include/psa
 	rm -f $(DESTDIR)/lib/libmbedtls.*
 	rm -f $(DESTDIR)/lib/libmbedx509.*
 	rm -f $(DESTDIR)/lib/libmbedcrypto.*
@@ -126,12 +127,26 @@
 endif
 
 ## Editor navigation files
-C_SOURCE_FILES = $(wildcard include/*/*.h library/*.[hc] programs/*/*.[hc] tests/suites/*.function)
+C_SOURCE_FILES = $(wildcard \
+	3rdparty/*/include/*/*.h 3rdparty/*/include/*/*/*.h 3rdparty/*/include/*/*/*/*.h \
+	3rdparty/*/*.c 3rdparty/*/*/*.c 3rdparty/*/*/*/*.c 3rdparty/*/*/*/*/*.c \
+	include/*/*.h \
+	library/*.[hc] \
+	programs/*/*.[hc] \
+	tests/include/*/*.h tests/include/*/*/*.h \
+	tests/src/*.c tests/src/*/*.c \
+	tests/suites/*.function \
+)
 # Exuberant-ctags invocation. Other ctags implementations may require different options.
 CTAGS = ctags --langmap=c:+.h.function -o
 tags: $(C_SOURCE_FILES)
 	$(CTAGS) $@ $(C_SOURCE_FILES)
 TAGS: $(C_SOURCE_FILES)
 	etags -o $@ $(C_SOURCE_FILES)
+global: GPATH GRTAGS GSYMS GTAGS
 GPATH GRTAGS GSYMS GTAGS: $(C_SOURCE_FILES)
 	ls $(C_SOURCE_FILES) | gtags -f - --gtagsconf .globalrc
+cscope: cscope.in.out cscope.po.out cscope.out
+cscope.in.out cscope.po.out cscope.out: $(C_SOURCE_FILES)
+	cscope -bq -u -Iinclude -Ilibrary $(patsubst %,-I%,$(wildcard 3rdparty/*/include)) -Itests/include $(C_SOURCE_FILES)
+.PHONY: cscope global
diff --git a/README.md b/README.md
index 2058d24..ac2a6ab 100644
--- a/README.md
+++ b/README.md
@@ -208,7 +208,7 @@
 
 * The API distinguishes caller memory from internal memory, which allows the library to be implemented in an isolated space for additional security. Library calls can be implemented as direct function calls if isolation is not desired, and as remote procedure calls if isolation is desired.
 * The structure of internal data is hidden to the application, which allows substituting alternative implementations at build time or run time, for example, in order to take advantage of hardware accelerators.
-* All access to the keys happens through handles, which allows support for external cryptoprocessors that is transparent to applications.
+* All access to the keys happens through key identifiers, which allows support for external cryptoprocessors that is transparent to applications.
 * The interface to algorithms is generic, favoring algorithm agility.
 * The interface is designed to be easy to use and hard to accidentally misuse.
 
diff --git a/configs/config-symmetric-only.h b/configs/config-symmetric-only.h
index 054cb9e..f05a0d7 100644
--- a/configs/config-symmetric-only.h
+++ b/configs/config-symmetric-only.h
@@ -92,6 +92,8 @@
 #define MBEDTLS_VERSION_C
 #define MBEDTLS_XTEA_C
 
+#include "mbedtls/config_psa.h"
+
 #include "check_config.h"
 
 #endif /* MBEDTLS_CONFIG_H */
diff --git a/docs/architecture/mbed-crypto-storage-specification.md b/docs/architecture/mbed-crypto-storage-specification.md
index afeb29f..914bca3 100644
--- a/docs/architecture/mbed-crypto-storage-specification.md
+++ b/docs/architecture/mbed-crypto-storage-specification.md
@@ -251,6 +251,7 @@
 * key material length (4 bytes).
 * key material:
     * For a transparent key: output of `psa_export_key`.
+    * For an opaque key (unified driver interface): driver-specific opaque key blob.
     * For an opaque key (key in a secure element): slot number (8 bytes), in platform endianness.
 * Any trailing data is rejected on load.
 
@@ -280,3 +281,36 @@
     * The slot in the secure element designated by the slot number.
     * The file containing the key metadata designated by the key identifier.
     * The driver persistent data.
+
+Mbed Crypto TBD
+---------------
+
+Tags: TBD
+
+Released in TBD 2020. <br>
+Integrated in Mbed OS TBD.
+
+### Changes introduced in TBD
+
+* The type field has been split into a type and a bits field of 2 bytes each.
+
+### Key file format for TBD
+
+All integers are encoded in little-endian order in 8-bit bytes except where otherwise indicated.
+
+The layout of a key file is:
+
+* magic (8 bytes): `"PSA\0KEY\0"`.
+* version (4 bytes): 0.
+* lifetime (4 bytes): `psa_key_lifetime_t` value.
+* type (2 bytes): `psa_key_type_t` value.
+* bits (2 bytes): `psa_key_bits_t` value.
+* policy usage flags (4 bytes): `psa_key_usage_t` value.
+* policy usage algorithm (4 bytes): `psa_algorithm_t` value.
+* policy enrollment algorithm (4 bytes): `psa_algorithm_t` value.
+* key material length (4 bytes).
+* key material:
+    * For a transparent key: output of `psa_export_key`.
+    * For an opaque key (unified driver interface): driver-specific opaque key blob.
+    * For an opaque key (key in a secure element): slot number (8 bytes), in platform endianness.
+* Any trailing data is rejected on load.
diff --git a/docs/architecture/testing/invasive-testing.md b/docs/architecture/testing/invasive-testing.md
index 744f194..de611a5 100644
--- a/docs/architecture/testing/invasive-testing.md
+++ b/docs/architecture/testing/invasive-testing.md
@@ -100,7 +100,7 @@
 
 * Memory.
 * Files in storage (PSA API only — in the Mbed TLS API, black-box unit tests are sufficient).
-* Key handles (PSA API only).
+* Key slots (PSA API only).
 * Key slots in a secure element (PSA SE HAL).
 * Communication handles (PSA crypto service only).
 
@@ -116,7 +116,7 @@
 
 * Zeroization of confidential data after use.
 * Freeing memory.
-* Closing key handles.
+* Freeing key slots.
 * Freeing key slots in a secure element.
 * Deleting files in storage (PSA API only).
 
diff --git a/docs/getting_started.md b/docs/getting_started.md
index e274f49..15d5a31 100644
--- a/docs/getting_started.md
+++ b/docs/getting_started.md
@@ -64,7 +64,7 @@
 ### Importing a key
 
 To use a key for cryptography operations in Mbed Crypto, you need to first
-import it. Importing the key creates a handle that refers to the key for use
+import it. The import operation returns the identifier of the key for use
 with other function calls.
 
 **Prerequisites to importing keys:**
@@ -76,7 +76,7 @@
 {
     psa_status_t status;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_handle_t handle;
+    psa_key_id_t key;
 
     printf("Import an AES key...\t");
     fflush(stdout);
@@ -95,7 +95,7 @@
     psa_set_key_bits(&attributes, 128);
 
     /* Import the key */
-    status = psa_import_key(&attributes, key, key_len, &handle);
+    status = psa_import_key(&attributes, key, key_len, &key);
     if (status != PSA_SUCCESS) {
         printf("Failed to import key\n");
         return;
@@ -106,7 +106,7 @@
     psa_reset_key_attributes(&attributes);
 
     /* Destroy the key */
-    psa_destroy_key(handle);
+    psa_destroy_key(key);
 
     mbedtls_psa_crypto_free();
 }
@@ -135,7 +135,7 @@
                         0xa9, 0xe8, 0xcc, 0xac, 0xd0, 0xf6, 0x54, 0x5c};
     uint8_t signature[PSA_SIGNATURE_MAX_SIZE] = {0};
     size_t signature_length;
-    psa_key_handle_t handle;
+    psa_key_id_t key;
 
     printf("Sign a message...\t");
     fflush(stdout);
@@ -154,14 +154,14 @@
     psa_set_key_bits(&attributes, 1024);
 
     /* Import the key */
-    status = psa_import_key(&attributes, key, key_len, &handle);
+    status = psa_import_key(&attributes, key, key_len, &key);
     if (status != PSA_SUCCESS) {
         printf("Failed to import key\n");
         return;
     }
 
     /* Sign message using the key */
-    status = psa_sign_hash(handle, PSA_ALG_RSA_PKCS1V15_SIGN_RAW,
+    status = psa_sign_hash(key, PSA_ALG_RSA_PKCS1V15_SIGN_RAW,
                            hash, sizeof(hash),
                            signature, sizeof(signature),
                            &signature_length);
@@ -176,7 +176,7 @@
     psa_reset_key_attributes(&attributes);
 
     /* Destroy the key */
-    psa_destroy_key(handle);
+    psa_destroy_key(key);
 
     mbedtls_psa_crypto_free();
 }
@@ -188,7 +188,7 @@
 
 **Prerequisites to working with the symmetric cipher API:**
 * Initialize the library with a successful call to `psa_crypto_init()`.
-* Have a handle to a symmetric key. This key's usage flags must include `PSA_KEY_USAGE_ENCRYPT` to allow encryption or `PSA_KEY_USAGE_DECRYPT` to allow decryption.
+* Have a symmetric key. This key's usage flags must include `PSA_KEY_USAGE_ENCRYPT` to allow encryption or `PSA_KEY_USAGE_DECRYPT` to allow decryption.
 
 **To encrypt a message with a symmetric cipher:**
 1. Allocate an operation (`psa_cipher_operation_t`) structure to pass to the cipher functions.
@@ -213,7 +213,7 @@
     size_t iv_len;
     uint8_t output[block_size];
     size_t output_len;
-    psa_key_handle_t handle;
+    psa_key_id_t key;
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
 
     printf("Encrypt with cipher...\t");
@@ -232,7 +232,7 @@
     psa_set_key_algorithm(&attributes, alg);
     psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
     psa_set_key_bits(&attributes, 128);
-    status = psa_import_key(&attributes, key, key_len, &handle);
+    status = psa_import_key(&attributes, key, key_len, &key);
     if (status != PSA_SUCCESS) {
         printf("Failed to import a key\n");
         return;
@@ -240,7 +240,7 @@
     psa_reset_key_attributes(&attributes);
 
     /* Encrypt the plaintext */
-    status = psa_cipher_encrypt_setup(&operation, handle, alg);
+    status = psa_cipher_encrypt_setup(&operation, key, alg);
     if (status != PSA_SUCCESS) {
         printf("Failed to begin cipher operation\n");
         return;
@@ -268,7 +268,7 @@
     psa_cipher_abort(&operation);
 
     /* Destroy the key */
-    psa_destroy_key(handle);
+    psa_destroy_key(key);
 
     mbedtls_psa_crypto_free();
 }
@@ -298,7 +298,7 @@
     uint8_t iv[block_size] = ENCRYPTED_WITH_IV;
     uint8_t output[block_size];
     size_t output_len;
-    psa_key_handle_t handle;
+    psa_key_id_t key;
 
     printf("Decrypt with cipher...\t");
     fflush(stdout);
@@ -316,7 +316,7 @@
     psa_set_key_algorithm(&attributes, alg);
     psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
     psa_set_key_bits(&attributes, 128);
-    status = psa_import_key(&attributes, key, key_len, &handle);
+    status = psa_import_key(&attributes, key, key_len, &key);
     if (status != PSA_SUCCESS) {
         printf("Failed to import a key\n");
         return;
@@ -324,7 +324,7 @@
     psa_reset_key_attributes(&attributes);
 
     /* Decrypt the ciphertext */
-    status = psa_cipher_decrypt_setup(&operation, handle, alg);
+    status = psa_cipher_decrypt_setup(&operation, key, alg);
     if (status != PSA_SUCCESS) {
         printf("Failed to begin cipher operation\n");
         return;
@@ -352,7 +352,7 @@
     psa_cipher_abort(&operation);
 
     /* Destroy the key */
-    psa_destroy_key(handle);
+    psa_destroy_key(key);
 
     mbedtls_psa_crypto_free();
 }
@@ -592,8 +592,8 @@
         PSA_KEY_DERIVATION_OPERATION_INIT;
     size_t derived_bits = 128;
     size_t capacity = PSA_BITS_TO_BYTES(derived_bits);
-    psa_key_handle_t base_key;
-    psa_key_handle_t derived_key;
+    psa_key_id_t base_key;
+    psa_key_id_t derived_key;
 
     printf("Derive a key (HKDF)...\t");
     fflush(stdout);
@@ -702,7 +702,7 @@
     size_t output_length = 0;
     size_t tag_length = 16;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_handle_t handle;
+    psa_key_id_t key;
 
     printf("Authenticate encrypt...\t");
     fflush(stdout);
@@ -726,11 +726,11 @@
     psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
     psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
     psa_set_key_bits(&attributes, 128);
-    status = psa_import_key(&attributes, key, sizeof(key), &handle);
+    status = psa_import_key(&attributes, key, sizeof(key), &key);
     psa_reset_key_attributes(&attributes);
 
     /* Authenticate and encrypt */
-    status = psa_aead_encrypt(handle, PSA_ALG_CCM,
+    status = psa_aead_encrypt(key, PSA_ALG_CCM,
                               nonce, sizeof(nonce),
                               additional_data, sizeof(additional_data),
                               input_data, sizeof(input_data),
@@ -747,7 +747,7 @@
     free(output_data);
 
     /* Destroy the key */
-    psa_destroy_key(handle);
+    psa_destroy_key(key);
 
     mbedtls_psa_crypto_free();
 ```
@@ -756,7 +756,7 @@
 
 ```C
     psa_status_t status;
-    static const uint8_t key[] = {
+    static const uint8_t key_data[] = {
         0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
         0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF };
     static const uint8_t nonce[] = {
@@ -773,7 +773,7 @@
     size_t output_size = 0;
     size_t output_length = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_handle_t handle;
+    psa_key_id_t key;
 
     printf("Authenticate decrypt...\t");
     fflush(stdout);
@@ -797,7 +797,7 @@
     psa_set_key_algorithm(&attributes, PSA_ALG_CCM);
     psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
     psa_set_key_bits(&attributes, 128);
-    status = psa_import_key(&attributes, key, sizeof(key), &handle);
+    status = psa_import_key(&attributes, key_data, sizeof(key_data), &key);
     if (status != PSA_SUCCESS) {
         printf("Failed to import a key\n");
         return;
@@ -805,7 +805,7 @@
     psa_reset_key_attributes(&attributes);
 
     /* Authenticate and decrypt */
-    status = psa_aead_decrypt(handle, PSA_ALG_CCM,
+    status = psa_aead_decrypt(key, PSA_ALG_CCM,
                               nonce, sizeof(nonce),
                               additional_data, sizeof(additional_data),
                               input_data, sizeof(input_data),
@@ -822,7 +822,7 @@
     free(output_data);
 
     /* Destroy the key */
-    psa_destroy_key(handle);
+    psa_destroy_key(key);
 
     mbedtls_psa_crypto_free();
 ```
@@ -848,7 +848,7 @@
     size_t exported_length = 0;
     static uint8_t exported[PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits)];
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_handle_t handle;
+    psa_key_id_t key;
 
     printf("Generate a key pair...\t");
     fflush(stdout);
@@ -867,14 +867,14 @@
     psa_set_key_type(&attributes,
                      PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
     psa_set_key_bits(&attributes, key_bits);
-    status = psa_generate_key(&attributes, &handle);
+    status = psa_generate_key(&attributes, &key);
     if (status != PSA_SUCCESS) {
         printf("Failed to generate key\n");
         return;
     }
     psa_reset_key_attributes(&attributes);
 
-    status = psa_export_public_key(handle, exported, sizeof(exported),
+    status = psa_export_public_key(key, exported, sizeof(exported),
                                    &exported_length);
     if (status != PSA_SUCCESS) {
         printf("Failed to export public key %ld\n", status);
@@ -884,7 +884,7 @@
     printf("Exported a public key\n");
 
     /* Destroy the key */
-    psa_destroy_key(handle);
+    psa_destroy_key(key);
 
     mbedtls_psa_crypto_free();
 ```
diff --git a/docs/proposed/psa-conditional-inclusion-c.md b/docs/proposed/psa-conditional-inclusion-c.md
index 08306d2..52138b1 100644
--- a/docs/proposed/psa-conditional-inclusion-c.md
+++ b/docs/proposed/psa-conditional-inclusion-c.md
@@ -5,7 +5,7 @@
 
 This is currently a proposal for Mbed TLS. It is not currently on track for standardization in PSA.
 
-Time-stamp: "2020/09/07 08:27:32 GMT"
+Time-stamp: "2020/11/26 09:30:50 GMT"
 
 ## Introduction
 
@@ -51,26 +51,34 @@
 
 ### PSA Crypto configuration file
 
-The PSA crypto configuration file `psa/crypto_config.h` defines a series of symbols of the form `PSA_WANT_xxx` where `xxx` . The symbols are documented in the section [“PSA Crypto configuration symbols”](#psa-crypto-configuration-symbols) below.
+The PSA Crypto configuration file `psa/crypto_config.h` defines a series of symbols of the form `PSA_WANT_xxx` where `xxx` describes the feature that the symbol enables. The symbols are documented in the section [“PSA Crypto configuration symbols”](#psa-crypto-configuration-symbols) below.
 
-The symbol `MBEDTLS_PSA_CRYPTO_CONFIG` in `mbedtls/config.h` determines whether `psa/crypto_config.h`. is used.
+The symbol `MBEDTLS_PSA_CRYPTO_CONFIG` in `mbedtls/config.h` determines whether `psa/crypto_config.h` is used.
 
 * If `MBEDTLS_PSA_CRYPTO_CONFIG` is unset, which is the default at least in Mbed TLS 2.x versions, things are as they are today: the PSA subsystem includes generic code unconditionally, and includes support for specific mechanisms conditionally based on the existing `MBEDTLS_xxx_` symbols.
-* If `MBEDTLS_PSA_CRYPTO_CONFIG` is set, the necessary software implementations of cryptographic algorithms are included based on both the content of the PSA crypto configuration file and the Mbed TLS configuration file. For example, the code in `aes.c` is enabled if either `mbedtls/config.h` contains `MBEDTLS_AES_C` or `psa/crypto_config.h` contains `PSA_WANT_KEY_TYPE_AES`.
+* If `MBEDTLS_PSA_CRYPTO_CONFIG` is set, the necessary software implementations of cryptographic algorithms are included based on both the content of the PSA Crypto configuration file and the Mbed TLS configuration file. For example, the code in `aes.c` is enabled if either `mbedtls/config.h` contains `MBEDTLS_AES_C` or `psa/crypto_config.h` contains `PSA_WANT_KEY_TYPE_AES`.
 
 ### PSA Crypto configuration symbols
 
 #### Configuration symbol syntax
 
-A PSA crypto configuration symbol is a C preprocessor symbol whose name starts with `PSA_WANT_`.
+A PSA Crypto configuration symbol is a C preprocessor symbol whose name starts with `PSA_WANT_`.
 
 * If the symbol is not defined, the corresponding feature is not included.
 * If the symbol is defined to a preprocessor expression with the value `1`, the corresponding feature is included.
 * If the symbol is defined with a different value, the behavior is currently undefined and reserved for future use.
 
+#### Configuration symbol usage
+
+The presence of a symbol `PSA_WANT_xxx` in the Mbed TLS configuration determines whether a feature is available through the PSA API. These symbols should be used in any place that requires conditional compilation based on the availability of a cryptographic mechanism through the PSA API, including:
+
+* In Mbed TLS test code.
+* In Mbed TLS library code using `MBEDTLS_USE_PSA_CRYPTO`, for example in TLS to determine which cipher suites to enable.
+* In application code that provides additional features based on cryptographic capabilities, for example additional key parsing and formatting functions, or cipher suite availability for network protocols.
+
 #### Configuration symbol semantics
 
-If a feature is not requested for inclusion in the PSA crypto configuration file, it may still be included in the build, either because the feature has been requested in some other way, or because the library does not support the exclusion of this feature. Mbed TLS should make a best effort to support the exclusion of all features, but in some cases this may be judged too much effort for too little benefit.
+If a feature is not requested for inclusion in the PSA Crypto configuration file, it may still be included in the build, either because the feature has been requested in some other way, or because the library does not support the exclusion of this feature. Mbed TLS should make a best effort to support the exclusion of all features, but in some cases this may be judged too much effort for too little benefit.
 
 #### Configuration symbols for key types
 
@@ -107,9 +115,37 @@
 
 ### Architecture of symbol definitions
 
-#### Definition of internal inclusion symbols
+#### New-style definition of configuration symbols
 
-The header file `mbedtls/config.h` needs to define all the `MBEDTLS_xxx_C` configuration symbols, including the ones deduced from the PSA crypto configuration. It does this by including the new header file **`mbedtls/config_psa.h`**, which defines the `MBEDTLS_PSA_BUILTIN_xxx` symbols and deduces the corresponding `MBEDTLS_xxx_C` (and other) symbols.
+When `MBEDTLS_PSA_CRYPTO_CONFIG` is set, the header file `mbedtls/config.h` needs to define all the `MBEDTLS_xxx_C` configuration symbols, including the ones deduced from the PSA Crypto configuration. It does this by including the new header file **`mbedtls/config_psa.h`**, which defines the `MBEDTLS_PSA_BUILTIN_xxx` symbols and deduces the corresponding `MBEDTLS_xxx_C` (and other) symbols.
+
+`mbedtls/config_psa.h` includes `psa/crypto_config.h`, the user-editable file that defines application requirements.
+
+#### Old-style definition of configuration symbols
+
+When `MBEDTLS_PSA_CRYPTO_CONFIG` is not set, the configuration of Mbed TLS works as before, and the inclusion of non-PSA code only depends on `MBEDTLS_xxx` symbols defined (or not) in `mbedtls/config.h`. Furthermore, the new header file **`mbedtls/config_psa.h`** deduces PSA configuration symbols (`PSA_WANT_xxx`, `MBEDTLS_PSA_BUILTIN_xxx`) from classic configuration symbols (`MBEDTLS_xxx`).
+
+The `PSA_WANT_xxx` definitions in `mbedtls/config_psa.h` are needed not only to build the PSA parts of the library, but also to build code that uses these parts. This includes structure definitions in `psa/crypto_struct.h`, size calculations in `psa/crypto_sizes.h`, and application code that's specific to a given cryptographic mechanism. In Mbed TLS itself, code under `MBEDTLS_USE_PSA_CRYPTO` and conditional compilation guards in tests and sample programs need `PSA_WANT_xxx`.
+
+Since some existing applications use a handwritten `mbedtls/config.h` or an edited copy of `mbedtls/config.h` from an earlier version of Mbed TLS, `mbedtls/config_psa.h` must be included via an already existing header that is not `mbedtls/config.h`, so it is included via `psa/crypto.h` (for example from `psa/crypto_platform.h`).
+
+#### Summary of definitions of configuration symbols
+
+Whether `MBEDTLS_PSA_CRYPTO_CONFIG` is set or not, `mbedtls/config_psa.h` includes `mbedtls/crypto_drivers.h`, a header file generated by the transpilation of the driver descriptions. It defines `MBEDTLS_PSA_ACCEL_xxx` symbols according to the availability of transparent drivers without fallback.
+
+The following table summarizes where symbols are defined depending on the configuration mode.
+
+* (U) indicates a symbol that is defined by the user (application).
+* (D) indicates a symbol that is deduced from other symbols by code that ships with Mbed TLS.
+* (G) indicates a symbol that is generated from driver descriptions.
+
+| Symbols                   | With `MBEDTLS_PSA_CRYPTO_CONFIG` | Without `MBEDTLS_PSA_CRYPTO_CONFIG` |
+| ------------------------- | -------------------------------- | ----------------------------------- |
+| `MBEDTLS_xxx_C`           | `mbedtls/config.h` (U) or        | `mbedtls/config.h` (U)              |
+|                           | `mbedtls/config_psa.h` (D)       |                                     |
+| `PSA_WANT_xxx`            | `psa/crypto_config.h` (U)        | `mbedtls/config_psa.h` (D)          |
+| `MBEDTLS_PSA_BUILTIN_xxx` | `mbedtls/config_psa.h` (D)       | `mbedtls/config_psa.h` (D)          |
+| `MBEDTLS_PSA_ACCEL_xxx`   | `mbedtls/crypto_drivers.h` (G)   | N/A                                 |
 
 #### Visibility of internal symbols
 
@@ -127,7 +163,7 @@
 
 A lot of the preprocessor symbol manipulation is systematic calculations that analyze the configuration. `mbedtls/config_psa.h` and `library/psa_check_config.h` should be generated automatically, in the same manner as `version_features.c`.
 
-### Structure of PSA crypto library code
+### Structure of PSA Crypto library code
 
 #### Conditional inclusion of library entry points
 
diff --git a/docs/proposed/psa-driver-developer-guide.md b/docs/proposed/psa-driver-developer-guide.md
index c221bb2..70cb9d3 100644
--- a/docs/proposed/psa-driver-developer-guide.md
+++ b/docs/proposed/psa-driver-developer-guide.md
@@ -36,10 +36,6 @@
 
 Mbed TLS calls driver entry points [as specified in the PSA Cryptography Driver Interface specification](psa-driver-interface.html#driver-entry-points) except as otherwise indicated in this section.
 
-### Key handles
-
-Mbed TLS currently implements the interface for opening and closing persistent keys from version 1.0 beta 3 of the PSA Crypto specification. As a consequence, functions that operate on an existing key take an argument of type `psa_key_handle_t` instead of `psa_key_id_t`. Functions that create a new key take an argument of type `psa_key_handle_t *` instead of `psa_key_id_t *`.
-
 ## Building and testing your driver
 
 <!-- TODO -->
diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md
index 2e061e5..d825794 100644
--- a/docs/proposed/psa-driver-interface.md
+++ b/docs/proposed/psa-driver-interface.md
@@ -666,8 +666,8 @@
 psa_set_key_size(&attributes, 128);
 psa_set_key_algorithm(&attributes, PSA_ALG_GCM);
 psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
-psa_key_handle_t handle = 0;
-psa_generate_key(&attributes, &handle);
+psa_key_id_t key;
+psa_generate_key(&attributes, &key);
 ```
 
 ## Using opaque drivers from an application
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 120c1d3..1ebb706 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -609,6 +609,11 @@
 #error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) && \
+    defined(MBEDTLS_USE_PSA_CRYPTO)
+#error "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined, but it cannot coexist with MBEDTLS_USE_PSA_CRYPTO."
+#endif
+
 #if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) ||         \
     !defined(MBEDTLS_OID_C) )
 #error "MBEDTLS_RSA_C defined, but not all prerequisites"
@@ -871,6 +876,10 @@
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
 #endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP) && ( !defined(MBEDTLS_SSL_PROTO_DTLS) )
+#error "MBEDTLS_SSL_DTLS_SRTP defined, but not all prerequisites"
+#endif
+
 /*
  * Avoid warning from -pedantic. This is a convenient place for this
  * workaround since this is included by every single file before the
diff --git a/include/mbedtls/cipher_internal.h b/include/mbedtls/cipher_internal.h
index d283108..2484c01 100644
--- a/include/mbedtls/cipher_internal.h
+++ b/include/mbedtls/cipher_internal.h
@@ -134,7 +134,7 @@
 typedef struct
 {
     psa_algorithm_t alg;
-    psa_key_handle_t slot;
+    psa_key_id_t slot;
     mbedtls_cipher_psa_key_ownership slot_state;
 } mbedtls_cipher_context_psa;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index b77b34b..464b61e 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -864,7 +864,7 @@
  * may result in a compromise of the long-term signing key. This is avoided by
  * the deterministic variant.
  *
- * Requires: MBEDTLS_HMAC_DRBG_C
+ * Requires: MBEDTLS_HMAC_DRBG_C, MBEDTLS_ECDSA_C
  *
  * Comment this macro to disable deterministic ECDSA.
  */
@@ -1266,7 +1266,7 @@
  * which is currently hard-coded to be int32_t.
  *
  * Note that this option is meant for internal use only and may be removed
- * without notice.
+ * without notice. It is incompatible with MBEDTLS_USE_PSA_CRYPTO.
  */
 //#define MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
 
@@ -1330,7 +1330,7 @@
  *
  * Enable support for the experimental PSA crypto driver interface.
  *
- * Requires: MBEDTLS_PSA_CRYPTO_C.
+ * Requires: MBEDTLS_PSA_CRYPTO_C
  *
  * \warning This interface is experimental and may change or be removed
  * without notice.
@@ -1813,6 +1813,37 @@
 #define MBEDTLS_SSL_DTLS_HELLO_VERIFY
 
 /**
+ * \def MBEDTLS_SSL_DTLS_SRTP
+ *
+ * Enable support for negotation of DTLS-SRTP (RFC 5764)
+ * through the use_srtp extension.
+ *
+ * \note This feature provides the minimum functionality required
+ * to negotiate the use of DTLS-SRTP and to allow the derivation of
+ * the associated SRTP packet protection key material.
+ * In particular, the SRTP packet protection itself, as well as the
+ * demultiplexing of RTP and DTLS packets at the datagram layer
+ * (see Section 5 of RFC 5764), are not handled by this feature.
+ * Instead, after successful completion of a handshake negotiating
+ * the use of DTLS-SRTP, the extended key exporter API
+ * mbedtls_ssl_conf_export_keys_ext_cb() should be used to implement
+ * the key exporter described in Section 4.2 of RFC 5764 and RFC 5705
+ * (this is implemented in the SSL example programs).
+ * The resulting key should then be passed to an SRTP stack.
+ *
+ * Setting this option enables the runtime API
+ * mbedtls_ssl_conf_dtls_srtp_protection_profiles()
+ * through which the supported DTLS-SRTP protection
+ * profiles can be configured. You must call this API at
+ * runtime if you wish to negotiate the use of DTLS-SRTP.
+ *
+ * Requires: MBEDTLS_SSL_PROTO_DTLS
+ *
+ * Uncomment this to enable support for use_srtp extension.
+ */
+//#define MBEDTLS_SSL_DTLS_SRTP
+
+/**
  * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
  *
  * Enable server-side support for clients that reconnect from the same port.
@@ -2020,6 +2051,24 @@
 //#define MBEDTLS_USE_PSA_CRYPTO
 
 /**
+ * \def MBEDTLS_PSA_CRYPTO_CONFIG
+ *
+ * This setting allows support for cryptographic mechanisms through the PSA
+ * API to be configured separately from support through the mbedtls API.
+ *
+ * Uncomment this to enable use of PSA Crypto configuration settings which
+ * can be found in include/psa/crypto_config.h.
+ *
+ * If you enable this option and write your own configuration file, you must
+ * include mbedtls/config_psa.h in your configuration file. The default
+ * provided mbedtls/config.h contains the necessary inclusion.
+ *
+ * This feature is still experimental and is not ready for production since
+ * it is not completed.
+ */
+//#define MBEDTLS_PSA_CRYPTO_CONFIG
+
+/**
  * \def MBEDTLS_VERSION_FEATURES
  *
  * Allow run-time checking of compile-time enabled features. Thus allowing users
@@ -3811,6 +3860,10 @@
 #include MBEDTLS_USER_CONFIG_FILE
 #endif
 
+#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
+#include "mbedtls/config_psa.h"
+#endif
+
 #include "mbedtls/check_config.h"
 
 #endif /* MBEDTLS_CONFIG_H */
diff --git a/include/mbedtls/config_psa.h b/include/mbedtls/config_psa.h
new file mode 100644
index 0000000..5cf1aa7
--- /dev/null
+++ b/include/mbedtls/config_psa.h
@@ -0,0 +1,233 @@
+/**
+ * \file mbedtls/config_psa.h
+ * \brief PSA crypto configuration options (set of defines)
+ *
+ *  This set of compile-time options takes settings defined in
+ *  include/mbedtls/config.h and include/psa/crypto_config.h and uses
+ *  those definitions to define symbols used in the library code.
+ *
+ *  Users and integrators should not edit this file, please edit
+ *  include/mbedtls/config.h for MBETLS_XXX settings or
+ *  include/psa/crypto_config.h for PSA_WANT_XXX settings.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef MBEDTLS_CONFIG_PSA_H
+#define MBEDTLS_CONFIG_PSA_H
+
+#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
+#include "psa/crypto_config.h"
+#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
+
+#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)
+#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA     1
+#define MBEDTLS_ECDSA_DETERMINISTIC
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_HMAC_DRBG_C
+#define MBEDTLS_MD_C
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA */
+#endif /* PSA_WANT_ALG_DETERMINISTIC_ECDSA */
+
+#if defined(PSA_WANT_ALG_ECDH)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH)
+#define MBEDTLS_PSA_BUILTIN_ALG_ECDH                    1
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_BIGNUM_C
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDH */
+#endif /* PSA_WANT_ALG_ECDH */
+
+#if defined(PSA_WANT_ALG_ECDSA)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA)
+#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA                   1
+#define MBEDTLS_ECDSA_C
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDSA */
+#endif /* PSA_WANT_ALG_ECDSA */
+
+#if defined(PSA_WANT_ALG_HKDF)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF)
+#define MBEDTLS_PSA_BUILTIN_ALG_HMAC                    1
+#define MBEDTLS_PSA_BUILTIN_ALG_HKDF                    1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */
+#endif /* PSA_WANT_ALG_HKDF */
+
+#if defined(PSA_WANT_ALG_HMAC)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC)
+#define MBEDTLS_PSA_BUILTIN_ALG_HMAC                    1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */
+#endif /* PSA_WANT_ALG_HMAC */
+
+#if defined(PSA_WANT_ALG_RSA_OAEP)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP)
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP                1
+#define MBEDTLS_RSA_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PKCS1_V21
+#define MBEDTLS_MD_C
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP */
+#endif /* PSA_WANT_ALG_RSA_OAEP */
+
+#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT)
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT      1
+#define MBEDTLS_RSA_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PKCS1_V15
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT */
+#endif /* PSA_WANT_ALG_RSA_PKCS1V15_CRYPT */
+
+#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN)
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN       1
+#define MBEDTLS_RSA_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PKCS1_V15
+#define MBEDTLS_MD_C
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN */
+#endif /* PSA_WANT_ALG_RSA_PKCS1V15_SIGN */
+
+#if defined(PSA_WANT_ALG_RSA_PSS)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS)
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS                 1
+#define MBEDTLS_RSA_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PKCS1_V21
+#define MBEDTLS_MD_C
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PSS */
+#endif /* PSA_WANT_ALG_RSA_PSS */
+
+#if defined(PSA_WANT_ALG_TLS12_PRF)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF)
+#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF               1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF */
+#endif /* PSA_WANT_ALG_TLS12_PRF */
+
+#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS)
+#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS         1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS */
+#endif /* PSA_WANT_ALG_TLS12_PSK_TO_MS */
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR       1
+#define MBEDTLS_ECP_C
+#define MBEDTLS_BIGNUM_C
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR */
+#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR */
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY     1
+#define MBEDTLS_ECP_C
+#define MBEDTLS_BIGNUM_C
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
+#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR       1
+#define MBEDTLS_RSA_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_GENPRIME
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PK_WRITE_C
+#define MBEDTLS_PK_C
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR */
+#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY     1
+#define MBEDTLS_RSA_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PK_WRITE_C
+#define MBEDTLS_PK_C
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY */
+#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */
+
+#else /* MBEDTLS_PSA_CRYPTO_CONFIG */
+
+/*
+ * Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG
+ * is not defined
+ */
+#if defined(MBEDTLS_ECDH_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_ECDH                    1
+#endif /* MBEDTLS_ECDH_C */
+
+#if defined(MBEDTLS_ECDSA_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA                   1
+
+// Only add in DETERMINISTIC support if ECDSA is also enabled
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA     1
+#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
+
+#endif /* MBEDTLS_ECDSA_C */
+
+#if defined(MBEDTLS_ECP_C)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR       1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY     1
+#endif /* MBEDTLS_ECP_C */
+
+#if defined(MBEDTLS_HKDF_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_HMAC                    1
+#define MBEDTLS_PSA_BUILTIN_ALG_HKDF                    1
+#endif /* MBEDTLS_HKDF_C */
+
+#if defined(MBEDTLS_MD_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_HMAC                    1
+#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF               1
+#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS         1
+#endif /* MBEDTLS_MD_C */
+
+#if defined(MBEDTLS_RSA_C)
+#if defined(MBEDTLS_PKCS1_V15)
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT      1
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN       1
+#endif /* MBEDTLSS_PKCS1_V15 */
+#if defined(MBEDTLS_PKCS1_V21)
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP                1
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS                 1
+#endif /* MBEDTLS_PKCS1_V21 */
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR       1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY     1
+#endif /* MBEDTLS_RSA_C */
+
+#endif /* MBEDTLS_PSA_CRYPTO_CONFIG */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_CONFIG_PSA_H */
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index 22fab13..7d0f977 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -331,12 +331,13 @@
  *
  * \return          \c 0 on success.
  * \return          #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input
- *                  (context already used, invalid key handle).
+ *                  (context already used, invalid key identifier).
  * \return          #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an
  *                  ECC key pair.
  * \return          #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure.
  */
-int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, const psa_key_handle_t key );
+int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx,
+                             const psa_key_id_t key );
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
@@ -858,9 +859,9 @@
  *
  * \param pk        Input: the EC key to import to a PSA key.
  *                  Output: a PK context wrapping that PSA key.
- * \param handle    Output: a PSA key handle.
+ * \param key       Output: a PSA key identifier.
  *                  It's the caller's responsibility to call
- *                  psa_destroy_key() on that handle after calling
+ *                  psa_destroy_key() on that key identifier after calling
  *                  mbedtls_pk_free() on the PK context.
  * \param hash_alg  The hash algorithm to allow for use with that key.
  *
@@ -868,7 +869,7 @@
  * \return          An Mbed TLS error code otherwise.
  */
 int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk,
-                               psa_key_handle_t *handle,
+                               psa_key_id_t *key,
                                psa_algorithm_t hash_alg );
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
diff --git a/include/mbedtls/sha512.h b/include/mbedtls/sha512.h
index 9036ed4..4a8ab42 100644
--- a/include/mbedtls/sha512.h
+++ b/include/mbedtls/sha512.h
@@ -131,8 +131,7 @@
 
 /**
  * \brief          This function finishes the SHA-512 operation, and writes
- *                 the result to the output buffer. This function is for
- *                 internal use only.
+ *                 the result to the output buffer.
  *
  * \param ctx      The SHA-512 context. This must be initialized
  *                 and have a hash operation started.
@@ -148,6 +147,7 @@
 /**
  * \brief          This function processes a single data block within
  *                 the ongoing SHA-512 computation.
+ *                 This function is for internal use only.
  *
  * \param ctx      The SHA-512 context. This must be initialized.
  * \param data     The buffer holding one block of data. This
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index a091261..7815ad9 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -42,7 +42,12 @@
 #include "mbedtls/dhm.h"
 #endif
 
-#if defined(MBEDTLS_ECDH_C)
+/* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due
+ * to guards also being in ssl_srv.c and ssl_cli.c. There is a gap
+ * in functionality that access to ecdh_ctx structure is needed for
+ * MBEDTLS_ECDSA_C which does not seem correct.
+ */
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
 #include "mbedtls/ecdh.h"
 #endif
 
@@ -214,6 +219,9 @@
 #define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED       1
 #define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED      0
 
+#define MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED    0
+#define MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED      1
+
 /*
  * Default range for DTLS retransmission timer value, in milliseconds.
  * RFC 6347 4.2.4.1 says from 1 second to 60 seconds.
@@ -393,6 +401,8 @@
 
 #define MBEDTLS_TLS_EXT_SIG_ALG                     13
 
+#define MBEDTLS_TLS_EXT_USE_SRTP                    14
+
 #define MBEDTLS_TLS_EXT_ALPN                        16
 
 #define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC            22 /* 0x16 */
@@ -851,6 +861,41 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED &&
           !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+
+#define MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH             255
+#define MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH    4
+/*
+ * For code readability use a typedef for DTLS-SRTP profiles
+ *
+ * Use_srtp extension protection profiles values as defined in
+ * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml
+ *
+ * Reminder: if this list is expanded mbedtls_ssl_check_srtp_profile_value
+ * must be updated too.
+ */
+#define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80     ( (uint16_t) 0x0001)
+#define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32     ( (uint16_t) 0x0002)
+#define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80          ( (uint16_t) 0x0005)
+#define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32          ( (uint16_t) 0x0006)
+/* This one is not iana defined, but for code readability. */
+#define MBEDTLS_TLS_SRTP_UNSET                      ( (uint16_t) 0x0000)
+
+typedef uint16_t mbedtls_ssl_srtp_profile;
+
+typedef struct mbedtls_dtls_srtp_info_t
+{
+    /*! The SRTP profile that was negotiated. */
+    mbedtls_ssl_srtp_profile chosen_dtls_srtp_profile;
+    /*! The length of mki_value. */
+    uint16_t mki_len;
+    /*! The mki_value used, with max size of 256 bytes. */
+    unsigned char mki_value[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH];
+}
+mbedtls_dtls_srtp_info;
+
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
 /*
  * This structure is used for storing current session data.
  *
@@ -1023,11 +1068,12 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_key_handle_t psk_opaque; /*!< PSA key slot holding opaque PSK.
-                                  *   This field should only be set via
-                                  *   mbedtls_ssl_conf_psk_opaque().
-                                  *   If either no PSK or a raw PSK have
-                                  *   been configured, this has value \c 0. */
+    psa_key_id_t psk_opaque; /*!< PSA key slot holding opaque PSK. This field
+                              *   should only be set via
+                              *   mbedtls_ssl_conf_psk_opaque().
+                              *   If either no PSK or a raw PSK have been
+                              *   configured, this has value \c 0.
+                              */
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
     unsigned char *psk;      /*!< The raw pre-shared key. This field should
@@ -1057,6 +1103,13 @@
     const char **alpn_list;         /*!< ordered list of protocols          */
 #endif
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    /*! ordered list of supported srtp profile */
+    const mbedtls_ssl_srtp_profile *dtls_srtp_profile_list;
+    /*! number of supported profiles */
+    size_t dtls_srtp_profile_list_len;
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
     /*
      * Numerical settings (int then char)
      */
@@ -1137,9 +1190,12 @@
                                              *   record with unexpected CID
                                              *   should lead to failure.    */
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    unsigned int dtls_srtp_mki_support : 1; /* support having mki_value
+                                               in the use_srtp extension     */
+#endif
 };
 
-
 struct mbedtls_ssl_context
 {
     const mbedtls_ssl_config *conf; /*!< configuration information          */
@@ -1298,6 +1354,13 @@
     const char *alpn_chosen;    /*!<  negotiated protocol                   */
 #endif /* MBEDTLS_SSL_ALPN */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    /*
+     * use_srtp extension
+     */
+    mbedtls_dtls_srtp_info dtls_srtp_info;
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
     /*
      * Information for DTLS hello verify
      */
@@ -2032,6 +2095,8 @@
  *                  (Default: none.)
  *
  * \note            See \c mbedtls_ssl_export_keys_ext_t.
+ * \warning         Exported key material must not be used for any purpose
+ *                  before the (D)TLS handshake is completed
  *
  * \param conf      SSL configuration context
  * \param f_export_keys_ext Callback for exporting keys
@@ -2755,7 +2820,7 @@
  * \return         An \c MBEDTLS_ERR_SSL_XXX error code on failure.
  */
 int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf,
-                                 psa_key_handle_t psk,
+                                 psa_key_id_t psk,
                                  const unsigned char *psk_identity,
                                  size_t psk_identity_len );
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
@@ -2801,7 +2866,7 @@
  * \return         An \c MBEDTLS_ERR_SSL_XXX error code on failure.
  */
 int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl,
-                                   psa_key_handle_t psk );
+                                   psa_key_id_t psk );
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 /**
@@ -3120,6 +3185,105 @@
 const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl );
 #endif /* MBEDTLS_SSL_ALPN */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+#if defined(MBEDTLS_DEBUG_C)
+static inline const char *mbedtls_ssl_get_srtp_profile_as_string( mbedtls_ssl_srtp_profile profile )
+{
+    switch( profile )
+    {
+        case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80:
+            return( "MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80" );
+        case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32:
+            return( "MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32" );
+        case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80:
+            return( "MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80" );
+        case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32:
+            return( "MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32" );
+        default: break;
+    }
+    return( "" );
+}
+#endif /* MBEDTLS_DEBUG_C */
+/**
+ * \brief                   Manage support for mki(master key id) value
+ *                          in use_srtp extension.
+ *                          MKI is an optional part of SRTP used for key management
+ *                          and re-keying. See RFC3711 section 3.1 for details.
+ *                          The default value is
+ *                          #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED.
+ *
+ * \param conf              The SSL configuration to manage mki support.
+ * \param support_mki_value Enable or disable mki usage. Values are
+ *                          #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED
+ *                          or #MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED.
+ */
+void mbedtls_ssl_conf_srtp_mki_value_supported( mbedtls_ssl_config *conf,
+                                                int support_mki_value );
+
+/**
+ * \brief                   Set the supported DTLS-SRTP protection profiles.
+ *
+ * \param conf              SSL configuration
+ * \param profiles          Pointer to a List of MBEDTLS_TLS_SRTP_UNSET terminated
+ *                          supported protection profiles
+ *                          in decreasing preference order.
+ *                          The pointer to the list is recorded by the library
+ *                          for later reference as required, so the lifetime
+ *                          of the table must be at least as long as the lifetime
+ *                          of the SSL configuration structure.
+ *                          The list must not hold more than
+ *                          MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH elements
+ *                          (excluding the terminating MBEDTLS_TLS_SRTP_UNSET).
+ *
+ * \return                  0 on success
+ * \return                  #MBEDTLS_ERR_SSL_BAD_INPUT_DATA when the list of
+ *                          protection profiles is incorrect.
+ */
+int mbedtls_ssl_conf_dtls_srtp_protection_profiles
+                               ( mbedtls_ssl_config *conf,
+                                 const mbedtls_ssl_srtp_profile *profiles );
+
+/**
+ * \brief                  Set the mki_value for the current DTLS-SRTP session.
+ *
+ * \param ssl              SSL context to use.
+ * \param mki_value        The MKI value to set.
+ * \param mki_len          The length of the MKI value.
+ *
+ * \note                   This function is relevant on client side only.
+ *                         The server discovers the mki value during handshake.
+ *                         A mki value set on server side using this function
+ *                         is ignored.
+ *
+ * \return                 0 on success
+ * \return                 #MBEDTLS_ERR_SSL_BAD_INPUT_DATA
+ * \return                 #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE
+ */
+int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl,
+                                         unsigned char *mki_value,
+                                         uint16_t mki_len );
+/**
+ * \brief                  Get the negotiated DTLS-SRTP informations:
+ *                         Protection profile and MKI value.
+ *
+ * \warning                This function must be called after the handshake is
+ *                         completed. The value returned by this function must
+ *                         not be trusted or acted upon before the handshake completes.
+ *
+ * \param ssl              The SSL context to query.
+ * \param dtls_srtp_info   The negotiated DTLS-SRTP informations:
+ *                         - Protection profile in use.
+ *                         A direct mapping of the iana defined value for protection
+ *                         profile on an uint16_t.
+                   http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml
+ *                         #MBEDTLS_TLS_SRTP_UNSET if the use of SRTP was not negotiated
+ *                         or peer's Hello packet was not parsed yet.
+ *                         - mki size and value( if size is > 0 ).
+ */
+void mbedtls_ssl_get_dtls_srtp_negotiation_result( const mbedtls_ssl_context *ssl,
+                                                   mbedtls_dtls_srtp_info *dtls_srtp_info );
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
 /**
  * \brief          Set the maximum supported version sent from the client side
  *                 and/or accepted at the server side
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index 7b78c73..577c959 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -437,17 +437,22 @@
 #if defined(MBEDTLS_DHM_C)
     mbedtls_dhm_context dhm_ctx;                /*!<  DHM key exchange        */
 #endif
-#if defined(MBEDTLS_ECDH_C)
+/* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due
+ * to guards also being in ssl_srv.c and ssl_cli.c. There is a gap
+ * in functionality that access to ecdh_ctx structure is needed for
+ * MBEDTLS_ECDSA_C which does not seem correct.
+ */
+#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
     mbedtls_ecdh_context ecdh_ctx;              /*!<  ECDH key exchange       */
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_key_type_t ecdh_psa_type;
     uint16_t ecdh_bits;
-    psa_key_handle_t ecdh_psa_privkey;
+    psa_key_id_t ecdh_psa_privkey;
     unsigned char ecdh_psa_peerkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
     size_t ecdh_psa_peerkey_len;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
-#endif /* MBEDTLS_ECDH_C */
+#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
     mbedtls_ecjpake_context ecjpake_ctx;        /*!< EC J-PAKE key exchange */
@@ -462,7 +467,7 @@
 #endif
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_key_handle_t psk_opaque;        /*!< Opaque PSK from the callback   */
+    psa_key_id_t psk_opaque;            /*!< Opaque PSK from the callback   */
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
     unsigned char *psk;                 /*!<  PSK from the callback         */
     size_t psk_len;                     /*!<  Length of PSK from callback   */
@@ -1061,16 +1066,16 @@
  * 2. static PSK configured by \c mbedtls_ssl_conf_psk_opaque()
  * Return an opaque PSK
  */
-static inline psa_key_handle_t mbedtls_ssl_get_opaque_psk(
+static inline psa_key_id_t mbedtls_ssl_get_opaque_psk(
     const mbedtls_ssl_context *ssl )
 {
-    if( ssl->handshake->psk_opaque != 0 )
+    if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) )
         return( ssl->handshake->psk_opaque );
 
-    if( ssl->conf->psk_opaque != 0 )
+    if( ! mbedtls_svc_key_id_is_null( ssl->conf->psk_opaque ) )
         return( ssl->conf->psk_opaque );
 
-    return( 0 );
+    return( MBEDTLS_SVC_KEY_ID_INIT );
 }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
@@ -1095,6 +1100,23 @@
                                 mbedtls_md_type_t md );
 #endif
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+static inline mbedtls_ssl_srtp_profile mbedtls_ssl_check_srtp_profile_value
+                                                    ( const uint16_t srtp_profile_value )
+{
+    switch( srtp_profile_value )
+    {
+        case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80:
+        case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32:
+        case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80:
+        case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32:
+            return srtp_profile_value;
+        default: break;
+    }
+    return( MBEDTLS_TLS_SRTP_UNSET );
+}
+#endif
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 static inline mbedtls_pk_context *mbedtls_ssl_own_key( mbedtls_ssl_context *ssl )
 {
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index 5ba16b9..b41a20b 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -36,16 +36,6 @@
  * @{
  */
 
-/** \brief Key handle.
- *
- * This type represents open handles to keys. It must be an unsigned integral
- * type. The choice of type is implementation-dependent.
- *
- * 0 is not a valid key handle. How other handle values are assigned is
- * implementation-dependent.
- */
-typedef _unsigned_integral_type_ psa_key_handle_t;
-
 /**@}*/
 #endif /* __DOXYGEN_ONLY__ */
 
@@ -152,6 +142,25 @@
 static void psa_set_key_id( psa_key_attributes_t *attributes,
                             mbedtls_svc_key_id_t key );
 
+#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
+/** Set the owner identifier of a key.
+ *
+ * When key identifiers encode key owner identifiers, psa_set_key_id() does
+ * not allow to define in key attributes the owner of volatile keys as
+ * psa_set_key_id() enforces the key to be persistent.
+ *
+ * This function allows to set in key attributes the owner identifier of a
+ * key. It is intended to be used for volatile keys. For persistent keys,
+ * it is recommended to use the PSA Cryptography API psa_set_key_id() to define
+ * the owner of a key.
+ *
+ * \param[out] attributes  The attribute structure to write to.
+ * \param owner_id         The key owner identifier.
+ */
+static void mbedtls_set_key_owner_id( psa_key_attributes_t *attributes,
+                                      mbedtls_key_owner_id_t owner_id );
+#endif
+
 /** Set the location of a persistent key.
  *
  * To make a key persistent, you must give it a persistent key identifier
@@ -348,7 +357,7 @@
  *       Once you have called this function on an attribute structure,
  *       you must call psa_reset_key_attributes() to free these resources.
  *
- * \param[in] handle            Handle to the key to query.
+ * \param[in] key               Identifier of the key to query.
  * \param[in,out] attributes    On success, the attributes of the key.
  *                              On failure, equivalent to a
  *                              freshly-initialized structure.
@@ -364,7 +373,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_get_key_attributes(psa_key_handle_t handle,
+psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key,
                                     psa_key_attributes_t *attributes);
 
 /** Reset a key attribute structure to a freshly initialized state.
@@ -387,93 +396,28 @@
  * @{
  */
 
-/** Open a handle to an existing persistent key.
+/** Remove non-essential copies of key material from memory.
  *
- * Open a handle to a persistent key. A key is persistent if it was created
- * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key
- * always has a nonzero key identifier, set with psa_set_key_id() when
- * creating the key. Implementations may provide additional pre-provisioned
- * keys that can be opened with psa_open_key(). Such keys have an application
- * key identifier in the vendor range, as documented in the description of
- * #psa_key_id_t.
+ * If the key identifier designates a volatile key, this functions does not do
+ * anything and returns successfully.
  *
- * The application must eventually close the handle with psa_close_key() or
- * psa_destroy_key() to release associated resources. If the application dies
- * without calling one of these functions, the implementation should perform
- * the equivalent of a call to psa_close_key().
+ * If the key identifier designates a persistent key, then this function will
+ * free all resources associated with the key in volatile memory. The key
+ * data in persistent storage is not affected and the key can still be used.
  *
- * Some implementations permit an application to open the same key multiple
- * times. If this is successful, each call to psa_open_key() will return a
- * different key handle.
- *
- * \note Applications that rely on opening a key multiple times will not be
- * portable to implementations that only permit a single key handle to be
- * opened. See also :ref:\`key-handles\`.
- *
- * \param key           The persistent identifier of the key.
- * \param[out] handle   On success, a handle to the key.
+ * \param key Identifier of the key to purge.
  *
  * \retval #PSA_SUCCESS
- *         Success. The application can now use the value of `*handle`
- *         to access the key.
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
- *         The implementation does not have sufficient resources to open the
- *         key. This can be due to reaching an implementation limit on the
- *         number of open keys, the number of open key handles, or available
- *         memory.
- * \retval #PSA_ERROR_DOES_NOT_EXIST
- *         There is no persistent key with key identifier \p id.
+ *         The key material will have been removed from memory if it is not
+ *         currently required.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p id is not a valid persistent key identifier.
- * \retval #PSA_ERROR_NOT_PERMITTED
- *         The specified key exists, but the application does not have the
- *         permission to access it. Note that this specification does not
- *         define any way to create such a key, but it may be possible
- *         through implementation-specific means.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_STORAGE_FAILURE
+ *         \p key is not a valid key identifier.
  * \retval #PSA_ERROR_BAD_STATE
  *         The library has not been previously initialized by psa_crypto_init().
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_open_key( mbedtls_svc_key_id_t key,
-                           psa_key_handle_t *handle );
-
-/** Close a key handle.
- *
- * If the handle designates a volatile key, this will destroy the key material
- * and free all associated resources, just like psa_destroy_key().
- *
- * If this is the last open handle to a persistent key, then closing the handle
- * will free all resources associated with the key in volatile memory. The key
- * data in persistent storage is not affected and can be opened again later
- * with a call to psa_open_key().
- *
- * Closing the key handle makes the handle invalid, and the key handle
- * must not be used again by the application.
- *
- * \note If the key handle was used to set up an active
- * :ref:\`multipart operation <multipart-operations>\`, then closing the
- * key handle can cause the multipart operation to fail. Applications should
- * maintain the key handle until after the multipart operation has finished.
- *
- * \param handle        The key handle to close.
- *                      If this is \c 0, do nothing and return \c PSA_SUCCESS.
- *
- * \retval #PSA_SUCCESS
- *         \p handle was a valid handle or \c 0. It is now closed.
- * \retval #PSA_ERROR_INVALID_HANDLE
- *         \p handle is not a valid handle nor \c 0.
- * \retval #PSA_ERROR_COMMUNICATION_FAILURE
- * \retval #PSA_ERROR_CORRUPTION_DETECTED
- * \retval #PSA_ERROR_BAD_STATE
- *         The library has not been previously initialized by psa_crypto_init().
- *         It is implementation-dependent whether a failure to initialize
- *         results in this error code.
- */
-psa_status_t psa_close_key(psa_key_handle_t handle);
+psa_status_t psa_purge_key(mbedtls_svc_key_id_t key);
 
 /** Make a copy of a key.
  *
@@ -512,7 +456,10 @@
  * The effect of this function on implementation-defined attributes is
  * implementation-defined.
  *
- * \param source_handle     The key to copy. It must be a valid key handle.
+ * \param source_key        The key to copy. It must allow the usage
+ *                          #PSA_KEY_USAGE_COPY. If a private or secret key is
+ *                          being copied outside of a secure element it must
+ *                          also allow #PSA_KEY_USAGE_EXPORT.
  * \param[in] attributes    The attributes for the new key.
  *                          They are used as follows:
  *                          - The key type and size may be 0. If either is
@@ -526,12 +473,14 @@
  *                            the source key and \p attributes so that
  *                            both sets of restrictions apply, as
  *                            described in the documentation of this function.
- * \param[out] target_handle On success, a handle to the newly created key.
+ * \param[out] target_key   On success, an identifier for the newly created
+ *                          key. For persistent keys, this is the key
+ *                          identifier defined in \p attributes.
  *                          \c 0 on failure.
  *
  * \retval #PSA_SUCCESS
  * \retval #PSA_ERROR_INVALID_HANDLE
- *         \p source_handle is invalid.
+ *         \p source_key is invalid.
  * \retval #PSA_ERROR_ALREADY_EXISTS
  *         This is an attempt to create a persistent key, and there is
  *         already a persistent key with the given identifier.
@@ -559,9 +508,9 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_copy_key(psa_key_handle_t source_handle,
+psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key,
                           const psa_key_attributes_t *attributes,
-                          psa_key_handle_t *target_handle);
+                          mbedtls_svc_key_id_t *target_key);
 
 
 /**
@@ -572,28 +521,22 @@
  * make a best effort to ensure that that the key material cannot be recovered.
  *
  * This function also erases any metadata such as policies and frees
- * resources associated with the key. To free all resources associated with
- * the key, all handles to the key must be closed or destroyed.
- *
- * Destroying the key makes the handle invalid, and the key handle
- * must not be used again by the application. Using other open handles to the
- * destroyed key in a cryptographic operation will result in an error.
+ * resources associated with the key.
  *
  * If a key is currently in use in a multipart operation, then destroying the
  * key will cause the multipart operation to fail.
  *
- * \param handle        Handle to the key to erase.
- *                      If this is \c 0, do nothing and return \c PSA_SUCCESS.
+ * \param key  Identifier of the key to erase. If this is \c 0, do nothing and
+ *             return #PSA_SUCCESS.
  *
  * \retval #PSA_SUCCESS
- *         \p handle was a valid handle and the key material that it
- *         referred to has been erased.
- *         Alternatively, \p handle is \c 0.
+ *         \p key was a valid identifier and the key material that it
+ *         referred to has been erased. Alternatively, \p key is \c 0.
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         The key cannot be erased because it is
  *         read-only, either due to a policy or due to physical restrictions.
  * \retval #PSA_ERROR_INVALID_HANDLE
- *         \p handle is not a valid handle nor \c 0.
+ *         \p key is not a valid identifier nor \c 0.
  * \retval #PSA_ERROR_COMMUNICATION_FAILURE
  *         There was an failure in communication with the cryptoprocessor.
  *         The key material may still be present in the cryptoprocessor.
@@ -611,7 +554,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_destroy_key(psa_key_handle_t handle);
+psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key);
 
 /**@}*/
 
@@ -646,7 +589,9 @@
  *                          \p data buffer.
  *                          If the key size in \p attributes is nonzero,
  *                          it must be equal to the size from \p data.
- * \param[out] handle       On success, a handle to the newly created key.
+ * \param[out] key          On success, an identifier to the newly created key.
+ *                          For persistent keys, this is the key identifier
+ *                          defined in \p attributes.
  *                          \c 0 on failure.
  * \param[in] data    Buffer containing the key data. The content of this
  *                    buffer is interpreted according to the type declared
@@ -691,7 +636,7 @@
 psa_status_t psa_import_key(const psa_key_attributes_t *attributes,
                             const uint8_t *data,
                             size_t data_length,
-                            psa_key_handle_t *handle);
+                            mbedtls_svc_key_id_t *key);
 
 
 
@@ -752,7 +697,9 @@
  *
  * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set.
  *
- * \param handle            Handle to the key to export.
+ * \param key               Identifier of the key to export. It must allow the
+ *                          usage #PSA_KEY_USAGE_EXPORT, unless it is a public
+ *                          key.
  * \param[out] data         Buffer where the key data is to be written.
  * \param data_size         Size of the \p data buffer in bytes.
  * \param[out] data_length  On success, the number of bytes
@@ -779,7 +726,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_export_key(psa_key_handle_t handle,
+psa_status_t psa_export_key(mbedtls_svc_key_id_t key,
                             uint8_t *data,
                             size_t data_size,
                             size_t *data_length);
@@ -822,7 +769,7 @@
  * Exporting a public key object or the public part of a key pair is
  * always permitted, regardless of the key's usage flags.
  *
- * \param handle            Handle to the key to export.
+ * \param key               Identifier of the key to export.
  * \param[out] data         Buffer where the key data is to be written.
  * \param data_size         Size of the \p data buffer in bytes.
  * \param[out] data_length  On success, the number of bytes
@@ -849,7 +796,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_export_public_key(psa_key_handle_t handle,
+psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key,
                                    uint8_t *data,
                                    size_t data_size,
                                    size_t *data_length);
@@ -1226,7 +1173,8 @@
  *       about the MAC value which could allow an attacker to guess
  *       a valid MAC and thereby bypass security controls.
  *
- * \param handle            Handle to the key to use for the operation.
+ * \param key               Identifier of the key to use for the operation. It
+ *                          must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE.
  * \param alg               The MAC algorithm to compute (\c PSA_ALG_XXX value
  *                          such that #PSA_ALG_IS_MAC(\p alg) is true).
  * \param[in] input         Buffer containing the input message.
@@ -1241,7 +1189,7 @@
  * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p handle is not compatible with \p alg.
+ *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a MAC algorithm.
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
@@ -1257,7 +1205,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_mac_compute(psa_key_handle_t handle,
+psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key,
                              psa_algorithm_t alg,
                              const uint8_t *input,
                              size_t input_length,
@@ -1267,7 +1215,8 @@
 
 /** Calculate the MAC of a message and compare it with a reference value.
  *
- * \param handle            Handle to the key to use for the operation.
+ * \param key               Identifier of the key to use for the operation. It
+ *                          must allow the usage PSA_KEY_USAGE_VERIFY_MESSAGE.
  * \param alg               The MAC algorithm to compute (\c PSA_ALG_XXX value
  *                          such that #PSA_ALG_IS_MAC(\p alg) is true).
  * \param[in] input         Buffer containing the input message.
@@ -1283,7 +1232,7 @@
  * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p handle is not compatible with \p alg.
+ *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a MAC algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -1297,7 +1246,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_mac_verify(psa_key_handle_t handle,
+psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key,
                             psa_algorithm_t alg,
                             const uint8_t *input,
                             size_t input_length,
@@ -1382,9 +1331,9 @@
  * \param[in,out] operation The operation object to set up. It must have
  *                          been initialized as per the documentation for
  *                          #psa_mac_operation_t and not yet in use.
- * \param handle            Handle to the key to use for the operation.
- *                          It must remain valid until the operation
- *                          terminates.
+ * \param key               Identifier of the key to use for the operation. It
+ *                          must remain valid until the operation terminates.
+ *                          It must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE.
  * \param alg               The MAC algorithm to compute (\c PSA_ALG_XXX value
  *                          such that #PSA_ALG_IS_MAC(\p alg) is true).
  *
@@ -1393,7 +1342,7 @@
  * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p handle is not compatible with \p alg.
+ *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a MAC algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -1410,7 +1359,7 @@
  *         results in this error code.
  */
 psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,
-                                psa_key_handle_t handle,
+                                mbedtls_svc_key_id_t key,
                                 psa_algorithm_t alg);
 
 /** Set up a multipart MAC verification operation.
@@ -1444,9 +1393,10 @@
  * \param[in,out] operation The operation object to set up. It must have
  *                          been initialized as per the documentation for
  *                          #psa_mac_operation_t and not yet in use.
- * \param handle            Handle to the key to use for the operation.
- *                          It must remain valid until the operation
- *                          terminates.
+ * \param key               Identifier of the key to use for the operation. It
+ *                          must remain valid until the operation terminates.
+ *                          It must allow the usage
+ *                          PSA_KEY_USAGE_VERIFY_MESSAGE.
  * \param alg               The MAC algorithm to compute (\c PSA_ALG_XXX value
  *                          such that #PSA_ALG_IS_MAC(\p alg) is true).
  *
@@ -1472,7 +1422,7 @@
  *         results in this error code.
  */
 psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,
-                                  psa_key_handle_t handle,
+                                  mbedtls_svc_key_id_t key,
                                   psa_algorithm_t alg);
 
 /** Add a message fragment to a multipart MAC operation.
@@ -1639,9 +1589,8 @@
  * vector). Use the multipart operation interface with a
  * #psa_cipher_operation_t object to provide other forms of IV.
  *
- * \param handle                Handle to the key to use for the operation.
- *                              It must remain valid until the operation
- *                              terminates.
+ * \param key                   Identifier of the key to use for the operation.
+ *                              It must allow the usage #PSA_KEY_USAGE_ENCRYPT.
  * \param alg                   The cipher algorithm to compute
  *                              (\c PSA_ALG_XXX value such that
  *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
@@ -1659,7 +1608,7 @@
  * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p handle is not compatible with \p alg.
+ *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a cipher algorithm.
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
@@ -1673,7 +1622,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_cipher_encrypt(psa_key_handle_t handle,
+psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key,
                                 psa_algorithm_t alg,
                                 const uint8_t *input,
                                 size_t input_length,
@@ -1685,9 +1634,10 @@
  *
  * This function decrypts a message encrypted with a symmetric cipher.
  *
- * \param handle                Handle to the key to use for the operation.
+ * \param key                   Identifier of the key to use for the operation.
  *                              It must remain valid until the operation
- *                              terminates.
+ *                              terminates. It must allow the usage
+ *                              #PSA_KEY_USAGE_DECRYPT.
  * \param alg                   The cipher algorithm to compute
  *                              (\c PSA_ALG_XXX value such that
  *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
@@ -1705,7 +1655,7 @@
  * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p handle is not compatible with \p alg.
+ *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a cipher algorithm.
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
@@ -1719,7 +1669,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_cipher_decrypt(psa_key_handle_t handle,
+psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key,
                                 psa_algorithm_t alg,
                                 const uint8_t *input,
                                 size_t input_length,
@@ -1805,9 +1755,10 @@
  * \param[in,out] operation     The operation object to set up. It must have
  *                              been initialized as per the documentation for
  *                              #psa_cipher_operation_t and not yet in use.
- * \param handle                Handle to the key to use for the operation.
+ * \param key                   Identifier of the key to use for the operation.
  *                              It must remain valid until the operation
- *                              terminates.
+ *                              terminates. It must allow the usage
+ *                              #PSA_KEY_USAGE_ENCRYPT.
  * \param alg                   The cipher algorithm to compute
  *                              (\c PSA_ALG_XXX value such that
  *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
@@ -1817,7 +1768,7 @@
  * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p handle is not compatible with \p alg.
+ *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a cipher algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -1833,7 +1784,7 @@
  *         results in this error code.
  */
 psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
-                                      psa_key_handle_t handle,
+                                      mbedtls_svc_key_id_t key,
                                       psa_algorithm_t alg);
 
 /** Set the key for a multipart symmetric decryption operation.
@@ -1868,9 +1819,10 @@
  * \param[in,out] operation     The operation object to set up. It must have
  *                              been initialized as per the documentation for
  *                              #psa_cipher_operation_t and not yet in use.
- * \param handle                Handle to the key to use for the operation.
+ * \param key                   Identifier of the key to use for the operation.
  *                              It must remain valid until the operation
- *                              terminates.
+ *                              terminates. It must allow the usage
+ *                              #PSA_KEY_USAGE_DECRYPT.
  * \param alg                   The cipher algorithm to compute
  *                              (\c PSA_ALG_XXX value such that
  *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
@@ -1880,7 +1832,7 @@
  * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p handle is not compatible with \p alg.
+ *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not a cipher algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -1896,7 +1848,7 @@
  *         results in this error code.
  */
 psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,
-                                      psa_key_handle_t handle,
+                                      mbedtls_svc_key_id_t key,
                                       psa_algorithm_t alg);
 
 /** Generate an IV for a symmetric encryption operation.
@@ -2110,7 +2062,9 @@
 
 /** Process an authenticated encryption operation.
  *
- * \param handle                  Handle to the key to use for the operation.
+ * \param key                     Identifier of the key to use for the
+ *                                operation. It must allow the usage
+ *                                #PSA_KEY_USAGE_ENCRYPT.
  * \param alg                     The AEAD algorithm to compute
  *                                (\c PSA_ALG_XXX value such that
  *                                #PSA_ALG_IS_AEAD(\p alg) is true).
@@ -2141,7 +2095,7 @@
  * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p handle is not compatible with \p alg.
+ *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not an AEAD algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -2156,7 +2110,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_aead_encrypt(psa_key_handle_t handle,
+psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key,
                               psa_algorithm_t alg,
                               const uint8_t *nonce,
                               size_t nonce_length,
@@ -2170,7 +2124,9 @@
 
 /** Process an authenticated decryption operation.
  *
- * \param handle                  Handle to the key to use for the operation.
+ * \param key                     Identifier of the key to use for the
+ *                                operation. It must allow the usage
+ *                                #PSA_KEY_USAGE_DECRYPT.
  * \param alg                     The AEAD algorithm to compute
  *                                (\c PSA_ALG_XXX value such that
  *                                #PSA_ALG_IS_AEAD(\p alg) is true).
@@ -2201,7 +2157,7 @@
  *         The ciphertext is not authentic.
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p handle is not compatible with \p alg.
+ *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not an AEAD algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -2216,7 +2172,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_aead_decrypt(psa_key_handle_t handle,
+psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key,
                               psa_algorithm_t alg,
                               const uint8_t *nonce,
                               size_t nonce_length,
@@ -2312,9 +2268,10 @@
  * \param[in,out] operation     The operation object to set up. It must have
  *                              been initialized as per the documentation for
  *                              #psa_aead_operation_t and not yet in use.
- * \param handle                Handle to the key to use for the operation.
+ * \param key                   Identifier of the key to use for the operation.
  *                              It must remain valid until the operation
- *                              terminates.
+ *                              terminates. It must allow the usage
+ *                              #PSA_KEY_USAGE_ENCRYPT.
  * \param alg                   The AEAD algorithm to compute
  *                              (\c PSA_ALG_XXX value such that
  *                              #PSA_ALG_IS_AEAD(\p alg) is true).
@@ -2323,10 +2280,10 @@
  *         Success.
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be inactive).
-  * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p handle is not compatible with \p alg.
+ *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not an AEAD algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -2340,7 +2297,7 @@
  *         results in this error code.
  */
 psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation,
-                                    psa_key_handle_t handle,
+                                    mbedtls_svc_key_id_t key,
                                     psa_algorithm_t alg);
 
 /** Set the key for a multipart authenticated decryption operation.
@@ -2378,9 +2335,10 @@
  * \param[in,out] operation     The operation object to set up. It must have
  *                              been initialized as per the documentation for
  *                              #psa_aead_operation_t and not yet in use.
- * \param handle                Handle to the key to use for the operation.
+ * \param key                   Identifier of the key to use for the operation.
  *                              It must remain valid until the operation
- *                              terminates.
+ *                              terminates. It must allow the usage
+ *                              #PSA_KEY_USAGE_DECRYPT.
  * \param alg                   The AEAD algorithm to compute
  *                              (\c PSA_ALG_XXX value such that
  *                              #PSA_ALG_IS_AEAD(\p alg) is true).
@@ -2389,10 +2347,10 @@
  *         Success.
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be inactive).
-  * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_INVALID_HANDLE
  * \retval #PSA_ERROR_NOT_PERMITTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p handle is not compatible with \p alg.
+ *         \p key is not compatible with \p alg.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p alg is not supported or is not an AEAD algorithm.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -2406,7 +2364,7 @@
  *         results in this error code.
  */
 psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation,
-                                    psa_key_handle_t handle,
+                                    mbedtls_svc_key_id_t key,
                                     psa_algorithm_t alg);
 
 /** Generate a random nonce for an authenticated encryption operation.
@@ -2432,7 +2390,7 @@
  *         Success.
  * \retval #PSA_ERROR_BAD_STATE
  *         The operation state is not valid (it must be an active aead encrypt
-           operation, with no nonce set).
+ *         operation, with no nonce set).
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p nonce buffer is too small.
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -2864,10 +2822,11 @@
  * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg)
  * to determine the hash algorithm to use.
  *
- * \param handle                Handle to the key to use for the operation.
- *                              It must be an asymmetric key pair.
+ * \param key                   Identifier of the key to use for the operation.
+ *                              It must be an asymmetric key pair. The key must
+ *                              allow the usage #PSA_KEY_USAGE_SIGN_HASH.
  * \param alg                   A signature algorithm that is compatible with
- *                              the type of \p handle.
+ *                              the type of \p key.
  * \param[in] hash              The hash or message to sign.
  * \param hash_length           Size of the \p hash buffer in bytes.
  * \param[out] signature        Buffer where the signature is to be written.
@@ -2883,7 +2842,7 @@
  *         determine a sufficient buffer size by calling
  *         #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
  *         where \c key_type and \c key_bits are the type and bit-size
- *         respectively of \p handle.
+ *         respectively of \p key.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -2897,7 +2856,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_sign_hash(psa_key_handle_t handle,
+psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key,
                            psa_algorithm_t alg,
                            const uint8_t *hash,
                            size_t hash_length,
@@ -2914,10 +2873,12 @@
  * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg)
  * to determine the hash algorithm to use.
  *
- * \param handle            Handle to the key to use for the operation.
- *                          It must be a public key or an asymmetric key pair.
+ * \param key               Identifier of the key to use for the operation. It
+ *                          must be a public key or an asymmetric key pair. The
+ *                          key must allow the usage
+ *                          #PSA_KEY_USAGE_VERIFY_HASH.
  * \param alg               A signature algorithm that is compatible with
- *                          the type of \p handle.
+ *                          the type of \p key.
  * \param[in] hash          The hash or message whose signature is to be
  *                          verified.
  * \param hash_length       Size of the \p hash buffer in bytes.
@@ -2943,7 +2904,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_verify_hash(psa_key_handle_t handle,
+psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key,
                              psa_algorithm_t alg,
                              const uint8_t *hash,
                              size_t hash_length,
@@ -2953,11 +2914,12 @@
 /**
  * \brief Encrypt a short message with a public key.
  *
- * \param handle                Handle to the key to use for the operation.
- *                              It must be a public key or an asymmetric
- *                              key pair.
+ * \param key                   Identifer of the key to use for the operation.
+ *                              It must be a public key or an asymmetric key
+ *                              pair. It must allow the usage
+ *                              #PSA_KEY_USAGE_ENCRYPT.
  * \param alg                   An asymmetric encryption algorithm that is
- *                              compatible with the type of \p handle.
+ *                              compatible with the type of \p key.
  * \param[in] input             The message to encrypt.
  * \param input_length          Size of the \p input buffer in bytes.
  * \param[in] salt              A salt or label, if supported by the
@@ -2986,7 +2948,7 @@
  *         determine a sufficient buffer size by calling
  *         #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
  *         where \c key_type and \c key_bits are the type and bit-size
- *         respectively of \p handle.
+ *         respectively of \p key.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -3000,7 +2962,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle,
+psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key,
                                     psa_algorithm_t alg,
                                     const uint8_t *input,
                                     size_t input_length,
@@ -3013,10 +2975,11 @@
 /**
  * \brief Decrypt a short message with a private key.
  *
- * \param handle                Handle to the key to use for the operation.
- *                              It must be an asymmetric key pair.
+ * \param key                   Identifier of the key to use for the operation.
+ *                              It must be an asymmetric key pair. It must
+ *                              allow the usage #PSA_KEY_USAGE_DECRYPT.
  * \param alg                   An asymmetric encryption algorithm that is
- *                              compatible with the type of \p handle.
+ *                              compatible with the type of \p key.
  * \param[in] input             The message to decrypt.
  * \param input_length          Size of the \p input buffer in bytes.
  * \param[in] salt              A salt or label, if supported by the
@@ -3045,7 +3008,7 @@
  *         determine a sufficient buffer size by calling
  *         #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
  *         where \c key_type and \c key_bits are the type and bit-size
- *         respectively of \p handle.
+ *         respectively of \p key.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
@@ -3060,7 +3023,7 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle,
+psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key,
                                     psa_algorithm_t alg,
                                     const uint8_t *input,
                                     size_t input_length,
@@ -3318,9 +3281,9 @@
  *                                psa_key_derivation_setup() and must not
  *                                have produced any output yet.
  * \param step                    Which step the input data is for.
- * \param handle                  Handle to the key. It must have an
- *                                appropriate type for \p step and must
- *                                allow the usage #PSA_KEY_USAGE_DERIVE.
+ * \param key                     Identifier of the key. It must have an
+ *                                appropriate type for step and must allow the
+ *                                usage #PSA_KEY_USAGE_DERIVE.
  *
  * \retval #PSA_SUCCESS
  *         Success.
@@ -3346,7 +3309,7 @@
 psa_status_t psa_key_derivation_input_key(
     psa_key_derivation_operation_t *operation,
     psa_key_derivation_step_t step,
-    psa_key_handle_t handle);
+    mbedtls_svc_key_id_t key);
 
 /** Perform a key agreement and use the shared secret as input to a key
  * derivation.
@@ -3371,7 +3334,8 @@
  *                                The operation must be ready for an
  *                                input of the type given by \p step.
  * \param step                    Which step the input data is for.
- * \param private_key             Handle to the private key to use.
+ * \param private_key             Identifier of the private key to use. It must
+ *                                allow the usage #PSA_KEY_USAGE_DERIVE.
  * \param[in] peer_key      Public key of the peer. The peer key must be in the
  *                          same format that psa_import_key() accepts for the
  *                          public key type corresponding to the type of
@@ -3415,7 +3379,7 @@
 psa_status_t psa_key_derivation_key_agreement(
     psa_key_derivation_operation_t *operation,
     psa_key_derivation_step_t step,
-    psa_key_handle_t private_key,
+    mbedtls_svc_key_id_t private_key,
     const uint8_t *peer_key,
     size_t peer_key_length);
 
@@ -3559,7 +3523,9 @@
  *
  * \param[in] attributes    The attributes for the new key.
  * \param[in,out] operation The key derivation operation object to read from.
- * \param[out] handle       On success, a handle to the newly created key.
+ * \param[out] key          On success, an identifier for the newly created
+ *                          key. For persistent keys, this is the key
+ *                          identifier defined in \p attributes.
  *                          \c 0 on failure.
  *
  * \retval #PSA_SUCCESS
@@ -3599,7 +3565,7 @@
 psa_status_t psa_key_derivation_output_key(
     const psa_key_attributes_t *attributes,
     psa_key_derivation_operation_t *operation,
-    psa_key_handle_t *handle);
+    mbedtls_svc_key_id_t *key);
 
 /** Abort a key derivation operation.
  *
@@ -3640,7 +3606,8 @@
  *                                (\c PSA_ALG_XXX value such that
  *                                #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg)
  *                                is true).
- * \param private_key             Handle to the private key to use.
+ * \param private_key             Identifier of the private key to use. It must
+ *                                allow the usage #PSA_KEY_USAGE_DERIVE.
  * \param[in] peer_key            Public key of the peer. It must be
  *                                in the same format that psa_import_key()
  *                                accepts. The standard formats for public
@@ -3678,7 +3645,7 @@
  *         results in this error code.
  */
 psa_status_t psa_raw_key_agreement(psa_algorithm_t alg,
-                                   psa_key_handle_t private_key,
+                                   mbedtls_svc_key_id_t private_key,
                                    const uint8_t *peer_key,
                                    size_t peer_key_length,
                                    uint8_t *output,
@@ -3734,7 +3701,9 @@
  *   attributes.
  *
  * \param[in] attributes    The attributes for the new key.
- * \param[out] handle       On success, a handle to the newly created key.
+ * \param[out] key          On success, an identifier for the newly created
+ *                          key. For persistent keys, this is the key
+ *                          identifier defined in \p attributes.
  *                          \c 0 on failure.
  *
  * \retval #PSA_SUCCESS
@@ -3759,7 +3728,7 @@
  *         results in this error code.
  */
 psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
-                              psa_key_handle_t *handle);
+                              mbedtls_svc_key_id_t *key);
 
 /**@}*/
 
diff --git a/include/psa/crypto_accel_driver.h b/include/psa/crypto_accel_driver.h
index 1a193c5..4488ea8 100644
--- a/include/psa/crypto_accel_driver.h
+++ b/include/psa/crypto_accel_driver.h
@@ -75,7 +75,7 @@
  * \param[in,out] p_context     A structure that will contain the
  * hardware-specific hash context
  *
- * \retval  PSA_SUCCESS     Success.
+ * \retval #PSA_SUCCESS     Success.
  */
 typedef psa_status_t (*psa_drv_hash_setup_t)(psa_drv_hash_context_t *p_context);
 
@@ -120,7 +120,7 @@
  * \param[out] p_output_length  The number of bytes placed in `p_output` after
  *                              success
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *          Success.
  */
 typedef psa_status_t (*psa_drv_hash_finish_t)(psa_drv_hash_context_t *p_context,
@@ -188,7 +188,7 @@
  *                              to be used in the operation
  * \param[in] key_length        The size in bytes of the key material
  *
- * \retval  PSA_SUCCESS
+ * \retval  #PSA_SUCCESS
  *          Success.
  */
 typedef psa_status_t (*psa_drv_accel_mac_setup_t)(psa_drv_accel_mac_context_t *p_context,
@@ -235,7 +235,7 @@
  * \param[in] mac_length        The size in bytes of the buffer that has been
  *                              allocated for the `p_mac` buffer
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *          Success.
  */
 typedef psa_status_t (*psa_drv_accel_mac_finish_t)(psa_drv_accel_mac_context_t *p_context,
@@ -261,7 +261,7 @@
  * \param[in] mac_length        The size in bytes of the data in the `p_mac`
  *                              buffer
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *          The operation completed successfully and the comparison matched
  */
 typedef psa_status_t (*psa_drv_accel_mac_finish_verify_t)(psa_drv_accel_mac_context_t *p_context,
@@ -335,7 +335,7 @@
  * \param[in] p_mac          The MAC data to be compared
  * \param[in] mac_length     The length in bytes of the `p_mac` buffer
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *  The operation completed successfully and the comparison matched
  */
 typedef psa_status_t (*psa_drv_accel_mac_verify_t)(const uint8_t *p_input,
@@ -396,7 +396,7 @@
  *                              to be used in the operation
  * \param[in] key_data_size     The size in bytes of the key material
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_accel_cipher_setup_t)(psa_drv_accel_cipher_context_t *p_context,
                                                      psa_encrypt_or_decrypt_t direction,
@@ -419,7 +419,7 @@
  * \param[in] p_iv              A buffer containing the initialization vecotr
  * \param[in] iv_length         The size in bytes of the contents of `p_iv`
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_accel_cipher_set_iv_t)(psa_drv_accel_cipher_context_t *p_context,
                                                       const uint8_t *p_iv,
@@ -448,7 +448,7 @@
  * \param[out] p_output_length      After completion, will contain the number
  *                                  of bytes placed in the `p_output` buffer
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_accel_cipher_update_t)(psa_drv_accel_cipher_context_t *p_context,
                                                       const uint8_t *p_input,
@@ -477,7 +477,7 @@
  * \param[out] p_output_length  After completion, will contain the number of
  *                              bytes placed in the `p_output` buffer
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_accel_cipher_finish_t)(psa_drv_accel_cipher_context_t *p_context,
                                                       uint8_t *p_output,
@@ -499,7 +499,7 @@
  * \param[in,out] p_context     A hardware-specific structure for the
  *                              previously started cipher operation
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_accel_cipher_abort_t)(psa_drv_accel_cipher_context_t *p_context);
 
@@ -659,7 +659,7 @@
  * \param[out] p_signature_length   On success, the number of bytes
  *                                  that make up the returned signature value
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_accel_asymmetric_sign_t)(const uint8_t *p_key,
                                                         size_t key_size,
@@ -697,7 +697,7 @@
  * \param[in] p_signature       Buffer containing the signature to verify
  * \param[in] signature_length  Size of the `p_signature` buffer in bytes
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *         The signature is valid.
  */
 typedef psa_status_t (*psa_drv_accel_asymmetric_verify_t)(const uint8_t *p_key,
@@ -748,7 +748,7 @@
  * \param[out] p_output_length  On success, the number of bytes
  *                              that make up the returned output
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_accel_asymmetric_encrypt_t)(const uint8_t *p_key,
                                                            size_t key_size,
@@ -800,7 +800,7 @@
  * \param[out] p_output_length  On success, the number of bytes
  *                              that make up the returned output
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_accel_asymmetric_decrypt_t)(const uint8_t *p_key,
                                                            size_t key_size,
diff --git a/include/psa/crypto_compat.h b/include/psa/crypto_compat.h
index 4b607b6..86aa271 100644
--- a/include/psa/crypto_compat.h
+++ b/include/psa/crypto_compat.h
@@ -34,6 +34,27 @@
 extern "C" {
 #endif
 
+/*
+ * To support both openless APIs and psa_open_key() temporarily, define
+ * psa_key_handle_t to be equal to mbedtls_svc_key_id_t. Do not mark the
+ * type and its utility macros and functions deprecated yet. This will be done
+ * in a subsequent phase.
+ */
+typedef mbedtls_svc_key_id_t psa_key_handle_t;
+
+#define PSA_KEY_HANDLE_INIT MBEDTLS_SVC_KEY_ID_INIT
+
+/** Check wether an handle is null.
+ *
+ * \param handle  Handle
+ *
+ * \return Non-zero if the handle is null, zero otherwise.
+ */
+static inline int psa_key_handle_is_null( psa_key_handle_t handle )
+{
+    return( mbedtls_svc_key_id_is_null( handle ) );
+}
+
 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
 
 /*
@@ -113,10 +134,6 @@
     return psa_verify_hash( key, alg, hash, hash_length, signature, signature_length );
 }
 
-
-
-#endif /* MBEDTLS_DEPRECATED_REMOVED */
-
 /*
  * Size-specific elliptic curve families.
  */
@@ -223,6 +240,109 @@
 #define PSA_DH_GROUP_CUSTOM \
     MBEDTLS_DEPRECATED_CONSTANT( psa_dh_family_t, PSA_DH_FAMILY_CUSTOM )
 
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+/** Open a handle to an existing persistent key.
+ *
+ * Open a handle to a persistent key. A key is persistent if it was created
+ * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key
+ * always has a nonzero key identifier, set with psa_set_key_id() when
+ * creating the key. Implementations may provide additional pre-provisioned
+ * keys that can be opened with psa_open_key(). Such keys have an application
+ * key identifier in the vendor range, as documented in the description of
+ * #psa_key_id_t.
+ *
+ * The application must eventually close the handle with psa_close_key() or
+ * psa_destroy_key() to release associated resources. If the application dies
+ * without calling one of these functions, the implementation should perform
+ * the equivalent of a call to psa_close_key().
+ *
+ * Some implementations permit an application to open the same key multiple
+ * times. If this is successful, each call to psa_open_key() will return a
+ * different key handle.
+ *
+ * \note This API is not part of the PSA Cryptography API Release 1.0.0
+ * specification. It was defined in the 1.0 Beta 3 version of the
+ * specification but was removed in the 1.0.0 released version. This API is
+ * kept for the time being to not break applications relying on it. It is not
+ * deprecated yet but will be in the near future.
+ *
+ * \note Applications that rely on opening a key multiple times will not be
+ * portable to implementations that only permit a single key handle to be
+ * opened. See also :ref:\`key-handles\`.
+ *
+ *
+ * \param key           The persistent identifier of the key.
+ * \param[out] handle   On success, a handle to the key.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success. The application can now use the value of `*handle`
+ *         to access the key.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         The implementation does not have sufficient resources to open the
+ *         key. This can be due to reaching an implementation limit on the
+ *         number of open keys, the number of open key handles, or available
+ *         memory.
+ * \retval #PSA_ERROR_DOES_NOT_EXIST
+ *         There is no persistent key with key identifier \p id.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p id is not a valid persistent key identifier.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The specified key exists, but the application does not have the
+ *         permission to access it. Note that this specification does not
+ *         define any way to create such a key, but it may be possible
+ *         through implementation-specific means.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_open_key( mbedtls_svc_key_id_t key,
+                           psa_key_handle_t *handle );
+
+/** Close a key handle.
+ *
+ * If the handle designates a volatile key, this will destroy the key material
+ * and free all associated resources, just like psa_destroy_key().
+ *
+ * If this is the last open handle to a persistent key, then closing the handle
+ * will free all resources associated with the key in volatile memory. The key
+ * data in persistent storage is not affected and can be opened again later
+ * with a call to psa_open_key().
+ *
+ * Closing the key handle makes the handle invalid, and the key handle
+ * must not be used again by the application.
+ *
+ * \note This API is not part of the PSA Cryptography API Release 1.0.0
+ * specification. It was defined in the 1.0 Beta 3 version of the
+ * specification but was removed in the 1.0.0 released version. This API is
+ * kept for the time being to not break applications relying on it. It is not
+ * deprecated yet but will be in the near future.
+ *
+ * \note If the key handle was used to set up an active
+ * :ref:\`multipart operation <multipart-operations>\`, then closing the
+ * key handle can cause the multipart operation to fail. Applications should
+ * maintain the key handle until after the multipart operation has finished.
+ *
+ * \param handle        The key handle to close.
+ *                      If this is \c 0, do nothing and return \c PSA_SUCCESS.
+ *
+ * \retval #PSA_SUCCESS
+ *         \p handle was a valid handle or \c 0. It is now closed.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ *         \p handle is not a valid handle nor \c 0.
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_close_key(psa_key_handle_t handle);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/psa/crypto_config.h b/include/psa/crypto_config.h
new file mode 100644
index 0000000..c12a522
--- /dev/null
+++ b/include/psa/crypto_config.h
@@ -0,0 +1,69 @@
+/**
+ * \file psa/crypto_config.h
+ * \brief PSA crypto configuration options (set of defines)
+ *
+ */
+#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
+/**
+ * When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled in config.h,
+ * this file determines which cryptographic mechanisms are enabled
+ * through the PSA Cryptography API (\c psa_xxx() functions).
+ *
+ * To enable a cryptographic mechanism, uncomment the definition of
+ * the corresponding \c PSA_WANT_xxx preprocessor symbol.
+ * To disable a cryptographic mechanism, comment out the definition of
+ * the corresponding \c PSA_WANT_xxx preprocessor symbol.
+ * The names of cryptographic mechanisms correspond to values
+ * defined in psa/crypto_values.h, with the prefix \c PSA_WANT_ instead
+ * of \c PSA_.
+ *
+ * Note that many cryptographic mechanisms involve two symbols: one for
+ * the key type (\c PSA_WANT_KEY_TYPE_xxx) and one for the algorithm
+ * (\c PSA_WANT_ALG_xxx). Mechanisms with additional parameters may involve
+ * additional symbols.
+ */
+#else
+/**
+ * When \c MBEDTLS_PSA_CRYPTO_CONFIG is disabled in config.h,
+ * this file is not used, and cryptographic mechanisms are supported
+ * through the PSA API if and only if they are supported through the
+ * mbedtls_xxx API.
+ */
+#endif
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef PSA_CRYPTO_CONFIG_H
+#define PSA_CRYPTO_CONFIG_H
+
+#define PSA_WANT_ALG_DETERMINISTIC_ECDSA        1
+#define PSA_WANT_ALG_ECDH                       1
+#define PSA_WANT_ALG_ECDSA                      1
+#define PSA_WANT_ALG_HKDF                       1
+#define PSA_WANT_ALG_HMAC                       1
+#define PSA_WANT_ALG_RSA_OAEP                   1
+#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT         1
+#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN          1
+#define PSA_WANT_ALG_RSA_PSS                    1
+#define PSA_WANT_ALG_TLS12_PRF                  1
+#define PSA_WANT_ALG_TLS12_PSK_TO_MS            1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR          1
+#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY        1
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR          1
+#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY        1
+
+#endif /* PSA_CRYPTO_CONFIG_H */
diff --git a/include/psa/crypto_entropy_driver.h b/include/psa/crypto_entropy_driver.h
index 6175044..9b6546e 100644
--- a/include/psa/crypto_entropy_driver.h
+++ b/include/psa/crypto_entropy_driver.h
@@ -47,7 +47,7 @@
  *                                      containing any context information for
  *                                      the implementation
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_entropy_init_t)(void *p_context);
 
@@ -75,7 +75,7 @@
  * \param[out] p_received_entropy_bits      The amount of entropy (in bits)
  *                                          actually provided in `p_buffer`
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_entropy_get_bits_t)(void *p_context,
                                                    uint8_t *p_buffer,
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index 71adb93..b25addc 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -231,6 +231,8 @@
     size_t cache_slots;
     /** Number of slots that are not used for anything. */
     size_t empty_slots;
+    /** Number of slots that are locked. */
+    size_t locked_slots;
     /** Largest key id value among open keys in internal persistent storage. */
     psa_key_id_t max_open_internal_key_id;
     /** Largest key id value among open keys in secure elements. */
diff --git a/include/psa/crypto_platform.h b/include/psa/crypto_platform.h
index c64f61d..567398d 100644
--- a/include/psa/crypto_platform.h
+++ b/include/psa/crypto_platform.h
@@ -41,6 +41,10 @@
 #include MBEDTLS_CONFIG_FILE
 #endif
 
+/* Translate between classic MBEDTLS_xxx feature symbols and PSA_xxx
+ * feature symbols. */
+#include "mbedtls/config_psa.h"
+
 /* PSA requires several types which C99 provides in stdint.h. */
 #include <stdint.h>
 
@@ -49,9 +53,6 @@
 #define inline __inline
 #endif
 
-/* Integral type representing a key handle. */
-typedef uint16_t psa_key_handle_t;
-
 #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
 
 /* Building for the PSA Crypto service on a PSA platform, a key owner is a PSA
diff --git a/include/psa/crypto_se_driver.h b/include/psa/crypto_se_driver.h
index 46b2d64..1fae575 100644
--- a/include/psa/crypto_se_driver.h
+++ b/include/psa/crypto_se_driver.h
@@ -178,7 +178,7 @@
  * \param[in] algorithm         The algorithm to be used to underly the MAC
  *                              operation
  *
- * \retval  PSA_SUCCESS
+ * \retval  #PSA_SUCCESS
  *          Success.
  */
 typedef psa_status_t (*psa_drv_se_mac_setup_t)(psa_drv_se_context_t *drv_context,
@@ -213,7 +213,7 @@
  * \param[out] p_mac_length     After completion, will contain the number of
  *                              bytes placed in the `p_mac` buffer
  *
- * \retval PSA_SUCCESS
+ * \retval  #PSA_SUCCESS
  *          Success.
  */
 typedef psa_status_t (*psa_drv_se_mac_finish_t)(void *op_context,
@@ -230,10 +230,10 @@
  *                              will be compared against
  * \param[in] mac_length        The size in bytes of the value stored in `p_mac`
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *         The operation completed successfully and the MACs matched each
  *         other
- * \retval PSA_ERROR_INVALID_SIGNATURE
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
  *         The operation completed successfully, but the calculated MAC did
  *         not match the provided MAC
  */
@@ -264,7 +264,7 @@
  * \param[out] p_mac_length     After completion, will contain the number of
  *                              bytes placed in the `output` buffer
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *         Success.
  */
 typedef psa_status_t (*psa_drv_se_mac_generate_t)(psa_drv_se_context_t *drv_context,
@@ -289,10 +289,10 @@
  *                          be compared against
  * \param[in] mac_length   The size in bytes of `mac`
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *         The operation completed successfully and the MACs matched each
  *         other
- * \retval PSA_ERROR_INVALID_SIGNATURE
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
  *         The operation completed successfully, but the calculated MAC did
  *         not match the provided MAC
  */
@@ -384,8 +384,8 @@
  * \param[in] direction         Indicates whether the operation is an encrypt
  *                              or decrypt
  *
- * \retval PSA_SUCCESS
- * \retval PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_NOT_SUPPORTED
  */
 typedef psa_status_t (*psa_drv_se_cipher_setup_t)(psa_drv_se_context_t *drv_context,
                                                   void *op_context,
@@ -406,7 +406,7 @@
  * \param[in] p_iv              A buffer containing the initialization vector
  * \param[in] iv_length         The size (in bytes) of the `p_iv` buffer
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *op_context,
                                                    const uint8_t *p_iv,
@@ -428,7 +428,7 @@
  * \param[out] p_output_length      After completion, will contain the number
  *                                  of bytes placed in the `p_output` buffer
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *op_context,
                                                    const uint8_t *p_input,
@@ -449,7 +449,7 @@
  * \param[out] p_output_length  After completion, will contain the number of
  *                              bytes placed in the `p_output` buffer
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *op_context,
                                                    uint8_t *p_output,
@@ -484,8 +484,8 @@
  * \param[in] output_size       The allocated size in bytes of the `p_output`
  *                              buffer
  *
- * \retval PSA_SUCCESS
- * \retval PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_NOT_SUPPORTED
  */
 typedef psa_status_t (*psa_drv_se_cipher_ecb_t)(psa_drv_se_context_t *drv_context,
                                                 psa_key_slot_number_t key_slot,
@@ -553,7 +553,7 @@
  * \param[out] p_signature_length   On success, the number of bytes
  *                                  that make up the returned signature value
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_drv_se_context_t *drv_context,
                                                      psa_key_slot_number_t key_slot,
@@ -578,7 +578,7 @@
  * \param[in] p_signature       Buffer containing the signature to verify
  * \param[in] signature_length  Size of the `p_signature` buffer in bytes
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *         The signature is valid.
  */
 typedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_drv_se_context_t *drv_context,
@@ -617,7 +617,7 @@
  * \param[out] p_output_length  On success, the number of bytes that make up
  *                              the returned output
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_drv_se_context_t *drv_context,
                                                         psa_key_slot_number_t key_slot,
@@ -657,7 +657,7 @@
  * \param[out] p_output_length  On success, the number of bytes
  *                              that make up the returned output
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_drv_se_context_t *drv_context,
                                                         psa_key_slot_number_t key_slot,
@@ -1195,7 +1195,7 @@
  * \param[in] source_key        The key to be used as the source material for
  *                              the key derivation
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(psa_drv_se_context_t *drv_context,
                                                           void *op_context,
@@ -1215,7 +1215,7 @@
  * \param[in] p_collateral      A buffer containing the collateral data
  * \param[in] collateral_size   The size in bytes of the collateral
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *op_context,
                                                                uint32_t collateral_id,
@@ -1230,7 +1230,7 @@
  * \param[in] dest_key          The slot where the generated key material
  *                              should be placed
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *op_context,
                                                           psa_key_slot_number_t dest_key);
@@ -1244,7 +1244,7 @@
  * \param[out] p_output_length  Upon success, contains the number of bytes of
  *                              key material placed in `p_output`
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  */
 typedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *op_context,
                                                            uint8_t *p_output,
@@ -1353,7 +1353,7 @@
  * \param location      The location value through which this driver will
  *                      be exposed to applications.
  *                      This driver will be used for all keys such that
- *                      `location == PSA_KEY_LIFETIME_LOCATION( lifetime )`.
+ *                      `location == #PSA_KEY_LIFETIME_GET_LOCATION( lifetime )`.
  *                      The value #PSA_KEY_LOCATION_LOCAL_STORAGE is reserved
  *                      and may not be used for drivers. Implementations
  *                      may reserve other values.
@@ -1362,22 +1362,22 @@
  *                      module keeps running. It is typically a global
  *                      constant.
  *
- * \return PSA_SUCCESS
+ * \return #PSA_SUCCESS
  *         The driver was successfully registered. Applications can now
  *         use \p lifetime to access keys through the methods passed to
  *         this function.
- * \return PSA_ERROR_BAD_STATE
+ * \return #PSA_ERROR_BAD_STATE
  *         This function was called after the initialization of the
  *         cryptography module, and this implementation does not support
  *         driver registration at this stage.
- * \return PSA_ERROR_ALREADY_EXISTS
+ * \return #PSA_ERROR_ALREADY_EXISTS
  *         There is already a registered driver for this value of \p lifetime.
- * \return PSA_ERROR_INVALID_ARGUMENT
+ * \return #PSA_ERROR_INVALID_ARGUMENT
  *         \p lifetime is a reserved value.
- * \return PSA_ERROR_NOT_SUPPORTED
+ * \return #PSA_ERROR_NOT_SUPPORTED
  *         `methods->hal_version` is not supported by this implementation.
- * \return PSA_ERROR_INSUFFICIENT_MEMORY
- * \return PSA_ERROR_NOT_PERMITTED
+ * \return #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \return #PSA_ERROR_NOT_PERMITTED
  */
 psa_status_t psa_register_se_driver(
     psa_key_location_t location,
diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h
index f6373b8..4dc8ad4 100644
--- a/include/psa/crypto_sizes.h
+++ b/include/psa/crypto_sizes.h
@@ -657,4 +657,91 @@
      PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \
      0)
 
+/** The default nonce size for an AEAD algorithm, in bytes.
+ *
+ * This macro can be used to allocate a buffer of sufficient size to
+ * store the nonce output from #psa_aead_generate_nonce().
+ *
+ * See also #PSA_AEAD_NONCE_MAX_SIZE.
+ *
+ * \note This is not the maximum size of nonce supported as input to #psa_aead_set_nonce(),
+ *       #psa_aead_encrypt() or #psa_aead_decrypt(), just the default size that is generated by
+ *       #psa_aead_generate_nonce().
+ *
+ * \warning This macro may evaluate its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param key_type  A symmetric key type that is compatible with algorithm \p alg.
+ *
+ * \param alg       An AEAD algorithm (\c PSA_ALG_XXX value such that #PSA_ALG_IS_AEAD(\p alg) is true).
+ *
+ * \return The default nonce size for the specified key type and algorithm.
+ *         If the key type or AEAD algorithm is not recognized,
+ *         or the parameters are incompatible, return 0.
+ *         An implementation can return either 0 or a correct size for a key type
+ *         and AEAD algorithm that it recognizes, but does not support.
+ */
+#define PSA_AEAD_NONCE_LENGTH(key_type, alg) \
+    (PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) == 16 && \
+         (PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg) == PSA_ALG_CCM || \
+          PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg) == PSA_ALG_GCM) ? 12 : \
+     (key_type) == PSA_KEY_TYPE_CHACHA20 && \
+          PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg) == PSA_ALG_CHACHA20_POLY1305 ? 12 : \
+     0)
+
+/** The maximum default nonce size among all supported pairs of key types and AEAD algorithms, in bytes.
+ *
+ * This is equal to or greater than any value that #PSA_AEAD_NONCE_LENGTH() may return.
+ *
+ * \note This is not the maximum size of nonce supported as input to #psa_aead_set_nonce(),
+ *       #psa_aead_encrypt() or #psa_aead_decrypt(), just the largest size that may be generated by
+ *       #psa_aead_generate_nonce().
+ */
+#define PSA_AEAD_NONCE_MAX_SIZE 12
+
+/** The default IV size for a cipher algorithm, in bytes.
+ *
+ * The IV that is generated as part of a call to #psa_cipher_encrypt() is always
+ * the default IV length for the algorithm.
+ *
+ * This macro can be used to allocate a buffer of sufficient size to
+ * store the IV output from #psa_cipher_generate_iv() when using
+ * a multi-part cipher operation.
+ *
+ * See also #PSA_CIPHER_IV_MAX_SIZE.
+ *
+ * \warning This macro may evaluate its arguments multiple times or
+ *          zero times, so you should not pass arguments that contain
+ *          side effects.
+ *
+ * \param key_type  A symmetric key type that is compatible with algorithm \p alg.
+ *
+ * \param alg       A cipher algorithm (\c PSA_ALG_XXX value such that #PSA_ALG_IS_CIPHER(\p alg) is true).
+ *
+ * \return The default IV size for the specified key type and algorithm.
+ *         If the algorithm does not use an IV, return 0.
+ *         If the key type or cipher algorithm is not recognized,
+ *         or the parameters are incompatible, return 0.
+ *         An implementation can return either 0 or a correct size for a key type
+ *         and cipher algorithm that it recognizes, but does not support.
+ */
+#define PSA_CIPHER_IV_LENGTH(key_type, alg) \
+    (PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) > 1 && \
+        ((alg) == PSA_ALG_CTR || \
+         (alg) == PSA_ALG_CFB || \
+         (alg) == PSA_ALG_OFB || \
+         (alg) == PSA_ALG_XTS || \
+         (alg) == PSA_ALG_CBC_NO_PADDING || \
+         (alg) == PSA_ALG_CBC_PKCS7) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \
+     (key_type) == PSA_KEY_TYPE_CHACHA20 && \
+         (alg) == PSA_ALG_CHACHA20 ? 12 : \
+     0)
+
+/** The maximum IV size for all supported cipher algorithms, in bytes.
+ *
+ * See also #PSA_CIPHER_IV_LENGTH().
+ */
+#define PSA_CIPHER_IV_MAX_SIZE 16
+
 #endif /* PSA_CRYPTO_SIZES_H */
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index be0e280..6a018e1 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -374,9 +374,17 @@
 static inline void psa_set_key_id( psa_key_attributes_t *attributes,
                                    mbedtls_svc_key_id_t key )
 {
+    psa_key_lifetime_t lifetime = attributes->core.lifetime;
+
     attributes->core.id = key;
-    if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE )
-        attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
+
+    if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
+    {
+        attributes->core.lifetime =
+            PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
+                PSA_KEY_LIFETIME_PERSISTENT,
+                PSA_KEY_LIFETIME_GET_LOCATION( lifetime ) );
+    }
 }
 
 static inline mbedtls_svc_key_id_t psa_get_key_id(
@@ -385,11 +393,19 @@
     return( attributes->core.id );
 }
 
+#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
+static inline void mbedtls_set_key_owner_id( psa_key_attributes_t *attributes,
+                                             mbedtls_key_owner_id_t owner )
+{
+    attributes->core.id.owner = owner;
+}
+#endif
+
 static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes,
                                         psa_key_lifetime_t lifetime)
 {
     attributes->core.lifetime = lifetime;
-    if( lifetime == PSA_KEY_LIFETIME_VOLATILE )
+    if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
     {
 #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
         attributes->core.id.key_id = 0;
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index 923b02b..0a2ae54 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -352,7 +352,7 @@
  * -# Call a key creation function: psa_import_key(), psa_generate_key(),
  *    psa_key_derivation_output_key() or psa_copy_key(). This function reads
  *    the attribute structure, creates a key with these attributes, and
- *    outputs a handle to the newly created key.
+ *    outputs a key identifier to the newly created key.
  * -# The attribute structure is now no longer necessary.
  *    You may call psa_reset_key_attributes(), although this is optional
  *    with the workflow presented here because the attributes currently
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index 3eb64d8..580b89e 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -108,7 +108,7 @@
  * as applicable.
  *
  * Implementations shall not return this error code to indicate that a
- * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE
+ * key identifier is invalid, but shall return #PSA_ERROR_INVALID_HANDLE
  * instead. */
 #define PSA_ERROR_BAD_STATE             ((psa_status_t)-137)
 
@@ -118,7 +118,7 @@
  * combination of parameters are recognized as invalid.
  *
  * Implementations shall not return this error code to indicate that a
- * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE
+ * key identifier is invalid, but shall return #PSA_ERROR_INVALID_HANDLE
  * instead.
  */
 #define PSA_ERROR_INVALID_ARGUMENT      ((psa_status_t)-135)
@@ -266,7 +266,7 @@
  * to read from a resource. */
 #define PSA_ERROR_INSUFFICIENT_DATA     ((psa_status_t)-143)
 
-/** The key handle is not valid. See also :ref:\`key-handles\`.
+/** The key identifier is not valid. See also :ref:\`key-handles\`.
  */
 #define PSA_ERROR_INVALID_HANDLE        ((psa_status_t)-136)
 
@@ -769,9 +769,9 @@
  *   an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each
  *   call to sign or verify a message may use a different hash.
  *   ```
- *   psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...);
- *   psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...);
- *   psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...);
+ *   psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...);
+ *   psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...);
+ *   psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...);
  *   ```
  *
  * This value may not be used to build other algorithms that are
@@ -1452,7 +1452,7 @@
  * a key derivation function.
  * Usually, raw key agreement algorithms are constructed directly with
  * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are
- * constructed with PSA_ALG_KEY_AGREEMENT().
+ * constructed with #PSA_ALG_KEY_AGREEMENT().
  *
  * \param alg An algorithm identifier (value of type #psa_algorithm_t).
  *
@@ -1561,7 +1561,7 @@
 
 /** The default lifetime for volatile keys.
  *
- * A volatile key only exists as long as the handle to it is not closed.
+ * A volatile key only exists as long as the identifier to it is not destroyed.
  * The key material is guaranteed to be erased on a power reset.
  *
  * A key with this lifetime is typically stored in the RAM area of the
@@ -1700,6 +1700,17 @@
     return( id1 == id2 );
 }
 
+/** Check whether a key identifier is null.
+ *
+ * \param key Key identifier.
+ *
+ * \return Non-zero if the key identifier is null, zero otherwise.
+ */
+static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key )
+{
+    return( key == 0 );
+}
+
 #else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
 
 #define MBEDTLS_SVC_KEY_ID_INIT ( (mbedtls_svc_key_id_t){ 0, 0 } )
@@ -1732,6 +1743,17 @@
             mbedtls_key_owner_id_equal( id1.owner, id2.owner ) );
 }
 
+/** Check whether a key identifier is null.
+ *
+ * \param key Key identifier.
+ *
+ * \return Non-zero if the key identifier is null, zero otherwise.
+ */
+static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key )
+{
+    return( ( key.key_id == 0 ) && ( key.owner == 0 ) );
+}
+
 #endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
 
 /**@}*/
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 4444b98..8962555 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -150,46 +150,59 @@
     message(FATAL_ERROR "Need to choose static or shared mbedtls build!")
 endif(NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY)
 
-set(target_libraries "mbedcrypto" "mbedx509" "mbedtls")
+set(mbedtls_target    "${MBEDTLS_TARGET_PREFIX}mbedtls")
+set(mbedx509_target   "${MBEDTLS_TARGET_PREFIX}mbedx509")
+set(mbedcrypto_target "${MBEDTLS_TARGET_PREFIX}mbedcrypto")
+
+set(mbedtls_target    ${mbedtls_target}    PARENT_SCOPE)
+set(mbedx509_target   ${mbedx509_target}   PARENT_SCOPE)
+set(mbedcrypto_target ${mbedcrypto_target} PARENT_SCOPE)
+
+if (USE_STATIC_MBEDTLS_LIBRARY)
+    set(mbedtls_static_target    ${mbedtls_target})
+    set(mbedx509_static_target   ${mbedx509_target})
+    set(mbedcrypto_static_target ${mbedcrypto_target})
+endif()
+
+set(target_libraries ${mbedcrypto_target} ${mbedx509_target} ${mbedtls_target})
 
 if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY)
-    set(mbedtls_static_target "mbedtls_static")
-    set(mbedx509_static_target "mbedx509_static")
-    set(mbedcrypto_static_target "mbedcrypto_static")
+    string(APPEND mbedtls_static_target    "_static")
+    string(APPEND mbedx509_static_target   "_static")
+    string(APPEND mbedcrypto_static_target "_static")
+
     list(APPEND target_libraries
-        "mbedcrypto_static" "mbedx509_static" "mbedtls_static")
-elseif(USE_STATIC_MBEDTLS_LIBRARY)
-    set(mbedtls_static_target "mbedtls")
-    set(mbedx509_static_target "mbedx509")
-    set(mbedcrypto_static_target "mbedcrypto")
+        ${mbedcrypto_static_target}
+        ${mbedx509_static_target}
+        ${mbedtls_static_target})
 endif()
 
 if(USE_STATIC_MBEDTLS_LIBRARY)
     add_library(${mbedcrypto_static_target} STATIC ${src_crypto})
     set_target_properties(${mbedcrypto_static_target} PROPERTIES OUTPUT_NAME mbedcrypto)
-    target_link_libraries(${mbedcrypto_static_target} ${libs})
+    target_link_libraries(${mbedcrypto_static_target} PUBLIC ${libs})
 
     add_library(${mbedx509_static_target} STATIC ${src_x509})
     set_target_properties(${mbedx509_static_target} PROPERTIES OUTPUT_NAME mbedx509)
-    target_link_libraries(${mbedx509_static_target} ${libs} ${mbedcrypto_static_target})
+    target_link_libraries(${mbedx509_static_target} PUBLIC ${libs} ${mbedcrypto_static_target})
 
     add_library(${mbedtls_static_target} STATIC ${src_tls})
     set_target_properties(${mbedtls_static_target} PROPERTIES OUTPUT_NAME mbedtls)
-    target_link_libraries(${mbedtls_static_target} ${libs} ${mbedx509_static_target})
+    target_link_libraries(${mbedtls_static_target} PUBLIC ${libs} ${mbedx509_static_target})
 endif(USE_STATIC_MBEDTLS_LIBRARY)
 
 if(USE_SHARED_MBEDTLS_LIBRARY)
-    add_library(mbedcrypto SHARED ${src_crypto})
-    set_target_properties(mbedcrypto PROPERTIES VERSION 2.24.0 SOVERSION 5)
-    target_link_libraries(mbedcrypto ${libs})
+    add_library(${mbedcrypto_target} SHARED ${src_crypto})
+    set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 2.24.0 SOVERSION 5)
+    target_link_libraries(${mbedcrypto_target} PUBLIC ${libs})
 
-    add_library(mbedx509 SHARED ${src_x509})
-    set_target_properties(mbedx509 PROPERTIES VERSION 2.24.0 SOVERSION 1)
-    target_link_libraries(mbedx509 ${libs} mbedcrypto)
+    add_library(${mbedx509_target} SHARED ${src_x509})
+    set_target_properties(${mbedx509_target} PROPERTIES VERSION 2.24.0 SOVERSION 1)
+    target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target})
 
-    add_library(mbedtls SHARED ${src_tls})
-    set_target_properties(mbedtls PROPERTIES VERSION 2.24.0 SOVERSION 13)
-    target_link_libraries(mbedtls ${libs} mbedx509)
+    add_library(${mbedtls_target} SHARED ${src_tls})
+    set_target_properties(${mbedtls_target} PROPERTIES VERSION 2.24.0 SOVERSION 13)
+    target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target})
 endif(USE_SHARED_MBEDTLS_LIBRARY)
 
 foreach(target IN LISTS target_libraries)
@@ -210,7 +223,9 @@
             PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)
 endforeach(target)
 
-add_custom_target(lib DEPENDS mbedcrypto mbedx509 mbedtls)
+set(lib_target "${MBEDTLS_TARGET_PREFIX}lib")
+
+add_custom_target(${lib_target} DEPENDS ${mbedcrypto_target} ${mbedx509_target} ${mbedtls_target})
 if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY)
-    add_dependencies(lib mbedcrypto_static mbedx509_static mbedtls_static)
+    add_dependencies(${lib_target} ${mbedcrypto_static_target} ${mbedx509_static_target} ${mbedtls_static_target})
 endif()
diff --git a/library/aes.c b/library/aes.c
index ed48b24..3f61642 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -730,6 +730,7 @@
 
     return( ret );
 }
+#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
 static int mbedtls_aes_xts_decode_keys( const unsigned char *key,
@@ -808,8 +809,6 @@
 }
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
-#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */
-
 #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)                     \
     do                                                          \
     {                                                           \
@@ -867,63 +866,56 @@
                                   unsigned char output[16] )
 {
     int i;
-    uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+    uint32_t *RK = ctx->rk;
+    struct
+    {
+        uint32_t X[4];
+        uint32_t Y[4];
+    } t;
 
-    RK = ctx->rk;
-
-    GET_UINT32_LE( X0, input,  0 ); X0 ^= *RK++;
-    GET_UINT32_LE( X1, input,  4 ); X1 ^= *RK++;
-    GET_UINT32_LE( X2, input,  8 ); X2 ^= *RK++;
-    GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
+    GET_UINT32_LE( t.X[0], input,  0 ); t.X[0] ^= *RK++;
+    GET_UINT32_LE( t.X[1], input,  4 ); t.X[1] ^= *RK++;
+    GET_UINT32_LE( t.X[2], input,  8 ); t.X[2] ^= *RK++;
+    GET_UINT32_LE( t.X[3], input, 12 ); t.X[3] ^= *RK++;
 
     for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
     {
-        AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
-        AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+        AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
+        AES_FROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] );
     }
 
-    AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+    AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
 
-    X0 = *RK++ ^ \
-            ( (uint32_t) FSb[ ( Y0       ) & 0xFF ]       ) ^
-            ( (uint32_t) FSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+    t.X[0] = *RK++ ^ \
+            ( (uint32_t) FSb[ ( t.Y[0]       ) & 0xFF ]       ) ^
+            ( (uint32_t) FSb[ ( t.Y[1] >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) FSb[ ( t.Y[2] >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) FSb[ ( t.Y[3] >> 24 ) & 0xFF ] << 24 );
 
-    X1 = *RK++ ^ \
-            ( (uint32_t) FSb[ ( Y1       ) & 0xFF ]       ) ^
-            ( (uint32_t) FSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+    t.X[1] = *RK++ ^ \
+            ( (uint32_t) FSb[ ( t.Y[1]       ) & 0xFF ]       ) ^
+            ( (uint32_t) FSb[ ( t.Y[2] >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) FSb[ ( t.Y[3] >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) FSb[ ( t.Y[0] >> 24 ) & 0xFF ] << 24 );
 
-    X2 = *RK++ ^ \
-            ( (uint32_t) FSb[ ( Y2       ) & 0xFF ]       ) ^
-            ( (uint32_t) FSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+    t.X[2] = *RK++ ^ \
+            ( (uint32_t) FSb[ ( t.Y[2]       ) & 0xFF ]       ) ^
+            ( (uint32_t) FSb[ ( t.Y[3] >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) FSb[ ( t.Y[0] >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) FSb[ ( t.Y[1] >> 24 ) & 0xFF ] << 24 );
 
-    X3 = *RK++ ^ \
-            ( (uint32_t) FSb[ ( Y3       ) & 0xFF ]       ) ^
-            ( (uint32_t) FSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+    t.X[3] = *RK++ ^ \
+            ( (uint32_t) FSb[ ( t.Y[3]       ) & 0xFF ]       ) ^
+            ( (uint32_t) FSb[ ( t.Y[0] >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) FSb[ ( t.Y[1] >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) FSb[ ( t.Y[2] >> 24 ) & 0xFF ] << 24 );
 
-    PUT_UINT32_LE( X0, output,  0 );
-    PUT_UINT32_LE( X1, output,  4 );
-    PUT_UINT32_LE( X2, output,  8 );
-    PUT_UINT32_LE( X3, output, 12 );
+    PUT_UINT32_LE( t.X[0], output,  0 );
+    PUT_UINT32_LE( t.X[1], output,  4 );
+    PUT_UINT32_LE( t.X[2], output,  8 );
+    PUT_UINT32_LE( t.X[3], output, 12 );
 
-    mbedtls_platform_zeroize( &X0, sizeof( X0 ) );
-    mbedtls_platform_zeroize( &X1, sizeof( X1 ) );
-    mbedtls_platform_zeroize( &X2, sizeof( X2 ) );
-    mbedtls_platform_zeroize( &X3, sizeof( X3 ) );
-
-    mbedtls_platform_zeroize( &Y0, sizeof( Y0 ) );
-    mbedtls_platform_zeroize( &Y1, sizeof( Y1 ) );
-    mbedtls_platform_zeroize( &Y2, sizeof( Y2 ) );
-    mbedtls_platform_zeroize( &Y3, sizeof( Y3 ) );
-
-    mbedtls_platform_zeroize( &RK, sizeof( RK ) );
+    mbedtls_platform_zeroize( &t, sizeof( t ) );
 
     return( 0 );
 }
@@ -947,63 +939,56 @@
                                   unsigned char output[16] )
 {
     int i;
-    uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+    uint32_t *RK = ctx->rk;
+    struct
+    {
+        uint32_t X[4];
+        uint32_t Y[4];
+    } t;
 
-    RK = ctx->rk;
-
-    GET_UINT32_LE( X0, input,  0 ); X0 ^= *RK++;
-    GET_UINT32_LE( X1, input,  4 ); X1 ^= *RK++;
-    GET_UINT32_LE( X2, input,  8 ); X2 ^= *RK++;
-    GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
+    GET_UINT32_LE( t.X[0], input,  0 ); t.X[0] ^= *RK++;
+    GET_UINT32_LE( t.X[1], input,  4 ); t.X[1] ^= *RK++;
+    GET_UINT32_LE( t.X[2], input,  8 ); t.X[2] ^= *RK++;
+    GET_UINT32_LE( t.X[3], input, 12 ); t.X[3] ^= *RK++;
 
     for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
     {
-        AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
-        AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+        AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
+        AES_RROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] );
     }
 
-    AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+    AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] );
 
-    X0 = *RK++ ^ \
-            ( (uint32_t) RSb[ ( Y0       ) & 0xFF ]       ) ^
-            ( (uint32_t) RSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+    t.X[0] = *RK++ ^ \
+            ( (uint32_t) RSb[ ( t.Y[0]       ) & 0xFF ]       ) ^
+            ( (uint32_t) RSb[ ( t.Y[3] >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) RSb[ ( t.Y[2] >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) RSb[ ( t.Y[1] >> 24 ) & 0xFF ] << 24 );
 
-    X1 = *RK++ ^ \
-            ( (uint32_t) RSb[ ( Y1       ) & 0xFF ]       ) ^
-            ( (uint32_t) RSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+    t.X[1] = *RK++ ^ \
+            ( (uint32_t) RSb[ ( t.Y[1]       ) & 0xFF ]       ) ^
+            ( (uint32_t) RSb[ ( t.Y[0] >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) RSb[ ( t.Y[3] >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) RSb[ ( t.Y[2] >> 24 ) & 0xFF ] << 24 );
 
-    X2 = *RK++ ^ \
-            ( (uint32_t) RSb[ ( Y2       ) & 0xFF ]       ) ^
-            ( (uint32_t) RSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+    t.X[2] = *RK++ ^ \
+            ( (uint32_t) RSb[ ( t.Y[2]       ) & 0xFF ]       ) ^
+            ( (uint32_t) RSb[ ( t.Y[1] >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) RSb[ ( t.Y[0] >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) RSb[ ( t.Y[3] >> 24 ) & 0xFF ] << 24 );
 
-    X3 = *RK++ ^ \
-            ( (uint32_t) RSb[ ( Y3       ) & 0xFF ]       ) ^
-            ( (uint32_t) RSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
-            ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
-            ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+    t.X[3] = *RK++ ^ \
+            ( (uint32_t) RSb[ ( t.Y[3]       ) & 0xFF ]       ) ^
+            ( (uint32_t) RSb[ ( t.Y[2] >>  8 ) & 0xFF ] <<  8 ) ^
+            ( (uint32_t) RSb[ ( t.Y[1] >> 16 ) & 0xFF ] << 16 ) ^
+            ( (uint32_t) RSb[ ( t.Y[0] >> 24 ) & 0xFF ] << 24 );
 
-    PUT_UINT32_LE( X0, output,  0 );
-    PUT_UINT32_LE( X1, output,  4 );
-    PUT_UINT32_LE( X2, output,  8 );
-    PUT_UINT32_LE( X3, output, 12 );
+    PUT_UINT32_LE( t.X[0], output,  0 );
+    PUT_UINT32_LE( t.X[1], output,  4 );
+    PUT_UINT32_LE( t.X[2], output,  8 );
+    PUT_UINT32_LE( t.X[3], output, 12 );
 
-    mbedtls_platform_zeroize( &X0, sizeof( X0 ) );
-    mbedtls_platform_zeroize( &X1, sizeof( X1 ) );
-    mbedtls_platform_zeroize( &X2, sizeof( X2 ) );
-    mbedtls_platform_zeroize( &X3, sizeof( X3 ) );
-
-    mbedtls_platform_zeroize( &Y0, sizeof( Y0 ) );
-    mbedtls_platform_zeroize( &Y1, sizeof( Y1 ) );
-    mbedtls_platform_zeroize( &Y2, sizeof( Y2 ) );
-    mbedtls_platform_zeroize( &Y3, sizeof( Y3 ) );
-
-    mbedtls_platform_zeroize( &RK, sizeof( RK ) );
+    mbedtls_platform_zeroize( &t, sizeof( t ) );
 
     return( 0 );
 }
diff --git a/library/ccm.c b/library/ccm.c
index e6ca588..424ee77 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -175,7 +175,7 @@
     if( iv_len < 7 || iv_len > 13 )
         return( MBEDTLS_ERR_CCM_BAD_INPUT );
 
-    if( add_len > 0xFF00 )
+    if( add_len >= 0xFF00 )
         return( MBEDTLS_ERR_CCM_BAD_INPUT );
 
     q = 16 - 1 - (unsigned char) iv_len;
diff --git a/library/check_crypto_config.h b/library/check_crypto_config.h
new file mode 100644
index 0000000..cac90a0
--- /dev/null
+++ b/library/check_crypto_config.h
@@ -0,0 +1,72 @@
+/**
+ * \file check_crypto_config.h
+ *
+ * \brief Consistency checks for PSA configuration options
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/*
+ * It is recommended to include this file from your crypto_config.h
+ * in order to catch dependency issues early.
+ */
+
+#ifndef MBEDTLS_CHECK_CRYPTO_CONFIG_H
+#define MBEDTLS_CHECK_CRYPTO_CONFIG_H
+
+#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \
+    !( defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \
+       defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) )
+#error "PSA_WANT_ALG_DETERMINISTIC_ECDSA defined, but not all prerequisites"
+#endif
+
+#if defined(PSA_WANT_ALG_ECDSA) && \
+    !( defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \
+       defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) )
+#error "PSA_WANT_ALG_ECDSA defined, but not all prerequisites"
+#endif
+
+#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \
+    !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
+       defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) )
+#error "PSA_WANT_ALG_RSA_PKCS1V15_CRYPT defined, but not all prerequisites"
+#endif
+
+#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) && \
+    !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
+       defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) )
+#error "PSA_WANT_ALG_RSA_PKCS1V15_SIGN defined, but not all prerequisites"
+#endif
+
+#if defined(PSA_WANT_ALG_RSA_OAEP) && \
+    !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
+       defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) )
+#error "PSA_WANT_ALG_RSA_OAEP defined, but not all prerequisites"
+#endif
+
+#if defined(PSA_WANT_ALG_RSA_PSS) && \
+    !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
+       defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) )
+#error "PSA_WANT_ALG_RSA_PSS defined, but not all prerequisites"
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) && \
+    !defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+#error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR defined, but not all prerequisites"
+#endif
+
+#endif /* MBEDTLS_CHECK_CRYPTO_CONFIG_H */
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index 8eb2ec0..57eb3cb 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -753,7 +753,7 @@
     MBEDTLS_MODE_ECB,
     128,
     "CAMELLIA-128-ECB",
-    16,
+    0,
     0,
     16,
     &camellia_info
@@ -764,7 +764,7 @@
     MBEDTLS_MODE_ECB,
     192,
     "CAMELLIA-192-ECB",
-    16,
+    0,
     0,
     16,
     &camellia_info
@@ -775,7 +775,7 @@
     MBEDTLS_MODE_ECB,
     256,
     "CAMELLIA-256-ECB",
-    16,
+    0,
     0,
     16,
     &camellia_info
@@ -1129,7 +1129,7 @@
     MBEDTLS_MODE_ECB,
     128,
     "ARIA-128-ECB",
-    16,
+    0,
     0,
     16,
     &aria_info
@@ -1140,7 +1140,7 @@
     MBEDTLS_MODE_ECB,
     192,
     "ARIA-192-ECB",
-    16,
+    0,
     0,
     16,
     &aria_info
@@ -1151,7 +1151,7 @@
     MBEDTLS_MODE_ECB,
     256,
     "ARIA-256-ECB",
-    16,
+    0,
     0,
     16,
     &aria_info
@@ -1553,7 +1553,7 @@
     MBEDTLS_MODE_ECB,
     MBEDTLS_KEY_LENGTH_DES,
     "DES-ECB",
-    8,
+    0,
     0,
     8,
     &des_info
@@ -1604,7 +1604,7 @@
     MBEDTLS_MODE_ECB,
     MBEDTLS_KEY_LENGTH_DES_EDE,
     "DES-EDE-ECB",
-    8,
+    0,
     0,
     8,
     &des_ede_info
@@ -1655,7 +1655,7 @@
     MBEDTLS_MODE_ECB,
     MBEDTLS_KEY_LENGTH_DES_EDE3,
     "DES-EDE3-ECB",
-    8,
+    0,
     0,
     8,
     &des_ede3_info
@@ -1770,7 +1770,7 @@
     MBEDTLS_MODE_ECB,
     128,
     "BLOWFISH-ECB",
-    8,
+    0,
     MBEDTLS_CIPHER_VARIABLE_KEY_LEN,
     8,
     &blowfish_info
diff --git a/library/ecp.c b/library/ecp.c
index 5d00de5..05a0b01 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -546,9 +546,12 @@
 #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
     { MBEDTLS_ECP_DP_SECP192K1,    18,     192,    "secp192k1"         },
 #endif
-#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
     { MBEDTLS_ECP_DP_CURVE25519,   29,     256,    "x25519"            },
 #endif
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+    { MBEDTLS_ECP_DP_CURVE448,     30,     448,    "x448"              },
+#endif
     { MBEDTLS_ECP_DP_NONE,          0,     0,      NULL                },
 };
 
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index 4bf660e..5250a7b 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -17,7 +17,7 @@
  *  limitations under the License.
  */
 
-#if defined(__linux__)
+#if defined(__linux__) && !defined(_GNU_SOURCE)
 /* Ensure that syscall() is available even when compiling with -std=c99 */
 #define _GNU_SOURCE
 #endif
diff --git a/library/error.c b/library/error.c
index cba61e9..901a369 100644
--- a/library/error.c
+++ b/library/error.c
@@ -19,20 +19,20 @@
 
 #include "common.h"
 
-#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
-#include <string.h>
-#endif
+#include "mbedtls/error.h"
+
+#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
+
+#if defined(MBEDTLS_ERROR_C)
 
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
 #define mbedtls_snprintf snprintf
-#define mbedtls_time_t   time_t
 #endif
 
-#if defined(MBEDTLS_ERROR_C)
-
 #include <stdio.h>
+#include <string.h>
 
 #if defined(MBEDTLS_AES_C)
 #include "mbedtls/aes.h"
@@ -960,8 +960,6 @@
 
 #else /* MBEDTLS_ERROR_C */
 
-#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
-
 /*
  * Provide an non-function in case MBEDTLS_ERROR_C is not defined
  */
@@ -973,6 +971,6 @@
         buf[0] = '\0';
 }
 
-#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */
-
 #endif /* MBEDTLS_ERROR_C */
+
+#endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */
diff --git a/library/net_sockets.c b/library/net_sockets.c
index 3f96cab..54c2b47 100644
--- a/library/net_sockets.c
+++ b/library/net_sockets.c
@@ -318,7 +318,7 @@
 
 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) ||  \
     defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \
-    defined(socklen_t)
+    defined(socklen_t) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L)
     socklen_t n = (socklen_t) sizeof( client_addr );
     socklen_t type_len = (socklen_t) sizeof( type );
 #else
diff --git a/library/pk.c b/library/pk.c
index 9a3bcb0..ecf002d 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -150,11 +150,12 @@
 /*
  * Initialise a PSA-wrapping context
  */
-int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, const psa_key_handle_t key )
+int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx,
+                             const psa_key_id_t key )
 {
     const mbedtls_pk_info_t * const info = &mbedtls_pk_opaque_info;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_handle_t *pk_ctx;
+    psa_key_id_t *pk_ctx;
     psa_key_type_t type;
 
     if( ctx == NULL || ctx->pk_info != NULL )
@@ -174,7 +175,7 @@
 
     ctx->pk_info = info;
 
-    pk_ctx = (psa_key_handle_t *) ctx->pk_ctx;
+    pk_ctx = (psa_key_id_t *) ctx->pk_ctx;
     *pk_ctx = key;
 
     return( 0 );
@@ -587,12 +588,12 @@
  * Currently only works for EC private keys.
  */
 int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk,
-                               psa_key_handle_t *handle,
+                               psa_key_id_t *key,
                                psa_algorithm_t hash_alg )
 {
 #if !defined(MBEDTLS_ECP_C)
     ((void) pk);
-    ((void) handle);
+    ((void) key);
     ((void) hash_alg);
     return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
 #else
@@ -624,14 +625,14 @@
     psa_set_key_algorithm( &attributes, PSA_ALG_ECDSA(hash_alg) );
 
     /* import private key into PSA */
-    if( PSA_SUCCESS != psa_import_key( &attributes, d, d_len, handle ) )
+    if( PSA_SUCCESS != psa_import_key( &attributes, d, d_len, key ) )
         return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
 
     /* make PK context wrap the key slot */
     mbedtls_pk_free( pk );
     mbedtls_pk_init( pk );
 
-    return( mbedtls_pk_setup_opaque( pk, *handle ) );
+    return( mbedtls_pk_setup_opaque( pk, *key ) );
 #endif /* MBEDTLS_ECP_C */
 }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 903c53b..107e912 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -543,7 +543,7 @@
     mbedtls_ecdsa_context *ctx = ctx_arg;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_handle_t key_handle = 0;
+    psa_key_id_t key_id = 0;
     psa_status_t status;
     mbedtls_pk_context key;
     int key_len;
@@ -576,7 +576,7 @@
 
     status = psa_import_key( &attributes,
                              buf + sizeof( buf ) - key_len, key_len,
-                             &key_handle );
+                             &key_id );
     if( status != PSA_SUCCESS )
     {
         ret = mbedtls_psa_err_translate_pk( status );
@@ -598,7 +598,7 @@
         goto cleanup;
     }
 
-    if( psa_verify_hash( key_handle, psa_sig_md,
+    if( psa_verify_hash( key_id, psa_sig_md,
                          hash, hash_len,
                          buf, 2 * signature_part_size )
          != PSA_SUCCESS )
@@ -615,7 +615,7 @@
     ret = 0;
 
 cleanup:
-    psa_destroy_key( key_handle );
+    psa_destroy_key( key_id );
     return( ret );
 }
 #else /* MBEDTLS_USE_PSA_CRYPTO */
@@ -870,7 +870,7 @@
 
 static void *pk_opaque_alloc_wrap( void )
 {
-    void *ctx = mbedtls_calloc( 1, sizeof( psa_key_handle_t ) );
+    void *ctx = mbedtls_calloc( 1, sizeof( psa_key_id_t ) );
 
     /* no _init() function to call, an calloc() already zeroized */
 
@@ -879,13 +879,13 @@
 
 static void pk_opaque_free_wrap( void *ctx )
 {
-    mbedtls_platform_zeroize( ctx, sizeof( psa_key_handle_t ) );
+    mbedtls_platform_zeroize( ctx, sizeof( psa_key_id_t ) );
     mbedtls_free( ctx );
 }
 
 static size_t pk_opaque_get_bitlen( const void *ctx )
 {
-    const psa_key_handle_t *key = (const psa_key_handle_t *) ctx;
+    const psa_key_id_t *key = (const psa_key_id_t *) ctx;
     size_t bits;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
@@ -1008,7 +1008,7 @@
     ((void) p_rng);
     return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
 #else /* !MBEDTLS_ECDSA_C */
-    const psa_key_handle_t *key = (const psa_key_handle_t *) ctx;
+    const psa_key_id_t *key = (const psa_key_id_t *) ctx;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_algorithm_t alg = PSA_ALG_ECDSA( mbedtls_psa_translate_md( md_alg ) );
     size_t buf_len;
diff --git a/library/pkparse.c b/library/pkparse.c
index a106dbe..0590f2b 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -662,7 +662,7 @@
         ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
 
     if( ret == 0 && *p != end )
-        ret = MBEDTLS_ERR_PK_INVALID_PUBKEY
+        ret = MBEDTLS_ERR_PK_INVALID_PUBKEY +
               MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
 
     if( ret != 0 )
diff --git a/library/pkwrite.c b/library/pkwrite.c
index b317ccf..0da3698 100644
--- a/library/pkwrite.c
+++ b/library/pkwrite.c
@@ -198,13 +198,13 @@
     if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_OPAQUE )
     {
         size_t buffer_size;
-        psa_key_handle_t* key_slot = (psa_key_handle_t*) key->pk_ctx;
+        psa_key_id_t* key_id = (psa_key_id_t*) key->pk_ctx;
 
         if ( *p < start )
             return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
 
         buffer_size = (size_t)( *p - start );
-        if ( psa_export_public_key( *key_slot, start, buffer_size, &len )
+        if ( psa_export_public_key( *key_id, start, buffer_size, &len )
              != PSA_SUCCESS )
         {
             return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
@@ -265,12 +265,12 @@
     {
         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
         psa_key_type_t key_type;
-        psa_key_handle_t handle;
+        psa_key_id_t key_id;
         psa_ecc_family_t curve;
         size_t bits;
 
-        handle = *((psa_key_handle_t*) key->pk_ctx );
-        if( PSA_SUCCESS != psa_get_key_attributes( handle, &attributes ) )
+        key_id = *((psa_key_id_t*) key->pk_ctx );
+        if( PSA_SUCCESS != psa_get_key_attributes( key_id, &attributes ) )
             return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
         key_type = psa_get_key_type( &attributes );
         bits = psa_get_key_bits( &attributes );
diff --git a/library/platform_util.c b/library/platform_util.c
index 4e1d617..98fe5de 100644
--- a/library/platform_util.c
+++ b/library/platform_util.c
@@ -84,7 +84,7 @@
 
 #if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) ||     \
        ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) &&                     \
-         _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) )
+         _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) )
 /*
  * This is a convenience shorthand macro to avoid checking the long
  * preprocessor conditions above. Ideally, we could expose this macro in
@@ -98,7 +98,7 @@
 
 #endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) ||     \
              ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) &&                     \
-                _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */
+                _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */
 
 struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt,
                                       struct tm *tm_buf )
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 931e2e9..66c8f65 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -22,6 +22,10 @@
 
 #if defined(MBEDTLS_PSA_CRYPTO_C)
 
+#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
+#include "check_crypto_config.h"
+#endif
+
 #include "psa_crypto_service_integration.h"
 #include "psa/crypto.h"
 
@@ -199,7 +203,7 @@
         case MBEDTLS_ERR_CIPHER_INVALID_PADDING:
             return( PSA_ERROR_INVALID_PADDING );
         case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED:
-            return( PSA_ERROR_BAD_STATE );
+            return( PSA_ERROR_INVALID_ARGUMENT );
         case MBEDTLS_ERR_CIPHER_AUTH_FAILED:
             return( PSA_ERROR_INVALID_SIGNATURE );
         case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT:
@@ -370,7 +374,15 @@
 }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
-#if defined(MBEDTLS_ECP_C)
+/* For now the MBEDTLS_PSA_ACCEL_ guards are also used here since the
+ * current test driver in key_management.c is using this function
+ * when accelerators are used for ECC key pair and public key.
+ * Once that dependency is resolved these guards can be removed.
+ */
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
+    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
 mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_family_t curve,
                                                size_t byte_length )
 {
@@ -438,7 +450,10 @@
             return( MBEDTLS_ECP_DP_NONE );
     }
 }
-#endif /* defined(MBEDTLS_ECP_C) */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
+        * defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) */
 
 static psa_status_t validate_unstructured_key_bit_size( psa_key_type_t type,
                                                         size_t bits )
@@ -447,9 +462,7 @@
     switch( type )
     {
         case PSA_KEY_TYPE_RAW_DATA:
-#if defined(MBEDTLS_MD_C)
         case PSA_KEY_TYPE_HMAC:
-#endif
         case PSA_KEY_TYPE_DERIVE:
             break;
 #if defined(MBEDTLS_AES_C)
@@ -491,9 +504,13 @@
     return( PSA_SUCCESS );
 }
 
-#if defined(MBEDTLS_RSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
 
-#if defined(MBEDTLS_PK_PARSE_C)
 /* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes
  * that are not a multiple of 8) well. For example, there is only
  * mbedtls_rsa_get_len(), which returns a number of bytes, and no
@@ -515,7 +532,6 @@
     mbedtls_mpi_free( &n );
     return( status );
 }
-#endif /* MBEDTLS_PK_PARSE_C */
 
 /** Load the contents of a key buffer into an internal RSA representation
  *
@@ -532,7 +548,6 @@
                                                  size_t data_length,
                                                  mbedtls_rsa_context **p_rsa )
 {
-#if defined(MBEDTLS_PK_PARSE_C)
     psa_status_t status;
     mbedtls_pk_context ctx;
     size_t bits;
@@ -577,15 +592,18 @@
 exit:
     mbedtls_pk_free( &ctx );
     return( status );
-#else
-    (void) data;
-    (void) data_length;
-    (void) type;
-    (void) rsa;
-    return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* MBEDTLS_PK_PARSE_C */
 }
 
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
+
 /** Export an RSA key to export representation
  *
  * \param[in] type          The type of key (public/private) to export
@@ -709,9 +727,15 @@
 
     return( PSA_SUCCESS );
 }
-#endif /* defined(MBEDTLS_RSA_C) */
 
-#if defined(MBEDTLS_ECP_C)
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
 /** Load the contents of a key buffer into an internal ECP representation
  *
  * \param[in] type          The type of key contained in \p data.
@@ -739,7 +763,7 @@
          * - The byte 0x04;
          * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
          * - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
-         * So its data length is 2m+1 where n is the key size in bits.
+         * So its data length is 2m+1 where m is the curve size in bits.
          */
         if( ( data_length & 1 ) == 0 )
             return( PSA_ERROR_INVALID_ARGUMENT );
@@ -811,7 +835,14 @@
 
     return( status );
 }
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
 
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
 /** Export an ECP key to export representation
  *
  * \param[in] type          The type of key (public/private) to export
@@ -930,7 +961,8 @@
 
     return( PSA_SUCCESS );
 }
-#endif /* defined(MBEDTLS_ECP_C) */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
 
 /** Return the size of the key in the given slot, in bits.
  *
@@ -969,14 +1001,45 @@
     return( PSA_SUCCESS );
 }
 
-/** Import key data into a slot. `slot->attr.type` must have been set
- * previously. This function assumes that the slot does not contain
- * any key material yet. On failure, the slot content is unchanged. */
-psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
-                                       const uint8_t *data,
-                                       size_t data_length )
+psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot,
+                                              const uint8_t* data,
+                                              size_t data_length )
+{
+    psa_status_t status = psa_allocate_buffer_to_slot( slot,
+                                                       data_length );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    memcpy( slot->data.key.data, data, data_length );
+    return( PSA_SUCCESS );
+}
+
+/** Import key data into a slot.
+ *
+ * `slot->type` must have been set previously.
+ * This function assumes that the slot does not contain any key material yet.
+ * On failure, the slot content is unchanged.
+ *
+ * Persistent storage is not affected.
+ *
+ * \param[in,out] slot  The key slot to import data into.
+ *                      Its `type` field must have previously been set to
+ *                      the desired key type.
+ *                      It must not contain any key material yet.
+ * \param[in] data      Buffer containing the key material to parse and import.
+ * \param data_length   Size of \p data in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ */
+static psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
+                                              const uint8_t *data,
+                                              size_t data_length )
 {
     psa_status_t status = PSA_SUCCESS;
+    size_t bit_size;
 
     /* zero-length keys are never supported. */
     if( data_length == 0 )
@@ -984,7 +1047,7 @@
 
     if( key_type_is_raw_bytes( slot->attr.type ) )
     {
-        size_t bit_size = PSA_BYTES_TO_BITS( data_length );
+        bit_size = PSA_BYTES_TO_BITS( data_length );
 
         /* Ensure that the bytes-to-bits conversion hasn't overflown. */
         if( data_length > SIZE_MAX / 8 )
@@ -1000,47 +1063,69 @@
             return( status );
 
         /* Allocate memory for the key */
-        status = psa_allocate_buffer_to_slot( slot, data_length );
+        status = psa_copy_key_material_into_slot( slot, data, data_length );
         if( status != PSA_SUCCESS )
             return( status );
 
-        /* copy key into allocated buffer */
-        memcpy( slot->data.key.data, data, data_length );
-
         /* Write the actual key size to the slot.
          * psa_start_key_creation() wrote the size declared by the
          * caller, which may be 0 (meaning unspecified) or wrong. */
         slot->attr.bits = (psa_key_bits_t) bit_size;
+
+        return( PSA_SUCCESS );
     }
-    else if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
+    else if( PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) )
     {
-#if defined(MBEDTLS_ECP_C)
-        status = psa_import_ecp_key( slot,
-                                     data, data_length );
-#else
-        /* No drivers have been implemented yet, so without mbed TLS backing
-         * there's no way to do ECP with the current library. */
+        /* Try validation through accelerators first. */
+        bit_size = slot->attr.bits;
+        psa_key_attributes_t attributes = {
+          .core = slot->attr
+        };
+        status = psa_driver_wrapper_validate_key( &attributes,
+                                                  data,
+                                                  data_length,
+                                                  &bit_size );
+        if( status == PSA_SUCCESS )
+        {
+            /* Key has been validated successfully by an accelerator.
+             * Copy key material into slot. */
+            status = psa_copy_key_material_into_slot( slot, data, data_length );
+            if( status != PSA_SUCCESS )
+                return( status );
+
+            slot->attr.bits = (psa_key_bits_t) bit_size;
+            return( PSA_SUCCESS );
+        }
+        else if( status != PSA_ERROR_NOT_SUPPORTED )
+            return( status );
+
+        /* Key format is not supported by any accelerator, try software fallback
+         * if present. */
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
+        if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
+        {
+            return( psa_import_ecp_key( slot, data, data_length ) );
+        }
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
+        if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
+        {
+            return( psa_import_rsa_key( slot, data, data_length ) );
+        }
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+
+        /* Fell through the fallback as well, so have nothing else to try. */
         return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* defined(MBEDTLS_ECP_C) */
-    }
-    else if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
-    {
-#if defined(MBEDTLS_RSA_C)
-        status = psa_import_rsa_key( slot,
-                                     data, data_length );
-#else
-        /* No drivers have been implemented yet, so without mbed TLS backing
-         * there's no way to do RSA with the current library. */
-        status = PSA_ERROR_NOT_SUPPORTED;
-#endif /* defined(MBEDTLS_RSA_C) */
     }
     else
     {
         /* Unknown key type */
         return( PSA_ERROR_NOT_SUPPORTED );
     }
-
-    return( status );
 }
 
 /** Calculate the intersection of two algorithm usage policies.
@@ -1084,6 +1169,15 @@
         return( ( policy_alg & ~PSA_ALG_HASH_MASK ) ==
                 ( requested_alg & ~PSA_ALG_HASH_MASK ) );
     }
+    /* If policy_alg is a generic key agreement operation, then using it for
+     * a key derivation with that key agreement should also be allowed. This
+     * behaviour is expected to be defined in a future specification version. */
+    if( PSA_ALG_IS_RAW_KEY_AGREEMENT( policy_alg ) &&
+        PSA_ALG_IS_KEY_AGREEMENT( requested_alg ) )
+    {
+        return( PSA_ALG_KEY_AGREEMENT_GET_BASE( requested_alg ) ==
+                policy_alg );
+    }
     /* If it isn't permitted, it's forbidden. */
     return( 0 );
 }
@@ -1129,22 +1223,31 @@
     return( PSA_SUCCESS );
 }
 
-/** Retrieve a slot which must contain a key. The key must have allow all the
- * usage flags set in \p usage. If \p alg is nonzero, the key must allow
- * operations with this algorithm. */
-static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle,
-                                           psa_key_slot_t **p_slot,
-                                           psa_key_usage_t usage,
-                                           psa_algorithm_t alg )
+/** Get the description of a key given its identifier and policy constraints
+ *  and lock it.
+ *
+ * The key must have allow all the usage flags set in \p usage. If \p alg is
+ * nonzero, the key must allow operations with this algorithm.
+ *
+ * In case of a persistent key, the function loads the description of the key
+ * into a key slot if not already done.
+ *
+ * On success, the returned key slot is locked. It is the responsibility of
+ * the caller to unlock the key slot when it does not access it anymore.
+ */
+static psa_status_t psa_get_and_lock_key_slot_with_policy(
+    mbedtls_svc_key_id_t key,
+    psa_key_slot_t **p_slot,
+    psa_key_usage_t usage,
+    psa_algorithm_t alg )
 {
-    psa_status_t status;
-    psa_key_slot_t *slot = NULL;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
 
-    *p_slot = NULL;
-
-    status = psa_get_key_slot( handle, &slot );
+    status = psa_get_and_lock_key_slot( key, p_slot );
     if( status != PSA_SUCCESS )
         return( status );
+    slot = *p_slot;
 
     /* Enforce that usage policy for the key slot contains all the flags
      * required by the usage parameter. There is one exception: public
@@ -1152,45 +1255,61 @@
      * if they had the export flag. */
     if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) )
         usage &= ~PSA_KEY_USAGE_EXPORT;
+
+    status = PSA_ERROR_NOT_PERMITTED;
     if( ( slot->attr.policy.usage & usage ) != usage )
-        return( PSA_ERROR_NOT_PERMITTED );
+        goto error;
 
     /* Enforce that the usage policy permits the requested algortihm. */
     if( alg != 0 && ! psa_key_policy_permits( &slot->attr.policy, alg ) )
-        return( PSA_ERROR_NOT_PERMITTED );
+        goto error;
 
-    *p_slot = slot;
     return( PSA_SUCCESS );
+
+error:
+    *p_slot = NULL;
+    psa_unlock_key_slot( slot );
+
+    return( status );
 }
 
-/** Retrieve a slot which must contain a transparent key.
+/** Get a key slot containing a transparent key and lock it.
  *
  * A transparent key is a key for which the key material is directly
  * available, as opposed to a key in a secure element.
  *
- * This is a temporary function to use instead of psa_get_key_from_slot()
- * until secure element support is fully implemented.
+ * This is a temporary function to use instead of
+ * psa_get_and_lock_key_slot_with_policy() until secure element support is
+ * fully implemented.
+ *
+ * On success, the returned key slot is locked. It is the responsibility of the
+ * caller to unlock the key slot when it does not access it anymore.
  */
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-static psa_status_t psa_get_transparent_key( psa_key_handle_t handle,
-                                             psa_key_slot_t **p_slot,
-                                             psa_key_usage_t usage,
-                                             psa_algorithm_t alg )
+static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy(
+    mbedtls_svc_key_id_t key,
+    psa_key_slot_t **p_slot,
+    psa_key_usage_t usage,
+    psa_algorithm_t alg )
 {
-    psa_status_t status = psa_get_key_from_slot( handle, p_slot, usage, alg );
+    psa_status_t status = psa_get_and_lock_key_slot_with_policy( key, p_slot,
+                                                                 usage, alg );
     if( status != PSA_SUCCESS )
         return( status );
+
     if( psa_key_slot_is_external( *p_slot ) )
     {
+        psa_unlock_key_slot( *p_slot );
         *p_slot = NULL;
         return( PSA_ERROR_NOT_SUPPORTED );
     }
+
     return( PSA_SUCCESS );
 }
 #else /* MBEDTLS_PSA_CRYPTO_SE_C */
 /* With no secure element support, all keys are transparent. */
-#define psa_get_transparent_key( handle, p_slot, usage, alg )   \
-    psa_get_key_from_slot( handle, p_slot, usage, alg )
+#define psa_get_and_lock_transparent_key_slot_with_policy( key, p_slot, usage, alg )   \
+    psa_get_and_lock_key_slot_with_policy( key, p_slot, usage, alg )
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
 /** Wipe key data from a slot. Preserve metadata such as the policy. */
@@ -1221,6 +1340,22 @@
 psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot )
 {
     psa_status_t status = psa_remove_key_data_from_memory( slot );
+
+    /*
+     * As the return error code may not be handled in case of multiple errors,
+     * do our best to report an unexpected lock counter: if available
+     * call MBEDTLS_PARAM_FAILED that may terminate execution (if called as
+     * part of the execution of a test suite this will stop the test suite
+     * execution).
+     */
+    if( slot->lock_count != 1 )
+    {
+#ifdef MBEDTLS_CHECK_PARAMS
+        MBEDTLS_PARAM_FAILED( slot->lock_count == 1 );
+#endif
+        status = PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
     /* Multipart operations may still be using the key. This is safe
      * because all multipart operation objects are independent from
      * the key slot: if they need to access the key after the setup
@@ -1233,7 +1368,7 @@
     return( status );
 }
 
-psa_status_t psa_destroy_key( psa_key_handle_t handle )
+psa_status_t psa_destroy_key( mbedtls_svc_key_id_t key )
 {
     psa_key_slot_t *slot;
     psa_status_t status; /* status of the last operation */
@@ -1242,13 +1377,33 @@
     psa_se_drv_table_entry_t *driver;
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
-    if( handle == 0 )
+    if( mbedtls_svc_key_id_is_null( key ) )
         return( PSA_SUCCESS );
 
-    status = psa_get_key_slot( handle, &slot );
+    /*
+     * Get the description of the key in a key slot. In case of a persistent
+     * key, this will load the key description from persistent memory if not
+     * done yet. We cannot avoid this loading as without it we don't know if
+     * the key is operated by an SE or not and this information is needed by
+     * the current implementation.
+     */
+    status = psa_get_and_lock_key_slot( key, &slot );
     if( status != PSA_SUCCESS )
         return( status );
 
+    /*
+     * If the key slot containing the key description is under access by the
+     * library (apart from the present access), the key cannot be destroyed
+     * yet. For the time being, just return in error. Eventually (to be
+     * implemented), the key should be destroyed when all accesses have
+     * stopped.
+     */
+    if( slot->lock_count > 1 )
+    {
+       psa_unlock_key_slot( slot );
+       return( PSA_ERROR_GENERIC_ERROR );
+    }
+
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
     driver = psa_get_se_driver_entry( slot->attr.lifetime );
     if( driver != NULL )
@@ -1284,7 +1439,7 @@
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-    if( slot->attr.lifetime != PSA_KEY_LIFETIME_VOLATILE )
+    if( ! PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) )
     {
         status = psa_destroy_persistent_key( slot->attr.id );
         if( overall_status == PSA_SUCCESS )
@@ -1368,7 +1523,8 @@
     return( PSA_SUCCESS );
 }
 
-#if defined(MBEDTLS_RSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
 static psa_status_t psa_get_rsa_public_exponent(
     const mbedtls_rsa_context *rsa,
     psa_key_attributes_t *attributes )
@@ -1408,19 +1564,21 @@
         mbedtls_free( buffer );
     return( mbedtls_to_psa_error( ret ) );
 }
-#endif /* MBEDTLS_RSA_C */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
 
 /** Retrieve all the publicly-accessible attributes of a key.
  */
-psa_status_t psa_get_key_attributes( psa_key_handle_t handle,
+psa_status_t psa_get_key_attributes( mbedtls_svc_key_id_t key,
                                      psa_key_attributes_t *attributes )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
-    psa_status_t status;
 
     psa_reset_key_attributes( attributes );
 
-    status = psa_get_key_from_slot( handle, &slot, 0, 0 );
+    status = psa_get_and_lock_key_slot_with_policy( key, &slot, 0, 0 );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -1435,7 +1593,8 @@
 
     switch( slot->attr.type )
     {
-#if defined(MBEDTLS_RSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
         case PSA_KEY_TYPE_RSA_KEY_PAIR:
         case PSA_KEY_TYPE_RSA_PUBLIC_KEY:
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@@ -1462,7 +1621,8 @@
                 mbedtls_free( rsa );
             }
             break;
-#endif /* MBEDTLS_RSA_C */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
         default:
             /* Nothing else to do. */
             break;
@@ -1470,7 +1630,10 @@
 
     if( status != PSA_SUCCESS )
         psa_reset_key_attributes( attributes );
-    return( status );
+
+    unlock_status = psa_unlock_key_slot( slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@@ -1558,13 +1721,24 @@
             /* Exporting private -> private */
             return( psa_internal_export_key_buffer( slot, data, data_size, data_length ) );
         }
+
         /* Need to export the public part of a private key,
-         * so conversion is needed */
+         * so conversion is needed. Try the accelerators first. */
+        psa_status_t status = psa_driver_wrapper_export_public_key( slot,
+                                                                    data,
+                                                                    data_size,
+                                                                    data_length );
+
+        if( status != PSA_ERROR_NOT_SUPPORTED ||
+            psa_key_lifetime_is_external( slot->attr.lifetime ) )
+            return( status );
+
         if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
         {
-#if defined(MBEDTLS_RSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
             mbedtls_rsa_context *rsa = NULL;
-            psa_status_t status = psa_load_rsa_representation(
+            status = psa_load_rsa_representation(
                                     slot->attr.type,
                                     slot->data.key.data,
                                     slot->data.key.bytes,
@@ -1585,13 +1759,15 @@
 #else
             /* We don't know how to convert a private RSA key to public. */
             return( PSA_ERROR_NOT_SUPPORTED );
-#endif
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
         }
         else
         {
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
             mbedtls_ecp_keypair *ecp = NULL;
-            psa_status_t status = psa_load_ecp_representation(
+            status = psa_load_ecp_representation(
                                     slot->attr.type,
                                     slot->data.key.data,
                                     slot->data.key.bytes,
@@ -1613,7 +1789,8 @@
 #else
             /* We don't know how to convert a private ECC key to public */
             return( PSA_ERROR_NOT_SUPPORTED );
-#endif
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
         }
     }
     else
@@ -1625,13 +1802,14 @@
     }
 }
 
-psa_status_t psa_export_key( psa_key_handle_t handle,
+psa_status_t psa_export_key( mbedtls_svc_key_id_t key,
                              uint8_t *data,
                              size_t data_size,
                              size_t *data_length )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
-    psa_status_t status;
 
     /* Set the key to empty now, so that even when there are errors, we always
      * set data_length to a value between 0 and data_size. On error, setting
@@ -1640,22 +1818,28 @@
     *data_length = 0;
 
     /* Export requires the EXPORT flag. There is an exception for public keys,
-     * which don't require any flag, but psa_get_key_from_slot takes
-     * care of this. */
-    status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_EXPORT, 0 );
+     * which don't require any flag, but
+     * psa_get_and_lock_key_slot_with_policy() takes care of this.
+     */
+    status = psa_get_and_lock_key_slot_with_policy( key, &slot,
+                                                    PSA_KEY_USAGE_EXPORT, 0 );
     if( status != PSA_SUCCESS )
         return( status );
-    return( psa_internal_export_key( slot, data, data_size,
-                                     data_length, 0 ) );
+
+    status = psa_internal_export_key( slot, data, data_size, data_length, 0 );
+    unlock_status = psa_unlock_key_slot( slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
-psa_status_t psa_export_public_key( psa_key_handle_t handle,
+psa_status_t psa_export_public_key( mbedtls_svc_key_id_t key,
                                     uint8_t *data,
                                     size_t data_size,
                                     size_t *data_length )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
-    psa_status_t status;
 
     /* Set the key to empty now, so that even when there are errors, we always
      * set data_length to a value between 0 and data_size. On error, setting
@@ -1664,11 +1848,14 @@
     *data_length = 0;
 
     /* Exporting a public key doesn't require a usage flag. */
-    status = psa_get_key_from_slot( handle, &slot, 0, 0 );
+    status = psa_get_and_lock_key_slot_with_policy( key, &slot, 0, 0 );
     if( status != PSA_SUCCESS )
         return( status );
-    return( psa_internal_export_key( slot, data, data_size,
-                                     data_length, 1 ) );
+
+    status = psa_internal_export_key( slot, data, data_size, data_length, 1 );
+    unlock_status = psa_unlock_key_slot( slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
 #if defined(static_assert)
@@ -1718,17 +1905,29 @@
     psa_se_drv_table_entry_t **p_drv )
 {
     psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+    psa_key_lifetime_t lifetime = psa_get_key_lifetime( attributes );
+    mbedtls_svc_key_id_t key = psa_get_key_id( attributes );
 
-    status = psa_validate_key_location( psa_get_key_lifetime( attributes ),
-                                        p_drv );
+    status = psa_validate_key_location( lifetime, p_drv );
     if( status != PSA_SUCCESS )
         return( status );
 
-    status = psa_validate_key_persistence( psa_get_key_lifetime( attributes ),
-                                           psa_get_key_id( attributes ) );
+    status = psa_validate_key_persistence( lifetime );
     if( status != PSA_SUCCESS )
         return( status );
 
+    if ( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
+    {
+        if( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key ) != 0 )
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+    else
+    {
+        status = psa_validate_key_id( psa_get_key_id( attributes ), 0 );
+        if( status != PSA_SUCCESS )
+            return( status );
+    }
+
     status = psa_validate_key_policy( &attributes->core.policy );
     if( status != PSA_SUCCESS )
         return( status );
@@ -1756,15 +1955,18 @@
  *
  * This function is intended to be used as follows:
  * -# Call psa_start_key_creation() to allocate a key slot, prepare
- *    it with the specified attributes, and assign it a handle.
+ *    it with the specified attributes, and in case of a volatile key assign it
+ *    a volatile key identifier.
  * -# Populate the slot with the key material.
  * -# Call psa_finish_key_creation() to finalize the creation of the slot.
  * In case of failure at any step, stop the sequence and call
  * psa_fail_key_creation().
  *
+ * On success, the key slot is locked. It is the responsibility of the caller
+ * to unlock the key slot when it does not access it anymore.
+ *
  * \param method            An identification of the calling function.
  * \param[in] attributes    Key attributes for the new key.
- * \param[out] handle       On success, a handle for the allocated slot.
  * \param[out] p_slot       On success, a pointer to the prepared slot.
  * \param[out] p_drv        On any return, the driver for the key, if any.
  *                          NULL for a transparent key.
@@ -1777,11 +1979,11 @@
 static psa_status_t psa_start_key_creation(
     psa_key_creation_method_t method,
     const psa_key_attributes_t *attributes,
-    psa_key_handle_t *handle,
     psa_key_slot_t **p_slot,
     psa_se_drv_table_entry_t **p_drv )
 {
     psa_status_t status;
+    psa_key_id_t volatile_key_id;
     psa_key_slot_t *slot;
 
     (void) method;
@@ -1791,7 +1993,7 @@
     if( status != PSA_SUCCESS )
         return( status );
 
-    status = psa_get_empty_key_slot( handle, p_slot );
+    status = psa_get_empty_key_slot( &volatile_key_id, p_slot );
     if( status != PSA_SUCCESS )
         return( status );
     slot = *p_slot;
@@ -1800,9 +2002,19 @@
      * creation mechanism to verify that this information is correct.
      * It's automatically correct for mechanisms that use the bit-size as
      * an input (generate, device) but not for those where the bit-size
-     * is optional (import, copy). */
+     * is optional (import, copy). In case of a volatile key, assign it the
+     * volatile key identifier associated to the slot returned to contain its
+     * definition. */
 
     slot->attr = attributes->core;
+    if( PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) )
+    {
+#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+        slot->attr.id = volatile_key_id;
+#else
+        slot->attr.id.key_id = volatile_key_id;
+#endif
+    }
 
     /* Erase external-only flags from the internal copy. To access
      * external-only flags, query `attributes`. Thanks to the check
@@ -1858,7 +2070,7 @@
     }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
-    return( status );
+    return( PSA_SUCCESS );
 }
 
 /** Finalize the creation of a key once its key material has been set.
@@ -1869,18 +2081,25 @@
  * See the documentation of psa_start_key_creation() for the intended use
  * of this function.
  *
+ * If the finalization succeeds, the function unlocks the key slot (it was
+ * locked by psa_start_key_creation()) and the key slot cannot be accessed
+ * anymore as part of the key creation process.
+ *
  * \param[in,out] slot  Pointer to the slot with key material.
  * \param[in] driver    The secure element driver for the key,
  *                      or NULL for a transparent key.
+ * \param[out] key      On success, identifier of the key. Note that the
+ *                      key identifier is also stored in the key slot.
  *
  * \retval #PSA_SUCCESS
- *         The key was successfully created. The handle is now valid.
+ *         The key was successfully created.
  * \return If this function fails, the key slot is an invalid state.
  *         You must call psa_fail_key_creation() to wipe and free the slot.
  */
 static psa_status_t psa_finish_key_creation(
     psa_key_slot_t *slot,
-    psa_se_drv_table_entry_t *driver )
+    psa_se_drv_table_entry_t *driver,
+    mbedtls_svc_key_id_t *key)
 {
     psa_status_t status = PSA_SUCCESS;
     (void) slot;
@@ -1897,13 +2116,9 @@
             static_assert( sizeof( slot->data.se.slot_number ) ==
                            sizeof( data.slot_number ),
                            "Slot number size does not match psa_se_key_data_storage_t" );
-            static_assert( sizeof( slot->attr.bits ) == sizeof( data.bits ),
-                           "Bit-size size does not match psa_se_key_data_storage_t" );
 #endif
             memcpy( &data.slot_number, &slot->data.se.slot_number,
                     sizeof( slot->data.se.slot_number ) );
-            memcpy( &data.bits, &slot->attr.bits,
-                    sizeof( slot->attr.bits ) );
             status = psa_save_persistent_key( &slot->attr,
                                               (uint8_t*) &data,
                                               sizeof( data ) );
@@ -1911,22 +2126,11 @@
         else
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
         {
-            size_t buffer_size =
-                PSA_KEY_EXPORT_MAX_SIZE( slot->attr.type,
-                                         slot->attr.bits );
-            uint8_t *buffer = mbedtls_calloc( 1, buffer_size );
-            size_t length = 0;
-            if( buffer == NULL )
-                return( PSA_ERROR_INSUFFICIENT_MEMORY );
-            status = psa_internal_export_key( slot,
-                                              buffer, buffer_size, &length,
-                                              0 );
-            if( status == PSA_SUCCESS )
-                status = psa_save_persistent_key( &slot->attr,
-                                                  buffer, length );
-
-            mbedtls_platform_zeroize( buffer, buffer_size );
-            mbedtls_free( buffer );
+            /* Key material is saved in export representation in the slot, so
+             * just pass the slot buffer for storage. */
+            status = psa_save_persistent_key( &slot->attr,
+                                              slot->data.key.data,
+                                              slot->data.key.bytes );
         }
     }
 #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
@@ -1947,11 +2151,17 @@
             return( status );
         }
         status = psa_crypto_stop_transaction( );
-        if( status != PSA_SUCCESS )
-            return( status );
     }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
+    if( status == PSA_SUCCESS )
+    {
+        *key = slot->attr.id;
+        status = psa_unlock_key_slot( slot );
+        if( status != PSA_SUCCESS )
+            *key = MBEDTLS_SVC_KEY_ID_INIT;
+    }
+
     return( status );
 }
 
@@ -2016,7 +2226,8 @@
 
     if( attributes->domain_parameters_size != 0 )
     {
-#if defined(MBEDTLS_RSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
         if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
         {
             mbedtls_rsa_context *rsa = NULL;
@@ -2053,7 +2264,8 @@
                 return( mbedtls_to_psa_error( ret ) );
         }
         else
-#endif
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
         {
             return( PSA_ERROR_INVALID_ARGUMENT );
         }
@@ -2071,12 +2283,14 @@
 psa_status_t psa_import_key( const psa_key_attributes_t *attributes,
                              const uint8_t *data,
                              size_t data_length,
-                             psa_key_handle_t *handle )
+                             mbedtls_svc_key_id_t *key )
 {
     psa_status_t status;
     psa_key_slot_t *slot = NULL;
     psa_se_drv_table_entry_t *driver = NULL;
 
+    *key = MBEDTLS_SVC_KEY_ID_INIT;
+
     /* Reject zero-length symmetric keys (including raw data key objects).
      * This also rejects any key which might be encoded as an empty string,
      * which is never valid. */
@@ -2084,7 +2298,7 @@
         return( PSA_ERROR_INVALID_ARGUMENT );
 
     status = psa_start_key_creation( PSA_KEY_CREATION_IMPORT, attributes,
-                                     handle, &slot, &driver );
+                                     &slot, &driver );
     if( status != PSA_SUCCESS )
         goto exit;
 
@@ -2125,13 +2339,11 @@
     if( status != PSA_SUCCESS )
         goto exit;
 
-    status = psa_finish_key_creation( slot, driver );
+    status = psa_finish_key_creation( slot, driver, key );
 exit:
     if( status != PSA_SUCCESS )
-    {
         psa_fail_key_creation( slot, driver );
-        *handle = 0;
-    }
+
     return( status );
 }
 
@@ -2142,7 +2354,7 @@
     psa_status_t status;
     psa_key_slot_t *slot = NULL;
     psa_se_drv_table_entry_t *driver = NULL;
-    psa_key_handle_t handle = 0;
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
 
     /* Leaving attributes unspecified is not currently supported.
      * It could make sense to query the key type and size from the
@@ -2154,19 +2366,18 @@
         return( PSA_ERROR_NOT_SUPPORTED );
 
     status = psa_start_key_creation( PSA_KEY_CREATION_REGISTER, attributes,
-                                     &handle, &slot, &driver );
+                                     &slot, &driver );
     if( status != PSA_SUCCESS )
         goto exit;
 
-    status = psa_finish_key_creation( slot, driver );
+    status = psa_finish_key_creation( slot, driver, &key );
 
 exit:
     if( status != PSA_SUCCESS )
-    {
         psa_fail_key_creation( slot, driver );
-    }
+
     /* Registration doesn't keep the key in RAM. */
-    psa_close_key( handle );
+    psa_close_key( key );
     return( status );
 }
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
@@ -2174,40 +2385,33 @@
 static psa_status_t psa_copy_key_material( const psa_key_slot_t *source,
                                            psa_key_slot_t *target )
 {
-    psa_status_t status;
-    uint8_t *buffer = NULL;
-    size_t buffer_size = 0;
-    size_t length;
-
-    buffer_size = PSA_KEY_EXPORT_MAX_SIZE( source->attr.type,
-                                           psa_get_key_slot_bits( source ) );
-    buffer = mbedtls_calloc( 1, buffer_size );
-    if( buffer == NULL )
-        return( PSA_ERROR_INSUFFICIENT_MEMORY );
-    status = psa_internal_export_key( source, buffer, buffer_size, &length, 0 );
+    psa_status_t status = psa_copy_key_material_into_slot( target,
+                                                           source->data.key.data,
+                                                           source->data.key.bytes );
     if( status != PSA_SUCCESS )
-        goto exit;
-    target->attr.type = source->attr.type;
-    status = psa_import_key_into_slot( target, buffer, length );
+        return( status );
 
-exit:
-    mbedtls_platform_zeroize( buffer, buffer_size );
-    mbedtls_free( buffer );
-    return( status );
+    target->attr.type = source->attr.type;
+    target->attr.bits = source->attr.bits;
+
+    return( PSA_SUCCESS );
 }
 
-psa_status_t psa_copy_key( psa_key_handle_t source_handle,
+psa_status_t psa_copy_key( mbedtls_svc_key_id_t source_key,
                            const psa_key_attributes_t *specified_attributes,
-                           psa_key_handle_t *target_handle )
+                           mbedtls_svc_key_id_t *target_key )
 {
-    psa_status_t status;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *source_slot = NULL;
     psa_key_slot_t *target_slot = NULL;
     psa_key_attributes_t actual_attributes = *specified_attributes;
     psa_se_drv_table_entry_t *driver = NULL;
 
-    status = psa_get_transparent_key( source_handle, &source_slot,
-                                      PSA_KEY_USAGE_COPY, 0 );
+    *target_key = MBEDTLS_SVC_KEY_ID_INIT;
+
+    status = psa_get_and_lock_transparent_key_slot_with_policy(
+                 source_key, &source_slot, PSA_KEY_USAGE_COPY, 0 );
     if( status != PSA_SUCCESS )
         goto exit;
 
@@ -2221,9 +2425,8 @@
     if( status != PSA_SUCCESS )
         goto exit;
 
-    status = psa_start_key_creation( PSA_KEY_CREATION_COPY,
-                                     &actual_attributes,
-                                     target_handle, &target_slot, &driver );
+    status = psa_start_key_creation( PSA_KEY_CREATION_COPY, &actual_attributes,
+                                     &target_slot, &driver );
     if( status != PSA_SUCCESS )
         goto exit;
 
@@ -2240,14 +2443,14 @@
     if( status != PSA_SUCCESS )
         goto exit;
 
-    status = psa_finish_key_creation( target_slot, driver );
+    status = psa_finish_key_creation( target_slot, driver, target_key );
 exit:
     if( status != PSA_SUCCESS )
-    {
         psa_fail_key_creation( target_slot, driver );
-        *target_handle = 0;
-    }
-    return( status );
+
+    unlock_status = psa_unlock_key_slot( source_slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
 
@@ -2256,7 +2459,10 @@
 /* Message digests */
 /****************************************************************/
 
-#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_DETERMINISTIC)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
 static const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg )
 {
     switch( alg )
@@ -2299,7 +2505,10 @@
             return( NULL );
     }
 }
-#endif
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
 
 psa_status_t psa_hash_abort( psa_hash_operation_t *operation )
 {
@@ -2816,7 +3025,7 @@
                                              (int) key_bits, mode ) );
 }
 
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
 static size_t psa_get_hash_block_size( psa_algorithm_t alg )
 {
     switch( alg )
@@ -2843,7 +3052,7 @@
             return( 0 );
     }
 }
-#endif /* MBEDTLS_MD_C */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) */
 
 /* Initialize the MAC operation structure. Once this function has been
  * called, psa_mac_abort can run and will do the right thing. */
@@ -2868,7 +3077,7 @@
     }
     else
 #endif /* MBEDTLS_CMAC_C */
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
     if( PSA_ALG_IS_HMAC( operation->alg ) )
     {
         /* We'll set up the hash operation later in psa_hmac_setup_internal. */
@@ -2876,7 +3085,7 @@
         status = PSA_SUCCESS;
     }
     else
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
     {
         if( ! PSA_ALG_IS_MAC( alg ) )
             status = PSA_ERROR_INVALID_ARGUMENT;
@@ -2887,13 +3096,13 @@
     return( status );
 }
 
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
 static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac )
 {
     mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) );
     return( psa_hash_abort( &hmac->hash_ctx ) );
 }
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
 
 psa_status_t psa_mac_abort( psa_mac_operation_t *operation )
 {
@@ -2912,13 +3121,13 @@
     }
     else
 #endif /* MBEDTLS_CMAC_C */
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
     if( PSA_ALG_IS_HMAC( operation->alg ) )
     {
         psa_hmac_abort_internal( &operation->ctx.hmac );
     }
     else
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
     {
         /* Sanity check (shouldn't happen: operation->alg should
          * always have been initialized to a valid value). */
@@ -2964,7 +3173,7 @@
 }
 #endif /* MBEDTLS_CMAC_C */
 
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
 static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac,
                                              const uint8_t *key,
                                              size_t key_length,
@@ -3026,14 +3235,15 @@
 
     return( status );
 }
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
 
 static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
-                                   psa_key_handle_t handle,
+                                   mbedtls_svc_key_id_t key,
                                    psa_algorithm_t alg,
                                    int is_sign )
 {
-    psa_status_t status;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
     size_t key_bits;
     psa_key_usage_t usage =
@@ -3053,7 +3263,8 @@
     if( is_sign )
         operation->is_sign = 1;
 
-    status = psa_get_transparent_key( handle, &slot, usage, alg );
+    status = psa_get_and_lock_transparent_key_slot_with_policy(
+                 key, &slot, usage, alg );
     if( status != PSA_SUCCESS )
         goto exit;
     key_bits = psa_get_key_slot_bits( slot );
@@ -3076,7 +3287,7 @@
     }
     else
 #endif /* MBEDTLS_CMAC_C */
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
     if( PSA_ALG_IS_HMAC( full_length_alg ) )
     {
         psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH( alg );
@@ -3107,7 +3318,7 @@
                                           hash_alg );
     }
     else
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
     {
         (void) key_bits;
         status = PSA_ERROR_NOT_SUPPORTED;
@@ -3142,21 +3353,24 @@
     {
         operation->key_set = 1;
     }
-    return( status );
+
+    unlock_status = psa_unlock_key_slot( slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
 psa_status_t psa_mac_sign_setup( psa_mac_operation_t *operation,
-                                 psa_key_handle_t handle,
+                                 mbedtls_svc_key_id_t key,
                                  psa_algorithm_t alg )
 {
-    return( psa_mac_setup( operation, handle, alg, 1 ) );
+    return( psa_mac_setup( operation, key, alg, 1 ) );
 }
 
 psa_status_t psa_mac_verify_setup( psa_mac_operation_t *operation,
-                                   psa_key_handle_t handle,
+                                   mbedtls_svc_key_id_t key,
                                    psa_algorithm_t alg )
 {
-    return( psa_mac_setup( operation, handle, alg, 0 ) );
+    return( psa_mac_setup( operation, key, alg, 0 ) );
 }
 
 psa_status_t psa_mac_update( psa_mac_operation_t *operation,
@@ -3179,14 +3393,14 @@
     }
     else
 #endif /* MBEDTLS_CMAC_C */
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
     if( PSA_ALG_IS_HMAC( operation->alg ) )
     {
         status = psa_hash_update( &operation->ctx.hmac.hash_ctx, input,
                                   input_length );
     }
     else
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
     {
         /* This shouldn't happen if `operation` was initialized by
          * a setup function. */
@@ -3198,7 +3412,7 @@
     return( status );
 }
 
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
 static psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac,
                                               uint8_t *mac,
                                               size_t mac_size )
@@ -3236,7 +3450,7 @@
     mbedtls_platform_zeroize( tmp, hash_size );
     return( status );
 }
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
 
 static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation,
                                              uint8_t *mac,
@@ -3262,14 +3476,14 @@
     }
     else
 #endif /* MBEDTLS_CMAC_C */
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
     if( PSA_ALG_IS_HMAC( operation->alg ) )
     {
         return( psa_hmac_finish_internal( &operation->ctx.hmac,
                                           mac, operation->mac_size ) );
     }
     else
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
     {
         /* This shouldn't happen if `operation` was initialized by
          * a setup function. */
@@ -3365,7 +3579,8 @@
 /* Asymmetric cryptography */
 /****************************************************************/
 
-#if defined(MBEDTLS_RSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
 /* Decode the hash algorithm from alg and store the mbedtls encoding in
  * md_alg. Verify that the hash length is acceptable. */
 static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg,
@@ -3384,7 +3599,7 @@
         return( PSA_ERROR_INVALID_ARGUMENT );
 #endif
 
-#if defined(MBEDTLS_PKCS1_V15)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
     /* For PKCS#1 v1.5 signature, if using a hash, the hash length
      * must be correct. */
     if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) &&
@@ -3395,16 +3610,16 @@
         if( mbedtls_md_get_size( md_info ) != hash_length )
             return( PSA_ERROR_INVALID_ARGUMENT );
     }
-#endif /* MBEDTLS_PKCS1_V15 */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
 
-#if defined(MBEDTLS_PKCS1_V21)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
     /* PSS requires a hash internally. */
     if( PSA_ALG_IS_RSA_PSS( alg ) )
     {
         if( md_info == NULL )
             return( PSA_ERROR_NOT_SUPPORTED );
     }
-#endif /* MBEDTLS_PKCS1_V21 */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
 
     return( PSA_SUCCESS );
 }
@@ -3428,7 +3643,7 @@
     if( signature_size < mbedtls_rsa_get_len( rsa ) )
         return( PSA_ERROR_BUFFER_TOO_SMALL );
 
-#if defined(MBEDTLS_PKCS1_V15)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
     if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
     {
         mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
@@ -3443,8 +3658,8 @@
                                       signature );
     }
     else
-#endif /* MBEDTLS_PKCS1_V15 */
-#if defined(MBEDTLS_PKCS1_V21)
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
     if( PSA_ALG_IS_RSA_PSS( alg ) )
     {
         mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
@@ -3458,7 +3673,7 @@
                                            signature );
     }
     else
-#endif /* MBEDTLS_PKCS1_V21 */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
     {
         return( PSA_ERROR_INVALID_ARGUMENT );
     }
@@ -3486,7 +3701,7 @@
     if( signature_length != mbedtls_rsa_get_len( rsa ) )
         return( PSA_ERROR_INVALID_SIGNATURE );
 
-#if defined(MBEDTLS_PKCS1_V15)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
     if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) )
     {
         mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15,
@@ -3501,8 +3716,8 @@
                                         signature );
     }
     else
-#endif /* MBEDTLS_PKCS1_V15 */
-#if defined(MBEDTLS_PKCS1_V21)
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
     if( PSA_ALG_IS_RSA_PSS( alg ) )
     {
         mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
@@ -3516,7 +3731,7 @@
                                              signature );
     }
     else
-#endif /* MBEDTLS_PKCS1_V21 */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
     {
         return( PSA_ERROR_INVALID_ARGUMENT );
     }
@@ -3528,9 +3743,11 @@
         return( PSA_ERROR_INVALID_SIGNATURE );
     return( mbedtls_to_psa_error( ret ) );
 }
-#endif /* MBEDTLS_RSA_C */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
 
-#if defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
 /* `ecp` cannot be const because `ecp->grp` needs to be non-const
  * for mbedtls_ecdsa_sign() and mbedtls_ecdsa_sign_det()
  * (even though these functions don't modify it). */
@@ -3554,7 +3771,7 @@
         goto cleanup;
     }
 
-#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
     if( PSA_ALG_DSA_IS_DETERMINISTIC( alg ) )
     {
         psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg );
@@ -3567,7 +3784,7 @@
                                                      &global_data.ctr_drbg ) );
     }
     else
-#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
     {
         (void) alg;
         MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ecp->grp, &r, &s, &ecp->d,
@@ -3629,9 +3846,10 @@
     mbedtls_mpi_free( &s );
     return( mbedtls_to_psa_error( ret ) );
 }
-#endif /* MBEDTLS_ECDSA_C */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
 
-psa_status_t psa_sign_hash( psa_key_handle_t handle,
+psa_status_t psa_sign_hash( mbedtls_svc_key_id_t key,
                             psa_algorithm_t alg,
                             const uint8_t *hash,
                             size_t hash_length,
@@ -3639,8 +3857,9 @@
                             size_t signature_size,
                             size_t *signature_length )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
-    psa_status_t status;
 
     *signature_length = signature_size;
     /* Immediately reject a zero-length signature buffer. This guarantees
@@ -3650,7 +3869,9 @@
     if( signature_size == 0 )
         return( PSA_ERROR_BUFFER_TOO_SMALL );
 
-    status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_SIGN_HASH, alg );
+    status = psa_get_and_lock_key_slot_with_policy( key, &slot,
+                                                    PSA_KEY_USAGE_SIGN_HASH,
+                                                    alg );
     if( status != PSA_SUCCESS )
         goto exit;
     if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) )
@@ -3672,7 +3893,8 @@
         goto exit;
 
     /* If the operation was not supported by any accelerator, try fallback. */
-#if defined(MBEDTLS_RSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
     if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR )
     {
         mbedtls_rsa_context *rsa = NULL;
@@ -3694,13 +3916,14 @@
         mbedtls_free( rsa );
     }
     else
-#endif /* defined(MBEDTLS_RSA_C) */
-#if defined(MBEDTLS_ECP_C)
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
     if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
     {
-#if defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
         if(
-#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
             PSA_ALG_IS_ECDSA( alg )
 #else
             PSA_ALG_IS_RANDOMIZED_ECDSA( alg )
@@ -3723,13 +3946,13 @@
             mbedtls_free( ecp );
         }
         else
-#endif /* defined(MBEDTLS_ECDSA_C) */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
         {
             status = PSA_ERROR_INVALID_ARGUMENT;
         }
     }
     else
-#endif /* defined(MBEDTLS_ECP_C) */
     {
         status = PSA_ERROR_NOT_SUPPORTED;
     }
@@ -3746,20 +3969,26 @@
         memset( signature, '!', signature_size );
     /* If signature_size is 0 then we have nothing to do. We must not call
      * memset because signature may be NULL in this case. */
-    return( status );
+
+    unlock_status = psa_unlock_key_slot( slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
-psa_status_t psa_verify_hash( psa_key_handle_t handle,
+psa_status_t psa_verify_hash( mbedtls_svc_key_id_t key,
                               psa_algorithm_t alg,
                               const uint8_t *hash,
                               size_t hash_length,
                               const uint8_t *signature,
                               size_t signature_length )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
-    psa_status_t status;
 
-    status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY_HASH, alg );
+    status = psa_get_and_lock_key_slot_with_policy( key, &slot,
+                                                    PSA_KEY_USAGE_VERIFY_HASH,
+                                                    alg );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -3772,9 +4001,10 @@
                                              signature_length );
     if( status != PSA_ERROR_NOT_SUPPORTED ||
         psa_key_lifetime_is_external( slot->attr.lifetime ) )
-        return status;
+        goto exit;
 
-#if defined(MBEDTLS_RSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
     if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
     {
         mbedtls_rsa_context *rsa = NULL;
@@ -3784,7 +4014,7 @@
                                               slot->data.key.bytes,
                                               &rsa );
         if( status != PSA_SUCCESS )
-            return( status );
+            goto exit;
 
         status = psa_rsa_verify( rsa,
                                  alg,
@@ -3792,14 +4022,15 @@
                                  signature, signature_length );
         mbedtls_rsa_free( rsa );
         mbedtls_free( rsa );
-        return( status );
+        goto exit;
     }
     else
-#endif /* defined(MBEDTLS_RSA_C) */
-#if defined(MBEDTLS_ECP_C)
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
     if( PSA_KEY_TYPE_IS_ECC( slot->attr.type ) )
     {
-#if defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
         if( PSA_ALG_IS_ECDSA( alg ) )
         {
             mbedtls_ecp_keypair *ecp = NULL;
@@ -3808,28 +4039,34 @@
                                                   slot->data.key.bytes,
                                                   &ecp );
             if( status != PSA_SUCCESS )
-                return( status );
+                goto exit;
             status = psa_ecdsa_verify( ecp,
                                        hash, hash_length,
                                        signature, signature_length );
             mbedtls_ecp_keypair_free( ecp );
             mbedtls_free( ecp );
-            return( status );
+            goto exit;
         }
         else
-#endif /* defined(MBEDTLS_ECDSA_C) */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
         {
-            return( PSA_ERROR_INVALID_ARGUMENT );
+            status =  PSA_ERROR_INVALID_ARGUMENT;
+            goto exit;
         }
     }
     else
-#endif /* defined(MBEDTLS_ECP_C) */
     {
-        return( PSA_ERROR_NOT_SUPPORTED );
+        status = PSA_ERROR_NOT_SUPPORTED;
     }
+
+exit:
+    unlock_status = psa_unlock_key_slot( slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
 static void psa_rsa_oaep_set_padding_mode( psa_algorithm_t alg,
                                            mbedtls_rsa_context *rsa )
 {
@@ -3838,9 +4075,9 @@
     mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info );
     mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg );
 }
-#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
 
-psa_status_t psa_asymmetric_encrypt( psa_key_handle_t handle,
+psa_status_t psa_asymmetric_encrypt( mbedtls_svc_key_id_t key,
                                      psa_algorithm_t alg,
                                      const uint8_t *input,
                                      size_t input_length,
@@ -3850,8 +4087,9 @@
                                      size_t output_size,
                                      size_t *output_length )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
-    psa_status_t status;
 
     (void) input;
     (void) input_length;
@@ -3864,14 +4102,19 @@
     if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
+    status = psa_get_and_lock_transparent_key_slot_with_policy(
+                 key, &slot, PSA_KEY_USAGE_ENCRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
     if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ||
             PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) )
-        return( PSA_ERROR_INVALID_ARGUMENT );
+    {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
 
-#if defined(MBEDTLS_RSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
     if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
     {
         mbedtls_rsa_context *rsa = NULL;
@@ -3887,7 +4130,7 @@
             status = PSA_ERROR_BUFFER_TOO_SMALL;
             goto rsa_exit;
         }
-#if defined(MBEDTLS_PKCS1_V15)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT)
         if( alg == PSA_ALG_RSA_PKCS1V15_CRYPT )
         {
             status = mbedtls_to_psa_error(
@@ -3900,8 +4143,8 @@
                                                output ) );
         }
         else
-#endif /* MBEDTLS_PKCS1_V15 */
-#if defined(MBEDTLS_PKCS1_V21)
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
         if( PSA_ALG_IS_RSA_OAEP( alg ) )
         {
             psa_rsa_oaep_set_padding_mode( alg, rsa );
@@ -3916,7 +4159,7 @@
                                                 output ) );
         }
         else
-#endif /* MBEDTLS_PKCS1_V21 */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */
         {
             status = PSA_ERROR_INVALID_ARGUMENT;
             goto rsa_exit;
@@ -3927,16 +4170,21 @@
 
         mbedtls_rsa_free( rsa );
         mbedtls_free( rsa );
-        return( status );
     }
     else
-#endif /* defined(MBEDTLS_RSA_C) */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
     {
-        return( PSA_ERROR_NOT_SUPPORTED );
+        status = PSA_ERROR_NOT_SUPPORTED;
     }
+
+exit:
+    unlock_status = psa_unlock_key_slot( slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
-psa_status_t psa_asymmetric_decrypt( psa_key_handle_t handle,
+psa_status_t psa_asymmetric_decrypt( mbedtls_svc_key_id_t key,
                                      psa_algorithm_t alg,
                                      const uint8_t *input,
                                      size_t input_length,
@@ -3946,8 +4194,9 @@
                                      size_t output_size,
                                      size_t *output_length )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
-    psa_status_t status;
 
     (void) input;
     (void) input_length;
@@ -3960,13 +4209,18 @@
     if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg );
+    status = psa_get_and_lock_transparent_key_slot_with_policy(
+                 key, &slot, PSA_KEY_USAGE_DECRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
     if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) )
-        return( PSA_ERROR_INVALID_ARGUMENT );
+    {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
 
-#if defined(MBEDTLS_RSA_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
     if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR )
     {
         mbedtls_rsa_context *rsa = NULL;
@@ -3975,7 +4229,7 @@
                                               slot->data.key.bytes,
                                               &rsa );
         if( status != PSA_SUCCESS )
-            return( status );
+            goto exit;
 
         if( input_length != mbedtls_rsa_get_len( rsa ) )
         {
@@ -3983,7 +4237,7 @@
             goto rsa_exit;
         }
 
-#if defined(MBEDTLS_PKCS1_V15)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT)
         if( alg == PSA_ALG_RSA_PKCS1V15_CRYPT )
         {
             status = mbedtls_to_psa_error(
@@ -3997,8 +4251,8 @@
                                            output_size ) );
         }
         else
-#endif /* MBEDTLS_PKCS1_V15 */
-#if defined(MBEDTLS_PKCS1_V21)
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
         if( PSA_ALG_IS_RSA_OAEP( alg ) )
         {
             psa_rsa_oaep_set_padding_mode( alg, rsa );
@@ -4014,7 +4268,7 @@
                                                 output_size ) );
         }
         else
-#endif /* MBEDTLS_PKCS1_V21 */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */
         {
             status = PSA_ERROR_INVALID_ARGUMENT;
         }
@@ -4022,13 +4276,18 @@
 rsa_exit:
         mbedtls_rsa_free( rsa );
         mbedtls_free( rsa );
-        return( status );
     }
     else
-#endif /* defined(MBEDTLS_RSA_C) */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
     {
-        return( PSA_ERROR_NOT_SUPPORTED );
+        status = PSA_ERROR_NOT_SUPPORTED;
     }
+
+exit:
+    unlock_status = psa_unlock_key_slot( slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
 
@@ -4038,12 +4297,13 @@
 /****************************************************************/
 
 static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation,
-                                      psa_key_handle_t handle,
+                                      mbedtls_svc_key_id_t key,
                                       psa_algorithm_t alg,
                                       mbedtls_operation_t cipher_operation )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     int ret = 0;
-    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
     psa_key_slot_t *slot;
     size_t key_bits;
     const mbedtls_cipher_info_t *cipher_info = NULL;
@@ -4060,7 +4320,7 @@
         return( PSA_ERROR_INVALID_ARGUMENT );
 
     /* Fetch key material from key storage. */
-    status = psa_get_key_from_slot( handle, &slot, usage, alg );
+    status = psa_get_and_lock_key_slot_with_policy( key, &slot, usage, alg );
     if( status != PSA_SUCCESS )
         goto exit;
 
@@ -4187,21 +4447,24 @@
     }
     else
         psa_cipher_abort( operation );
-    return( status );
+
+    unlock_status = psa_unlock_key_slot( slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
 psa_status_t psa_cipher_encrypt_setup( psa_cipher_operation_t *operation,
-                                       psa_key_handle_t handle,
+                                       mbedtls_svc_key_id_t key,
                                        psa_algorithm_t alg )
 {
-    return( psa_cipher_setup( operation, handle, alg, MBEDTLS_ENCRYPT ) );
+    return( psa_cipher_setup( operation, key, alg, MBEDTLS_ENCRYPT ) );
 }
 
 psa_status_t psa_cipher_decrypt_setup( psa_cipher_operation_t *operation,
-                                       psa_key_handle_t handle,
+                                       mbedtls_svc_key_id_t key,
                                        psa_algorithm_t alg )
 {
-    return( psa_cipher_setup( operation, handle, alg, MBEDTLS_DECRYPT ) );
+    return( psa_cipher_setup( operation, key, alg, MBEDTLS_DECRYPT ) );
 }
 
 psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation,
@@ -4473,8 +4736,7 @@
     if( operation->ctx.cipher.unprocessed_len != 0 )
     {
         if( operation->alg == PSA_ALG_ECB_NO_PADDING ||
-            ( operation->alg == PSA_ALG_CBC_NO_PADDING &&
-              operation->ctx.cipher.operation == MBEDTLS_ENCRYPT ) )
+            operation->alg == PSA_ALG_CBC_NO_PADDING )
         {
             status = PSA_ERROR_INVALID_ARGUMENT;
             goto exit;
@@ -4554,6 +4816,7 @@
     const mbedtls_cipher_info_t *cipher_info;
     union
     {
+        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
 #if defined(MBEDTLS_CCM_C)
         mbedtls_ccm_context ccm;
 #endif /* MBEDTLS_CCM_C */
@@ -4569,6 +4832,8 @@
     uint8_t tag_length;
 } aead_operation_t;
 
+#define AEAD_OPERATION_INIT {0, 0, {0}, 0, 0, 0}
+
 static void psa_aead_abort_internal( aead_operation_t *operation )
 {
     switch( operation->core_alg )
@@ -4584,10 +4849,12 @@
             break;
 #endif /* MBEDTLS_GCM_C */
     }
+
+    psa_unlock_key_slot( operation->slot );
 }
 
 static psa_status_t psa_aead_setup( aead_operation_t *operation,
-                                    psa_key_handle_t handle,
+                                    mbedtls_svc_key_id_t key,
                                     psa_key_usage_t usage,
                                     psa_algorithm_t alg )
 {
@@ -4595,7 +4862,8 @@
     size_t key_bits;
     mbedtls_cipher_id_t cipher_id;
 
-    status = psa_get_transparent_key( handle, &operation->slot, usage, alg );
+    status = psa_get_and_lock_transparent_key_slot_with_policy(
+                 key, &operation->slot, usage, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -4605,7 +4873,10 @@
         mbedtls_cipher_info_from_psa( alg, operation->slot->attr.type, key_bits,
                                       &cipher_id );
     if( operation->cipher_info == NULL )
-        return( PSA_ERROR_NOT_SUPPORTED );
+    {
+        status = PSA_ERROR_NOT_SUPPORTED;
+        goto cleanup;
+    }
 
     switch( PSA_ALG_AEAD_WITH_TAG_LENGTH( alg, 0 ) )
     {
@@ -4617,7 +4888,10 @@
              * The call to mbedtls_ccm_encrypt_and_tag or
              * mbedtls_ccm_auth_decrypt will validate the tag length. */
             if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->attr.type ) != 16 )
-                return( PSA_ERROR_INVALID_ARGUMENT );
+            {
+                status = PSA_ERROR_INVALID_ARGUMENT;
+                goto cleanup;
+            }
             mbedtls_ccm_init( &operation->ctx.ccm );
             status = mbedtls_to_psa_error(
                 mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id,
@@ -4636,7 +4910,10 @@
              * The call to mbedtls_gcm_crypt_and_tag or
              * mbedtls_gcm_auth_decrypt will validate the tag length. */
             if( PSA_BLOCK_CIPHER_BLOCK_SIZE( operation->slot->attr.type ) != 16 )
-                return( PSA_ERROR_INVALID_ARGUMENT );
+            {
+                status = PSA_ERROR_INVALID_ARGUMENT;
+                goto cleanup;
+            }
             mbedtls_gcm_init( &operation->ctx.gcm );
             status = mbedtls_to_psa_error(
                 mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id,
@@ -4653,7 +4930,10 @@
             operation->full_tag_length = 16;
             /* We only support the default tag length. */
             if( alg != PSA_ALG_CHACHA20_POLY1305 )
-                return( PSA_ERROR_NOT_SUPPORTED );
+            {
+                status = PSA_ERROR_NOT_SUPPORTED;
+                goto cleanup;
+            }
             mbedtls_chachapoly_init( &operation->ctx.chachapoly );
             status = mbedtls_to_psa_error(
                 mbedtls_chachapoly_setkey( &operation->ctx.chachapoly,
@@ -4664,7 +4944,8 @@
 #endif /* MBEDTLS_CHACHAPOLY_C */
 
         default:
-            return( PSA_ERROR_NOT_SUPPORTED );
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto cleanup;
     }
 
     if( PSA_AEAD_TAG_LENGTH( alg ) > operation->full_tag_length )
@@ -4681,7 +4962,7 @@
     return( status );
 }
 
-psa_status_t psa_aead_encrypt( psa_key_handle_t handle,
+psa_status_t psa_aead_encrypt( mbedtls_svc_key_id_t key,
                                psa_algorithm_t alg,
                                const uint8_t *nonce,
                                size_t nonce_length,
@@ -4694,12 +4975,12 @@
                                size_t *ciphertext_length )
 {
     psa_status_t status;
-    aead_operation_t operation;
+    aead_operation_t operation = AEAD_OPERATION_INIT;
     uint8_t *tag;
 
     *ciphertext_length = 0;
 
-    status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_ENCRYPT, alg );
+    status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_ENCRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -4795,7 +5076,7 @@
     return( PSA_SUCCESS );
 }
 
-psa_status_t psa_aead_decrypt( psa_key_handle_t handle,
+psa_status_t psa_aead_decrypt( mbedtls_svc_key_id_t key,
                                psa_algorithm_t alg,
                                const uint8_t *nonce,
                                size_t nonce_length,
@@ -4808,12 +5089,12 @@
                                size_t *plaintext_length )
 {
     psa_status_t status;
-    aead_operation_t operation;
+    aead_operation_t operation = AEAD_OPERATION_INIT;
     const uint8_t *tag = NULL;
 
     *plaintext_length = 0;
 
-    status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_DECRYPT, alg );
+    status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_DECRYPT, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
@@ -4891,6 +5172,12 @@
 /* Generators */
 /****************************************************************/
 
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+#define AT_LEAST_ONE_BUILTIN_KDF
+#endif
+
 #define HKDF_STATE_INIT 0 /* no input yet */
 #define HKDF_STATE_STARTED 1 /* got salt */
 #define HKDF_STATE_KEYED 2 /* got key */
@@ -4905,7 +5192,6 @@
         return( operation->alg );
 }
 
-
 psa_status_t psa_key_derivation_abort( psa_key_derivation_operation_t *operation )
 {
     psa_status_t status = PSA_SUCCESS;
@@ -4917,13 +5203,17 @@
          * nothing to do. */
     }
     else
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
     if( PSA_ALG_IS_HKDF( kdf_alg ) )
     {
         mbedtls_free( operation->ctx.hkdf.info );
         status = psa_hmac_abort_internal( &operation->ctx.hkdf.hmac );
     }
-    else if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) ||
+    else
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+    if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) ||
              /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */
              PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
     {
@@ -4947,7 +5237,8 @@
          * mbedtls_platform_zeroize() in the end of this function. */
     }
     else
-#endif /* MBEDTLS_MD_C */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) */
     {
         status = PSA_ERROR_BAD_STATE;
     }
@@ -4979,7 +5270,7 @@
     return( PSA_SUCCESS );
 }
 
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
 /* Read some bytes from an HKDF-based operation. This performs a chunk
  * of the expand phase of the HKDF algorithm. */
 static psa_status_t psa_key_derivation_hkdf_read( psa_hkdf_key_derivation_t *hkdf,
@@ -5048,7 +5339,10 @@
 
     return( PSA_SUCCESS );
 }
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */
 
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
 static psa_status_t psa_key_derivation_tls12_prf_generate_next_block(
     psa_tls12_prf_key_derivation_t *tls12_prf,
     psa_algorithm_t alg )
@@ -5195,7 +5489,8 @@
 
     return( PSA_SUCCESS );
 }
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF ||
+        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
 
 psa_status_t psa_key_derivation_output_bytes(
     psa_key_derivation_operation_t *operation,
@@ -5231,7 +5526,7 @@
     }
     operation->capacity -= output_length;
 
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
     if( PSA_ALG_IS_HKDF( kdf_alg ) )
     {
         psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg );
@@ -5239,15 +5534,19 @@
                                           output, output_length );
     }
     else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
     if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) ||
-             PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
+        PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
     {
         status = psa_key_derivation_tls12_prf_read( &operation->ctx.tls12_prf,
                                                kdf_alg, output,
                                                output_length );
     }
     else
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF ||
+        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
     {
         return( PSA_ERROR_BAD_STATE );
     }
@@ -5312,12 +5611,14 @@
 
 psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attributes,
                                        psa_key_derivation_operation_t *operation,
-                                       psa_key_handle_t *handle )
+                                       mbedtls_svc_key_id_t *key )
 {
     psa_status_t status;
     psa_key_slot_t *slot = NULL;
     psa_se_drv_table_entry_t *driver = NULL;
 
+    *key = MBEDTLS_SVC_KEY_ID_INIT;
+
     /* Reject any attempt to create a zero-length key so that we don't
      * risk tripping up later, e.g. on a malloc(0) that returns NULL. */
     if( psa_get_key_bits( attributes ) == 0 )
@@ -5326,8 +5627,8 @@
     if( ! operation->can_output_key )
         return( PSA_ERROR_NOT_PERMITTED );
 
-    status = psa_start_key_creation( PSA_KEY_CREATION_DERIVE,
-                                     attributes, handle, &slot, &driver );
+    status = psa_start_key_creation( PSA_KEY_CREATION_DERIVE, attributes,
+                                     &slot, &driver );
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
     if( driver != NULL )
     {
@@ -5342,12 +5643,10 @@
                                                     operation );
     }
     if( status == PSA_SUCCESS )
-        status = psa_finish_key_creation( slot, driver );
+        status = psa_finish_key_creation( slot, driver, key );
     if( status != PSA_SUCCESS )
-    {
         psa_fail_key_creation( slot, driver );
-        *handle = 0;
-    }
+
     return( status );
 }
 
@@ -5357,19 +5656,36 @@
 /* Key derivation */
 /****************************************************************/
 
+#ifdef AT_LEAST_ONE_BUILTIN_KDF
 static psa_status_t psa_key_derivation_setup_kdf(
     psa_key_derivation_operation_t *operation,
     psa_algorithm_t kdf_alg )
 {
+    int is_kdf_alg_supported;
+
     /* Make sure that operation->ctx is properly zero-initialised. (Macro
      * initialisers for this union leave some bytes unspecified.) */
     memset( &operation->ctx, 0, sizeof( operation->ctx ) );
 
     /* Make sure that kdf_alg is a supported key derivation algorithm. */
-#if defined(MBEDTLS_MD_C)
-    if( PSA_ALG_IS_HKDF( kdf_alg ) ||
-        PSA_ALG_IS_TLS12_PRF( kdf_alg ) ||
-        PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
+    if( PSA_ALG_IS_HKDF( kdf_alg ) )
+        is_kdf_alg_supported = 1;
+    else
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF)
+    if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) )
+        is_kdf_alg_supported = 1;
+    else
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+    if( PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
+        is_kdf_alg_supported = 1;
+    else
+#endif
+    is_kdf_alg_supported = 0;
+
+    if( is_kdf_alg_supported )
     {
         psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg );
         size_t hash_size = PSA_HASH_SIZE( hash_alg );
@@ -5384,10 +5700,10 @@
         operation->capacity = 255 * hash_size;
         return( PSA_SUCCESS );
     }
-#endif /* MBEDTLS_MD_C */
-    else
-        return( PSA_ERROR_NOT_SUPPORTED );
+
+    return( PSA_ERROR_NOT_SUPPORTED );
 }
+#endif /* AT_LEAST_ONE_BUILTIN_KDF */
 
 psa_status_t psa_key_derivation_setup( psa_key_derivation_operation_t *operation,
                                        psa_algorithm_t alg )
@@ -5399,6 +5715,7 @@
 
     if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) )
         return( PSA_ERROR_INVALID_ARGUMENT );
+#ifdef AT_LEAST_ONE_BUILTIN_KDF
     else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) )
     {
         psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF( alg );
@@ -5408,6 +5725,7 @@
     {
         status = psa_key_derivation_setup_kdf( operation, alg );
     }
+#endif
     else
         return( PSA_ERROR_INVALID_ARGUMENT );
 
@@ -5416,7 +5734,7 @@
     return( status );
 }
 
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
 static psa_status_t psa_hkdf_input( psa_hkdf_key_derivation_t *hkdf,
                                     psa_algorithm_t hash_alg,
                                     psa_key_derivation_step_t step,
@@ -5481,7 +5799,10 @@
             return( PSA_ERROR_INVALID_ARGUMENT );
     }
 }
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */
 
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
 static psa_status_t psa_tls12_prf_set_seed( psa_tls12_prf_key_derivation_t *prf,
                                             const uint8_t *data,
                                             size_t data_length )
@@ -5522,41 +5843,6 @@
     return( PSA_SUCCESS );
 }
 
-static psa_status_t psa_tls12_prf_psk_to_ms_set_key(
-    psa_tls12_prf_key_derivation_t *prf,
-    psa_algorithm_t hash_alg,
-    const uint8_t *data,
-    size_t data_length )
-{
-    psa_status_t status;
-    uint8_t pms[ 4 + 2 * PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN ];
-    uint8_t *cur = pms;
-
-    if( data_length > PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN )
-        return( PSA_ERROR_INVALID_ARGUMENT );
-
-    /* Quoting RFC 4279, Section 2:
-     *
-     * The premaster secret is formed as follows: if the PSK is N octets
-     * long, concatenate a uint16 with the value N, N zero octets, a second
-     * uint16 with the value N, and the PSK itself.
-     */
-
-    *cur++ = ( data_length >> 8 ) & 0xff;
-    *cur++ = ( data_length >> 0 ) & 0xff;
-    memset( cur, 0, data_length );
-    cur += data_length;
-    *cur++ = pms[0];
-    *cur++ = pms[1];
-    memcpy( cur, data, data_length );
-    cur += data_length;
-
-    status = psa_tls12_prf_set_key( prf, hash_alg, pms, cur - pms );
-
-    mbedtls_platform_zeroize( pms, sizeof( pms ) );
-    return( status );
-}
-
 static psa_status_t psa_tls12_prf_set_label( psa_tls12_prf_key_derivation_t *prf,
                                              const uint8_t *data,
                                              size_t data_length )
@@ -5597,6 +5883,44 @@
             return( PSA_ERROR_INVALID_ARGUMENT );
     }
 }
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
+        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+static psa_status_t psa_tls12_prf_psk_to_ms_set_key(
+    psa_tls12_prf_key_derivation_t *prf,
+    psa_algorithm_t hash_alg,
+    const uint8_t *data,
+    size_t data_length )
+{
+    psa_status_t status;
+    uint8_t pms[ 4 + 2 * PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN ];
+    uint8_t *cur = pms;
+
+    if( data_length > PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    /* Quoting RFC 4279, Section 2:
+     *
+     * The premaster secret is formed as follows: if the PSK is N octets
+     * long, concatenate a uint16 with the value N, N zero octets, a second
+     * uint16 with the value N, and the PSK itself.
+     */
+
+    *cur++ = ( data_length >> 8 ) & 0xff;
+    *cur++ = ( data_length >> 0 ) & 0xff;
+    memset( cur, 0, data_length );
+    cur += data_length;
+    *cur++ = pms[0];
+    *cur++ = pms[1];
+    memcpy( cur, data, data_length );
+    cur += data_length;
+
+    status = psa_tls12_prf_set_key( prf, hash_alg, pms, cur - pms );
+
+    mbedtls_platform_zeroize( pms, sizeof( pms ) );
+    return( status );
+}
 
 static psa_status_t psa_tls12_prf_psk_to_ms_input(
     psa_tls12_prf_key_derivation_t *prf,
@@ -5613,7 +5937,7 @@
 
     return( psa_tls12_prf_input( prf, hash_alg, step, data, data_length ) );
 }
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
 
 /** Check whether the given key type is acceptable for the given
  * input step of a key derivation.
@@ -5663,27 +5987,33 @@
     if( status != PSA_SUCCESS )
         goto exit;
 
-#if defined(MBEDTLS_MD_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
     if( PSA_ALG_IS_HKDF( kdf_alg ) )
     {
         status = psa_hkdf_input( &operation->ctx.hkdf,
                                  PSA_ALG_HKDF_GET_HASH( kdf_alg ),
                                  step, data, data_length );
     }
-    else if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) )
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF)
+    if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) )
     {
         status = psa_tls12_prf_input( &operation->ctx.tls12_prf,
                                       PSA_ALG_HKDF_GET_HASH( kdf_alg ),
                                       step, data, data_length );
     }
-    else if( PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+    if( PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) )
     {
         status = psa_tls12_prf_psk_to_ms_input( &operation->ctx.tls12_prf,
                                                 PSA_ALG_HKDF_GET_HASH( kdf_alg ),
                                                 step, data, data_length );
     }
     else
-#endif /* MBEDTLS_MD_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
     {
         /* This can't happen unless the operation object was not initialized */
         return( PSA_ERROR_BAD_STATE );
@@ -5709,14 +6039,14 @@
 psa_status_t psa_key_derivation_input_key(
     psa_key_derivation_operation_t *operation,
     psa_key_derivation_step_t step,
-    psa_key_handle_t handle )
+    mbedtls_svc_key_id_t key )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
-    psa_status_t status;
 
-    status = psa_get_transparent_key( handle, &slot,
-                                      PSA_KEY_USAGE_DERIVE,
-                                      operation->alg );
+    status = psa_get_and_lock_transparent_key_slot_with_policy(
+                 key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg );
     if( status != PSA_SUCCESS )
     {
         psa_key_derivation_abort( operation );
@@ -5728,10 +6058,14 @@
     if( step == PSA_KEY_DERIVATION_INPUT_SECRET )
         operation->can_output_key = 1;
 
-    return( psa_key_derivation_input_internal( operation,
-                                               step, slot->attr.type,
-                                               slot->data.key.data,
-                                               slot->data.key.bytes ) );
+    status = psa_key_derivation_input_internal( operation,
+                                                step, slot->attr.type,
+                                                slot->data.key.data,
+                                                slot->data.key.bytes );
+
+    unlock_status = psa_unlock_key_slot( slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
 
@@ -5740,7 +6074,7 @@
 /* Key agreement */
 /****************************************************************/
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
 static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key,
                                             size_t peer_key_length,
                                             const mbedtls_ecp_keypair *our_key,
@@ -5791,7 +6125,7 @@
 
     return( status );
 }
-#endif /* MBEDTLS_ECDH_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
 
 #define PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE MBEDTLS_ECP_MAX_BYTES
 
@@ -5805,7 +6139,7 @@
 {
     switch( alg )
     {
-#if defined(MBEDTLS_ECDH_C)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
         case PSA_ALG_ECDH:
             if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->attr.type ) )
                 return( PSA_ERROR_INVALID_ARGUMENT );
@@ -5824,7 +6158,7 @@
             mbedtls_ecp_keypair_free( ecp );
             mbedtls_free( ecp );
             return( status );
-#endif /* MBEDTLS_ECDH_C */
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
         default:
             (void) private_key;
             (void) peer_key;
@@ -5868,7 +6202,6 @@
                                                 PSA_KEY_TYPE_DERIVE,
                                                 shared_secret,
                                                 shared_secret_length );
-
 exit:
     mbedtls_platform_zeroize( shared_secret, shared_secret_length );
     return( status );
@@ -5876,16 +6209,18 @@
 
 psa_status_t psa_key_derivation_key_agreement( psa_key_derivation_operation_t *operation,
                                                psa_key_derivation_step_t step,
-                                               psa_key_handle_t private_key,
+                                               mbedtls_svc_key_id_t private_key,
                                                const uint8_t *peer_key,
                                                size_t peer_key_length )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_key_slot_t *slot;
-    psa_status_t status;
+
     if( ! PSA_ALG_IS_KEY_AGREEMENT( operation->alg ) )
         return( PSA_ERROR_INVALID_ARGUMENT );
-    status = psa_get_transparent_key( private_key, &slot,
-                                      PSA_KEY_USAGE_DERIVE, operation->alg );
+    status = psa_get_and_lock_transparent_key_slot_with_policy(
+                 private_key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg );
     if( status != PSA_SUCCESS )
         return( status );
     status = psa_key_agreement_internal( operation, step,
@@ -5893,27 +6228,38 @@
                                          peer_key, peer_key_length );
     if( status != PSA_SUCCESS )
         psa_key_derivation_abort( operation );
-    return( status );
+    else
+    {
+        /* If a private key has been added as SECRET, we allow the derived
+         * key material to be used as a key in PSA Crypto. */
+        if( step == PSA_KEY_DERIVATION_INPUT_SECRET )
+            operation->can_output_key = 1;
+    }
+
+    unlock_status = psa_unlock_key_slot( slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
 psa_status_t psa_raw_key_agreement( psa_algorithm_t alg,
-                                    psa_key_handle_t private_key,
+                                    mbedtls_svc_key_id_t private_key,
                                     const uint8_t *peer_key,
                                     size_t peer_key_length,
                                     uint8_t *output,
                                     size_t output_size,
                                     size_t *output_length )
 {
-    psa_key_slot_t *slot;
-    psa_status_t status;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot = NULL;
 
     if( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) )
     {
         status = PSA_ERROR_INVALID_ARGUMENT;
         goto exit;
     }
-    status = psa_get_transparent_key( private_key, &slot,
-                                      PSA_KEY_USAGE_DERIVE, alg );
+    status = psa_get_and_lock_transparent_key_slot_with_policy(
+                 private_key, &slot, PSA_KEY_USAGE_DERIVE, alg );
     if( status != PSA_SUCCESS )
         goto exit;
 
@@ -5935,7 +6281,10 @@
         psa_generate_random( output, output_size );
         *output_length = output_size;
     }
-    return( status );
+
+    unlock_status = psa_unlock_key_slot( slot );
+
+    return( ( status == PSA_SUCCESS ) ? unlock_status : status );
 }
 
 
@@ -5982,7 +6331,7 @@
 }
 #endif /* MBEDTLS_PSA_INJECT_ENTROPY */
 
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
 static psa_status_t psa_read_rsa_exponent( const uint8_t *domain_parameters,
                                            size_t domain_parameters_size,
                                            int *exponent )
@@ -6008,7 +6357,7 @@
     *exponent = acc;
     return( PSA_SUCCESS );
 }
-#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */
 
 static psa_status_t psa_generate_key_internal(
     psa_key_slot_t *slot, size_t bits,
@@ -6046,7 +6395,7 @@
     }
     else
 
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_GENPRIME)
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR)
     if ( type == PSA_KEY_TYPE_RSA_KEY_PAIR )
     {
         mbedtls_rsa_context rsa;
@@ -6094,9 +6443,9 @@
         return( status );
     }
     else
-#endif /* MBEDTLS_RSA_C && MBEDTLS_GENPRIME */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) */
 
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR)
     if ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) )
     {
         psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( type );
@@ -6110,8 +6459,6 @@
             return( PSA_ERROR_NOT_SUPPORTED );
         if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
             return( PSA_ERROR_NOT_SUPPORTED );
-        if( curve_info->bit_size != bits )
-            return( PSA_ERROR_INVALID_ARGUMENT );
         mbedtls_ecp_keypair_init( &ecp );
         ret = mbedtls_ecp_gen_key( grp_id, &ecp,
                                    mbedtls_ctr_drbg_random,
@@ -6143,7 +6490,7 @@
         return( status );
     }
     else
-#endif /* MBEDTLS_ECP_C */
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */
     {
         return( PSA_ERROR_NOT_SUPPORTED );
     }
@@ -6152,19 +6499,21 @@
 }
 
 psa_status_t psa_generate_key( const psa_key_attributes_t *attributes,
-                               psa_key_handle_t *handle )
+                               mbedtls_svc_key_id_t *key )
 {
     psa_status_t status;
     psa_key_slot_t *slot = NULL;
     psa_se_drv_table_entry_t *driver = NULL;
 
+    *key = MBEDTLS_SVC_KEY_ID_INIT;
+
     /* Reject any attempt to create a zero-length key so that we don't
      * risk tripping up later, e.g. on a malloc(0) that returns NULL. */
     if( psa_get_key_bits( attributes ) == 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    status = psa_start_key_creation( PSA_KEY_CREATION_GENERATE,
-                                     attributes, handle, &slot, &driver );
+    status = psa_start_key_creation( PSA_KEY_CREATION_GENERATE, attributes,
+                                     &slot, &driver );
     if( status != PSA_SUCCESS )
         goto exit;
 
@@ -6180,12 +6529,10 @@
 
 exit:
     if( status == PSA_SUCCESS )
-        status = psa_finish_key_creation( slot, driver );
+        status = psa_finish_key_creation( slot, driver, key );
     if( status != PSA_SUCCESS )
-    {
         psa_fail_key_creation( slot, driver );
-        *handle = 0;
-    }
+
     return( status );
 }
 
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index 6ee17fc..f61ef95 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -36,6 +36,32 @@
 typedef struct
 {
     psa_core_key_attributes_t attr;
+
+    /*
+     * Number of locks on the key slot held by the library.
+     *
+     * This counter is incremented by one each time a library function
+     * retrieves through one of the dedicated internal API a pointer to the
+     * key slot.
+     *
+     * This counter is decremented by one each time a library function stops
+     * accessing the key slot and states it by calling the
+     * psa_unlock_key_slot() API.
+     *
+     * This counter is used to prevent resetting the key slot while the library
+     * may access it. For example, such control is needed in the following
+     * scenarios:
+     * . In case of key slot starvation, all key slots contain the description
+     *   of a key, and the library asks for the description of a persistent
+     *   key not present in the key slots, the key slots currently accessed by
+     *   the library cannot be reclaimed to free a key slot to load the
+     *   persistent key.
+     * . In case of a multi-threaded application where one thread asks to close
+     *   or purge or destroy a key while it is in used by the library through
+     *   another thread.
+     */
+    size_t lock_count;
+
     union
     {
         /* Dynamically allocated key data buffer.
@@ -74,6 +100,19 @@
     return( slot->attr.type != 0 );
 }
 
+/** Test whether a key slot is locked.
+ *
+ * A key slot is locked iff its lock counter is strictly greater than 0.
+ *
+ * \param[in] slot  The key slot to test.
+ *
+ * \return 1 if the slot is locked, 0 otherwise.
+ */
+static inline int psa_is_key_slot_locked( const psa_key_slot_t *slot )
+{
+    return( slot->lock_count > 0 );
+}
+
 /** Retrieve flags from psa_key_slot_t::attr::core::flags.
  *
  * \param[in] slot      The key slot to query.
@@ -130,37 +169,33 @@
  *
  * \param[in,out] slot  The key slot to wipe.
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *         Success. This includes the case of a key slot that was
  *         already fully wiped.
- * \retval PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
  */
 psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot );
 
-/** Import key data into a slot.
+/** Copy key data (in export format) into an empty key slot.
  *
- * `slot->type` must have been set previously.
- * This function assumes that the slot does not contain any key material yet.
- * On failure, the slot content is unchanged.
+ * This function assumes that the slot does not contain
+ * any key material yet. On failure, the slot content is unchanged.
  *
- * Persistent storage is not affected.
+ * \param[in,out] slot          Key slot to copy the key into.
+ * \param[in] data              Buffer containing the key material.
+ * \param data_length           Size of the key buffer.
  *
- * \param[in,out] slot  The key slot to import data into.
- *                      Its `type` field must have previously been set to
- *                      the desired key type.
- *                      It must not contain any key material yet.
- * \param[in] data      Buffer containing the key material to parse and import.
- * \param data_length   Size of \p data in bytes.
- *
- * \retval PSA_SUCCESS
- * \retval PSA_ERROR_INVALID_ARGUMENT
- * \retval PSA_ERROR_NOT_SUPPORTED
- * \retval PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_SUCCESS
+ *         The key has been copied successfully.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         Not enough memory was available for allocation of the
+ *         copy buffer.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ *         There was other key material already present in the slot.
  */
-psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot,
-                                       const uint8_t *data,
-                                       size_t data_length );
-
+psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot,
+                                              const uint8_t *data,
+                                              size_t data_length );
 
 /** Convert an mbed TLS error code to a PSA error code
  *
diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c
index d41209b..c3ea6f1 100644
--- a/library/psa_crypto_driver_wrappers.c
+++ b/library/psa_crypto_driver_wrappers.c
@@ -256,26 +256,60 @@
                                            size_t *expected_size )
 {
     size_t buffer_size = 0;
-    if( PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ) == PSA_KEY_LOCATION_LOCAL_STORAGE )
-    {
-        buffer_size = PSA_KEY_EXPORT_MAX_SIZE( attributes->core.type,
-                                               attributes->core.bits );
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
+    psa_key_type_t key_type = attributes->core.type;
+    size_t key_bits = attributes->core.bits;
 
-        if( buffer_size == 0 )
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            buffer_size = PSA_KEY_EXPORT_MAX_SIZE( key_type, key_bits );
+
+            if( buffer_size == 0 )
+                return( PSA_ERROR_NOT_SUPPORTED );
+
+            *expected_size = buffer_size;
+            return( PSA_SUCCESS );
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LIFETIME:
+#ifdef TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION
+            *expected_size = test_size_function( key_type, key_bits );
+            return( PSA_SUCCESS );
+#else /* TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION */
+            if( PSA_KEY_TYPE_IS_KEY_PAIR( key_type ) )
+            {
+                int public_key_overhead = ( ( TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY == 1 ) ?
+                                           PSA_KEY_EXPORT_MAX_SIZE( key_type, key_bits ) : 0 );
+                *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
+                                 + TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE
+                                 + public_key_overhead;
+            }
+            else if( PSA_KEY_TYPE_IS_PUBLIC_KEY( attributes->core.type ) )
+            {
+                *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
+                                 + TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE;
+            }
+            else if ( !PSA_KEY_TYPE_IS_KEY_PAIR( key_type ) &&
+                      !PSA_KEY_TYPE_IS_PUBLIC_KEY ( attributes->core.type ) )
+            {
+                *expected_size = TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
+                                 + TEST_DRIVER_KEY_CONTEXT_SYMMETRIC_FACTOR
+                                 * ( ( key_bits + 7 ) / 8 );
+            }
+            else
+            {
+                return( PSA_ERROR_NOT_SUPPORTED );
+            }
+            return( PSA_SUCCESS );
+#endif /* TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION */
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
+        default:
             return( PSA_ERROR_NOT_SUPPORTED );
-
-        *expected_size = buffer_size;
-        return( PSA_SUCCESS );
-    }
-    else
-    {
-        /* TBD: opaque driver support: need to calculate size through a
-         * driver-defined size function, since the size of an opaque (wrapped)
-         * key will be different for each implementation. */
-        return( PSA_ERROR_NOT_SUPPORTED );
     }
 }
-#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
 
 psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes,
                                               psa_key_slot_t *slot )
@@ -376,6 +410,87 @@
 #endif /* PSA_CRYPTO_DRIVER_PRESENT */
 }
 
+psa_status_t psa_driver_wrapper_validate_key( const psa_key_attributes_t *attributes,
+                                              const uint8_t *data,
+                                              size_t data_length,
+                                              size_t *bits )
+{
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    /* Try accelerators in turn */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+    status = test_transparent_validate_key( attributes,
+                                            data,
+                                            data_length,
+                                            bits );
+    /* Declared with fallback == true */
+    if( status != PSA_ERROR_NOT_SUPPORTED )
+        return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    (void) attributes;
+    (void) data;
+    (void) data_length;
+    (void) bits;
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+psa_status_t psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot,
+                                                   uint8_t *data,
+                                                   size_t data_size,
+                                                   size_t *data_length )
+{
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime);
+    psa_key_attributes_t attributes = {
+      .core = slot->attr
+    };
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = test_transparent_export_public_key( &attributes,
+                                                         slot->data.key.data,
+                                                         slot->data.key.bytes,
+                                                         data,
+                                                         data_size,
+                                                         data_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+            /* Fell through, meaning no accelerator supports this operation */
+            return( PSA_ERROR_NOT_SUPPORTED );
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LIFETIME:
+            return( test_opaque_export_public_key( &attributes,
+                                                   slot->data.key.data,
+                                                   slot->data.key.bytes,
+                                                   data,
+                                                   data_size,
+                                                   data_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            return( status );
+    }
+#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    (void) slot;
+    (void) data;
+    (void) data_size;
+    (void) data_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+}
+
 /*
  * Cipher functions
  */
@@ -583,7 +698,7 @@
 #endif /* PSA_CRYPTO_DRIVER_TEST */
         default:
             /* Key is declared with a lifetime not known to us */
-            return( PSA_ERROR_BAD_STATE );
+            return( PSA_ERROR_NOT_SUPPORTED );
     }
 #else /* PSA_CRYPTO_DRIVER_PRESENT */
     (void)slot;
@@ -664,7 +779,7 @@
 #endif /* PSA_CRYPTO_DRIVER_TEST */
         default:
             /* Key is declared with a lifetime not known to us */
-            return( PSA_ERROR_BAD_STATE );
+            return( PSA_ERROR_NOT_SUPPORTED );
     }
 #else /* PSA_CRYPTO_DRIVER_PRESENT */
     (void)slot;
diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h
index 0db15d6..6b51437 100644
--- a/library/psa_crypto_driver_wrappers.h
+++ b/library/psa_crypto_driver_wrappers.h
@@ -43,9 +43,23 @@
                                              const uint8_t *signature,
                                              size_t signature_length );
 
+/*
+ * Key handling functions
+ */
+
 psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes,
                                               psa_key_slot_t *slot );
 
+psa_status_t psa_driver_wrapper_validate_key( const psa_key_attributes_t *attributes,
+                                              const uint8_t *data,
+                                              size_t data_length,
+                                              size_t *bits );
+
+psa_status_t psa_driver_wrapper_export_public_key( const psa_key_slot_t *slot,
+                                                   uint8_t *data,
+                                                   size_t data_size,
+                                                   size_t *data_length );
+
 /*
  * Cipher functions
  */
diff --git a/library/psa_crypto_invasive.h b/library/psa_crypto_invasive.h
index c609c77..2b4ee1f 100644
--- a/library/psa_crypto_invasive.h
+++ b/library/psa_crypto_invasive.h
@@ -62,12 +62,12 @@
  *                      It is called by mbedtls_psa_crypto_free().
  *                      By default this is mbedtls_entropy_free().
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *         Success.
- * \retval PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_NOT_PERMITTED
  *         The caller does not have the permission to configure
  *         entropy sources.
- * \retval PSA_ERROR_BAD_STATE
+ * \retval #PSA_ERROR_BAD_STATE
  *         The library has already been initialized.
  */
 psa_status_t mbedtls_psa_crypto_configure_entropy_sources(
diff --git a/library/psa_crypto_its.h b/library/psa_crypto_its.h
index 93c4ce9..11703a0 100644
--- a/library/psa_crypto_its.h
+++ b/library/psa_crypto_its.h
@@ -72,12 +72,12 @@
  *
  * \return      A status indicating the success/failure of the operation
  *
- * \retval      PSA_SUCCESS                      The operation completed successfully
- * \retval      PSA_ERROR_NOT_PERMITTED          The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG
- * \retval      PSA_ERROR_NOT_SUPPORTED          The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid
- * \retval      PSA_ERROR_INSUFFICIENT_STORAGE   The operation failed because there was insufficient space on the storage medium
- * \retval      PSA_ERROR_STORAGE_FAILURE        The operation failed because the physical storage has failed (Fatal error)
- * \retval      PSA_ERROR_INVALID_ARGUMENT       The operation failed because one of the provided pointers(`p_data`)
+ * \retval     #PSA_SUCCESS                      The operation completed successfully
+ * \retval     #PSA_ERROR_NOT_PERMITTED          The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG
+ * \retval     #PSA_ERROR_NOT_SUPPORTED          The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid
+ * \retval     #PSA_ERROR_INSUFFICIENT_STORAGE   The operation failed because there was insufficient space on the storage medium
+ * \retval     #PSA_ERROR_STORAGE_FAILURE        The operation failed because the physical storage has failed (Fatal error)
+ * \retval     #PSA_ERROR_INVALID_ARGUMENT       The operation failed because one of the provided pointers(`p_data`)
  *                                               is invalid, for example is `NULL` or references memory the caller cannot access
  */
 psa_status_t psa_its_set(psa_storage_uid_t uid,
@@ -97,11 +97,11 @@
  *
  * \return      A status indicating the success/failure of the operation
  *
- * \retval      PSA_SUCCESS                  The operation completed successfully
- * \retval      PSA_ERROR_DOES_NOT_EXIST     The operation failed because the provided `uid` value was not found in the storage
- * \retval      PSA_ERROR_INVALID_SIZE       The operation failed because the data associated with provided uid is larger than `data_size`
- * \retval      PSA_ERROR_STORAGE_FAILURE    The operation failed because the physical storage has failed (Fatal error)
- * \retval      PSA_ERROR_INVALID_ARGUMENT   The operation failed because one of the provided pointers(`p_data`, `p_data_length`)
+ * \retval     #PSA_SUCCESS                  The operation completed successfully
+ * \retval     #PSA_ERROR_DOES_NOT_EXIST     The operation failed because the provided `uid` value was not found in the storage
+ * \retval     #PSA_ERROR_INVALID_SIZE       The operation failed because the data associated with provided uid is larger than `data_size`
+ * \retval     #PSA_ERROR_STORAGE_FAILURE    The operation failed because the physical storage has failed (Fatal error)
+ * \retval     #PSA_ERROR_INVALID_ARGUMENT   The operation failed because one of the provided pointers(`p_data`, `p_data_length`)
  *                                           is invalid. For example is `NULL` or references memory the caller cannot access.
  *                                           In addition, this can also happen if an invalid offset was provided.
  */
@@ -119,10 +119,10 @@
  *
  * \return      A status indicating the success/failure of the operation
  *
- * \retval      PSA_SUCCESS                  The operation completed successfully
- * \retval      PSA_ERROR_DOES_NOT_EXIST     The operation failed because the provided uid value was not found in the storage
- * \retval      PSA_ERROR_STORAGE_FAILURE    The operation failed because the physical storage has failed (Fatal error)
- * \retval      PSA_ERROR_INVALID_ARGUMENT   The operation failed because one of the provided pointers(`p_info`)
+ * \retval     #PSA_SUCCESS                  The operation completed successfully
+ * \retval     #PSA_ERROR_DOES_NOT_EXIST     The operation failed because the provided uid value was not found in the storage
+ * \retval     #PSA_ERROR_STORAGE_FAILURE    The operation failed because the physical storage has failed (Fatal error)
+ * \retval     #PSA_ERROR_INVALID_ARGUMENT   The operation failed because one of the provided pointers(`p_info`)
  *                                           is invalid, for example is `NULL` or references memory the caller cannot access
  */
 psa_status_t psa_its_get_info(psa_storage_uid_t uid,
@@ -135,11 +135,15 @@
  *
  * \return  A status indicating the success/failure of the operation
  *
- * \retval      PSA_SUCCESS                  The operation completed successfully
- * \retval      PSA_ERROR_DOES_NOT_EXIST     The operation failed because the provided key value was not found in the storage
- * \retval      PSA_ERROR_NOT_PERMITTED      The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG
- * \retval      PSA_ERROR_STORAGE_FAILURE    The operation failed because the physical storage has failed (Fatal error)
+ * \retval     #PSA_SUCCESS                  The operation completed successfully
+ * \retval     #PSA_ERROR_DOES_NOT_EXIST     The operation failed because the provided key value was not found in the storage
+ * \retval     #PSA_ERROR_NOT_PERMITTED      The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG
+ * \retval     #PSA_ERROR_STORAGE_FAILURE    The operation failed because the physical storage has failed (Fatal error)
  */
 psa_status_t psa_its_remove(psa_storage_uid_t uid);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* PSA_CRYPTO_ITS_H */
diff --git a/library/psa_crypto_se.h b/library/psa_crypto_se.h
index 5691738..67fadf8 100644
--- a/library/psa_crypto_se.h
+++ b/library/psa_crypto_se.h
@@ -182,7 +182,6 @@
 typedef struct
 {
     uint8_t slot_number[sizeof( psa_key_slot_number_t )];
-    uint8_t bits[sizeof( psa_key_bits_t )];
 } psa_se_key_data_storage_t;
 
 #endif /* PSA_CRYPTO_SE_H */
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
index e526560..4c4ad03 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -51,30 +51,101 @@
 
 static psa_global_data_t global_data;
 
-/* Access a key slot at the given handle. The handle of a key slot is
- * the index of the slot in the global slot array, plus one so that handles
- * start at 1 and not 0. */
-psa_status_t psa_get_key_slot( psa_key_handle_t handle,
-                               psa_key_slot_t **p_slot )
+psa_status_t psa_validate_key_id(
+    mbedtls_svc_key_id_t key, int vendor_ok )
 {
+    psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key );
+
+    if( ( PSA_KEY_ID_USER_MIN <= key_id ) &&
+        ( key_id <= PSA_KEY_ID_USER_MAX ) )
+        return( PSA_SUCCESS );
+
+    if( vendor_ok &&
+        ( PSA_KEY_ID_VENDOR_MIN <= key_id ) &&
+        ( key_id <= PSA_KEY_ID_VENDOR_MAX ) )
+        return( PSA_SUCCESS );
+
+    return( PSA_ERROR_INVALID_HANDLE );
+}
+
+/** Get the description in memory of a key given its identifier and lock it.
+ *
+ * The descriptions of volatile keys and loaded persistent keys are
+ * stored in key slots. This function returns a pointer to the key slot
+ * containing the description of a key given its identifier.
+ *
+ * The function searches the key slots containing the description of the key
+ * with \p key identifier. The function does only read accesses to the key
+ * slots. The function does not load any persistent key thus does not access
+ * any storage.
+ *
+ * For volatile key identifiers, only one key slot is queried as a volatile
+ * key with identifier key_id can only be stored in slot of index
+ * ( key_id - #PSA_KEY_ID_VOLATILE_MIN ).
+ *
+ * On success, the function locks the key slot. It is the responsibility of
+ * the caller to unlock the key slot when it does not access it anymore.
+ *
+ * \param key           Key identifier to query.
+ * \param[out] p_slot   On success, `*p_slot` contains a pointer to the
+ *                      key slot containing the description of the key
+ *                      identified by \p key.
+ *
+ * \retval #PSA_SUCCESS
+ *         The pointer to the key slot containing the description of the key
+ *         identified by \p key was returned.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ *         \p key is not a valid key identifier.
+ * \retval #PSA_ERROR_DOES_NOT_EXIST
+ *         There is no key with key identifier \p key in the key slots.
+ */
+static psa_status_t psa_get_and_lock_key_slot_in_memory(
+    mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key );
+    size_t slot_idx;
     psa_key_slot_t *slot = NULL;
 
-    if( ! global_data.key_slots_initialized )
-        return( PSA_ERROR_BAD_STATE );
+    if( psa_key_id_is_volatile( key_id ) )
+    {
+        slot = &global_data.key_slots[ key_id - PSA_KEY_ID_VOLATILE_MIN ];
 
-    /* 0 is not a valid handle under any circumstance. This
-     * implementation provides slots number 1 to N where N is the
-     * number of available slots. */
-    if( handle == 0 || handle > ARRAY_LENGTH( global_data.key_slots ) )
-        return( PSA_ERROR_INVALID_HANDLE );
-    slot = &global_data.key_slots[handle - 1];
+        /*
+         * Check if both the PSA key identifier key_id and the owner
+         * identifier of key match those of the key slot.
+         *
+         * Note that, if the key slot is not occupied, its PSA key identifier
+         * is equal to zero. This is an invalid value for a PSA key identifier
+         * and thus cannot be equal to the valid PSA key identifier key_id.
+         */
+        status = mbedtls_svc_key_id_equal( key, slot->attr.id ) ?
+                 PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
+    }
+    else
+    {
+        status = psa_validate_key_id( key, 1 );
+        if( status != PSA_SUCCESS )
+            return( status );
 
-    /* If the slot isn't occupied, the handle is invalid. */
-    if( ! psa_is_key_slot_occupied( slot ) )
-        return( PSA_ERROR_INVALID_HANDLE );
+        for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
+        {
+            slot = &global_data.key_slots[ slot_idx ];
+            if( mbedtls_svc_key_id_equal( key, slot->attr.id ) )
+                break;
+        }
+        status = ( slot_idx < PSA_KEY_SLOT_COUNT ) ?
+                 PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
+    }
 
-    *p_slot = slot;
-    return( PSA_SUCCESS );
+    if( status == PSA_SUCCESS )
+    {
+        status = psa_lock_key_slot( slot );
+        if( status == PSA_SUCCESS )
+            *p_slot = slot;
+    }
+
+    return( status );
 }
 
 psa_status_t psa_initialize_key_slots( void )
@@ -88,29 +159,80 @@
 
 void psa_wipe_all_key_slots( void )
 {
-    psa_key_handle_t key;
-    for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ )
+    size_t slot_idx;
+
+    for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
     {
-        psa_key_slot_t *slot = &global_data.key_slots[key - 1];
+        psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
+        slot->lock_count = 1;
         (void) psa_wipe_key_slot( slot );
     }
     global_data.key_slots_initialized = 0;
 }
 
-psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle,
-                                             psa_key_slot_t **p_slot )
+psa_status_t psa_get_empty_key_slot( psa_key_id_t *volatile_key_id,
+                                     psa_key_slot_t **p_slot )
 {
-    if( ! global_data.key_slots_initialized )
-        return( PSA_ERROR_BAD_STATE );
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t slot_idx;
+    psa_key_slot_t *selected_slot, *unlocked_persistent_key_slot;
 
-    for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) )
+    if( ! global_data.key_slots_initialized )
     {
-        *p_slot = &global_data.key_slots[*handle - 1];
-        if( ! psa_is_key_slot_occupied( *p_slot ) )
-            return( PSA_SUCCESS );
+        status = PSA_ERROR_BAD_STATE;
+        goto error;
     }
+
+    selected_slot = unlocked_persistent_key_slot = NULL;
+    for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
+    {
+        psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
+        if( ! psa_is_key_slot_occupied( slot ) )
+        {
+            selected_slot = slot;
+            break;
+        }
+
+        if( ( unlocked_persistent_key_slot == NULL ) &&
+            ( ! PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) ) &&
+            ( ! psa_is_key_slot_locked( slot ) ) )
+            unlocked_persistent_key_slot = slot;
+    }
+
+    /*
+     * If there is no unused key slot and there is at least one unlocked key
+     * slot containing the description of a persistent key, recycle the first
+     * such key slot we encountered. If we later need to operate on the
+     * persistent key we are evicting now, we will reload its description from
+     * storage.
+     */
+    if( ( selected_slot == NULL ) &&
+        ( unlocked_persistent_key_slot != NULL ) )
+    {
+        selected_slot = unlocked_persistent_key_slot;
+        selected_slot->lock_count = 1;
+        psa_wipe_key_slot( selected_slot );
+    }
+
+    if( selected_slot != NULL )
+    {
+       status = psa_lock_key_slot( selected_slot );
+       if( status != PSA_SUCCESS )
+           goto error;
+
+        *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN +
+            ( (psa_key_id_t)( selected_slot - global_data.key_slots ) );
+        *p_slot = selected_slot;
+
+        return( PSA_SUCCESS );
+    }
+    status = PSA_ERROR_INSUFFICIENT_MEMORY;
+
+error:
     *p_slot = NULL;
-    return( PSA_ERROR_INSUFFICIENT_MEMORY );
+    *volatile_key_id = 0;
+
+    return( status );
 }
 
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
@@ -137,46 +259,84 @@
         data = (psa_se_key_data_storage_t *) key_data;
         memcpy( &slot->data.se.slot_number, &data->slot_number,
                 sizeof( slot->data.se.slot_number ) );
-        memcpy( &slot->attr.bits, &data->bits,
-                sizeof( slot->attr.bits ) );
     }
     else
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
     {
-        status = psa_import_key_into_slot( slot, key_data, key_data_length );
+        status = psa_copy_key_material_into_slot( slot, key_data, key_data_length );
+        if( status != PSA_SUCCESS )
+            goto exit;
     }
 
 exit:
     psa_free_persistent_key_data( key_data, key_data_length );
     return( status );
 }
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
 
-/** Check whether a key identifier is acceptable.
- *
- * For backward compatibility, key identifiers that were valid in a
- * past released version must remain valid, unless a migration path
- * is provided.
- *
- * \param key        The key identifier to check.
- * \param vendor_ok  Nonzero to allow key ids in the vendor range.
- *                   0 to allow only key ids in the application range.
- *
- * \return           1 if \p key is acceptable, otherwise 0.
- */
-static int psa_is_key_id_valid( mbedtls_svc_key_id_t key, int vendor_ok )
+psa_status_t psa_get_and_lock_key_slot( mbedtls_svc_key_id_t key,
+                                        psa_key_slot_t **p_slot )
 {
-    psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key );
-    if( PSA_KEY_ID_USER_MIN <= key_id && key_id <= PSA_KEY_ID_USER_MAX )
-        return( 1 );
-    else if( vendor_ok &&
-             PSA_KEY_ID_VENDOR_MIN <= key_id &&
-             key_id <= PSA_KEY_ID_VENDOR_MAX )
-        return( 1 );
-    else
-        return( 0 );
-}
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    *p_slot = NULL;
+    if( ! global_data.key_slots_initialized )
+        return( PSA_ERROR_BAD_STATE );
+
+    /*
+     * On success, the pointer to the slot is passed directly to the caller
+     * thus no need to unlock the key slot here.
+     */
+    status = psa_get_and_lock_key_slot_in_memory( key, p_slot );
+    if( status != PSA_ERROR_DOES_NOT_EXIST )
+        return( status );
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+    psa_key_id_t volatile_key_id;
+
+    status = psa_get_empty_key_slot( &volatile_key_id, p_slot );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
+    (*p_slot)->attr.id = key;
+
+    status = psa_load_persistent_key_into_slot( *p_slot );
+    if( status != PSA_SUCCESS )
+        psa_wipe_key_slot( *p_slot );
+
+    return( status );
+#else
+    return( PSA_ERROR_DOES_NOT_EXIST );
 #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
 
+}
+
+psa_status_t psa_unlock_key_slot( psa_key_slot_t *slot )
+{
+    if( slot == NULL )
+        return( PSA_SUCCESS );
+
+    if( slot->lock_count > 0 )
+    {
+        slot->lock_count--;
+        return( PSA_SUCCESS );
+    }
+
+    /*
+     * As the return error code may not be handled in case of multiple errors,
+     * do our best to report if the lock counter is equal to zero: if
+     * available call MBEDTLS_PARAM_FAILED that may terminate execution (if
+     * called as part of the execution of a unit test suite this will stop the
+     * test suite execution).
+     */
+#ifdef MBEDTLS_CHECK_PARAMS
+    MBEDTLS_PARAM_FAILED( slot->lock_count > 0 );
+#endif
+
+    return( PSA_ERROR_CORRUPTION_DETECTED );
+}
+
 psa_status_t psa_validate_key_location( psa_key_lifetime_t lifetime,
                                         psa_se_drv_table_entry_t **p_drv )
 {
@@ -202,8 +362,7 @@
         return( PSA_SUCCESS );
 }
 
-psa_status_t psa_validate_key_persistence( psa_key_lifetime_t lifetime,
-                                           mbedtls_svc_key_id_t key )
+psa_status_t psa_validate_key_persistence( psa_key_lifetime_t lifetime )
 {
     if ( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
     {
@@ -214,13 +373,8 @@
     {
         /* Persistent keys require storage support */
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-        if( psa_is_key_id_valid( key,
-                                 psa_key_lifetime_is_external( lifetime ) ) )
-            return( PSA_SUCCESS );
-        else
-            return( PSA_ERROR_INVALID_ARGUMENT );
+        return( PSA_SUCCESS );
 #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
-        (void) key;
         return( PSA_ERROR_NOT_SUPPORTED );
 #endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */
     }
@@ -232,29 +386,20 @@
     psa_status_t status;
     psa_key_slot_t *slot;
 
-    *handle = 0;
-
-    if( ! psa_is_key_id_valid( key, 1 ) )
-        return( PSA_ERROR_INVALID_ARGUMENT );
-
-    status = psa_get_empty_key_slot( handle, &slot );
-    if( status != PSA_SUCCESS )
-        return( status );
-
-    slot->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
-    slot->attr.id = key;
-
-    status = psa_load_persistent_key_into_slot( slot );
+    status = psa_get_and_lock_key_slot( key, &slot );
     if( status != PSA_SUCCESS )
     {
-        psa_wipe_key_slot( slot );
-        *handle = 0;
+        *handle = PSA_KEY_HANDLE_INIT;
+        return( status );
     }
-    return( status );
+
+    *handle = key;
+
+    return( psa_unlock_key_slot( slot ) );
 
 #else /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
     (void) key;
-    *handle = 0;
+    *handle = PSA_KEY_HANDLE_INIT;
     return( PSA_ERROR_NOT_SUPPORTED );
 #endif /* !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
 }
@@ -264,23 +409,48 @@
     psa_status_t status;
     psa_key_slot_t *slot;
 
-    if( handle == 0 )
+    if( psa_key_handle_is_null( handle ) )
         return( PSA_SUCCESS );
 
-    status = psa_get_key_slot( handle, &slot );
+    status = psa_get_and_lock_key_slot_in_memory( handle, &slot );
     if( status != PSA_SUCCESS )
         return( status );
 
-    return( psa_wipe_key_slot( slot ) );
+    if( slot->lock_count <= 1 )
+        return( psa_wipe_key_slot( slot ) );
+    else
+        return( psa_unlock_key_slot( slot ) );
+}
+
+psa_status_t psa_purge_key( mbedtls_svc_key_id_t key )
+{
+    psa_status_t status;
+    psa_key_slot_t *slot;
+
+    status = psa_get_and_lock_key_slot_in_memory( key, &slot );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    if( ( ! PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) ) &&
+        ( slot->lock_count <= 1 ) )
+        return( psa_wipe_key_slot( slot ) );
+    else
+        return( psa_unlock_key_slot( slot ) );
 }
 
 void mbedtls_psa_get_stats( mbedtls_psa_stats_t *stats )
 {
-    psa_key_handle_t key;
+    size_t slot_idx;
+
     memset( stats, 0, sizeof( *stats ) );
-    for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ )
+
+    for( slot_idx = 0; slot_idx < PSA_KEY_SLOT_COUNT; slot_idx++ )
     {
-        const psa_key_slot_t *slot = &global_data.key_slots[key - 1];
+        const psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ];
+        if( psa_is_key_slot_locked( slot ) )
+        {
+            ++stats->locked_slots;
+        }
         if( ! psa_is_key_slot_occupied( slot ) )
         {
             ++stats->empty_slots;
diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h
index c6fecbb..ef0814a 100644
--- a/library/psa_crypto_slot_management.h
+++ b/library/psa_crypto_slot_management.h
@@ -22,32 +22,86 @@
 #define PSA_CRYPTO_SLOT_MANAGEMENT_H
 
 #include "psa/crypto.h"
+#include "psa_crypto_core.h"
 #include "psa_crypto_se.h"
 
 /* Number of key slots (plus one because 0 is not used).
  * The value is a compile-time constant for now, for simplicity. */
 #define PSA_KEY_SLOT_COUNT 32
 
-/** Access a key slot at the given handle.
+/** Range of volatile key identifiers.
  *
- * \param handle        Key handle to query.
- * \param[out] p_slot   On success, `*p_slot` contains a pointer to the
- *                      key slot in memory designated by \p handle.
- *
- * \retval PSA_SUCCESS
- *         Success: \p handle is a handle to `*p_slot`. Note that `*p_slot`
- *         may be empty or occupied.
- * \retval PSA_ERROR_INVALID_HANDLE
- *         \p handle is out of range or is not in use.
- * \retval PSA_ERROR_BAD_STATE
- *         The library has not been initialized.
+ *  The last PSA_KEY_SLOT_COUNT identifiers of the implementation range
+ *  of key identifiers are reserved for volatile key identifiers.
+ *  A volatile key identifier is equal to #PSA_KEY_ID_VOLATILE_MIN plus the
+ *  index of the key slot containing the volatile key definition.
  */
-psa_status_t psa_get_key_slot( psa_key_handle_t handle,
-                               psa_key_slot_t **p_slot );
+
+/** The minimum value for a volatile key identifier.
+ */
+#define PSA_KEY_ID_VOLATILE_MIN  ( PSA_KEY_ID_VENDOR_MAX - \
+                                   PSA_KEY_SLOT_COUNT + 1 )
+
+/** The maximum value for a volatile key identifier.
+ */
+#define PSA_KEY_ID_VOLATILE_MAX  PSA_KEY_ID_VENDOR_MAX
+
+/** Test whether a key identifier is a volatile key identifier.
+ *
+ * \param key_id  Key identifier to test.
+ *
+ * \retval 1
+ *         The key identifier is a volatile key identifier.
+ * \retval 0
+ *         The key identifier is not a volatile key identifier.
+ */
+static inline int psa_key_id_is_volatile( psa_key_id_t key_id )
+{
+    return( ( key_id >= PSA_KEY_ID_VOLATILE_MIN ) &&
+            ( key_id <= PSA_KEY_ID_VOLATILE_MAX ) );
+}
+
+/** Get the description of a key given its identifier and lock it.
+ *
+ * The descriptions of volatile keys and loaded persistent keys are stored in
+ * key slots. This function returns a pointer to the key slot containing the
+ * description of a key given its identifier.
+ *
+ * In case of a persistent key, the function loads the description of the key
+ * into a key slot if not already done.
+ *
+ * On success, the returned key slot is locked. It is the responsibility of
+ * the caller to unlock the key slot when it does not access it anymore.
+ *
+ * \param key           Key identifier to query.
+ * \param[out] p_slot   On success, `*p_slot` contains a pointer to the
+ *                      key slot containing the description of the key
+ *                      identified by \p key.
+ *
+ * \retval #PSA_SUCCESS
+ *         \p *p_slot contains a pointer to the key slot containing the
+ *         description of the key identified by \p key.
+ *         The key slot counter has been incremented.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been initialized.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ *         \p key is not a valid key identifier.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         \p key is a persistent key identifier. The implementation does not
+ *         have sufficient resources to load the persistent key. This can be
+ *         due to a lack of empty key slot, or available memory.
+ * \retval #PSA_ERROR_DOES_NOT_EXIST
+ *         There is no key with key identifier \p key.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DATA_CORRUPT
+ */
+psa_status_t psa_get_and_lock_key_slot( mbedtls_svc_key_id_t key,
+                                        psa_key_slot_t **p_slot );
 
 /** Initialize the key slot structures.
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *         Currently this function always succeeds.
  */
 psa_status_t psa_initialize_key_slots( void );
@@ -60,19 +114,61 @@
 /** Find a free key slot.
  *
  * This function returns a key slot that is available for use and is in its
- * ground state (all-bits-zero).
+ * ground state (all-bits-zero). On success, the key slot is locked. It is
+ * the responsibility of the caller to unlock the key slot when it does not
+ * access it anymore.
  *
- * \param[out] handle   On success, a slot number that can be used as a
- *                      handle to the slot.
- * \param[out] p_slot   On success, a pointer to the slot.
+ * \param[out] volatile_key_id   On success, volatile key identifier
+ *                               associated to the returned slot.
+ * \param[out] p_slot            On success, a pointer to the slot.
  *
  * \retval #PSA_SUCCESS
  * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
  * \retval #PSA_ERROR_BAD_STATE
  */
-psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle,
+psa_status_t psa_get_empty_key_slot( psa_key_id_t *volatile_key_id,
                                      psa_key_slot_t **p_slot );
 
+/** Lock a key slot.
+ *
+ * This function increments the key slot lock counter by one.
+ *
+ * \param[in] slot  The key slot.
+ *
+ * \retval #PSA_SUCCESS
+               The key slot lock counter was incremented.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ *             The lock counter already reached its maximum value and was not
+ *             increased.
+ */
+static inline psa_status_t psa_lock_key_slot( psa_key_slot_t *slot )
+{
+    if( slot->lock_count >= SIZE_MAX )
+        return( PSA_ERROR_CORRUPTION_DETECTED );
+
+    slot->lock_count++;
+
+    return( PSA_SUCCESS );
+}
+
+/** Unlock a key slot.
+ *
+ * This function decrements the key slot lock counter by one.
+ *
+ * \note To ease the handling of errors in retrieving a key slot
+ *       a NULL input pointer is valid, and the function returns
+ *       successfully without doing anything in that case.
+ *
+ * \param[in] slot  The key slot.
+ * \retval #PSA_SUCCESS
+ *             \p slot is NULL or the key slot lock counter has been
+ *             decremented successfully.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ *             The lock counter was equal to 0.
+ *
+ */
+psa_status_t psa_unlock_key_slot( psa_key_slot_t *slot );
+
 /** Test whether a lifetime designates a key in an external cryptoprocessor.
  *
  * \param lifetime      The lifetime to test.
@@ -108,18 +204,26 @@
 psa_status_t psa_validate_key_location( psa_key_lifetime_t lifetime,
                                         psa_se_drv_table_entry_t **p_drv );
 
-/** Validate that a key's persistence attributes are valid.
- *
- * This function checks whether a key's declared persistence level and key ID
- * attributes are valid and known to the PSA Core in its actual configuration.
+/** Validate the persistence of a key.
  *
  * \param[in] lifetime  The key lifetime attribute.
- * \param[in] key       The key identifier.
  *
  * \retval #PSA_SUCCESS
- * \retval #PSA_ERROR_INVALID_ARGUMENT
+ * \retval #PSA_ERROR_INVALID_ARGUMENT The key is persistent but persistent
+ *         keys are not supported.
  */
-psa_status_t psa_validate_key_persistence( psa_key_lifetime_t lifetime,
-                                           mbedtls_svc_key_id_t key );
+psa_status_t psa_validate_key_persistence( psa_key_lifetime_t lifetime );
+
+/** Validate a key identifier.
+ *
+ * \param[in] key           The key identifier.
+ * \param[in] vendor_ok     Non-zero to indicate that key identifiers in the
+ *                          vendor range are allowed, volatile key identifiers
+ *                          excepted \c 0 otherwise.
+ *
+ * \retval #PSA_SUCCESS The identifier is valid.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT The key identifier is not valid.
+ */
+psa_status_t psa_validate_key_id( mbedtls_svc_key_id_t key, int vendor_ok );
 
 #endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */
diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c
index 46d0b65..1ebd20e 100644
--- a/library/psa_crypto_storage.c
+++ b/library/psa_crypto_storage.c
@@ -90,9 +90,9 @@
  * \param[out] data         Buffer where the data is to be written.
  * \param data_size         Size of the \c data buffer in bytes.
  *
- * \retval PSA_SUCCESS
- * \retval PSA_ERROR_STORAGE_FAILURE
- * \retval PSA_ERROR_DOES_NOT_EXIST
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DOES_NOT_EXIST
  */
 static psa_status_t psa_crypto_storage_load(
     const mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size )
@@ -137,10 +137,10 @@
  * \param data_length   The number of bytes
  *                      that make up the data.
  *
- * \retval PSA_SUCCESS
- * \retval PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval PSA_ERROR_STORAGE_FAILURE
- * \retval PSA_ERROR_ALREADY_EXISTS
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_ALREADY_EXISTS
  */
 static psa_status_t psa_crypto_storage_store( const mbedtls_svc_key_id_t key,
                                               const uint8_t *data,
@@ -210,8 +210,8 @@
  *                          is to be obtained.
  * \param[out] data_length  The number of bytes that make up the data.
  *
- * \retval PSA_SUCCESS
- * \retval PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  */
 static psa_status_t psa_crypto_storage_get_data_length(
     const mbedtls_svc_key_id_t key,
@@ -253,6 +253,25 @@
 }
 #endif
 
+/*
+ * 16-bit integer manipulation macros (little endian)
+ */
+#ifndef GET_UINT16_LE
+#define GET_UINT16_LE( n, b, i )                        \
+{                                                       \
+    (n) = ( (uint16_t) (b)[(i)    ]       )             \
+        | ( (uint16_t) (b)[(i) + 1] <<  8 );            \
+}
+#endif
+
+#ifndef PUT_UINT16_LE
+#define PUT_UINT16_LE( n, b, i )                                \
+{                                                               \
+    (b)[(i)    ] = (unsigned char) ( ( (n)       ) & 0xFF );    \
+    (b)[(i) + 1] = (unsigned char) ( ( (n) >>  8 ) & 0xFF );    \
+}
+#endif
+
 /**
  * Persistent key storage magic header.
  */
@@ -263,9 +282,8 @@
     uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH];
     uint8_t version[4];
     uint8_t lifetime[sizeof( psa_key_lifetime_t )];
-    uint8_t type[4]; /* Size=4 for a 2-byte type to keep the structure more
-                      * regular and aligned and to make potential future
-                      * extensibility easier. */
+    uint8_t type[2];
+    uint8_t bits[2];
     uint8_t policy[sizeof( psa_key_policy_t )];
     uint8_t data_len[4];
     uint8_t key_data[];
@@ -282,7 +300,8 @@
     memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH );
     PUT_UINT32_LE( 0, storage_format->version, 0 );
     PUT_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 );
-    PUT_UINT32_LE( (uint32_t) attr->type, storage_format->type, 0 );
+    PUT_UINT16_LE( (uint16_t) attr->type, storage_format->type, 0 );
+    PUT_UINT16_LE( (uint16_t) attr->bits, storage_format->bits, 0 );
     PUT_UINT32_LE( attr->policy.usage, storage_format->policy, 0 );
     PUT_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) );
     PUT_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
@@ -308,7 +327,6 @@
     const psa_persistent_key_storage_format *storage_format =
         (const psa_persistent_key_storage_format *)storage_data;
     uint32_t version;
-    uint32_t type;
 
     if( storage_data_length < sizeof(*storage_format) )
         return( PSA_ERROR_STORAGE_FAILURE );
@@ -339,11 +357,8 @@
     }
 
     GET_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 );
-    GET_UINT32_LE( type, storage_format->type, 0 );
-    if( type <= (psa_key_type_t) -1 )
-        attr->type = (psa_key_type_t) type;
-    else
-        return( PSA_ERROR_STORAGE_FAILURE );
+    GET_UINT16_LE( attr->type, storage_format->type, 0 );
+    GET_UINT16_LE( attr->bits, storage_format->bits, 0 );
     GET_UINT32_LE( attr->policy.usage, storage_format->policy, 0 );
     GET_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) );
     GET_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) );
diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h
index de845a7..fbc94fc 100644
--- a/library/psa_crypto_storage.h
+++ b/library/psa_crypto_storage.h
@@ -81,9 +81,10 @@
  * This function formats the key data and metadata and saves it to a
  * persistent storage backend. The storage location corresponding to the
  * key slot must be empty, otherwise this function will fail. This function
- * should be called after psa_import_key_into_slot() to ensure the
+ * should be called after loading the key into an internal slot to ensure the
  * persistent key is not saved into a storage location corresponding to an
- * already occupied non-persistent key, as well as validating the key data.
+ * already occupied non-persistent key, as well as ensuring the key data is
+ * validated.
  *
  *
  * \param[in] attr          The attributes of the key to save.
@@ -92,11 +93,11 @@
  * \param[in] data          Buffer containing the key data.
  * \param data_length       The number of bytes that make up the key data.
  *
- * \retval PSA_SUCCESS
- * \retval PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval PSA_ERROR_STORAGE_FAILURE
- * \retval PSA_ERROR_ALREADY_EXISTS
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_ALREADY_EXISTS
  */
 psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr,
                                       const uint8_t *data,
@@ -121,10 +122,10 @@
  * \param[out] data         Pointer to an allocated key data buffer on return.
  * \param[out] data_length  The number of bytes that make up the key data.
  *
- * \retval PSA_SUCCESS
- * \retval PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval PSA_ERROR_STORAGE_FAILURE
- * \retval PSA_ERROR_DOES_NOT_EXIST
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_DOES_NOT_EXIST
  */
 psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr,
                                       uint8_t **data,
@@ -136,10 +137,10 @@
  * \param key           Persistent identifier of the key to remove
  *                      from persistent storage.
  *
- * \retval PSA_SUCCESS
+ * \retval #PSA_SUCCESS
  *         The key was successfully removed,
  *         or the key did not exist.
- * \retval PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  */
 psa_status_t psa_destroy_persistent_key( const mbedtls_svc_key_id_t key );
 
@@ -181,10 +182,10 @@
  * \param[out] attr            On success, the attribute structure is filled
  *                             with the loaded key metadata.
  *
- * \retval PSA_SUCCESS
- * \retval PSA_ERROR_INSUFFICIENT_STORAGE
- * \retval PSA_ERROR_INSUFFICIENT_MEMORY
- * \retval PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_STORAGE_FAILURE
  */
 psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data,
                                               size_t storage_data_length,
diff --git a/library/rsa.c b/library/rsa.c
index 84d87de..d6abd65 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -811,15 +811,14 @@
          * which one, we just loop and choose new values for both of them.
          * (Each iteration succeeds with overwhelming probability.) */
         ret = mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vi, &ctx->N );
-        if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
-            continue;
-        if( ret != 0 )
+        if( ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
             goto cleanup;
 
-        /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &R ) );
-        MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) );
-    } while( 0 );
+    } while( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
+
+    /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */
+    MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &R ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) );
 
     /* Blinding value: Vi = Vf^(-e) mod N
      * (Vi already contains Vf^-1 at this point) */
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 083b720..a8331d9 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -63,7 +63,7 @@
         return( 1 );
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( conf->psk_opaque != 0 )
+    if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) )
         return( 1 );
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
@@ -756,6 +756,126 @@
 }
 #endif /* MBEDTLS_SSL_ALPN */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
+                                   unsigned char *buf,
+                                   const unsigned char *end,
+                                   size_t *olen )
+{
+    unsigned char *p = buf;
+    size_t protection_profiles_index = 0, ext_len = 0;
+    uint16_t mki_len = 0, profile_value = 0;
+
+    *olen = 0;
+
+    if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ||
+        ( ssl->conf->dtls_srtp_profile_list == NULL ) ||
+        ( ssl->conf->dtls_srtp_profile_list_len == 0 ) )
+    {
+        return( 0 );
+    }
+
+    /* RFC 5764 section 4.1.1
+     * uint8 SRTPProtectionProfile[2];
+     *
+     * struct {
+     *   SRTPProtectionProfiles SRTPProtectionProfiles;
+     *   opaque srtp_mki<0..255>;
+     * } UseSRTPData;
+     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
+     */
+    if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED )
+    {
+        mki_len = ssl->dtls_srtp_info.mki_len;
+    }
+    /* Extension length = 2 bytes for profiles length,
+     *                    ssl->conf->dtls_srtp_profile_list_len * 2 (each profile is 2 bytes length ),
+     *                    1 byte for srtp_mki vector length and the mki_len value
+     */
+    ext_len = 2 + 2 * ( ssl->conf->dtls_srtp_profile_list_len ) + 1 + mki_len;
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding use_srtp extension" ) );
+
+    /* Check there is room in the buffer for the extension + 4 bytes
+     * - the extension tag (2 bytes)
+     * - the extension length (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, ext_len + 4 );
+
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP      ) & 0xFF );
+
+
+    *p++ = (unsigned char)( ( ( ext_len & 0xFF00 ) >> 8 ) & 0xFF );
+    *p++ = (unsigned char)( ext_len & 0xFF );
+
+    /* protection profile length: 2*(ssl->conf->dtls_srtp_profile_list_len) */
+    /* micro-optimization:
+     * the list size is limited to MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH
+     * which is lower than 127, so the upper byte of the length is always 0
+     * For the documentation, the more generic code is left in comments
+     * *p++ = (unsigned char)( ( ( 2 * ssl->conf->dtls_srtp_profile_list_len )
+     *                        >> 8 ) & 0xFF );
+     */
+    *p++ = 0;
+    *p++ = (unsigned char)( ( 2 * ssl->conf->dtls_srtp_profile_list_len )
+                            & 0xFF );
+
+    for( protection_profiles_index=0;
+         protection_profiles_index < ssl->conf->dtls_srtp_profile_list_len;
+         protection_profiles_index++ )
+    {
+        profile_value = mbedtls_ssl_check_srtp_profile_value
+                ( ssl->conf->dtls_srtp_profile_list[protection_profiles_index] );
+        if( profile_value != MBEDTLS_TLS_SRTP_UNSET )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_write_use_srtp_ext, add profile: %04x",
+                                        profile_value ) );
+            *p++ = ( ( profile_value >> 8 ) & 0xFF );
+            *p++ = ( profile_value & 0xFF );
+        }
+        else
+        {
+            /*
+             * Note: we shall never arrive here as protection profiles
+             * is checked by mbedtls_ssl_conf_dtls_srtp_protection_profiles function
+             */
+            MBEDTLS_SSL_DEBUG_MSG( 3,
+                    ( "client hello, "
+                      "illegal DTLS-SRTP protection profile %d",
+                      ssl->conf->dtls_srtp_profile_list[protection_profiles_index]
+                    ) );
+            return( MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED );
+        }
+    }
+
+    *p++ = mki_len & 0xFF;
+
+    if( mki_len != 0 )
+    {
+        memcpy( p, ssl->dtls_srtp_info.mki_value, mki_len );
+        /*
+         * Increment p to point to the current position.
+         */
+        p += mki_len;
+        MBEDTLS_SSL_DEBUG_BUF( 3, "sending mki",  ssl->dtls_srtp_info.mki_value,
+                               ssl->dtls_srtp_info.mki_len );
+    }
+
+    /*
+     * total extension length: extension type (2 bytes)
+     *                         + extension length (2 bytes)
+     *                         + protection profile length (2 bytes)
+     *                         + 2 * number of protection profiles
+     *                         + srtp_mki vector length(1 byte)
+     *                         + mki value
+     */
+    *olen = p - buf;
+
+    return( 0 );
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
 /*
  * Generate random bytes for ClientHello
  */
@@ -1277,6 +1397,16 @@
     ext_len += olen;
 #endif
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    if( ( ret = ssl_write_use_srtp_ext( ssl, p + 2 + ext_len,
+                                        end, &olen ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_use_srtp_ext", ret );
+        return( ret );
+    }
+    ext_len += olen;
+#endif
+
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
     if( ( ret = ssl_write_session_ticket_ext( ssl, p + 2 + ext_len,
                                               end, &olen ) ) != 0 )
@@ -1710,6 +1840,123 @@
 }
 #endif /* MBEDTLS_SSL_ALPN */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
+                                   const unsigned char *buf,
+                                   size_t len )
+{
+    mbedtls_ssl_srtp_profile server_protection = MBEDTLS_TLS_SRTP_UNSET;
+    size_t i, mki_len = 0;
+    uint16_t server_protection_profile_value = 0;
+
+    /* If use_srtp is not configured, just ignore the extension */
+    if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ||
+        ( ssl->conf->dtls_srtp_profile_list == NULL ) ||
+        ( ssl->conf->dtls_srtp_profile_list_len == 0 ) )
+        return( 0 );
+
+    /* RFC 5764 section 4.1.1
+     * uint8 SRTPProtectionProfile[2];
+     *
+     * struct {
+     *   SRTPProtectionProfiles SRTPProtectionProfiles;
+     *   opaque srtp_mki<0..255>;
+     * } UseSRTPData;
+
+     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
+     *
+     */
+    if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED )
+    {
+        mki_len = ssl->dtls_srtp_info.mki_len;
+    }
+
+    /*
+     * Length is 5 + optional mki_value : one protection profile length (2 bytes)
+     *                                      + protection profile (2 bytes)
+     *                                      + mki_len(1 byte)
+     *                                      and optional srtp_mki
+     */
+    if( ( len < 5 ) || ( len != ( buf[4] + 5u ) ) )
+        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+    /*
+     * get the server protection profile
+     */
+
+    /*
+     * protection profile length must be 0x0002 as we must have only
+     * one protection profile in server Hello
+     */
+    if( (  buf[0] != 0 ) || ( buf[1] != 2 ) )
+        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+    server_protection_profile_value = ( buf[2] << 8 ) | buf[3];
+    server_protection = mbedtls_ssl_check_srtp_profile_value(
+                    server_protection_profile_value );
+    if( server_protection != MBEDTLS_TLS_SRTP_UNSET )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "found srtp profile: %s",
+                                      mbedtls_ssl_get_srtp_profile_as_string(
+                                              server_protection ) ) );
+    }
+
+    ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET;
+
+    /*
+     * Check we have the server profile in our list
+     */
+    for( i=0; i < ssl->conf->dtls_srtp_profile_list_len; i++)
+    {
+        if( server_protection == ssl->conf->dtls_srtp_profile_list[i] )
+        {
+            ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i];
+            MBEDTLS_SSL_DEBUG_MSG( 3, ( "selected srtp profile: %s",
+                                      mbedtls_ssl_get_srtp_profile_as_string(
+                                              server_protection ) ) );
+            break;
+        }
+    }
+
+    /* If no match was found : server problem, it shall never answer with incompatible profile */
+    if( ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET )
+    {
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+
+    /* If server does not use mki in its reply, make sure the client won't keep
+     * one as negotiated */
+    if( len == 5 )
+    {
+        ssl->dtls_srtp_info.mki_len = 0;
+    }
+
+    /*
+     * RFC5764:
+     *  If the client detects a nonzero-length MKI in the server's response
+     *  that is different than the one the client offered, then the client
+     *  MUST abort the handshake and SHOULD send an invalid_parameter alert.
+     */
+    if( len > 5  && ( buf[4] != mki_len ||
+        ( memcmp( ssl->dtls_srtp_info.mki_value, &buf[5], mki_len ) ) ) )
+    {
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                        MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+    }
+#if defined (MBEDTLS_DEBUG_C)
+    if( len > 5 )
+    {
+        MBEDTLS_SSL_DEBUG_BUF( 3, "received mki", ssl->dtls_srtp_info.mki_value,
+                                                  ssl->dtls_srtp_info.mki_len );
+    }
+#endif
+    return( 0 );
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
 /*
  * Parse HelloVerifyRequest.  Only called after verifying the HS type.
  */
@@ -2278,6 +2525,16 @@
             break;
 #endif /* MBEDTLS_SSL_ALPN */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+        case MBEDTLS_TLS_EXT_USE_SRTP:
+            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found use_srtp extension" ) );
+
+            if( ( ret = ssl_parse_use_srtp_ext( ssl, ext + 4, ext_size ) ) != 0 )
+                return( ret );
+
+            break;
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
         default:
             MBEDTLS_SSL_DEBUG_MSG( 3,
                 ( "unknown extension found: %d (ignoring)", ext_id ) );
@@ -3545,7 +3802,7 @@
         status = psa_destroy_key( handshake->ecdh_psa_privkey );
         if( status != PSA_SUCCESS )
             return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
-        handshake->ecdh_psa_privkey = 0;
+        handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
     }
     else
 #endif /* MBEDTLS_USE_PSA_CRYPTO &&
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index 2ea3580..bdf882d 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -1045,21 +1045,86 @@
 
 #if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
 /*
- * Constant-flow conditional memcpy:
- *  - if c1 == c2, equivalent to memcpy(dst, src, len),
- *  - otherwise, a no-op,
- * but with execution flow independent of the values of c1 and c2.
+ * Turn a bit into a mask:
+ * - if bit == 1, return the all-bits 1 mask, aka (size_t) -1
+ * - if bit == 0, return the all-bits 0 mask, aka 0
  *
- * Use only bit operations to avoid branches that could be used by some
- * compilers on some platforms to translate comparison operators.
+ * This function can be used to write constant-time code by replacing branches
+ * with bit operations using masks.
+ *
+ * This function is implemented without using comparison operators, as those
+ * might be translated to branches by some compilers on some platforms.
  */
-static void mbedtls_ssl_cf_memcpy_if_eq( unsigned char *dst,
-                                         const unsigned char *src,
-                                         size_t len,
-                                         size_t c1, size_t c2 )
+static size_t mbedtls_ssl_cf_mask_from_bit( size_t bit )
 {
-    /* diff = 0 if c1 == c2, non-zero otherwise */
-    const size_t diff = c1 ^ c2;
+    /* MSVC has a warning about unary minus on unsigned integer types,
+     * but this is well-defined and precisely what we want to do here. */
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+    return -bit;
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+}
+
+/*
+ * Constant-flow mask generation for "less than" comparison:
+ * - if x < y,  return all bits 1, that is (size_t) -1
+ * - otherwise, return all bits 0, that is 0
+ *
+ * This function can be used to write constant-time code by replacing branches
+ * with bit operations using masks.
+ *
+ * This function is implemented without using comparison operators, as those
+ * might be translated to branches by some compilers on some platforms.
+ */
+static size_t mbedtls_ssl_cf_mask_lt( size_t x, size_t y )
+{
+    /* This has the most significant bit set if and only if x < y */
+    const size_t sub = x - y;
+
+    /* sub1 = (x < y) ? 1 : 0 */
+    const size_t sub1 = sub >> ( sizeof( sub ) * 8 - 1 );
+
+    /* mask = (x < y) ? 0xff... : 0x00... */
+    const size_t mask = mbedtls_ssl_cf_mask_from_bit( sub1 );
+
+    return( mask );
+}
+
+/*
+ * Constant-flow mask generation for "greater or equal" comparison:
+ * - if x >= y, return all bits 1, that is (size_t) -1
+ * - otherwise, return all bits 0, that is 0
+ *
+ * This function can be used to write constant-time code by replacing branches
+ * with bit operations using masks.
+ *
+ * This function is implemented without using comparison operators, as those
+ * might be translated to branches by some compilers on some platforms.
+ */
+static size_t mbedtls_ssl_cf_mask_ge( size_t x, size_t y )
+{
+    return( ~mbedtls_ssl_cf_mask_lt( x, y ) );
+}
+
+/*
+ * Constant-flow boolean "equal" comparison:
+ * return x == y
+ *
+ * This function can be used to write constant-time code by replacing branches
+ * with bit operations - it can be used in conjunction with
+ * mbedtls_ssl_cf_mask_from_bit().
+ *
+ * This function is implemented without using comparison operators, as those
+ * might be translated to branches by some compilers on some platforms.
+ */
+static size_t mbedtls_ssl_cf_bool_eq( size_t x, size_t y )
+{
+    /* diff = 0 if x == y, non-zero otherwise */
+    const size_t diff = x ^ y;
 
     /* MSVC has a warning about unary minus on unsigned integer types,
      * but this is well-defined and precisely what we want to do here. */
@@ -1068,22 +1133,40 @@
 #pragma warning( disable : 4146 )
 #endif
 
-    /* diff_msb's most significant bit is equal to c1 != c2 */
+    /* diff_msb's most significant bit is equal to x != y */
     const size_t diff_msb = ( diff | -diff );
 
-    /* diff1 = c1 != c2 */
-    const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
-
-    /* mask = c1 != c2 ? 0xff : 0x00 */
-    const unsigned char mask = (unsigned char) -diff1;
-
 #if defined(_MSC_VER)
 #pragma warning( pop )
 #endif
 
-    /* dst[i] = c1 != c2 ? dst[i] : src[i] */
+    /* diff1 = (x != y) ? 1 : 0 */
+    const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 );
+
+    return( 1 ^ diff1 );
+}
+
+/*
+ * Constant-flow conditional memcpy:
+ *  - if c1 == c2, equivalent to memcpy(dst, src, len),
+ *  - otherwise, a no-op,
+ * but with execution flow independent of the values of c1 and c2.
+ *
+ * This function is implemented without using comparison operators, as those
+ * might be translated to branches by some compilers on some platforms.
+ */
+static void mbedtls_ssl_cf_memcpy_if_eq( unsigned char *dst,
+                                         const unsigned char *src,
+                                         size_t len,
+                                         size_t c1, size_t c2 )
+{
+    /* mask = c1 == c2 ? 0xff : 0x00 */
+    const size_t equal = mbedtls_ssl_cf_bool_eq( c1, c2 );
+    const unsigned char mask = (unsigned char) mbedtls_ssl_cf_mask_from_bit( equal );
+
+    /* dst[i] = c1 == c2 ? src[i] : dst[i] */
     for( size_t i = 0; i < len; i++ )
-        dst[i] = ( dst[i] & mask ) | ( src[i] & ~mask );
+        dst[i] = ( src[i] & mask ) | ( dst[i] & ~mask );
 }
 
 /*
@@ -1528,8 +1611,11 @@
 
         if( auth_done == 1 )
         {
-            correct *= ( rec->data_len >= padlen + 1 );
-            padlen  *= ( rec->data_len >= padlen + 1 );
+            const size_t mask = mbedtls_ssl_cf_mask_ge(
+                                rec->data_len,
+                                padlen + 1 );
+            correct &= mask;
+            padlen  &= mask;
         }
         else
         {
@@ -1543,8 +1629,11 @@
             }
 #endif
 
-            correct *= ( rec->data_len >= transform->maclen + padlen + 1 );
-            padlen  *= ( rec->data_len >= transform->maclen + padlen + 1 );
+            const size_t mask = mbedtls_ssl_cf_mask_ge(
+                                rec->data_len,
+                                transform->maclen + padlen + 1 );
+            correct &= mask;
+            padlen  &= mask;
         }
 
         padlen++;
@@ -1555,6 +1644,10 @@
 #if defined(MBEDTLS_SSL_PROTO_SSL3)
         if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
         {
+            /* This is the SSL 3.0 path, we don't have to worry about Lucky
+             * 13, because there's a strictly worse padding attack built in
+             * the protocol (known as part of POODLE), so we don't care if the
+             * code is not constant-time, in particular branches are OK. */
             if( padlen > transform->ivlen )
             {
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
@@ -1578,7 +1671,6 @@
              * `min(256,plaintext_len)` reads (but take into account
              * only the last `padlen` bytes for the padding check). */
             size_t pad_count = 0;
-            size_t real_count = 0;
             volatile unsigned char* const check = data;
 
             /* Index of first padding byte; it has been ensured above
@@ -1590,16 +1682,21 @@
 
             for( idx = start_idx; idx < rec->data_len; idx++ )
             {
-                real_count |= ( idx >= padding_idx );
-                pad_count += real_count * ( check[idx] == padlen - 1 );
+                /* pad_count += (idx >= padding_idx) &&
+                 *              (check[idx] == padlen - 1);
+                 */
+                const size_t mask = mbedtls_ssl_cf_mask_ge( idx, padding_idx );
+                const size_t equal = mbedtls_ssl_cf_bool_eq( check[idx],
+                                                             padlen - 1 );
+                pad_count += mask & equal;
             }
-            correct &= ( pad_count == padlen );
+            correct &= mbedtls_ssl_cf_bool_eq( pad_count, padlen );
 
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
             if( padlen > 0 && correct == 0 )
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) );
 #endif
-            padlen &= correct * 0x1FF;
+            padlen &= mbedtls_ssl_cf_mask_from_bit( correct );
         }
         else
 #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
@@ -1921,14 +2018,6 @@
     {
         uint32_t timeout;
 
-        /* Just to be sure */
-        if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use "
-                        "mbedtls_ssl_set_timer_cb() for DTLS" ) );
-            return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-        }
-
         /*
          * The point is, we need to always read a full datagram at once, so we
          * sometimes read more then requested, and handle the additional data.
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 2e63fce..e33b828 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -157,7 +157,7 @@
         return( 1 );
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( conf->psk_opaque != 0 )
+    if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) )
         return( 1 );
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
@@ -172,13 +172,13 @@
         /* If we've used a callback to select the PSK,
          * the static configuration is irrelevant. */
 
-        if( ssl->handshake->psk_opaque != 0 )
+        if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) )
             return( 1 );
 
         return( 0 );
     }
 
-    if( ssl->conf->psk_opaque != 0 )
+    if( ! mbedtls_svc_key_id_is_null( ssl->conf->psk_opaque ) )
         return( 1 );
 
     return( 0 );
@@ -776,6 +776,126 @@
 }
 #endif /* MBEDTLS_SSL_ALPN */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
+                                   const unsigned char *buf,
+                                   size_t len )
+{
+    mbedtls_ssl_srtp_profile client_protection = MBEDTLS_TLS_SRTP_UNSET;
+    size_t i,j;
+    size_t profile_length;
+    uint16_t mki_length;
+    /*! 2 bytes for profile length and 1 byte for mki len */
+    const size_t size_of_lengths = 3;
+
+    /* If use_srtp is not configured, just ignore the extension */
+    if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ||
+        ( ssl->conf->dtls_srtp_profile_list == NULL ) ||
+        ( ssl->conf->dtls_srtp_profile_list_len == 0 ) )
+    {
+        return( 0 );
+    }
+
+    /* RFC5764 section 4.1.1
+     * uint8 SRTPProtectionProfile[2];
+     *
+     * struct {
+     *   SRTPProtectionProfiles SRTPProtectionProfiles;
+     *   opaque srtp_mki<0..255>;
+     * } UseSRTPData;
+
+     * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>;
+     */
+
+    /*
+     * Min length is 5: at least one protection profile(2 bytes)
+     *                  and length(2 bytes) + srtp_mki length(1 byte)
+     * Check here that we have at least 2 bytes of protection profiles length
+     * and one of srtp_mki length
+     */
+    if( len < size_of_lengths )
+    {
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+   ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET;
+
+    /* first 2 bytes are protection profile length(in bytes) */
+    profile_length = ( buf[0] << 8 ) | buf[1];
+    buf += 2;
+
+    /* The profile length cannot be bigger than input buffer size - lengths fields */
+    if( profile_length > len - size_of_lengths ||
+        profile_length % 2 != 0 ) /* profiles are 2 bytes long, so the length must be even */
+    {
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+    /*
+     * parse the extension list values are defined in
+     * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml
+     */
+    for( j = 0; j < profile_length; j += 2 )
+    {
+        uint16_t protection_profile_value = buf[j] << 8 | buf[j + 1];
+        client_protection = mbedtls_ssl_check_srtp_profile_value( protection_profile_value );
+
+        if( client_protection != MBEDTLS_TLS_SRTP_UNSET )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 3, ( "found srtp profile: %s",
+                                    mbedtls_ssl_get_srtp_profile_as_string(
+                                            client_protection ) ) );
+        }
+        else
+        {
+            continue;
+        }
+        /* check if suggested profile is in our list */
+        for( i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++)
+        {
+            if( client_protection == ssl->conf->dtls_srtp_profile_list[i] )
+            {
+                ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i];
+                MBEDTLS_SSL_DEBUG_MSG( 3, ( "selected srtp profile: %s",
+                                            mbedtls_ssl_get_srtp_profile_as_string(
+                                                    client_protection ) ) );
+                break;
+            }
+        }
+        if( ssl->dtls_srtp_info.chosen_dtls_srtp_profile != MBEDTLS_TLS_SRTP_UNSET )
+            break;
+    }
+    buf += profile_length; /* buf points to the mki length */
+    mki_length = *buf;
+    buf++;
+
+    if( mki_length > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH ||
+        mki_length + profile_length + size_of_lengths != len )
+    {
+        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                        MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
+        return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+    }
+
+    /* Parse the mki only if present and mki is supported locally */
+    if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED &&
+          mki_length > 0 )
+    {
+        ssl->dtls_srtp_info.mki_len = mki_length;
+
+        memcpy( ssl->dtls_srtp_info.mki_value, buf, mki_length );
+
+        MBEDTLS_SSL_DEBUG_BUF( 3, "using mki",  ssl->dtls_srtp_info.mki_value,
+                                                ssl->dtls_srtp_info.mki_len );
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
 /*
  * Auxiliary functions for ServerHello parsing and related actions
  */
@@ -1942,6 +2062,16 @@
                 break;
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+            case MBEDTLS_TLS_EXT_USE_SRTP:
+                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found use_srtp extension" ) );
+
+                ret = ssl_parse_use_srtp_ext( ssl, ext + 4, ext_size );
+                if( ret != 0 )
+                    return( ret );
+                break;
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
             default:
                 MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)",
                                ext_id ) );
@@ -2500,6 +2630,78 @@
 }
 #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP ) && defined(MBEDTLS_SSL_PROTO_DTLS)
+static void ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
+                                    unsigned char *buf,
+                                    size_t *olen )
+{
+    size_t mki_len = 0, ext_len = 0;
+    uint16_t profile_value = 0;
+    const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
+
+    *olen = 0;
+
+    if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) ||
+        ( ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET ) )
+    {
+        return;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding use_srtp extension" ) );
+
+    if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED )
+    {
+        mki_len = ssl->dtls_srtp_info.mki_len;
+    }
+
+    /* The extension total size is 9 bytes :
+     * - 2 bytes for the extension tag
+     * - 2 bytes for the total size
+     * - 2 bytes for the protection profile length
+     * - 2 bytes for the protection profile
+     * - 1 byte for the mki length
+     * +  the actual mki length
+     * Check we have enough room in the output buffer */
+    if( (size_t)( end - buf ) < mki_len + 9 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) );
+        return;
+    }
+
+    /* extension */
+    buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP >> 8 ) & 0xFF );
+    buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_USE_SRTP      ) & 0xFF );
+    /*
+     * total length 5 and mki value: only one profile(2 bytes)
+     *              and length(2 bytes) and srtp_mki  )
+     */
+    ext_len = 5 + mki_len;
+    buf[2] = (unsigned char)( ( ext_len >> 8 ) & 0xFF );
+    buf[3] = (unsigned char)( ext_len & 0xFF );
+
+    /* protection profile length: 2 */
+    buf[4] = 0x00;
+    buf[5] = 0x02;
+    profile_value = mbedtls_ssl_check_srtp_profile_value(
+                                ssl->dtls_srtp_info.chosen_dtls_srtp_profile );
+    if( profile_value != MBEDTLS_TLS_SRTP_UNSET )
+    {
+        buf[6] = (unsigned char)( ( profile_value >> 8 ) & 0xFF );
+        buf[7] = (unsigned char)( profile_value & 0xFF );
+    }
+    else
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "use_srtp extension invalid profile" ) );
+        return;
+    }
+
+    buf[8] = mki_len & 0xFF;
+    memcpy( &buf[9], ssl->dtls_srtp_info.mki_value, mki_len );
+
+    *olen = 9 + mki_len;
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
 static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
 {
@@ -2788,6 +2990,11 @@
     ext_len += olen;
 #endif
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    ssl_write_use_srtp_ext( ssl, p + 2 + ext_len, &olen );
+    ext_len += olen;
+#endif
+
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) );
 
     if( ext_len > 0 )
@@ -3722,11 +3929,12 @@
     /* In case of a failure in decryption, the decryption may write less than
      * 2 bytes of output, but we always read the first two bytes. It doesn't
      * matter in the end because diff will be nonzero in that case due to
-     * peer_pmslen being less than 48, and we only care whether diff is 0.
-     * But do initialize peer_pms for robustness anyway. This also makes
-     * memory analyzers happy (don't access uninitialized memory, even
-     * if it's an unsigned char). */
+     * ret being nonzero, and we only care whether diff is 0.
+     * But do initialize peer_pms and peer_pmslen for robustness anyway. This
+     * also makes memory analyzers happy (don't access uninitialized memory,
+     * even if it's an unsigned char). */
     peer_pms[0] = peer_pms[1] = ~0;
+    peer_pmslen = 0;
 
     ret = ssl_decrypt_encrypted_pms( ssl, p, end,
                                      peer_pms,
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 7062d53..041578e 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -446,7 +446,7 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 
 static psa_status_t setup_psa_key_derivation( psa_key_derivation_operation_t* derivation,
-                                              psa_key_handle_t slot,
+                                              psa_key_id_t key,
                                               psa_algorithm_t alg,
                                               const unsigned char* seed, size_t seed_length,
                                               const unsigned char* label, size_t label_length,
@@ -466,7 +466,7 @@
         if( status != PSA_SUCCESS )
             return( status );
 
-        if( slot == 0 )
+        if( mbedtls_svc_key_id_is_null( key ) )
         {
             status = psa_key_derivation_input_bytes(
                 derivation, PSA_KEY_DERIVATION_INPUT_SECRET,
@@ -475,8 +475,7 @@
         else
         {
             status = psa_key_derivation_input_key(
-                derivation, PSA_KEY_DERIVATION_INPUT_SECRET,
-                slot );
+                derivation, PSA_KEY_DERIVATION_INPUT_SECRET, key );
         }
         if( status != PSA_SUCCESS )
             return( status );
@@ -507,7 +506,7 @@
 {
     psa_status_t status;
     psa_algorithm_t alg;
-    psa_key_handle_t master_slot = 0;
+    psa_key_id_t master_key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_derivation_operation_t derivation =
         PSA_KEY_DERIVATION_OPERATION_INIT;
 
@@ -521,7 +520,7 @@
      * this PRF is also used to derive an IV, in particular in EAP-TLS,
      * and for this use case it makes sense to have a 0-length "secret".
      * Since the key API doesn't allow importing a key of length 0,
-     * keep master_slot=0, which setup_psa_key_derivation() understands
+     * keep master_key=0, which setup_psa_key_derivation() understands
      * to mean a 0-length "secret" input. */
     if( slen != 0 )
     {
@@ -530,13 +529,13 @@
         psa_set_key_algorithm( &key_attributes, alg );
         psa_set_key_type( &key_attributes, PSA_KEY_TYPE_DERIVE );
 
-        status = psa_import_key( &key_attributes, secret, slen, &master_slot );
+        status = psa_import_key( &key_attributes, secret, slen, &master_key );
         if( status != PSA_SUCCESS )
             return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
     }
 
     status = setup_psa_key_derivation( &derivation,
-                                       master_slot, alg,
+                                       master_key, alg,
                                        random, rlen,
                                        (unsigned char const *) label,
                                        (size_t) strlen( label ),
@@ -544,7 +543,7 @@
     if( status != PSA_SUCCESS )
     {
         psa_key_derivation_abort( &derivation );
-        psa_destroy_key( master_slot );
+        psa_destroy_key( master_key );
         return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
     }
 
@@ -552,19 +551,19 @@
     if( status != PSA_SUCCESS )
     {
         psa_key_derivation_abort( &derivation );
-        psa_destroy_key( master_slot );
+        psa_destroy_key( master_key );
         return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
     }
 
     status = psa_key_derivation_abort( &derivation );
     if( status != PSA_SUCCESS )
     {
-        psa_destroy_key( master_slot );
+        psa_destroy_key( master_key );
         return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
     }
 
-    if( master_slot != 0 )
-        status = psa_destroy_key( master_slot );
+    if( ! mbedtls_svc_key_id_is_null( master_key ) )
+        status = psa_destroy_key( master_key );
     if( status != PSA_SUCCESS )
         return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
 
@@ -707,13 +706,13 @@
     {
         /* If we've used a callback to select the PSK,
          * the static configuration is irrelevant. */
-        if( ssl->handshake->psk_opaque != 0 )
+        if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) )
             return( 1 );
 
         return( 0 );
     }
 
-    if( ssl->conf->psk_opaque != 0 )
+    if( ! mbedtls_svc_key_id_is_null( ssl->conf->psk_opaque ) )
         return( 1 );
 
     return( 0 );
@@ -1514,7 +1513,7 @@
         /* Perform PSK-to-MS expansion in a single step. */
         psa_status_t status;
         psa_algorithm_t alg;
-        psa_key_handle_t psk;
+        psa_key_id_t psk;
         psa_key_derivation_operation_t derivation =
             PSA_KEY_DERIVATION_OPERATION_INIT;
         mbedtls_md_type_t hash_alg = handshake->ciphersuite_info->mac;
@@ -3859,6 +3858,10 @@
 
     mbedtls_ssl_reset_in_out_pointers( ssl );
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    memset( &ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info) );
+#endif
+
     if( ( ret = ssl_handshake_init( ssl ) ) != 0 )
         goto error;
 
@@ -4340,11 +4343,11 @@
 {
     /* Remove reference to existing PSK, if any. */
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( conf->psk_opaque != 0 )
+    if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) )
     {
         /* The maintenance of the PSK key slot is the
          * user's responsibility. */
-        conf->psk_opaque = 0;
+        conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;
     }
     /* This and the following branch should never
      * be taken simultaenously as we maintain the
@@ -4428,9 +4431,9 @@
 static void ssl_remove_psk( mbedtls_ssl_context *ssl )
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if( ssl->handshake->psk_opaque != 0 )
+    if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) )
     {
-        ssl->handshake->psk_opaque = 0;
+        ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;
     }
     else
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
@@ -4465,7 +4468,7 @@
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf,
-                                 psa_key_handle_t psk_slot,
+                                 psa_key_id_t psk,
                                  const unsigned char *psk_identity,
                                  size_t psk_identity_len )
 {
@@ -4474,9 +4477,9 @@
     ssl_conf_remove_psk( conf );
 
     /* Check and set opaque PSK */
-    if( psk_slot == 0 )
+    if( mbedtls_svc_key_id_is_null( psk ) )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-    conf->psk_opaque = psk_slot;
+    conf->psk_opaque = psk;
 
     /* Check and set PSK Identity */
     ret = ssl_conf_set_psk_identity( conf, psk_identity,
@@ -4488,13 +4491,14 @@
 }
 
 int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl,
-                                   psa_key_handle_t psk_slot )
+                                   psa_key_id_t psk )
 {
-    if( psk_slot == 0 || ssl->handshake == NULL )
+    if( ( mbedtls_svc_key_id_is_null( psk ) ) ||
+        ( ssl->handshake == NULL ) )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
     ssl_remove_psk( ssl );
-    ssl->handshake->psk_opaque = psk_slot;
+    ssl->handshake->psk_opaque = psk;
     return( 0 );
 }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
@@ -4685,6 +4689,86 @@
 }
 #endif /* MBEDTLS_SSL_ALPN */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+void mbedtls_ssl_conf_srtp_mki_value_supported( mbedtls_ssl_config *conf,
+                                                int support_mki_value )
+{
+    conf->dtls_srtp_mki_support = support_mki_value;
+}
+
+int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl,
+                                         unsigned char *mki_value,
+                                         uint16_t mki_len )
+{
+    if( mki_len > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH )
+    {
+        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED )
+    {
+        return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+    }
+
+    memcpy( ssl->dtls_srtp_info.mki_value, mki_value, mki_len );
+    ssl->dtls_srtp_info.mki_len = mki_len;
+    return( 0 );
+}
+
+int mbedtls_ssl_conf_dtls_srtp_protection_profiles( mbedtls_ssl_config *conf,
+                                                    const mbedtls_ssl_srtp_profile *profiles )
+{
+    const mbedtls_ssl_srtp_profile *p;
+    size_t list_size = 0;
+
+    /* check the profiles list: all entry must be valid,
+     * its size cannot be more than the total number of supported profiles, currently 4 */
+    for( p = profiles; *p != MBEDTLS_TLS_SRTP_UNSET &&
+                       list_size <= MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH;
+         p++ )
+    {
+        if( mbedtls_ssl_check_srtp_profile_value( *p ) != MBEDTLS_TLS_SRTP_UNSET )
+        {
+            list_size++;
+        }
+        else
+        {
+            /* unsupported value, stop parsing and set the size to an error value */
+            list_size = MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + 1;
+        }
+    }
+
+    if( list_size > MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH )
+    {
+                conf->dtls_srtp_profile_list = NULL;
+                conf->dtls_srtp_profile_list_len = 0;
+                return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    }
+
+    conf->dtls_srtp_profile_list = profiles;
+    conf->dtls_srtp_profile_list_len = list_size;
+
+    return( 0 );
+}
+
+void mbedtls_ssl_get_dtls_srtp_negotiation_result( const mbedtls_ssl_context *ssl,
+                                                   mbedtls_dtls_srtp_info *dtls_srtp_info )
+{
+    dtls_srtp_info->chosen_dtls_srtp_profile = ssl->dtls_srtp_info.chosen_dtls_srtp_profile;
+    /* do not copy the mki value if there is no chosen profile */
+    if( dtls_srtp_info->chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET )
+    {
+        dtls_srtp_info->mki_len = 0;
+    }
+    else
+    {
+        dtls_srtp_info->mki_len = ssl->dtls_srtp_info.mki_len;
+        memcpy( dtls_srtp_info->mki_value, ssl->dtls_srtp_info.mki_value,
+                ssl->dtls_srtp_info.mki_len );
+    }
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
 void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor )
 {
     conf->max_major_ver = major;
@@ -5682,11 +5766,24 @@
 {
     int ret = 0;
 
+    /* Sanity checks */
+
     if( ssl == NULL || ssl->conf == NULL )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use "
+                                     "mbedtls_ssl_set_timer_cb() for DTLS" ) );
+        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) );
 
+    /* Main handshake loop */
     while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER )
     {
         ret = mbedtls_ssl_handshake_step( ssl );
diff --git a/library/threading.c b/library/threading.c
index 9268da1..2bb932d 100644
--- a/library/threading.c
+++ b/library/threading.c
@@ -42,7 +42,7 @@
 
 #if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) ||     \
        ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) &&                     \
-         _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) )
+         _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) )
 /*
  * This is a convenience shorthand macro to avoid checking the long
  * preprocessor conditions above. Ideally, we could expose this macro in
@@ -57,7 +57,7 @@
 
 #endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) ||     \
              ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) &&                     \
-                _POSIX_THREAD_SAFE_FUNCTIONS >= 20112L ) ) */
+                _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */
 
 #endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */
 
diff --git a/library/version_features.c b/library/version_features.c
index 478d8fa..42ccaf9 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -534,6 +534,9 @@
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
     "MBEDTLS_SSL_DTLS_HELLO_VERIFY",
 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    "MBEDTLS_SSL_DTLS_SRTP",
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
 #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
     "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE",
 #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */
@@ -576,6 +579,9 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     "MBEDTLS_USE_PSA_CRYPTO",
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
+#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
+    "MBEDTLS_PSA_CRYPTO_CONFIG",
+#endif /* MBEDTLS_PSA_CRYPTO_CONFIG */
 #if defined(MBEDTLS_VERSION_FEATURES)
     "MBEDTLS_VERSION_FEATURES",
 #endif /* MBEDTLS_VERSION_FEATURES */
diff --git a/programs/.gitignore b/programs/.gitignore
index 53c1ed7..88fb9d5 100644
--- a/programs/.gitignore
+++ b/programs/.gitignore
@@ -32,7 +32,6 @@
 psa/crypto_examples
 psa/key_ladder_demo
 psa/psa_constant_names
-psa/psa_constant_names_generated.c
 random/gen_entropy
 random/gen_random_ctr_drbg
 random/gen_random_havege
diff --git a/programs/Makefile b/programs/Makefile
index dfe0555..9cbc471 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -118,8 +118,6 @@
 APPS += test/cpp_dummy_build$(EXEXT)
 endif
 
-EXTRA_GENERATED =
-
 .SILENT:
 
 .PHONY: all clean list fuzz
@@ -141,16 +139,6 @@
 ${MBEDTLS_TEST_OBJS}:
 	$(MAKE) -C ../tests mbedtls_test
 
-ifdef WINDOWS
-EXTRA_GENERATED += psa\psa_constant_names_generated.c
-else
-EXTRA_GENERATED += psa/psa_constant_names_generated.c
-endif
-
-psa/psa_constant_names$(EXEXT): psa/psa_constant_names_generated.c
-psa/psa_constant_names_generated.c: ../scripts/generate_psa_constants.py ../include/psa/crypto_values.h ../include/psa/crypto_extra.h
-	../scripts/generate_psa_constants.py
-
 aes/aescrypt2$(EXEXT): aes/aescrypt2.c $(DEP)
 	echo "  CC    aes/aescrypt2.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) aes/aescrypt2.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
@@ -371,12 +359,10 @@
 ifndef WINDOWS
 	rm -f $(APPS)
 	-rm -f ssl/ssl_pthread_server$(EXEXT)
-	rm -f $(EXTRA_GENERATED)
 	-rm -f test/cpp_dummy_build$(EXEXT)
 else
 	if exist *.o del /Q /F *.o
 	if exist *.exe del /Q /F *.exe
-	del /S /Q /F $(EXTRA_GENERATED)
 endif
 	$(MAKE) -C fuzz clean
 
diff --git a/programs/aes/CMakeLists.txt b/programs/aes/CMakeLists.txt
index 2309789..6b8ce2a 100644
--- a/programs/aes/CMakeLists.txt
+++ b/programs/aes/CMakeLists.txt
@@ -5,7 +5,7 @@
 
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
-    target_link_libraries(${exe} mbedcrypto)
+    target_link_libraries(${exe} ${mbedcrypto_target})
 endforeach()
 
 install(TARGETS ${executables}
diff --git a/programs/fuzz/CMakeLists.txt b/programs/fuzz/CMakeLists.txt
index e2b0eac..f0e5705 100644
--- a/programs/fuzz/CMakeLists.txt
+++ b/programs/fuzz/CMakeLists.txt
@@ -1,5 +1,5 @@
 set(libs
-    mbedtls
+    ${mbedtls_target}
 )
 
 if(USE_PKCS11_HELPER_LIBRARY)
@@ -36,7 +36,7 @@
 
     if (NOT FUZZINGENGINE_LIB)
         target_link_libraries(${exe} ${libs})
-        target_sources(${exe} PRIVATE onefile.c)
+        set_property(TARGET ${exe} APPEND PROPERTY SOURCES onefile.c)
     else()
         target_link_libraries(${exe} ${libs} FuzzingEngine)
         SET_TARGET_PROPERTIES(${exe} PROPERTIES LINKER_LANGUAGE CXX)
@@ -45,7 +45,7 @@
     # This emulates "if ( ... IN_LIST ... )" which becomes available in CMake 3.3
     list(FIND executables_with_common_c ${exe} exe_index)
     if (${exe_index} GREATER -1)
-        target_sources(${exe} PRIVATE common.c)
+        set_property(TARGET ${exe} APPEND PROPERTY SOURCES common.c)
     endif()
 
 endforeach()
diff --git a/programs/hash/CMakeLists.txt b/programs/hash/CMakeLists.txt
index ae29479..b2f2a1f 100644
--- a/programs/hash/CMakeLists.txt
+++ b/programs/hash/CMakeLists.txt
@@ -5,7 +5,7 @@
 
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
-    target_link_libraries(${exe} mbedcrypto)
+    target_link_libraries(${exe} ${mbedcrypto_target})
 endforeach()
 
 install(TARGETS ${executables}
diff --git a/programs/pkey/CMakeLists.txt b/programs/pkey/CMakeLists.txt
index b4b3d30..9c6fe7d 100644
--- a/programs/pkey/CMakeLists.txt
+++ b/programs/pkey/CMakeLists.txt
@@ -5,7 +5,7 @@
 
 foreach(exe IN LISTS executables_mbedtls)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
-    target_link_libraries(${exe} mbedtls)
+    target_link_libraries(${exe} ${mbedtls_target})
 endforeach()
 
 set(executables_mbedcrypto
@@ -31,7 +31,7 @@
 
 foreach(exe IN LISTS executables_mbedcrypto)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
-    target_link_libraries(${exe} mbedcrypto)
+    target_link_libraries(${exe} ${mbedcrypto_target})
 endforeach()
 
 install(TARGETS ${executables_mbedtls} ${executables_mbedcrypto}
diff --git a/programs/psa/CMakeLists.txt b/programs/psa/CMakeLists.txt
index e519696..23e85fe 100644
--- a/programs/psa/CMakeLists.txt
+++ b/programs/psa/CMakeLists.txt
@@ -6,19 +6,12 @@
 
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
-    target_link_libraries(${exe} mbedcrypto)
+    target_link_libraries(${exe} ${mbedcrypto_target})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 endforeach()
 
 target_include_directories(psa_constant_names PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
 
-add_custom_target(
-    psa_constant_names_generated
-    COMMAND ${MBEDTLS_PYTHON_EXECUTABLE} scripts/generate_psa_constants.py ${CMAKE_CURRENT_BINARY_DIR}
-    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../
-)
-add_dependencies(psa_constant_names psa_constant_names_generated)
-
 install(TARGETS ${executables}
         DESTINATION "bin"
         PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
diff --git a/programs/psa/crypto_examples.c b/programs/psa/crypto_examples.c
index 623a090..d165d2e 100644
--- a/programs/psa/crypto_examples.c
+++ b/programs/psa/crypto_examples.c
@@ -45,13 +45,15 @@
 
 #if !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(MBEDTLS_AES_C) || \
     !defined(MBEDTLS_CIPHER_MODE_CBC) || !defined(MBEDTLS_CIPHER_MODE_CTR) || \
-    !defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
+    !defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) || \
+    defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
 int main( void )
 {
     printf( "MBEDTLS_PSA_CRYPTO_C and/or MBEDTLS_AES_C and/or "
             "MBEDTLS_CIPHER_MODE_CBC and/or MBEDTLS_CIPHER_MODE_CTR "
             "and/or MBEDTLS_CIPHER_MODE_WITH_PADDING "
-            "not defined.\r\n" );
+            "not defined and/or MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER"
+            " defined.\r\n" );
     return( 0 );
 }
 #else
@@ -92,7 +94,7 @@
     return( status );
 }
 
-static psa_status_t cipher_encrypt( psa_key_handle_t key_handle,
+static psa_status_t cipher_encrypt( psa_key_id_t key,
                                     psa_algorithm_t alg,
                                     uint8_t * iv,
                                     size_t iv_size,
@@ -108,7 +110,7 @@
     size_t iv_len = 0;
 
     memset( &operation, 0, sizeof( operation ) );
-    status = psa_cipher_encrypt_setup( &operation, key_handle, alg );
+    status = psa_cipher_encrypt_setup( &operation, key, alg );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
     status = psa_cipher_generate_iv( &operation, iv, iv_size, &iv_len );
@@ -123,7 +125,7 @@
     return( status );
 }
 
-static psa_status_t cipher_decrypt( psa_key_handle_t key_handle,
+static psa_status_t cipher_decrypt( psa_key_id_t key,
                                     psa_algorithm_t alg,
                                     const uint8_t * iv,
                                     size_t iv_size,
@@ -138,7 +140,7 @@
     psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
 
     memset( &operation, 0, sizeof( operation ) );
-    status = psa_cipher_decrypt_setup( &operation, key_handle, alg );
+    status = psa_cipher_decrypt_setup( &operation, key, alg );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
     status = psa_cipher_set_iv( &operation, iv, iv_size );
@@ -165,7 +167,7 @@
 
     psa_status_t status;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_handle_t key_handle = 0;
+    psa_key_id_t key = 0;
     size_t output_len = 0;
     uint8_t iv[block_size];
     uint8_t input[block_size];
@@ -181,15 +183,15 @@
     psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
     psa_set_key_bits( &attributes, key_bits );
 
-    status = psa_generate_key( &attributes, &key_handle );
+    status = psa_generate_key( &attributes, &key );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
+    status = cipher_encrypt( key, alg, iv, sizeof( iv ),
                              input, sizeof( input ), part_size,
                              encrypt, sizeof( encrypt ), &output_len );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ),
+    status = cipher_decrypt( key, alg, iv, sizeof( iv ),
                              encrypt, output_len, part_size,
                              decrypt, sizeof( decrypt ), &output_len );
     ASSERT_STATUS( status, PSA_SUCCESS );
@@ -198,7 +200,7 @@
     ASSERT_STATUS( status, PSA_SUCCESS );
 
 exit:
-    psa_destroy_key( key_handle );
+    psa_destroy_key( key );
     return( status );
 }
 
@@ -215,7 +217,7 @@
 
     psa_status_t status;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_handle_t key_handle = 0;
+    psa_key_id_t key = 0;
     size_t output_len = 0;
     uint8_t iv[block_size], input[input_size],
             encrypt[input_size + block_size], decrypt[input_size + block_size];
@@ -229,15 +231,15 @@
     psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
     psa_set_key_bits( &attributes, key_bits );
 
-    status = psa_generate_key( &attributes, &key_handle );
+    status = psa_generate_key( &attributes, &key );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
+    status = cipher_encrypt( key, alg, iv, sizeof( iv ),
                              input, sizeof( input ), part_size,
                              encrypt, sizeof( encrypt ), &output_len );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ),
+    status = cipher_decrypt( key, alg, iv, sizeof( iv ),
                              encrypt, output_len, part_size,
                              decrypt, sizeof( decrypt ), &output_len );
     ASSERT_STATUS( status, PSA_SUCCESS );
@@ -246,7 +248,7 @@
     ASSERT_STATUS( status, PSA_SUCCESS );
 
 exit:
-    psa_destroy_key( key_handle );
+    psa_destroy_key( key );
     return( status );
 }
 
@@ -262,7 +264,7 @@
 
     psa_status_t status;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_handle_t key_handle = 0;
+    psa_key_id_t key = 0;
     size_t output_len = 0;
     uint8_t iv[block_size], input[input_size], encrypt[input_size],
             decrypt[input_size];
@@ -276,15 +278,15 @@
     psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
     psa_set_key_bits( &attributes, key_bits );
 
-    status = psa_generate_key( &attributes, &key_handle );
+    status = psa_generate_key( &attributes, &key );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = cipher_encrypt( key_handle, alg, iv, sizeof( iv ),
+    status = cipher_encrypt( key, alg, iv, sizeof( iv ),
                              input, sizeof( input ), part_size,
                              encrypt, sizeof( encrypt ), &output_len );
     ASSERT_STATUS( status, PSA_SUCCESS );
 
-    status = cipher_decrypt( key_handle, alg, iv, sizeof( iv ),
+    status = cipher_decrypt( key, alg, iv, sizeof( iv ),
                              encrypt, output_len, part_size,
                              decrypt, sizeof( decrypt ), &output_len );
     ASSERT_STATUS( status, PSA_SUCCESS );
@@ -293,7 +295,7 @@
     ASSERT_STATUS( status, PSA_SUCCESS );
 
 exit:
-    psa_destroy_key( key_handle );
+    psa_destroy_key( key );
     return( status );
 }
 
@@ -317,18 +319,6 @@
         printf( "\tsuccess!\r\n" );
 }
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    exit( EXIT_FAILURE );
-}
-#endif
-
 int main( void )
 {
     ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
diff --git a/programs/psa/key_ladder_demo.c b/programs/psa/key_ladder_demo.c
index ae2442e..47d5de6 100644
--- a/programs/psa/key_ladder_demo.c
+++ b/programs/psa/key_ladder_demo.c
@@ -65,15 +65,17 @@
 #include <psa/crypto.h>
 
 /* If the build options we need are not enabled, compile a placeholder. */
-#if !defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_MD_C) ||     \
-    !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CCM_C) ||       \
-    !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(MBEDTLS_FS_IO)
+#if !defined(MBEDTLS_SHA256_C) || !defined(MBEDTLS_MD_C) ||      \
+    !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CCM_C) ||        \
+    !defined(MBEDTLS_PSA_CRYPTO_C) || !defined(MBEDTLS_FS_IO) || \
+    defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
 int main( void )
 {
-    printf("MBEDTLS_SHA256_C and/or MBEDTLS_MD_C and/or "
-           "MBEDTLS_AES_C and/or MBEDTLS_CCM_C and/or "
-           "MBEDTLS_PSA_CRYPTO_C and/or MBEDTLS_FS_IO "
-           "not defined.\n");
+    printf( "MBEDTLS_SHA256_C and/or MBEDTLS_MD_C and/or "
+            "MBEDTLS_AES_C and/or MBEDTLS_CCM_C and/or "
+            "MBEDTLS_PSA_CRYPTO_C and/or MBEDTLS_FS_IO "
+            "not defined and/or MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER "
+            "defined.\n" );
     return( 0 );
 }
 #else
@@ -167,7 +169,7 @@
 
 /* Save a key to a file. In the real world, you may want to export a derived
  * key sometimes, to share it with another party. */
-static psa_status_t save_key( psa_key_handle_t key_handle,
+static psa_status_t save_key( psa_key_id_t key,
                               const char *output_file_name )
 {
     psa_status_t status = PSA_SUCCESS;
@@ -175,7 +177,7 @@
     size_t key_size;
     FILE *key_file = NULL;
 
-    PSA_CHECK( psa_export_key( key_handle,
+    PSA_CHECK( psa_export_key( key,
                                key_data, sizeof( key_data ),
                                &key_size ) );
     SYS_CHECK( ( key_file = fopen( output_file_name, "wb" ) ) != NULL );
@@ -197,7 +199,7 @@
 static psa_status_t generate( const char *key_file_name )
 {
     psa_status_t status = PSA_SUCCESS;
-    psa_key_handle_t key_handle = 0;
+    psa_key_id_t key = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
     psa_set_key_usage_flags( &attributes,
@@ -206,12 +208,12 @@
     psa_set_key_type( &attributes, PSA_KEY_TYPE_DERIVE );
     psa_set_key_bits( &attributes, PSA_BYTES_TO_BITS( KEY_SIZE_BYTES ) );
 
-    PSA_CHECK( psa_generate_key( &attributes, &key_handle ) );
+    PSA_CHECK( psa_generate_key( &attributes, &key ) );
 
-    PSA_CHECK( save_key( key_handle, key_file_name ) );
+    PSA_CHECK( save_key( key, key_file_name ) );
 
 exit:
-    (void) psa_destroy_key( key_handle );
+    (void) psa_destroy_key( key );
     return( status );
 }
 
@@ -223,7 +225,7 @@
 static psa_status_t import_key_from_file( psa_key_usage_t usage,
                                           psa_algorithm_t alg,
                                           const char *key_file_name,
-                                          psa_key_handle_t *master_key_handle )
+                                          psa_key_id_t *master_key )
 {
     psa_status_t status = PSA_SUCCESS;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -232,8 +234,6 @@
     FILE *key_file = NULL;
     unsigned char extra_byte;
 
-    *master_key_handle = 0;
-
     SYS_CHECK( ( key_file = fopen( key_file_name, "rb" ) ) != NULL );
     SYS_CHECK( ( key_size = fread( key_data, 1, sizeof( key_data ),
                                    key_file ) ) != 0 );
@@ -250,8 +250,7 @@
     psa_set_key_usage_flags( &attributes, usage );
     psa_set_key_algorithm( &attributes, alg );
     psa_set_key_type( &attributes, PSA_KEY_TYPE_DERIVE );
-    PSA_CHECK( psa_import_key( &attributes, key_data, key_size,
-                               master_key_handle ) );
+    PSA_CHECK( psa_import_key( &attributes, key_data, key_size, master_key ) );
 exit:
     if( key_file != NULL )
         fclose( key_file );
@@ -259,21 +258,22 @@
     if( status != PSA_SUCCESS )
     {
         /* If the key creation hasn't happened yet or has failed,
-         * *master_key_handle is 0. psa_destroy_key(0) is guaranteed to do
-         * nothing and return PSA_ERROR_INVALID_HANDLE. */
-        (void) psa_destroy_key( *master_key_handle );
-        *master_key_handle = 0;
+         * *master_key is null. psa_destroy_key( 0 ) is
+         * guaranteed to do nothing and return PSA_SUCCESS. */
+        (void) psa_destroy_key( *master_key );
+        *master_key = 0;
     }
     return( status );
 }
 
 /* Derive the intermediate keys, using the list of labels provided on
- * the command line. On input, *key_handle is a handle to the master key.
- * This function closes the master key. On successful output, *key_handle
- * is a handle to the final derived key. */
+ * the command line. On input, *key is the master key identifier.
+ * This function destroys the master key. On successful output, *key
+ * is the identifier of the final derived key.
+ */
 static psa_status_t derive_key_ladder( const char *ladder[],
                                        size_t ladder_depth,
-                                       psa_key_handle_t *key_handle )
+                                       psa_key_id_t *key )
 {
     psa_status_t status = PSA_SUCCESS;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -297,17 +297,17 @@
                        DERIVE_KEY_SALT, DERIVE_KEY_SALT_LENGTH ) );
         PSA_CHECK( psa_key_derivation_input_key(
                        &operation, PSA_KEY_DERIVATION_INPUT_SECRET,
-                       *key_handle ) );
+                       *key ) );
         PSA_CHECK( psa_key_derivation_input_bytes(
                        &operation, PSA_KEY_DERIVATION_INPUT_INFO,
                        (uint8_t*) ladder[i], strlen( ladder[i] ) ) );
         /* When the parent key is not the master key, destroy it,
          * since it is no longer needed. */
-        PSA_CHECK( psa_close_key( *key_handle ) );
-        *key_handle = 0;
+        PSA_CHECK( psa_destroy_key( *key ) );
+        *key = 0;
         /* Derive the next intermediate key from the parent key. */
         PSA_CHECK( psa_key_derivation_output_key( &attributes, &operation,
-                                                  key_handle ) );
+                                                  key ) );
         PSA_CHECK( psa_key_derivation_abort( &operation ) );
     }
 
@@ -315,22 +315,22 @@
     psa_key_derivation_abort( &operation );
     if( status != PSA_SUCCESS )
     {
-        psa_close_key( *key_handle );
-        *key_handle = 0;
+        psa_destroy_key( *key );
+        *key = 0;
     }
     return( status );
 }
 
 /* Derive a wrapping key from the last intermediate key. */
 static psa_status_t derive_wrapping_key( psa_key_usage_t usage,
-                                         psa_key_handle_t derived_key_handle,
-                                         psa_key_handle_t *wrapping_key_handle )
+                                         psa_key_id_t derived_key,
+                                         psa_key_id_t *wrapping_key )
 {
     psa_status_t status = PSA_SUCCESS;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
 
-    *wrapping_key_handle = 0;
+    *wrapping_key = 0;
 
     /* Set up a key derivation operation from the key derived from
      * the master key. */
@@ -340,7 +340,7 @@
                    WRAPPING_KEY_SALT, WRAPPING_KEY_SALT_LENGTH ) );
     PSA_CHECK( psa_key_derivation_input_key(
                    &operation, PSA_KEY_DERIVATION_INPUT_SECRET,
-                   derived_key_handle ) );
+                   derived_key ) );
     PSA_CHECK( psa_key_derivation_input_bytes(
                    &operation, PSA_KEY_DERIVATION_INPUT_INFO,
                    NULL, 0 ) );
@@ -351,7 +351,7 @@
     psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
     psa_set_key_bits( &attributes, WRAPPING_KEY_BITS );
     PSA_CHECK( psa_key_derivation_output_key( &attributes, &operation,
-                                              wrapping_key_handle ) );
+                                              wrapping_key ) );
 
 exit:
     psa_key_derivation_abort( &operation );
@@ -360,7 +360,7 @@
 
 static psa_status_t wrap_data( const char *input_file_name,
                                const char *output_file_name,
-                               psa_key_handle_t wrapping_key_handle )
+                               psa_key_id_t wrapping_key )
 {
     psa_status_t status;
     FILE *input_file = NULL;
@@ -408,7 +408,7 @@
 
     /* Wrap the data. */
     PSA_CHECK( psa_generate_random( header.iv, WRAPPING_IV_SIZE ) );
-    PSA_CHECK( psa_aead_encrypt( wrapping_key_handle, WRAPPING_ALG,
+    PSA_CHECK( psa_aead_encrypt( wrapping_key, WRAPPING_ALG,
                                  header.iv, WRAPPING_IV_SIZE,
                                  (uint8_t *) &header, sizeof( header ),
                                  buffer, input_size,
@@ -437,7 +437,7 @@
 
 static psa_status_t unwrap_data( const char *input_file_name,
                                  const char *output_file_name,
-                                 psa_key_handle_t wrapping_key_handle )
+                                 psa_key_id_t wrapping_key )
 {
     psa_status_t status;
     FILE *input_file = NULL;
@@ -489,7 +489,7 @@
     input_file = NULL;
 
     /* Unwrap the data. */
-    PSA_CHECK( psa_aead_decrypt( wrapping_key_handle, WRAPPING_ALG,
+    PSA_CHECK( psa_aead_decrypt( wrapping_key, WRAPPING_ALG,
                                  header.iv, WRAPPING_IV_SIZE,
                                  (uint8_t *) &header, sizeof( header ),
                                  buffer, ciphertext_size,
@@ -527,8 +527,8 @@
                          const char *output_file_name )
 {
     psa_status_t status = PSA_SUCCESS;
-    psa_key_handle_t derivation_key_handle = 0;
-    psa_key_handle_t wrapping_key_handle = 0;
+    psa_key_id_t derivation_key = 0;
+    psa_key_id_t wrapping_key = 0;
 
     /* Initialize the PSA crypto library. */
     PSA_CHECK( psa_crypto_init( ) );
@@ -541,30 +541,30 @@
     PSA_CHECK( import_key_from_file( PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT,
                                      KDF_ALG,
                                      key_file_name,
-                                     &derivation_key_handle ) );
+                                     &derivation_key ) );
 
     /* Calculate the derived key for this session. */
     PSA_CHECK( derive_key_ladder( ladder, ladder_depth,
-                                  &derivation_key_handle ) );
+                                  &derivation_key ) );
 
     switch( mode )
     {
         case MODE_SAVE:
-            PSA_CHECK( save_key( derivation_key_handle, output_file_name ) );
+            PSA_CHECK( save_key( derivation_key, output_file_name ) );
             break;
         case MODE_UNWRAP:
             PSA_CHECK( derive_wrapping_key( PSA_KEY_USAGE_DECRYPT,
-                                            derivation_key_handle,
-                                            &wrapping_key_handle ) );
+                                            derivation_key,
+                                            &wrapping_key ) );
             PSA_CHECK( unwrap_data( input_file_name, output_file_name,
-                                    wrapping_key_handle ) );
+                                    wrapping_key ) );
             break;
         case MODE_WRAP:
             PSA_CHECK( derive_wrapping_key( PSA_KEY_USAGE_ENCRYPT,
-                                            derivation_key_handle,
-                                            &wrapping_key_handle ) );
+                                            derivation_key,
+                                            &wrapping_key ) );
             PSA_CHECK( wrap_data( input_file_name, output_file_name,
-                                  wrapping_key_handle ) );
+                                  wrapping_key ) );
             break;
         default:
             /* Unreachable but some compilers don't realize it. */
@@ -572,11 +572,11 @@
     }
 
 exit:
-    /* Close any remaining key. Deinitializing the crypto library would do
-     * this anyway, but explicitly closing handles makes the code easier
-     * to reuse. */
-    (void) psa_close_key( derivation_key_handle );
-    (void) psa_close_key( wrapping_key_handle );
+    /* Destroy any remaining key. Deinitializing the crypto library would do
+     * this anyway since they are volatile keys, but explicitly destroying
+     * keys makes the code easier to reuse. */
+    (void) psa_destroy_key( derivation_key );
+    (void) psa_destroy_key( wrapping_key );
     /* Deinitialize the PSA crypto library. */
     mbedtls_psa_crypto_free( );
     return( status );
@@ -603,18 +603,6 @@
     printf( "                    and the same sequence of labels.\n" );
 }
 
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    exit( EXIT_FAILURE );
-}
-#endif
-
 int main( int argc, char *argv[] )
 {
     const char *key_file_name = "master.key";
diff --git a/programs/psa/psa_constant_names_generated.c b/programs/psa/psa_constant_names_generated.c
new file mode 100644
index 0000000..a9568f3
--- /dev/null
+++ b/programs/psa/psa_constant_names_generated.c
@@ -0,0 +1,400 @@
+/* Automatically generated by generate_psa_constant.py. DO NOT EDIT. */
+
+static const char *psa_strerror(psa_status_t status)
+{
+    switch (status) {
+    case PSA_ERROR_ALREADY_EXISTS: return "PSA_ERROR_ALREADY_EXISTS";
+    case PSA_ERROR_BAD_STATE: return "PSA_ERROR_BAD_STATE";
+    case PSA_ERROR_BUFFER_TOO_SMALL: return "PSA_ERROR_BUFFER_TOO_SMALL";
+    case PSA_ERROR_COMMUNICATION_FAILURE: return "PSA_ERROR_COMMUNICATION_FAILURE";
+    case PSA_ERROR_CORRUPTION_DETECTED: return "PSA_ERROR_CORRUPTION_DETECTED";
+    case PSA_ERROR_DOES_NOT_EXIST: return "PSA_ERROR_DOES_NOT_EXIST";
+    case PSA_ERROR_GENERIC_ERROR: return "PSA_ERROR_GENERIC_ERROR";
+    case PSA_ERROR_HARDWARE_FAILURE: return "PSA_ERROR_HARDWARE_FAILURE";
+    case PSA_ERROR_INSUFFICIENT_DATA: return "PSA_ERROR_INSUFFICIENT_DATA";
+    case PSA_ERROR_INSUFFICIENT_ENTROPY: return "PSA_ERROR_INSUFFICIENT_ENTROPY";
+    case PSA_ERROR_INSUFFICIENT_MEMORY: return "PSA_ERROR_INSUFFICIENT_MEMORY";
+    case PSA_ERROR_INSUFFICIENT_STORAGE: return "PSA_ERROR_INSUFFICIENT_STORAGE";
+    case PSA_ERROR_INVALID_ARGUMENT: return "PSA_ERROR_INVALID_ARGUMENT";
+    case PSA_ERROR_INVALID_HANDLE: return "PSA_ERROR_INVALID_HANDLE";
+    case PSA_ERROR_INVALID_PADDING: return "PSA_ERROR_INVALID_PADDING";
+    case PSA_ERROR_INVALID_SIGNATURE: return "PSA_ERROR_INVALID_SIGNATURE";
+    case PSA_ERROR_NOT_PERMITTED: return "PSA_ERROR_NOT_PERMITTED";
+    case PSA_ERROR_NOT_SUPPORTED: return "PSA_ERROR_NOT_SUPPORTED";
+    case PSA_ERROR_STORAGE_FAILURE: return "PSA_ERROR_STORAGE_FAILURE";
+    case PSA_SUCCESS: return "PSA_SUCCESS";
+    default: return NULL;
+    }
+}
+
+static const char *psa_ecc_family_name(psa_ecc_family_t curve)
+{
+    switch (curve) {
+    case PSA_ECC_FAMILY_BRAINPOOL_P_R1: return "PSA_ECC_FAMILY_BRAINPOOL_P_R1";
+    case PSA_ECC_FAMILY_MONTGOMERY: return "PSA_ECC_FAMILY_MONTGOMERY";
+    case PSA_ECC_FAMILY_SECP_K1: return "PSA_ECC_FAMILY_SECP_K1";
+    case PSA_ECC_FAMILY_SECP_R1: return "PSA_ECC_FAMILY_SECP_R1";
+    case PSA_ECC_FAMILY_SECP_R2: return "PSA_ECC_FAMILY_SECP_R2";
+    case PSA_ECC_FAMILY_SECT_K1: return "PSA_ECC_FAMILY_SECT_K1";
+    case PSA_ECC_FAMILY_SECT_R1: return "PSA_ECC_FAMILY_SECT_R1";
+    case PSA_ECC_FAMILY_SECT_R2: return "PSA_ECC_FAMILY_SECT_R2";
+    default: return NULL;
+    }
+}
+
+static const char *psa_dh_family_name(psa_dh_family_t group)
+{
+    switch (group) {
+    case PSA_DH_FAMILY_CUSTOM: return "PSA_DH_FAMILY_CUSTOM";
+    case PSA_DH_FAMILY_RFC7919: return "PSA_DH_FAMILY_RFC7919";
+    default: return NULL;
+    }
+}
+
+static const char *psa_hash_algorithm_name(psa_algorithm_t hash_alg)
+{
+    switch (hash_alg) {
+    case PSA_ALG_ANY_HASH: return "PSA_ALG_ANY_HASH";
+    case PSA_ALG_CATEGORY_HASH: return "PSA_ALG_CATEGORY_HASH";
+    case PSA_ALG_MD2: return "PSA_ALG_MD2";
+    case PSA_ALG_MD4: return "PSA_ALG_MD4";
+    case PSA_ALG_MD5: return "PSA_ALG_MD5";
+    case PSA_ALG_RIPEMD160: return "PSA_ALG_RIPEMD160";
+    case PSA_ALG_SHA3_224: return "PSA_ALG_SHA3_224";
+    case PSA_ALG_SHA3_256: return "PSA_ALG_SHA3_256";
+    case PSA_ALG_SHA3_384: return "PSA_ALG_SHA3_384";
+    case PSA_ALG_SHA3_512: return "PSA_ALG_SHA3_512";
+    case PSA_ALG_SHA_1: return "PSA_ALG_SHA_1";
+    case PSA_ALG_SHA_224: return "PSA_ALG_SHA_224";
+    case PSA_ALG_SHA_256: return "PSA_ALG_SHA_256";
+    case PSA_ALG_SHA_384: return "PSA_ALG_SHA_384";
+    case PSA_ALG_SHA_512: return "PSA_ALG_SHA_512";
+    case PSA_ALG_SHA_512_224: return "PSA_ALG_SHA_512_224";
+    case PSA_ALG_SHA_512_256: return "PSA_ALG_SHA_512_256";
+    default: return NULL;
+    }
+}
+
+static const char *psa_ka_algorithm_name(psa_algorithm_t ka_alg)
+{
+    switch (ka_alg) {
+    case PSA_ALG_CATEGORY_KEY_AGREEMENT: return "PSA_ALG_CATEGORY_KEY_AGREEMENT";
+    case PSA_ALG_ECDH: return "PSA_ALG_ECDH";
+    case PSA_ALG_FFDH: return "PSA_ALG_FFDH";
+    default: return NULL;
+    }
+}
+
+static int psa_snprint_key_type(char *buffer, size_t buffer_size,
+                                psa_key_type_t type)
+{
+    size_t required_size = 0;
+    switch (type) {
+    case PSA_KEY_TYPE_AES: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_AES", 16); break;
+    case PSA_KEY_TYPE_ARC4: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_ARC4", 17); break;
+    case PSA_KEY_TYPE_CAMELLIA: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_CAMELLIA", 21); break;
+    case PSA_KEY_TYPE_CATEGORY_FLAG_PAIR: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_CATEGORY_FLAG_PAIR", 31); break;
+    case PSA_KEY_TYPE_CATEGORY_KEY_PAIR: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_CATEGORY_KEY_PAIR", 30); break;
+    case PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY", 32); break;
+    case PSA_KEY_TYPE_CATEGORY_RAW: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_CATEGORY_RAW", 25); break;
+    case PSA_KEY_TYPE_CATEGORY_SYMMETRIC: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_CATEGORY_SYMMETRIC", 31); break;
+    case PSA_KEY_TYPE_CHACHA20: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_CHACHA20", 21); break;
+    case PSA_KEY_TYPE_DERIVE: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_DERIVE", 19); break;
+    case PSA_KEY_TYPE_DES: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_DES", 16); break;
+    case PSA_KEY_TYPE_DH_KEY_PAIR_BASE: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_DH_KEY_PAIR_BASE", 29); break;
+    case PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE", 31); break;
+    case PSA_KEY_TYPE_DSA_KEY_PAIR: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_DSA_KEY_PAIR", 25); break;
+    case PSA_KEY_TYPE_DSA_PUBLIC_KEY: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_DSA_PUBLIC_KEY", 27); break;
+    case PSA_KEY_TYPE_ECC_KEY_PAIR_BASE: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_ECC_KEY_PAIR_BASE", 30); break;
+    case PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE", 32); break;
+    case PSA_KEY_TYPE_HMAC: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_HMAC", 17); break;
+    case PSA_KEY_TYPE_NONE: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_NONE", 17); break;
+    case PSA_KEY_TYPE_RAW_DATA: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_RAW_DATA", 21); break;
+    case PSA_KEY_TYPE_RSA_KEY_PAIR: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_RSA_KEY_PAIR", 25); break;
+    case PSA_KEY_TYPE_RSA_PUBLIC_KEY: append(&buffer, buffer_size, &required_size, "PSA_KEY_TYPE_RSA_PUBLIC_KEY", 27); break;
+    default:
+        if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
+            append_with_curve(&buffer, buffer_size, &required_size,
+                              "PSA_KEY_TYPE_ECC_KEY_PAIR", 25,
+                              PSA_KEY_TYPE_ECC_GET_FAMILY(type));
+        } else if (PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type)) {
+            append_with_curve(&buffer, buffer_size, &required_size,
+                              "PSA_KEY_TYPE_ECC_PUBLIC_KEY", 27,
+                              PSA_KEY_TYPE_ECC_GET_FAMILY(type));
+        } else if (PSA_KEY_TYPE_IS_DH_KEY_PAIR(type)) {
+            append_with_group(&buffer, buffer_size, &required_size,
+                              "PSA_KEY_TYPE_DH_KEY_PAIR", 24,
+                              PSA_KEY_TYPE_DH_GET_FAMILY(type));
+        } else if (PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type)) {
+            append_with_group(&buffer, buffer_size, &required_size,
+                              "PSA_KEY_TYPE_DH_PUBLIC_KEY", 26,
+                              PSA_KEY_TYPE_DH_GET_FAMILY(type));
+        } else {
+            return snprintf(buffer, buffer_size,
+                            "0x%04x", (unsigned) type);
+        }
+        break;
+    }
+    buffer[0] = 0;
+    return (int) required_size;
+}
+
+#define NO_LENGTH_MODIFIER 0xfffffffflu
+static int psa_snprint_algorithm(char *buffer, size_t buffer_size,
+                                 psa_algorithm_t alg)
+{
+    size_t required_size = 0;
+    psa_algorithm_t core_alg = alg;
+    unsigned long length_modifier = NO_LENGTH_MODIFIER;
+    if (PSA_ALG_IS_MAC(alg)) {
+        core_alg = PSA_ALG_TRUNCATED_MAC(alg, 0);
+        if (core_alg != alg) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_TRUNCATED_MAC(", 22);
+            length_modifier = PSA_MAC_TRUNCATED_LENGTH(alg);
+        }
+    } else if (PSA_ALG_IS_AEAD(alg)) {
+        core_alg = PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg);
+        if (core_alg == 0) {
+            /* For unknown AEAD algorithms, there is no "default tag length". */
+            core_alg = alg;
+        } else if (core_alg != alg) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_AEAD_WITH_TAG_LENGTH(", 29);
+            length_modifier = PSA_AEAD_TAG_LENGTH(alg);
+        }
+    } else if (PSA_ALG_IS_KEY_AGREEMENT(alg) &&
+               !PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {
+        core_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg);
+        append(&buffer, buffer_size, &required_size,
+               "PSA_ALG_KEY_AGREEMENT(", 22);
+        append_with_alg(&buffer, buffer_size, &required_size,
+                        psa_ka_algorithm_name,
+                        PSA_ALG_KEY_AGREEMENT_GET_BASE(alg));
+        append(&buffer, buffer_size, &required_size, ", ", 2);
+    }
+    switch (core_alg) {
+    case PSA_ALG_ANY_HASH: append(&buffer, buffer_size, &required_size, "PSA_ALG_ANY_HASH", 16); break;
+    case PSA_ALG_ARC4: append(&buffer, buffer_size, &required_size, "PSA_ALG_ARC4", 12); break;
+    case PSA_ALG_CATEGORY_AEAD: append(&buffer, buffer_size, &required_size, "PSA_ALG_CATEGORY_AEAD", 21); break;
+    case PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION: append(&buffer, buffer_size, &required_size, "PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION", 38); break;
+    case PSA_ALG_CATEGORY_CIPHER: append(&buffer, buffer_size, &required_size, "PSA_ALG_CATEGORY_CIPHER", 23); break;
+    case PSA_ALG_CATEGORY_HASH: append(&buffer, buffer_size, &required_size, "PSA_ALG_CATEGORY_HASH", 21); break;
+    case PSA_ALG_CATEGORY_KEY_AGREEMENT: append(&buffer, buffer_size, &required_size, "PSA_ALG_CATEGORY_KEY_AGREEMENT", 30); break;
+    case PSA_ALG_CATEGORY_KEY_DERIVATION: append(&buffer, buffer_size, &required_size, "PSA_ALG_CATEGORY_KEY_DERIVATION", 31); break;
+    case PSA_ALG_CATEGORY_MAC: append(&buffer, buffer_size, &required_size, "PSA_ALG_CATEGORY_MAC", 20); break;
+    case PSA_ALG_CATEGORY_SIGN: append(&buffer, buffer_size, &required_size, "PSA_ALG_CATEGORY_SIGN", 21); break;
+    case PSA_ALG_CBC_MAC: append(&buffer, buffer_size, &required_size, "PSA_ALG_CBC_MAC", 15); break;
+    case PSA_ALG_CBC_NO_PADDING: append(&buffer, buffer_size, &required_size, "PSA_ALG_CBC_NO_PADDING", 22); break;
+    case PSA_ALG_CBC_PKCS7: append(&buffer, buffer_size, &required_size, "PSA_ALG_CBC_PKCS7", 17); break;
+    case PSA_ALG_CCM: append(&buffer, buffer_size, &required_size, "PSA_ALG_CCM", 11); break;
+    case PSA_ALG_CFB: append(&buffer, buffer_size, &required_size, "PSA_ALG_CFB", 11); break;
+    case PSA_ALG_CHACHA20: append(&buffer, buffer_size, &required_size, "PSA_ALG_CHACHA20", 16); break;
+    case PSA_ALG_CHACHA20_POLY1305: append(&buffer, buffer_size, &required_size, "PSA_ALG_CHACHA20_POLY1305", 25); break;
+    case PSA_ALG_CIPHER_MAC_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_CIPHER_MAC_BASE", 23); break;
+    case PSA_ALG_CMAC: append(&buffer, buffer_size, &required_size, "PSA_ALG_CMAC", 12); break;
+    case PSA_ALG_CTR: append(&buffer, buffer_size, &required_size, "PSA_ALG_CTR", 11); break;
+    case PSA_ALG_DETERMINISTIC_DSA_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_DETERMINISTIC_DSA_BASE", 30); break;
+    case PSA_ALG_DETERMINISTIC_ECDSA_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_DETERMINISTIC_ECDSA_BASE", 32); break;
+    case PSA_ALG_DSA_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_DSA_BASE", 16); break;
+    case PSA_ALG_ECB_NO_PADDING: append(&buffer, buffer_size, &required_size, "PSA_ALG_ECB_NO_PADDING", 22); break;
+    case PSA_ALG_ECDH: append(&buffer, buffer_size, &required_size, "PSA_ALG_ECDH", 12); break;
+    case PSA_ALG_ECDSA_ANY: append(&buffer, buffer_size, &required_size, "PSA_ALG_ECDSA_ANY", 17); break;
+    case PSA_ALG_FFDH: append(&buffer, buffer_size, &required_size, "PSA_ALG_FFDH", 12); break;
+    case PSA_ALG_GCM: append(&buffer, buffer_size, &required_size, "PSA_ALG_GCM", 11); break;
+    case PSA_ALG_HKDF_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_HKDF_BASE", 17); break;
+    case PSA_ALG_HMAC_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_HMAC_BASE", 17); break;
+    case PSA_ALG_MD2: append(&buffer, buffer_size, &required_size, "PSA_ALG_MD2", 11); break;
+    case PSA_ALG_MD4: append(&buffer, buffer_size, &required_size, "PSA_ALG_MD4", 11); break;
+    case PSA_ALG_MD5: append(&buffer, buffer_size, &required_size, "PSA_ALG_MD5", 11); break;
+    case PSA_ALG_OFB: append(&buffer, buffer_size, &required_size, "PSA_ALG_OFB", 11); break;
+    case PSA_ALG_RIPEMD160: append(&buffer, buffer_size, &required_size, "PSA_ALG_RIPEMD160", 17); break;
+    case PSA_ALG_RSA_OAEP_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_RSA_OAEP_BASE", 21); break;
+    case PSA_ALG_RSA_PKCS1V15_CRYPT: append(&buffer, buffer_size, &required_size, "PSA_ALG_RSA_PKCS1V15_CRYPT", 26); break;
+    case PSA_ALG_RSA_PKCS1V15_SIGN_RAW: append(&buffer, buffer_size, &required_size, "PSA_ALG_RSA_PKCS1V15_SIGN_RAW", 29); break;
+    case PSA_ALG_RSA_PSS_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_RSA_PSS_BASE", 20); break;
+    case PSA_ALG_SHA3_224: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA3_224", 16); break;
+    case PSA_ALG_SHA3_256: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA3_256", 16); break;
+    case PSA_ALG_SHA3_384: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA3_384", 16); break;
+    case PSA_ALG_SHA3_512: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA3_512", 16); break;
+    case PSA_ALG_SHA_1: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA_1", 13); break;
+    case PSA_ALG_SHA_224: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA_224", 15); break;
+    case PSA_ALG_SHA_256: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA_256", 15); break;
+    case PSA_ALG_SHA_384: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA_384", 15); break;
+    case PSA_ALG_SHA_512: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA_512", 15); break;
+    case PSA_ALG_SHA_512_224: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA_512_224", 19); break;
+    case PSA_ALG_SHA_512_256: append(&buffer, buffer_size, &required_size, "PSA_ALG_SHA_512_256", 19); break;
+    case PSA_ALG_TLS12_PRF_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_TLS12_PRF_BASE", 22); break;
+    case PSA_ALG_TLS12_PSK_TO_MS_BASE: append(&buffer, buffer_size, &required_size, "PSA_ALG_TLS12_PSK_TO_MS_BASE", 28); break;
+    case PSA_ALG_XTS: append(&buffer, buffer_size, &required_size, "PSA_ALG_XTS", 11); break;
+    default:
+        if (PSA_ALG_IS_DETERMINISTIC_DSA(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_DETERMINISTIC_DSA(", 25 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
+        } else if (PSA_ALG_IS_DETERMINISTIC_ECDSA(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_DETERMINISTIC_ECDSA(", 27 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
+        } else if (PSA_ALG_IS_RANDOMIZED_DSA(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_DSA(", 11 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
+        } else if (PSA_ALG_IS_RANDOMIZED_ECDSA(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_ECDSA(", 13 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
+        } else if (PSA_ALG_IS_HKDF(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_HKDF(", 12 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
+        } else if (PSA_ALG_IS_HMAC(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_HMAC(", 12 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
+        } else if (PSA_ALG_IS_RSA_OAEP(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_RSA_OAEP(", 16 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
+        } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_RSA_PKCS1V15_SIGN(", 25 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
+        } else if (PSA_ALG_IS_RSA_PSS(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_RSA_PSS(", 15 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
+        } else if (PSA_ALG_IS_TLS12_PRF(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_TLS12_PRF(", 17 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
+        } else if (PSA_ALG_IS_TLS12_PSK_TO_MS(core_alg)) {
+            append(&buffer, buffer_size, &required_size,
+                   "PSA_ALG_TLS12_PSK_TO_MS(", 23 + 1);
+            append_with_alg(&buffer, buffer_size, &required_size,
+                            psa_hash_algorithm_name,
+                            PSA_ALG_GET_HASH(core_alg));
+            append(&buffer, buffer_size, &required_size, ")", 1);
+        } else {
+            append_integer(&buffer, buffer_size, &required_size,
+                           "0x%08lx", (unsigned long) core_alg);
+        }
+        break;
+    }
+    if (core_alg != alg) {
+        if (length_modifier != NO_LENGTH_MODIFIER) {
+            append(&buffer, buffer_size, &required_size, ", ", 2);
+            append_integer(&buffer, buffer_size, &required_size,
+                           "%lu", length_modifier);
+        }
+        append(&buffer, buffer_size, &required_size, ")", 1);
+    }
+    buffer[0] = 0;
+    return (int) required_size;
+}
+
+static int psa_snprint_key_usage(char *buffer, size_t buffer_size,
+                                 psa_key_usage_t usage)
+{
+    size_t required_size = 0;
+    if (usage == 0) {
+        if (buffer_size > 1) {
+            buffer[0] = '0';
+            buffer[1] = 0;
+        } else if (buffer_size == 1) {
+            buffer[0] = 0;
+        }
+        return 1;
+    }
+    if (usage & PSA_KEY_USAGE_COPY) {
+        if (required_size != 0) {
+            append(&buffer, buffer_size, &required_size, " | ", 3);
+        }
+        append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_COPY", 18);
+        usage ^= PSA_KEY_USAGE_COPY;
+    }
+    if (usage & PSA_KEY_USAGE_DECRYPT) {
+        if (required_size != 0) {
+            append(&buffer, buffer_size, &required_size, " | ", 3);
+        }
+        append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_DECRYPT", 21);
+        usage ^= PSA_KEY_USAGE_DECRYPT;
+    }
+    if (usage & PSA_KEY_USAGE_DERIVE) {
+        if (required_size != 0) {
+            append(&buffer, buffer_size, &required_size, " | ", 3);
+        }
+        append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_DERIVE", 20);
+        usage ^= PSA_KEY_USAGE_DERIVE;
+    }
+    if (usage & PSA_KEY_USAGE_ENCRYPT) {
+        if (required_size != 0) {
+            append(&buffer, buffer_size, &required_size, " | ", 3);
+        }
+        append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_ENCRYPT", 21);
+        usage ^= PSA_KEY_USAGE_ENCRYPT;
+    }
+    if (usage & PSA_KEY_USAGE_EXPORT) {
+        if (required_size != 0) {
+            append(&buffer, buffer_size, &required_size, " | ", 3);
+        }
+        append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_EXPORT", 20);
+        usage ^= PSA_KEY_USAGE_EXPORT;
+    }
+    if (usage & PSA_KEY_USAGE_SIGN_HASH) {
+        if (required_size != 0) {
+            append(&buffer, buffer_size, &required_size, " | ", 3);
+        }
+        append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_SIGN_HASH", 23);
+        usage ^= PSA_KEY_USAGE_SIGN_HASH;
+    }
+    if (usage & PSA_KEY_USAGE_VERIFY_HASH) {
+        if (required_size != 0) {
+            append(&buffer, buffer_size, &required_size, " | ", 3);
+        }
+        append(&buffer, buffer_size, &required_size, "PSA_KEY_USAGE_VERIFY_HASH", 25);
+        usage ^= PSA_KEY_USAGE_VERIFY_HASH;
+    }
+    if (usage != 0) {
+        if (required_size != 0) {
+            append(&buffer, buffer_size, &required_size, " | ", 3);
+        }
+        append_integer(&buffer, buffer_size, &required_size,
+                       "0x%08lx", (unsigned long) usage);
+    } else {
+        buffer[0] = 0;
+    }
+    return (int) required_size;
+}
+
+/* End of automatically generated file. */
diff --git a/programs/random/CMakeLists.txt b/programs/random/CMakeLists.txt
index 95acb7e..8df8365 100644
--- a/programs/random/CMakeLists.txt
+++ b/programs/random/CMakeLists.txt
@@ -6,7 +6,7 @@
 
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
-    target_link_libraries(${exe} mbedcrypto)
+    target_link_libraries(${exe} ${mbedcrypto_target})
 endforeach()
 
 install(TARGETS ${executables}
diff --git a/programs/ssl/CMakeLists.txt b/programs/ssl/CMakeLists.txt
index 28fbfc5..149aa30 100644
--- a/programs/ssl/CMakeLists.txt
+++ b/programs/ssl/CMakeLists.txt
@@ -2,7 +2,7 @@
 find_package(Threads)
 
 set(libs
-    mbedtls
+    ${mbedtls_target}
 )
 
 if(USE_PKCS11_HELPER_LIBRARY)
@@ -32,8 +32,8 @@
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
 endforeach()
 
-target_sources(ssl_client2 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
-target_sources(ssl_server2 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
+set_property(TARGET ssl_client2 APPEND PROPERTY SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
+set_property(TARGET ssl_server2 APPEND PROPERTY SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
 
 if(THREADS_FOUND)
     add_executable(ssl_pthread_server ssl_pthread_server.c $<TARGET_OBJECTS:mbedtls_test>)
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index a26dd51..fc69061 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -42,12 +42,14 @@
 
 #if !defined(MBEDTLS_ENTROPY_C) || \
     !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
-    !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_CTR_DRBG_C)
+    !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
+    defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
 int main( void )
 {
-    mbedtls_printf("MBEDTLS_ENTROPY_C and/or "
+    mbedtls_printf( "MBEDTLS_ENTROPY_C and/or "
            "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or "
-           "MBEDTLS_NET_C and/or MBEDTLS_CTR_DRBG_C and/or not defined.\n");
+           "MBEDTLS_NET_C and/or MBEDTLS_CTR_DRBG_C and/or not defined "
+           " and/or MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined.\n" );
     mbedtls_exit( 0 );
 }
 #else
@@ -149,6 +151,10 @@
 #define DFL_NSS_KEYLOG          0
 #define DFL_NSS_KEYLOG_FILE     NULL
 #define DFL_SKIP_CLOSE_NOTIFY   0
+#define DFL_QUERY_CONFIG_MODE   0
+#define DFL_USE_SRTP            0
+#define DFL_SRTP_FORCE_PROFILE  0
+#define DFL_SRTP_MKI            ""
 
 #define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: "
 #define GET_REQUEST_END "\r\n\r\n"
@@ -253,10 +259,26 @@
     "                             This cannot be used with eap_tls=1\n"
 #define USAGE_NSS_KEYLOG_FILE                               \
     "    nss_keylog_file=%%s\n"
-#else
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+#define USAGE_SRTP \
+    "    use_srtp=%%d         default: 0 (disabled)\n" \
+    "                          This cannot be used with eap_tls=1 or "\
+    "                          nss_keylog=1\n"             \
+    "    srtp_force_profile=%%d  default: 0 (all enabled)\n"   \
+    "                        available profiles:\n"       \
+    "                        1 - SRTP_AES128_CM_HMAC_SHA1_80\n"  \
+    "                        2 - SRTP_AES128_CM_HMAC_SHA1_32\n"  \
+    "                        3 - SRTP_NULL_HMAC_SHA1_80\n"       \
+    "                        4 - SRTP_NULL_HMAC_SHA1_32\n"       \
+    "    mki=%%s              default: \"\" (in hex, without 0x)\n"
+#else /* MBEDTLS_SSL_DTLS_SRTP */
+#define USAGE_SRTP ""
+#endif
+#else /* MBEDTLS_SSL_EXPORT_KEYS */
 #define USAGE_EAP_TLS ""
 #define USAGE_NSS_KEYLOG ""
 #define USAGE_NSS_KEYLOG_FILE ""
+#define USAGE_SRTP ""
 #endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
@@ -406,6 +428,7 @@
     "\n"                                                    \
     USAGE_DTLS                                              \
     USAGE_CID                                               \
+    USAGE_SRTP                                              \
     "\n"
 #define USAGE2 \
     "    auth_mode=%%s        default: (library default: none)\n" \
@@ -539,6 +562,10 @@
                                  * after renegotiation                      */
     int reproducible;           /* make communication reproducible          */
     int skip_close_notify;      /* skip sending the close_notify alert      */
+    int query_config_mode;      /* whether to read config                   */
+    int use_srtp;               /* Support SRTP                             */
+    int force_srtp_profile;     /* SRTP protection profile to use or all    */
+    const char *mki;            /* The dtls mki value to use                */
 } opt;
 
 int query_config( const char *config );
@@ -653,7 +680,49 @@
                               sizeof( nss_keylog_line ) );
     return( ret );
 }
-#endif
+
+#if defined( MBEDTLS_SSL_DTLS_SRTP )
+/* Supported SRTP mode needs a maximum of :
+ * - 16 bytes for key (AES-128)
+ * - 14 bytes SALT
+ * One for sender, one for receiver context
+ */
+#define MBEDTLS_TLS_SRTP_MAX_KEY_MATERIAL_LENGTH    60
+typedef struct dtls_srtp_keys
+{
+    unsigned char master_secret[48];
+    unsigned char randbytes[64];
+    mbedtls_tls_prf_types tls_prf_type;
+} dtls_srtp_keys;
+
+static int dtls_srtp_key_derivation( void *p_expkey,
+                                     const unsigned char *ms,
+                                     const unsigned char *kb,
+                                     size_t maclen,
+                                     size_t keylen,
+                                     size_t ivlen,
+                                     const unsigned char client_random[32],
+                                     const unsigned char server_random[32],
+                                     mbedtls_tls_prf_types tls_prf_type )
+{
+    dtls_srtp_keys *keys = (dtls_srtp_keys *)p_expkey;
+
+    ( ( void ) kb );
+    memcpy( keys->master_secret, ms, sizeof( keys->master_secret ) );
+    memcpy( keys->randbytes, client_random, 32 );
+    memcpy( keys->randbytes + 32, server_random, 32 );
+    keys->tls_prf_type = tls_prf_type;
+
+    if( opt.debug_level > 2 )
+    {
+        mbedtls_printf( "exported maclen is %u\n", (unsigned) maclen );
+        mbedtls_printf( "exported keylen is %u\n", (unsigned) keylen );
+        mbedtls_printf( "exported ivlen is %u\n", (unsigned) ivlen );
+    }
+    return( 0 );
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 static void my_debug( void *ctx, int level,
                       const char *file, int line,
@@ -1102,6 +1171,7 @@
 int main( int argc, char *argv[] )
 {
     int ret = 0, len, tail_len, i, written, frags, retry_left;
+    int query_config_ret = 0;
     mbedtls_net_context server_fd;
     io_ctx_t io_ctx;
 
@@ -1131,11 +1201,15 @@
     mbedtls_ecp_group_id curve_list[CURVE_LIST_SIZE];
     const mbedtls_ecp_curve_info *curve_cur;
 #endif
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    unsigned char mki[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH];
+    size_t mki_len=0;
+#endif
 
     const char *pers = "ssl_client2";
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_key_handle_t slot = 0;
+    psa_key_id_t slot = 0;
     psa_algorithm_t alg = 0;
     psa_key_attributes_t key_attributes;
     psa_status_t status;
@@ -1160,7 +1234,7 @@
     mbedtls_x509_crt clicert;
     mbedtls_pk_context pkey;
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_key_handle_t key_slot = 0; /* invalid key slot */
+    psa_key_id_t key_slot = 0; /* invalid key slot */
 #endif
 #endif
     char *p, *q;
@@ -1174,7 +1248,20 @@
     unsigned char eap_tls_iv[8];
     const char* eap_tls_label = "client EAP encryption";
     eap_tls_keys eap_tls_keying;
-#endif
+#if defined( MBEDTLS_SSL_DTLS_SRTP )
+    /*! master keys and master salt for SRTP generated during handshake */
+    unsigned char dtls_srtp_key_material[MBEDTLS_TLS_SRTP_MAX_KEY_MATERIAL_LENGTH];
+    const char* dtls_srtp_label = "EXTRACTOR-dtls_srtp";
+    dtls_srtp_keys dtls_srtp_keying;
+    const mbedtls_ssl_srtp_profile default_profiles[] = {
+        MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80,
+        MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32,
+        MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80,
+        MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32,
+        MBEDTLS_TLS_SRTP_UNSET
+    };
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
@@ -1300,6 +1387,10 @@
     opt.nss_keylog          = DFL_NSS_KEYLOG;
     opt.nss_keylog_file     = DFL_NSS_KEYLOG_FILE;
     opt.skip_close_notify   = DFL_SKIP_CLOSE_NOTIFY;
+    opt.query_config_mode   = DFL_QUERY_CONFIG_MODE;
+    opt.use_srtp            = DFL_USE_SRTP;
+    opt.force_srtp_profile  = DFL_SRTP_FORCE_PROFILE;
+    opt.mki                 = DFL_SRTP_MKI;
 
     for( i = 1; i < argc; i++ )
     {
@@ -1686,7 +1777,9 @@
         }
         else if( strcmp( p, "query_config" ) == 0 )
         {
-            mbedtls_exit( query_config( q ) );
+            opt.query_config_mode = 1;
+            query_config_ret = query_config( q );
+            goto exit;
         }
         else if( strcmp( p, "serialize") == 0 )
         {
@@ -1724,6 +1817,18 @@
             if( opt.skip_close_notify < 0 || opt.skip_close_notify > 1 )
                 goto usage;
         }
+        else if( strcmp( p, "use_srtp" ) == 0 )
+        {
+            opt.use_srtp = atoi ( q );
+        }
+        else if( strcmp( p, "srtp_force_profile" ) == 0 )
+        {
+            opt.force_srtp_profile = atoi( q );
+        }
+        else if( strcmp( p, "mki" ) == 0 )
+        {
+            opt.mki = q;
+        }
         else
             goto usage;
     }
@@ -1831,7 +1936,6 @@
             opt.arc4 = MBEDTLS_SSL_ARC4_ENABLED;
         }
 
-
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
         if( opt.psk_opaque != 0 )
         {
@@ -2234,6 +2338,36 @@
     }
 #endif
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    if( opt.use_srtp == 1 )
+    {
+        if( opt.force_srtp_profile != 0 )
+        {
+            const mbedtls_ssl_srtp_profile forced_profile[] =
+                                        { opt.force_srtp_profile, MBEDTLS_TLS_SRTP_UNSET };
+            ret = mbedtls_ssl_conf_dtls_srtp_protection_profiles ( &conf, forced_profile );
+        }
+        else
+        {
+            ret = mbedtls_ssl_conf_dtls_srtp_protection_profiles ( &conf, default_profiles );
+        }
+
+        if( ret != 0 )
+        {
+            mbedtls_printf( " failed\n  ! "
+                            "mbedtls_ssl_conf_dtls_srtp_protection_profiles returned %d\n\n",
+                            ret );
+            goto exit;
+        }
+
+    }
+    else if( opt.force_srtp_profile != 0 )
+    {
+        mbedtls_printf( " failed\n  ! must enable use_srtp to force srtp profile\n\n" );
+        goto exit;
+    }
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
     if( opt.trunc_hmac != DFL_TRUNC_HMAC )
         mbedtls_ssl_conf_truncated_hmac( &conf, opt.trunc_hmac );
@@ -2261,7 +2395,14 @@
                                              nss_keylog_export,
                                              NULL );
     }
-#endif
+#if defined( MBEDTLS_SSL_DTLS_SRTP )
+    else if( opt.use_srtp != 0 )
+    {
+        mbedtls_ssl_conf_export_keys_ext_cb( &conf, dtls_srtp_key_derivation,
+                                             &dtls_srtp_keying );
+    }
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
     if( opt.recsplit != DFL_RECSPLIT )
@@ -2470,6 +2611,26 @@
         mbedtls_ecp_set_max_ops( opt.ec_max_ops );
 #endif
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    if( opt.use_srtp != 0 && strlen( opt.mki ) != 0 )
+    {
+        if( mbedtls_test_unhexify( mki, sizeof( mki ),
+                                   opt.mki,&mki_len ) != 0 )
+        {
+            mbedtls_printf( "mki value not valid hex\n" );
+            goto exit;
+        }
+
+        mbedtls_ssl_conf_srtp_mki_value_supported( &conf, MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED );
+        if( ( ret = mbedtls_ssl_dtls_srtp_set_mki_value( &ssl, mki,
+                                                         (uint16_t) strlen( opt.mki ) / 2 ) ) != 0 )
+        {
+            mbedtls_printf( " failed\n  ! mbedtls_ssl_dtls_srtp_set_mki_value returned %d\n\n", ret );
+            goto exit;
+        }
+    }
+#endif
+
     mbedtls_printf( " ok\n" );
 
     /*
@@ -2591,7 +2752,74 @@
         }
         mbedtls_printf("\n");
     }
-#endif
+
+#if defined( MBEDTLS_SSL_DTLS_SRTP )
+    else if( opt.use_srtp != 0  )
+    {
+        size_t j = 0;
+        mbedtls_dtls_srtp_info dtls_srtp_negotiation_result;
+        mbedtls_ssl_get_dtls_srtp_negotiation_result( &ssl, &dtls_srtp_negotiation_result );
+
+        if( dtls_srtp_negotiation_result.chosen_dtls_srtp_profile
+                                == MBEDTLS_TLS_SRTP_UNSET )
+        {
+            mbedtls_printf( "    Unable to negotiate "
+                            "the use of DTLS-SRTP\n" );
+        }
+        else
+        {
+            if( ( ret = mbedtls_ssl_tls_prf( dtls_srtp_keying.tls_prf_type,
+                                             dtls_srtp_keying.master_secret,
+                                             sizeof( dtls_srtp_keying.master_secret ),
+                                             dtls_srtp_label,
+                                             dtls_srtp_keying.randbytes,
+                                             sizeof( dtls_srtp_keying.randbytes ),
+                                             dtls_srtp_key_material,
+                                             sizeof( dtls_srtp_key_material ) ) )
+                                             != 0 )
+            {
+                mbedtls_printf( " failed\n  ! mbedtls_ssl_tls_prf returned -0x%x\n\n",
+                                (unsigned int) -ret );
+                goto exit;
+            }
+
+            mbedtls_printf( "    DTLS-SRTP key material is:" );
+            for( j = 0; j < sizeof( dtls_srtp_key_material ); j++ )
+            {
+                if( j % 8 == 0 )
+                    mbedtls_printf( "\n    " );
+                mbedtls_printf( "%02x ", dtls_srtp_key_material[j] );
+            }
+            mbedtls_printf( "\n" );
+
+            /* produce a less readable output used to perform automatic checks
+             * - compare client and server output
+             * - interop test with openssl which client produces this kind of output
+             */
+            mbedtls_printf( "    Keying material: " );
+            for( j = 0; j < sizeof( dtls_srtp_key_material ); j++ )
+            {
+                mbedtls_printf( "%02X", dtls_srtp_key_material[j] );
+            }
+            mbedtls_printf( "\n" );
+
+            if ( dtls_srtp_negotiation_result.mki_len > 0 )
+            {
+                mbedtls_printf( "    DTLS-SRTP mki value: " );
+                for( j = 0; j < dtls_srtp_negotiation_result.mki_len; j++ )
+                {
+                    mbedtls_printf( "%02X", dtls_srtp_negotiation_result.mki_value[j] );
+                }
+            }
+            else
+            {
+                mbedtls_printf( "    DTLS-SRTP no mki value negotiated" );
+            }
+            mbedtls_printf( "\n" );
+        }
+    }
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
     if( opt.reconnect != 0 )
     {
         mbedtls_printf("  . Saving session for reuse..." );
@@ -2685,7 +2913,7 @@
         {
             mbedtls_printf( " failed\n  ! mbedtls_ssl_set_cid returned %d\n\n",
                             ret );
-            return( ret );
+            goto exit;
         }
     }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
@@ -3348,7 +3576,8 @@
          * immediately because of bad cmd line params,
          * for example). */
         status = psa_destroy_key( slot );
-        if( status != PSA_SUCCESS )
+        if( ( status != PSA_SUCCESS ) &&
+            ( opt.query_config_mode == DFL_QUERY_CONFIG_MODE ) )
         {
             mbedtls_printf( "Failed to destroy key slot %u - error was %d",
                             (unsigned) slot, (int) status );
@@ -3367,15 +3596,21 @@
 #endif
 
 #if defined(_WIN32)
-    mbedtls_printf( "  + Press Enter to exit this program.\n" );
-    fflush( stdout ); getchar();
+    if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE )
+    {
+        mbedtls_printf( "  + Press Enter to exit this program.\n" );
+        fflush( stdout ); getchar();
+    }
 #endif
 
     // Shell can not handle large exit numbers -> 1 for errors
     if( ret < 0 )
         ret = 1;
 
-    mbedtls_exit( ret );
+    if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE )
+        mbedtls_exit( ret );
+    else
+        mbedtls_exit( query_config_ret );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
           MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
diff --git a/programs/ssl/ssl_context_info.c b/programs/ssl/ssl_context_info.c
index df8819a..a204d9e 100644
--- a/programs/ssl/ssl_context_info.c
+++ b/programs/ssl/ssl_context_info.c
@@ -26,10 +26,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C)
+#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_ERROR_C) || \
+    !defined(MBEDTLS_SSL_TLS_C)
 int main( void )
 {
-    printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C not defined.\n");
+    printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_ERROR_C and/or "
+           "MBEDTLS_SSL_TLS_C not defined.\n");
     return( 0 );
 }
 #else
@@ -377,13 +379,13 @@
     int valid_balance = 0;  /* balance between valid and invalid characters */
     size_t len = 0;
     char pad = 0;
-    char c = 0;
+    int c = 0;
 
     while( EOF != c )
     {
         char c_valid = 0;
 
-        c = (char) fgetc( b64_file );
+        c = fgetc( b64_file );
 
         if( pad > 0 )
         {
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index c445ddb..ceeb224 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -42,12 +42,14 @@
 
 #if !defined(MBEDTLS_ENTROPY_C) || \
     !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_SRV_C) || \
-    !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_CTR_DRBG_C)
+    !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
+    defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
 int main( void )
 {
-    mbedtls_printf("MBEDTLS_ENTROPY_C and/or "
+    mbedtls_printf( "MBEDTLS_ENTROPY_C and/or "
            "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or "
-           "MBEDTLS_NET_C and/or MBEDTLS_CTR_DRBG_C and/or not defined.\n");
+           "MBEDTLS_NET_C and/or MBEDTLS_CTR_DRBG_C and/or not defined "
+           " and/or MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined.\n" );
     mbedtls_exit( 0 );
 }
 #else
@@ -182,6 +184,10 @@
 #define DFL_REPRODUCIBLE        0
 #define DFL_NSS_KEYLOG          0
 #define DFL_NSS_KEYLOG_FILE     NULL
+#define DFL_QUERY_CONFIG_MODE   0
+#define DFL_USE_SRTP            0
+#define DFL_SRTP_FORCE_PROFILE  0
+#define DFL_SRTP_SUPPORT_MKI    0
 
 #define LONG_RESPONSE "<p>01-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
     "02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n"  \
@@ -324,10 +330,24 @@
     "                             This cannot be used with eap_tls=1\n"
 #define USAGE_NSS_KEYLOG_FILE                               \
     "    nss_keylog_file=%%s\n"
-#else
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+#define USAGE_SRTP \
+    "    use_srtp=%%d         default: 0 (disabled)\n" \
+    "    srtp_force_profile=%%d  default: 0 (all enabled)\n"   \
+    "                        available profiles:\n"       \
+    "                        1 - SRTP_AES128_CM_HMAC_SHA1_80\n"  \
+    "                        2 - SRTP_AES128_CM_HMAC_SHA1_32\n"  \
+    "                        3 - SRTP_NULL_HMAC_SHA1_80\n"       \
+    "                        4 - SRTP_NULL_HMAC_SHA1_32\n"       \
+    "    support_mki=%%d     default: 0 (not supported)\n"
+#else /* MBEDTLS_SSL_DTLS_SRTP */
+#define USAGE_SRTP ""
+#endif
+#else /* MBEDTLS_SSL_EXPORT_KEYS */
 #define USAGE_EAP_TLS ""
 #define USAGE_NSS_KEYLOG ""
 #define USAGE_NSS_KEYLOG_FILE ""
+#define USAGE_SRTP ""
 #endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_CACHE_C)
@@ -489,6 +509,7 @@
     "    read_timeout=%%d     default: 0 ms (no timeout)\n"    \
     "\n"                                                    \
     USAGE_DTLS                                              \
+    USAGE_SRTP                                              \
     USAGE_COOKIES                                           \
     USAGE_ANTI_REPLAY                                       \
     USAGE_BADMAC_LIMIT                                      \
@@ -643,6 +664,10 @@
     const char *cid_val_renego; /* the CID to use for incoming messages
                                  * after renegotiation                      */
     int reproducible;           /* make communication reproducible          */
+    int query_config_mode;      /* whether to read config                   */
+    int use_srtp;               /* Support SRTP                             */
+    int force_srtp_profile;     /* SRTP protection profile to use or all    */
+    int support_mki;            /* The dtls mki mki support                 */
 } opt;
 
 int query_config( const char *config );
@@ -758,7 +783,49 @@
     return( ret );
 }
 
-#endif
+#if defined( MBEDTLS_SSL_DTLS_SRTP )
+/* Supported SRTP mode needs a maximum of :
+ * - 16 bytes for key (AES-128)
+ * - 14 bytes SALT
+ * One for sender, one for receiver context
+ */
+#define MBEDTLS_TLS_SRTP_MAX_KEY_MATERIAL_LENGTH    60
+typedef struct dtls_srtp_keys
+{
+    unsigned char master_secret[48];
+    unsigned char randbytes[64];
+    mbedtls_tls_prf_types tls_prf_type;
+} dtls_srtp_keys;
+
+static int dtls_srtp_key_derivation( void *p_expkey,
+                                     const unsigned char *ms,
+                                     const unsigned char *kb,
+                                     size_t maclen,
+                                     size_t keylen,
+                                     size_t ivlen,
+                                     const unsigned char client_random[32],
+                                     const unsigned char server_random[32],
+                                     mbedtls_tls_prf_types tls_prf_type )
+{
+    dtls_srtp_keys *keys = (dtls_srtp_keys *)p_expkey;
+
+    ( ( void ) kb );
+    memcpy( keys->master_secret, ms, sizeof( keys->master_secret ) );
+    memcpy( keys->randbytes, client_random, 32 );
+    memcpy( keys->randbytes + 32, server_random, 32 );
+    keys->tls_prf_type = tls_prf_type;
+
+    if( opt.debug_level > 2 )
+    {
+        mbedtls_printf( "exported maclen is %u\n", (unsigned) maclen );
+        mbedtls_printf( "exported keylen is %u\n", (unsigned) keylen );
+        mbedtls_printf( "exported ivlen is %u\n", (unsigned) ivlen );
+    }
+    return( 0 );
+}
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 static void my_debug( void *ctx, int level,
                       const char *file, int line,
@@ -1220,7 +1287,7 @@
     size_t key_len;
     unsigned char key[MBEDTLS_PSK_MAX_LEN];
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_key_handle_t slot;
+    psa_key_id_t slot;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
     psk_entry *next;
 };
@@ -1236,7 +1303,7 @@
     {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
         psa_status_t status;
-        psa_key_handle_t const slot = head->slot;
+        psa_key_id_t const slot = head->slot;
 
         if( slot != 0 )
         {
@@ -1646,7 +1713,7 @@
 }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-static psa_status_t psa_setup_psk_key_slot( psa_key_handle_t *slot,
+static psa_status_t psa_setup_psk_key_slot( psa_key_id_t *slot,
                                             psa_algorithm_t alg,
                                             unsigned char *psk,
                                             size_t psk_len )
@@ -1723,13 +1790,14 @@
 int main( int argc, char *argv[] )
 {
     int ret = 0, len, written, frags, exchanges_left;
+    int query_config_ret = 0;
     int version_suites[4][2];
     io_ctx_t io_ctx;
     unsigned char* buf = 0;
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_algorithm_t alg = 0;
-    psa_key_handle_t psk_slot = 0;
+    psa_key_id_t psk_slot = 0;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
     unsigned char psk[MBEDTLS_PSK_MAX_LEN];
     size_t psk_len = 0;
@@ -1789,7 +1857,6 @@
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
     unsigned char alloc_buf[MEMORY_HEAP_SIZE];
 #endif
-
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     unsigned char cid[MBEDTLS_SSL_CID_IN_LEN_MAX];
     unsigned char cid_renego[MBEDTLS_SSL_CID_IN_LEN_MAX];
@@ -1812,7 +1879,20 @@
     unsigned char eap_tls_iv[8];
     const char* eap_tls_label = "client EAP encryption";
     eap_tls_keys eap_tls_keying;
-#endif
+#if defined( MBEDTLS_SSL_DTLS_SRTP )
+    /*! master keys and master salt for SRTP generated during handshake */
+     unsigned char dtls_srtp_key_material[MBEDTLS_TLS_SRTP_MAX_KEY_MATERIAL_LENGTH];
+     const char* dtls_srtp_label = "EXTRACTOR-dtls_srtp";
+     dtls_srtp_keys dtls_srtp_keying;
+     const mbedtls_ssl_srtp_profile default_profiles[] = {
+         MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80,
+         MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32,
+         MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80,
+         MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32,
+         MBEDTLS_TLS_SRTP_UNSET
+     };
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
@@ -1972,6 +2052,10 @@
     opt.reproducible        = DFL_REPRODUCIBLE;
     opt.nss_keylog          = DFL_NSS_KEYLOG;
     opt.nss_keylog_file     = DFL_NSS_KEYLOG_FILE;
+    opt.query_config_mode   = DFL_QUERY_CONFIG_MODE;
+    opt.use_srtp            = DFL_USE_SRTP;
+    opt.force_srtp_profile  = DFL_SRTP_FORCE_PROFILE;
+    opt.support_mki         = DFL_SRTP_SUPPORT_MKI;
 
     for( i = 1; i < argc; i++ )
     {
@@ -2386,7 +2470,9 @@
         }
         else if( strcmp( p, "query_config" ) == 0 )
         {
-            mbedtls_exit( query_config( q ) );
+            opt.query_config_mode = 1;
+            query_config_ret = query_config( q );
+            goto exit;
         }
         else if( strcmp( p, "serialize") == 0 )
         {
@@ -2418,6 +2504,18 @@
         {
             opt.nss_keylog_file = q;
         }
+        else if( strcmp( p, "use_srtp" ) == 0 )
+        {
+            opt.use_srtp = atoi ( q );
+        }
+        else if( strcmp( p, "srtp_force_profile" ) == 0 )
+        {
+            opt.force_srtp_profile = atoi( q );
+        }
+        else if( strcmp( p, "support_mki" ) == 0 )
+        {
+            opt.support_mki = atoi( q );
+        }
         else
             goto usage;
     }
@@ -3022,7 +3120,7 @@
     {
         mbedtls_printf( " failed\n  ! mbedtls_ssl_conf_max_frag_len returned %d\n\n", ret );
         goto exit;
-    };
+    }
 #endif
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
@@ -3052,6 +3150,38 @@
     }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    if( opt.use_srtp == 1 )
+    {
+        if( opt.force_srtp_profile != 0 )
+        {
+            const mbedtls_ssl_srtp_profile forced_profile[] = { opt.force_srtp_profile, MBEDTLS_TLS_SRTP_UNSET };
+            ret = mbedtls_ssl_conf_dtls_srtp_protection_profiles( &conf, forced_profile );
+        }
+        else
+        {
+            ret = mbedtls_ssl_conf_dtls_srtp_protection_profiles( &conf, default_profiles );
+        }
+
+        if( ret != 0 )
+        {
+            mbedtls_printf( " failed\n  ! mbedtls_ssl_conf_dtls_srtp_protection_profiles returned %d\n\n", ret );
+            goto exit;
+        }
+
+        mbedtls_ssl_conf_srtp_mki_value_supported( &conf,
+                                                   opt.support_mki ?
+                                                   MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED :
+                                                   MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED );
+
+    }
+    else if( opt.force_srtp_profile != 0 )
+    {
+        mbedtls_printf( " failed\n  ! must enable use_srtp to force srtp profile\n\n" );
+        goto exit;
+    }
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
 #if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
     if( opt.trunc_hmac != DFL_TRUNC_HMAC )
         mbedtls_ssl_conf_truncated_hmac( &conf, opt.trunc_hmac );
@@ -3079,7 +3209,14 @@
                                              nss_keylog_export,
                                              NULL );
     }
-#endif
+#if defined( MBEDTLS_SSL_DTLS_SRTP )
+    else if( opt.use_srtp != 0 )
+    {
+        mbedtls_ssl_conf_export_keys_ext_cb( &conf, dtls_srtp_key_derivation,
+                                             &dtls_srtp_keying );
+    }
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_ALPN)
     if( opt.alpn_string != NULL )
@@ -3725,7 +3862,75 @@
         }
         mbedtls_printf("\n");
     }
-#endif
+
+#if defined( MBEDTLS_SSL_DTLS_SRTP )
+    else if( opt.use_srtp != 0  )
+    {
+        size_t j = 0;
+        mbedtls_dtls_srtp_info dtls_srtp_negotiation_result;
+        mbedtls_ssl_get_dtls_srtp_negotiation_result( &ssl, &dtls_srtp_negotiation_result );
+
+        if( dtls_srtp_negotiation_result.chosen_dtls_srtp_profile
+                                == MBEDTLS_TLS_SRTP_UNSET )
+        {
+            mbedtls_printf( "    Unable to negotiate "
+                            "the use of DTLS-SRTP\n" );
+        }
+        else
+        {
+            if( ( ret = mbedtls_ssl_tls_prf( dtls_srtp_keying.tls_prf_type,
+                                             dtls_srtp_keying.master_secret,
+                                             sizeof( dtls_srtp_keying.master_secret ),
+                                             dtls_srtp_label,
+                                             dtls_srtp_keying.randbytes,
+                                             sizeof( dtls_srtp_keying.randbytes ),
+                                             dtls_srtp_key_material,
+                                             sizeof( dtls_srtp_key_material ) ) )
+                                             != 0 )
+            {
+                mbedtls_printf( " failed\n  ! mbedtls_ssl_tls_prf returned -0x%x\n\n",
+                                (unsigned int) -ret );
+                goto exit;
+            }
+
+            mbedtls_printf( "    DTLS-SRTP key material is:" );
+            for( j = 0; j < sizeof( dtls_srtp_key_material ); j++ )
+            {
+                if( j % 8 == 0 )
+                    mbedtls_printf( "\n    " );
+                mbedtls_printf( "%02x ", dtls_srtp_key_material[j] );
+            }
+            mbedtls_printf( "\n" );
+
+            /* produce a less readable output used to perform automatic checks
+             * - compare client and server output
+             * - interop test with openssl which client produces this kind of output
+             */
+            mbedtls_printf( "    Keying material: " );
+            for( j = 0; j < sizeof( dtls_srtp_key_material ); j++ )
+            {
+                mbedtls_printf( "%02X", dtls_srtp_key_material[j] );
+            }
+            mbedtls_printf( "\n" );
+
+            if ( dtls_srtp_negotiation_result.mki_len > 0 )
+            {
+                mbedtls_printf( "    DTLS-SRTP mki value: " );
+                for( j = 0; j < dtls_srtp_negotiation_result.mki_len; j++ )
+                {
+                    mbedtls_printf( "%02X", dtls_srtp_negotiation_result.mki_value[j] );
+                }
+            }
+            else
+            {
+                mbedtls_printf( "    DTLS-SRTP no mki value negotiated" );
+            }
+            mbedtls_printf( "\n" );
+
+        }
+    }
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     ret = report_cid_usage( &ssl, "initial handshake" );
@@ -4261,8 +4466,11 @@
     }
 #endif
 
-    mbedtls_printf( "  . Cleaning up..." );
-    fflush( stdout );
+    if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE )
+    {
+        mbedtls_printf( "  . Cleaning up..." );
+        fflush( stdout );
+    }
 
     mbedtls_net_free( &client_fd );
     mbedtls_net_free( &listen_fd );
@@ -4292,7 +4500,8 @@
     sni_free( sni_info );
 #endif
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-    if( ( ret = psk_free( psk_info ) ) != 0 )
+    ret = psk_free( psk_info );
+    if( ( ret != 0 ) && ( opt.query_config_mode == DFL_QUERY_CONFIG_MODE ) )
         mbedtls_printf( "Failed to list of opaque PSKs - error was %d\n", ret );
 #endif
 #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO)
@@ -4308,7 +4517,8 @@
          * immediately because of bad cmd line params,
          * for example). */
         status = psa_destroy_key( psk_slot );
-        if( status != PSA_SUCCESS )
+        if( ( status != PSA_SUCCESS ) &&
+            ( opt.query_config_mode == DFL_QUERY_CONFIG_MODE ) )
         {
             mbedtls_printf( "Failed to destroy key slot %u - error was %d",
                             (unsigned) psk_slot, (int) status );
@@ -4347,18 +4557,24 @@
     mbedtls_memory_buffer_alloc_free();
 #endif
 
-    mbedtls_printf( " done.\n" );
+    if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE )
+    {
+        mbedtls_printf( " done.\n" );
 
 #if defined(_WIN32)
-    mbedtls_printf( "  + Press Enter to exit this program.\n" );
-    fflush( stdout ); getchar();
+        mbedtls_printf( "  + Press Enter to exit this program.\n" );
+        fflush( stdout ); getchar();
 #endif
+    }
 
     // Shell can not handle large exit numbers -> 1 for errors
     if( ret < 0 )
         ret = 1;
 
-    mbedtls_exit( ret );
+    if( opt.query_config_mode == DFL_QUERY_CONFIG_MODE )
+        mbedtls_exit( ret );
+    else
+        mbedtls_exit( query_config_ret );
 }
 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
           MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt
index 0df0bec..49b44e7 100644
--- a/programs/test/CMakeLists.txt
+++ b/programs/test/CMakeLists.txt
@@ -1,5 +1,5 @@
 set(libs
-    mbedtls
+    ${mbedtls_target}
 )
 
 if(USE_PKCS11_HELPER_LIBRARY)
@@ -33,11 +33,12 @@
     if (${exe_index} GREATER -1)
         target_link_libraries(${exe} ${libs})
     else()
-        target_link_libraries(${exe} mbedcrypto)
+        target_link_libraries(${exe} ${mbedcrypto_target})
     endif()
 endforeach()
 
-target_sources(query_compile_time_config PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/query_config.c)
+set_property(TARGET query_compile_time_config APPEND PROPERTY SOURCES
+             ${CMAKE_CURRENT_SOURCE_DIR}/query_config.c)
 
 install(TARGETS ${executables_libs} ${executables_mbedcrypto}
         DESTINATION "bin"
diff --git a/programs/test/cmake_subproject/CMakeLists.txt b/programs/test/cmake_subproject/CMakeLists.txt
index 3e32c5f..a9fcfde 100644
--- a/programs/test/cmake_subproject/CMakeLists.txt
+++ b/programs/test/cmake_subproject/CMakeLists.txt
@@ -1,5 +1,8 @@
 cmake_minimum_required(VERSION 2.6)
 
+# Test the target renaming support by adding a prefix to the targets built
+set(MBEDTLS_TARGET_PREFIX subproject_test_)
+
 # We use the parent Mbed TLS directory as the MBEDTLS_DIR for this test. Other
 # projects that use Mbed TLS as a subproject are likely to add by their own
 # relative paths.
@@ -8,11 +11,12 @@
 # Add Mbed TLS as a subdirectory.
 add_subdirectory(${MBEDTLS_DIR} build)
 
-# Link against all the Mbed TLS libraries.
+# Link against all the Mbed TLS libraries. Verifies that the targets have been
+# created using the specified prefix
 set(libs
-    mbedcrypto
-    mbedx509
-    mbedtls
+    subproject_test_mbedcrypto
+    subproject_test_mbedx509
+    subproject_test_mbedtls
 )
 
 add_executable(cmake_subproject cmake_subproject.c)
diff --git a/programs/test/cpp_dummy_build.cpp b/programs/test/cpp_dummy_build.cpp
index 09c5273..c69cd2b 100644
--- a/programs/test/cpp_dummy_build.cpp
+++ b/programs/test/cpp_dummy_build.cpp
@@ -109,6 +109,12 @@
 #include "mbedtls/memory_buffer_alloc.h"
 #endif
 
+#include "psa/crypto.h"
+#include "psa/crypto_se_driver.h"
+#include "psa/crypto_entropy_driver.h"
+#include "psa/crypto_accel_driver.h"
+#include "../library/psa_crypto_its.h"
+
 int main()
 {
     mbedtls_platform_context *ctx = NULL;
diff --git a/programs/test/query_config.c b/programs/test/query_config.c
index 8873734..1345b11 100644
--- a/programs/test/query_config.c
+++ b/programs/test/query_config.c
@@ -1480,6 +1480,14 @@
     }
 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
 
+#if defined(MBEDTLS_SSL_DTLS_SRTP)
+    if( strcmp( "MBEDTLS_SSL_DTLS_SRTP", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_DTLS_SRTP );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_DTLS_SRTP */
+
 #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
     if( strcmp( "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", config ) == 0 )
     {
@@ -1592,6 +1600,14 @@
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
+#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
+    if( strcmp( "MBEDTLS_PSA_CRYPTO_CONFIG", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_CRYPTO_CONFIG );
+        return( 0 );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_CONFIG */
+
 #if defined(MBEDTLS_VERSION_FEATURES)
     if( strcmp( "MBEDTLS_VERSION_FEATURES", config ) == 0 )
     {
diff --git a/programs/util/CMakeLists.txt b/programs/util/CMakeLists.txt
index cb14a3e..2a11212 100644
--- a/programs/util/CMakeLists.txt
+++ b/programs/util/CMakeLists.txt
@@ -1,5 +1,5 @@
 set(libs
-    mbedcrypto
+    ${mbedcrypto_target}
 )
 
 set(executables
diff --git a/programs/x509/CMakeLists.txt b/programs/x509/CMakeLists.txt
index f7b5fe1..29cbeb8 100644
--- a/programs/x509/CMakeLists.txt
+++ b/programs/x509/CMakeLists.txt
@@ -1,5 +1,5 @@
 set(libs
-    mbedx509
+    ${mbedx509_target}
 )
 
 if(USE_PKCS11_HELPER_LIBRARY)
@@ -23,7 +23,7 @@
     target_link_libraries(${exe} ${libs})
 endforeach()
 
-target_link_libraries(cert_app mbedtls)
+target_link_libraries(cert_app ${mbedtls_target})
 
 install(TARGETS ${executables}
         DESTINATION "bin"
diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c
index ade67e2..e8241a3 100644
--- a/programs/x509/cert_req.c
+++ b/programs/x509/cert_req.c
@@ -100,9 +100,8 @@
     "                          Add NsCertType even if it is empty\n"    \
     "    md=%%s               default: SHA256\n"       \
     "                          possible values:\n"     \
-    "                          MD2, MD4, MD5, SHA1\n"  \
-    "                          SHA224, SHA256\n"       \
-    "                          SHA384, SHA512\n"       \
+    "                          MD2, MD4, MD5, RIPEMD160, SHA1,\n" \
+    "                          SHA224, SHA256, SHA384, SHA512\n" \
     "\n"
 
 
@@ -217,58 +216,14 @@
         }
         else if( strcmp( p, "md" ) == 0 )
         {
-            if( strcmp( q, "SHA256" ) == 0 )
+            const mbedtls_md_info_t *md_info =
+                mbedtls_md_info_from_string( q );
+            if( md_info == NULL )
             {
-                opt.md_alg = MBEDTLS_MD_SHA256;
-            }
-            else if( strcmp( q, "SHA224" ) == 0 )
-            {
-                opt.md_alg = MBEDTLS_MD_SHA224;
-            }
-            else
-#if defined(MBEDTLS_MD5_C)
-            if( strcmp( q, "MD5" ) == 0 )
-            {
-                opt.md_alg = MBEDTLS_MD_MD5;
-            }
-            else
-#endif /* MBEDTLS_MD5_C */
-#if defined(MBEDTLS_MD4_C)
-            if( strcmp( q, "MD4" ) == 0 )
-            {
-                opt.md_alg = MBEDTLS_MD_MD4;
-            }
-            else
-#endif /* MBEDTLS_MD5_C */
-#if defined(MBEDTLS_MD2_C)
-            if( strcmp( q, "MD2" ) == 0 )
-            {
-                opt.md_alg = MBEDTLS_MD_MD2;
-            }
-            else
-#endif /* MBEDTLS_MD2_C */
-#if defined(MBEDTLS_SHA1_C)
-            if( strcmp( q, "SHA1" ) == 0 )
-            {
-                opt.md_alg = MBEDTLS_MD_SHA1;
-            }
-            else
-#endif /* MBEDTLS_SHA1_C */
-#if defined(MBEDTLS_SHA512_C)
-            if( strcmp( q, "SHA384" ) == 0 )
-            {
-                opt.md_alg = MBEDTLS_MD_SHA384;
-            }
-            else
-            if( strcmp( q, "SHA512" ) == 0 )
-            {
-                opt.md_alg = MBEDTLS_MD_SHA512;
-            }
-            else
-#endif /* MBEDTLS_SHA512_C */
-            {
+                mbedtls_printf( "Invalid argument for option %s\n", p );
                 goto usage;
             }
+            opt.md_alg = mbedtls_md_get_type( md_info );
         }
         else if( strcmp( p, "key_usage" ) == 0 )
         {
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index 1eeb861..18174d8 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -118,8 +118,9 @@
     "    is_ca=%%d                default: 0 (disabled)\n"  \
     "    max_pathlen=%%d          default: -1 (none)\n"     \
     "    md=%%s                   default: SHA256\n"        \
-    "                            Supported values:\n"       \
-    "                            MD2, MD4, MD5, SHA1, SHA256, SHA512\n"\
+    "                            Supported values (if enabled):\n"      \
+    "                            MD2, MD4, MD5, RIPEMD160, SHA1,\n" \
+    "                            SHA224, SHA256, SHA384, SHA512\n" \
     "    version=%%d              default: 3\n"            \
     "                            Possible values: 1, 2, 3\n"\
     "    subject_identifier=%%s   default: 1\n"             \
@@ -353,27 +354,14 @@
         }
         else if( strcmp( p, "md" ) == 0 )
         {
-            if( strcmp( q, "SHA1" ) == 0 )
-                opt.md = MBEDTLS_MD_SHA1;
-            else if( strcmp( q, "SHA224" ) == 0 )
-                opt.md = MBEDTLS_MD_SHA224;
-            else if( strcmp( q, "SHA256" ) == 0 )
-                opt.md = MBEDTLS_MD_SHA256;
-            else if( strcmp( q, "SHA384" ) == 0 )
-                opt.md = MBEDTLS_MD_SHA384;
-            else if( strcmp( q, "SHA512" ) == 0 )
-                opt.md = MBEDTLS_MD_SHA512;
-            else if( strcmp( q, "MD2" ) == 0 )
-                opt.md = MBEDTLS_MD_MD2;
-            else if( strcmp( q, "MD4" ) == 0 )
-                opt.md = MBEDTLS_MD_MD4;
-            else if( strcmp( q, "MD5" ) == 0 )
-                opt.md = MBEDTLS_MD_MD5;
-            else
+            const mbedtls_md_info_t *md_info =
+                mbedtls_md_info_from_string( q );
+            if( md_info == NULL )
             {
                 mbedtls_printf( "Invalid argument for option %s\n", p );
                 goto usage;
             }
+            opt.md = mbedtls_md_get_type( md_info );
         }
         else if( strcmp( p, "version" ) == 0 )
         {
diff --git a/scripts/config.py b/scripts/config.py
index 017bba0..ae0614a 100755
--- a/scripts/config.py
+++ b/scripts/config.py
@@ -184,6 +184,8 @@
     'MBEDTLS_NO_UDBL_DIVISION', # influences anything that uses bignum
     'MBEDTLS_PKCS11_C', # build dependency (libpkcs11-helper)
     'MBEDTLS_PLATFORM_NO_STD_FUNCTIONS', # removes a feature
+    'MBEDTLS_PSA_CRYPTO_CONFIG', # toggles old/new style PSA config
+    'MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER', # incompatible with USE_PSA_CRYPTO
     'MBEDTLS_PSA_CRYPTO_SPM', # platform dependency (PSA SPM)
     'MBEDTLS_PSA_INJECT_ENTROPY', # build dependency (hook functions)
     'MBEDTLS_REMOVE_3DES_CIPHERSUITES', # removes a feature
diff --git a/scripts/data_files/error.fmt b/scripts/data_files/error.fmt
index fd72f8b..9e479bb 100644
--- a/scripts/data_files/error.fmt
+++ b/scripts/data_files/error.fmt
@@ -19,20 +19,20 @@
 
 #include "common.h"
 
-#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
-#include <string.h>
-#endif
+#include "mbedtls/error.h"
+
+#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
+
+#if defined(MBEDTLS_ERROR_C)
 
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
 #define mbedtls_snprintf snprintf
-#define mbedtls_time_t   time_t
 #endif
 
-#if defined(MBEDTLS_ERROR_C)
-
 #include <stdio.h>
+#include <string.h>
 
 HEADER_INCLUDED
 
@@ -149,8 +149,6 @@
 
 #else /* MBEDTLS_ERROR_C */
 
-#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
-
 /*
  * Provide an non-function in case MBEDTLS_ERROR_C is not defined
  */
@@ -162,6 +160,6 @@
         buf[0] = '\0';
 }
 
-#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */
-
 #endif /* MBEDTLS_ERROR_C */
+
+#endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */
diff --git a/scripts/generate_psa_constants.py b/scripts/generate_psa_constants.py
index 95dc4db..401c2fc 100755
--- a/scripts/generate_psa_constants.py
+++ b/scripts/generate_psa_constants.py
@@ -411,7 +411,7 @@
     temp_file_name = output_file_name + '.tmp'
     with open(temp_file_name, 'w') as output_file:
         collector.write_file(output_file)
-    os.rename(temp_file_name, output_file_name)
+    os.replace(temp_file_name, output_file_name)
 
 if __name__ == '__main__':
     if not os.path.isdir('programs') and os.path.isdir('../programs'):
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index cc68663..f8ce925 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,5 +1,5 @@
 set(libs
-    mbedtls
+    ${mbedtls_target}
 )
 
 # Set the project root directory if it's not already defined, as may happen if
@@ -43,7 +43,7 @@
     add_custom_command(
         OUTPUT test_suite_${data_name}.c
         COMMAND ${MBEDTLS_PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py -f ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function -d ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${data_name}.data -t ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function -p ${CMAKE_CURRENT_SOURCE_DIR}/suites/host_test.function -s ${CMAKE_CURRENT_SOURCE_DIR}/suites --helpers-file ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function -o .
-        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py mbedtls ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/host_test.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${data_name}.data
+        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py ${mbedtls_target} ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/host_test.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${data_name}.data
     )
 
     add_executable(test_suite_${data_name} test_suite_${data_name}.c $<TARGET_OBJECTS:mbedtls_test>)
@@ -166,6 +166,7 @@
         link_to_source(seedfile)
     endif()
     link_to_source(compat.sh)
+    link_to_source(context-info.sh)
     link_to_source(data_files)
     link_to_source(scripts)
     link_to_source(ssl-opt.sh)
diff --git a/tests/compat.sh b/tests/compat.sh
index 68b9f74..6e0a8f9 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -90,12 +90,12 @@
 print_usage() {
     echo "Usage: $0"
     printf "  -h|--help\tPrint this help.\n"
-    printf "  -f|--filter\tOnly matching ciphersuites are tested (Default: '$FILTER')\n"
-    printf "  -e|--exclude\tMatching ciphersuites are excluded (Default: '$EXCLUDE')\n"
-    printf "  -m|--modes\tWhich modes to perform (Default: '$MODES')\n"
-    printf "  -t|--types\tWhich key exchange type to perform (Default: '$TYPES')\n"
-    printf "  -V|--verify\tWhich verification modes to perform (Default: '$VERIFIES')\n"
-    printf "  -p|--peers\tWhich peers to use (Default: '$PEERS')\n"
+    printf "  -f|--filter\tOnly matching ciphersuites are tested (Default: '%s')\n" "$FILTER"
+    printf "  -e|--exclude\tMatching ciphersuites are excluded (Default: '%s')\n" "$EXCLUDE"
+    printf "  -m|--modes\tWhich modes to perform (Default: '%s')\n" "$MODES"
+    printf "  -t|--types\tWhich key exchange type to perform (Default: '%s')\n" "$TYPES"
+    printf "  -V|--verify\tWhich verification modes to perform (Default: '%s')\n" "$VERIFIES"
+    printf "  -p|--peers\tWhich peers to use (Default: '%s')\n" "$PEERS"
     printf "            \tAlso available: GnuTLS (needs v3.2.15 or higher)\n"
     printf "  -M|--memcheck\tCheck memory leaks and errors.\n"
     printf "  -v|--verbose\tSet verbose output.\n"
@@ -1107,7 +1107,7 @@
     VERIF=$(echo $VERIFY | tr '[:upper:]' '[:lower:]')
     TITLE="`echo $1 | head -c1`->`echo $SERVER_NAME | head -c1`"
     TITLE="$TITLE $MODE,$VERIF $2"
-    printf "$TITLE "
+    printf "%s " "$TITLE"
     LEN=$(( 72 - `echo "$TITLE" | wc -c` ))
     for i in `seq 1 $LEN`; do printf '.'; done; printf ' '
 
diff --git a/tests/context-info.sh b/tests/context-info.sh
index 150584b..3465298 100755
--- a/tests/context-info.sh
+++ b/tests/context-info.sh
@@ -430,13 +430,19 @@
          -u "Too many bad symbols detected. File check aborted" \
          -n "Deserializing"
 
+run_test "Decoder continues past 0xff character" \
+         "def_b64_ff.bin" \
+         -n "No valid base64" \
+         -u "ciphersuite.* TLS-"
+
 
 # End of tests
 
+echo
 if [ $T_FAILED -eq 0 ]; then
-    printf "\nPASSED ( $T_COUNT tests )\n"
+    echo "PASSED ( $T_COUNT tests )"
 else
-    printf "\nFAILED ( $T_FAILED / $T_COUNT tests )\n"
+    echo "FAILED ( $T_FAILED / $T_COUNT tests )"
 fi
 
 exit $T_FAILED
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 88f265c..bf2f538 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -13,8 +13,10 @@
 ## Tools
 OPENSSL ?= openssl
 FAKETIME ?= faketime
-MBEDTLS_CERT_WRITE ?= $(PWD)/../../programs/x509/cert_write
-MBEDTLS_CERT_REQ ?= $(PWD)/../../programs/x509/cert_req
+
+TOP_DIR = ../..
+MBEDTLS_CERT_WRITE ?= $(TOP_DIR)/programs/x509/cert_write
+MBEDTLS_CERT_REQ ?= $(TOP_DIR)/programs/x509/cert_req
 
 
 ## Build the generated test data. Note that since the final outputs
diff --git a/tests/data_files/base64/def_b64_ff.bin b/tests/data_files/base64/def_b64_ff.bin
new file mode 100644
index 0000000..66aa827
--- /dev/null
+++ b/tests/data_files/base64/def_b64_ff.bin
@@ -0,0 +1,5 @@
+// Ensure that the b64 parser continues after encountering a 0xFF
+// character.  Note that this byte is invalid UTF-8, making this
+// entire file invalid UTF-8.  Use care when editing.
+// -> ÿ <-
+AhUAAH8AAA4AAABtAAAAAF6HQx3MqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACG2QbHbUj8eGpdx5KVIebiwk0jvRj9/3m6BOSzpA7qBXeEunhqr3D11NE7ciGjeHMAAACAAAAAAAAAAAAAAAAAAV6HQx248L77RH0Z973tSYNQ8zBsz861CZG5/T09TJz3XodDHe/iJ+cgXb5An3zTdnTBtw3EWAb68T+gCE33GN8AAAAAAAAAAAAAAAEAAAAAAAAAAwAAAQAAAAAAAgAAAA==
diff --git a/tests/data_files/cert_md2.csr b/tests/data_files/cert_md2.csr
new file mode 100644
index 0000000..a8c39bd
--- /dev/null
+++ b/tests/data_files/cert_md2.csr
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICgTCCAWkCAQAwPDELMAkGA1UEBhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRow
+GAYDVQQDDBFQb2xhclNTTCBDZXJ0IE1EMjCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAMh0xMy5+bV56UXZFGCwfbuT8msenzOtDY+KPFZl5dxE2cxmhQfV
++CewSjXQY54Kbhu32vB+q+4MEJOGSRg086gq0lf1LtQvdymEYU2CUI+nlUhw9W5N
+stUTw9Ia7eZD6kIU63TqwO0f1FdOqfOo7dLgwTBxMDIw1dP2CNBWT0aO8l/5PWeR
+iDAuQrLfffvlDHf/7DHAeI+/wn/KrWwh1o3Zi2qOb+Cb+BBWzLOOExXmNARmx+75
+Ng5qlfYJmgZn9GVx+MqksSXg/jyLNQRnuuBPdoX8f/w2a7XpzS0DYk6zPQDPr3ag
+aVaDatKo1OdQcea1NgV3BW17yOTE/UzVIV8CAwEAAaAAMA0GCSqGSIb3DQEBAgUA
+A4IBAQBPUqodRcH2ZUa8A3fQX/nxrIwWiLmQ9BaOI6G7vzEWVE1sxmkrHP+pXgi9
+1eFceN9xUBKEd+LmUPmHpObZ4nwRSprFj3DeIXpn9aSBr+jGY8RaaC9cMkaSq5Mb
+q65THEJ1xemIfZvbhjvNi/ycXXu/v1Gpj62dpIFGbm+o4AXQF2ocYGEM+X1u2eVn
+mnuuvPAHTllGjB0daTSYoQtMy3luPUEj0Yct3iVR1pUeTrHchOs9p5ACDZcf6D3x
+sm9atH2ZIaXo1c9SqHzdk/uLt/CwxQrn1WU1inwOkzjim2Yq9vWgpQypfGZdScXV
+oHOmuGG901WMMemzZXjoLi+8ZpVL
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/data_files/cert_md4.csr b/tests/data_files/cert_md4.csr
new file mode 100644
index 0000000..d8a3dbf
--- /dev/null
+++ b/tests/data_files/cert_md4.csr
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICgTCCAWkCAQAwPDELMAkGA1UEBhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRow
+GAYDVQQDDBFQb2xhclNTTCBDZXJ0IE1ENDCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAMh0xMy5+bV56UXZFGCwfbuT8msenzOtDY+KPFZl5dxE2cxmhQfV
++CewSjXQY54Kbhu32vB+q+4MEJOGSRg086gq0lf1LtQvdymEYU2CUI+nlUhw9W5N
+stUTw9Ia7eZD6kIU63TqwO0f1FdOqfOo7dLgwTBxMDIw1dP2CNBWT0aO8l/5PWeR
+iDAuQrLfffvlDHf/7DHAeI+/wn/KrWwh1o3Zi2qOb+Cb+BBWzLOOExXmNARmx+75
+Ng5qlfYJmgZn9GVx+MqksSXg/jyLNQRnuuBPdoX8f/w2a7XpzS0DYk6zPQDPr3ag
+aVaDatKo1OdQcea1NgV3BW17yOTE/UzVIV8CAwEAAaAAMA0GCSqGSIb3DQEBAwUA
+A4IBAQAztRb+vAecvhelhszzCctzmhGs4TGmr9h4zddZoQ8dTdy1OCsnmU+yz3oh
+oiQjy7UPLt8DS2ZKhGhvwPvtwFh5icMWQVnv2kE4Evz8xJT12VRw+U6L5rfKmf/L
+mVNxsuk17MDyBcMlwuNk+CHrYVdrXhSWUH3UCQQUH1iqqBMKmNiPa1UGU0budZ9X
+HZjn9uqyyOGy8l3hffqjDxsDjZyBDf5aqKIdnvukdrUiacPdUYVF0fwK8d1/1PA9
+dA4JjTvz+tTK6mL9Ic9Pv+64v1vwMU4Qu8IJHk5x3I0e7KuK2A/lK6az2Vb6FAh6
+MkGpWB68T8FRBoVrWLOh+a9yNwyp
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/data_files/cert_md5.csr b/tests/data_files/cert_md5.csr
new file mode 100644
index 0000000..dc6792d
--- /dev/null
+++ b/tests/data_files/cert_md5.csr
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICgTCCAWkCAQAwPDELMAkGA1UEBhMCTkwxETAPBgNVBAoMCFBvbGFyU1NMMRow
+GAYDVQQDDBFQb2xhclNTTCBDZXJ0IE1ENTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAMh0xMy5+bV56UXZFGCwfbuT8msenzOtDY+KPFZl5dxE2cxmhQfV
++CewSjXQY54Kbhu32vB+q+4MEJOGSRg086gq0lf1LtQvdymEYU2CUI+nlUhw9W5N
+stUTw9Ia7eZD6kIU63TqwO0f1FdOqfOo7dLgwTBxMDIw1dP2CNBWT0aO8l/5PWeR
+iDAuQrLfffvlDHf/7DHAeI+/wn/KrWwh1o3Zi2qOb+Cb+BBWzLOOExXmNARmx+75
+Ng5qlfYJmgZn9GVx+MqksSXg/jyLNQRnuuBPdoX8f/w2a7XpzS0DYk6zPQDPr3ag
+aVaDatKo1OdQcea1NgV3BW17yOTE/UzVIV8CAwEAAaAAMA0GCSqGSIb3DQEBBAUA
+A4IBAQBNEvxgn3Pc62hsMgMz33IdeNpazeK3ae2gwQQFgL7qMp/kskfpIKF4m8eB
+YrmjKn9cqszRD606/ZtWYDwINUUc6O7bQGmpGIFd7bSPm/pbsajc6R7kzA/tD/bk
+G5zqu9Bj0x92hEwdku0zY+Hx9PgT2dK8M72iFylHBwT3X1tNyXhh7xWJ9RlAfSvN
+KdS6s3kRjK4qcir0MnflV5f2HD6r1v9cSVyme6eVLvOmup89z0cihH7NDwDJaYbi
+oqcKXFbro8/2ruEzPUS6U8NA9cjlX9DW8buIu4cQACVx5YevlwKoayYfXcRRvIFo
+OLiPq14TuZj3c0+HFOxWj4UBAjvI
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/include/test/drivers/key_management.h b/tests/include/test/drivers/key_management.h
new file mode 100644
index 0000000..90f8c58
--- /dev/null
+++ b/tests/include/test/drivers/key_management.h
@@ -0,0 +1,78 @@
+/*
+ * Test driver for generating and verifying keys.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H
+#define PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include <psa/crypto_driver_common.h>
+
+typedef struct {
+    /* If non-null, on success, copy this to the output. */
+    void *forced_output;
+    size_t forced_output_length;
+    /* If not PSA_SUCCESS, return this error code instead of processing the
+     * function call. */
+    psa_status_t forced_status;
+    /* Count the amount of times one of the key management driver functions
+     * is called. */
+    unsigned long hits;
+} test_driver_key_management_hooks_t;
+
+#define TEST_DRIVER_KEY_MANAGEMENT_INIT { NULL, 0, PSA_ERROR_NOT_SUPPORTED, 0 }
+static inline test_driver_key_management_hooks_t test_driver_key_management_hooks_init( void )
+{
+    const test_driver_key_management_hooks_t v = TEST_DRIVER_KEY_MANAGEMENT_INIT;
+    return( v );
+}
+
+extern test_driver_key_management_hooks_t test_driver_key_management_hooks;
+
+psa_status_t test_transparent_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key, size_t key_size, size_t *key_length );
+
+psa_status_t test_opaque_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key, size_t key_size, size_t *key_length );
+
+psa_status_t test_transparent_validate_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *data,
+    size_t data_length,
+    size_t *bits);
+
+psa_status_t test_transparent_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    uint8_t *data, size_t data_size, size_t *data_length );
+
+psa_status_t test_opaque_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    uint8_t *data, size_t data_size, size_t *data_length );
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_TEST_DRIVERS_KEY_MANAGEMENT_H */
diff --git a/tests/include/test/drivers/keygen.h b/tests/include/test/drivers/keygen.h
deleted file mode 100644
index b72c65c..0000000
--- a/tests/include/test/drivers/keygen.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Test driver for generating keys.
- */
-/*  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-#ifndef PSA_CRYPTO_TEST_DRIVERS_KEYGEN_H
-#define PSA_CRYPTO_TEST_DRIVERS_KEYGEN_H
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#if defined(PSA_CRYPTO_DRIVER_TEST)
-#include <psa/crypto_driver_common.h>
-
-typedef struct {
-    /* If non-null, on success, copy this to the output. */
-    void *forced_output;
-    size_t forced_output_length;
-    /* If not PSA_SUCCESS, return this error code instead of processing the
-     * function call. */
-    psa_status_t forced_status;
-    /* Count the amount of times one of the keygen driver functions is called. */
-    unsigned long hits;
-} test_driver_keygen_hooks_t;
-
-#define TEST_DRIVER_KEYGEN_INIT { NULL, 0, PSA_ERROR_NOT_SUPPORTED, 0 }
-static inline test_driver_keygen_hooks_t test_driver_keygen_hooks_init( void )
-{
-    const test_driver_keygen_hooks_t v = TEST_DRIVER_KEYGEN_INIT;
-    return( v );
-}
-
-extern test_driver_keygen_hooks_t test_driver_keygen_hooks;
-
-psa_status_t test_transparent_generate_key(
-    const psa_key_attributes_t *attributes,
-    uint8_t *key, size_t key_size, size_t *key_length );
-
-psa_status_t test_opaque_generate_key(
-    const psa_key_attributes_t *attributes,
-    uint8_t *key, size_t key_size, size_t *key_length );
-
-#endif /* PSA_CRYPTO_DRIVER_TEST */
-#endif /* PSA_CRYPTO_TEST_DRIVERS_KEYGEN_H */
diff --git a/tests/include/test/drivers/signature.h b/tests/include/test/drivers/signature.h
index e41892e..8abcb11 100644
--- a/tests/include/test/drivers/signature.h
+++ b/tests/include/test/drivers/signature.h
@@ -36,7 +36,7 @@
     /* If not PSA_SUCCESS, return this error code instead of processing the
      * function call. */
     psa_status_t forced_status;
-    /* Count the amount of times one of the keygen driver functions is called. */
+    /* Count the amount of times one of the signature driver functions is called. */
     unsigned long hits;
 } test_driver_signature_hooks_t;
 
diff --git a/tests/include/test/drivers/size.h b/tests/include/test/drivers/size.h
new file mode 100644
index 0000000..4bfe986
--- /dev/null
+++ b/tests/include/test/drivers/size.h
@@ -0,0 +1,95 @@
+/*
+ * Test driver for context size functions
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef PSA_CRYPTO_TEST_DRIVERS_SIZE_H
+#define PSA_CRYPTO_TEST_DRIVERS_SIZE_H
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include <psa/crypto_driver_common.h>
+
+typedef struct {
+    unsigned int context;
+} test_driver_key_context_t;
+
+/** \def TEST_DRIVER_KEY_CONTEXT_BASE_SIZE
+ *
+ * This macro returns the base size for the key context. It is the size of the
+ * driver specific information stored in each key context.
+ */
+#define TEST_DRIVER_KEY_CONTEXT_BASE_SIZE          sizeof( test_driver_key_context_t )
+
+/** \def TEST_DRIVER_KEY_CONTEXT_KEY_PAIR_SIZE
+ *
+ * Number of bytes included in every key context for a key pair.
+ *
+ * This pair size is for an ECC 256-bit private/public key pair.
+ * Based on this value, the size of the private key can be derived by
+ * subtracting the public key size below from this one.
+ */
+
+#define TEST_DRIVER_KEY_CONTEXT_KEY_PAIR_SIZE      65
+
+/** \def TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE
+ *
+ * Number of bytes included in every key context for a public key.
+ *
+ * For ECC public keys, it needs 257 bits so 33 bytes.
+ */
+#define TEST_DRIVER_KEY_CONTEXT_PUBLIC_KEY_SIZE    33
+
+/** \def TEST_DRIVER_KEY_CONTEXT_SYMMETRIC_FACTOR
+ *
+ * Every key context for a symmetric key includes this many times the key size.
+ */
+#define TEST_DRIVER_KEY_CONTEXT_SYMMETRIC_FACTOR   0
+
+/** \def TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY
+ *
+ * If this is true for a key pair, the key context includes space for the public key.
+ * If this is false, no additional space is added for the public key.
+ *
+ * For this instance, store the public key with the private one.
+ */
+#define TEST_DRIVER_KEY_CONTEXT_STORE_PUBLIC_KEY   1
+
+/** \def TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION
+ *
+ * If TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION is defined, the test driver
+ * provides a size_function entry point, otherwise, it does not.
+ *
+ * Some opaque drivers have the need to support a custom size for the storage
+ * of key and context information. The size_function provides the ability to
+ * provide that customization.
+ */
+//#define TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION
+
+#ifdef TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION
+size_t test_size_function(
+    const psa_key_type_t key_type,
+    const size_t key_bits );
+#endif /* TEST_DRIVER_KEY_CONTEXT_SIZE_FUNCTION */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_TEST_DRIVERS_SIZE_H */
diff --git a/tests/include/test/drivers/test_driver.h b/tests/include/test/drivers/test_driver.h
index 7ee8e5e..f26b795 100644
--- a/tests/include/test/drivers/test_driver.h
+++ b/tests/include/test/drivers/test_driver.h
@@ -23,7 +23,8 @@
 #define PSA_CRYPTO_TEST_DRIVER_LIFETIME 0x7fffff
 
 #include "test/drivers/signature.h"
-#include "test/drivers/keygen.h"
+#include "test/drivers/key_management.h"
 #include "test/drivers/cipher.h"
+#include "test/drivers/size.h"
 
 #endif /* PSA_CRYPTO_TEST_DRIVER_H */
diff --git a/tests/include/test/helpers.h b/tests/include/test/helpers.h
index c4979cc..2c7b179 100644
--- a/tests/include/test/helpers.h
+++ b/tests/include/test/helpers.h
@@ -53,10 +53,8 @@
 void mbedtls_test_platform_teardown( void );
 
 /**
- * \brief          This function translates an ASCII string encoding an
- *                 hexadecimal number into the encoded hexadecimal number. The
- *                 hexadecimal number is represented as an array of
- *                 unsigned char.
+ * \brief          This function decodes the hexadecimal representation of
+ *                 data.
  *
  * \note           The output buffer can be the same as the input buffer. For
  *                 any other overlapping of the input and output buffers, the
@@ -70,7 +68,7 @@
  *
  * \return         \c 0 on success.
  * \return         \c -1 if the output buffer is too small or the input string
- *                 is not a valid ASCII encoding of an hexadecimal number.
+ *                 is not a valid hexadecimal representation.
  */
 int mbedtls_test_unhexify( unsigned char *obuf, size_t obufmax,
                            const char *ibuf, size_t *len );
@@ -103,4 +101,93 @@
 int mbedtls_test_hexcmp( uint8_t * a, uint8_t * b,
                          uint32_t a_len, uint32_t b_len );
 
+#if defined(MBEDTLS_CHECK_PARAMS)
+
+typedef struct
+{
+    const char *failure_condition;
+    const char *file;
+    int line;
+}
+mbedtls_test_param_failed_location_record_t;
+
+/**
+ * \brief   Get the location record of the last call to
+ *          mbedtls_test_param_failed().
+ *
+ * \note    The call expectation is set up and active until the next call to
+ *          mbedtls_test_param_failed_check_expected_call() or
+ *          mbedtls_param_failed() that cancels it.
+ */
+void mbedtls_test_param_failed_get_location_record(
+         mbedtls_test_param_failed_location_record_t *location_record );
+
+/**
+ * \brief   State that a call to mbedtls_param_failed() is expected.
+ *
+ * \note    The call expectation is set up and active until the next call to
+ *          mbedtls_test_param_failed_check_expected_call() or
+ *          mbedtls_param_failed that cancel it.
+ */
+void mbedtls_test_param_failed_expect_call( void );
+
+/**
+ * \brief   Check whether mbedtls_param_failed() has been called as expected.
+ *
+ * \note    Check whether mbedtls_param_failed() has been called between the
+ *          last call to mbedtls_test_param_failed_expect_call() and the call
+ *          to this function.
+ *
+ * \return  \c 0 Since the last call to mbedtls_param_failed_expect_call(),
+ *               mbedtls_param_failed() has been called.
+ *          \c -1 Otherwise.
+ */
+int mbedtls_test_param_failed_check_expected_call( void );
+
+/**
+ * \brief   Get the address of the object of type jmp_buf holding the execution
+ *          state information used by mbedtls_param_failed() to do a long jump.
+ *
+ * \note    If a call to mbedtls_param_failed() is not expected in the sense
+ *          that there is no call to mbedtls_test_param_failed_expect_call()
+ *          preceding it, then mbedtls_param_failed() will try to restore the
+ *          execution to the state stored in the jmp_buf object whose address
+ *          is returned by the present function.
+ *
+ * \note    This function is intended to provide the parameter of the
+ *          setjmp() function to set-up where mbedtls_param_failed() should
+ *          long-jump if it has to. It is foreseen to be used as:
+ *
+ *          setjmp( mbedtls_test_param_failed_get_state_buf() ).
+ *
+ * \note    The type of the returned value is not jmp_buf as jmp_buf is an
+ *          an array type (C specification) and a function cannot return an
+ *          array type.
+ *
+ * \note    The type of the returned value is not jmp_buf* as then the return
+ *          value couldn't be used by setjmp(), as its parameter's type is
+ *          jmp_buf.
+ *
+ * \return  Address of the object of type jmp_buf holding the execution state
+ *          information used by mbedtls_param_failed() to do a long jump.
+ */
+void* mbedtls_test_param_failed_get_state_buf( void );
+
+/**
+ * \brief   Reset the execution state used by mbedtls_param_failed() to do a
+ *          long jump.
+ *
+ * \note    If a call to mbedtls_param_failed() is not expected in the sense
+ *          that there is no call to mbedtls_test_param_failed_expect_call()
+ *          preceding it, then mbedtls_param_failed() will try to restore the
+ *          execution state that this function reset.
+ *
+ * \note    It is recommended to reset the execution state when the state
+ *          is not relevant anymore. That way an unexpected call to
+ *          mbedtls_param_failed() will not trigger a long jump with
+ *          undefined behavior but rather a long jump that will rather fault.
+ */
+void mbedtls_test_param_failed_reset_state( void );
+#endif /* MBEDTLS_CHECK_PARAMS */
+
 #endif /* TEST_HELPERS_H */
diff --git a/tests/include/test/psa_crypto_helpers.h b/tests/include/test/psa_crypto_helpers.h
index c8013a1..01b0547 100644
--- a/tests/include/test/psa_crypto_helpers.h
+++ b/tests/include/test/psa_crypto_helpers.h
@@ -24,6 +24,7 @@
 #include "test/psa_helpers.h"
 
 #include <psa/crypto.h>
+#include <psa_crypto_slot_management.h>
 
 static int test_helper_is_psa_pristine( int line, const char *file )
 {
@@ -40,6 +41,10 @@
         msg = "An external slot has not been closed properly.";
     else if( stats.half_filled_slots != 0 )
         msg = "A half-filled slot has not been cleared properly.";
+    else if( stats.locked_slots != 0 )
+    {
+        msg = "Some slots are still marked as locked.";
+    }
 
     /* If the test has already failed, don't overwrite the failure
      * information. Do keep the stats lookup above, because it can be
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 578d03e..2bb2216 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -127,6 +127,8 @@
 pre_initialize_variables () {
     CONFIG_H='include/mbedtls/config.h'
     CONFIG_BAK="$CONFIG_H.bak"
+    CRYPTO_CONFIG_H='include/psa/crypto_config.h'
+    CRYPTO_CONFIG_BAK="$CRYPTO_CONFIG_H.bak"
 
     append_outcome=0
     MEMORY=0
@@ -285,6 +287,10 @@
     if [ -f "$CONFIG_BAK" ]; then
         mv "$CONFIG_BAK" "$CONFIG_H"
     fi
+
+    if [ -f "$CRYPTO_CONFIG_BAK" ]; then
+        mv "$CRYPTO_CONFIG_BAK" "$CRYPTO_CONFIG_H"
+    fi
 }
 
 # Executed on exit. May be redefined depending on command line options.
@@ -780,6 +786,18 @@
     if_build_succeeded tests/context-info.sh
 }
 
+component_test_psa_crypto_key_id_encodes_owner () {
+    msg "build: full config - USE_PSA_CRYPTO + PSA_CRYPTO_KEY_ID_ENCODES_OWNER, cmake, gcc, ASan"
+    scripts/config.py full
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+    make
+
+    msg "test: full config - USE_PSA_CRYPTO + PSA_CRYPTO_KEY_ID_ENCODES_OWNER, cmake, gcc, ASan"
+    make test
+}
+
 component_test_zlib_make() {
     msg "build: zlib enabled, make"
     scripts/config.py set MBEDTLS_ZLIB_SUPPORT
@@ -1290,14 +1308,224 @@
     if_build_succeeded env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
 }
 
+component_test_psa_crypto_config_basic() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+
+    msg "test: full + MBEDTLS_PSA_CRYPTO_CONFIG"
+    make test
+}
+
+component_test_psa_crypto_config_no_driver() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG minus MBEDTLS_PSA_CRYPTO_DRIVERS"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py unset MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
+
+    msg "test: full + MBEDTLS_PSA_CRYPTO_CONFIG minus MBEDTLS_PSA_CRYPTO_DRIVERS"
+    make test
+}
+
+# This should be renamed to test and updated once the accelerator ECDSA code is in place and ready to test.
+component_build_psa_accel_alg_ecdsa() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_ALG_ECDSA
+    # without MBEDTLS_ECDSA_C
+    # PSA_WANT_ALG_ECDSA and PSA_WANT_ALG_DETERMINISTIC_ECDSA are already
+    # set in include/psa/crypto_config.h
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG + PSA_WANT_ALG_ECDSA without MBEDTLS_ECDSA_C"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py unset MBEDTLS_ECDSA_C
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_ECDSA -DMBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+}
+
+# This should be renamed to test and updated once the accelerator ECDH code is in place and ready to test.
+component_build_psa_accel_alg_ecdh() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_ALG_ECDH
+    # without MBEDTLS_ECDH_C
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG + PSA_WANT_ALG_ECDH without MBEDTLS_ECDH_C"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py unset MBEDTLS_ECDH_C
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_ECDH -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+}
+
+# This should be renamed to test and updated once the accelerator ECC key pair code is in place and ready to test.
+component_build_psa_accel_key_type_ecc_key_pair() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG + PSA_WANT_KEY_TYPE_ECC_KEY_PAIR"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1
+    scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+}
+
+# This should be renamed to test and updated once the accelerator ECC public key code is in place and ready to test.
+component_build_psa_accel_key_type_ecc_public_key() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG + PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+}
+
+# This should be renamed to test and updated once the accelerator HMAC code is in place and ready to test.
+component_build_psa_accel_alg_hmac() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_ALG_HMAC
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG + PSA_WANT_ALG_HMAC"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_HMAC -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+}
+
+# This should be renamed to test and updated once the accelerator HKDF code is in place and ready to test.
+component_build_psa_accel_alg_hkdf() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_ALG_HKDF
+    # without MBEDTLS_HKDF_C
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG + PSA_WANT_ALG_HKDF without MBEDTLS_HKDF_C"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py unset MBEDTLS_HKDF_C
+    # Make sure to unset TLS1_3_EXPERIMENTAL since it requires HKDF_C and will not build properly without it.
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_HKDF -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+}
+
+# This should be renamed to test and updated once the accelerator RSA code is in place and ready to test.
+component_build_psa_accel_alg_rsa_pkcs1v15_crypt() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG + PSA_WANT_ALG_RSA_PKCS1V15_CRYPT + PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_OAEP
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PSS
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+}
+
+# This should be renamed to test and updated once the accelerator RSA code is in place and ready to test.
+component_build_psa_accel_alg_rsa_pkcs1v15_sign() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_ALG_RSA_PKCS1V15_SIGN and PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG + PSA_WANT_ALG_RSA_PKCS1V15_SIGN + PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_OAEP
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PSS
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+}
+
+# This should be renamed to test and updated once the accelerator RSA code is in place and ready to test.
+component_build_psa_accel_alg_rsa_oaep() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_ALG_RSA_OAEP and PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG + PSA_WANT_ALG_RSA_OAEP + PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_ALG_RSA_OAEP 1
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PSS
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_RSA_OAEP -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+}
+
+# This should be renamed to test and updated once the accelerator RSA code is in place and ready to test.
+component_build_psa_accel_alg_rsa_pss() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_ALG_RSA_PSS and PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG + PSA_WANT_ALG_RSA_PSS + PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_ALG_RSA_PSS 1
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_CRYPT
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_RSA_OAEP
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_ALG_RSA_PSS -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+}
+
+# This should be renamed to test and updated once the accelerator RSA code is in place and ready to test.
+component_build_psa_accel_key_type_rsa_key_pair() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_KEY_TYPE_RSA_KEY_PAIR and PSA_WANT_ALG_RSA_PSS
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG + PSA_WANT_KEY_TYPE_RSA_KEY_PAIR + PSA_WANT_ALG_RSA_PSS"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_ALG_RSA_PSS 1
+    scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+}
+
+# This should be renamed to test and updated once the accelerator RSA code is in place and ready to test.
+component_build_psa_accel_key_type_rsa_public_key() {
+    # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY and PSA_WANT_ALG_RSA_PSS
+    msg "build: full + MBEDTLS_PSA_CRYPTO_CONFIG + PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY + PSA_WANT_ALG_RSA_PSS"
+    scripts/config.py full
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_ALG_RSA_PSS 1
+    scripts/config.py -f include/psa/crypto_config.h set PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1
+    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY -I../tests/include -O2" LDFLAGS="$ASAN_CFLAGS"
+}
+
 component_test_check_params_functionality () {
     msg "build+test: MBEDTLS_CHECK_PARAMS functionality"
     scripts/config.py full # includes CHECK_PARAMS
     # Make MBEDTLS_PARAM_FAILED call mbedtls_param_failed().
     scripts/config.py unset MBEDTLS_CHECK_PARAMS_ASSERT
-    # Only build and run tests. Do not build sample programs, because
-    # they don't have a mbedtls_param_failed() function.
-    make CC=gcc CFLAGS='-Werror -O1' lib test
+    make CC=gcc CFLAGS='-Werror -O1' all test
 }
 
 component_test_check_params_without_platform () {
@@ -1852,6 +2080,20 @@
     make test
 }
 
+component_test_no_strings () {
+    msg "build: no strings" # ~10s
+    scripts/config.py full
+    # Disable options that activate a large amount of string constants.
+    scripts/config.py unset MBEDTLS_DEBUG_C
+    scripts/config.py unset MBEDTLS_ERROR_C
+    scripts/config.py set MBEDTLS_ERROR_STRERROR_DUMMY
+    scripts/config.py unset MBEDTLS_VERSION_FEATURES
+    make CFLAGS='-Werror -Os'
+
+    msg "test: no strings" # ~ 10s
+    make test
+}
+
 component_build_arm_none_eabi_gcc () {
     msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1" # ~ 10s
     scripts/config.py baremetal
@@ -2122,6 +2364,7 @@
     # Back up the configuration in case the component modifies it.
     # The cleanup function will restore it.
     cp -p "$CONFIG_H" "$CONFIG_BAK"
+    cp -p "$CRYPTO_CONFIG_H" "$CRYPTO_CONFIG_BAK"
     current_component="$1"
     export MBEDTLS_TEST_CONFIGURATION="$current_component"
 
diff --git a/tests/scripts/check-generated-files.sh b/tests/scripts/check-generated-files.sh
index 3ab62f8..845d1c6 100755
--- a/tests/scripts/check-generated-files.sh
+++ b/tests/scripts/check-generated-files.sh
@@ -105,3 +105,4 @@
 check scripts/generate_query_config.pl programs/test/query_config.c
 check scripts/generate_features.pl library/version_features.c
 check scripts/generate_visualc_files.pl visualc/VS2010
+check scripts/generate_psa_constants.py programs/psa/psa_constant_names_generated.c
diff --git a/tests/scripts/check-names.sh b/tests/scripts/check-names.sh
index 6c9195b..55f76da 100755
--- a/tests/scripts/check-names.sh
+++ b/tests/scripts/check-names.sh
@@ -65,7 +65,7 @@
 diff macros identifiers | sed -n -e 's/< //p' > actual-macros
 
 for THING in actual-macros enum-consts; do
-    printf "Names of $THING: "
+    printf 'Names of %s: ' "$THING"
     test -r $THING
     BAD=$( grep -E -v '^(MBEDTLS|PSA)_[0-9A-Z_]*[0-9A-Z]$' $THING || true )
     UNDERSCORES=$( grep -E '.*__.*' $THING || true )
@@ -81,7 +81,7 @@
 done
 
 for THING in identifiers; do
-    printf "Names of $THING: "
+    printf 'Names of %s: ' "$THING"
     test -r $THING
     BAD=$( grep -E -v '^(mbedtls|psa)_[0-9a-z_]*[0-9a-z]$' $THING || true )
     if [ "x$BAD" = "x" ]; then
diff --git a/tests/scripts/list-macros.sh b/tests/scripts/list-macros.sh
index 15d2590..a8617a0 100755
--- a/tests/scripts/list-macros.sh
+++ b/tests/scripts/list-macros.sh
@@ -30,4 +30,10 @@
     | egrep -v '^(asm|inline|EMIT|_CRT_SECURE_NO_DEPRECATE)$|^MULADDC_' \
     | sort -u > macros
 
+# For include/mbedtls/config_psa.h need to ignore the MBEDTLS_xxx define
+# in that file since they may not be defined in include/psa/crypto_config.h
+# This line renames the potentially missing defines to ones that should
+# be present.
+sed -ne 's/^MBEDTLS_PSA_BUILTIN_/MBEDTLS_PSA_ACCEL_/p' <macros >>macros
+
 wc -l macros
diff --git a/tests/scripts/test-ref-configs.pl b/tests/scripts/test-ref-configs.pl
index 01edfe2..cf4175a 100755
--- a/tests/scripts/test-ref-configs.pl
+++ b/tests/scripts/test-ref-configs.pl
@@ -28,17 +28,21 @@
 use strict;
 
 my %configs = (
+    'config-ccm-psk-tls1_2.h' => {
+        'compat' => '-m tls1_2 -f \'^TLS-PSK-WITH-AES-...-CCM-8\'',
+    },
     'config-mini-tls1_1.h' => {
         'compat' => '-m tls1_1 -f \'^DES-CBC3-SHA$\|^TLS-RSA-WITH-3DES-EDE-CBC-SHA$\'', #'
     },
+    'config-no-entropy.h' => {
+    },
+    'config-psa-crypto.h' => {
+    },
     'config-suite-b.h' => {
         'compat' => "-m tls1_2 -f 'ECDHE-ECDSA.*AES.*GCM' -p mbedTLS",
     },
     'config-symmetric-only.h' => {
     },
-    'config-ccm-psk-tls1_2.h' => {
-        'compat' => '-m tls1_2 -f \'^TLS-PSK-WITH-AES-...-CCM-8\'',
-    },
     'config-thread.h' => {
         'opt' => '-f ECJPAKE.*nolog',
     },
diff --git a/tests/src/drivers/key_management.c b/tests/src/drivers/key_management.c
new file mode 100644
index 0000000..00d2b45
--- /dev/null
+++ b/tests/src/drivers/key_management.c
@@ -0,0 +1,355 @@
+/*
+ * Test driver for generating and verifying keys.
+ * Currently only supports generating and verifying ECC keys.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
+#include "psa/crypto.h"
+#include "psa_crypto_core.h"
+#include "mbedtls/ecp.h"
+#include "mbedtls/error.h"
+
+#include "test/drivers/key_management.h"
+
+#include "test/random.h"
+
+#include <string.h>
+
+test_driver_key_management_hooks_t test_driver_key_management_hooks =
+    TEST_DRIVER_KEY_MANAGEMENT_INIT;
+
+psa_status_t test_transparent_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key, size_t key_size, size_t *key_length )
+{
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
+    (void)attributes;
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR &&
+        * !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
+    ++test_driver_key_management_hooks.hits;
+
+    if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
+        return( test_driver_key_management_hooks.forced_status );
+
+    if( test_driver_key_management_hooks.forced_output != NULL )
+    {
+        if( test_driver_key_management_hooks.forced_output_length > key_size )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+        memcpy( key, test_driver_key_management_hooks.forced_output,
+                test_driver_key_management_hooks.forced_output_length );
+        *key_length = test_driver_key_management_hooks.forced_output_length;
+        return( PSA_SUCCESS );
+    }
+
+    /* Copied from psa_crypto.c */
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
+    if ( PSA_KEY_TYPE_IS_ECC( psa_get_key_type( attributes ) )
+         && PSA_KEY_TYPE_IS_KEY_PAIR( psa_get_key_type( attributes ) ) )
+    {
+        psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
+            psa_get_key_type( attributes ) );
+        mbedtls_ecp_group_id grp_id =
+            mbedtls_ecc_group_of_psa(
+                curve,
+                PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) );
+        const mbedtls_ecp_curve_info *curve_info =
+            mbedtls_ecp_curve_info_from_grp_id( grp_id );
+        mbedtls_ecp_keypair ecp;
+        mbedtls_test_rnd_pseudo_info rnd_info;
+        memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
+
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        if( attributes->domain_parameters_size != 0 )
+            return( PSA_ERROR_NOT_SUPPORTED );
+        if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
+            return( PSA_ERROR_NOT_SUPPORTED );
+        if( curve_info->bit_size != psa_get_key_bits( attributes ) )
+            return( PSA_ERROR_INVALID_ARGUMENT );
+        mbedtls_ecp_keypair_init( &ecp );
+        ret = mbedtls_ecp_gen_key( grp_id, &ecp,
+                                   &mbedtls_test_rnd_pseudo_rand,
+                                   &rnd_info );
+        if( ret != 0 )
+        {
+            mbedtls_ecp_keypair_free( &ecp );
+            return( mbedtls_to_psa_error( ret ) );
+        }
+
+        /* Make sure to use export representation */
+        size_t bytes = PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) );
+        if( key_size < bytes )
+        {
+            mbedtls_ecp_keypair_free( &ecp );
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+        }
+        psa_status_t status = mbedtls_to_psa_error(
+            mbedtls_mpi_write_binary( &ecp.d, key, bytes ) );
+
+        if( status == PSA_SUCCESS )
+        {
+            *key_length = bytes;
+        }
+        else
+        {
+            memset( key, 0, bytes );
+        }
+
+        mbedtls_ecp_keypair_free( &ecp );
+        return( status );
+    }
+    else
+#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR ||
+        * MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t test_opaque_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key, size_t key_size, size_t *key_length )
+{
+    (void) attributes;
+    (void) key;
+    (void) key_size;
+    (void) key_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t test_transparent_validate_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *data,
+    size_t data_length,
+    size_t *bits )
+{
+    ++test_driver_key_management_hooks.hits;
+
+    if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
+        return( test_driver_key_management_hooks.forced_status );
+
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
+    psa_key_type_t type = psa_get_key_type( attributes );
+    if ( PSA_KEY_TYPE_IS_ECC( type ) )
+    {
+        // Code mostly copied from psa_load_ecp_representation
+        psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( type );
+        mbedtls_ecp_group_id grp_id;
+        mbedtls_ecp_keypair ecp;
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+        if( psa_get_key_bits( attributes ) == 0 )
+        {
+            // Attempt auto-detect of curve bit size
+            size_t curve_size = data_length;
+
+            if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) &&
+                PSA_KEY_TYPE_ECC_GET_FAMILY( type ) != PSA_ECC_FAMILY_MONTGOMERY )
+            {
+                /* A Weierstrass public key is represented as:
+                 * - The byte 0x04;
+                 * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
+                 * - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
+                 * So its data length is 2m+1 where m is the curve size in bits.
+                 */
+                if( ( data_length & 1 ) == 0 )
+                    return( PSA_ERROR_INVALID_ARGUMENT );
+                curve_size = data_length / 2;
+
+                /* Montgomery public keys are represented in compressed format, meaning
+                 * their curve_size is equal to the amount of input. */
+
+                /* Private keys are represented in uncompressed private random integer
+                 * format, meaning their curve_size is equal to the amount of input. */
+            }
+
+            grp_id = mbedtls_ecc_group_of_psa( curve, curve_size );
+        }
+        else
+        {
+            grp_id = mbedtls_ecc_group_of_psa( curve,
+                PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) );
+        }
+
+        const mbedtls_ecp_curve_info *curve_info =
+            mbedtls_ecp_curve_info_from_grp_id( grp_id );
+
+        if( attributes->domain_parameters_size != 0 )
+            return( PSA_ERROR_NOT_SUPPORTED );
+        if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        *bits = curve_info->bit_size;
+
+        mbedtls_ecp_keypair_init( &ecp );
+
+        status = mbedtls_to_psa_error(
+                    mbedtls_ecp_group_load( &ecp.grp, grp_id ) );
+        if( status != PSA_SUCCESS )
+            goto ecp_exit;
+
+        /* Load the key material. */
+        if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) )
+        {
+            /* Load the public value. */
+            status = mbedtls_to_psa_error(
+                mbedtls_ecp_point_read_binary( &ecp.grp, &ecp.Q,
+                                               data,
+                                               data_length ) );
+            if( status != PSA_SUCCESS )
+                goto ecp_exit;
+
+            /* Check that the point is on the curve. */
+            status = mbedtls_to_psa_error(
+                mbedtls_ecp_check_pubkey( &ecp.grp, &ecp.Q ) );
+        }
+        else
+        {
+            /* Load and validate the secret value. */
+            status = mbedtls_to_psa_error(
+                mbedtls_ecp_read_key( ecp.grp.id,
+                                      &ecp,
+                                      data,
+                                      data_length ) );
+        }
+
+ecp_exit:
+        mbedtls_ecp_keypair_free( &ecp );
+        return( status );
+    }
+    return( PSA_ERROR_NOT_SUPPORTED );
+#else
+    (void) attributes;
+    (void) data;
+    (void) data_length;
+    (void) bits;
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR ||
+        * MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
+}
+
+psa_status_t test_transparent_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    uint8_t *data, size_t data_size, size_t *data_length )
+{
+    ++test_driver_key_management_hooks.hits;
+
+    if( test_driver_key_management_hooks.forced_status != PSA_SUCCESS )
+        return( test_driver_key_management_hooks.forced_status );
+
+    if( test_driver_key_management_hooks.forced_output != NULL )
+    {
+        if( test_driver_key_management_hooks.forced_output_length > data_size )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+        memcpy( data, test_driver_key_management_hooks.forced_output,
+                test_driver_key_management_hooks.forced_output_length );
+        *data_length = test_driver_key_management_hooks.forced_output_length;
+        return( PSA_SUCCESS );
+    }
+
+    if( key == NULL || key_length == 0 )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    psa_key_type_t keytype = psa_get_key_type( attributes );
+    (void) keytype;
+
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) || \
+    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
+    if( PSA_KEY_TYPE_IS_ECC( keytype ) )
+    {
+        if( !PSA_KEY_TYPE_IS_KEY_PAIR( keytype ) )
+            return( PSA_ERROR_INVALID_ARGUMENT );
+
+        /* Mostly copied from psa_crypto.c */
+        mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
+        psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+        mbedtls_ecp_keypair ecp;
+        mbedtls_test_rnd_pseudo_info rnd_info;
+        memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
+
+        if( attributes->domain_parameters_size != 0 )
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( keytype ),
+                                           PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) );
+        if( grp_id == MBEDTLS_ECP_DP_NONE )
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        mbedtls_ecp_keypair_init( &ecp );
+
+        status = mbedtls_to_psa_error(
+                    mbedtls_ecp_group_load( &ecp.grp, grp_id ) );
+        if( status != PSA_SUCCESS )
+            goto ecp_exit;
+
+        status = mbedtls_to_psa_error(
+            mbedtls_ecp_read_key( ecp.grp.id,
+                                  &ecp,
+                                  key,
+                                  key_length ) );
+        if( status != PSA_SUCCESS )
+            goto ecp_exit;
+
+        /* Calculate the public key */
+        status = mbedtls_to_psa_error(
+            mbedtls_ecp_mul( &ecp.grp, &ecp.Q, &ecp.d, &ecp.grp.G,
+                             &mbedtls_test_rnd_pseudo_rand,
+                             &rnd_info ) );
+        if( status != PSA_SUCCESS )
+            goto ecp_exit;
+
+        status = mbedtls_to_psa_error(
+                    mbedtls_ecp_point_write_binary( &ecp.grp, &ecp.Q,
+                                                    MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                                    data_length,
+                                                    data,
+                                                    data_size ) );
+        if( status != PSA_SUCCESS )
+            memset( data, 0, data_size );
+ecp_exit:
+        mbedtls_ecp_keypair_free( &ecp );
+        return( status );
+    }
+#endif /* MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR ||
+        * MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t test_opaque_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    uint8_t *data, size_t data_size, size_t *data_length )
+{
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) data;
+    (void) data_size;
+    (void) data_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/tests/src/drivers/keygen.c b/tests/src/drivers/keygen.c
deleted file mode 100644
index f15a4bc..0000000
--- a/tests/src/drivers/keygen.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Test driver for generating keys.
- * Currently only supports generating ECC keys.
- */
-/*  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
-#include "psa/crypto.h"
-#include "psa_crypto_core.h"
-#include "mbedtls/ecp.h"
-#include "mbedtls/error.h"
-
-#include "test/drivers/keygen.h"
-
-#include "test/random.h"
-
-#include <string.h>
-
-test_driver_keygen_hooks_t test_driver_keygen_hooks = TEST_DRIVER_KEYGEN_INIT;
-
-psa_status_t test_transparent_generate_key(
-    const psa_key_attributes_t *attributes,
-    uint8_t *key, size_t key_size, size_t *key_length )
-{
-    ++test_driver_keygen_hooks.hits;
-
-    if( test_driver_keygen_hooks.forced_status != PSA_SUCCESS )
-        return( test_driver_keygen_hooks.forced_status );
-
-    if( test_driver_keygen_hooks.forced_output != NULL )
-    {
-        if( test_driver_keygen_hooks.forced_output_length > key_size )
-            return( PSA_ERROR_BUFFER_TOO_SMALL );
-        memcpy( key, test_driver_keygen_hooks.forced_output,
-                test_driver_keygen_hooks.forced_output_length );
-        *key_length = test_driver_keygen_hooks.forced_output_length;
-        return( PSA_SUCCESS );
-    }
-
-    /* Copied from psa_crypto.c */
-#if defined(MBEDTLS_ECP_C)
-    if ( PSA_KEY_TYPE_IS_ECC( psa_get_key_type( attributes ) )
-         && PSA_KEY_TYPE_IS_KEY_PAIR( psa_get_key_type( attributes ) ) )
-    {
-        psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( psa_get_key_type( attributes ) );
-        mbedtls_ecp_group_id grp_id =
-            mbedtls_ecc_group_of_psa( curve, PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) ) );
-        const mbedtls_ecp_curve_info *curve_info =
-            mbedtls_ecp_curve_info_from_grp_id( grp_id );
-        mbedtls_ecp_keypair ecp;
-        mbedtls_test_rnd_pseudo_info rnd_info;
-        memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
-
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        if( attributes->domain_parameters_size != 0 )
-            return( PSA_ERROR_NOT_SUPPORTED );
-        if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL )
-            return( PSA_ERROR_NOT_SUPPORTED );
-        if( curve_info->bit_size != psa_get_key_bits( attributes ) )
-            return( PSA_ERROR_INVALID_ARGUMENT );
-        mbedtls_ecp_keypair_init( &ecp );
-        ret = mbedtls_ecp_gen_key( grp_id, &ecp,
-                                   &mbedtls_test_rnd_pseudo_rand,
-                                   &rnd_info );
-        if( ret != 0 )
-        {
-            mbedtls_ecp_keypair_free( &ecp );
-            return( mbedtls_to_psa_error( ret ) );
-        }
-
-        /* Make sure to use export representation */
-        size_t bytes = PSA_BITS_TO_BYTES( psa_get_key_bits( attributes ) );
-        if( key_size < bytes )
-        {
-            mbedtls_ecp_keypair_free( &ecp );
-            return( PSA_ERROR_BUFFER_TOO_SMALL );
-        }
-        psa_status_t status = mbedtls_to_psa_error(
-            mbedtls_mpi_write_binary( &ecp.d, key, bytes ) );
-
-        if( status == PSA_SUCCESS )
-        {
-            *key_length = bytes;
-        }
-
-        mbedtls_ecp_keypair_free( &ecp );
-        return( status );
-    }
-    else
-#endif /* MBEDTLS_ECP_C */
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-psa_status_t test_opaque_generate_key(
-    const psa_key_attributes_t *attributes,
-    uint8_t *key, size_t key_size, size_t *key_length )
-{
-    (void) attributes;
-    (void) key;
-    (void) key_size;
-    (void) key_length;
-    return( PSA_ERROR_NOT_SUPPORTED );
-}
-
-#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/tests/src/drivers/signature.c b/tests/src/drivers/signature.c
index 028d24a..cea0351 100644
--- a/tests/src/drivers/signature.c
+++ b/tests/src/drivers/signature.c
@@ -262,6 +262,8 @@
     (void) alg;
     (void) hash;
     (void) hash_length;
+    (void) signature;
+    (void) signature_length;
 #endif /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
           defined(MBEDTLS_SHA256_C) */
 
diff --git a/tests/src/drivers/size.c b/tests/src/drivers/size.c
new file mode 100644
index 0000000..16a8692
--- /dev/null
+++ b/tests/src/drivers/size.c
@@ -0,0 +1,42 @@
+/*
+ * Test driver for retrieving key context size.
+ * Only used by opaque drivers.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
+
+#include "test/drivers/size.h"
+
+#ifdef TEST_KEY_CONTEXT_SIZE_FUNCTION
+size_t test_size_function(
+    const psa_key_type_t key_type,
+    const size_t key_bits )
+{
+    (void) key_type;
+    (void) key_bits;
+    return 0;
+}
+#endif /*TEST_KEY_CONTEXT_SIZE_FUNCTION */
+
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/tests/src/helpers.c b/tests/src/helpers.c
index f385079..a18f1d4 100644
--- a/tests/src/helpers.c
+++ b/tests/src/helpers.c
@@ -19,10 +19,34 @@
 #include <test/macros.h>
 #include <string.h>
 
+#if defined(MBEDTLS_CHECK_PARAMS)
+#include <setjmp.h>
+#endif
+
+/*----------------------------------------------------------------------------*/
+/* Static global variables */
+
+#if defined(MBEDTLS_CHECK_PARAMS)
+typedef struct
+{
+    uint8_t expected_call;
+    uint8_t expected_call_happened;
+
+    jmp_buf state;
+
+    mbedtls_test_param_failed_location_record_t location_record;
+}
+param_failed_ctx_t;
+static param_failed_ctx_t param_failed_ctx;
+#endif
+
 #if defined(MBEDTLS_PLATFORM_C)
 static mbedtls_platform_context platform_ctx;
 #endif
 
+/*----------------------------------------------------------------------------*/
+/* Helper Functions */
+
 int mbedtls_test_platform_setup( void )
 {
     int ret = 0;
@@ -159,3 +183,64 @@
     }
     return ret;
 }
+
+#if defined(MBEDTLS_CHECK_PARAMS)
+void mbedtls_test_param_failed_get_location_record(
+         mbedtls_test_param_failed_location_record_t *location_record )
+{
+    *location_record = param_failed_ctx.location_record;
+}
+
+void mbedtls_test_param_failed_expect_call( void )
+{
+    param_failed_ctx.expected_call_happened = 0;
+    param_failed_ctx.expected_call = 1;
+}
+
+int mbedtls_test_param_failed_check_expected_call( void )
+{
+    param_failed_ctx.expected_call = 0;
+
+    if( param_failed_ctx.expected_call_happened != 0 )
+        return( 0 );
+
+    return( -1 );
+}
+
+void* mbedtls_test_param_failed_get_state_buf( void )
+{
+    return &param_failed_ctx.state;
+}
+
+void mbedtls_test_param_failed_reset_state( void )
+{
+    memset( param_failed_ctx.state, 0, sizeof( param_failed_ctx.state ) );
+}
+
+void mbedtls_param_failed( const char *failure_condition,
+                           const char *file,
+                           int line )
+{
+    /* Record the location of the failure */
+    param_failed_ctx.location_record.failure_condition = failure_condition;
+    param_failed_ctx.location_record.file = file;
+    param_failed_ctx.location_record.line = line;
+
+    /* If we are testing the callback function...  */
+    if( param_failed_ctx.expected_call != 0 )
+    {
+        param_failed_ctx.expected_call = 0;
+        param_failed_ctx.expected_call_happened = 1;
+    }
+    else
+    {
+        /* ...else try a long jump. If the execution state has not been set-up
+         * or reset then the long jump buffer is all zero's and the call will
+         * with high probability fault, emphasizing there is something to look
+         * at.
+         */
+
+        longjmp( param_failed_ctx.state, 1 );
+    }
+}
+#endif /* MBEDTLS_CHECK_PARAMS */
diff --git a/tests/src/random.c b/tests/src/random.c
index af88d98..e01bd4d 100644
--- a/tests/src/random.c
+++ b/tests/src/random.c
@@ -22,6 +22,15 @@
  *  limitations under the License.
  */
 
+/*
+ * for arc4random_buf() from <stdlib.h>
+ */
+#if defined(__NetBSD__)
+#define _NETBSD_SOURCE 1
+#elif defined(__OpenBSD__)
+#define _BSD_SOURCE 1
+#endif
+
 #include <test/macros.h>
 #include <test/random.h>
 #include <string.h>
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 653d88d..fcd73f2 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -114,8 +114,8 @@
     echo "Usage: $0 [options]"
     printf "  -h|--help\tPrint this help.\n"
     printf "  -m|--memcheck\tCheck memory leaks and errors.\n"
-    printf "  -f|--filter\tOnly matching tests are executed (BRE; default: '$FILTER')\n"
-    printf "  -e|--exclude\tMatching tests are excluded (BRE; default: '$EXCLUDE')\n"
+    printf "  -f|--filter\tOnly matching tests are executed (BRE)\n"
+    printf "  -e|--exclude\tMatching tests are excluded (BRE)\n"
     printf "  -n|--number\tExecute only numbered test (comma-separated, e.g. '245,256')\n"
     printf "  -s|--show-numbers\tShow test numbers in front of test names\n"
     printf "  -p|--preserve-logs\tPreserve logs of successful tests as well\n"
@@ -411,7 +411,7 @@
     fi
 
     LINE="$LINE$1"
-    printf "$LINE "
+    printf "%s " "$LINE"
     LEN=$(( 72 - `echo "$LINE" | wc -c` ))
     for i in `seq 1 $LEN`; do printf '.'; done
     printf ' '
@@ -634,6 +634,23 @@
     fi
 }
 
+# Compare file content
+# Usage: find_in_both pattern file1 file2
+# extract from file1 the first line matching the pattern
+# check in file2 that the same line can be found
+find_in_both() {
+        srv_pattern=$(grep -m 1 "$1" "$2");
+        if [ -z "$srv_pattern" ]; then
+                return 1;
+        fi
+
+        if grep "$srv_pattern" $3 >/dev/null; then :
+                return 0;
+        else
+                return 1;
+        fi
+}
+
 # Usage: run_test name [-p proxy_cmd] srv_cmd cli_cmd cli_exit [option [...]]
 # Options:  -s pattern  pattern that must be present in server output
 #           -c pattern  pattern that must be present in client output
@@ -643,6 +660,7 @@
 #           -C pattern  pattern that must be absent in client output
 #           -U pattern  lines after pattern must be unique in server output
 #           -F call shell function on server output
+#           -g call shell function on server and client output
 run_test() {
     NAME="$1"
     shift 1
@@ -738,12 +756,12 @@
         fi
 
         check_osrv_dtls
-        printf "# $NAME\n$SRV_CMD\n" > $SRV_OUT
+        printf '# %s\n%s\n' "$NAME" "$SRV_CMD" > $SRV_OUT
         provide_input | $SRV_CMD >> $SRV_OUT 2>&1 &
         SRV_PID=$!
         wait_server_start "$SRV_PORT" "$SRV_PID"
 
-        printf "# $NAME\n$CLI_CMD\n" > $CLI_OUT
+        printf '# %s\n%s\n' "$NAME" "$CLI_CMD" > $CLI_OUT
         eval "$CLI_CMD" >> $CLI_OUT 2>&1 &
         wait_client_done
 
@@ -865,6 +883,12 @@
                     return
                 fi
                 ;;
+            "-g")
+                if ! eval "$2 '$SRV_OUT' '$CLI_OUT'"; then
+                    fail "function call to '$2' failed on Server and Client output"
+                    return
+                fi
+                ;;
 
             *)
                 echo "Unknown test: $1" >&2
@@ -3023,12 +3047,12 @@
 # Tests for Max Fragment Length extension
 
 if [ "$MAX_CONTENT_LEN" -lt "4096" ]; then
-    printf "${CONFIG_H} defines MBEDTLS_SSL_MAX_CONTENT_LEN to be less than 4096. Fragment length tests will fail.\n"
+    printf '%s defines MBEDTLS_SSL_MAX_CONTENT_LEN to be less than 4096. Fragment length tests will fail.\n' "${CONFIG_H}"
     exit 1
 fi
 
 if [ $MAX_CONTENT_LEN -ne 16384 ]; then
-    printf "Using non-default maximum content length $MAX_CONTENT_LEN\n"
+    echo "Using non-default maximum content length $MAX_CONTENT_LEN"
 fi
 
 requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
@@ -4182,14 +4206,14 @@
 MAX_IM_CA_CONFIG=$( ../scripts/config.py get MBEDTLS_X509_MAX_INTERMEDIATE_CA)
 
 if [ -n "$MAX_IM_CA_CONFIG" ] && [ "$MAX_IM_CA_CONFIG" -ne "$MAX_IM_CA" ]; then
-    printf "The ${CONFIG_H} file contains a value for the configuration of\n"
-    printf "MBEDTLS_X509_MAX_INTERMEDIATE_CA that is different from the script’s\n"
-    printf "test value of ${MAX_IM_CA}. \n"
-    printf "\n"
-    printf "The tests assume this value and if it changes, the tests in this\n"
-    printf "script should also be adjusted.\n"
-    printf "\n"
+    cat <<EOF
+${CONFIG_H} contains a value for the configuration of
+MBEDTLS_X509_MAX_INTERMEDIATE_CA that is different from the script's
+test value of ${MAX_IM_CA}.
 
+The tests assume this value and if it changes, the tests in this
+script should also be adjusted.
+EOF
     exit 1
 fi
 
@@ -8713,6 +8737,539 @@
             0 \
             -s "fragmenting handshake message"
 
+# Tests for DTLS-SRTP (RFC 5764)
+requires_config_enabled MBEDTLS_SSL_DTLS_SRTP
+run_test  "DTLS-SRTP all profiles supported" \
+          "$P_SRV dtls=1 use_srtp=1 debug_level=3" \
+          "$P_CLI dtls=1 use_srtp=1 debug_level=3" \
+          0 \
+          -s "found use_srtp extension" \
+          -s "found srtp profile" \
+          -s "selected srtp profile" \
+          -s "server hello, adding use_srtp extension" \
+          -s "DTLS-SRTP key material is"\
+          -c "client hello, adding use_srtp extension" \
+          -c "found use_srtp extension" \
+          -c "found srtp profile" \
+          -c "selected srtp profile" \
+          -c "DTLS-SRTP key material is"\
+          -g "find_in_both '^ *Keying material: [0-9A-F]*$'"\
+          -C "error"
+
+
+requires_config_enabled MBEDTLS_SSL_DTLS_SRTP
+run_test  "DTLS-SRTP server supports all profiles. Client supports one profile." \
+          "$P_SRV dtls=1 use_srtp=1 debug_level=3" \
+          "$P_CLI dtls=1 use_srtp=1 srtp_force_profile=5 debug_level=3" \
+          0 \
+          -s "found use_srtp extension" \
+          -s "found srtp profile: MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80" \
+          -s "selected srtp profile: MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80" \
+          -s "server hello, adding use_srtp extension" \
+          -s "DTLS-SRTP key material is"\
+          -c "client hello, adding use_srtp extension" \
+          -c "found use_srtp extension" \
+          -c "found srtp profile: MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80" \
+          -c "selected srtp profile" \
+          -c "DTLS-SRTP key material is"\
+          -g "find_in_both '^ *Keying material: [0-9A-F]*$'"\
+          -C "error"
+
+requires_config_enabled MBEDTLS_SSL_DTLS_SRTP
+run_test  "DTLS-SRTP server supports one profile. Client supports all profiles." \
+          "$P_SRV dtls=1 use_srtp=1 srtp_force_profile=6 debug_level=3" \
+          "$P_CLI dtls=1 use_srtp=1 debug_level=3" \
+          0 \
+          -s "found use_srtp extension" \
+          -s "found srtp profile" \
+          -s "selected srtp profile: MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32" \
+          -s "server hello, adding use_srtp extension" \
+          -s "DTLS-SRTP key material is"\
+          -c "client hello, adding use_srtp extension" \
+          -c "found use_srtp extension" \
+          -c "found srtp profile: MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32" \
+          -c "selected srtp profile" \
+          -c "DTLS-SRTP key material is"\
+          -g "find_in_both '^ *Keying material: [0-9A-F]*$'"\
+          -C "error"
+
+requires_config_enabled MBEDTLS_SSL_DTLS_SRTP
+run_test  "DTLS-SRTP server and Client support only one matching profile." \
+          "$P_SRV dtls=1 use_srtp=1 srtp_force_profile=2 debug_level=3" \
+          "$P_CLI dtls=1 use_srtp=1 srtp_force_profile=2 debug_level=3" \
+          0 \
+          -s "found use_srtp extension" \
+          -s "found srtp profile: MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32" \
+          -s "selected srtp profile: MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32" \
+          -s "server hello, adding use_srtp extension" \
+          -s "DTLS-SRTP key material is"\
+          -c "client hello, adding use_srtp extension" \
+          -c "found use_srtp extension" \
+          -c "found srtp profile: MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32" \
+          -c "selected srtp profile" \
+          -c "DTLS-SRTP key material is"\
+          -g "find_in_both '^ *Keying material: [0-9A-F]*$'"\
+          -C "error"
+
+requires_config_enabled MBEDTLS_SSL_DTLS_SRTP
+run_test  "DTLS-SRTP server and Client support only one different profile." \
+          "$P_SRV dtls=1 use_srtp=1 srtp_force_profile=2 debug_level=3" \
+          "$P_CLI dtls=1 use_srtp=1 srtp_force_profile=6 debug_level=3" \
+          0 \
+          -s "found use_srtp extension" \
+          -s "found srtp profile: MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32" \
+          -S "selected srtp profile" \
+          -S "server hello, adding use_srtp extension" \
+          -S "DTLS-SRTP key material is"\
+          -c "client hello, adding use_srtp extension" \
+          -C "found use_srtp extension" \
+          -C "found srtp profile" \
+          -C "selected srtp profile" \
+          -C "DTLS-SRTP key material is"\
+          -C "error"
+
+requires_config_enabled MBEDTLS_SSL_DTLS_SRTP
+run_test  "DTLS-SRTP server doesn't support use_srtp extension." \
+          "$P_SRV dtls=1 debug_level=3" \
+          "$P_CLI dtls=1 use_srtp=1 debug_level=3" \
+          0 \
+          -s "found use_srtp extension" \
+          -S "server hello, adding use_srtp extension" \
+          -S "DTLS-SRTP key material is"\
+          -c "client hello, adding use_srtp extension" \
+          -C "found use_srtp extension" \
+          -C "found srtp profile" \
+          -C "selected srtp profile" \
+          -C "DTLS-SRTP key material is"\
+          -C "error"
+
+requires_config_enabled MBEDTLS_SSL_DTLS_SRTP
+run_test  "DTLS-SRTP all profiles supported. mki used" \
+          "$P_SRV dtls=1 use_srtp=1 support_mki=1 debug_level=3" \
+          "$P_CLI dtls=1 use_srtp=1 mki=542310ab34290481 debug_level=3" \
+          0 \
+          -s "found use_srtp extension" \
+          -s "found srtp profile" \
+          -s "selected srtp profile" \
+          -s "server hello, adding use_srtp extension" \
+          -s "dumping 'using mki' (8 bytes)" \
+          -s "DTLS-SRTP key material is"\
+          -c "client hello, adding use_srtp extension" \
+          -c "found use_srtp extension" \
+          -c "found srtp profile" \
+          -c "selected srtp profile" \
+          -c "dumping 'sending mki' (8 bytes)" \
+          -c "dumping 'received mki' (8 bytes)" \
+          -c "DTLS-SRTP key material is"\
+          -g "find_in_both '^ *Keying material: [0-9A-F]*$'"\
+          -g "find_in_both '^ *DTLS-SRTP mki value: [0-9A-F]*$'"\
+          -C "error"
+
+requires_config_enabled MBEDTLS_SSL_DTLS_SRTP
+run_test  "DTLS-SRTP all profiles supported. server doesn't support mki." \
+          "$P_SRV dtls=1 use_srtp=1 debug_level=3" \
+          "$P_CLI dtls=1 use_srtp=1 mki=542310ab34290481 debug_level=3" \
+          0 \
+          -s "found use_srtp extension" \
+          -s "found srtp profile" \
+          -s "selected srtp profile" \
+          -s "server hello, adding use_srtp extension" \
+          -s "DTLS-SRTP key material is"\
+          -s "DTLS-SRTP no mki value negotiated"\
+          -S "dumping 'using mki' (8 bytes)" \
+          -c "client hello, adding use_srtp extension" \
+          -c "found use_srtp extension" \
+          -c "found srtp profile" \