Merge pull request #3717 from pkolbus/issue-3647

Restore retry in rsa_prepare_blinding()
diff --git a/.travis.yml b/.travis.yml
index c67c0cd..76cb1c5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -28,10 +28,6 @@
       script:
         - tests/scripts/all.sh -k test_full_cmake_gcc_asan
 
-    - name: check compilation guards
-      script:
-        - tests/scripts/all.sh -k 'test_depends_*' 'build_key_exchanges'
-
     - name: macOS
       os: osx
       compiler: clang
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8833246..5af4c81 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -261,7 +261,7 @@
 # to define the test executables.
 #
 if(ENABLE_TESTING OR ENABLE_PROGRAMS)
-    file(GLOB MBEDTLS_TEST_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/*.c)
+    file(GLOB MBEDTLS_TEST_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/*.c ${CMAKE_CURRENT_SOURCE_DIR}/tests/src/drivers/*.c)
     add_library(mbedtls_test OBJECT ${MBEDTLS_TEST_FILES})
     target_include_directories(mbedtls_test
         PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests/include
diff --git a/ChangeLog.d/add-aes-ecb-to-psa.txt b/ChangeLog.d/add-aes-ecb-to-psa.txt
new file mode 100644
index 0000000..b0de67c
--- /dev/null
+++ b/ChangeLog.d/add-aes-ecb-to-psa.txt
@@ -0,0 +1,2 @@
+Features
+   * Add support for ECB to the PSA cipher API.
diff --git a/ChangeLog.d/add_cipher_transparent_driver.txt b/ChangeLog.d/add_cipher_transparent_driver.txt
new file mode 100644
index 0000000..ce6f33d
--- /dev/null
+++ b/ChangeLog.d/add_cipher_transparent_driver.txt
@@ -0,0 +1,4 @@
+Features
+   * Partial implementation of the new PSA Crypto accelerator APIs for
+     enabling symmetric cipher acceleration through crypto accelerators.
+     Contributed by Steven Cooreman in #3644.
diff --git a/ChangeLog.d/add_sign_verify_keygen_transparent_driver.txt b/ChangeLog.d/add_sign_verify_keygen_transparent_driver.txt
new file mode 100644
index 0000000..fe43899
--- /dev/null
+++ b/ChangeLog.d/add_sign_verify_keygen_transparent_driver.txt
@@ -0,0 +1,4 @@
+Features
+   * Partial implementation of the new PSA Crypto accelerator APIs for
+     enabling key generation and asymmetric signing/verification through crypto
+     accelerators. Contributed by Steven Cooreman in #3501.
diff --git a/ChangeLog.d/adjusting sliding_window_size_PR3592.txt b/ChangeLog.d/adjusting sliding_window_size_PR3592.txt
new file mode 100644
index 0000000..6089565
--- /dev/null
+++ b/ChangeLog.d/adjusting sliding_window_size_PR3592.txt
@@ -0,0 +1,3 @@
+Changes
+   * Reduce stack usage significantly during sliding window exponentiation.
+     Reported in #3591 and fix contributed in #3592 by Daniel Otte.
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_PR3294.txt b/ChangeLog.d/bugfix_PR3294.txt
new file mode 100644
index 0000000..a6ea75e
--- /dev/null
+++ b/ChangeLog.d/bugfix_PR3294.txt
@@ -0,0 +1,4 @@
+Bugfix
+   * Fix build failure in configurations where MBEDTLS_USE_PSA_CRYPTO is
+     enabled but ECDSA is disabled. Contributed by jdurkop. Fixes #3294.
+
diff --git a/ChangeLog.d/comment_typo_in_mbedtls_ssl_set_bio.txt b/ChangeLog.d/comment_typo_in_mbedtls_ssl_set_bio.txt
new file mode 100644
index 0000000..2f94c16
--- /dev/null
+++ b/ChangeLog.d/comment_typo_in_mbedtls_ssl_set_bio.txt
@@ -0,0 +1,2 @@
+Changes
+   * Fix comment typo in documentation of mbedtls_ssl_set_bio.
diff --git a/ChangeLog.d/fix-typo.txt b/ChangeLog.d/fix-typo.txt
new file mode 100644
index 0000000..8e961d2
--- /dev/null
+++ b/ChangeLog.d/fix-typo.txt
@@ -0,0 +1,3 @@
+Changes
+   * Fixes a typo in the example code located in
+     program/pkey/ecdh_curve25519.c
diff --git a/ChangeLog.d/getrandom.txt b/ChangeLog.d/getrandom.txt
new file mode 100644
index 0000000..87a3a6c
--- /dev/null
+++ b/ChangeLog.d/getrandom.txt
@@ -0,0 +1,2 @@
+Changes
+   Use glibc's getrandom() instead of syscall when glibc > 2.25.
diff --git a/configs/config-psa-crypto.h b/configs/config-psa-crypto.h
index 70563ae..b98fc9c 100644
--- a/configs/config-psa-crypto.h
+++ b/configs/config-psa-crypto.h
@@ -1144,20 +1144,20 @@
  */
 //#define MBEDTLS_ENTROPY_NV_SEED
 
-/* MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
+/* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
  *
- * In PSA key storage, encode the owner of the key.
+ * Enable key identifiers that encode a key owner identifier.
  *
  * This is only meaningful when building the library as part of a
- * multi-client service. When you activate this option, you must provide
- * an implementation of the type psa_key_owner_id_t and a translation
- * from psa_key_file_id_t to file name in all the storage backends that
+ * multi-client service. When you activate this option, you must provide an
+ * implementation of the type mbedtls_key_owner_id_t and a translation from
+ * mbedtls_svc_key_id_t to file name in all the storage backends that you
  * you wish to support.
  *
  * Note that this option is meant for internal use only and may be removed
  * without notice.
  */
-//#define MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
+//#define MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
 
 /**
  * \def MBEDTLS_MEMORY_DEBUG
diff --git a/docs/architecture/mbed-crypto-storage-specification.md b/docs/architecture/mbed-crypto-storage-specification.md
index e7315eb..afeb29f 100644
--- a/docs/architecture/mbed-crypto-storage-specification.md
+++ b/docs/architecture/mbed-crypto-storage-specification.md
@@ -107,14 +107,12 @@
 
 ### Key names for 1.0.0
 
-Information about each key is stored in a dedicated file designated by a _key file identifier_ (`psa_key_file_id_t`). The key file identifier is constructed from the 32-bit key identifier (`psa_key_id_t`) and, if applicable, an identifier of the owner of the key. In integrations where there is no concept of key owner (in particular, in library integrations), the key file identifier is exactly the key identifier. When the library is integrated into a service, the service determines the semantics of the owner identifier.
+Information about each key is stored in a dedicated file designated by the key identifier. In integrations where there is no concept of key owner (in particular, in library integrations), the key identifier is exactly the key identifier as defined in the PSA Cryptography API specification (`psa_key_id_t`). In integrations where there is a concept of key owner (integration into a service for example), the key identifier is made of an owner identifier (its semantics and type are integration specific) and of the key identifier (`psa_key_id_t`) from the key owner point of view.
 
-The way in which the file name is constructed from the key file identifier depends on the storage backend. The content of the file is described [below](#key-file-format-for-1.0.0).
+The way in which the file name is constructed from the key identifier depends on the storage backend. The content of the file is described [below](#key-file-format-for-1.0.0).
 
-The valid values for a key identifier are the range from 1 to 0xfffeffff. This limitation on the range is not documented in user-facing documentation: according to the user-facing documentation, arbitrary 32-bit values are valid.
-
-* Library integration: the key file name is just the key identifer. This is a 32-bit value.
-* PSA service integration: the key file identifier is `(uint32_t)owner_uid << 32 | key_id` where `key_id` is the key identifier specified by the application and `owner_uid` (of type `int32_t`) is the calling partition identifier provided to the server by the partition manager. This is a 64-bit value.
+* Library integration: the key file name is just the key identifier as defined in the PSA crypto specification. This is a 32-bit value.
+* PSA service integration: the key file name is `(uint32_t)owner_uid << 32 | key_id` where `key_id` is the key identifier from the owner point of view and `owner_uid` (of type `int32_t`) is the calling partition identifier provided to the server by the partition manager. This is a 64-bit value.
 
 ### Key file format for 1.0.0
 
diff --git a/docs/architecture/tls13-experimental.md b/docs/architecture/tls13-experimental.md
index bcf3e34..3db16e0 100644
--- a/docs/architecture/tls13-experimental.md
+++ b/docs/architecture/tls13-experimental.md
@@ -38,3 +38,12 @@
 - The HKDF key derivation function on which the TLS 1.3 key schedule is based,
   is already present as an independent module controlled by `MBEDTLS_HKDF_C`
   independently of the development of the TLS 1.3 prototype.
+
+- The TLS 1.3-specific HKDF-based key derivation functions (see RFC 8446):
+  * HKDF-Expand-Label
+  * Derive-Secret
+  - Secret evolution
+  * The traffic {Key,IV} generation from secret
+  Those functions are implemented in `library/ssl_tls13_keys.c` and
+  tested in `test_suite_ssl` using test vectors from RFC 8448 and
+  https://tls13.ulfheim.net/.
diff --git a/docs/proposed/Makefile b/docs/proposed/Makefile
index 2132b08..1c31464 100644
--- a/docs/proposed/Makefile
+++ b/docs/proposed/Makefile
@@ -3,6 +3,7 @@
 default: all
 
 all_markdown = \
+	       psa-conditional-inclusion-c.md \
 	       psa-driver-developer-guide.md \
 	       psa-driver-integration-guide.md \
 	       psa-driver-interface.md \
diff --git a/docs/proposed/psa-conditional-inclusion-c.md b/docs/proposed/psa-conditional-inclusion-c.md
new file mode 100644
index 0000000..08306d2
--- /dev/null
+++ b/docs/proposed/psa-conditional-inclusion-c.md
@@ -0,0 +1,202 @@
+Conditional inclusion of cryptographic mechanism through the PSA API in Mbed TLS
+================================================================================
+
+This document is a proposed interface for deciding at build time which cryptographic mechanisms to include in the PSA Cryptography interface.
+
+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"
+
+## Introduction
+
+### Purpose of this specification
+
+The [PSA Cryptography API specification](https://armmbed.github.io/mbed-crypto/psa/#application-programming-interface) specifies the interface between a PSA Cryptography implementation and an application. The interface defines a number of categories of cryptographic algorithms (hashes, MAC, signatures, etc.). In each category, a typical implementation offers many algorithms (e.g. for signatures: RSA-PKCS#1v1.5, RSA-PSS, ECDSA). When building the implementation for a specific use case, it is often desirable to include only a subset of the available cryptographic mechanisms, primarily in order to reduce the code footprint of the compiled system.
+
+The present document proposes a way for an application using the PSA cryptography interface to declare which mechanisms it requires.
+
+### Conditional inclusion of legacy cryptography modules
+
+Mbed TLS offers a way to select which cryptographic mechanisms are included in a build through its configuration file (`config.h`). This mechanism is based on two main sets of symbols: `MBEDTLS_xxx_C` controls the availability of the mechanism to the application, and `MBEDTLS_xxx_ALT` controls the availability of an alternative implementation, so the software implementation is only included if `MBEDTLS_xxx_C` is defined but not `MBEDTLS_xxx_ALT`.
+
+### PSA evolution
+
+In the PSA cryptography interface, the **core** (built-in implementations of cryptographic mechanisms) can be augmented with drivers. **Transparent drivers** replace the built-in implementation of a cryptographic mechanism (or, with **fallback**, the built-in implementation is tried if the driver only has partial support for the mechanism). **Opaque drivers** implement cryptographic mechanisms on keys which are stored in a separate domain such as a secure element, for which the core only does key management and dispatch using wrapped key blobs or key identifiers.
+
+The current model is difficult to adapt to the PSA interface for several reasons. The `MBEDTLS_xxx_ALT` symbols are somewhat inconsistent, and in particular do not work well for asymmetric cryptography. For example, many parts of the ECC code have no `MBEDTLS_xxx_ALT` symbol, so a platform with ECC acceleration that can perform all ECDSA and ECDH operations in the accelerator would still embark the `bignum` module and large parts of the `ecp_curves`, `ecp` and `ecdsa` modules. Also the availability of a transparent driver for a mechanism does not translate directly to `MBEDTLS_xxx` symbols.
+
+### Requirements
+
+[Req.interface] The application can declare which cryptographic mechanisms it needs.
+
+[Req.inclusion] If the application does not require a mechanism, a suitably configured Mbed TLS build must not include it. The granularity of mechanisms must work for typical use cases and has [acceptable limitations](#acceptable-limitations).
+
+[Req.drivers] If a PSA driver is available in the build, a suitably configured Mbed TLS build must not include the corresponding software code (unless a software fallback is needed).
+
+[Req.c] The configuration mechanism consists of C preprocessor definitions, and the build does not require tools other than a C compiler. This is necessary to allow building an application and Mbed TLS in development environments that do not allow third-party tools.
+
+[Req.adaptability] The implementation of the mechanism must be adaptable with future evolution of the PSA cryptography specifications and Mbed TLS. Therefore the interface must remain sufficiently simple and abstract.
+
+### Acceptable limitations
+
+[Limitation.matrix] If a mechanism is defined by a combination of algorithms and key types, for example a block cipher mode (CBC, CTR, CFB, …) and a block permutation (AES, CAMELLIA, ARIA, …), there is no requirement to include only specific combinations.
+
+[Limitation.direction] For mechanisms that have multiple directions (for example encrypt/decrypt, sign/verify), there is no requirement to include only one direction.
+
+[Limitation.size] There is no requirement to include only support for certain key sizes.
+
+[Limitation.multipart] Where there are multiple ways to perform an operation, for example single-part and multi-part, there is no mechanism to select only one or a subset of the possible ways.
+
+## Interface
+
+### 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 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`.
+
+### PSA Crypto configuration symbols
+
+#### Configuration symbol syntax
+
+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 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.
+
+#### Configuration symbols for key types
+
+For each constant or constructor macro of the form `PSA_KEY_TYPE_xxx`, the symbol **`PSA_WANT_KEY_TYPE_xxx`** indicates that support for this key type is desired.
+
+For asymmetric cryptography, `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR` determines whether private-key operations are desired, and `PSA_WANT_KEY_TYPE_xxx_PUBLIC_KEY` determines whether public-key operations are desired. `PSA_WANT_KEY_TYPE_xxx_KEY_PAIR` implicitly enables `PSA_WANT_KEY_TYPE_xxx_PUBLIC_KEY`: there is no way to only include private-key operations (which typically saves little code).
+
+#### Configuration symbols for curves
+
+For elliptic curve key types, only the specified curves are included. To include a curve, include a symbol of the form **`PSA_WANT_ECC_family_size`**. For example: `PSA_WANT_ECC_SECP_R1_256` for secp256r1, `PSA_WANT_ECC_MONTGOMERY_CURVE25519`. It is an error to require an ECC key type but no curve, and Mbed TLS will reject this at compile time.
+
+#### Configuration symbols for algorithms
+
+For each constant or constructor macro of the form `PSA_ALG_xxx`, the symbol **`PSA_WANT_ALG_xxx`** indicates that support for this algorithm is desired.
+
+For parametrized algorithms, the `PSA_WANT_ALG_xxx` symbol indicates whether the base mechanism is supported. Parameters must themselves be included through their own `PSA_WANT_ALG_xxx` symbols. It is an error to include a base mechanism without at least one possible parameter, and Mbed TLS will reject this at compile time. For example, `PSA_WANT_ALG_ECDSA` requires the inclusion of randomized ECDSA for all hash algorithms whose corresponding symbol `PSA_WANT_ALG_xxx` is enabled.
+
+## Implementation
+
+### Additional non-public symbols
+
+#### Accounting for transparent drivers
+
+In addition to the [configuration symbols](#psa-crypto-configuration-symbols), we need two parallel or mostly parallel sets of symbols:
+
+* **`MBEDTLS_PSA_ACCEL_xxx`** indicates whether a fully-featured, fallback-free transparent driver is available.
+* **`MBEDTLS_PSA_BUILTIN_xxx`** indicates whether the software implementation is needed.
+
+`MBEDTLS_PSA_ACCEL_xxx` is one of the outputs of the transpilation of a driver description, alongside the glue code for calling the drivers.
+
+`MBEDTLS_PSA_BUILTIN_xxx` is enabled when `PSA_WANT_xxx` is enabled and `MBEDTLS_PSA_ACCEL_xxx` is disabled.
+
+These symbols are not part of the public interface of Mbed TLS towards applications or to drivers, regardless of whether the symbols are actually visible.
+
+### Architecture of symbol definitions
+
+#### Definition of internal inclusion 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.
+
+#### Visibility of internal symbols
+
+Ideally, the `MBEDTLS_PSA_ACCEL_xxx` and `MBEDTLS_PSA_BUILTIN_xxx` symbols should not be visible to application code or driver code, since they are not part of the public interface of the library. However these symbols are needed to deduce whether to include library modules (for example `MBEDTLS_AES_C` has to be enabled if `MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES` is enabled), which makes it difficult to keep them private.
+
+#### Compile-time checks
+
+The header file **`library/psa_check_config.h`** applies sanity checks to the configuration, throwing `#error` if something is wrong.
+
+A mechanism similar to `mbedtls/check_config.h` detects errors such as enabling ECDSA but no curve.
+
+Since configuration symbols must be undefined or 1, any other value should trigger an `#error`.
+
+#### Automatic generation of preprocessor symbol manipulations
+
+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
+
+#### Conditional inclusion of library entry points
+
+An entry point can be eliminated entirely if no algorithm requires it.
+
+#### Conditional inclusion of mechanism-specific code
+
+Code that is specific to certain key types or to certain algorithms must be guarded by the applicable symbols: `PSA_WANT_xxx` for code that is independent of the application, and `MBEDTLS_PSA_BUILTIN_xxx` for code that calls an Mbed TLS software implementation.
+
+## PSA standardization
+
+### JSON configuration mechanism
+
+At the time of writing, the preferred configuration mechanism for a PSA service is in JSON syntax. The translation from JSON to build instructions is not specified by PSA.
+
+For PSA Crypto, the preferred configuration mechanism would be similar to capability specifications of transparent drivers. The same JSON properties that are used to mean “this driver can perform that mechanism” in a driver description would be used to mean “the application wants to perform that mechanism” in the application configuration.
+
+### From JSON to C
+
+The JSON capability language allows a more fine-grained selection than the C mechanism proposed here. For example, it allows requesting only single-part mechanisms, only certain key sizes, or only certain combinations of algorithms and key types.
+
+The JSON capability language can be translated approximately to the boolean symbol mechanism proposed here. The approximation considers a feature to be enabled if any part of it is enabled. For example, if there is a capability for AES-CTR and one for CAMELLIA-GCM, the translation to boolean symbols will also include AES-GCM and CAMELLIA-CTR. If there is a capability for AES-128, the translation will also include AES-192 and AES-256.
+
+The boolean symbol mechanism proposed here can be translated to a list of JSON capabilities: for each included algorithm, include a capability with that algorithm, the key types that apply to that algorithm, no size restriction, and all the entry points that apply to that algorithm.
+
+## Open questions
+
+### Open questions about the interface
+
+#### Naming of symbols
+
+The names of [elliptic curve symbols](#configuration-symbols-for-curves) are a bit weird: `SECP_R1_256` instead of `SECP256R1`. Should we make them more classical, but less systematic?
+
+#### Impossible combinations
+
+What does it mean to have `PSA_WANT_ALG_ECDSA` enabled but with only Curve25519? Is it a mandatory error?
+
+#### Diffie-Hellman
+
+Way to request only specific groups? Not a priority: constrained devices don't do FFDH. Specify it as may change in future versions.
+
+#### Coexistence with the current Mbed TLS configuration
+
+The two mechanisms have very different designs. Is there serious potential for confusion? Do we understand how the combinations work?
+
+### Open questions about the design
+
+#### Algorithms without a key type or vice versa
+
+Is it realistic to mandate a compile-time error if a key type is required, but no matching algorithm, or vice versa? Is it always the right thing, for example if there is an opaque driver that manipulates this key type?
+
+#### Opaque-only mechanisms
+
+If a mechanism should only be supported in an opaque driver, what does the core need to know about it? Do we have all the information we need?
+
+This is especially relevant to suppress a mechanism completely if there is no matching algorithm. For example, if there is no transparent implementation of RSA or ECDSA, `psa_sign_hash` and `psa_verify_hash` may still be needed if there is an opaque signature driver.
+
+### Open questions about the implementation
+
+#### Testability
+
+Is this proposal decently testable? There are a lot of combinations. What combinations should we test?
+
+<!--
+Local Variables:
+time-stamp-line-limit: 40
+time-stamp-start: "Time-stamp: *\""
+time-stamp-end: "\""
+time-stamp-format: "%04Y/%02m/%02d %02H:%02M:%02S %Z"
+time-stamp-time-zone: "GMT"
+End:
+-->
diff --git a/docs/proposed/psa-driver-developer-guide.md b/docs/proposed/psa-driver-developer-guide.md
index ca24441..c221bb2 100644
--- a/docs/proposed/psa-driver-developer-guide.md
+++ b/docs/proposed/psa-driver-developer-guide.md
@@ -5,7 +5,7 @@
 
 This document describes how to write drivers of cryptoprocessors such as accelerators and secure elements for the PSA cryptography subsystem of Mbed TLS.
 
-This document focuses on behavior that is specific to Mbed TLS. For a reference of the interface between Mbed TLS and drivers, refer to the [PSA Cryptoprocessor Driver Interface specification](architecture/psa-driver-interface.md).
+This document focuses on behavior that is specific to Mbed TLS. For a reference of the interface between Mbed TLS and drivers, refer to the [PSA Cryptoprocessor Driver Interface specification](psa-driver-interface.html).
 
 The interface is not fully implemented in Mbed TLS yet and is disabled by default. You can enable the experimental work in progress by setting `MBEDTLS_PSA_CRYPTO_DRIVERS` in the compile-time configuration. Please note that the interface may still change: until further notice, we do not guarantee backward compatibility with existing driver code when `MBEDTLS_PSA_CRYPTO_DRIVERS` is enabled.
 
@@ -24,7 +24,7 @@
 
 To write a driver, you need to implement some functions with C linkage, and to declare these functions in a **driver description file**. The driver description file declares which functions the driver implements and what cryptographic mechanisms they support. Depending on the driver type, you may also need to define some C types and macros in a header file.
 
-The concrete syntax for a driver description file is JSON. The structure of this JSON file is specified in the section [“Driver description syntax”](architecture/psa-driver-interface.md#driver-description-syntax) of the PSA cryptography driver interface specification.
+The concrete syntax for a driver description file is JSON. The structure of this JSON file is specified in the section [“Driver description syntax”](psa-driver-interface.html#driver-description-syntax) of the PSA cryptography driver interface specification.
 
 A driver therefore consists of:
 
@@ -34,7 +34,7 @@
 
 ## Driver C interfaces
 
-Mbed TLS calls [driver functions as specified in the PSA Cryptography Driver Interface specification](architecture/psa-driver-interface.md#) except as otherwise indicated in this section.
+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
 
diff --git a/docs/proposed/psa-driver-interface.md b/docs/proposed/psa-driver-interface.md
index 8ef972a..56e2b29 100644
--- a/docs/proposed/psa-driver-interface.md
+++ b/docs/proposed/psa-driver-interface.md
@@ -5,15 +5,15 @@
 
 This specification is work in progress and should be considered to be in a beta stage. There is ongoing work to implement this interface in Mbed TLS, which is the reference implementation of the PSA Cryptography API. At this stage, Arm does not expect major changes, but minor changes are expected based on experience from the first implementation and on external feedback.
 
-Time-stamp: "2020/08/05 20:37:24 GMT"
+Time-stamp: "2020/08/19 19:47:39 GMT"
 
 ## Introduction
 
 ### Purpose of the driver interface
 
-The PSA Cryptography API defines an interface that allows applications to perform cryptographic operations in a uniform way regardless of how the operations are performed. Under the hood, different keys may be processed in different hardware or in different logical partitions, and different algorithms may involve different hardware or software components.
+The PSA Cryptography API defines an interface that allows applications to perform cryptographic operations in a uniform way regardless of how the operations are performed. Under the hood, different keys may be stored and used in different hardware or in different logical partitions, and different algorithms may involve different hardware or software components.
 
-The driver interface allows implementations of the PSA Crypytography API to be built compositionally. An implementation of the PSA Cryptography API is composed of a **core** and zero or more **drivers**. The core handles key management, enforces key usage policies, and dispatches cryptographic operations either to the applicable driver or to built-in code.
+The driver interface allows implementations of the PSA Cryptography API to be built compositionally. An implementation of the PSA Cryptography API is composed of a **core** and zero or more **drivers**. The core handles key management, enforces key usage policies, and dispatches cryptographic operations either to the applicable driver or to built-in code.
 
 Functions in the PSA Cryptography API invoke functions in the core. Code from the core calls drivers as described in the present document.
 
@@ -21,12 +21,12 @@
 
 The PSA Cryptography driver interface supports two types of cryptoprocessors, and accordingly two types of drivers.
 
-* **Transparent** drivers implement cryptographic operations on keys that are provided in cleartext at the beginning of each operation. They are typically used for hardware **accelerators**. When a transparent driver is available for a particular combination of parameters (cryptographic algorithm, key type and size, etc.), it is used instead of the default software implementation. Transparent drivers can also be pure software implementations that are distributed as plug-ins to a PSA Crypto implementation (for example, an alternative implementation with different performance characteristics, or a certified implementation).
+* **Transparent** drivers implement cryptographic operations on keys that are provided in cleartext at the beginning of each operation. They are typically used for hardware **accelerators**. When a transparent driver is available for a particular combination of parameters (cryptographic algorithm, key type and size, etc.), it is used instead of the default software implementation. Transparent drivers can also be pure software implementations that are distributed as plug-ins to a PSA Cryptography implementation (for example, an alternative implementation with different performance characteristics, or a certified implementation).
 * **Opaque** drivers implement cryptographic operations on keys that can only be used inside a protected environment such as a **secure element**, a hardware security module, a smartcard, a secure enclave, etc. An opaque driver is invoked for the specific [key location](#lifetimes-and-locations) that the driver is registered for: the dispatch is based on the key's lifetime.
 
 ### Requirements
 
-The present specification was designed to fulfil the following high-level requirements.
+The present specification was designed to fulfill the following high-level requirements.
 
 [Req.plugins] It is possible to combine multiple drivers from different providers into the same implementation, without any prior arrangement other than choosing certain names and values from disjoint namespaces.
 
@@ -34,7 +34,7 @@
 
 [Req.types] Support drivers for the following types of hardware: accelerators that operate on keys in cleartext; cryptoprocessors that can wrap keys with a built-in keys but not store user keys; and cryptoprocessors that store key material.
 
-[Req.portable] The interface between drivers and the core does not involve any platform-specific consideration. Driver calls are simple C functions. Interactions between driver code and hardware happen inside the driver (and in fact a driver need not involve any hardware at all).
+[Req.portable] The interface between drivers and the core does not involve any platform-specific consideration. Driver calls are simple C function calls. Interactions with platform-specific hardware happen only inside the driver (and in fact a driver need not involve any hardware at all).
 
 [Req.location] Applications can tell which location values correspond to which secure element drivers.
 
@@ -46,54 +46,94 @@
 
 ### Deliverables for a driver
 
-To write a driver, you need to implement some functions with C linkage, and to declare these functions in a **driver description file**. The driver description file declares which functions the driver implements and what cryptographic mechanisms they support. Depending on the driver type, you may also need to define some C types and macros in a header file.
+To write a driver, you need to implement some functions with C linkage, and to declare these functions in a **driver description file**. The driver description file declares which functions the driver implements and what cryptographic mechanisms they support. If the driver description references custom types, macros or constants, you also need to provide C header files defining those elements.
 
 The concrete syntax for a driver description file is JSON. The structure of this JSON file is specified in the section [“Driver description syntax”](#driver-description-syntax).
 
 A driver therefore consists of:
 
 * A driver description file (in JSON format).
-* C header files defining the types required by the driver description. The names of these header files is declared in the driver description file.
-* An object file compiled for the target platform defining the functions required by the driver description. Implementations may allow drivers to be provided as source files and compiled with the core instead of being pre-compiled.
+* C header files defining the types required by the driver description. The names of these header files are declared in the driver description file.
+* An object file compiled for the target platform defining the entry point functions specified by the driver description. Implementations may allow drivers to be provided as source files and compiled with the core instead of being pre-compiled.
 
 How to provide the driver description file, the C header files and the object code is implementation-dependent.
 
-Implementations should support multiple drivers.
-
 ### Driver description syntax
 
 The concrete syntax for a driver description file is JSON.
 
+#### Driver description list
+
+PSA Cryptography core implementations should support multiple drivers. The driver description files are passed to the implementation as an ordered list in an unspecified manner. This may be, for example, a list of file names passed on a command line, or a JSON list whose elements are individual driver descriptions.
+
 #### Driver description top-level element
 
 A driver description is a JSON object containing the following properties:
 
 * `"prefix"` (mandatory, string). This must be a valid prefix for a C identifier. All the types and functions provided by the driver have a name that starts with this prefix unless overridden with a `"name"` element in the applicable capability as described below.
 * `"type"` (mandatory, string). One of `"transparent"` or `"opaque"`.
-* `"headers"` (optional, array of strings). A list of header files. These header files must define the types provided by the driver and may declare the functions provided by the driver. They may include other PSA headers and standard headers of the platform. Whether they may include other headers is implementation-specific. If omitted, the list of headers is empty.
+* `"headers"` (optional, array of strings). A list of header files. These header files must define the types, macros and constants referenced by the driver description. They may declare the entry point functions, but this is not required. They may include other PSA headers and standard headers of the platform. Whether they may include other headers is implementation-specific. If omitted, the list of headers is empty. The header files must be present at the specified location relative to a directory on the compiler's include path when compiling glue code between the core and the drivers.
 * `"capabilities"` (mandatory, array of [capabilities](#driver-description-capability)).
 A list of **capabilities**. Each capability describes a family of functions that the driver implements for a certain class of cryptographic mechanisms.
 * `"key_context"` (not permitted for transparent drivers, mandatory for opaque drivers): information about the [representation of keys](#key-format-for-opaque-drivers).
 * `"persistent_state_size"` (not permitted for transparent drivers, optional for opaque drivers, integer or string). The size in bytes of the [persistent state of the driver](#opaque-driver-persistent-state). This may be either a non-negative integer or a C constant expression of type `size_t`.
 * `"location"` (not permitted for transparent drivers, optional for opaque drivers, integer or string). The [location value](#lifetimes-and-locations) for which this driver is invoked. In other words, this determines the lifetimes for which the driver is invoked. This may be either a non-negative integer or a C constant expression of type `psa_key_location_t`.
 
-#### Driver description capability
+### Driver description capability
+
+#### Capability syntax
 
 A capability declares a family of functions that the driver implements for a certain class of cryptographic mechanisms. The capability specifies which key types and algorithms are covered and the names of the types and functions that implement it.
 
 A capability is a JSON object containing the following properties:
 
-* `"functions"` (optional, list of strings). Each element is the name of a [driver function](#driver-functions) or driver function family. If specified, the core will invoke this capability of the driver only when performing one of the specified operations. If omitted, the `"algorithms"` property is mandatory and the core will invoke this capability of the driver for all operations that are applicable to the specified algorithms. The driver must implement all the specified or implied functions, as well as the types if applicable.
+* `"entry_points"` (mandatory, list of strings). Each element is the name of a [driver entry point](#driver-entry-points) or driver entry point family. An entry point is a function defined by the driver. If specified, the core will invoke this capability of the driver only when performing one of the specified operations. The driver must implement all the specified entry points, as well as the types if applicable.
 * `"algorithms"` (optional, list of strings). Each element is an [algorithm specification](#algorithm-specifications). If specified, the core will invoke this capability of the driver only when performing one of the specified algorithms. If omitted, the core will invoke this capability for all applicable algorithms.
 * `"key_types"` (optional, list of strings). Each element is a [key type specification](#key-type-specifications). If specified, the core will invoke this capability of the driver only for operations involving a key with one of the specified key types. If omitted, the core will invoke this capability of the driver for all applicable key types.
 * `"key_sizes"` (optional, list of integers). If specified, the core will invoke this capability of the driver only for operations involving a key with one of the specified key sizes. If omitted, the core will invoke this capability of the driver for all applicable key sizes. Key sizes are expressed in bits.
-* `"names"` (optional, object). A mapping from entry point names described by the `"functions"` property, to the name of the C function in the driver that implements the corresponding function. If a function is not listed here, name of the driver function that implements it is the driver's prefix followed by an underscore (`_`) followed by the function name. If this property is omitted, it is equivalent to an empty object (so each entry point *suffix* is implemented by a function called *prefix*`_`*suffix*).
-* `"fallback"` (optional for transparent drivers, not permitted for opaque drivers, boolean). If present and true, the driver may return `PSA_ERROR_NOT_SUPPORTED`, in which case the core should call another driver or use built-in code to perform this operation. If absent or false, the core should not include built-in code to perform this particular cryptographic mechanism. See the section “[Fallback](#fallback)” for more information.
+* `"names"` (optional, object). A mapping from entry point names described by the `"entry_points"` property, to the name of the C function in the driver that implements the corresponding function. If a function is not listed here, name of the driver function that implements it is the driver's prefix followed by an underscore (`_`) followed by the function name. If this property is omitted, it is equivalent to an empty object (so each entry point *suffix* is implemented by a function called *prefix*`_`*suffix*).
+* `"fallback"` (optional for transparent drivers, not permitted for opaque drivers, boolean). If present and true, the driver may return `PSA_ERROR_NOT_SUPPORTED`, in which case the core should call another driver or use built-in code to perform this operation. If absent or false, the driver is expected to fully support the mechanisms described by this capability. See the section “[Fallback](#fallback)” for more information.
 
-Example: the following capability declares that the driver can perform deterministic ECDSA signatures using SHA-256 or SHA-384 with a SECP256R1 or SECP384R1 private key (with either hash being possible in combination with either curve). If the prefix of this driver is `"acme"`, the function that performs the signature is called `acme_sign_hash`.
+#### Capability semantics
+
+When the PSA Cryptography implementation performs a cryptographic mechanism, it invokes available driver entry points as described in the section [“Driver entry points”](#driver-entry-points).
+
+A driver is considered available for a cryptographic mechanism that invokes a given entry point if all of the following conditions are met:
+
+* The driver specification includes a capability whose `"entry_points"` list either includes the entry point or includes an entry point family that includes the entry point.
+* If the mechanism involves an algorithm:
+    * either the capability does not have an `"algorithms"` property;
+    * or the value of the capability's `"algorithms"` property includes an [algorithm specification](#algorithm-specifications) that matches this algorithm.
+* If the mechanism involves a key:
+    * either the key is transparent (its location is `PSA_KEY_LOCATION_LOCAL_STORAGE`) and the driver is transparent;
+    * or the key is opaque (its location is not `PSA_KEY_LOCATION_LOCAL_STORAGE`) and the driver is an opaque driver whose location is the key's location.
+* If the mechanism involves a key:
+    * either the capability does not have a `"key_types"` property;
+    * or the value of the capability's `"key_types"` property includes a [key type specification](#key-type-specifications) that matches this algorithm.
+* If the mechanism involves a key:
+    * either the capability does not have a `"key_sizes"` property;
+    * or the value of the capability's `"key_sizes"` property includes the key's size.
+
+If a driver includes multiple applicable capabilities for a given combination of entry point, algorithm, key type and key size, and all the capabilities map the entry point to the same function name, the driver is considered available for this cryptographic mechanism. If a driver includes multiple applicable capabilities for a given combination of entry point, algorithm, key type and key size, and at least two of these capabilities map the entry point to the different function names, the driver specification is invalid.
+
+If multiple transparent drivers have applicable capabilities for a given combination of entry point, algorithm, key type and key size, the first matching driver in the [specification list](#driver-description-list) is invoked. If the capability has [fallback](#fallback) enabled and the first driver returns `PSA_ERROR_NOT_SUPPORTED`, the next matching driver is invoked, and so on.
+
+If multiple opaque drivers have the same location, the list of driver specifications is invalid.
+
+#### Capability examples
+
+Example 1: the following capability declares that the driver can perform deterministic ECDSA signatures (but not signature verification) using any hash algorithm and any curve that the core supports. If the prefix of this driver is `"acme"`, the function that performs the signature is called `acme_sign_hash`.
 ```
 {
-    "functions": ["sign_hash"],
+    "entry_points": ["sign_hash"],
+    "algorithms": ["PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH)"],
+}
+```
+
+Example 2: the following capability declares that the driver can perform deterministic ECDSA signatures using SHA-256 or SHA-384 with a SECP256R1 or SECP384R1 private key (with either hash being possible in combination with either curve). If the prefix of this driver is `"acme"`, the function that performs the signature is called `acme_sign_hash`.
+```
+{
+    "entry_points": ["sign_hash"],
     "algorithms": ["PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256)",
                    "PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384)"],
     "key_types": ["PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_CURVE_SECP_R1)"],
@@ -105,7 +145,7 @@
 
 #### Algorithm specifications
 
-An algorithm specification is a string consisting of a `PSA_ALG_xxx` macro that specifies a cryptographic algorithm defined by the PSA Cryptography API. If the macro takes arguments, the string must have the syntax of a C macro call and each argument must be an algorithm specification or a decimal or hexadecimal literal with no suffix, depending on the expected type of argument.
+An algorithm specification is a string consisting of a `PSA_ALG_xxx` macro that specifies a cryptographic algorithm or an algorithm wildcard policy defined by the PSA Cryptography API. If the macro takes arguments, the string must have the syntax of a C macro call and each argument must be an algorithm specification or a decimal or hexadecimal literal with no suffix, depending on the expected type of argument.
 
 Spaces are optional after commas. Whether other whitespace is permitted is implementation-specific.
 
@@ -114,6 +154,7 @@
 PSA_ALG_SHA_256
 PSA_ALG_HMAC(PSA_ALG_SHA_256)
 PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256))
+PSA_ALG_RSA_PSS(PSA_ALG_ANY_HASH)
 ```
 
 #### Key type specifications
@@ -135,9 +176,9 @@
 
 Drivers define functions, each of which implements an aspect of a capability of a driver, such as a cryptographic operation, a part of a cryptographic operation, or a key management action. These functions are called the **entry points** of the driver. Most driver entry points correspond to a particular function in the PSA Cryptography API. For example, if a call to `psa_sign_hash()` is dispatched to a driver, it invokes the driver's `sign_hash` function.
 
-All driver entry points return a status of type `psa_status_t` which should use the status codes documented for PSA services in general and for PSA Crypto in particular: `PSA_SUCCESS` indicates that the function succeeded, and `PSA_ERROR_xxx` values indicate that an error occurred.
+All driver entry points return a status of type `psa_status_t` which should use the status codes documented for PSA services in general and for PSA Cryptography in particular: `PSA_SUCCESS` indicates that the function succeeded, and `PSA_ERROR_xxx` values indicate that an error occurred.
 
-The signature of a driver entry point generally looks like the signature of the PSA Crypto API that it implements, with some modifications. This section gives an overview of modifications that apply to whole classes of entry points. Refer to the reference section for each entry point or entry point family for details.
+The signature of a driver entry point generally looks like the signature of the PSA Cryptography API that it implements, with some modifications. This section gives an overview of modifications that apply to whole classes of entry points. Refer to the reference section for each entry point or entry point family for details.
 
 * For entry points that operate on an existing key, the `psa_key_id_t` parameter is replaced by a sequence of three parameters that describe the key:
     1. `const psa_key_attributes_t *attributes`: the key attributes.
@@ -148,15 +189,15 @@
 
 * For entry points that involve a multi-part operation, the operation state type (`psa_XXX_operation_t`) is replaced by a driver-specific operation state type (*prefix*`_XXX_operation_t`).
 
-Some entry points are grouped in families that must be implemented as a whole. If a driver supports a entry point family, it must provide all the entry points in the family.
+Some entry points are grouped in families that must be implemented as a whole. If a driver supports an entry point family, it must provide all the entry points in the family.
 
 #### General considerations on driver entry point parameters
 
 Buffer parameters for driver entry points obey the following conventions:
 
 * An input buffer has the type `const uint8_t *` and is immediately followed by a parameter of type `size_t` that indicates the buffer size.
-* An output buffer has the type `uint8_t *` and is immediately followed by a parameter of type `size_t` that indicates the buffer size. A third parameter of type `size_t *` is provided to report the actual buffer size if the function succeeds.
-* An in-out buffer has the type `uint8_t *` and is immediately followed by a parameter of type `size_t` that indicates the buffer size. Note that the buffer size does not change.
+* An output buffer has the type `uint8_t *` and is immediately followed by a parameter of type `size_t` that indicates the buffer size. A third parameter of type `size_t *` is provided to report the actual length of the data written in the buffer if the function succeeds.
+* An in-out buffer has the type `uint8_t *` and is immediately followed by a parameter of type `size_t` that indicates the buffer size. In-out buffers are only used when the input and the output have the same length.
 
 Buffers of size 0 may be represented with either a null pointer or a non-null pointer.
 
@@ -201,15 +242,15 @@
 
 This family applies to transparent drivers only.
 
-This family requires the following type and functions:
+This family requires the following type and entry points:
 
 * Type `"hash_operation_t"`: the type of a hash operation context. It must be possible to copy a hash operation context byte by byte, therefore hash operation contexts must not contain any embedded pointers (except pointers to global data that do not change after the setup step).
 * `"hash_setup"`: called by `psa_hash_setup()`.
 * `"hash_update"`: called by `psa_hash_update()`.
 * `"hash_finish"`: called by `psa_hash_finish()` and `psa_hash_verify()`.
-* `"hash_abort"`: called by all multi-part hash functions.
+* `"hash_abort"`: called by all multi-part hash functions of the PSA Cryptography API.
 
-To verify a hash with `psa_hash_verify()`, the core calls the driver's *prefix`_hash_finish` entry point and compares the result with the reference hash value.
+To verify a hash with `psa_hash_verify()`, the core calls the driver's *prefix*`_hash_finish` entry point and compares the result with the reference hash value.
 
 For example, a driver with the prefix `"acme"` that implements the `"hash_multipart"` entry point family must define the following type and entry points (assuming that the capability does not use the `"names"` property to declare different type and entry point names):
 
@@ -261,7 +302,8 @@
 * `"key_derivation_input_bytes"`: called by `psa_key_derivation_input_bytes()` and `psa_key_derivation_input_key()`. For transparent drivers, when processing a call to `psa_key_derivation_input_key()`, the core always calls the applicable driver's `"key_derivation_input_bytes"` entry point.
 * `"key_derivation_input_key"` (opaque drivers only)
 * `"key_derivation_output_bytes"`: called by `psa_key_derivation_output_bytes()`; also by `psa_key_derivation_output_key()` for transparent drivers.
-* `"key_derivation_abort"`: called by all key derivation functions.
+* `"key_derivation_output_key"`: called by `psa_key_derivation_output_key()` for transparent drivers when deriving an asymmetric key pair, and also for opaque drivers.
+* `"key_derivation_abort"`: called by all key derivation functions of the PSA Cryptography API.
 
 TODO: key input and output for opaque drivers; deterministic key generation for transparent drivers
 
@@ -275,39 +317,43 @@
 
 #### Driver initialization
 
-A driver may declare an `"init"` entry point in a capability with no algorithm, key type or key size. If so, the driver calls this entry point once during the initialization of the PSA Crypto subsystem. If the init entry point of any driver fails, the initialization of the PSA Crypto subsystem fails.
+A driver may declare an `"init"` entry point in a capability with no algorithm, key type or key size. If so, the core calls this entry point once during the initialization of the PSA Cryptography subsystem. If the init entry point of any driver fails, the initialization of the PSA Cryptography subsystem fails.
 
-When multiple drivers have an init entry point, the order in which they are called is unspecified. It is also unspecified whether other drivers' init functions are called if one or more init function fails.
+When multiple drivers have an init entry point, the order in which they are called is unspecified. It is also unspecified whether other drivers' `"init"` entry points are called if one or more init entry point fails.
 
-On platforms where the PSA Crypto implementation is a subsystem of a single application, the initialization of the PSA Crypto subsystem takes place during the call to `psa_crypto_init()`. On platforms where the PSA Crypto implementation is separate from the application or applications, the initialization the initialization of the PSA Crypto subsystem takes place before or during the first time an application calls `psa_crypto_init()`.
+On platforms where the PSA Cryptography implementation is a subsystem of a single application, the initialization of the PSA Cryptography subsystem takes place during the call to `psa_crypto_init()`. On platforms where the PSA Cryptography implementation is separate from the application or applications, the initialization of the PSA Cryptography subsystem takes place before or during the first time an application calls `psa_crypto_init()`.
 
-The init function does not take any parameter.
+The init entry point does not take any parameter.
 
 ### Combining multiple drivers
 
-To declare a cryptoprocessor can handle both cleartext and plaintext keys, you need to provide two driver descriptions, one for a transparent driver and one for an opaque driver. You can use the mapping in capabilities' `"names"` property to arrange for multiple driver entry points to map to the same C function.
+To declare a cryptoprocessor can handle both cleartext and wrapped keys, you need to provide two driver descriptions, one for a transparent driver and one for an opaque driver. You can use the mapping in capabilities' `"names"` property to arrange for multiple driver entry points to map to the same C function.
 
 ## Transparent drivers
 
 ### Key format for transparent drivers
 
-The format of a key for transparent drivers is the same as in applications. Refer to the documentation of `psa_export_key()` and `psa_export_public_key()`.
+The format of a key for transparent drivers is the same as in applications. Refer to the documentation of [`psa_export_key()`](https://armmbed.github.io/mbed-crypto/html/api/keys/management.html#c.psa_export_key) and [`psa_export_public_key()`](https://armmbed.github.io/mbed-crypto/html/api/keys/management.html#c.psa_export_public_key) in the PSA Cryptography API specification. For custom key types defined by an implementation, refer to the documentation of that implementation.
 
 ### Key management with transparent drivers
 
 Transparent drivers may provide the following key management entry points:
 
 * `"generate_key"`: called by `psa_generate_key()`, only when generating a key pair (key such that `PSA_KEY_TYPE_IS_ASYMMETRIC` is true).
-* `"derive_key"`: called by `psa_key_derivation_output_key()`, only when deriving a key pair (key such that `PSA_KEY_TYPE_IS_ASYMMETRIC` is true).
+* `"key_derivation_output_key"`: called by `psa_key_derivation_output_key()`, only when deriving a key pair (key such that `PSA_KEY_TYPE_IS_ASYMMETRIC` is true).
 * `"export_public_key"`: called by the core to obtain the public key of a key pair. The core may call this function at any time to obtain the public key, which can be for `psa_export_public_key()` but also at other times, including during a cryptographic operation that requires the public key such as a call to `psa_verify_message()` on a key pair object.
 
 Transparent drivers are not involved when importing, exporting, copying or destroying keys, or when generating or deriving symmetric keys.
 
 ### Fallback
 
-If a transparent driver entry point is part of a capability which has a true `"fallback"` property and returns `PSA_ERROR_NOT_SUPPORTED`, the built-in software implementation will be called instead. Any other value (`PSA_SUCCESS` or a different error code) is returned to the application.
+Sometimes cryptographic accelerators only support certain cryptographic mechanisms partially. The capability description language allows specifying some restrictions, including restrictions on key sizes, but it cannot cover all the possibilities that may arise in practice. Furthermore, it may be desirable to deploy the same binary image on different devices, only some of which have a cryptographic accelerators.
+For these purposes, a transparent driver can declare that it only supports a [capability](#driver-description-capability) partially, by setting the capability's `"fallback"` property to true.
 
-If there are multiple available transparent drivers, the core tries them in turn until one is declared without a true `"fallback"` property or returns a status other than `PSA_ERROR_NOT_SUPPORTED`. The order in which the drivers are called is unspecified and may be different for different entry points.
+If a transparent driver entry point is part of a capability which has a true `"fallback"` property and returns `PSA_ERROR_NOT_SUPPORTED`, the core will call the next transparent driver that supports the mechanism, if there is one. The core considers drivers in the order given by the [driver description list](#driver-description-list).
+
+If all the available drivers have fallback enabled and return `PSA_ERROR_NOT_SUPPORTED`, the core will perform the operation using built-in code.
+As soon as a driver returns any value other than `PSA_ERROR_NOT_SUPPORTED` (`PSA_SUCCESS` or a different error code), this value is returned to the application, without attempting to call any other driver or built-in code.
 
 If a transparent driver entry point is part of a capability where the `"fallback"` property is false or omitted, the core should not include any other code for this capability, whether built in or in another transparent driver.
 
@@ -379,13 +425,13 @@
 
 ### Key management with opaque drivers
 
-Transparent drivers may provide the following key management entry points:
+Opaque drivers may provide the following key management entry points:
 
 * `"export_key"`: called by `psa_export_key()`, or by `psa_copy_key()` when copying a key from or to a different [location](#lifetimes-and-locations).
 * `"export_public_key"`: called by the core to obtain the public key of a key pair. The core may call this entry point at any time to obtain the public key, which can be for `psa_export_public_key()` but also at other times, including during a cryptographic operation that requires the public key such as a call to `psa_verify_message()` on a key pair object.
 * `"import_key"`: called by `psa_import_key()`, or by `psa_copy_key()` when copying a key from another location.
 * `"generate_key"`: called by `psa_generate_key()`.
-* `"derive_key"`: called by `psa_key_derivation_output_key()`.
+* `"key_derivation_output_key"`: called by `psa_key_derivation_output_key()`.
 * `"copy_key"`: called by `psa_copy_key()` when copying a key within the same [location](#lifetimes-and-locations).
 
 In addition, secure elements that store the key material internally must provide the following two entry points:
@@ -400,7 +446,7 @@
 When creating a key with an opaque driver which does not have an `"allocate_key"` or `"destroy_key"` entry point:
 
 1. The core allocates memory for the key context.
-2. The core calls the driver's import, generate, derive or copy function.
+2. The core calls the driver's import, generate, derive or copy entry point.
 3. The core saves the resulting wrapped key material and any other data that the key context may contain.
 
 To destroy a key, the core simply destroys the wrapped key material, without invoking driver code.
@@ -412,7 +458,7 @@
 * `"allocate_key"`: this function obtains an internal identifier for the key. This may be, for example, a unique label or a slot number.
 * `"destroy_key"`: this function invalidates the internal identifier and destroys the associated key material.
 
-These functions have the following prototypes:
+These functions have the following prototypes for a driver with the prefix `"acme"`:
 ```
 psa_status_t acme_allocate_key(const psa_key_attributes_t *attributes,
                                uint8_t *key_buffer,
@@ -439,7 +485,7 @@
 
 To destroy a key, the core calls the driver's `"destroy_key"` entry point.
 
-Note that the key allocation and destruction entry point must not rely solely on the key identifier in the key attributes to identify a key. Some implementations of the PSA Crypto API store keys on behalf of multiple clients, and different clients may use the same key identifier to designate different keys. The manner in which the core distinguishes keys that have the same identifier but are part of the key namespace for different clients is implementation-dependent and is not accessible to drivers. Some typical strategies to allocate an internal key identifier are:
+Note that the key allocation and destruction entry points must not rely solely on the key identifier in the key attributes to identify a key. Some implementations of the PSA Cryptography API store keys on behalf of multiple clients, and different clients may use the same key identifier to designate different keys. The manner in which the core distinguishes keys that have the same identifier but are part of the key namespace for different clients is implementation-dependent and is not accessible to drivers. Some typical strategies to allocate an internal key identifier are:
 
 * Maintain a set of free slot numbers which is stored either in the secure element or in the driver's persistent storage. To allocate a key slot, find a free slot number, mark it as occupied and store the number in the key context. When the key is destroyed, mark the slot number as free.
 * Maintain a monotonic counter with a practically unbounded range in the secure element or in the driver's persistent storage. To allocate a key slot, increment the counter and store the current value in the key context. Destroying a key does not change the counter.
@@ -450,7 +496,7 @@
 
 #### Key creation entry points in opaque drivers
 
-The key creation entry points have the following prototypes:
+The key creation entry points have the following prototypes for a driver with the prefix `"acme"`:
 
 ```
 psa_status_t acme_import_key(const psa_key_attributes_t *attributes,
@@ -463,13 +509,13 @@
                                size_t key_buffer_size);
 ```
 
-If the driver has an [`"allocate_key"` entry point](#key-management-in-a-secure-element-with-storage), the core calls the `"allocate_key"` entry point with the same attributes on the same key buffer before calling the key creation function.
+If the driver has an [`"allocate_key"` entry point](#key-management-in-a-secure-element-with-storage), the core calls the `"allocate_key"` entry point with the same attributes on the same key buffer before calling the key creation entry point.
 
 TODO: derivation, copy
 
 #### Key export entry points in opaque drivers
 
-The key export entry points have the following prototypes:
+The key export entry points have the following prototypes for a driver with the prefix `"acme"`:
 
 ```
 psa_status_t acme_export_key(const psa_key_attributes_t *attributes,
@@ -524,7 +570,7 @@
 
 Each opaque driver is assigned a [location](#lifetimes-and-locations). The driver is invoked for all actions that use a key in that location. A key's location is indicated by its lifetime. The application chooses the key's lifetime when it creates the key.
 
-For example, the following snippet creates an AES-GCM key which is only accessible inside a secure element.
+For example, the following snippet creates an AES-GCM key which is only accessible inside the secure element designated by the location `PSA_KEY_LOCATION_acme`.
 ```
 psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
@@ -574,9 +620,9 @@
 
 ### Driver declarations
 
-#### Declaring driver functions
+#### Declaring driver entry points
 
-The core may want to provide declarations for the driver functions so that it can compile code using them. At the time of writing this paragraph, the driver headers must define types but there is no obligation for them to declare functions. The core knows what the function names and argument types are, so it can generate prototypes.
+The core may want to provide declarations for the driver entry points so that it can compile code using them. At the time of writing this paragraph, the driver headers must define types but there is no obligation for them to declare functions. The core knows what the function names and argument types are, so it can generate prototypes.
 
 It should be ok for driver functions to be function-like macros or function pointers.
 
@@ -586,6 +632,14 @@
 
 Can the driver assembly process generate distinct location values as needed? This can be convenient, but it's also risky: if you upgrade a device, you need the location values to be the same between builds.
 
+The current plan is for Arm to maintain a registry of vendors and assign a location namespace to each vendor. Parts of the namespace would be reserved for implementations and integrators.
+
+#### Multiple transparent drivers
+
+When multiple transparent drivers implement the same mechanism, which one is called? The first one? The last one? Unspecified? Or is this an error (excluding capabilities with fallback enabled)?
+
+The current choice is that the first one is used, which allows having a preference order on drivers, but may mask integration errors.
+
 ### Driver function interfaces
 
 #### Driver function parameter conventions
diff --git a/include/mbedtls/bignum.h b/include/mbedtls/bignum.h
index 0d019b9..637360e 100644
--- a/include/mbedtls/bignum.h
+++ b/include/mbedtls/bignum.h
@@ -61,12 +61,12 @@
  * Maximum window size used for modular exponentiation. Default: 6
  * Minimum value: 1. Maximum value: 6.
  *
- * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used
+ * Result is an array of ( 2 ** MBEDTLS_MPI_WINDOW_SIZE ) MPIs used
  * for the sliding window calculation. (So 64 by default)
  *
  * Reduction in size, reduces speed.
  */
-#define MBEDTLS_MPI_WINDOW_SIZE                           6        /**< Maximum windows size used. */
+#define MBEDTLS_MPI_WINDOW_SIZE                           6        /**< Maximum window size used. */
 #endif /* !MBEDTLS_MPI_WINDOW_SIZE */
 
 #if !defined(MBEDTLS_MPI_MAX_SIZE)
diff --git a/include/mbedtls/ccm.h b/include/mbedtls/ccm.h
index 81965ba..7193863 100644
--- a/include/mbedtls/ccm.h
+++ b/include/mbedtls/ccm.h
@@ -148,7 +148,7 @@
  *                  than zero, \p output must be a writable buffer of at least
  *                  that length.
  * \param tag       The buffer holding the authentication field. This must be a
- *                  readable buffer of at least \p tag_len Bytes.
+ *                  writable buffer of at least \p tag_len Bytes.
  * \param tag_len   The length of the authentication field to generate in Bytes:
  *                  4, 6, 8, 10, 12, 14 or 16.
  *
@@ -193,7 +193,7 @@
  *                  than zero, \p output must be a writable buffer of at least
  *                  that length.
  * \param tag       The buffer holding the authentication field. This must be a
- *                  readable buffer of at least \p tag_len Bytes.
+ *                  writable buffer of at least \p tag_len Bytes.
  * \param tag_len   The length of the authentication field to generate in Bytes:
  *                  0, 4, 6, 8, 10, 12, 14 or 16.
  *
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index 014786a..8827e0b 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -227,10 +227,30 @@
 };
 
 /** Maximum length of any IV, in Bytes. */
+/* This should ideally be derived automatically from list of ciphers.
+ * This should be kept in sync with MBEDTLS_SSL_MAX_IV_LENGTH defined
+ * in ssl_internal.h. */
 #define MBEDTLS_MAX_IV_LENGTH      16
+
 /** Maximum block size of any cipher, in Bytes. */
+/* This should ideally be derived automatically from list of ciphers.
+ * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined
+ * in ssl_internal.h. */
 #define MBEDTLS_MAX_BLOCK_LENGTH   16
 
+/** Maximum key length, in Bytes. */
+/* This should ideally be derived automatically from list of ciphers.
+ * For now, only check whether XTS is enabled which uses 64 Byte keys,
+ * and use 32 Bytes as an upper bound for the maximum key length otherwise.
+ * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined
+ * in ssl_internal.h, which however deliberately ignores the case of XTS
+ * since the latter isn't used in SSL/TLS. */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+#define MBEDTLS_MAX_KEY_LENGTH     64
+#else
+#define MBEDTLS_MAX_KEY_LENGTH     32
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
 /**
  * Base cipher information (opaque struct).
  */
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 1e6e052..b77b34b 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -1258,20 +1258,17 @@
  */
 //#define MBEDTLS_ENTROPY_NV_SEED
 
-/* MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
+/* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
  *
- * In PSA key storage, encode the owner of the key.
+ * Enable key identifiers that encode a key owner identifier.
  *
- * This is only meaningful when building the library as part of a
- * multi-client service. When you activate this option, you must provide
- * an implementation of the type psa_key_owner_id_t and a translation
- * from psa_key_file_id_t to file name in all the storage backends that
- * you wish to support.
+ * The owner of a key is identified by a value of type ::mbedtls_key_owner_id_t
+ * 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.
  */
-//#define MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
+//#define MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
 
 /**
  * \def MBEDTLS_MEMORY_DEBUG
@@ -1329,6 +1326,17 @@
  */
 #define MBEDTLS_PKCS1_V21
 
+/** \def MBEDTLS_PSA_CRYPTO_DRIVERS
+ *
+ * Enable support for the experimental PSA crypto driver interface.
+ *
+ * Requires: MBEDTLS_PSA_CRYPTO_C.
+ *
+ * \warning This interface is experimental and may change or be removed
+ * without notice.
+ */
+//#define MBEDTLS_PSA_CRYPTO_DRIVERS
+
 /**
  * \def MBEDTLS_PSA_CRYPTO_SPM
  *
@@ -3450,7 +3458,7 @@
  */
 
 /* MPI / BIGNUM options */
-//#define MBEDTLS_MPI_WINDOW_SIZE            6 /**< Maximum windows size used. */
+//#define MBEDTLS_MPI_WINDOW_SIZE            6 /**< Maximum window size used. */
 //#define MBEDTLS_MPI_MAX_SIZE            1024 /**< Maximum number of bytes for usable MPIs. */
 
 /* CTR_DRBG options */
diff --git a/include/mbedtls/gcm.h b/include/mbedtls/gcm.h
index ed23cb9..6b67361 100644
--- a/include/mbedtls/gcm.h
+++ b/include/mbedtls/gcm.h
@@ -155,7 +155,7 @@
  *                  than zero, this must be a writable buffer of at least that
  *                  size in Bytes.
  * \param tag_len   The length of the tag to generate.
- * \param tag       The buffer for holding the tag. This must be a readable
+ * \param tag       The buffer for holding the tag. This must be a writable
  *                  buffer of at least \p tag_len Bytes.
  *
  * \return          \c 0 if the encryption or decryption was performed
@@ -283,7 +283,7 @@
  *                  tag. The tag can have a maximum length of 16 Bytes.
  *
  * \param ctx       The GCM context. This must be initialized.
- * \param tag       The buffer for holding the tag. This must be a readable
+ * \param tag       The buffer for holding the tag. This must be a writable
  *                  buffer of at least \p tag_len Bytes.
  * \param tag_len   The length of the tag to generate. This must be at least
  *                  four.
diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h
index 3c03706..d8a32c5 100644
--- a/include/mbedtls/psa_util.h
+++ b/include/mbedtls/psa_util.h
@@ -83,6 +83,8 @@
 {
     switch( mode )
     {
+        case MBEDTLS_MODE_ECB:
+            return( PSA_ALG_ECB_NO_PADDING );
         case MBEDTLS_MODE_GCM:
             return( PSA_ALG_AEAD_WITH_TAG_LENGTH( PSA_ALG_GCM, taglen ) );
         case MBEDTLS_MODE_CCM:
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index f086bdf..a091261 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1559,7 +1559,7 @@
  * \note           For DTLS, you need to provide either a non-NULL
  *                 f_recv_timeout callback, or a f_recv that doesn't block.
  *
- * \note           See the documentations of \c mbedtls_ssl_sent_t,
+ * \note           See the documentations of \c mbedtls_ssl_send_t,
  *                 \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for
  *                 the conventions those callbacks must follow.
  *
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index b3d53d3..7b78c73 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -378,6 +378,49 @@
                                      const char *label,
                                      const unsigned char *random, size_t rlen,
                                      unsigned char *dstbuf, size_t dlen );
+
+/* cipher.h exports the maximum IV, key and block length from
+ * all ciphers enabled in the config, regardless of whether those
+ * ciphers are actually usable in SSL/TLS. Notably, XTS is enabled
+ * in the default configuration and uses 64 Byte keys, but it is
+ * not used for record protection in SSL/TLS.
+ *
+ * In order to prevent unnecessary inflation of key structures,
+ * we introduce SSL-specific variants of the max-{key,block,IV}
+ * macros here which are meant to only take those ciphers into
+ * account which can be negotiated in SSL/TLS.
+ *
+ * Since the current definitions of MBEDTLS_MAX_{KEY|BLOCK|IV}_LENGTH
+ * in cipher.h are rough overapproximations of the real maxima, here
+ * we content ourselves with replicating those overapproximations
+ * for the maximum block and IV length, and excluding XTS from the
+ * computation of the maximum key length. */
+#define MBEDTLS_SSL_MAX_BLOCK_LENGTH 16
+#define MBEDTLS_SSL_MAX_IV_LENGTH    16
+#define MBEDTLS_SSL_MAX_KEY_LENGTH   32
+
+/**
+ * \brief   The data structure holding the cryptographic material (key and IV)
+ *          used for record protection in TLS 1.3.
+ */
+struct mbedtls_ssl_key_set
+{
+    /*! The key for client->server records. */
+    unsigned char client_write_key[ MBEDTLS_SSL_MAX_KEY_LENGTH ];
+    /*! The key for server->client records. */
+    unsigned char server_write_key[ MBEDTLS_SSL_MAX_KEY_LENGTH ];
+    /*! The IV  for client->server records. */
+    unsigned char client_write_iv[ MBEDTLS_SSL_MAX_IV_LENGTH ];
+    /*! The IV  for server->client records. */
+    unsigned char server_write_iv[ MBEDTLS_SSL_MAX_IV_LENGTH ];
+
+    size_t key_len; /*!< The length of client_write_key and
+                     *   server_write_key, in Bytes. */
+    size_t iv_len;  /*!< The length of client_write_iv and
+                     *   server_write_iv, in Bytes. */
+};
+typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set;
+
 /*
  * This structure contains the parameters only needed during handshake.
  */
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index a316166..5ba16b9 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -146,11 +146,11 @@
  * linkage). This function may be provided as a function-like macro,
  * but in this case it must evaluate each of its arguments exactly once.
  *
- * \param[out] attributes       The attribute structure to write to.
- * \param id                    The persistent identifier for the key.
+ * \param[out] attributes  The attribute structure to write to.
+ * \param key              The persistent identifier for the key.
  */
-static void psa_set_key_id(psa_key_attributes_t *attributes,
-                           psa_key_id_t id);
+static void psa_set_key_id( psa_key_attributes_t *attributes,
+                            mbedtls_svc_key_id_t key );
 
 /** Set the location of a persistent key.
  *
@@ -192,7 +192,8 @@
  *         This value is unspecified if the attribute structure declares
  *         the key as volatile.
  */
-static psa_key_id_t psa_get_key_id(const psa_key_attributes_t *attributes);
+static mbedtls_svc_key_id_t psa_get_key_id(
+    const psa_key_attributes_t *attributes);
 
 /** Retrieve the lifetime from key attributes.
  *
@@ -392,8 +393,9 @@
  * 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 a key identifier
- * in the vendor range, as documented in the description of #psa_key_id_t.
+ * 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
@@ -408,7 +410,7 @@
  * portable to implementations that only permit a single key handle to be
  * opened. See also :ref:\`key-handles\`.
  *
- * \param id            The persistent identifier of the key.
+ * \param key           The persistent identifier of the key.
  * \param[out] handle   On success, a handle to the key.
  *
  * \retval #PSA_SUCCESS
@@ -436,9 +438,8 @@
  *         It is implementation-dependent whether a failure to initialize
  *         results in this error code.
  */
-psa_status_t psa_open_key(psa_key_id_t id,
-                          psa_key_handle_t *handle);
-
+psa_status_t psa_open_key( mbedtls_svc_key_id_t key,
+                           psa_key_handle_t *handle );
 
 /** Close a key handle.
  *
diff --git a/include/psa/crypto_extra.h b/include/psa/crypto_extra.h
index f0c7979..71adb93 100644
--- a/include/psa/crypto_extra.h
+++ b/include/psa/crypto_extra.h
@@ -232,9 +232,9 @@
     /** Number of slots that are not used for anything. */
     size_t empty_slots;
     /** Largest key id value among open keys in internal persistent storage. */
-    psa_app_key_id_t max_open_internal_key_id;
+    psa_key_id_t max_open_internal_key_id;
     /** Largest key id value among open keys in secure elements. */
-    psa_app_key_id_t max_open_external_key_id;
+    psa_key_id_t max_open_external_key_id;
 } mbedtls_psa_stats_t;
 
 /** \brief Get statistics about
diff --git a/include/psa/crypto_platform.h b/include/psa/crypto_platform.h
index 77c0e5b..c64f61d 100644
--- a/include/psa/crypto_platform.h
+++ b/include/psa/crypto_platform.h
@@ -44,57 +44,40 @@
 /* PSA requires several types which C99 provides in stdint.h. */
 #include <stdint.h>
 
+#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
+    !defined(inline) && !defined(__cplusplus)
+#define inline __inline
+#endif
+
 /* Integral type representing a key handle. */
 typedef uint16_t psa_key_handle_t;
 
-/* This implementation distinguishes *application key identifiers*, which
- * are the key identifiers specified by the application, from
- * *key file identifiers*, which are the key identifiers that the library
- * sees internally. The two types can be different if there is a remote
- * call layer between the application and the library which supports
- * multiple client applications that do not have access to each others'
- * keys. The point of having different types is that the key file
- * identifier may encode not only the key identifier specified by the
- * application, but also the the identity of the application.
+#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
+ * partition identifier.
  *
- * Note that this is an internal concept of the library and the remote
- * call layer. The application itself never sees anything other than
- * #psa_app_key_id_t with its standard definition.
+ * The function psa_its_identifier_of_slot() in psa_crypto_storage.c that
+ * translates a key identifier to a key storage file name assumes that
+ * mbedtls_key_owner_id_t is an 32 bits integer. This function thus needs
+ * reworking if mbedtls_key_owner_id_t is not defined as a 32 bits integer
+ * here anymore.
  */
+typedef int32_t mbedtls_key_owner_id_t;
 
-/* The application key identifier is always what the application sees as
- * #psa_key_id_t. */
-typedef uint32_t psa_app_key_id_t;
-
-#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER)
-
-#if defined(PSA_CRYPTO_SECURE)
-/* Building for the PSA Crypto service on a PSA platform. */
-/* A key owner is a PSA partition identifier. */
-typedef int32_t psa_key_owner_id_t;
-#endif
-
-typedef struct
+/** Compare two key owner identifiers.
+ *
+ * \param id1 First key owner identifier.
+ * \param id2 Second key owner identifier.
+ *
+ * \return Non-zero if the two key owner identifiers are equal, zero otherwise.
+ */
+static inline int mbedtls_key_owner_id_equal( mbedtls_key_owner_id_t id1,
+                                              mbedtls_key_owner_id_t id2 )
 {
-    uint32_t key_id;
-    psa_key_owner_id_t owner;
-} psa_key_file_id_t;
-#define PSA_KEY_FILE_GET_KEY_ID( file_id ) ( ( file_id ).key_id )
+    return( id1 == id2 );
+}
 
-/* Since crypto.h is used as part of the PSA Cryptography API specification,
- * it must use standard types for things like the argument of psa_open_key().
- * If it wasn't for that constraint, psa_open_key() would take a
- * `psa_key_file_id_t` argument. As a workaround, make `psa_key_id_t` an
- * alias for `psa_key_file_id_t` when building for a multi-client service. */
-typedef psa_key_file_id_t psa_key_id_t;
-#define PSA_KEY_ID_INIT {0, 0}
-
-#else /* !MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER */
-
-/* By default, a key file identifier is just the application key identifier. */
-typedef psa_app_key_id_t psa_key_file_id_t;
-#define PSA_KEY_FILE_GET_KEY_ID( id ) ( id )
-
-#endif /* !MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER */
+#endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
 
 #endif /* PSA_CRYPTO_PLATFORM_H */
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index 67c53db..be0e280 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -77,6 +77,16 @@
 #include "mbedtls/sha256.h"
 #include "mbedtls/sha512.h"
 
+typedef struct {
+    /** Unique ID indicating which driver got assigned to do the
+     * operation. Since driver contexts are driver-specific, swapping
+     * drivers halfway through the operation is not supported.
+     * ID values are auto-generated in psa_driver_wrappers.h */
+    unsigned int id;
+    /** Context structure for the assigned driver, when id is not zero. */
+    void* ctx;
+} psa_operation_driver_context_t;
+
 struct psa_hash_operation_s
 {
     psa_algorithm_t alg;
@@ -158,16 +168,18 @@
     unsigned int key_set : 1;
     unsigned int iv_required : 1;
     unsigned int iv_set : 1;
+    unsigned int mbedtls_in_use : 1; /* Indicates mbed TLS is handling the operation. */
     uint8_t iv_size;
     uint8_t block_size;
     union
     {
         unsigned dummy; /* Enable easier initializing of the union. */
         mbedtls_cipher_context_t cipher;
+        psa_operation_driver_context_t driver;
     } ctx;
 };
 
-#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, {0}}
+#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, {0}}
 static inline struct psa_cipher_operation_s psa_cipher_operation_init( void )
 {
     const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT;
@@ -330,12 +342,12 @@
     psa_key_type_t type;
     psa_key_bits_t bits;
     psa_key_lifetime_t lifetime;
-    psa_key_id_t id;
+    mbedtls_svc_key_id_t id;
     psa_key_policy_t policy;
     psa_key_attributes_flag_t flags;
 } psa_core_key_attributes_t;
 
-#define PSA_CORE_KEY_ATTRIBUTES_INIT {PSA_KEY_TYPE_NONE, 0, PSA_KEY_LIFETIME_VOLATILE, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0}
+#define PSA_CORE_KEY_ATTRIBUTES_INIT {PSA_KEY_TYPE_NONE, 0, PSA_KEY_LIFETIME_VOLATILE, MBEDTLS_SVC_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0}
 
 struct psa_key_attributes_s
 {
@@ -359,15 +371,15 @@
     return( v );
 }
 
-static inline void psa_set_key_id(psa_key_attributes_t *attributes,
-                                  psa_key_id_t id)
+static inline void psa_set_key_id( psa_key_attributes_t *attributes,
+                                   mbedtls_svc_key_id_t key )
 {
-    attributes->core.id = id;
+    attributes->core.id = key;
     if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE )
         attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
 }
 
-static inline psa_key_id_t psa_get_key_id(
+static inline mbedtls_svc_key_id_t psa_get_key_id(
     const psa_key_attributes_t *attributes)
 {
     return( attributes->core.id );
@@ -379,9 +391,8 @@
     attributes->core.lifetime = lifetime;
     if( lifetime == PSA_KEY_LIFETIME_VOLATILE )
     {
-#ifdef MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER
+#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
         attributes->core.id.key_id = 0;
-        attributes->core.id.owner = 0;
 #else
         attributes->core.id = 0;
 #endif
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index 17718eb..923b02b 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -33,6 +33,8 @@
 #ifndef PSA_CRYPTO_TYPES_H
 #define PSA_CRYPTO_TYPES_H
 
+#include "crypto_platform.h"
+
 #include <stdint.h>
 
 /** \defgroup error Error codes
@@ -123,7 +125,7 @@
  * implementation-specific device management event occurs (for example,
  * a factory reset).
  *
- * Persistent keys have a key identifier of type #psa_key_id_t.
+ * Persistent keys have a key identifier of type #mbedtls_svc_key_id_t.
  * This identifier remains valid throughout the lifetime of the key,
  * even if the application instance that created the key terminates.
  * The application can call psa_open_key() to open a persistent key that
@@ -226,15 +228,24 @@
  * - 0 is reserved as an invalid key identifier.
  * - Key identifiers outside these ranges are reserved for future use.
  */
-/* Implementation-specific quirk: The Mbed Crypto library can be built as
- * part of a multi-client service that exposes the PSA Crypto API in each
- * client and encodes the client identity in the key id argument of functions
- * such as psa_open_key(). In this build configuration, we define
- * psa_key_id_t in crypto_platform.h instead of here. */
-#if !defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER)
 typedef uint32_t psa_key_id_t;
-#define PSA_KEY_ID_INIT 0
-#endif
+
+#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+typedef psa_key_id_t mbedtls_svc_key_id_t;
+
+#else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
+/* Implementation-specific: The Mbed Cryptography library can be built as
+ * part of a multi-client service that exposes the PSA Cryptograpy API in each
+ * client and encodes the client identity in the key identifier argument of
+ * functions such as psa_open_key().
+ */
+typedef struct
+{
+    psa_key_id_t key_id;
+    mbedtls_key_owner_id_t owner;
+} mbedtls_svc_key_id_t;
+
+#endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
 
 /**@}*/
 
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index a940711..3eb64d8 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -978,6 +978,26 @@
  */
 #define PSA_ALG_XTS                             ((psa_algorithm_t)0x044000ff)
 
+/** The Electronic Code Book (ECB) mode of a block cipher, with no padding.
+ *
+ * \warning ECB mode does not protect the confidentiality of the encrypted data
+ * except in extremely narrow circumstances. It is recommended that applications
+ * only use ECB if they need to construct an operating mode that the
+ * implementation does not provide. Implementations are encouraged to provide
+ * the modes that applications need in preference to supporting direct access
+ * to ECB.
+ *
+ * The underlying block cipher is determined by the key type.
+ *
+ * This symmetric cipher mode can only be used with messages whose lengths are a
+ * multiple of the block size of the chosen block cipher.
+ *
+ * ECB mode does not accept an initialization vector (IV). When using a
+ * multi-part cipher operation with this algorithm, psa_cipher_generate_iv()
+ * and psa_cipher_set_iv() must not be called.
+ */
+#define PSA_ALG_ECB_NO_PADDING                  ((psa_algorithm_t)0x04404400)
+
 /** The CBC block cipher chaining mode, with no padding.
  *
  * The underlying block cipher is determined by the key type.
@@ -1636,16 +1656,83 @@
 
 /** The minimum value for a key identifier chosen by the application.
  */
-#define PSA_KEY_ID_USER_MIN                     ((psa_app_key_id_t)0x00000001)
+#define PSA_KEY_ID_USER_MIN                     ((psa_key_id_t)0x00000001)
 /** The maximum value for a key identifier chosen by the application.
  */
-#define PSA_KEY_ID_USER_MAX                     ((psa_app_key_id_t)0x3fffffff)
+#define PSA_KEY_ID_USER_MAX                     ((psa_key_id_t)0x3fffffff)
 /** The minimum value for a key identifier chosen by the implementation.
  */
-#define PSA_KEY_ID_VENDOR_MIN                   ((psa_app_key_id_t)0x40000000)
+#define PSA_KEY_ID_VENDOR_MIN                   ((psa_key_id_t)0x40000000)
 /** The maximum value for a key identifier chosen by the implementation.
  */
-#define PSA_KEY_ID_VENDOR_MAX                   ((psa_app_key_id_t)0x7fffffff)
+#define PSA_KEY_ID_VENDOR_MAX                   ((psa_key_id_t)0x7fffffff)
+
+
+#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+
+#define MBEDTLS_SVC_KEY_ID_INIT ( (psa_key_id_t)0 )
+#define MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ( id )
+#define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( id ) ( 0 )
+
+/** Utility to initialize a key identifier at runtime.
+ *
+ * \param unused  Unused parameter.
+ * \param key_id  Identifier of the key.
+ */
+static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make(
+    unsigned int unused, psa_key_id_t key_id )
+{
+    (void)unused;
+
+    return( key_id );
+}
+
+/** Compare two key identifiers.
+ *
+ * \param id1 First key identifier.
+ * \param id2 Second key identifier.
+ *
+ * \return Non-zero if the two key identifier are equal, zero otherwise.
+ */
+static inline int mbedtls_svc_key_id_equal( mbedtls_svc_key_id_t id1,
+                                            mbedtls_svc_key_id_t id2 )
+{
+    return( id1 == id2 );
+}
+
+#else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
+
+#define MBEDTLS_SVC_KEY_ID_INIT ( (mbedtls_svc_key_id_t){ 0, 0 } )
+#define MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ( ( id ).key_id )
+#define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( id ) ( ( id ).owner )
+
+/** Utility to initialize a key identifier at runtime.
+ *
+ * \param owner_id Identifier of the key owner.
+ * \param key_id   Identifier of the key.
+ */
+static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make(
+    mbedtls_key_owner_id_t owner_id, psa_key_id_t key_id )
+{
+    return( (mbedtls_svc_key_id_t){ .key_id = key_id,
+                                    .owner = owner_id } );
+}
+
+/** Compare two key identifiers.
+ *
+ * \param id1 First key identifier.
+ * \param id2 Second key identifier.
+ *
+ * \return Non-zero if the two key identifier are equal, zero otherwise.
+ */
+static inline int mbedtls_svc_key_id_equal( mbedtls_svc_key_id_t id1,
+                                            mbedtls_svc_key_id_t id2 )
+{
+    return( ( id1.key_id == id2.key_id ) &&
+            mbedtls_key_owner_id_equal( id1.owner, id2.owner ) );
+}
+
+#endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
 
 /**@}*/
 
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index 33e2cfc..4444b98 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -61,6 +61,7 @@
     platform_util.c
     poly1305.c
     psa_crypto.c
+    psa_crypto_driver_wrappers.c
     psa_crypto_se.c
     psa_crypto_slot_management.c
     psa_crypto_storage.c
@@ -103,6 +104,7 @@
     ssl_srv.c
     ssl_ticket.c
     ssl_tls.c
+    ssl_tls13_keys.c
 )
 
 if(CMAKE_COMPILER_IS_GNUCC)
diff --git a/library/Makefile b/library/Makefile
index b76a84b..a6db9b3 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -118,6 +118,7 @@
 	     platform_util.o \
 	     poly1305.o \
 	     psa_crypto.o \
+	     psa_crypto_driver_wrappers.o \
 	     psa_crypto_se.o \
 	     psa_crypto_slot_management.o \
 	     psa_crypto_storage.o \
@@ -162,6 +163,7 @@
 	  ssl_srv.o \
 	  ssl_ticket.o \
 	  ssl_tls.o \
+	  ssl_tls13_keys.o \
 	  # This line is intentionally left blank
 
 .SILENT:
diff --git a/library/bignum.c b/library/bignum.c
index 9325632..fa97d19 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -2101,7 +2101,7 @@
     size_t i, j, nblimbs;
     size_t bufsize, nbits;
     mbedtls_mpi_uint ei, mm, state;
-    mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
+    mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], Apos;
     int neg;
 
     MPI_VALIDATE_RET( X != NULL );
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index 4bf660e..0f992f3 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -18,9 +18,15 @@
  */
 
 #if defined(__linux__)
+#if !defined(_GNU_SOURCE)
 /* Ensure that syscall() is available even when compiling with -std=c99 */
 #define _GNU_SOURCE
 #endif
+#include <features.h>
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)
+#define HAVE_SYS_RANDOM 1
+#endif
+#endif
 
 #include "common.h"
 
@@ -86,10 +92,16 @@
 
 /*
  * Test for Linux getrandom() support.
- * Since there is no wrapper in the libc yet, use the generic syscall wrapper
+ * When the C library is GNU libc and its version is greater than 2.25,
+ * include sys/random.h to use getrandom(),
+ * otherwise use the generic use the generic syscall wrapper
  * available in GNU libc and compatible libc's (eg uClibc).
  */
-#if ((defined(__linux__) && defined(__GLIBC__)) || defined(__midipix__))
+#if HAVE_SYS_RANDOM
+#include <sys/random.h>
+#include <errno.h>
+#define HAVE_GETRANDOM
+#elif (defined(__linux__) && defined(__GLIBC__)) || defined(__midipix__)
 #include <unistd.h>
 #include <sys/syscall.h>
 #if defined(SYS_getrandom)
@@ -155,7 +167,11 @@
     ((void) data);
 
 #if defined(HAVE_GETRANDOM)
+#if HAVE_SYS_RANDOM
+    ret = getrandom(output, len, 0);
+#else
     ret = getrandom_wrapper( output, len, 0 );
+#endif
     if( ret >= 0 )
     {
         *olen = ret;
diff --git a/library/md2.c b/library/md2.c
index 5ebf072..b4f7cc6 100644
--- a/library/md2.c
+++ b/library/md2.c
@@ -287,8 +287,7 @@
     { "message digest" },
     { "abcdefghijklmnopqrstuvwxyz" },
     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
-    { "12345678901234567890123456789012345678901234567890123456789012"
-      "345678901234567890" }
+    { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
 };
 
 static const size_t md2_test_strlen[7] =
diff --git a/library/md4.c b/library/md4.c
index ac95074..1cac0a4 100644
--- a/library/md4.c
+++ b/library/md4.c
@@ -408,8 +408,7 @@
     { "message digest" },
     { "abcdefghijklmnopqrstuvwxyz" },
     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
-    { "12345678901234567890123456789012345678901234567890123456789012"
-      "345678901234567890" }
+    { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
 };
 
 static const size_t md4_test_strlen[7] =
diff --git a/library/md5.c b/library/md5.c
index 8cea902..1e702b4 100644
--- a/library/md5.c
+++ b/library/md5.c
@@ -422,8 +422,7 @@
     { "message digest" },
     { "abcdefghijklmnopqrstuvwxyz" },
     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
-    { "12345678901234567890123456789012345678901234567890123456789012"
-      "345678901234567890" }
+    { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
 };
 
 static const size_t md5_test_buflen[7] =
diff --git a/library/pk.c b/library/pk.c
index 8ffbed2..9a3bcb0 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -591,6 +591,9 @@
                                psa_algorithm_t hash_alg )
 {
 #if !defined(MBEDTLS_ECP_C)
+    ((void) pk);
+    ((void) handle);
+    ((void) hash_alg);
     return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
 #else
     const mbedtls_ecp_keypair *ec;
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index 6bf3169..903c53b 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -551,11 +551,12 @@
     unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES];
     unsigned char *p;
     mbedtls_pk_info_t pk_info = mbedtls_eckey_info;
-    psa_algorithm_t psa_sig_md, psa_md;
+    psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY;
     size_t curve_bits;
     psa_ecc_family_t curve =
         mbedtls_ecc_group_to_psa( ctx->grp.id, &curve_bits );
     const size_t signature_part_size = ( ctx->grp.nbits + 7 ) / 8;
+    ((void) md_alg);
 
     if( curve == 0 )
         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
@@ -569,11 +570,6 @@
     if( key_len <= 0 )
         return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
 
-    psa_md = mbedtls_psa_translate_md( md_alg );
-    if( psa_md == 0 )
-        return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
-    psa_sig_md = PSA_ALG_ECDSA( psa_md );
-
     psa_set_key_type( &attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY( curve ) );
     psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH );
     psa_set_key_algorithm( &attributes, psa_sig_md );
@@ -910,6 +906,8 @@
             type == MBEDTLS_PK_ECDSA );
 }
 
+#if defined(MBEDTLS_ECDSA_C)
+
 /*
  * Simultaneously convert and move raw MPI from the beginning of a buffer
  * to an ASN.1 MPI at the end of the buffer.
@@ -992,11 +990,24 @@
     return( 0 );
 }
 
+#endif /* MBEDTLS_ECDSA_C */
+
 static int pk_opaque_sign_wrap( void *ctx, mbedtls_md_type_t md_alg,
                    const unsigned char *hash, size_t hash_len,
                    unsigned char *sig, size_t *sig_len,
                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
 {
+#if !defined(MBEDTLS_ECDSA_C)
+    ((void) ctx);
+    ((void) md_alg);
+    ((void) hash);
+    ((void) hash_len);
+    ((void) sig);
+    ((void) sig_len);
+    ((void) f_rng);
+    ((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;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_algorithm_t alg = PSA_ALG_ECDSA( mbedtls_psa_translate_md( md_alg ) );
@@ -1027,6 +1038,7 @@
 
     /* transcode it to ASN.1 sequence */
     return( pk_ecdsa_sig_asn1_from_psa( sig, sig_len, buf_len ) );
+#endif /* !MBEDTLS_ECDSA_C */
 }
 
 const mbedtls_pk_info_t mbedtls_pk_opaque_info = {
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/psa_crypto.c b/library/psa_crypto.c
index bffddc9..931e2e9 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -27,6 +27,7 @@
 
 #include "psa_crypto_core.h"
 #include "psa_crypto_invasive.h"
+#include "psa_crypto_driver_wrappers.h"
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
 #include "psa_crypto_se.h"
 #endif
@@ -124,7 +125,7 @@
     if( global_data.initialized == 0 )  \
         return( PSA_ERROR_BAD_STATE );
 
-static psa_status_t mbedtls_to_psa_error( int ret )
+psa_status_t mbedtls_to_psa_error( int ret )
 {
     /* If there's both a high-level code and low-level code, dispatch on
      * the high-level code. */
@@ -2751,6 +2752,9 @@
             case PSA_ALG_OFB:
                 mode = MBEDTLS_MODE_OFB;
                 break;
+            case PSA_ALG_ECB_NO_PADDING:
+                mode = MBEDTLS_MODE_ECB;
+                break;
             case PSA_ALG_CBC_NO_PADDING:
                 mode = MBEDTLS_MODE_CBC;
                 break;
@@ -3637,10 +3641,6 @@
 {
     psa_key_slot_t *slot;
     psa_status_t status;
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    const psa_drv_se_t *drv;
-    psa_drv_se_context_t *drv_context;
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     *signature_length = signature_size;
     /* Immediately reject a zero-length signature buffer. This guarantees
@@ -3659,24 +3659,19 @@
         goto exit;
     }
 
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) )
-    {
-        if( drv->asymmetric == NULL ||
-            drv->asymmetric->p_sign == NULL )
-        {
-            status = PSA_ERROR_NOT_SUPPORTED;
-            goto exit;
-        }
-        status = drv->asymmetric->p_sign( drv_context,
-                                          slot->data.se.slot_number,
-                                          alg,
-                                          hash, hash_length,
-                                          signature, signature_size,
-                                          signature_length );
-    }
-    else
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+    /* Try any of the available accelerators first */
+    status = psa_driver_wrapper_sign_hash( slot,
+                                           alg,
+                                           hash,
+                                           hash_length,
+                                           signature,
+                                           signature_size,
+                                           signature_length );
+    if( status != PSA_ERROR_NOT_SUPPORTED ||
+        psa_key_lifetime_is_external( slot->attr.lifetime ) )
+        goto exit;
+
+    /* If the operation was not supported by any accelerator, try fallback. */
 #if defined(MBEDTLS_RSA_C)
     if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR )
     {
@@ -3763,29 +3758,22 @@
 {
     psa_key_slot_t *slot;
     psa_status_t status;
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    const psa_drv_se_t *drv;
-    psa_drv_se_context_t *drv_context;
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 
     status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY_HASH, alg );
     if( status != PSA_SUCCESS )
         return( status );
 
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) )
-    {
-        if( drv->asymmetric == NULL ||
-            drv->asymmetric->p_verify == NULL )
-            return( PSA_ERROR_NOT_SUPPORTED );
-        return( drv->asymmetric->p_verify( drv_context,
-                                           slot->data.se.slot_number,
-                                           alg,
-                                           hash, hash_length,
-                                           signature, signature_length ) );
-    }
-    else
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+    /* Try any of the available accelerators first */
+    status = psa_driver_wrapper_verify_hash( slot,
+                                             alg,
+                                             hash,
+                                             hash_length,
+                                             signature,
+                                             signature_length );
+    if( status != PSA_ERROR_NOT_SUPPORTED ||
+        psa_key_lifetime_is_external( slot->attr.lifetime ) )
+        return status;
+
 #if defined(MBEDTLS_RSA_C)
     if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) )
     {
@@ -4049,27 +4037,6 @@
 /* Symmetric cryptography */
 /****************************************************************/
 
-/* Initialize the cipher operation structure. Once this function has been
- * called, psa_cipher_abort can run and will do the right thing. */
-static psa_status_t psa_cipher_init( psa_cipher_operation_t *operation,
-                                     psa_algorithm_t alg )
-{
-    if( ! PSA_ALG_IS_CIPHER( alg ) )
-    {
-        memset( operation, 0, sizeof( *operation ) );
-        return( PSA_ERROR_INVALID_ARGUMENT );
-    }
-
-    operation->alg = alg;
-    operation->key_set = 0;
-    operation->iv_set = 0;
-    operation->iv_required = 1;
-    operation->iv_size = 0;
-    operation->block_size = 0;
-    mbedtls_cipher_init( &operation->ctx.cipher );
-    return( PSA_SUCCESS );
-}
-
 static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation,
                                       psa_key_handle_t handle,
                                       psa_algorithm_t alg,
@@ -4086,19 +4053,63 @@
 
     /* A context must be freshly initialized before it can be set up. */
     if( operation->alg != 0 )
-    {
         return( PSA_ERROR_BAD_STATE );
-    }
 
-    status = psa_cipher_init( operation, alg );
-    if( status != PSA_SUCCESS )
-        return( status );
+    /* The requested algorithm must be one that can be processed by cipher. */
+    if( ! PSA_ALG_IS_CIPHER( alg ) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
 
-    status = psa_get_transparent_key( handle, &slot, usage, alg);
+    /* Fetch key material from key storage. */
+    status = psa_get_key_from_slot( handle, &slot, usage, alg );
     if( status != PSA_SUCCESS )
         goto exit;
-    key_bits = psa_get_key_slot_bits( slot );
 
+    /* Initialize the operation struct members, except for alg. The alg member
+     * is used to indicate to psa_cipher_abort that there are resources to free,
+     * so we only set it after resources have been allocated/initialized. */
+    operation->key_set = 0;
+    operation->iv_set = 0;
+    operation->mbedtls_in_use = 0;
+    operation->iv_size = 0;
+    operation->block_size = 0;
+    if( alg == PSA_ALG_ECB_NO_PADDING )
+        operation->iv_required = 0;
+    else
+        operation->iv_required = 1;
+
+    /* Try doing the operation through a driver before using software fallback. */
+    if( cipher_operation == MBEDTLS_ENCRYPT )
+        status = psa_driver_wrapper_cipher_encrypt_setup( &operation->ctx.driver,
+                                                          slot,
+                                                          alg );
+    else
+        status = psa_driver_wrapper_cipher_decrypt_setup( &operation->ctx.driver,
+                                                          slot,
+                                                          alg );
+
+    if( status == PSA_SUCCESS )
+    {
+        /* Once the driver context is initialised, it needs to be freed using
+        * psa_cipher_abort. Indicate this through setting alg. */
+        operation->alg = alg;
+    }
+
+    if( status != PSA_ERROR_NOT_SUPPORTED ||
+        psa_key_lifetime_is_external( slot->attr.lifetime ) )
+        goto exit;
+
+    /* Proceed with initializing an mbed TLS cipher context if no driver is
+     * available for the given algorithm & key. */
+    mbedtls_cipher_init( &operation->ctx.cipher );
+
+    /* Once the cipher context is initialised, it needs to be freed using
+     * psa_cipher_abort. Indicate there is something to be freed through setting
+     * alg, and indicate the operation is being done using mbedtls crypto through
+     * setting mbedtls_in_use. */
+    operation->alg = alg;
+    operation->mbedtls_in_use = 1;
+
+    key_bits = psa_get_key_slot_bits( slot );
     cipher_info = mbedtls_cipher_info_from_psa( alg, slot->attr.type, key_bits, NULL );
     if( cipher_info == NULL )
     {
@@ -4151,10 +4162,10 @@
         goto exit;
 #endif //MBEDTLS_CIPHER_MODE_WITH_PADDING
 
-    operation->key_set = 1;
     operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 :
                               PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type ) );
-    if( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG )
+    if( ( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG ) != 0 &&
+        alg != PSA_ALG_ECB_NO_PADDING )
     {
         operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_SIZE( slot->attr.type );
     }
@@ -4164,10 +4175,17 @@
         operation->iv_size = 12;
 #endif
 
+    status = PSA_SUCCESS;
+
 exit:
-    if( status == 0 )
+    if( ret != 0 )
         status = mbedtls_to_psa_error( ret );
-    if( status != 0 )
+    if( status == PSA_SUCCESS )
+    {
+        /* Update operation flags for both driver and software implementations */
+        operation->key_set = 1;
+    }
+    else
         psa_cipher_abort( operation );
     return( status );
 }
@@ -4197,6 +4215,16 @@
     {
         return( PSA_ERROR_BAD_STATE );
     }
+
+    if( operation->mbedtls_in_use == 0 )
+    {
+        status = psa_driver_wrapper_cipher_generate_iv( &operation->ctx.driver,
+                                                        iv,
+                                                        iv_size,
+                                                        iv_length );
+        goto exit;
+    }
+
     if( iv_size < operation->iv_size )
     {
         status = PSA_ERROR_BUFFER_TOO_SMALL;
@@ -4214,7 +4242,9 @@
     status = psa_cipher_set_iv( operation, iv, *iv_length );
 
 exit:
-    if( status != PSA_SUCCESS )
+    if( status == PSA_SUCCESS )
+        operation->iv_set = 1;
+    else
         psa_cipher_abort( operation );
     return( status );
 }
@@ -4229,6 +4259,15 @@
     {
         return( PSA_ERROR_BAD_STATE );
     }
+
+    if( operation->mbedtls_in_use == 0 )
+    {
+        status = psa_driver_wrapper_cipher_set_iv( &operation->ctx.driver,
+                                                   iv,
+                                                   iv_length );
+        goto exit;
+    }
+
     if( iv_length != operation->iv_size )
     {
         status = PSA_ERROR_INVALID_ARGUMENT;
@@ -4244,6 +4283,94 @@
     return( status );
 }
 
+/* Process input for which the algorithm is set to ECB mode. This requires
+ * manual processing, since the PSA API is defined as being able to process
+ * arbitrary-length calls to psa_cipher_update() with ECB mode, but the
+ * underlying mbedtls_cipher_update only takes full blocks. */
+static psa_status_t psa_cipher_update_ecb_internal(
+    mbedtls_cipher_context_t *ctx,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t block_size = ctx->cipher_info->block_size;
+    size_t internal_output_length = 0;
+    *output_length = 0;
+
+    if( input_length == 0 )
+    {
+        status = PSA_SUCCESS;
+        goto exit;
+    }
+
+    if( ctx->unprocessed_len > 0 )
+    {
+        /* Fill up to block size, and run the block if there's a full one. */
+        size_t bytes_to_copy = block_size - ctx->unprocessed_len;
+
+        if( input_length < bytes_to_copy )
+            bytes_to_copy = input_length;
+
+        memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ),
+                input, bytes_to_copy );
+        input_length -= bytes_to_copy;
+        input += bytes_to_copy;
+        ctx->unprocessed_len += bytes_to_copy;
+
+        if( ctx->unprocessed_len == block_size )
+        {
+            status = mbedtls_to_psa_error(
+                mbedtls_cipher_update( ctx,
+                                       ctx->unprocessed_data,
+                                       block_size,
+                                       output, &internal_output_length ) );
+
+            if( status != PSA_SUCCESS )
+                goto exit;
+
+            output += internal_output_length;
+            output_size -= internal_output_length;
+            *output_length += internal_output_length;
+            ctx->unprocessed_len = 0;
+        }
+    }
+
+    while( input_length >= block_size )
+    {
+        /* Run all full blocks we have, one by one */
+        status = mbedtls_to_psa_error(
+            mbedtls_cipher_update( ctx, input,
+                                   block_size,
+                                   output, &internal_output_length ) );
+
+        if( status != PSA_SUCCESS )
+            goto exit;
+
+        input_length -= block_size;
+        input += block_size;
+
+        output += internal_output_length;
+        output_size -= internal_output_length;
+        *output_length += internal_output_length;
+    }
+
+    if( input_length > 0 )
+    {
+        /* Save unprocessed bytes for later processing */
+        memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ),
+                input, input_length );
+        ctx->unprocessed_len += input_length;
+    }
+
+    status = PSA_SUCCESS;
+
+exit:
+    return( status );
+}
+
 psa_status_t psa_cipher_update( psa_cipher_operation_t *operation,
                                 const uint8_t *input,
                                 size_t input_length,
@@ -4251,14 +4378,27 @@
                                 size_t output_size,
                                 size_t *output_length )
 {
-    psa_status_t status;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     size_t expected_output_size;
-
     if( operation->alg == 0 )
     {
         return( PSA_ERROR_BAD_STATE );
     }
+    if( operation->iv_required && ! operation->iv_set )
+    {
+        return( PSA_ERROR_BAD_STATE );
+    }
+
+    if( operation->mbedtls_in_use == 0 )
+    {
+        status = psa_driver_wrapper_cipher_update( &operation->ctx.driver,
+                                                   input,
+                                                   input_length,
+                                                   output,
+                                                   output_size,
+                                                   output_length );
+        goto exit;
+    }
 
     if( ! PSA_ALG_IS_STREAM_CIPHER( operation->alg ) )
     {
@@ -4281,9 +4421,24 @@
         goto exit;
     }
 
-    ret = mbedtls_cipher_update( &operation->ctx.cipher, input,
-                                 input_length, output, output_length );
-    status = mbedtls_to_psa_error( ret );
+    if( operation->alg == PSA_ALG_ECB_NO_PADDING )
+    {
+        /* mbedtls_cipher_update has an API inconsistency: it will only
+        * process a single block at a time in ECB mode. Abstract away that
+        * inconsistency here to match the PSA API behaviour. */
+        status = psa_cipher_update_ecb_internal( &operation->ctx.cipher,
+                                                 input,
+                                                 input_length,
+                                                 output,
+                                                 output_size,
+                                                 output_length );
+    }
+    else
+    {
+        status = mbedtls_to_psa_error(
+            mbedtls_cipher_update( &operation->ctx.cipher, input,
+                                   input_length, output, output_length ) );
+    }
 exit:
     if( status != PSA_SUCCESS )
         psa_cipher_abort( operation );
@@ -4296,10 +4451,8 @@
                                 size_t *output_length )
 {
     psa_status_t status = PSA_ERROR_GENERIC_ERROR;
-    int cipher_ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
-
-    if( ! operation->key_set )
+    if( operation->alg == 0 )
     {
         return( PSA_ERROR_BAD_STATE );
     }
@@ -4308,53 +4461,60 @@
         return( PSA_ERROR_BAD_STATE );
     }
 
-    if( operation->ctx.cipher.operation == MBEDTLS_ENCRYPT &&
-        operation->alg == PSA_ALG_CBC_NO_PADDING &&
-        operation->ctx.cipher.unprocessed_len != 0 )
+    if( operation->mbedtls_in_use == 0 )
     {
-            status = PSA_ERROR_INVALID_ARGUMENT;
-            goto error;
+        status = psa_driver_wrapper_cipher_finish( &operation->ctx.driver,
+                                                   output,
+                                                   output_size,
+                                                   output_length );
+        goto exit;
     }
 
-    cipher_ret = mbedtls_cipher_finish( &operation->ctx.cipher,
-                                        temp_output_buffer,
-                                        output_length );
-    if( cipher_ret != 0 )
+    if( operation->ctx.cipher.unprocessed_len != 0 )
     {
-        status = mbedtls_to_psa_error( cipher_ret );
-        goto error;
+        if( operation->alg == PSA_ALG_ECB_NO_PADDING ||
+            ( operation->alg == PSA_ALG_CBC_NO_PADDING &&
+              operation->ctx.cipher.operation == MBEDTLS_ENCRYPT ) )
+        {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            goto exit;
+        }
     }
 
+    status = mbedtls_to_psa_error(
+        mbedtls_cipher_finish( &operation->ctx.cipher,
+                               temp_output_buffer,
+                               output_length ) );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
     if( *output_length == 0 )
         ; /* Nothing to copy. Note that output may be NULL in this case. */
     else if( output_size >= *output_length )
         memcpy( output, temp_output_buffer, *output_length );
     else
-    {
         status = PSA_ERROR_BUFFER_TOO_SMALL;
-        goto error;
+
+exit:
+    if( operation->mbedtls_in_use == 1 )
+        mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) );
+
+    if( status == PSA_SUCCESS )
+        return( psa_cipher_abort( operation ) );
+    else
+    {
+        *output_length = 0;
+        (void) psa_cipher_abort( operation );
+
+        return( status );
     }
-
-    mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) );
-    status = psa_cipher_abort( operation );
-
-    return( status );
-
-error:
-
-    *output_length = 0;
-
-    mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) );
-    (void) psa_cipher_abort( operation );
-
-    return( status );
 }
 
 psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation )
 {
     if( operation->alg == 0 )
     {
-        /* The object has (apparently) been initialized but it is not
+        /* The object has (apparently) been initialized but it is not (yet)
          * in use. It's ok to call abort on such an object, and there's
          * nothing to do. */
         return( PSA_SUCCESS );
@@ -4365,11 +4525,15 @@
     if( ! PSA_ALG_IS_CIPHER( operation->alg ) )
         return( PSA_ERROR_BAD_STATE );
 
-    mbedtls_cipher_free( &operation->ctx.cipher );
+    if( operation->mbedtls_in_use == 0 )
+        psa_driver_wrapper_cipher_abort( &operation->ctx.driver );
+    else
+        mbedtls_cipher_free( &operation->ctx.cipher );
 
     operation->alg = 0;
     operation->key_set = 0;
     operation->iv_set = 0;
+    operation->mbedtls_in_use = 0;
     operation->iv_size = 0;
     operation->block_size = 0;
     operation->iv_required = 0;
@@ -6004,29 +6168,15 @@
     if( status != PSA_SUCCESS )
         goto exit;
 
-#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    if( driver != NULL )
-    {
-        const psa_drv_se_t *drv = psa_get_se_driver_methods( driver );
-        size_t pubkey_length = 0; /* We don't support this feature yet */
-        if( drv->key_management == NULL ||
-            drv->key_management->p_generate == NULL )
-        {
-            status = PSA_ERROR_NOT_SUPPORTED;
-            goto exit;
-        }
-        status = drv->key_management->p_generate(
-            psa_get_se_driver_context( driver ),
-            slot->data.se.slot_number, attributes,
-            NULL, 0, &pubkey_length );
-    }
-    else
-#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
-    {
-        status = psa_generate_key_internal(
-            slot, attributes->core.bits,
-            attributes->domain_parameters, attributes->domain_parameters_size );
-    }
+    status = psa_driver_wrapper_generate_key( attributes,
+                                              slot );
+    if( status != PSA_ERROR_NOT_SUPPORTED ||
+        psa_key_lifetime_is_external( attributes->core.lifetime ) )
+        goto exit;
+
+    status = psa_generate_key_internal(
+        slot, attributes->core.bits,
+        attributes->domain_parameters, attributes->domain_parameters_size );
 
 exit:
     if( status == PSA_SUCCESS )
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index 9a61bab..6ee17fc 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -161,4 +161,16 @@
                                        const uint8_t *data,
                                        size_t data_length );
 
+
+/** Convert an mbed TLS error code to a PSA error code
+ *
+ * \note This function is provided solely for the convenience of
+ *       Mbed TLS and may be removed at any time without notice.
+ *
+ * \param ret           An mbed TLS-thrown error code
+ *
+ * \return              The corresponding PSA error code
+ */
+psa_status_t mbedtls_to_psa_error( int ret );
+
 #endif /* PSA_CRYPTO_CORE_H */
diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c
new file mode 100644
index 0000000..d41209b
--- /dev/null
+++ b/library/psa_crypto_driver_wrappers.c
@@ -0,0 +1,878 @@
+/*
+ *  Functions to delegate cryptographic operations to an available
+ *  and appropriate accelerator.
+ *  Warning: This file will be auto-generated in the future.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include "psa_crypto_core.h"
+#include "psa_crypto_driver_wrappers.h"
+#include "mbedtls/platform.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
+
+/* Include test driver definition when running tests */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#ifndef PSA_CRYPTO_DRIVER_PRESENT
+#define PSA_CRYPTO_DRIVER_PRESENT
+#endif
+#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
+#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT
+#endif
+#include "test/drivers/test_driver.h"
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
+/* Repeat above block for each JSON-declared driver during autogeneration */
+
+/* Auto-generated values depending on which drivers are registered. ID 0 is
+ * reserved for unallocated operations. */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#define PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID (1)
+#define PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID (2)
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
+
+/* Support the 'old' SE interface when asked to */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style
+ * SE driver is present, to avoid unused argument errors at compile time. */
+#ifndef PSA_CRYPTO_DRIVER_PRESENT
+#define PSA_CRYPTO_DRIVER_PRESENT
+#endif
+#include "psa_crypto_se.h"
+#endif
+
+/* Start delegation functions */
+psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot,
+                                           psa_algorithm_t alg,
+                                           const uint8_t *hash,
+                                           size_t hash_length,
+                                           uint8_t *signature,
+                                           size_t signature_size,
+                                           size_t *signature_length )
+{
+#if defined(PSA_CRYPTO_DRIVER_PRESENT)
+    /* Try dynamically-registered SE interface first */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    const psa_drv_se_t *drv;
+    psa_drv_se_context_t *drv_context;
+
+    if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) )
+    {
+        if( drv->asymmetric == NULL ||
+            drv->asymmetric->p_sign == NULL )
+        {
+            /* Key is defined in SE, but we have no way to exercise it */
+            return( PSA_ERROR_NOT_SUPPORTED );
+        }
+        return( drv->asymmetric->p_sign( drv_context,
+                                         slot->data.se.slot_number,
+                                         alg,
+                                         hash, hash_length,
+                                         signature, signature_size,
+                                         signature_length ) );
+    }
+#endif /* PSA_CRYPTO_SE_C */
+
+    /* Then try accelerator API */
+#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_signature_sign_hash( &attributes,
+                                                           slot->data.key.data,
+                                                           slot->data.key.bytes,
+                                                           alg,
+                                                           hash,
+                                                           hash_length,
+                                                           signature,
+                                                           signature_size,
+                                                           signature_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_signature_sign_hash( &attributes,
+                                                     slot->data.key.data,
+                                                     slot->data.key.bytes,
+                                                     alg,
+                                                     hash,
+                                                     hash_length,
+                                                     signature,
+                                                     signature_size,
+                                                     signature_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 */
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#else /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void)slot;
+    (void)alg;
+    (void)hash;
+    (void)hash_length;
+    (void)signature;
+    (void)signature_size;
+    (void)signature_length;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot,
+                                             psa_algorithm_t alg,
+                                             const uint8_t *hash,
+                                             size_t hash_length,
+                                             const uint8_t *signature,
+                                             size_t signature_length )
+{
+#if defined(PSA_CRYPTO_DRIVER_PRESENT)
+    /* Try dynamically-registered SE interface first */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    const psa_drv_se_t *drv;
+    psa_drv_se_context_t *drv_context;
+
+    if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) )
+    {
+        if( drv->asymmetric == NULL ||
+            drv->asymmetric->p_verify == NULL )
+        {
+            /* Key is defined in SE, but we have no way to exercise it */
+            return( PSA_ERROR_NOT_SUPPORTED );
+        }
+        return( drv->asymmetric->p_verify( drv_context,
+                                           slot->data.se.slot_number,
+                                           alg,
+                                           hash, hash_length,
+                                           signature, signature_length ) );
+    }
+#endif /* PSA_CRYPTO_SE_C */
+
+    /* Then try accelerator API */
+#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_signature_verify_hash( &attributes,
+                                                             slot->data.key.data,
+                                                             slot->data.key.bytes,
+                                                             alg,
+                                                             hash,
+                                                             hash_length,
+                                                             signature,
+                                                             signature_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_signature_verify_hash( &attributes,
+                                                       slot->data.key.data,
+                                                       slot->data.key.bytes,
+                                                       alg,
+                                                       hash,
+                                                       hash_length,
+                                                       signature,
+                                                       signature_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 */
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#else /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void)slot;
+    (void)alg;
+    (void)hash;
+    (void)hash_length;
+    (void)signature;
+    (void)signature_length;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+/** Calculate the size to allocate for buffering a key with given attributes.
+ *
+ * This function provides a way to get the expected size for storing a key with
+ * the given attributes. This will be the size of the export representation for
+ * cleartext keys, and a driver-defined size for keys stored by opaque drivers.
+ *
+ * \param[in] attributes        The key attribute structure of the key to store.
+ * \param[out] expected_size    On success, a byte size large enough to contain
+ *                              the declared key.
+ *
+ * \retval #PSA_SUCCESS
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ */
+static psa_status_t get_expected_key_size( const psa_key_attributes_t *attributes,
+                                           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 );
+
+        if( buffer_size == 0 )
+            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 */
+
+psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes,
+                                              psa_key_slot_t *slot )
+{
+#if defined(PSA_CRYPTO_DRIVER_PRESENT)
+    /* Try dynamically-registered SE interface first */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    const psa_drv_se_t *drv;
+    psa_drv_se_context_t *drv_context;
+
+    if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) )
+    {
+        size_t pubkey_length = 0; /* We don't support this feature yet */
+        if( drv->key_management == NULL ||
+            drv->key_management->p_generate == NULL )
+        {
+            /* Key is defined as being in SE, but we have no way to generate it */
+            return( PSA_ERROR_NOT_SUPPORTED );
+        }
+        return( drv->key_management->p_generate(
+            drv_context,
+            slot->data.se.slot_number, attributes,
+            NULL, 0, &pubkey_length ) );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    /* Then try accelerator API */
+#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);
+    size_t export_size = 0;
+
+    status = get_expected_key_size( attributes, &export_size );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    slot->data.key.data = mbedtls_calloc(1, export_size);
+    if( slot->data.key.data == NULL )
+        return( PSA_ERROR_INSUFFICIENT_MEMORY );
+    slot->data.key.bytes = export_size;
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+
+            /* Transparent drivers are limited to generating asymmetric keys */
+            if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) )
+            {
+                status = PSA_ERROR_NOT_SUPPORTED;
+                break;
+            }
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = test_transparent_generate_key( attributes,
+                                                    slot->data.key.data,
+                                                    slot->data.key.bytes,
+                                                    &slot->data.key.bytes );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                break;
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+            /* Fell through, meaning no accelerator supports this operation */
+            status = PSA_ERROR_NOT_SUPPORTED;
+            break;
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LIFETIME:
+            status = test_opaque_generate_key( attributes,
+                                               slot->data.key.data,
+                                               slot->data.key.bytes,
+                                               &slot->data.key.bytes );
+            break;
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            break;
+    }
+
+    if( status != PSA_SUCCESS )
+    {
+        /* free allocated buffer */
+        mbedtls_free( slot->data.key.data );
+        slot->data.key.data = NULL;
+        slot->data.key.bytes = 0;
+    }
+
+    return( status );
+#else /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#else /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void) attributes;
+    (void) slot;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+/*
+ * Cipher functions
+ */
+psa_status_t psa_driver_wrapper_cipher_encrypt(
+    psa_key_slot_t *slot,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length )
+{
+#if defined(PSA_CRYPTO_DRIVER_PRESENT) && 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_cipher_encrypt( &attributes,
+                                                      slot->data.key.data,
+                                                      slot->data.key.bytes,
+                                                      alg,
+                                                      input,
+                                                      input_length,
+                                                      output,
+                                                      output_size,
+                                                      output_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_cipher_encrypt( &attributes,
+                                                slot->data.key.data,
+                                                slot->data.key.bytes,
+                                                alg,
+                                                input,
+                                                input_length,
+                                                output,
+                                                output_size,
+                                                output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            return( status );
+    }
+#else /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void) slot;
+    (void) alg;
+    (void) input;
+    (void) input_length;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+psa_status_t psa_driver_wrapper_cipher_decrypt(
+    psa_key_slot_t *slot,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length )
+{
+#if defined(PSA_CRYPTO_DRIVER_PRESENT) && 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_cipher_decrypt( &attributes,
+                                                      slot->data.key.data,
+                                                      slot->data.key.bytes,
+                                                      alg,
+                                                      input,
+                                                      input_length,
+                                                      output,
+                                                      output_size,
+                                                      output_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_cipher_decrypt( &attributes,
+                                                slot->data.key.data,
+                                                slot->data.key.bytes,
+                                                alg,
+                                                input,
+                                                input_length,
+                                                output,
+                                                output_size,
+                                                output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            return( status );
+    }
+#else /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void) slot;
+    (void) alg;
+    (void) input;
+    (void) input_length;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+psa_status_t psa_driver_wrapper_cipher_encrypt_setup(
+    psa_operation_driver_context_t *operation,
+    psa_key_slot_t *slot,
+    psa_algorithm_t alg )
+{
+#if defined(PSA_CRYPTO_DRIVER_PRESENT) && 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)
+            operation->ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) );
+            if( operation->ctx == NULL )
+                return PSA_ERROR_INSUFFICIENT_MEMORY;
+
+            status = test_transparent_cipher_encrypt_setup( operation->ctx,
+                                                            &attributes,
+                                                            slot->data.key.data,
+                                                            slot->data.key.bytes,
+                                                            alg );
+            /* Declared with fallback == true */
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID;
+            else
+            {
+                mbedtls_platform_zeroize(
+                    operation->ctx,
+                    sizeof( test_transparent_cipher_operation_t ) );
+                mbedtls_free( operation->ctx );
+                operation->ctx = NULL;
+            }
+
+            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:
+            operation->ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) );
+            if( operation->ctx == NULL )
+                return( PSA_ERROR_INSUFFICIENT_MEMORY );
+
+            status = test_opaque_cipher_encrypt_setup( operation->ctx,
+                                                       &attributes,
+                                                       slot->data.key.data,
+                                                       slot->data.key.bytes,
+                                                       alg );
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID;
+            else
+            {
+                mbedtls_platform_zeroize(
+                    operation->ctx,
+                    sizeof( test_opaque_cipher_operation_t ) );
+                mbedtls_free( operation->ctx );
+                operation->ctx = NULL;
+            }
+
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            return( PSA_ERROR_BAD_STATE );
+    }
+#else /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void)slot;
+    (void)alg;
+    (void)operation;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+psa_status_t psa_driver_wrapper_cipher_decrypt_setup(
+    psa_operation_driver_context_t *operation,
+    psa_key_slot_t *slot,
+    psa_algorithm_t alg )
+{
+#if defined(PSA_CRYPTO_DRIVER_PRESENT) && 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)
+            operation->ctx = mbedtls_calloc( 1, sizeof(test_transparent_cipher_operation_t) );
+            if( operation->ctx == NULL )
+                return( PSA_ERROR_INSUFFICIENT_MEMORY );
+
+            status = test_transparent_cipher_decrypt_setup( operation->ctx,
+                                                            &attributes,
+                                                            slot->data.key.data,
+                                                            slot->data.key.bytes,
+                                                            alg );
+            /* Declared with fallback == true */
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID;
+            else
+            {
+                mbedtls_platform_zeroize(
+                    operation->ctx,
+                    sizeof( test_transparent_cipher_operation_t ) );
+                mbedtls_free( operation->ctx );
+                operation->ctx = NULL;
+            }
+
+            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:
+            operation->ctx = mbedtls_calloc( 1, sizeof(test_opaque_cipher_operation_t) );
+            if( operation->ctx == NULL )
+                return PSA_ERROR_INSUFFICIENT_MEMORY;
+
+            status = test_opaque_cipher_decrypt_setup( operation->ctx,
+                                                       &attributes,
+                                                       slot->data.key.data,
+                                                       slot->data.key.bytes,
+                                                       alg );
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID;
+            else
+            {
+                mbedtls_platform_zeroize(
+                    operation->ctx,
+                    sizeof( test_opaque_cipher_operation_t ) );
+                mbedtls_free( operation->ctx );
+                operation->ctx = NULL;
+            }
+
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            return( PSA_ERROR_BAD_STATE );
+    }
+#else /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void)slot;
+    (void)alg;
+    (void)operation;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+psa_status_t psa_driver_wrapper_cipher_generate_iv(
+    psa_operation_driver_context_t *operation,
+    uint8_t *iv,
+    size_t iv_size,
+    size_t *iv_length )
+{
+#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+    switch( operation->id )
+    {
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( test_transparent_cipher_generate_iv( operation->ctx,
+                                                         iv,
+                                                         iv_size,
+                                                         iv_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
+            return( test_opaque_cipher_generate_iv( operation->ctx,
+                                                    iv,
+                                                    iv_size,
+                                                    iv_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            /* Key is attached to a driver not known to us */
+            return( PSA_ERROR_BAD_STATE );
+    }
+#else /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void) operation;
+    (void) iv;
+    (void) iv_size;
+    (void) iv_length;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+psa_status_t psa_driver_wrapper_cipher_set_iv(
+    psa_operation_driver_context_t *operation,
+    const uint8_t *iv,
+    size_t iv_length )
+{
+#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+    switch( operation->id )
+    {
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( test_transparent_cipher_set_iv( operation->ctx,
+                                                    iv,
+                                                    iv_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
+            return( test_opaque_cipher_set_iv( operation->ctx,
+                                               iv,
+                                               iv_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            /* Key is attached to a driver not known to us */
+            return( PSA_ERROR_BAD_STATE );
+    }
+#else /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void) operation;
+    (void) iv;
+    (void) iv_length;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+psa_status_t psa_driver_wrapper_cipher_update(
+    psa_operation_driver_context_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length )
+{
+#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+    switch( operation->id )
+    {
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( test_transparent_cipher_update( operation->ctx,
+                                                    input,
+                                                    input_length,
+                                                    output,
+                                                    output_size,
+                                                    output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
+            return( test_opaque_cipher_update( operation->ctx,
+                                               input,
+                                               input_length,
+                                               output,
+                                               output_size,
+                                               output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            /* Key is attached to a driver not known to us */
+            return( PSA_ERROR_BAD_STATE );
+    }
+#else /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void) operation;
+    (void) input;
+    (void) input_length;
+    (void) output;
+    (void) output_length;
+    (void) output_size;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+psa_status_t psa_driver_wrapper_cipher_finish(
+    psa_operation_driver_context_t *operation,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length )
+{
+#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+    switch( operation->id )
+    {
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( test_transparent_cipher_finish( operation->ctx,
+                                                    output,
+                                                    output_size,
+                                                    output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
+            return( test_opaque_cipher_finish( operation->ctx,
+                                               output,
+                                               output_size,
+                                               output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            /* Key is attached to a driver not known to us */
+            return( PSA_ERROR_BAD_STATE );
+    }
+#else /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void) operation;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+psa_status_t psa_driver_wrapper_cipher_abort(
+    psa_operation_driver_context_t *operation )
+{
+#if defined(PSA_CRYPTO_DRIVER_PRESENT) && defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+
+    /* The object has (apparently) been initialized but it is not in use. It's
+     * ok to call abort on such an object, and there's nothing to do. */
+    if( operation->ctx == NULL && operation->id == 0 )
+        return( PSA_SUCCESS );
+
+    switch( operation->id )
+    {
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            status = test_transparent_cipher_abort( operation->ctx );
+            mbedtls_platform_zeroize(
+                operation->ctx,
+                sizeof( test_transparent_cipher_operation_t ) );
+            mbedtls_free( operation->ctx );
+            operation->ctx = NULL;
+            operation->id = 0;
+
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID:
+            status = test_opaque_cipher_abort( operation->ctx );
+            mbedtls_platform_zeroize(
+                operation->ctx,
+                sizeof( test_opaque_cipher_operation_t ) );
+            mbedtls_free( operation->ctx );
+            operation->ctx = NULL;
+            operation->id = 0;
+
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+        default:
+            /* Operation is attached to a driver not known to us */
+            return( PSA_ERROR_BAD_STATE );
+    }
+#else /* PSA_CRYPTO_DRIVER_PRESENT */
+    (void)operation;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_PRESENT */
+}
+
+/* End of automatically generated file. */
diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h
new file mode 100644
index 0000000..0db15d6
--- /dev/null
+++ b/library/psa_crypto_driver_wrappers.h
@@ -0,0 +1,110 @@
+/*
+ *  Function signatures for functionality that can be provided by
+ *  cryptographic accelerators.
+ *  Warning: This file will be auto-generated in the future.
+ */
+/*  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_DRIVER_WRAPPERS_H
+#define PSA_CRYPTO_DRIVER_WRAPPERS_H
+
+#include "psa/crypto.h"
+#include "psa/crypto_driver_common.h"
+
+/*
+ * Signature functions
+ */
+psa_status_t psa_driver_wrapper_sign_hash( psa_key_slot_t *slot,
+                                           psa_algorithm_t alg,
+                                           const uint8_t *hash,
+                                           size_t hash_length,
+                                           uint8_t *signature,
+                                           size_t signature_size,
+                                           size_t *signature_length );
+
+psa_status_t psa_driver_wrapper_verify_hash( psa_key_slot_t *slot,
+                                             psa_algorithm_t alg,
+                                             const uint8_t *hash,
+                                             size_t hash_length,
+                                             const uint8_t *signature,
+                                             size_t signature_length );
+
+psa_status_t psa_driver_wrapper_generate_key( const psa_key_attributes_t *attributes,
+                                              psa_key_slot_t *slot );
+
+/*
+ * Cipher functions
+ */
+psa_status_t psa_driver_wrapper_cipher_encrypt(
+    psa_key_slot_t *slot,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length );
+
+psa_status_t psa_driver_wrapper_cipher_decrypt(
+    psa_key_slot_t *slot,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length );
+
+psa_status_t psa_driver_wrapper_cipher_encrypt_setup(
+    psa_operation_driver_context_t *operation,
+    psa_key_slot_t *slot,
+    psa_algorithm_t alg );
+
+psa_status_t psa_driver_wrapper_cipher_decrypt_setup(
+    psa_operation_driver_context_t *operation,
+    psa_key_slot_t *slot,
+    psa_algorithm_t alg );
+
+psa_status_t psa_driver_wrapper_cipher_generate_iv(
+    psa_operation_driver_context_t *operation,
+    uint8_t *iv,
+    size_t iv_size,
+    size_t *iv_length );
+
+psa_status_t psa_driver_wrapper_cipher_set_iv(
+    psa_operation_driver_context_t *operation,
+    const uint8_t *iv,
+    size_t iv_length );
+
+psa_status_t psa_driver_wrapper_cipher_update(
+    psa_operation_driver_context_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length );
+
+psa_status_t psa_driver_wrapper_cipher_finish(
+    psa_operation_driver_context_t *operation,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length );
+
+psa_status_t psa_driver_wrapper_cipher_abort(
+    psa_operation_driver_context_t *operation );
+
+#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */
+
+/* End of automatically generated file. */
diff --git a/library/psa_crypto_se.h b/library/psa_crypto_se.h
index a464232..5691738 100644
--- a/library/psa_crypto_se.h
+++ b/library/psa_crypto_se.h
@@ -45,7 +45,7 @@
 /** The base of the range of ITS file identifiers for secure element
  * driver persistent data.
  *
- * We use a slice of the implemenation reserved range 0xffff0000..0xffffffff,
+ * We use a slice of the implementation reserved range 0xffff0000..0xffffffff,
  * specifically the range 0xfffffe00..0xfffffeff. The length of this range
  * drives the value of #PSA_MAX_SE_LOCATION. The identifier 0xfffffe00 is
  * actually not used since it corresponds to #PSA_KEY_LOCATION_LOCAL_STORAGE
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
index a32a027..e526560 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -157,16 +157,15 @@
  * past released version must remain valid, unless a migration path
  * is provided.
  *
- * \param file_id       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.
+ * \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 file_id is acceptable, otherwise 0.
+ * \return           1 if \p key is acceptable, otherwise 0.
  */
-static int psa_is_key_id_valid( psa_key_file_id_t file_id,
-                                int vendor_ok )
+static int psa_is_key_id_valid( mbedtls_svc_key_id_t key, int vendor_ok )
 {
-    psa_app_key_id_t key_id = PSA_KEY_FILE_GET_KEY_ID( file_id );
+    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 &&
@@ -204,7 +203,7 @@
 }
 
 psa_status_t psa_validate_key_persistence( psa_key_lifetime_t lifetime,
-                                           psa_key_id_t key_id )
+                                           mbedtls_svc_key_id_t key )
 {
     if ( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) )
     {
@@ -215,19 +214,19 @@
     {
         /* Persistent keys require storage support */
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-        if( psa_is_key_id_valid( key_id,
+        if( psa_is_key_id_valid( key,
                                  psa_key_lifetime_is_external( lifetime ) ) )
             return( PSA_SUCCESS );
         else
             return( PSA_ERROR_INVALID_ARGUMENT );
 #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
-        (void) key_id;
+        (void) key;
         return( PSA_ERROR_NOT_SUPPORTED );
 #endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */
     }
 }
 
-psa_status_t psa_open_key( psa_key_file_id_t id, psa_key_handle_t *handle )
+psa_status_t psa_open_key( mbedtls_svc_key_id_t key, psa_key_handle_t *handle )
 {
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
     psa_status_t status;
@@ -235,7 +234,7 @@
 
     *handle = 0;
 
-    if( ! psa_is_key_id_valid( id, 1 ) )
+    if( ! psa_is_key_id_valid( key, 1 ) )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
     status = psa_get_empty_key_slot( handle, &slot );
@@ -243,7 +242,7 @@
         return( status );
 
     slot->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
-    slot->attr.id = id;
+    slot->attr.id = key;
 
     status = psa_load_persistent_key_into_slot( slot );
     if( status != PSA_SUCCESS )
@@ -254,7 +253,7 @@
     return( status );
 
 #else /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
-    (void) id;
+    (void) key;
     *handle = 0;
     return( PSA_ERROR_NOT_SUPPORTED );
 #endif /* !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
@@ -291,14 +290,14 @@
             ++stats->volatile_slots;
         else if( slot->attr.lifetime == PSA_KEY_LIFETIME_PERSISTENT )
         {
-            psa_app_key_id_t id = PSA_KEY_FILE_GET_KEY_ID(slot->attr.id);
+            psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( slot->attr.id );
             ++stats->persistent_slots;
             if( id > stats->max_open_internal_key_id )
                 stats->max_open_internal_key_id = id;
         }
         else
         {
-            psa_app_key_id_t id = PSA_KEY_FILE_GET_KEY_ID(slot->attr.id);
+            psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( slot->attr.id );
             ++stats->external_slots;
             if( id > stats->max_open_external_key_id )
                 stats->max_open_external_key_id = id;
diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h
index 676a77e..c6fecbb 100644
--- a/library/psa_crypto_slot_management.h
+++ b/library/psa_crypto_slot_management.h
@@ -113,14 +113,13 @@
  * 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.
  *
- * \param[in] lifetime    The key lifetime attribute.
- * \param[in] key_id      The key ID attribute
+ * \param[in] lifetime  The key lifetime attribute.
+ * \param[in] key       The key identifier.
  *
  * \retval #PSA_SUCCESS
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  */
 psa_status_t psa_validate_key_persistence( psa_key_lifetime_t lifetime,
-                                           psa_key_id_t key_id );
-
+                                           mbedtls_svc_key_id_t key );
 
 #endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */
diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c
index 103c9bb..46d0b65 100644
--- a/library/psa_crypto_storage.c
+++ b/library/psa_crypto_storage.c
@@ -55,27 +55,27 @@
 /* Key storage */
 /****************************************************************/
 
-/* Determine a file name (ITS file identifier) for the given key file
- * identifier. The file name must be distinct from any file that is used
- * for a purpose other than storing a key. Currently, the only such file
- * is the random seed file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID
- * and whose value is 0xFFFFFF52. */
-static psa_storage_uid_t psa_its_identifier_of_slot( psa_key_file_id_t file_id )
+/* Determine a file name (ITS file identifier) for the given key identifier.
+ * The file name must be distinct from any file that is used for a purpose
+ * other than storing a key. Currently, the only such file is the random seed
+ * file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID and whose value is
+ * 0xFFFFFF52. */
+static psa_storage_uid_t psa_its_identifier_of_slot( mbedtls_svc_key_id_t key )
 {
-#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) && \
-    defined(PSA_CRYPTO_SECURE)
+#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
     /* Encode the owner in the upper 32 bits. This means that if
      * owner values are nonzero (as they are on a PSA platform),
      * no key file will ever have a value less than 0x100000000, so
      * the whole range 0..0xffffffff is available for non-key files. */
-    uint32_t unsigned_owner = (uint32_t) file_id.owner;
-    return( (uint64_t) unsigned_owner << 32 | file_id.key_id );
+    uint32_t unsigned_owner_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( key );
+    return(  ( (uint64_t) unsigned_owner_id << 32 ) |
+             MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key ) );
 #else
     /* Use the key id directly as a file name.
-     * psa_is_key_file_id_valid() in psa_crypto_slot_management.c
+     * psa_is_key_id_valid() in psa_crypto_slot_management.c
      * is responsible for ensuring that key identifiers do not have a
      * value that is reserved for non-key files. */
-    return( file_id );
+    return( key );
 #endif
 }
 
@@ -94,9 +94,8 @@
  * \retval PSA_ERROR_STORAGE_FAILURE
  * \retval PSA_ERROR_DOES_NOT_EXIST
  */
-static psa_status_t psa_crypto_storage_load( const psa_key_file_id_t key,
-                                             uint8_t *data,
-                                             size_t data_size )
+static psa_status_t psa_crypto_storage_load(
+    const mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size )
 {
     psa_status_t status;
     psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
@@ -114,7 +113,7 @@
     return( status );
 }
 
-int psa_is_key_present_in_storage( const psa_key_file_id_t key )
+int psa_is_key_present_in_storage( const mbedtls_svc_key_id_t key )
 {
     psa_status_t ret;
     psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
@@ -143,7 +142,7 @@
  * \retval PSA_ERROR_STORAGE_FAILURE
  * \retval PSA_ERROR_ALREADY_EXISTS
  */
-static psa_status_t psa_crypto_storage_store( const psa_key_file_id_t key,
+static psa_status_t psa_crypto_storage_store( const mbedtls_svc_key_id_t key,
                                               const uint8_t *data,
                                               size_t data_length )
 {
@@ -184,7 +183,7 @@
     return( status );
 }
 
-psa_status_t psa_destroy_persistent_key( const psa_key_file_id_t key )
+psa_status_t psa_destroy_persistent_key( const mbedtls_svc_key_id_t key )
 {
     psa_status_t ret;
     psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key );
@@ -215,7 +214,7 @@
  * \retval PSA_ERROR_STORAGE_FAILURE
  */
 static psa_status_t psa_crypto_storage_get_data_length(
-    const psa_key_file_id_t key,
+    const mbedtls_svc_key_id_t key,
     size_t *data_length )
 {
     psa_status_t status;
@@ -394,7 +393,7 @@
     psa_status_t status = PSA_SUCCESS;
     uint8_t *loaded_data;
     size_t storage_data_length = 0;
-    psa_key_id_t key = attr->id;
+    mbedtls_svc_key_id_t key = attr->id;
 
     status = psa_crypto_storage_get_data_length( key, &storage_data_length );
     if( status != PSA_SUCCESS )
diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h
index debc742..de845a7 100644
--- a/library/psa_crypto_storage.h
+++ b/library/psa_crypto_storage.h
@@ -72,7 +72,7 @@
  * \retval 1
  *         Persistent data present for slot number
  */
-int psa_is_key_present_in_storage( const psa_key_file_id_t key );
+int psa_is_key_present_in_storage( const mbedtls_svc_key_id_t key );
 
 /**
  * \brief Format key data and metadata and save to a location for given key
@@ -141,7 +141,7 @@
  *         or the key did not exist.
  * \retval PSA_ERROR_STORAGE_FAILURE
  */
-psa_status_t psa_destroy_persistent_key( const psa_key_file_id_t key );
+psa_status_t psa_destroy_persistent_key( const mbedtls_svc_key_id_t key );
 
 /**
  * \brief Free the temporary buffer allocated by psa_load_persistent_key().
@@ -292,7 +292,7 @@
         uint16_t unused1;
         psa_key_lifetime_t lifetime;
         psa_key_slot_number_t slot;
-        psa_key_id_t id;
+        mbedtls_svc_key_id_t id;
     } key;
 } psa_crypto_transaction_t;
 
diff --git a/library/ripemd160.c b/library/ripemd160.c
index 830f61b..603b6ba 100644
--- a/library/ripemd160.c
+++ b/library/ripemd160.c
@@ -478,8 +478,7 @@
     { "abcdefghijklmnopqrstuvwxyz" },
     { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
-    { "12345678901234567890123456789012345678901234567890123456789012"
-      "345678901234567890" },
+    { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" },
 };
 
 static const size_t ripemd160_test_strlen[TESTS] =
diff --git a/library/sha512.c b/library/sha512.c
index 80219d4..e881198 100644
--- a/library/sha512.c
+++ b/library/sha512.c
@@ -516,8 +516,7 @@
 static const unsigned char sha512_test_buf[3][113] =
 {
     { "abc" },
-    { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
-      "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
+    { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
     { "" }
 };
 
diff --git a/library/ssl_tls13_keys.c b/library/ssl_tls13_keys.c
new file mode 100644
index 0000000..c39e032
--- /dev/null
+++ b/library/ssl_tls13_keys.c
@@ -0,0 +1,349 @@
+/*
+ *  TLS 1.3 key schedule
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 ( the "License" ); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
+
+#include "mbedtls/hkdf.h"
+#include "mbedtls/ssl_internal.h"
+#include "ssl_tls13_keys.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#define MBEDTLS_SSL_TLS1_3_LABEL( name, string )       \
+    .name = string,
+
+struct mbedtls_ssl_tls1_3_labels_struct const mbedtls_ssl_tls1_3_labels =
+{
+    /* This seems to work in C, despite the string literal being one
+     * character too long due to the 0-termination. */
+    MBEDTLS_SSL_TLS1_3_LABEL_LIST
+};
+
+#undef MBEDTLS_SSL_TLS1_3_LABEL
+
+/*
+ * This function creates a HkdfLabel structure used in the TLS 1.3 key schedule.
+ *
+ * The HkdfLabel is specified in RFC 8446 as follows:
+ *
+ * struct HkdfLabel {
+ *   uint16 length;            // Length of expanded key material
+ *   opaque label<7..255>;     // Always prefixed by "tls13 "
+ *   opaque context<0..255>;   // Usually a communication transcript hash
+ * };
+ *
+ * Parameters:
+ * - desired_length: Length of expanded key material
+ *                   Even though the standard allows expansion to up to
+ *                   2**16 Bytes, TLS 1.3 never uses expansion to more than
+ *                   255 Bytes, so we require `desired_length` to be at most
+ *                   255. This allows us to save a few Bytes of code by
+ *                   hardcoding the writing of the high bytes.
+ * - (label, llen): label + label length, without "tls13 " prefix
+ *                  The label length MUST be less than or equal to
+ *                  MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN
+ *                  It is the caller's responsibility to ensure this.
+ *                  All (label, label length) pairs used in TLS 1.3
+ *                  can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN().
+ * - (ctx, clen): context + context length
+ *                The context length MUST be less than or equal to
+ *                MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN
+ *                It is the caller's responsibility to ensure this.
+ * - dst: Target buffer for HkdfLabel structure,
+ *        This MUST be a writable buffer of size
+ *        at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes.
+ * - dlen: Pointer at which to store the actual length of
+ *         the HkdfLabel structure on success.
+ */
+
+static const char tls1_3_label_prefix[6] = "tls13 ";
+
+#define SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( label_len, context_len ) \
+    (   2                  /* expansion length           */ \
+      + 1                  /* label length               */ \
+      + label_len                                           \
+      + 1                  /* context length             */ \
+      + context_len )
+
+#define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN                      \
+    SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN(                             \
+                     sizeof(tls1_3_label_prefix) +                      \
+                     MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN,     \
+                     MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN )
+
+static void ssl_tls1_3_hkdf_encode_label(
+                            size_t desired_length,
+                            const unsigned char *label, size_t llen,
+                            const unsigned char *ctx, size_t clen,
+                            unsigned char *dst, size_t *dlen )
+{
+    size_t total_label_len =
+        sizeof(tls1_3_label_prefix) + llen;
+    size_t total_hkdf_lbl_len =
+        SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( total_label_len, clen );
+
+    unsigned char *p = dst;
+
+    /* Add the size of the expanded key material.
+     * We're hardcoding the high byte to 0 here assuming that we never use
+     * TLS 1.3 HKDF key expansion to more than 255 Bytes. */
+#if MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN > 255
+#error "The implementation of ssl_tls1_3_hkdf_encode_label() is not fit for the \
+        value of MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN"
+#endif
+
+    *p++ = 0;
+    *p++ = (unsigned char)( ( desired_length >> 0 ) & 0xFF );
+
+    /* Add label incl. prefix */
+    *p++ = (unsigned char)( total_label_len & 0xFF );
+    memcpy( p, tls1_3_label_prefix, sizeof(tls1_3_label_prefix) );
+    p += sizeof(tls1_3_label_prefix);
+    memcpy( p, label, llen );
+    p += llen;
+
+    /* Add context value */
+    *p++ = (unsigned char)( clen & 0xFF );
+    if( clen != 0 )
+        memcpy( p, ctx, clen );
+
+    /* Return total length to the caller.  */
+    *dlen = total_hkdf_lbl_len;
+}
+
+int mbedtls_ssl_tls1_3_hkdf_expand_label(
+                     mbedtls_md_type_t hash_alg,
+                     const unsigned char *secret, size_t slen,
+                     const unsigned char *label, size_t llen,
+                     const unsigned char *ctx, size_t clen,
+                     unsigned char *buf, size_t blen )
+{
+    const mbedtls_md_info_t *md;
+    unsigned char hkdf_label[ SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN ];
+    size_t hkdf_label_len;
+
+    if( llen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN )
+    {
+        /* Should never happen since this is an internal
+         * function, and we know statically which labels
+         * are allowed. */
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    if( clen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN )
+    {
+        /* Should not happen, as above. */
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    if( blen > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN )
+    {
+        /* Should not happen, as above. */
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    md = mbedtls_md_info_from_type( hash_alg );
+    if( md == NULL )
+        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+    ssl_tls1_3_hkdf_encode_label( blen,
+                                  label, llen,
+                                  ctx, clen,
+                                  hkdf_label,
+                                  &hkdf_label_len );
+
+    return( mbedtls_hkdf_expand( md,
+                                 secret, slen,
+                                 hkdf_label, hkdf_label_len,
+                                 buf, blen ) );
+}
+
+/*
+ * The traffic keying material is generated from the following inputs:
+ *
+ *  - One secret value per sender.
+ *  - A purpose value indicating the specific value being generated
+ *  - The desired lengths of key and IV.
+ *
+ * The expansion itself is based on HKDF:
+ *
+ *   [sender]_write_key = HKDF-Expand-Label( Secret, "key", "", key_length )
+ *   [sender]_write_iv  = HKDF-Expand-Label( Secret, "iv" , "", iv_length )
+ *
+ * [sender] denotes the sending side and the Secret value is provided
+ * by the function caller. Note that we generate server and client side
+ * keys in a single function call.
+ */
+int mbedtls_ssl_tls1_3_make_traffic_keys(
+                     mbedtls_md_type_t hash_alg,
+                     const unsigned char *client_secret,
+                     const unsigned char *server_secret,
+                     size_t slen, size_t key_len, size_t iv_len,
+                     mbedtls_ssl_key_set *keys )
+{
+    int ret = 0;
+
+    ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
+                    client_secret, slen,
+                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ),
+                    NULL, 0,
+                    keys->client_write_key, key_len );
+    if( ret != 0 )
+        return( ret );
+
+    ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
+                    server_secret, slen,
+                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ),
+                    NULL, 0,
+                    keys->server_write_key, key_len );
+    if( ret != 0 )
+        return( ret );
+
+    ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
+                    client_secret, slen,
+                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ),
+                    NULL, 0,
+                    keys->client_write_iv, iv_len );
+    if( ret != 0 )
+        return( ret );
+
+    ret = mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
+                    server_secret, slen,
+                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ),
+                    NULL, 0,
+                    keys->server_write_iv, iv_len );
+    if( ret != 0 )
+        return( ret );
+
+    keys->key_len = key_len;
+    keys->iv_len = iv_len;
+
+    return( 0 );
+}
+
+int mbedtls_ssl_tls1_3_derive_secret(
+                   mbedtls_md_type_t hash_alg,
+                   const unsigned char *secret, size_t slen,
+                   const unsigned char *label, size_t llen,
+                   const unsigned char *ctx, size_t clen,
+                   int ctx_hashed,
+                   unsigned char *dstbuf, size_t buflen )
+{
+    int ret;
+    unsigned char hashed_context[ MBEDTLS_MD_MAX_SIZE ];
+
+    const mbedtls_md_info_t *md;
+    md = mbedtls_md_info_from_type( hash_alg );
+    if( md == NULL )
+        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+    if( ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED )
+    {
+        ret = mbedtls_md( md, ctx, clen, hashed_context );
+        if( ret != 0 )
+            return( ret );
+        clen = mbedtls_md_get_size( md );
+    }
+    else
+    {
+        if( clen > sizeof(hashed_context) )
+        {
+            /* This should never happen since this function is internal
+             * and the code sets `ctx_hashed` correctly.
+             * Let's double-check nonetheless to not run at the risk
+             * of getting a stack overflow. */
+            return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+        }
+
+        memcpy( hashed_context, ctx, clen );
+    }
+
+    return( mbedtls_ssl_tls1_3_hkdf_expand_label( hash_alg,
+                                                  secret, slen,
+                                                  label, llen,
+                                                  hashed_context, clen,
+                                                  dstbuf, buflen ) );
+}
+
+int mbedtls_ssl_tls1_3_evolve_secret(
+                   mbedtls_md_type_t hash_alg,
+                   const unsigned char *secret_old,
+                   const unsigned char *input, size_t input_len,
+                   unsigned char *secret_new )
+{
+    int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    size_t hlen, ilen;
+    unsigned char tmp_secret[ MBEDTLS_MD_MAX_SIZE ] = { 0 };
+    unsigned char tmp_input [ MBEDTLS_MD_MAX_SIZE ] = { 0 };
+
+    const mbedtls_md_info_t *md;
+    md = mbedtls_md_info_from_type( hash_alg );
+    if( md == NULL )
+        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+
+    hlen = mbedtls_md_get_size( md );
+
+    /* For non-initial runs, call Derive-Secret( ., "derived", "")
+     * on the old secret. */
+    if( secret_old != NULL )
+    {
+        ret = mbedtls_ssl_tls1_3_derive_secret(
+                   hash_alg,
+                   secret_old, hlen,
+                   MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( derived ),
+                   NULL, 0, /* context */
+                   MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
+                   tmp_secret, hlen );
+        if( ret != 0 )
+            goto cleanup;
+    }
+
+    if( input != NULL )
+    {
+        memcpy( tmp_input, input, input_len );
+        ilen = input_len;
+    }
+    else
+    {
+        ilen = hlen;
+    }
+
+    /* HKDF-Extract takes a salt and input key material.
+     * The salt is the old secret, and the input key material
+     * is the input secret (PSK / ECDHE). */
+    ret = mbedtls_hkdf_extract( md,
+                    tmp_secret, hlen,
+                    tmp_input, ilen,
+                    secret_new );
+    if( ret != 0 )
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+
+    mbedtls_platform_zeroize( tmp_secret, sizeof(tmp_secret) );
+    mbedtls_platform_zeroize( tmp_input,  sizeof(tmp_input)  );
+    return( ret );
+}
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
diff --git a/library/ssl_tls13_keys.h b/library/ssl_tls13_keys.h
new file mode 100644
index 0000000..7089049
--- /dev/null
+++ b/library/ssl_tls13_keys.h
@@ -0,0 +1,274 @@
+/*
+ *  TLS 1.3 key schedule
+ *
+ *  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_SSL_TLS1_3_KEYS_H)
+#define MBEDTLS_SSL_TLS1_3_KEYS_H
+
+/* This requires MBEDTLS_SSL_TLS1_3_LABEL( idx, name, string ) to be defined at
+ * the point of use. See e.g. the definition of mbedtls_ssl_tls1_3_labels_union
+ * below. */
+#define MBEDTLS_SSL_TLS1_3_LABEL_LIST                               \
+    MBEDTLS_SSL_TLS1_3_LABEL( finished    , "finished"     ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( resumption  , "resumption"   ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( traffic_upd , "traffic upd"  ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( exporter    , "exporter"     ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( key         , "key"          ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( iv          , "iv"           ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( c_hs_traffic, "c hs traffic" ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( c_ap_traffic, "c ap traffic" ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( c_e_traffic , "c e traffic"  ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( s_hs_traffic, "s hs traffic" ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( s_ap_traffic, "s ap traffic" ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( s_e_traffic , "s e traffic"  ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( e_exp_master, "e exp master" ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( res_master  , "res master"   ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( exp_master  , "exp master"   ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( ext_binder  , "ext binder"   ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( res_binder  , "res binder"   ) \
+    MBEDTLS_SSL_TLS1_3_LABEL( derived     , "derived"      )
+
+#define MBEDTLS_SSL_TLS1_3_LABEL( name, string )       \
+    const unsigned char name    [ sizeof(string) - 1 ];
+
+union mbedtls_ssl_tls1_3_labels_union
+{
+    MBEDTLS_SSL_TLS1_3_LABEL_LIST
+};
+struct mbedtls_ssl_tls1_3_labels_struct
+{
+    MBEDTLS_SSL_TLS1_3_LABEL_LIST
+};
+#undef MBEDTLS_SSL_TLS1_3_LABEL
+
+extern const struct mbedtls_ssl_tls1_3_labels_struct mbedtls_ssl_tls1_3_labels;
+
+#define MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( LABEL )  \
+    mbedtls_ssl_tls1_3_labels.LABEL,              \
+    sizeof(mbedtls_ssl_tls1_3_labels.LABEL)
+
+#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN  \
+    sizeof( union mbedtls_ssl_tls1_3_labels_union )
+
+/* The maximum length of HKDF contexts used in the TLS 1.3 standard.
+ * Since contexts are always hashes of message transcripts, this can
+ * be approximated from above by the maximum hash size. */
+#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN  \
+    MBEDTLS_MD_MAX_SIZE
+
+/* Maximum desired length for expanded key material generated
+ * by HKDF-Expand-Label.
+ *
+ * Warning: If this ever needs to be increased, the implementation
+ * ssl_tls1_3_hkdf_encode_label() in ssl_tls13_keys.c needs to be
+ * adjusted since it currently assumes that HKDF key expansion
+ * is never used with more than 255 Bytes of output. */
+#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN 255
+
+/**
+ * \brief           The \c HKDF-Expand-Label function from
+ *                  the TLS 1.3 standard RFC 8446.
+ *
+ * <tt>
+ *                  HKDF-Expand-Label( Secret, Label, Context, Length ) =
+ *                       HKDF-Expand( Secret, HkdfLabel, Length )
+ * </tt>
+ *
+ * \param hash_alg  The identifier for the hash algorithm to use.
+ * \param secret    The \c Secret argument to \c HKDF-Expand-Label.
+ *                  This must be a readable buffer of length \p slen Bytes.
+ * \param slen      The length of \p secret in Bytes.
+ * \param label     The \c Label argument to \c HKDF-Expand-Label.
+ *                  This must be a readable buffer of length \p llen Bytes.
+ * \param llen      The length of \p label in Bytes.
+ * \param ctx       The \c Context argument to \c HKDF-Expand-Label.
+ *                  This must be a readable buffer of length \p clen Bytes.
+ * \param clen      The length of \p context in Bytes.
+ * \param buf       The destination buffer to hold the expanded secret.
+ *                  This must be a writable buffer of length \p blen Bytes.
+ * \param blen      The desired size of the expanded secret in Bytes.
+ *
+ * \returns         \c 0 on success.
+ * \return          A negative error code on failure.
+ */
+
+int mbedtls_ssl_tls1_3_hkdf_expand_label(
+                     mbedtls_md_type_t hash_alg,
+                     const unsigned char *secret, size_t slen,
+                     const unsigned char *label, size_t llen,
+                     const unsigned char *ctx, size_t clen,
+                     unsigned char *buf, size_t blen );
+
+/**
+ * \brief           This function is part of the TLS 1.3 key schedule.
+ *                  It extracts key and IV for the actual client/server traffic
+ *                  from the client/server traffic secrets.
+ *
+ * From RFC 8446:
+ *
+ * <tt>
+ *   [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
+ *   [sender]_write_iv  = HKDF-Expand-Label(Secret, "iv", "", iv_length)*
+ * </tt>
+ *
+ * \param hash_alg      The identifier for the hash algorithm to be used
+ *                      for the HKDF-based expansion of the secret.
+ * \param client_secret The client traffic secret.
+ *                      This must be a readable buffer of size \p slen Bytes
+ * \param server_secret The server traffic secret.
+ *                      This must be a readable buffer of size \p slen Bytes
+ * \param slen          Length of the secrets \p client_secret and
+ *                      \p server_secret in Bytes.
+ * \param key_len       The desired length of the key to be extracted in Bytes.
+ * \param iv_len        The desired length of the IV to be extracted in Bytes.
+ * \param keys          The address of the structure holding the generated
+ *                      keys and IVs.
+ *
+ * \returns             \c 0 on success.
+ * \returns             A negative error code on failure.
+ */
+
+int mbedtls_ssl_tls1_3_make_traffic_keys(
+                     mbedtls_md_type_t hash_alg,
+                     const unsigned char *client_secret,
+                     const unsigned char *server_secret,
+                     size_t slen, size_t key_len, size_t iv_len,
+                     mbedtls_ssl_key_set *keys );
+
+
+#define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0
+#define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED   1
+
+/**
+ * \brief The \c Derive-Secret function from the TLS 1.3 standard RFC 8446.
+ *
+ * <tt>
+ *   Derive-Secret( Secret, Label, Messages ) =
+ *      HKDF-Expand-Label( Secret, Label,
+ *                         Hash( Messages ),
+ *                         Hash.Length ) )
+ * </tt>
+ *
+ * \param hash_alg   The identifier for the hash function used for the
+ *                   applications of HKDF.
+ * \param secret     The \c Secret argument to the \c Derive-Secret function.
+ *                   This must be a readable buffer of length \p slen Bytes.
+ * \param slen       The length of \p secret in Bytes.
+ * \param label      The \c Label argument to the \c Derive-Secret function.
+ *                   This must be a readable buffer of length \p llen Bytes.
+ * \param llen       The length of \p label in Bytes.
+ * \param ctx        The hash of the \c Messages argument to the
+ *                   \c Derive-Secret function, or the \c Messages argument
+ *                   itself, depending on \p context_already_hashed.
+ * \param clen       The length of \p hash.
+ * \param ctx_hashed This indicates whether the \p ctx contains the hash of
+ *                   the \c Messages argument in the application of the
+ *                   \c Derive-Secret function
+ *                   (value MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED), or whether
+ *                   it is the content of \c Messages itself, in which case
+ *                   the function takes care of the hashing
+ *                   (value MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED).
+ * \param dstbuf     The target buffer to write the output of
+ *                   \c Derive-Secret to. This must be a writable buffer of
+ *                   size \p buflen Bytes.
+ * \param buflen     The length of \p dstbuf in Bytes.
+ *
+ * \returns        \c 0 on success.
+ * \returns        A negative error code on failure.
+ */
+int mbedtls_ssl_tls1_3_derive_secret(
+                   mbedtls_md_type_t hash_alg,
+                   const unsigned char *secret, size_t slen,
+                   const unsigned char *label, size_t llen,
+                   const unsigned char *ctx, size_t clen,
+                   int ctx_hashed,
+                   unsigned char *dstbuf, size_t buflen );
+
+/**
+ * \brief Compute the next secret in the TLS 1.3 key schedule
+ *
+ * The TLS 1.3 key schedule proceeds as follows to compute
+ * the three main secrets during the handshake: The early
+ * secret for early data, the handshake secret for all
+ * other encrypted handshake messages, and the master
+ * secret for all application traffic.
+ *
+ * <tt>
+ *                    0
+ *                    |
+ *                    v
+ *     PSK ->  HKDF-Extract = Early Secret
+ *                    |
+ *                    v
+ *     Derive-Secret( ., "derived", "" )
+ *                    |
+ *                    v
+ *  (EC)DHE -> HKDF-Extract = Handshake Secret
+ *                    |
+ *                    v
+ *     Derive-Secret( ., "derived", "" )
+ *                    |
+ *                    v
+ *     0 -> HKDF-Extract = Master Secret
+ * </tt>
+ *
+ * Each of the three secrets in turn is the basis for further
+ * key derivations, such as the derivation of traffic keys and IVs;
+ * see e.g. mbedtls_ssl_tls1_3_make_traffic_keys().
+ *
+ * This function implements one step in this evolution of secrets:
+ *
+ * <tt>
+ *                old_secret
+ *                    |
+ *                    v
+ *     Derive-Secret( ., "derived", "" )
+ *                    |
+ *                    v
+ *     input -> HKDF-Extract = new_secret
+ * </tt>
+ *
+ * \param hash_alg    The identifier for the hash function used for the
+ *                    applications of HKDF.
+ * \param secret_old  The address of the buffer holding the old secret
+ *                    on function entry. If not \c NULL, this must be a
+ *                    readable buffer whose size matches the output size
+ *                    of the hash function represented by \p hash_alg.
+ *                    If \c NULL, an all \c 0 array will be used instead.
+ * \param input       The address of the buffer holding the additional
+ *                    input for the key derivation (e.g., the PSK or the
+ *                    ephemeral (EC)DH secret). If not \c NULL, this must be
+ *                    a readable buffer whose size \p input_len Bytes.
+ *                    If \c NULL, an all \c 0 array will be used instead.
+ * \param input_len   The length of \p input in Bytes.
+ * \param secret_new  The address of the buffer holding the new secret
+ *                    on function exit. This must be a writable buffer
+ *                    whose size matches the output size of the hash
+ *                    function represented by \p hash_alg.
+ *                    This may be the same as \p secret_old.
+ *
+ * \returns           \c 0 on success.
+ * \returns           A negative error code on failure.
+ */
+
+int mbedtls_ssl_tls1_3_evolve_secret(
+                   mbedtls_md_type_t hash_alg,
+                   const unsigned char *secret_old,
+                   const unsigned char *input, size_t input_len,
+                   unsigned char *secret_new );
+
+#endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */
diff --git a/library/version_features.c b/library/version_features.c
index d2840fa..478d8fa 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -417,9 +417,9 @@
 #if defined(MBEDTLS_ENTROPY_NV_SEED)
     "MBEDTLS_ENTROPY_NV_SEED",
 #endif /* MBEDTLS_ENTROPY_NV_SEED */
-#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER)
-    "MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER",
-#endif /* MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER */
+#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+    "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER",
+#endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
 #if defined(MBEDTLS_MEMORY_DEBUG)
     "MBEDTLS_MEMORY_DEBUG",
 #endif /* MBEDTLS_MEMORY_DEBUG */
@@ -435,6 +435,9 @@
 #if defined(MBEDTLS_PKCS1_V21)
     "MBEDTLS_PKCS1_V21",
 #endif /* MBEDTLS_PKCS1_V21 */
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
+    "MBEDTLS_PSA_CRYPTO_DRIVERS",
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
 #if defined(MBEDTLS_PSA_CRYPTO_SPM)
     "MBEDTLS_PSA_CRYPTO_SPM",
 #endif /* MBEDTLS_PSA_CRYPTO_SPM */
diff --git a/library/x509.c b/library/x509.c
index 1579c1a..2a7be32 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -154,7 +154,7 @@
         return( MBEDTLS_ERR_X509_INVALID_ALG +
                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
 
-    p = (unsigned char *) alg->p;
+    p = alg->p;
     end = p + alg->len;
 
     if( p >= end )
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 f9c2608..9cbc471 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -8,7 +8,7 @@
 LDFLAGS ?=
 
 MBEDTLS_TEST_PATH:=../tests/src
-MBEDTLS_TEST_OBJS:=$(patsubst %.c,%.o,$(wildcard ${MBEDTLS_TEST_PATH}/*.c))
+MBEDTLS_TEST_OBJS:=$(patsubst %.c,%.o,$(wildcard ${MBEDTLS_TEST_PATH}/*.c ${MBEDTLS_TEST_PATH}/drivers/*.c))
 
 LOCAL_CFLAGS = $(WARNING_CFLAGS) -I../tests/include -I../include -D_FILE_OFFSET_BITS=64
 LOCAL_CXXFLAGS = $(WARNING_CXXFLAGS) -I../include -D_FILE_OFFSET_BITS=64
@@ -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/fuzz/Makefile b/programs/fuzz/Makefile
index 8196f39..fa17918 100644
--- a/programs/fuzz/Makefile
+++ b/programs/fuzz/Makefile
@@ -1,5 +1,5 @@
 MBEDTLS_TEST_PATH:=../../tests/src
-MBEDTLS_TEST_OBJS:=$(patsubst %.c,%.o,$(wildcard ${MBEDTLS_TEST_PATH}/*.c))
+MBEDTLS_TEST_OBJS:=$(patsubst %.c,%.o,$(wildcard ${MBEDTLS_TEST_PATH}/*.c ${MBEDTLS_TEST_PATH}/drivers/*.c))
 
 LOCAL_CFLAGS = -I../../tests/include -I../../include -D_FILE_OFFSET_BITS=64
 LOCAL_LDFLAGS = ${MBEDTLS_TEST_OBJS}		\
diff --git a/programs/pkey/ecdh_curve25519.c b/programs/pkey/ecdh_curve25519.c
index a76266f..67f1363 100644
--- a/programs/pkey/ecdh_curve25519.c
+++ b/programs/pkey/ecdh_curve25519.c
@@ -86,7 +86,7 @@
     mbedtls_printf( " ok\n" );
 
     /*
-     * Client: inialize context and generate keypair
+     * Client: initialize context and generate keypair
      */
     mbedtls_printf( "  . Setting up client context..." );
     fflush( stdout );
diff --git a/programs/psa/CMakeLists.txt b/programs/psa/CMakeLists.txt
index e519696..5cbcf71 100644
--- a/programs/psa/CMakeLists.txt
+++ b/programs/psa/CMakeLists.txt
@@ -12,13 +12,6 @@
 
 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/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/test/query_config.c b/programs/test/query_config.c
index f4c14d6..8873734 100644
--- a/programs/test/query_config.c
+++ b/programs/test/query_config.c
@@ -1168,13 +1168,13 @@
     }
 #endif /* MBEDTLS_ENTROPY_NV_SEED */
 
-#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER)
-    if( strcmp( "MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER", config ) == 0 )
+#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+    if( strcmp( "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER", config ) == 0 )
     {
-        MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER );
+        MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER );
         return( 0 );
     }
-#endif /* MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER */
+#endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
 
 #if defined(MBEDTLS_MEMORY_DEBUG)
     if( strcmp( "MBEDTLS_MEMORY_DEBUG", config ) == 0 )
@@ -1216,6 +1216,14 @@
     }
 #endif /* MBEDTLS_PKCS1_V21 */
 
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
+    if( strcmp( "MBEDTLS_PSA_CRYPTO_DRIVERS", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_PSA_CRYPTO_DRIVERS );
+        return( 0 );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
+
 #if defined(MBEDTLS_PSA_CRYPTO_SPM)
     if( strcmp( "MBEDTLS_PSA_CRYPTO_SPM", config ) == 0 )
     {
diff --git a/scripts/config.py b/scripts/config.py
index 703e6e9..017bba0 100755
--- a/scripts/config.py
+++ b/scripts/config.py
@@ -184,7 +184,6 @@
     '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_KEY_FILE_ID_ENCODES_OWNER', # platform dependency (PSA SPM) (at this time)
     '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/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/scripts/generate_visualc_files.pl b/scripts/generate_visualc_files.pl
index 3d4baca..6c2b5e4 100755
--- a/scripts/generate_visualc_files.pl
+++ b/scripts/generate_visualc_files.pl
@@ -39,6 +39,7 @@
 my $source_dir = 'library';
 my $test_source_dir = 'tests/src';
 my $test_header_dir = 'tests/include/test';
+my $test_drivers_header_dir = 'tests/include/test/drivers';
 
 my @thirdparty_header_dirs = qw(
     3rdparty/everest/include/everest
@@ -116,6 +117,7 @@
         && -d $source_dir
         && -d $test_source_dir
         && -d $test_header_dir
+        && -d $test_drivers_header_dir
         && -d $programs_dir;
 }
 
@@ -262,6 +264,7 @@
                        $mbedtls_header_dir,
                        $psa_header_dir,
                        $test_header_dir,
+                       $test_drivers_header_dir,
                        $source_dir,
                        @thirdparty_header_dirs,
                       );
diff --git a/tests/.gitignore b/tests/.gitignore
index d49611c..d9f4b51 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -11,4 +11,5 @@
 include/test/instrument_record_status.h
 
 src/*.o
+src/drivers/*.o
 src/libmbed*
diff --git a/tests/Makefile b/tests/Makefile
index ffa4812..511db9d 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -80,7 +80,7 @@
 $(MBEDLIBS):
 	$(MAKE) -C ../library
 
-MBEDTLS_TEST_OBJS=$(patsubst %.c,%.o,$(wildcard src/*.c))
+MBEDTLS_TEST_OBJS=$(patsubst %.c,%.o,$(wildcard src/*.c src/drivers/*.c))
 
 mbedtls_test: $(MBEDTLS_TEST_OBJS)
 
@@ -89,6 +89,10 @@
 	echo "  CC    $<"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $<
 
+src/drivers/%.o : src/drivers/%.c
+	echo "  CC    $<"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $<
+
 C_FILES := $(addsuffix .c,$(APPS))
 
 # Wildcard target for test code generation:
@@ -130,12 +134,13 @@
 clean:
 ifndef WINDOWS
 	rm -rf $(BINARIES) *.c *.datax TESTS
-	rm -f src/*.o src/libmbed*
+	rm -f src/*.o src/drivers/*.o src/libmbed*
 else
 	if exist *.c del /Q /F *.c
 	if exist *.exe del /Q /F *.exe
 	if exist *.datax del /Q /F *.datax
 	if exist src/*.o del /Q /F src/*.o
+	if exist src/drivers/*.o del /Q /F src/drivers/*.o
 	if exist src/libmbed* del /Q /F src/libmed*
 ifneq ($(wildcard TESTS/.*),)
 	rmdir /Q /S TESTS
diff --git a/tests/include/test/drivers/cipher.h b/tests/include/test/drivers/cipher.h
new file mode 100644
index 0000000..ef787f7
--- /dev/null
+++ b/tests/include/test/drivers/cipher.h
@@ -0,0 +1,180 @@
+/*
+ * Test driver for cipher 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_CIPHER_H
+#define PSA_CRYPTO_TEST_DRIVERS_CIPHER_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>
+
+#include "mbedtls/cipher.h"
+typedef struct {
+    psa_algorithm_t alg;
+    unsigned int key_set : 1;
+    unsigned int iv_required : 1;
+    unsigned int iv_set : 1;
+    uint8_t iv_size;
+    uint8_t block_size;
+    mbedtls_cipher_context_t cipher;
+} test_transparent_cipher_operation_t;
+
+typedef struct{
+    unsigned int initialised : 1;
+    test_transparent_cipher_operation_t ctx;
+} test_opaque_cipher_operation_t;
+
+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 cipher driver functions is called. */
+    unsigned long hits;
+} test_driver_cipher_hooks_t;
+
+#define TEST_DRIVER_CIPHER_INIT { NULL, 0, PSA_SUCCESS, 0 }
+static inline test_driver_cipher_hooks_t test_driver_cipher_hooks_init( void )
+{
+    const test_driver_cipher_hooks_t v = TEST_DRIVER_CIPHER_INIT;
+    return( v );
+}
+
+extern test_driver_cipher_hooks_t test_driver_cipher_hooks;
+
+psa_status_t test_transparent_cipher_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output, size_t output_size, size_t *output_length);
+
+psa_status_t test_transparent_cipher_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output, size_t output_size, size_t *output_length);
+
+psa_status_t test_transparent_cipher_encrypt_setup(
+    test_transparent_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg);
+
+psa_status_t test_transparent_cipher_decrypt_setup(
+    test_transparent_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg);
+
+psa_status_t test_transparent_cipher_abort(
+    test_transparent_cipher_operation_t *operation);
+
+psa_status_t test_transparent_cipher_generate_iv(
+    test_transparent_cipher_operation_t *operation,
+    uint8_t *iv,
+    size_t iv_size,
+    size_t *iv_length);
+
+psa_status_t test_transparent_cipher_set_iv(
+    test_transparent_cipher_operation_t *operation,
+    const uint8_t *iv,
+    size_t iv_length);
+
+psa_status_t test_transparent_cipher_update(
+    test_transparent_cipher_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length);
+
+psa_status_t test_transparent_cipher_finish(
+    test_transparent_cipher_operation_t *operation,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length);
+
+/*
+ * opaque versions
+ */
+psa_status_t test_opaque_cipher_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output, size_t output_size, size_t *output_length);
+
+psa_status_t test_opaque_cipher_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output, size_t output_size, size_t *output_length);
+
+psa_status_t test_opaque_cipher_encrypt_setup(
+    test_opaque_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg);
+
+psa_status_t test_opaque_cipher_decrypt_setup(
+    test_opaque_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg);
+
+psa_status_t test_opaque_cipher_abort(
+    test_opaque_cipher_operation_t *operation);
+
+psa_status_t test_opaque_cipher_generate_iv(
+    test_opaque_cipher_operation_t *operation,
+    uint8_t *iv,
+    size_t iv_size,
+    size_t *iv_length);
+
+psa_status_t test_opaque_cipher_set_iv(
+    test_opaque_cipher_operation_t *operation,
+    const uint8_t *iv,
+    size_t iv_length);
+
+psa_status_t test_opaque_cipher_update(
+    test_opaque_cipher_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length);
+
+psa_status_t test_opaque_cipher_finish(
+    test_opaque_cipher_operation_t *operation,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length);
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_TEST_DRIVERS_CIPHER_H */
diff --git a/tests/include/test/drivers/keygen.h b/tests/include/test/drivers/keygen.h
new file mode 100644
index 0000000..b72c65c
--- /dev/null
+++ b/tests/include/test/drivers/keygen.h
@@ -0,0 +1,61 @@
+/*
+ * 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
new file mode 100644
index 0000000..e41892e
--- /dev/null
+++ b/tests/include/test/drivers/signature.h
@@ -0,0 +1,82 @@
+/*
+ * Test driver for signature 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_SIGNATURE_H
+#define PSA_CRYPTO_TEST_DRIVERS_SIGNATURE_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_signature_hooks_t;
+
+#define TEST_DRIVER_SIGNATURE_INIT { NULL, 0, PSA_ERROR_NOT_SUPPORTED, 0 }
+static inline test_driver_signature_hooks_t test_driver_signature_hooks_init( void )
+{
+    const test_driver_signature_hooks_t v = TEST_DRIVER_SIGNATURE_INIT;
+    return( v );
+}
+
+extern test_driver_signature_hooks_t test_driver_signature_sign_hooks;
+extern test_driver_signature_hooks_t test_driver_signature_verify_hooks;
+
+psa_status_t test_transparent_signature_sign_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length );
+
+psa_status_t test_opaque_signature_sign_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length );
+
+psa_status_t test_transparent_signature_verify_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length );
+
+psa_status_t test_opaque_signature_verify_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length );
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_TEST_DRIVERS_SIGNATURE_H */
diff --git a/tests/include/test/drivers/test_driver.h b/tests/include/test/drivers/test_driver.h
new file mode 100644
index 0000000..7ee8e5e
--- /dev/null
+++ b/tests/include/test/drivers/test_driver.h
@@ -0,0 +1,29 @@
+/*
+ * Umbrella include for all of the test driver functionality
+ */
+/*  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_DRIVER_H
+#define PSA_CRYPTO_TEST_DRIVER_H
+
+#define PSA_CRYPTO_TEST_DRIVER_LIFETIME 0x7fffff
+
+#include "test/drivers/signature.h"
+#include "test/drivers/keygen.h"
+#include "test/drivers/cipher.h"
+
+#endif /* PSA_CRYPTO_TEST_DRIVER_H */
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index ca73722..578d03e 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -1217,16 +1217,34 @@
     record_status tests/scripts/curves.pl
 }
 
+component_test_depends_curves_psa () {
+    msg "test/build: curves.pl with MBEDTLS_USE_PSA_CRYPTO defined (gcc)"
+    scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
+    record_status tests/scripts/curves.pl
+}
+
 component_test_depends_hashes () {
     msg "test/build: depends-hashes.pl (gcc)" # ~ 2 min
     record_status tests/scripts/depends-hashes.pl
 }
 
+component_test_depends_hashes_psa () {
+    msg "test/build: depends-hashes.pl with MBEDTLS_USE_PSA_CRYPTO defined (gcc)"
+    scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
+    record_status tests/scripts/depends-hashes.pl
+}
+
 component_test_depends_pkalgs () {
     msg "test/build: depends-pkalgs.pl (gcc)" # ~ 2 min
     record_status tests/scripts/depends-pkalgs.pl
 }
 
+component_test_depends_pkalgs_psa () {
+    msg "test/build: depends-pkalgs.pl with MBEDTLS_USE_PSA_CRYPTO defined (gcc)"
+    scripts/config.py set MBEDTLS_USE_PSA_CRYPTO
+    record_status tests/scripts/depends-pkalgs.pl
+}
+
 component_build_key_exchanges () {
     msg "test/build: key-exchanges (gcc)" # ~ 1 min
     record_status tests/scripts/key-exchanges.pl
@@ -1656,6 +1674,16 @@
     make test
 }
 
+component_test_psa_crypto_drivers () {
+    msg "build: MBEDTLS_PSA_CRYPTO_DRIVERS w/ driver hooks"
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    # 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: MBEDTLS_PSA_CRYPTO_DRIVERS, signature"
+    make test
+}
+
 component_test_make_shared () {
     msg "build/test: make shared" # ~ 40s
     make SHARED=1 all check
@@ -1827,7 +1855,7 @@
 component_build_arm_none_eabi_gcc () {
     msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1" # ~ 10s
     scripts/config.py baremetal
-    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-Werror -Wall -Wextra -O1' lib
+    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-std=c99 -Werror -Wall -Wextra -O1' lib
 
     msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -O1"
     ${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
@@ -1841,7 +1869,7 @@
     # See https://github.com/ARMmbed/mbedtls/pull/2169 and comments.
     # It would be better to build with arm-linux-gnueabi-gcc but
     # we don't have that on our CI at this time.
-    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" CFLAGS='-Werror -Wall -Wextra -march=armv5te -O1' LDFLAGS='-march=armv5te' SHELL='sh -x' lib
+    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" CFLAGS='-std=c99 -Werror -Wall -Wextra -march=armv5te -O1' LDFLAGS='-march=armv5te' SHELL='sh -x' lib
 
     msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -march=armv5te -O1"
     ${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
@@ -1850,7 +1878,7 @@
 component_build_arm_none_eabi_gcc_m0plus () {
     msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -mthumb -mcpu=cortex-m0plus" # ~ 10s
     scripts/config.py baremetal
-    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-Werror -Wall -Wextra -mthumb -mcpu=cortex-m0plus -Os' lib
+    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-std=c99 -Werror -Wall -Wextra -mthumb -mcpu=cortex-m0plus -Os' lib
 
     msg "size: ${ARM_NONE_EABI_GCC_PREFIX}gcc -mthumb -mcpu=cortex-m0plus -Os"
     ${ARM_NONE_EABI_GCC_PREFIX}size library/*.o
@@ -1860,7 +1888,7 @@
     msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc -DMBEDTLS_NO_UDBL_DIVISION, make" # ~ 10s
     scripts/config.py baremetal
     scripts/config.py set MBEDTLS_NO_UDBL_DIVISION
-    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-Werror -Wall -Wextra' lib
+    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-std=c99 -Werror -Wall -Wextra' lib
     echo "Checking that software 64-bit division is not required"
     if_build_succeeded not grep __aeabi_uldiv library/*.o
 }
@@ -1869,7 +1897,7 @@
     msg "build: ${ARM_NONE_EABI_GCC_PREFIX}gcc MBEDTLS_NO_64BIT_MULTIPLICATION, make" # ~ 10s
     scripts/config.py baremetal
     scripts/config.py set MBEDTLS_NO_64BIT_MULTIPLICATION
-    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-Werror -O1 -march=armv6-m -mthumb' lib
+    make CC="${ARM_NONE_EABI_GCC_PREFIX}gcc" AR="${ARM_NONE_EABI_GCC_PREFIX}ar" LD="${ARM_NONE_EABI_GCC_PREFIX}ld" CFLAGS='-std=c99 -Werror -O1 -march=armv6-m -mthumb' lib
     echo "Checking that software 64-bit multiplication is not required"
     if_build_succeeded not grep __aeabi_lmul library/*.o
 }
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/src/drivers/cipher.c b/tests/src/drivers/cipher.c
new file mode 100644
index 0000000..fa7c6a9
--- /dev/null
+++ b/tests/src/drivers/cipher.c
@@ -0,0 +1,611 @@
+/*
+ * Test driver for cipher functions.
+ * Currently only supports multi-part operations using AES-CTR.
+ */
+/*  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/cipher.h"
+
+#include "test/drivers/cipher.h"
+
+#include "test/random.h"
+
+#include <string.h>
+
+/* Test driver implements AES-CTR only. Its default behaviour (when its return
+ * status is not overridden through the hooks) is to take care of all AES-CTR
+ * operations, and return PSA_ERROR_NOT_SUPPORTED for all others.
+ * Set test_driver_cipher_hooks.forced_status to PSA_ERROR_NOT_SUPPORTED to use
+ * fallback even for AES-CTR. */
+test_driver_cipher_hooks_t test_driver_cipher_hooks = TEST_DRIVER_CIPHER_INIT;
+
+static psa_status_t test_transparent_cipher_oneshot(
+    mbedtls_operation_t direction,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output, size_t output_size, size_t *output_length)
+{
+    test_driver_cipher_hooks.hits++;
+
+    /* Test driver supports AES-CTR only, to verify operation calls. */
+    if( alg != PSA_ALG_CTR ||
+        psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    /* If test driver response code is not SUCCESS, we can return early */
+    if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( test_driver_cipher_hooks.forced_status );
+
+    /* If test driver output is overridden, we don't need to do actual crypto */
+    if( test_driver_cipher_hooks.forced_output != NULL )
+    {
+        if( output_size < test_driver_cipher_hooks.forced_output_length )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+        memcpy( output,
+                test_driver_cipher_hooks.forced_output,
+                test_driver_cipher_hooks.forced_output_length );
+        *output_length = test_driver_cipher_hooks.forced_output_length;
+
+        return( test_driver_cipher_hooks.forced_status );
+    }
+
+    /* Run AES-CTR using the cipher module */
+    {
+        mbedtls_test_rnd_pseudo_info rnd_info;
+        memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
+
+        const mbedtls_cipher_info_t *cipher_info =
+            mbedtls_cipher_info_from_values( MBEDTLS_CIPHER_ID_AES,
+                                             key_length * 8,
+                                             MBEDTLS_MODE_CTR );
+        mbedtls_cipher_context_t cipher;
+        int ret = 0;
+        uint8_t temp_output_buffer[16] = {0};
+        size_t temp_output_length = 0;
+
+        if( direction == MBEDTLS_ENCRYPT )
+        {
+            /* Oneshot encrypt needs to prepend the IV to the output */
+            if( output_size < ( input_length + 16 ) )
+                return( PSA_ERROR_BUFFER_TOO_SMALL );
+        }
+        else
+        {
+            /* Oneshot decrypt has the IV prepended to the input */
+            if( output_size < ( input_length - 16 ) )
+                return( PSA_ERROR_BUFFER_TOO_SMALL );
+        }
+
+        if( cipher_info == NULL )
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        mbedtls_cipher_init( &cipher );
+        ret = mbedtls_cipher_setup( &cipher, cipher_info );
+        if( ret != 0 )
+            goto exit;
+
+        ret = mbedtls_cipher_setkey( &cipher,
+                                     key,
+                                     key_length * 8, direction );
+        if( ret != 0 )
+            goto exit;
+
+        if( direction == MBEDTLS_ENCRYPT )
+        {
+            mbedtls_test_rnd_pseudo_info rnd_info;
+            memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
+
+            ret = mbedtls_test_rnd_pseudo_rand( &rnd_info,
+                                                temp_output_buffer,
+                                                16 );
+            if( ret != 0 )
+                goto exit;
+
+            ret = mbedtls_cipher_set_iv( &cipher, temp_output_buffer, 16 );
+        }
+        else
+            ret = mbedtls_cipher_set_iv( &cipher, input, 16 );
+
+        if( ret != 0 )
+            goto exit;
+
+        if( direction == MBEDTLS_ENCRYPT )
+        {
+            ret = mbedtls_cipher_update( &cipher,
+                                         input, input_length,
+                                         &output[16], output_length );
+            if( ret == 0 )
+            {
+                memcpy( output, temp_output_buffer, 16 );
+                *output_length += 16;
+            }
+        }
+        else
+            ret = mbedtls_cipher_update( &cipher,
+                                         &input[16], input_length - 16,
+                                         output, output_length );
+
+        if( ret != 0 )
+            goto exit;
+
+        ret = mbedtls_cipher_finish( &cipher,
+                                     temp_output_buffer,
+                                     &temp_output_length );
+
+exit:
+        if( ret != 0 )
+        {
+            *output_length = 0;
+            memset(output, 0, output_size);
+        }
+
+        mbedtls_cipher_free( &cipher );
+        return( mbedtls_to_psa_error( ret ) );
+    }
+}
+
+psa_status_t test_transparent_cipher_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output, size_t output_size, size_t *output_length)
+{
+    return (
+        test_transparent_cipher_oneshot(
+            MBEDTLS_ENCRYPT,
+            attributes,
+            key, key_length,
+            alg,
+            input, input_length,
+            output, output_size, output_length) );
+}
+
+psa_status_t test_transparent_cipher_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output, size_t output_size, size_t *output_length)
+{
+    return (
+        test_transparent_cipher_oneshot(
+            MBEDTLS_DECRYPT,
+            attributes,
+            key, key_length,
+            alg,
+            input, input_length,
+            output, output_size, output_length) );
+}
+
+static psa_status_t test_transparent_cipher_setup(
+    mbedtls_operation_t direction,
+    test_transparent_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg)
+{
+    const mbedtls_cipher_info_t *cipher_info = NULL;
+    int ret = 0;
+
+    test_driver_cipher_hooks.hits++;
+
+    if( operation->alg != 0 )
+        return( PSA_ERROR_BAD_STATE );
+
+    /* Wiping the entire struct here, instead of member-by-member. This is useful
+     * for the test suite, since it gives a chance of catching memory corruption
+     * errors should the core not have allocated (enough) memory for our context
+     * struct. */
+    memset( operation, 0, sizeof( *operation ) );
+
+    /* Allow overriding return value for testing purposes */
+    if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( test_driver_cipher_hooks.forced_status );
+
+    /* Test driver supports AES-CTR only, to verify operation calls. */
+    if( alg != PSA_ALG_CTR ||
+        psa_get_key_type( attributes ) != PSA_KEY_TYPE_AES )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    operation->alg = alg;
+    operation->iv_size = 16;
+
+    cipher_info = mbedtls_cipher_info_from_values( MBEDTLS_CIPHER_ID_AES,
+                                                   key_length * 8,
+                                                   MBEDTLS_MODE_CTR );
+    if( cipher_info == NULL )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    mbedtls_cipher_init( &operation->cipher );
+    ret = mbedtls_cipher_setup( &operation->cipher, cipher_info );
+    if( ret != 0 ) {
+        mbedtls_cipher_free( &operation->cipher );
+        return( mbedtls_to_psa_error( ret ) );
+    }
+
+    ret = mbedtls_cipher_setkey( &operation->cipher,
+                                 key,
+                                 key_length * 8, direction );
+    if( ret != 0 ) {
+        mbedtls_cipher_free( &operation->cipher );
+        return( mbedtls_to_psa_error( ret ) );
+    }
+
+    operation->iv_set = 0;
+    operation->iv_required = 1;
+    operation->key_set = 1;
+
+    return( test_driver_cipher_hooks.forced_status );
+}
+
+psa_status_t test_transparent_cipher_encrypt_setup(
+    test_transparent_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg)
+{
+    return ( test_transparent_cipher_setup( MBEDTLS_ENCRYPT,
+                                            operation,
+                                            attributes,
+                                            key,
+                                            key_length,
+                                            alg ) );
+}
+
+psa_status_t test_transparent_cipher_decrypt_setup(
+    test_transparent_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg)
+{
+    return ( test_transparent_cipher_setup( MBEDTLS_DECRYPT,
+                                            operation,
+                                            attributes,
+                                            key,
+                                            key_length,
+                                            alg ) );
+}
+
+psa_status_t test_transparent_cipher_abort(
+    test_transparent_cipher_operation_t *operation)
+{
+    test_driver_cipher_hooks.hits++;
+
+    if( operation->alg == 0 )
+        return( PSA_SUCCESS );
+    if( operation->alg != PSA_ALG_CTR )
+        return( PSA_ERROR_BAD_STATE );
+
+    mbedtls_cipher_free( &operation->cipher );
+
+    /* Wiping the entire struct here, instead of member-by-member. This is useful
+     * for the test suite, since it gives a chance of catching memory corruption
+     * errors should the core not have allocated (enough) memory for our context
+     * struct. */
+    memset( operation, 0, sizeof( *operation ) );
+
+    return( PSA_SUCCESS );
+}
+
+psa_status_t test_transparent_cipher_generate_iv(
+    test_transparent_cipher_operation_t *operation,
+    uint8_t *iv,
+    size_t iv_size,
+    size_t *iv_length)
+{
+    psa_status_t status;
+    mbedtls_test_rnd_pseudo_info rnd_info;
+    memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
+
+    test_driver_cipher_hooks.hits++;
+
+    if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( test_driver_cipher_hooks.forced_status );
+
+    if( operation->alg != PSA_ALG_CTR )
+        return( PSA_ERROR_BAD_STATE );
+
+    if( operation->iv_set || ! operation->iv_required )
+        return( PSA_ERROR_BAD_STATE );
+
+    if( iv_size < operation->iv_size )
+        return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+    status = mbedtls_to_psa_error(
+        mbedtls_test_rnd_pseudo_rand( &rnd_info,
+                                      iv,
+                                      operation->iv_size ) );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    *iv_length = operation->iv_size;
+    status = test_transparent_cipher_set_iv( operation, iv, *iv_length );
+
+    return( status );
+}
+
+psa_status_t test_transparent_cipher_set_iv(
+    test_transparent_cipher_operation_t *operation,
+    const uint8_t *iv,
+    size_t iv_length)
+{
+    psa_status_t status;
+
+    test_driver_cipher_hooks.hits++;
+
+    if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( test_driver_cipher_hooks.forced_status );
+
+    if( operation->alg != PSA_ALG_CTR )
+        return( PSA_ERROR_BAD_STATE );
+
+    if( operation->iv_set || ! operation->iv_required )
+        return( PSA_ERROR_BAD_STATE );
+
+    if( iv_length != operation->iv_size )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    status = mbedtls_to_psa_error(
+        mbedtls_cipher_set_iv( &operation->cipher, iv, iv_length ) );
+
+    if( status == PSA_SUCCESS )
+        operation->iv_set = 1;
+
+    return( status );
+}
+
+psa_status_t test_transparent_cipher_update(
+    test_transparent_cipher_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length)
+{
+    psa_status_t status;
+
+    test_driver_cipher_hooks.hits++;
+
+    if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( test_driver_cipher_hooks.forced_status );
+
+    if( operation->alg != PSA_ALG_CTR )
+        return( PSA_ERROR_BAD_STATE );
+
+    /* CTR is a stream cipher, so data in and out are always the same size */
+    if( output_size < input_length )
+        return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+    status = mbedtls_to_psa_error(
+        mbedtls_cipher_update( &operation->cipher, input,
+                               input_length, output, output_length ) );
+
+    if( status != PSA_SUCCESS )
+        return status;
+
+    if( test_driver_cipher_hooks.forced_output != NULL )
+    {
+        if( output_size < test_driver_cipher_hooks.forced_output_length )
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+
+        memcpy( output,
+                test_driver_cipher_hooks.forced_output,
+                test_driver_cipher_hooks.forced_output_length );
+        *output_length = test_driver_cipher_hooks.forced_output_length;
+    }
+
+    return( test_driver_cipher_hooks.forced_status );
+}
+
+psa_status_t test_transparent_cipher_finish(
+    test_transparent_cipher_operation_t *operation,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
+
+    test_driver_cipher_hooks.hits++;
+
+    if( test_driver_cipher_hooks.forced_status != PSA_SUCCESS )
+        return( test_driver_cipher_hooks.forced_status );
+
+    if( operation->alg != PSA_ALG_CTR )
+        return( PSA_ERROR_BAD_STATE );
+
+    if( ! operation->key_set )
+        return( PSA_ERROR_BAD_STATE );
+
+    if( operation->iv_required && ! operation->iv_set )
+        return( PSA_ERROR_BAD_STATE );
+
+    status = mbedtls_to_psa_error(
+        mbedtls_cipher_finish( &operation->cipher,
+                               temp_output_buffer,
+                               output_length ) );
+
+    mbedtls_cipher_free( &operation->cipher );
+
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    if( *output_length == 0 )
+        ; /* Nothing to copy. Note that output may be NULL in this case. */
+    else if( output_size >= *output_length )
+        memcpy( output, temp_output_buffer, *output_length );
+    else
+        return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+
+    if( test_driver_cipher_hooks.forced_output != NULL )
+    {
+        if( output_size < test_driver_cipher_hooks.forced_output_length )
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+
+        memcpy( output,
+                test_driver_cipher_hooks.forced_output,
+                test_driver_cipher_hooks.forced_output_length );
+        *output_length = test_driver_cipher_hooks.forced_output_length;
+    }
+
+    return( test_driver_cipher_hooks.forced_status );
+}
+
+/*
+ * opaque versions, to do
+ */
+psa_status_t test_opaque_cipher_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output, size_t output_size, size_t *output_length)
+{
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    (void) input;
+    (void) input_length;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t test_opaque_cipher_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output, size_t output_size, size_t *output_length)
+{
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    (void) input;
+    (void) input_length;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t test_opaque_cipher_encrypt_setup(
+    test_opaque_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg)
+{
+    (void) operation;
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t test_opaque_cipher_decrypt_setup(
+    test_opaque_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg)
+{
+    (void) operation;
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t test_opaque_cipher_abort(
+    test_opaque_cipher_operation_t *operation)
+{
+    (void) operation;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t test_opaque_cipher_generate_iv(
+    test_opaque_cipher_operation_t *operation,
+    uint8_t *iv,
+    size_t iv_size,
+    size_t *iv_length)
+{
+    (void) operation;
+    (void) iv;
+    (void) iv_size;
+    (void) iv_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t test_opaque_cipher_set_iv(
+    test_opaque_cipher_operation_t *operation,
+    const uint8_t *iv,
+    size_t iv_length)
+{
+    (void) operation;
+    (void) iv;
+    (void) iv_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t test_opaque_cipher_update(
+    test_opaque_cipher_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length)
+{
+    (void) operation;
+    (void) input;
+    (void) input_length;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t test_opaque_cipher_finish(
+    test_opaque_cipher_operation_t *operation,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length)
+{
+    (void) operation;
+    (void) output;
+    (void) output_size;
+    (void) output_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
new file mode 100644
index 0000000..f15a4bc
--- /dev/null
+++ b/tests/src/drivers/keygen.c
@@ -0,0 +1,125 @@
+/*
+ * 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
new file mode 100644
index 0000000..028d24a
--- /dev/null
+++ b/tests/src/drivers/signature.c
@@ -0,0 +1,289 @@
+/*
+ * Test driver for signature functions.
+ * Currently supports signing and verifying precalculated hashes, using
+ * only deterministic ECDSA on curves secp256r1, secp384r1 and secp521r1.
+ */
+/*  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 "test/drivers/signature.h"
+
+#include "mbedtls/md.h"
+#include "mbedtls/ecdsa.h"
+
+#include "test/random.h"
+
+#include <string.h>
+
+test_driver_signature_hooks_t test_driver_signature_sign_hooks = TEST_DRIVER_SIGNATURE_INIT;
+test_driver_signature_hooks_t test_driver_signature_verify_hooks = TEST_DRIVER_SIGNATURE_INIT;
+
+psa_status_t test_transparent_signature_sign_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length )
+{
+    ++test_driver_signature_sign_hooks.hits;
+
+    if( test_driver_signature_sign_hooks.forced_status != PSA_SUCCESS )
+        return( test_driver_signature_sign_hooks.forced_status );
+
+    if( test_driver_signature_sign_hooks.forced_output != NULL )
+    {
+        if( test_driver_signature_sign_hooks.forced_output_length > signature_size )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+        memcpy( signature, test_driver_signature_sign_hooks.forced_output,
+                test_driver_signature_sign_hooks.forced_output_length );
+        *signature_length = test_driver_signature_sign_hooks.forced_output_length;
+        return( PSA_SUCCESS );
+    }
+
+    psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
+    defined(MBEDTLS_SHA256_C)
+    if( alg != PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ) )
+        return( PSA_ERROR_NOT_SUPPORTED );
+    mbedtls_ecp_group_id grp_id;
+    switch( psa_get_key_type( attributes ) )
+    {
+        case PSA_ECC_CURVE_SECP_R1:
+            switch( psa_get_key_bits( attributes ) )
+            {
+                case 256:
+                    grp_id = MBEDTLS_ECP_DP_SECP256R1;
+                    break;
+                case 384:
+                    grp_id = MBEDTLS_ECP_DP_SECP384R1;
+                    break;
+                case 521:
+                    grp_id = MBEDTLS_ECP_DP_SECP521R1;
+                    break;
+                default:
+                    return( PSA_ERROR_NOT_SUPPORTED );
+            }
+            break;
+        default:
+            return( PSA_ERROR_NOT_SUPPORTED );
+    }
+
+    /* Beyond this point, the driver is actually doing the work of
+     * calculating the signature. */
+
+    status = PSA_ERROR_GENERIC_ERROR;
+    int ret = 0;
+    mbedtls_mpi r, s;
+    mbedtls_mpi_init( &r );
+    mbedtls_mpi_init( &s );
+    mbedtls_ecp_keypair ecp;
+    mbedtls_ecp_keypair_init( &ecp );
+    size_t curve_bytes = PSA_BITS_TO_BYTES( ecp.grp.pbits );
+
+    MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ecp.grp, grp_id ) );
+    MBEDTLS_MPI_CHK( mbedtls_ecp_point_read_binary( &ecp.grp, &ecp.Q,
+                                                    key, key_length ) );
+
+    /* Code adapted from psa_ecdsa_sign() in psa_crypto.c. */
+    mbedtls_md_type_t md_alg = MBEDTLS_MD_SHA256;
+    if( signature_size < 2 * curve_bytes )
+    {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto cleanup;
+    }
+    MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ecp.grp, &r, &s, &ecp.d,
+                                  hash, hash_length, md_alg ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r,
+                                               signature,
+                                               curve_bytes ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s,
+                                               signature + curve_bytes,
+                                               curve_bytes ) );
+cleanup:
+    status = mbedtls_to_psa_error( ret );
+    mbedtls_mpi_free( &r );
+    mbedtls_mpi_free( &s );
+    mbedtls_ecp_keypair_free( &ecp );
+    if( status == PSA_SUCCESS )
+        *signature_length = 2 * curve_bytes;
+#else /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
+         defined(MBEDTLS_SHA256_C) */
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    (void) hash;
+    (void) hash_length;
+#endif /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
+          defined(MBEDTLS_SHA256_C) */
+
+    return( status );
+}
+
+psa_status_t test_opaque_signature_sign_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length )
+{
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    (void) hash;
+    (void) hash_length;
+    (void) signature;
+    (void) signature_size;
+    (void) signature_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+psa_status_t test_transparent_signature_verify_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length )
+{
+    ++test_driver_signature_verify_hooks.hits;
+
+    if( test_driver_signature_verify_hooks.forced_status != PSA_SUCCESS )
+        return( test_driver_signature_verify_hooks.forced_status );
+
+    psa_status_t status = PSA_ERROR_NOT_SUPPORTED;
+
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
+    defined(MBEDTLS_SHA256_C)
+    if( alg != PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ) )
+        return( PSA_ERROR_NOT_SUPPORTED );
+    mbedtls_ecp_group_id grp_id;
+    switch( psa_get_key_type( attributes ) )
+    {
+        case PSA_ECC_CURVE_SECP_R1:
+            switch( psa_get_key_bits( attributes ) )
+            {
+                case 256:
+                    grp_id = MBEDTLS_ECP_DP_SECP256R1;
+                    break;
+                case 384:
+                    grp_id = MBEDTLS_ECP_DP_SECP384R1;
+                    break;
+                case 521:
+                    grp_id = MBEDTLS_ECP_DP_SECP521R1;
+                    break;
+                default:
+                    return( PSA_ERROR_NOT_SUPPORTED );
+            }
+            break;
+        default:
+            return( PSA_ERROR_NOT_SUPPORTED );
+    }
+
+    /* Beyond this point, the driver is actually doing the work of
+     * calculating the signature. */
+
+    status = PSA_ERROR_GENERIC_ERROR;
+    int ret = 0;
+    mbedtls_mpi r, s;
+    mbedtls_mpi_init( &r );
+    mbedtls_mpi_init( &s );
+    mbedtls_ecp_keypair ecp;
+    mbedtls_ecp_keypair_init( &ecp );
+    mbedtls_test_rnd_pseudo_info rnd_info;
+    memset( &rnd_info, 0x5A, sizeof( mbedtls_test_rnd_pseudo_info ) );
+    size_t curve_bytes = PSA_BITS_TO_BYTES( ecp.grp.pbits );
+
+    MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ecp.grp, grp_id ) );
+
+    /* Code adapted from psa_ecdsa_verify() in psa_crypto.c. */
+    if( signature_length < 2 * curve_bytes )
+    {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto cleanup;
+    }
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r,
+                                              signature,
+                                              curve_bytes ) );
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s,
+                                              signature + curve_bytes,
+                                              curve_bytes ) );
+
+    if( PSA_KEY_TYPE_IS_PUBLIC_KEY( psa_get_key_type( attributes ) ) )
+        MBEDTLS_MPI_CHK( mbedtls_ecp_point_read_binary( &ecp.grp, &ecp.Q,
+                                                    key, key_length ) );
+    else
+    {
+        MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ecp.d, key, key_length ) );
+        MBEDTLS_MPI_CHK(
+            mbedtls_ecp_mul( &ecp.grp, &ecp.Q, &ecp.d, &ecp.grp.G,
+                             &mbedtls_test_rnd_pseudo_rand,
+                             &rnd_info ) );
+    }
+
+    MBEDTLS_MPI_CHK( mbedtls_ecdsa_verify( &ecp.grp, hash, hash_length,
+                                &ecp.Q, &r, &s ) );
+cleanup:
+    status = mbedtls_to_psa_error( ret );
+    mbedtls_mpi_free( &r );
+    mbedtls_mpi_free( &s );
+    mbedtls_ecp_keypair_free( &ecp );
+#else /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
+         defined(MBEDTLS_SHA256_C) */
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    (void) hash;
+    (void) hash_length;
+#endif /* defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECDSA_DETERMINISTIC) && \
+          defined(MBEDTLS_SHA256_C) */
+
+    return( status );
+}
+
+psa_status_t test_opaque_signature_verify_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key, size_t key_length,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length )
+{
+    (void) attributes;
+    (void) key;
+    (void) key_length;
+    (void) alg;
+    (void) hash;
+    (void) hash_length;
+    (void) signature;
+    (void) signature_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index 7425a35..ec43d13 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -407,6 +407,12 @@
 
 void test_fail( const char *test, int line_no, const char* filename )
 {
+    if( test_info.result == TEST_RESULT_FAILED )
+    {
+        /* We've already recorded the test as having failed. Don't
+         * overwrite any previous information about the failure. */
+        return;
+    }
     test_info.result = TEST_RESULT_FAILED;
     test_info.test = test;
     test_info.line_no = line_no;
diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function
index e54aaff..2b2daf6 100644
--- a/tests/suites/test_suite_mpi.function
+++ b/tests/suites/test_suite_mpi.function
@@ -596,7 +596,7 @@
                             int size_Y, char * input_Y,
                             int input_ret, int input_err )
 {
-    unsigned ret;
+    unsigned ret = -1;
     unsigned input_uret = input_ret;
     mbedtls_mpi X, Y;
     mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y );
diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function
index 43b4914..c6041b2 100644
--- a/tests/suites/test_suite_pk.function
+++ b/tests/suites/test_suite_pk.function
@@ -775,8 +775,8 @@
     TEST_ASSERT( mbedtls_ecp_point_read_binary( &eckey->grp, &eckey->Q,
                                         key->x, key->len ) == 0 );
 
-    // MBEDTLS_MD_SHA1 is a dummy - it is ignored, but has to be other than MBEDTLS_MD_NONE.
-    TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA1,
+    // MBEDTLS_MD_NONE is used since it will be ignored.
+    TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_NONE,
                             hash->x, hash->len, sig->x, sig->len ) == ret );
 
 exit:
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index cd26017..2c6924a 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -2,22 +2,22 @@
 static_checks:
 
 PSA key attributes structure
-attributes_set_get:0x6963:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:128
+attributes_set_get:0xffff1234:0x6963:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT:PSA_ALG_CCM:PSA_KEY_TYPE_AES:128
 
 PSA key attributes: id only
-persistence_attributes:0x1234:-1:-1:0x1234:PSA_KEY_LIFETIME_PERSISTENT
+persistence_attributes:0x1234:0x5678:-1:-1:0:0x1234:0x5678:PSA_KEY_LIFETIME_PERSISTENT
 
 PSA key attributes: lifetime=3 only
-persistence_attributes:-1:3:-1:0:3
+persistence_attributes:-1:0:3:-1:0:0:0:3
 
 PSA key attributes: id then back to volatile
-persistence_attributes:0x1234:PSA_KEY_LIFETIME_VOLATILE:-1:0:PSA_KEY_LIFETIME_VOLATILE
+persistence_attributes:0x1234:0x5678:PSA_KEY_LIFETIME_VOLATILE:-1:0:0:0x5678:PSA_KEY_LIFETIME_VOLATILE
 
 PSA key attributes: id then lifetime
-persistence_attributes:0x1234:3:-1:0x1234:3
+persistence_attributes:0x1234:0x5678:3:-1:0:0x1234:0x5678:3
 
 PSA key attributes: lifetime then id
-persistence_attributes:0x1234:3:0x1235:0x1235:3
+persistence_attributes:0x1234:0x5678:3:0x1235:0x5679:0x1235:0x5679:3
 
 PSA key attributes: slot number
 slot_number_attribute:
@@ -366,7 +366,11 @@
 depends_on:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
 import_rsa_made_up:PSA_VENDOR_RSA_MAX_KEY_BITS+8:0:PSA_ERROR_NOT_SUPPORTED
 
-PSA key policy: AES
+PSA key policy: AES ECB
+depends_on:MBEDTLS_AES_C
+check_key_policy:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_ECB_NO_PADDING
+
+PSA key policy: AES CBC
 depends_on:MBEDTLS_AES_C
 check_key_policy:PSA_KEY_TYPE_AES:128:PSA_KEY_USAGE_ENCRYPT:PSA_ALG_CBC_NO_PADDING
 
@@ -1150,6 +1154,18 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_bad_order:
 
+PSA symmetric encrypt: AES-ECB, 0 bytes, good
+depends_on:MBEDTLS_AES_C
+cipher_encrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"":"":PSA_SUCCESS
+
+PSA symmetric encrypt: AES-ECB, 16 bytes, good
+depends_on:MBEDTLS_AES_C
+cipher_encrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a":"3ad77bb40d7a3660a89ecaf32466ef97":PSA_SUCCESS
+
+PSA symmetric encrypt: AES-ECB, 32 bytes, good
+depends_on:MBEDTLS_AES_C
+cipher_encrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a3ad77bb40d7a3660a89ecaf32466ef97":"3ad77bb40d7a3660a89ecaf32466ef972249a2638c6f1c755a84f9681a9f08c1":PSA_SUCCESS
+
 PSA symmetric encrypt: AES-CBC-nopad, 16 bytes, good
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_encrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"a076ec9dfbe47d52afc357336f20743b":PSA_SUCCESS
@@ -1162,6 +1178,10 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_encrypt:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"6279b49d7f7a8dd87b685175d4276e24":PSA_SUCCESS
 
+PSA symmetric encrypt: AES-ECB, input too short (15 bytes)
+depends_on:MBEDTLS_AES_C
+cipher_encrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e11739317":"":PSA_ERROR_INVALID_ARGUMENT
+
 PSA symmetric encrypt: AES-CBC-nopad, input too short
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_encrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee223":"6bc1bee223":PSA_ERROR_INVALID_ARGUMENT
@@ -1186,6 +1206,26 @@
 depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_encrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"2a2a2a2a2a2a2a2a":"eda4011239bc3ac9":"817ca7d69b80d86a":PSA_SUCCESS
 
+PSA symmetric encrypt: 2-key 3DES-ECB, 8 bytes, good
+depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
+cipher_encrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"":"c78e2b38139610e3":"5d0652429c5b0ac7":PSA_SUCCESS
+
+PSA symmetric encrypt: 3-key 3DES-ECB, 8 bytes, good
+depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
+cipher_encrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"":"c78e2b38139610e3":"817ca7d69b80d86a":PSA_SUCCESS
+
+PSA symmetric decrypt: AES-ECB, 0 bytes, good
+depends_on:MBEDTLS_AES_C
+cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"":"":PSA_SUCCESS
+
+PSA symmetric decrypt: AES-ECB, 16 bytes, good
+depends_on:MBEDTLS_AES_C
+cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"396ee84fb75fdbb5c2b13c7fe5a654aa":"63cecc46a382414d5fa7d2b79387437f":PSA_SUCCESS
+
+PSA symmetric decrypt: AES-ECB, 32 bytes, good
+depends_on:MBEDTLS_AES_C
+cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef972249a2638c6f1c755a84f9681a9f08c1":"6bc1bee22e409f96e93d7e117393172a3ad77bb40d7a3660a89ecaf32466ef97":PSA_SUCCESS
+
 PSA symmetric decrypt: AES-CBC-nopad, 16 bytes, good
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"49e4e66c89a86b67758df89db9ad6955":PSA_SUCCESS
@@ -1206,6 +1246,10 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR
 cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":PSA_SUCCESS
 
+PSA symmetric decrypt: AES-ECB, input too short (15 bytes)
+depends_on:MBEDTLS_AES_C
+cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"396ee84fb75fdbb5c2b13c7fe5a654":"63cecc46a382414d5fa7d2b7938743":PSA_ERROR_INVALID_ARGUMENT
+
 PSA symmetric decrypt: AES-CBC-nopad, input too short (5 bytes)
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee223":"6bc1bee223":PSA_ERROR_BAD_STATE
@@ -1222,6 +1266,18 @@
 depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"2a2a2a2a2a2a2a2a":"817ca7d69b80d86a":"eda4011239bc3ac9":PSA_SUCCESS
 
+PSA symmetric decrypt: 2-key 3DES-ECB, 8 bytes, good
+depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
+cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce":"":"5d0652429c5b0ac7":"c78e2b38139610e3":PSA_SUCCESS
+
+PSA symmetric decrypt: 3-key 3DES-ECB, 8 bytes, good
+depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC
+cipher_decrypt:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_DES:"01020407080b0d0ec1c2c4c7c8cbcdce31323437383b3d3e":"":"817ca7d69b80d86a":"c78e2b38139610e3":PSA_SUCCESS
+
+PSA symmetric encrypt/decrypt: AES-ECB, 16 bytes, good
+depends_on:MBEDTLS_AES_C
+cipher_verify_output:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
+
 PSA symmetric encrypt/decrypt: AES-CBC-nopad, 16 bytes, good
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_verify_output:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
@@ -1238,6 +1294,18 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 cipher_verify_output:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
 
+PSA symmetric encryption multipart: AES-ECB, 16+16 bytes
+depends_on:MBEDTLS_AES_C
+cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c"
+
+PSA symmetric encryption multipart: AES-ECB, 13+19 bytes
+depends_on:MBEDTLS_AES_C
+cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":13:0:32:"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c"
+
+PSA symmetric encryption multipart: AES-ECB, 24+12 bytes
+depends_on:MBEDTLS_AES_C
+cipher_encrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":24:16:16:"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c"
+
 PSA symmetric encryption multipart: AES-CBC-nopad, 7+9 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":7:0:16:"a076ec9dfbe47d52afc357336f20743b"
@@ -1266,23 +1334,23 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_encrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:16:16:"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f"
 
-PSA symmetric encryption multipart: AES-CTR, 11+5 bytes [#1]
+PSA symmetric encryption multipart: AES-CTR, 11+5 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32"
 
-PSA symmetric encryption multipart: AES-CTR, 16+16 bytes [#1]
+PSA symmetric encryption multipart: AES-CTR, 16+16 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
 
-PSA symmetric encryption multipart: AES-CTR, 12+20 bytes [#1]
+PSA symmetric encryption multipart: AES-CTR, 12+20 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
 
-PSA symmetric encryption multipart: AES-CTR, 20+12 bytes [#1]
+PSA symmetric encryption multipart: AES-CTR, 20+12 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
 
-PSA symmetric encryption multipart: AES-CTR, 12+10 bytes [#1]
+PSA symmetric encryption multipart: AES-CTR, 12+10 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b"
 
@@ -1302,6 +1370,18 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32"
 
+PSA symmetric decryption multipart: AES-ECB, 16+16 bytes
+depends_on:MBEDTLS_AES_C
+cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c":16:16:16:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef"
+
+PSA symmetric decryption multipart: AES-ECB, 11+21 bytes
+depends_on:MBEDTLS_AES_C
+cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c":11:0:32:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef"
+
+PSA symmetric decryption multipart: AES-ECB, 28+4 bytes
+depends_on:MBEDTLS_AES_C
+cipher_decrypt_multipart:PSA_ALG_ECB_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"":"3ad77bb40d7a3660a89ecaf32466ef9755ed5e9e066820fa52c729886d18854c":28:16:16:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef"
+
 PSA symmetric decryption multipart: AES-CBC-nopad, 7+9 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b":7:0:16:"6bc1bee22e409f96e93d7e117393172a"
@@ -1326,23 +1406,23 @@
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_decrypt_multipart:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743b89906f2f9207ac02aa658cb4ef19c61f":20:16:16:"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef"
 
-PSA symmetric encryption multipart: AES-CTR, 11+5 bytes [#2]
+PSA symmetric decryption multipart: AES-CTR, 11+5 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32"
 
-PSA symmetric encryption multipart: AES-CTR, 16+16 bytes [#2]
+PSA symmetric decryption multipart: AES-CTR, 16+16 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
 
-PSA symmetric encryption multipart: AES-CTR, 12+20 bytes [#2]
+PSA symmetric decryption multipart: AES-CTR, 12+20 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
 
-PSA symmetric encryption multipart: AES-CTR, 20+12 bytes [#2]
+PSA symmetric decryption multipart: AES-CTR, 20+12 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
 
-PSA symmetric encryption multipart: AES-CTR, 12+10 bytes [#2]
+PSA symmetric decryption multipart: AES-CTR, 12+10 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
 cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b"
 
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 665580b..45916b9 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -233,7 +233,7 @@
     int ok = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_lifetime_t lifetime;
-    psa_key_id_t id;
+    mbedtls_svc_key_id_t id;
     psa_key_type_t type;
     psa_key_type_t bits;
 
@@ -245,12 +245,12 @@
 
     /* Persistence */
     if( lifetime == PSA_KEY_LIFETIME_VOLATILE )
-        TEST_ASSERT( id == 0 );
+        TEST_ASSERT( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) == 0 );
     else
     {
         TEST_ASSERT(
-            ( PSA_KEY_ID_USER_MIN <= id && id <= PSA_KEY_ID_USER_MAX ) ||
-            ( PSA_KEY_ID_USER_MIN <= id && id <= PSA_KEY_ID_USER_MAX ) );
+            ( PSA_KEY_ID_USER_MIN <= MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ) &&
+            ( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) <= PSA_KEY_ID_USER_MAX ) );
     }
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
     /* randomly-generated 64-bit constant, should never appear in test data */
@@ -1178,17 +1178,21 @@
 static int test_operations_on_invalid_handle( psa_key_handle_t handle )
 {
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make( 1, 0x6964 );
     uint8_t buffer[1];
     size_t length;
     int ok = 0;
 
-    psa_set_key_id( &attributes, 0x6964 );
+    psa_set_key_id( &attributes, key_id );
     psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
     psa_set_key_algorithm( &attributes, PSA_ALG_CTR );
     psa_set_key_type( &attributes, PSA_KEY_TYPE_AES );
     TEST_EQUAL( psa_get_key_attributes( handle, &attributes ),
                 PSA_ERROR_INVALID_HANDLE );
-    TEST_EQUAL( psa_get_key_id( &attributes ), 0 );
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( &attributes ) ), 0 );
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( psa_get_key_id( &attributes ) ), 0 );
     TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
     TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
     TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
@@ -1321,19 +1325,22 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void attributes_set_get( int id_arg, int lifetime_arg,
+void attributes_set_get( int owner_id_arg, int id_arg, int lifetime_arg,
                          int usage_flags_arg, int alg_arg,
                          int type_arg, int bits_arg )
 {
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_id_t id = id_arg;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( owner_id_arg, id_arg );
     psa_key_lifetime_t lifetime = lifetime_arg;
     psa_key_usage_t usage_flags = usage_flags_arg;
     psa_algorithm_t alg = alg_arg;
     psa_key_type_t type = type_arg;
     size_t bits = bits_arg;
 
-    TEST_EQUAL( psa_get_key_id( &attributes ), 0 );
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( &attributes ) ), 0 );
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( psa_get_key_id( &attributes ) ), 0 );
     TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
     TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
     TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
@@ -1347,7 +1354,8 @@
     psa_set_key_type( &attributes, type );
     psa_set_key_bits( &attributes, bits );
 
-    TEST_EQUAL( psa_get_key_id( &attributes ), id );
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes ), id ) );
     TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
     TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
     TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
@@ -1356,7 +1364,10 @@
 
     psa_reset_key_attributes( &attributes );
 
-    TEST_EQUAL( psa_get_key_id( &attributes ), 0 );
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_KEY_ID( psa_get_key_id( &attributes ) ), 0 );
+    TEST_EQUAL(
+        MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( psa_get_key_id( &attributes ) ), 0 );
     TEST_EQUAL( psa_get_key_lifetime( &attributes ), 0 );
     TEST_EQUAL( psa_get_key_usage_flags( &attributes ), 0 );
     TEST_EQUAL( psa_get_key_algorithm( &attributes ), 0 );
@@ -1366,14 +1377,19 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void persistence_attributes( int id1_arg, int lifetime_arg, int id2_arg,
-                             int expected_id_arg, int expected_lifetime_arg )
+void persistence_attributes( int id1_arg, int owner_id1_arg, int lifetime_arg,
+                             int id2_arg, int owner_id2_arg,
+                             int expected_id_arg, int expected_owner_id_arg,
+                             int expected_lifetime_arg )
 {
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_id_t id1 = id1_arg;
+    mbedtls_svc_key_id_t id1 =
+        mbedtls_svc_key_id_make( owner_id1_arg, id1_arg );
     psa_key_lifetime_t lifetime = lifetime_arg;
-    psa_key_id_t id2 = id2_arg;
-    psa_key_id_t expected_id = expected_id_arg;
+    mbedtls_svc_key_id_t id2 =
+        mbedtls_svc_key_id_make( owner_id2_arg, id2_arg );
+    mbedtls_svc_key_id_t expected_id =
+        mbedtls_svc_key_id_make( expected_owner_id_arg, expected_id_arg );
     psa_key_lifetime_t expected_lifetime = expected_lifetime_arg;
 
     if( id1_arg != -1 )
@@ -1383,7 +1399,8 @@
     if( id2_arg != -1 )
         psa_set_key_id( &attributes, id2 );
 
-    TEST_EQUAL( psa_get_key_id( &attributes ), expected_id );
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes ), expected_id ) );
     TEST_EQUAL( psa_get_key_lifetime( &attributes ), expected_lifetime );
 }
 /* END_CASE */
@@ -3430,7 +3447,11 @@
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation,
                                           handle, alg ) );
 
-    PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+    if( iv->len > 0 )
+    {
+        PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+    }
+
     output_buffer_size = ( (size_t) input->len +
                            PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
     ASSERT_ALLOC( output, output_buffer_size );
@@ -3494,7 +3515,11 @@
     PSA_ASSERT( psa_cipher_encrypt_setup( &operation,
                                           handle, alg ) );
 
-    PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+    if( iv->len > 0 )
+    {
+        PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+    }
+
     output_buffer_size = ( (size_t) input->len +
                            PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
     ASSERT_ALLOC( output, output_buffer_size );
@@ -3564,7 +3589,10 @@
     PSA_ASSERT( psa_cipher_decrypt_setup( &operation,
                                           handle, alg ) );
 
-    PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+    if( iv->len > 0 )
+    {
+        PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+    }
 
     output_buffer_size = ( (size_t) input->len +
                            PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
@@ -3632,7 +3660,10 @@
     PSA_ASSERT( psa_cipher_decrypt_setup( &operation,
                                           handle, alg ) );
 
-    PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+    if( iv->len > 0 )
+    {
+        PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+    }
 
     output_buffer_size = ( (size_t) input->len +
                            PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
@@ -3700,9 +3731,12 @@
     PSA_ASSERT( psa_cipher_decrypt_setup( &operation2,
                                           handle, alg ) );
 
-    PSA_ASSERT( psa_cipher_generate_iv( &operation1,
-                                        iv, iv_size,
-                                        &iv_length ) );
+    if( alg != PSA_ALG_ECB_NO_PADDING )
+    {
+        PSA_ASSERT( psa_cipher_generate_iv( &operation1,
+                                            iv, iv_size,
+                                            &iv_length ) );
+    }
     output1_size = ( (size_t) input->len +
                      PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
     ASSERT_ALLOC( output1, output1_size );
@@ -3722,8 +3756,12 @@
     output2_size = output1_length;
     ASSERT_ALLOC( output2, output2_size );
 
-    PSA_ASSERT( psa_cipher_set_iv( &operation2,
-                                   iv, iv_length ) );
+    if( iv_length > 0 )
+    {
+        PSA_ASSERT( psa_cipher_set_iv( &operation2,
+                                       iv, iv_length ) );
+    }
+
     PSA_ASSERT( psa_cipher_update( &operation2, output1, output1_length,
                                    output2, output2_size,
                                    &output2_length ) );
@@ -3787,9 +3825,13 @@
     PSA_ASSERT( psa_cipher_decrypt_setup( &operation2,
                                           handle, alg ) );
 
-    PSA_ASSERT( psa_cipher_generate_iv( &operation1,
-                                        iv, iv_size,
-                                        &iv_length ) );
+    if( alg != PSA_ALG_ECB_NO_PADDING )
+    {
+        PSA_ASSERT( psa_cipher_generate_iv( &operation1,
+                                            iv, iv_size,
+                                            &iv_length ) );
+    }
+
     output1_buffer_size = ( (size_t) input->len +
                             PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
     ASSERT_ALLOC( output1, output1_buffer_size );
@@ -3819,8 +3861,11 @@
     output2_buffer_size = output1_length;
     ASSERT_ALLOC( output2, output2_buffer_size );
 
-    PSA_ASSERT( psa_cipher_set_iv( &operation2,
-                                   iv, iv_length ) );
+    if( iv_length > 0 )
+    {
+        PSA_ASSERT( psa_cipher_set_iv( &operation2,
+                                       iv, iv_length ) );
+    }
 
     PSA_ASSERT( psa_cipher_update( &operation2, output1, first_part_size,
                                    output2, output2_buffer_size,
@@ -5584,7 +5629,7 @@
                                            int usage_flags_arg, int alg_arg,
                                            int generation_method )
 {
-    psa_key_id_t key_id = 1;
+    mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_handle_t handle = 0;
     psa_key_handle_t base_key = 0;
@@ -5676,7 +5721,8 @@
     /* Check key slot still contains key data */
     PSA_ASSERT( psa_open_key( key_id, &handle ) );
     PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
-    TEST_EQUAL( psa_get_key_id( &attributes ), key_id );
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes ), key_id ) );
     TEST_EQUAL( psa_get_key_lifetime( &attributes ),
                 PSA_KEY_LIFETIME_PERSISTENT );
     TEST_EQUAL( psa_get_key_type( &attributes ), type );
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data
new file mode 100644
index 0000000..7abc256
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data
@@ -0,0 +1,152 @@
+sign_hash through transparent driver: calculate in driver
+ecdsa_sign:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":0:PSA_SUCCESS
+
+sign_hash through transparent driver: fallback
+ecdsa_sign:PSA_ERROR_NOT_SUPPORTED:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":0:PSA_SUCCESS
+
+sign_hash through transparent driver: error
+ecdsa_sign:PSA_ERROR_GENERIC_ERROR:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":0:PSA_ERROR_GENERIC_ERROR
+
+sign_hash through transparent driver: fake
+ecdsa_sign:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"000102030405060708090A0B0C0D0E0F":1:PSA_SUCCESS
+
+verify_hash using private key through transparent driver: calculate in driver
+ecdsa_verify:PSA_SUCCESS:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS
+
+verify_hash using private key through transparent driver: fallback
+ecdsa_verify:PSA_ERROR_NOT_SUPPORTED:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS
+
+verify_hash using private key through transparent driver: error
+ecdsa_verify:PSA_ERROR_GENERIC_ERROR:0:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_GENERIC_ERROR
+
+verify_hash using public key through transparent driver: calculate in driver
+ecdsa_verify:PSA_SUCCESS:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS
+
+verify_hash using public key through transparent driver: fallback
+ecdsa_verify:PSA_ERROR_NOT_SUPPORTED:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_SUCCESS
+
+verify_hash using public key through transparent driver: error
+ecdsa_verify:PSA_ERROR_GENERIC_ERROR:1:"04dea5e45d0ea37fc566232a508f4ad20ea13d47e4bf5fa4d54a57a0ba012042087097496efc583fed8b24a5b9be9a51de063f5a00a8b698a16fd7f29b5485f320":"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f":PSA_ERROR_GENERIC_ERROR
+
+generate_key through transparent driver: fake
+generate_key:PSA_SUCCESS:"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_SUCCESS
+
+generate_key through transparent driver: in-driver
+generate_key:PSA_SUCCESS:"":PSA_SUCCESS
+
+generate_key through transparent driver: fallback
+generate_key:PSA_ERROR_NOT_SUPPORTED:"":PSA_SUCCESS
+
+generate_key through transparent driver: error
+generate_key:PSA_ERROR_GENERIC_ERROR:"":PSA_ERROR_GENERIC_ERROR
+
+PSA symmetric encrypt: AES-CTR, 16 bytes, good
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_SUCCESS:PSA_SUCCESS
+
+PSA symmetric encrypt: AES-CTR, 15 bytes, good
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_SUCCESS:PSA_SUCCESS
+
+PSA symmetric encrypt: AES-CTR, 16 bytes, fallback
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"8f9408fe80a81d3e813da3c7b0b2bd32":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS
+
+PSA symmetric encrypt: AES-CTR, 15 bytes, fallback
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"8f9408fe80a81d3e813da3c7b0b2bd":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS
+
+PSA symmetric encrypt: AES-CTR, 16 bytes, fake
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS
+
+PSA symmetric encrypt: AES-CTR, 15 bytes, fake
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS
+
+PSA symmetric decrypt: AES-CTR, 16 bytes, good
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR
+cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":0:PSA_SUCCESS:PSA_SUCCESS
+
+PSA symmetric decrypt: AES-CTR, 16 bytes, fallback
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR
+cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":0:PSA_ERROR_NOT_SUPPORTED:PSA_SUCCESS
+
+PSA symmetric decrypt: AES-CTR, 16 bytes, fake
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_MODE_CTR
+cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"d07a6a6e2687feb2":1:PSA_SUCCESS:PSA_SUCCESS
+
+PSA symmetric encryption multipart: AES-CTR, 11+5 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32"
+
+PSA symmetric encryption multipart: AES-CTR, 16+16 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+
+PSA symmetric encryption multipart: AES-CTR, 12+20 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+
+PSA symmetric encryption multipart: AES-CTR, 20+12 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+
+PSA symmetric encryption multipart: AES-CTR, 12+10 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b"
+
+PSA symmetric encryption multipart: AES-CTR, 0+15 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:15:"8f9408fe80a81d3e813da3c7b0b2bd"
+
+PSA symmetric encryption multipart: AES-CTR, 15+0 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd"
+
+PSA symmetric encryption multipart: AES-CTR, 0+16 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":0:0:16:"8f9408fe80a81d3e813da3c7b0b2bd32"
+
+PSA symmetric encryption multipart: AES-CTR, 16+0 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_encrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32"
+
+PSA symmetric decryption multipart: AES-CTR, 11+5 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":11:11:5:"8f9408fe80a81d3e813da3c7b0b2bd32"
+
+PSA symmetric decryption multipart: AES-CTR, 16+16 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":16:16:16:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+
+PSA symmetric decryption multipart: AES-CTR, 12+20 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":12:12:20:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+
+PSA symmetric decryption multipart: AES-CTR, 20+12 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597bcef1389318c7fc865ef":20:20:12:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7baf71025f6ef6393ca587"
+
+PSA symmetric decryption multipart: AES-CTR, 12+10 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a5434f378a597":12:12:10:"8f9408fe80a81d3e813da3c7b0b2bd321c965bb1de7b"
+
+PSA symmetric decryption multipart: AES-CTR, 0+15 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":0:0:15:"8f9408fe80a81d3e813da3c7b0b2bd"
+
+PSA symmetric decryption multipart: AES-CTR, 15+0 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e11739317":15:15:0:"8f9408fe80a81d3e813da3c7b0b2bd"
+
+PSA symmetric decryption multipart: AES-CTR, 0+16 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":0:0:16:"8f9408fe80a81d3e813da3c7b0b2bd32"
+
+PSA symmetric decryption multipart: AES-CTR, 16+0 bytes
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR
+cipher_decrypt_multipart:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":16:16:0:"8f9408fe80a81d3e813da3c7b0b2bd32"
+
+Cipher driver: negative testing on all entry points
+cipher_entry_points:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a"
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
new file mode 100644
index 0000000..951670d
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
@@ -0,0 +1,718 @@
+/* BEGIN_HEADER */
+#include "test/psa_crypto_helpers.h"
+
+#include "test/drivers/test_driver.h"
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PSA_CRYPTO_C:MBEDTLS_PSA_CRYPTO_DRIVERS:PSA_CRYPTO_DRIVER_TEST
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C */
+void ecdsa_sign( int force_status_arg,
+                 data_t *key_input,
+                 data_t *data_input,
+                 data_t *expected_output,
+                 int fake_output,
+                 int expected_status_arg )
+{
+    psa_status_t force_status = force_status_arg;
+    psa_status_t expected_status = expected_status_arg;
+    psa_key_handle_t handle = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t alg = PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 );
+    uint8_t signature[64];
+    size_t signature_length = 0xdeadbeef;
+    psa_status_t actual_status;
+    test_driver_signature_sign_hooks = test_driver_signature_hooks_init();
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    psa_set_key_type( &attributes,
+                      PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP_R1 ) );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_import_key( &attributes,
+                    key_input->x, key_input->len,
+                    &handle );
+
+    test_driver_signature_sign_hooks.forced_status = force_status;
+    if( fake_output == 1 )
+    {
+        test_driver_signature_sign_hooks.forced_output = expected_output->x;
+        test_driver_signature_sign_hooks.forced_output_length = expected_output->len;
+    }
+
+    actual_status = psa_sign_hash( handle, alg,
+                                   data_input->x, data_input->len,
+                                   signature, sizeof( signature ),
+                                   &signature_length );
+    TEST_EQUAL( actual_status, expected_status );
+    if( expected_status == PSA_SUCCESS )
+    {
+        ASSERT_COMPARE( signature, signature_length,
+                        expected_output->x, expected_output->len );
+    }
+    TEST_EQUAL( test_driver_signature_sign_hooks.hits, 1 );
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( handle );
+    PSA_DONE( );
+    test_driver_signature_sign_hooks = test_driver_signature_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C */
+void ecdsa_verify( int force_status_arg,
+                   int register_public_key,
+                   data_t *key_input,
+                   data_t *data_input,
+                   data_t *signature_input,
+                   int expected_status_arg )
+{
+    psa_status_t force_status = force_status_arg;
+    psa_status_t expected_status = expected_status_arg;
+    psa_key_handle_t handle = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t alg = PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 );
+    psa_status_t actual_status;
+    test_driver_signature_verify_hooks = test_driver_signature_hooks_init();
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    if( register_public_key )
+    {
+        psa_set_key_type( &attributes,
+                      PSA_KEY_TYPE_ECC_PUBLIC_KEY( PSA_ECC_CURVE_SECP_R1 ) );
+        psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH );
+        psa_set_key_algorithm( &attributes, alg );
+        psa_import_key( &attributes,
+                        key_input->x, key_input->len,
+                        &handle );
+    }
+    else
+    {
+        psa_set_key_type( &attributes,
+                      PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP_R1 ) );
+        psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH );
+        psa_set_key_algorithm( &attributes, alg );
+        psa_import_key( &attributes,
+                        key_input->x, key_input->len,
+                        &handle );
+    }
+
+    test_driver_signature_verify_hooks.forced_status = force_status;
+
+    actual_status = psa_verify_hash( handle, alg,
+                                     data_input->x, data_input->len,
+                                     signature_input->x, signature_input->len );
+    TEST_EQUAL( actual_status, expected_status );
+    TEST_EQUAL( test_driver_signature_verify_hooks.hits, 1 );
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( handle );
+    PSA_DONE( );
+    test_driver_signature_verify_hooks = test_driver_signature_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+void generate_key( int force_status_arg,
+                   data_t *fake_output,
+                   int expected_status_arg )
+{
+    psa_status_t force_status = force_status_arg;
+    psa_status_t expected_status = expected_status_arg;
+    psa_key_handle_t handle = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t alg = PSA_ALG_ECDSA( PSA_ALG_SHA_256 );
+    const uint8_t *expected_output = NULL;
+    size_t expected_output_length = 0;
+    psa_status_t actual_status;
+    uint8_t actual_output[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(256)] = {0};
+    size_t actual_output_length;
+    test_driver_keygen_hooks = test_driver_keygen_hooks_init();
+
+    psa_set_key_type( &attributes,
+                      PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP_R1 ) );
+    psa_set_key_bits( &attributes, 256 );
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_EXPORT );
+    psa_set_key_algorithm( &attributes, alg );
+
+    if( fake_output->len > 0 )
+    {
+        expected_output = test_driver_keygen_hooks.forced_output = fake_output->x;
+        expected_output_length = test_driver_keygen_hooks.forced_output_length =
+            fake_output->len;
+    }
+
+    test_driver_keygen_hooks.hits = 0;
+    test_driver_keygen_hooks.forced_status = force_status;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    actual_status = psa_generate_key( &attributes, &handle );
+    TEST_EQUAL( test_driver_keygen_hooks.hits, 1 );
+    TEST_EQUAL( actual_status, expected_status );
+
+    if( actual_status == PSA_SUCCESS )
+    {
+        psa_export_key( handle, actual_output, sizeof(actual_output), &actual_output_length );
+
+        if( fake_output->len > 0 )
+        {
+            ASSERT_COMPARE( actual_output, actual_output_length,
+                            expected_output, expected_output_length );
+        }
+        else
+        {
+            size_t zeroes = 0;
+            for( size_t i = 0; i < sizeof(actual_output); i++ )
+            {
+                if( actual_output[i] == 0)
+                    zeroes++;
+            }
+            TEST_ASSERT( zeroes != sizeof(actual_output) );
+        }
+    }
+exit:
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( handle );
+    PSA_DONE( );
+    test_driver_keygen_hooks = test_driver_keygen_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_encrypt( int alg_arg, int key_type_arg,
+                     data_t *key, data_t *iv,
+                     data_t *input, data_t *expected_output,
+                     int mock_output_arg,
+                     int force_status_arg,
+                     int expected_status_arg )
+{
+    psa_key_handle_t handle = 0;
+    psa_status_t status;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t expected_status = expected_status_arg;
+    psa_status_t force_status = force_status_arg;
+    unsigned char *output = NULL;
+    size_t output_buffer_size = 0;
+    size_t function_output_length = 0;
+    size_t total_output_length = 0;
+    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+    test_driver_cipher_hooks.forced_status = force_status;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key->x, key->len, &handle ) );
+
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation,
+                                          handle, alg ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    test_driver_cipher_hooks.hits = 0;
+
+    PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
+    test_driver_cipher_hooks.hits = 0;
+
+    output_buffer_size = ( (size_t) input->len +
+                           PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
+    ASSERT_ALLOC( output, output_buffer_size );
+
+    if( mock_output_arg )
+    {
+        test_driver_cipher_hooks.forced_output = expected_output->x;
+        test_driver_cipher_hooks.forced_output_length = expected_output->len;
+    }
+
+    PSA_ASSERT( psa_cipher_update( &operation,
+                                   input->x, input->len,
+                                   output, output_buffer_size,
+                                   &function_output_length ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
+    test_driver_cipher_hooks.hits = 0;
+
+    if( mock_output_arg )
+    {
+        test_driver_cipher_hooks.forced_output = NULL;
+        test_driver_cipher_hooks.forced_output_length = 0;
+    }
+
+    total_output_length += function_output_length;
+    status = psa_cipher_finish( &operation,
+                                output + total_output_length,
+                                output_buffer_size - total_output_length,
+                                &function_output_length );
+    /* Finish will have called abort as well, so expecting two hits here */
+    TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 2 : 0 ) );
+    test_driver_cipher_hooks.hits = 0;
+
+    total_output_length += function_output_length;
+
+    TEST_EQUAL( status, expected_status );
+    if( expected_status == PSA_SUCCESS )
+    {
+        PSA_ASSERT( psa_cipher_abort( &operation ) );
+        // driver function should've been called as part of the finish() core routine
+        TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+        ASSERT_COMPARE( expected_output->x, expected_output->len,
+                        output, total_output_length );
+    }
+
+exit:
+    psa_cipher_abort( &operation );
+    mbedtls_free( output );
+    psa_destroy_key( handle );
+    PSA_DONE( );
+    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_encrypt_multipart( int alg_arg, int key_type_arg,
+                               data_t *key, data_t *iv,
+                               data_t *input,
+                               int first_part_size_arg,
+                               int output1_length_arg, int output2_length_arg,
+                               data_t *expected_output )
+{
+    psa_key_handle_t handle = 0;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t first_part_size = first_part_size_arg;
+    size_t output1_length = output1_length_arg;
+    size_t output2_length = output2_length_arg;
+    unsigned char *output = NULL;
+    size_t output_buffer_size = 0;
+    size_t function_output_length = 0;
+    size_t total_output_length = 0;
+    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key->x, key->len, &handle ) );
+
+    PSA_ASSERT( psa_cipher_encrypt_setup( &operation,
+                                          handle, alg ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    test_driver_cipher_hooks.hits = 0;
+
+    PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    test_driver_cipher_hooks.hits = 0;
+
+    output_buffer_size = ( (size_t) input->len +
+                           PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
+    ASSERT_ALLOC( output, output_buffer_size );
+
+    TEST_ASSERT( first_part_size <= input->len );
+    PSA_ASSERT( psa_cipher_update( &operation, input->x, first_part_size,
+                                   output, output_buffer_size,
+                                   &function_output_length ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    test_driver_cipher_hooks.hits = 0;
+
+    TEST_ASSERT( function_output_length == output1_length );
+    total_output_length += function_output_length;
+    PSA_ASSERT( psa_cipher_update( &operation,
+                                   input->x + first_part_size,
+                                   input->len - first_part_size,
+                                   output + total_output_length,
+                                   output_buffer_size - total_output_length,
+                                   &function_output_length ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    test_driver_cipher_hooks.hits = 0;
+    TEST_ASSERT( function_output_length == output2_length );
+    total_output_length += function_output_length;
+    PSA_ASSERT( psa_cipher_finish( &operation,
+                                   output + total_output_length,
+                                   output_buffer_size - total_output_length,
+                                   &function_output_length ) );
+    /* Finish will have called abort as well, so expecting two hits here */
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 2 );
+    test_driver_cipher_hooks.hits = 0 ;
+    total_output_length += function_output_length;
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+
+    ASSERT_COMPARE( expected_output->x, expected_output->len,
+                    output, total_output_length );
+
+exit:
+    psa_cipher_abort( &operation );
+    mbedtls_free( output );
+    psa_destroy_key( handle );
+    PSA_DONE( );
+    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_decrypt_multipart( int alg_arg, int key_type_arg,
+                               data_t *key, data_t *iv,
+                               data_t *input,
+                               int first_part_size_arg,
+                               int output1_length_arg, int output2_length_arg,
+                               data_t *expected_output )
+{
+    psa_key_handle_t handle = 0;
+
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    size_t first_part_size = first_part_size_arg;
+    size_t output1_length = output1_length_arg;
+    size_t output2_length = output2_length_arg;
+    unsigned char *output = NULL;
+    size_t output_buffer_size = 0;
+    size_t function_output_length = 0;
+    size_t total_output_length = 0;
+    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key->x, key->len, &handle ) );
+
+    PSA_ASSERT( psa_cipher_decrypt_setup( &operation,
+                                          handle, alg ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    test_driver_cipher_hooks.hits = 0;
+
+    PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    test_driver_cipher_hooks.hits = 0;
+
+    output_buffer_size = ( (size_t) input->len +
+                           PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
+    ASSERT_ALLOC( output, output_buffer_size );
+
+    TEST_ASSERT( first_part_size <= input->len );
+    PSA_ASSERT( psa_cipher_update( &operation,
+                                   input->x, first_part_size,
+                                   output, output_buffer_size,
+                                   &function_output_length ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    test_driver_cipher_hooks.hits = 0;
+
+    TEST_ASSERT( function_output_length == output1_length );
+    total_output_length += function_output_length;
+    PSA_ASSERT( psa_cipher_update( &operation,
+                                   input->x + first_part_size,
+                                   input->len - first_part_size,
+                                   output + total_output_length,
+                                   output_buffer_size - total_output_length,
+                                   &function_output_length ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    test_driver_cipher_hooks.hits = 0;
+
+    TEST_ASSERT( function_output_length == output2_length );
+    total_output_length += function_output_length;
+    PSA_ASSERT( psa_cipher_finish( &operation,
+                                   output + total_output_length,
+                                   output_buffer_size - total_output_length,
+                                   &function_output_length ) );
+    /* Finish will have called abort as well, so expecting two hits here */
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 2 );
+    test_driver_cipher_hooks.hits = 0;
+    total_output_length += function_output_length;
+    PSA_ASSERT( psa_cipher_abort( &operation ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+
+    ASSERT_COMPARE( expected_output->x, expected_output->len,
+                    output, total_output_length );
+
+exit:
+    psa_cipher_abort( &operation );
+    mbedtls_free( output );
+    psa_destroy_key( handle );
+    PSA_DONE( );
+    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_decrypt( int alg_arg, int key_type_arg,
+                     data_t *key, data_t *iv,
+                     data_t *input, data_t *expected_output,
+                     int mock_output_arg,
+                     int force_status_arg,
+                     int expected_status_arg )
+{
+    psa_key_handle_t handle = 0;
+    psa_status_t status;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_status_t expected_status = expected_status_arg;
+    psa_status_t force_status = force_status_arg;
+    unsigned char *output = NULL;
+    size_t output_buffer_size = 0;
+    size_t function_output_length = 0;
+    size_t total_output_length = 0;
+    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+    test_driver_cipher_hooks.forced_status = force_status;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key->x, key->len, &handle ) );
+
+    PSA_ASSERT( psa_cipher_decrypt_setup( &operation,
+                                          handle, alg ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    test_driver_cipher_hooks.hits = 0;
+
+    PSA_ASSERT( psa_cipher_set_iv( &operation, iv->x, iv->len ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
+    test_driver_cipher_hooks.hits = 0;
+
+    output_buffer_size = ( (size_t) input->len +
+                           PSA_BLOCK_CIPHER_BLOCK_SIZE( key_type ) );
+    ASSERT_ALLOC( output, output_buffer_size );
+
+    if( mock_output_arg )
+    {
+        test_driver_cipher_hooks.forced_output = expected_output->x;
+        test_driver_cipher_hooks.forced_output_length = expected_output->len;
+    }
+
+    PSA_ASSERT( psa_cipher_update( &operation,
+                                   input->x, input->len,
+                                   output, output_buffer_size,
+                                   &function_output_length ) );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 1 : 0 ) );
+    test_driver_cipher_hooks.hits = 0;
+
+    if( mock_output_arg )
+    {
+        test_driver_cipher_hooks.forced_output = NULL;
+        test_driver_cipher_hooks.forced_output_length = 0;
+    }
+
+    total_output_length += function_output_length;
+    status = psa_cipher_finish( &operation,
+                                output + total_output_length,
+                                output_buffer_size - total_output_length,
+                                &function_output_length );
+    /* Finish will have called abort as well, so expecting two hits here */
+    TEST_EQUAL( test_driver_cipher_hooks.hits, ( force_status == PSA_SUCCESS ? 2 : 0 ) );
+    test_driver_cipher_hooks.hits = 0;
+
+    total_output_length += function_output_length;
+    TEST_EQUAL( status, expected_status );
+
+    if( expected_status == PSA_SUCCESS )
+    {
+        PSA_ASSERT( psa_cipher_abort( &operation ) );
+        TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+        ASSERT_COMPARE( expected_output->x, expected_output->len,
+                        output, total_output_length );
+    }
+
+exit:
+    psa_cipher_abort( &operation );
+    mbedtls_free( output );
+    psa_destroy_key( handle );
+    PSA_DONE( );
+    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void cipher_entry_points( int alg_arg, int key_type_arg,
+                          data_t *key, data_t *iv,
+                          data_t *input )
+{
+    psa_key_handle_t handle = 0;
+    psa_status_t status;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    unsigned char *output = NULL;
+    size_t output_buffer_size = 0;
+    size_t function_output_length = 0;
+    psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+
+    ASSERT_ALLOC( output, input->len + 16 );
+    output_buffer_size = input->len + 16;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type );
+
+    PSA_ASSERT( psa_import_key( &attributes, key->x, key->len, &handle ) );
+
+    /* Test setup call, encrypt */
+    test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
+    status = psa_cipher_encrypt_setup( &operation,
+                                       handle, alg );
+    /* When setup fails, it shouldn't call any further entry points */
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    test_driver_cipher_hooks.hits = 0;
+    status = psa_cipher_set_iv( &operation, iv->x, iv->len );
+    TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+
+    /* Test setup call failure, decrypt */
+    status = psa_cipher_decrypt_setup( &operation,
+                                       handle, alg );
+    /* When setup fails, it shouldn't call any further entry points */
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    test_driver_cipher_hooks.hits = 0;
+    status = psa_cipher_set_iv( &operation, iv->x, iv->len );
+    TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+
+    /* Test IV setting failure */
+    test_driver_cipher_hooks.forced_status = PSA_SUCCESS;
+    status = psa_cipher_encrypt_setup( &operation,
+                                       handle, alg );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    test_driver_cipher_hooks.hits = 0;
+
+    test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
+    status = psa_cipher_set_iv( &operation, iv->x, iv->len );
+    /* When setting the IV fails, it should call abort too */
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 2 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    /* Failure should prevent further operations from executing on the driver */
+    test_driver_cipher_hooks.hits = 0;
+    status = psa_cipher_update( &operation,
+                                input->x, input->len,
+                                output, output_buffer_size,
+                                &function_output_length );
+    TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+    psa_cipher_abort( &operation );
+
+    /* Test IV generation failure */
+    test_driver_cipher_hooks.forced_status = PSA_SUCCESS;
+    status = psa_cipher_encrypt_setup( &operation,
+                                       handle, alg );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    test_driver_cipher_hooks.hits = 0;
+
+    test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
+    status = psa_cipher_generate_iv( &operation, output, 16, &function_output_length );
+    /* When generating the IV fails, it should call abort too */
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 2 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    /* Failure should prevent further operations from executing on the driver */
+    test_driver_cipher_hooks.hits = 0;
+    status = psa_cipher_update( &operation,
+                                input->x, input->len,
+                                output, output_buffer_size,
+                                &function_output_length );
+    TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+    psa_cipher_abort( &operation );
+
+    /* Test update failure */
+    test_driver_cipher_hooks.forced_status = PSA_SUCCESS;
+    status = psa_cipher_encrypt_setup( &operation,
+                                       handle, alg );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    test_driver_cipher_hooks.hits = 0;
+
+    status = psa_cipher_set_iv( &operation, iv->x, iv->len );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    test_driver_cipher_hooks.hits = 0;
+
+    test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
+    status = psa_cipher_update( &operation,
+                                input->x, input->len,
+                                output, output_buffer_size,
+                                &function_output_length );
+    /* When the update call fails, it should call abort too */
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 2 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    /* Failure should prevent further operations from executing on the driver */
+    test_driver_cipher_hooks.hits = 0;
+    status = psa_cipher_update( &operation,
+                                input->x, input->len,
+                                output, output_buffer_size,
+                                &function_output_length );
+    TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+    psa_cipher_abort( &operation );
+
+    /* Test finish failure */
+    test_driver_cipher_hooks.forced_status = PSA_SUCCESS;
+    status = psa_cipher_encrypt_setup( &operation,
+                                       handle, alg );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    test_driver_cipher_hooks.hits = 0;
+
+    status = psa_cipher_set_iv( &operation, iv->x, iv->len );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    test_driver_cipher_hooks.hits = 0;
+
+    status = psa_cipher_update( &operation,
+                                input->x, input->len,
+                                output, output_buffer_size,
+                                &function_output_length );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 1 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    test_driver_cipher_hooks.hits = 0;
+
+    test_driver_cipher_hooks.forced_status = PSA_ERROR_GENERIC_ERROR;
+    status = psa_cipher_finish( &operation,
+                                output + function_output_length,
+                                output_buffer_size - function_output_length,
+                                &function_output_length );
+    /* When the finish call fails, it should call abort too */
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 2 );
+    TEST_EQUAL( status, test_driver_cipher_hooks.forced_status );
+    /* Failure should prevent further operations from executing on the driver */
+    test_driver_cipher_hooks.hits = 0;
+    status = psa_cipher_update( &operation,
+                                input->x, input->len,
+                                output, output_buffer_size,
+                                &function_output_length );
+    TEST_EQUAL( status, PSA_ERROR_BAD_STATE );
+    TEST_EQUAL( test_driver_cipher_hooks.hits, 0 );
+    psa_cipher_abort( &operation );
+
+exit:
+    psa_cipher_abort( &operation );
+    mbedtls_free( output );
+    psa_destroy_key( handle );
+    PSA_DONE( );
+    test_driver_cipher_hooks = test_driver_cipher_hooks_init();
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_psa_crypto_metadata.data b/tests/suites/test_suite_psa_crypto_metadata.data
index f2b16e4..14979d3 100644
--- a/tests/suites/test_suite_psa_crypto_metadata.data
+++ b/tests/suites/test_suite_psa_crypto_metadata.data
@@ -122,6 +122,10 @@
 depends_on:MBEDTLS_CIPHER_C:MBEDTLS_CIPHER_MODE_OFB
 cipher_algorithm:PSA_ALG_OFB:ALG_IS_STREAM_CIPHER
 
+Cipher: ECB-nopad
+depends_on:MBEDTLS_CIPHER_C
+cipher_algorithm:PSA_ALG_ECB_NO_PADDING:0
+
 Cipher: CBC-nopad
 depends_on:MBEDTLS_CIPHER_C:MBEDTLS_CIPHER_MODE_CBC
 cipher_algorithm:PSA_ALG_CBC_NO_PADDING:0
diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.data b/tests/suites/test_suite_psa_crypto_persistent_key.data
index e0fba02..f65e57e 100644
--- a/tests/suites/test_suite_psa_crypto_persistent_key.data
+++ b/tests/suites/test_suite_psa_crypto_persistent_key.data
@@ -32,23 +32,23 @@
 
 Persistent key destroy
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-persistent_key_destroy:1:0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RAW_DATA:"deadbeef"
+persistent_key_destroy:2:1:0:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RAW_DATA:"deadbeef"
 
 Persistent key destroy after restart
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-persistent_key_destroy:1:1:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RAW_DATA:"deadbeef"
+persistent_key_destroy:17:1:1:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":PSA_KEY_TYPE_RAW_DATA:"deadbeef"
 
 Persistent key import (RSA)
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-persistent_key_import:1:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_SUCCESS
+persistent_key_import:256:1:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":0:PSA_SUCCESS
 
 Persistent key import with restart (RSA)
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-persistent_key_import:1:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":1:PSA_SUCCESS
+persistent_key_import:256:1:PSA_KEY_TYPE_RSA_KEY_PAIR:"3082025e02010002818100af057d396ee84fb75fdbb5c2b13c7fe5a654aa8aa2470b541ee1feb0b12d25c79711531249e1129628042dbbb6c120d1443524ef4c0e6e1d8956eeb2077af12349ddeee54483bc06c2c61948cd02b202e796aebd94d3a7cbf859c2c1819c324cb82b9cd34ede263a2abffe4733f077869e8660f7d6834da53d690ef7985f6bc3020301000102818100874bf0ffc2f2a71d14671ddd0171c954d7fdbf50281e4f6d99ea0e1ebcf82faa58e7b595ffb293d1abe17f110b37c48cc0f36c37e84d876621d327f64bbe08457d3ec4098ba2fa0a319fba411c2841ed7be83196a8cdf9daa5d00694bc335fc4c32217fe0488bce9cb7202e59468b1ead119000477db2ca797fac19eda3f58c1024100e2ab760841bb9d30a81d222de1eb7381d82214407f1b975cbbfe4e1a9467fd98adbd78f607836ca5be1928b9d160d97fd45c12d6b52e2c9871a174c66b488113024100c5ab27602159ae7d6f20c3c2ee851e46dc112e689e28d5fcbbf990a99ef8a90b8bb44fd36467e7fc1789ceb663abda338652c3c73f111774902e840565927091024100b6cdbd354f7df579a63b48b3643e353b84898777b48b15f94e0bfc0567a6ae5911d57ad6409cf7647bf96264e9bd87eb95e263b7110b9a1f9f94acced0fafa4d024071195eec37e8d257decfc672b07ae639f10cbb9b0c739d0c809968d644a94e3fd6ed9287077a14583f379058f76a8aecd43c62dc8c0f41766650d725275ac4a1024100bb32d133edc2e048d463388b7be9cb4be29f4b6250be603e70e3647501c97ddde20a4e71be95fd5e71784e25aca4baf25be5738aae59bbfe1c997781447a2b24":1:PSA_SUCCESS
 
 Persistent key import garbage data, should fail
 depends_on:MBEDTLS_PK_C:MBEDTLS_PK_PARSE_C:MBEDTLS_RSA_C
-persistent_key_import:1:PSA_KEY_TYPE_RSA_KEY_PAIR:"11111111":0:PSA_ERROR_INVALID_ARGUMENT
+persistent_key_import:256:1:PSA_KEY_TYPE_RSA_KEY_PAIR:"11111111":0:PSA_ERROR_INVALID_ARGUMENT
 
 import/export persistent raw key: 1 byte
 import_export_persistent_key:"2a":PSA_KEY_TYPE_RAW_DATA:8:0:0
diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.function b/tests/suites/test_suite_psa_crypto_persistent_key.function
index 49ce964..9e2fbf6 100644
--- a/tests/suites/test_suite_psa_crypto_persistent_key.function
+++ b/tests/suites/test_suite_psa_crypto_persistent_key.function
@@ -112,7 +112,7 @@
 /* BEGIN_CASE */
 void save_large_persistent_key( int data_length_arg, int expected_status )
 {
-    psa_key_id_t key_id = 42;
+    mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make( 1, 42 );
     psa_key_handle_t handle = 0;
     uint8_t *data = NULL;
     size_t data_length = data_length_arg;
@@ -139,11 +139,12 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void persistent_key_destroy( int key_id_arg, int restart,
+void persistent_key_destroy( int owner_id_arg, int key_id_arg, int restart,
                              int first_type_arg, data_t *first_data,
                              int second_type_arg, data_t *second_data )
 {
-    psa_key_id_t key_id = key_id_arg;
+    mbedtls_svc_key_id_t key_id =
+        mbedtls_svc_key_id_make( owner_id_arg, key_id_arg );
     psa_key_handle_t handle = 0;
     psa_key_type_t first_type = (psa_key_type_t) first_type_arg;
     psa_key_type_t second_type = (psa_key_type_t) second_type_arg;
@@ -193,10 +194,11 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void persistent_key_import( int key_id_arg, int type_arg, data_t *data,
-                            int restart, int expected_status )
+void persistent_key_import( int owner_id_arg, int key_id_arg, int type_arg,
+                            data_t *data, int restart, int expected_status )
 {
-    psa_key_id_t key_id = (psa_key_id_t) key_id_arg;
+    mbedtls_svc_key_id_t key_id =
+        mbedtls_svc_key_id_make( owner_id_arg, key_id_arg );
     psa_key_type_t type = (psa_key_type_t) type_arg;
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -224,7 +226,8 @@
 
     psa_reset_key_attributes( &attributes );
     PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
-    TEST_EQUAL( psa_get_key_id( &attributes ), key_id );
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes ), key_id ) );
     TEST_EQUAL( psa_get_key_lifetime( &attributes ),
                 PSA_KEY_LIFETIME_PERSISTENT );
     TEST_EQUAL( psa_get_key_type( &attributes ), type );
@@ -245,7 +248,7 @@
                                    int expected_bits,
                                    int restart, int key_not_exist )
 {
-    psa_key_id_t key_id = 42;
+    mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make( 1, 42 );
     psa_key_type_t type = (psa_key_type_t) type_arg;
     psa_key_handle_t handle = 0;
     unsigned char *exported = NULL;
@@ -276,7 +279,8 @@
     /* Test the key information */
     psa_reset_key_attributes( &attributes );
     PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
-    TEST_EQUAL( psa_get_key_id( &attributes ), key_id );
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes ), key_id ) );
     TEST_EQUAL( psa_get_key_lifetime( &attributes ),
                 PSA_KEY_LIFETIME_PERSISTENT );
     TEST_EQUAL( psa_get_key_type( &attributes ), type );
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.data b/tests/suites/test_suite_psa_crypto_se_driver_hal.data
index 32e2ecb..e5eee58 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal.data
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.data
@@ -130,28 +130,28 @@
 generate_key_smoke:PSA_KEY_TYPE_HMAC:256:PSA_ALG_HMAC( PSA_ALG_SHA_256 )
 
 Key registration: smoke test
-register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:1:1:PSA_SUCCESS
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:1:1:PSA_SUCCESS
 
 Key registration: invalid lifetime (volatile internal storage)
-register_key_smoke_test:PSA_KEY_LIFETIME_VOLATILE:1:1:PSA_ERROR_INVALID_ARGUMENT
+register_key_smoke_test:PSA_KEY_LIFETIME_VOLATILE:7:1:1:PSA_ERROR_INVALID_ARGUMENT
 
 Key registration: invalid lifetime (internal storage)
-register_key_smoke_test:PSA_KEY_LIFETIME_PERSISTENT:1:1:PSA_ERROR_INVALID_ARGUMENT
+register_key_smoke_test:PSA_KEY_LIFETIME_PERSISTENT:7:1:1:PSA_ERROR_INVALID_ARGUMENT
 
 Key registration: invalid lifetime (no registered driver)
-register_key_smoke_test:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( PSA_KEY_PERSISTENCE_DEFAULT, TEST_DRIVER_LOCATION + 1 ):1:1:PSA_ERROR_INVALID_ARGUMENT
+register_key_smoke_test:PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( PSA_KEY_PERSISTENCE_DEFAULT, TEST_DRIVER_LOCATION + 1 ):7:1:1:PSA_ERROR_INVALID_ARGUMENT
 
 Key registration: rejected
-register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:1:0:PSA_ERROR_NOT_PERMITTED
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:1:0:PSA_ERROR_NOT_PERMITTED
 
 Key registration: not supported
-register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:1:-1:PSA_ERROR_NOT_SUPPORTED
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:1:-1:PSA_ERROR_NOT_SUPPORTED
 
 Key registration: key id out of range
-register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:PSA_KEY_ID_VENDOR_MAX+1:-1:PSA_ERROR_INVALID_ARGUMENT
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:PSA_KEY_ID_VENDOR_MAX+1:-1:PSA_ERROR_INVALID_ARGUMENT
 
 Key registration: key id in vendor range
-register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:PSA_KEY_ID_VENDOR_MAX:1:PSA_SUCCESS
+register_key_smoke_test:TEST_SE_PERSISTENT_LIFETIME:7:PSA_KEY_ID_VENDOR_MAX:1:PSA_SUCCESS
 
 Import-sign-verify: sign in driver, ECDSA
 depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.function b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
index c9ce866..8584e5e 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal.function
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.function
@@ -532,8 +532,9 @@
 
     PSA_ASSERT( psa_get_key_attributes( handle, &actual_attributes ) );
 
-    TEST_EQUAL( psa_get_key_id( &actual_attributes ),
-                psa_get_key_id( reference_attributes ) );
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &actual_attributes ),
+                     psa_get_key_id( reference_attributes ) ) );
     TEST_EQUAL( psa_get_key_lifetime( &actual_attributes ),
                 psa_get_key_lifetime( reference_attributes ) );
     TEST_EQUAL( psa_get_key_type( &actual_attributes ),
@@ -757,16 +758,41 @@
     return( ok );
 }
 
-#define MAX_KEY_ID_FOR_TEST 10
+static mbedtls_svc_key_id_t key_ids_used_in_test[10];
+static size_t num_key_ids_used;
+
+/* Record a key id as potentially used in a test case. */
+static int test_uses_key_id( mbedtls_svc_key_id_t key_id )
+{
+    size_t i;
+
+    for( i = 0; i < num_key_ids_used ; i++ )
+    {
+        if( mbedtls_svc_key_id_equal( key_id, key_ids_used_in_test[i] ) )
+            return( 1 );
+    }
+
+    if( num_key_ids_used >= ARRAY_LENGTH( key_ids_used_in_test ) )
+        return( 0 );
+
+    key_ids_used_in_test[num_key_ids_used] = key_id;
+    ++num_key_ids_used;
+
+    return( 1 );
+}
+
+#define TEST_USES_KEY_ID( key_id )                       \
+    TEST_ASSERT( test_uses_key_id( key_id ) )
+
 static void psa_purge_storage( void )
 {
-    psa_key_id_t id;
+    size_t i;
     psa_key_location_t location;
-    /* The tests may have potentially created key ids from 1 to
-     * MAX_KEY_ID_FOR_TEST. In addition, run the destroy function on key id
-     * 0, which file-based storage uses as a temporary file. */
-    for( id = 0; id <= MAX_KEY_ID_FOR_TEST; id++ )
-        psa_destroy_persistent_key( id );
+
+    for( i = 0; i < num_key_ids_used; i++ )
+        psa_destroy_persistent_key( key_ids_used_in_test[i] );
+    num_key_ids_used = 0;
+
     /* Purge the transaction file. */
     psa_crypto_stop_transaction( );
     /* Purge driver persistent data. */
@@ -853,13 +879,15 @@
     psa_drv_se_key_management_t key_management;
     psa_key_lifetime_t lifetime = (psa_key_lifetime_t) lifetime_arg;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
-    psa_key_id_t id = 1;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     const uint8_t key_material[3] = {0xfa, 0xca, 0xde};
     uint8_t exported[sizeof( key_material )];
     size_t exported_length;
 
+    TEST_USES_KEY_ID( id );
+
     memset( &driver, 0, sizeof( driver ) );
     memset( &key_management, 0, sizeof( key_management ) );
     driver.hal_version = PSA_DRV_SE_HAL_VERSION;
@@ -985,11 +1013,13 @@
     psa_drv_se_key_management_t key_management;
     psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
-    psa_key_id_t id = 1;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     const uint8_t key_material[3] = {0xfa, 0xca, 0xde};
 
+    TEST_USES_KEY_ID( id );
+
     memset( &driver, 0, sizeof( driver ) );
     memset( &key_management, 0, sizeof( key_management ) );
     driver.hal_version = PSA_DRV_SE_HAL_VERSION;
@@ -1067,10 +1097,12 @@
     psa_drv_se_key_management_t key_management;
     psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
-    psa_key_id_t id = 1;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
+    TEST_USES_KEY_ID( id );
+
     memset( &driver, 0, sizeof( driver ) );
     memset( &key_management, 0, sizeof( key_management ) );
     driver.hal_version = PSA_DRV_SE_HAL_VERSION;
@@ -1139,10 +1171,12 @@
     psa_drv_se_key_management_t key_management;
     psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
-    psa_key_id_t id = 1;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
+    TEST_USES_KEY_ID( id );
+
     memset( &driver, 0, sizeof( driver ) );
     memset( &key_management, 0, sizeof( key_management ) );
     driver.hal_version = PSA_DRV_SE_HAL_VERSION;
@@ -1178,10 +1212,12 @@
     psa_drv_se_key_management_t key_management;
     psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
-    psa_key_id_t id = 1;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
+    TEST_USES_KEY_ID( id );
+
     memset( &driver, 0, sizeof( driver ) );
     memset( &key_management, 0, sizeof( key_management ) );
     driver.hal_version = PSA_DRV_SE_HAL_VERSION;
@@ -1258,7 +1294,7 @@
 
     psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
-    psa_key_id_t id = 1;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_handle_t drv_handle = 0; /* key managed by the driver */
     psa_key_handle_t sw_handle = 0; /* transparent key */
     psa_key_attributes_t sw_attributes = PSA_KEY_ATTRIBUTES_INIT;
@@ -1266,6 +1302,8 @@
     uint8_t signature[PSA_SIGNATURE_MAX_SIZE];
     size_t signature_length;
 
+    TEST_USES_KEY_ID( id );
+
     memset( &driver, 0, sizeof( driver ) );
     memset( &key_management, 0, sizeof( key_management ) );
     memset( &asymmetric, 0, sizeof( asymmetric ) );
@@ -1410,6 +1448,7 @@
 
 /* BEGIN_CASE */
 void register_key_smoke_test( int lifetime_arg,
+                              int owner_id_arg,
                               int id_arg,
                               int validate,
                               int expected_status_arg )
@@ -1420,12 +1459,14 @@
     psa_drv_se_t driver;
     psa_drv_se_key_management_t key_management;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_key_id_t id = id_arg;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( owner_id_arg, id_arg );
     size_t bit_size = 48;
     psa_key_slot_number_t wanted_slot = 0x123456789;
     psa_key_handle_t handle = 0;
     psa_status_t status;
 
+    TEST_USES_KEY_ID( id );
+
     memset( &driver, 0, sizeof( driver ) );
     driver.hal_version = PSA_DRV_SE_HAL_VERSION;
     memset( &key_management, 0, sizeof( key_management ) );
@@ -1462,6 +1503,12 @@
         goto exit;
     PSA_ASSERT( psa_close_key( handle ) );
 
+#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+    mbedtls_svc_key_id_t invalid_id =
+        mbedtls_svc_key_id_make( owner_id_arg + 1, id_arg );
+    TEST_EQUAL( psa_open_key( invalid_id, &handle ), PSA_ERROR_DOES_NOT_EXIST );
+#endif
+
     /* Restart and try again. */
     PSA_DONE( );
     PSA_ASSERT( psa_register_se_driver( location, &driver ) );
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
index ef50a68..7d4a591 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal_mocks.function
@@ -91,11 +91,13 @@
 {
     psa_key_id_t id;
     psa_key_location_t location;
+
     /* The tests may have potentially created key ids from 1 to
      * MAX_KEY_ID_FOR_TEST. In addition, run the destroy function on key id
      * 0, which file-based storage uses as a temporary file. */
     for( id = 0; id <= MAX_KEY_ID_FOR_TEST; id++ )
-        psa_destroy_persistent_key( id );
+        psa_destroy_persistent_key( mbedtls_svc_key_id_make( 1, id ) );
+
     /* Purge the transaction file. */
     psa_crypto_stop_transaction( );
     /* Purge driver persistent data. */
@@ -330,7 +332,7 @@
     psa_drv_se_key_management_t key_management;
     psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
-    psa_key_id_t id = 1;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     const uint8_t key_material[3] = {0xfa, 0xca, 0xde};
@@ -360,8 +362,20 @@
     TEST_ASSERT( mock_allocate_data.called == 1 );
     TEST_ASSERT( mock_import_data.called ==
         ( mock_alloc_return_value == PSA_SUCCESS? 1 : 0 ) );
-    TEST_ASSERT( mock_import_data.attributes.core.id ==
-        ( mock_alloc_return_value == PSA_SUCCESS? id : 0 ) );
+
+    if( mock_alloc_return_value == PSA_SUCCESS )
+    {
+        TEST_ASSERT( mbedtls_svc_key_id_equal(
+                         mock_import_data.attributes.core.id, id ) );
+    }
+    else
+    {
+        TEST_ASSERT( MBEDTLS_SVC_KEY_ID_GET_KEY_ID(
+                         mock_import_data.attributes.core.id ) == 0 );
+        TEST_ASSERT( MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(
+                         mock_import_data.attributes.core.id ) == 0 );
+    }
+
     TEST_ASSERT( mock_import_data.attributes.core.lifetime ==
         ( mock_alloc_return_value == PSA_SUCCESS? lifetime : 0 ) );
     TEST_ASSERT( mock_import_data.attributes.core.policy.usage ==
@@ -387,7 +401,7 @@
     psa_drv_se_key_management_t key_management;
     psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
-    psa_key_id_t id = 1;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     const uint8_t key_material[3] = {0xfa, 0xca, 0xde};
@@ -441,7 +455,7 @@
     psa_drv_se_key_management_t key_management;
     psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
-    psa_key_id_t id = 1;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
@@ -467,8 +481,20 @@
     TEST_ASSERT( mock_allocate_data.called == 1 );
     TEST_ASSERT( mock_generate_data.called ==
         ( mock_alloc_return_value == PSA_SUCCESS? 1 : 0 ) );
-    TEST_ASSERT( mock_generate_data.attributes.core.id ==
-        ( mock_alloc_return_value == PSA_SUCCESS? id : 0 ) );
+
+    if( mock_alloc_return_value == PSA_SUCCESS )
+    {
+        TEST_ASSERT( mbedtls_svc_key_id_equal(
+                         mock_generate_data.attributes.core.id, id ) );
+    }
+    else
+    {
+        TEST_ASSERT( MBEDTLS_SVC_KEY_ID_GET_KEY_ID(
+                         mock_generate_data.attributes.core.id ) == 0 );
+        TEST_ASSERT( MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(
+                         mock_generate_data.attributes.core.id ) == 0 );
+    }
+
     TEST_ASSERT( mock_generate_data.attributes.core.lifetime ==
         ( mock_alloc_return_value == PSA_SUCCESS? lifetime : 0 ) );
     TEST_ASSERT( mock_generate_data.attributes.core.policy.usage ==
@@ -496,7 +522,7 @@
     psa_drv_se_key_management_t key_management;
     psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
-    psa_key_id_t id = 1;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     const uint8_t key_material[3] = {0xfa, 0xca, 0xde};
@@ -546,7 +572,7 @@
     psa_drv_se_asymmetric_t asymmetric;
     psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
-    psa_key_id_t id = 1;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     const uint8_t key_material[3] = {0xfa, 0xca, 0xde};
@@ -607,7 +633,7 @@
     psa_drv_se_asymmetric_t asymmetric;
     psa_key_lifetime_t lifetime = TEST_SE_PERSISTENT_LIFETIME;
     psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime );
-    psa_key_id_t id = 1;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, 1 );
     psa_key_handle_t handle = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     const uint8_t key_material[3] = {0xfa, 0xca, 0xde};
diff --git a/tests/suites/test_suite_psa_crypto_slot_management.data b/tests/suites/test_suite_psa_crypto_slot_management.data
index 84caef9..e16089d 100644
--- a/tests/suites/test_suite_psa_crypto_slot_management.data
+++ b/tests/suites/test_suite_psa_crypto_slot_management.data
@@ -14,61 +14,61 @@
 transient_slot_lifecycle:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_SHUTDOWN
 
 Persistent slot, check after closing, id=min
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:124:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE
 
 Persistent slot, check after closing and restarting, id=min
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:125:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE
 
 Persistent slot, check after destroying, id=min
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:126:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY
 
 Persistent slot, check after destroying and restarting, id=min
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:127:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY
 
 Persistent slot, check after restart with live handle, id=min
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_SHUTDOWN
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:128:PSA_KEY_ID_USER_MIN:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_SHUTDOWN
 
 Persistent slot, check after closing, id=max
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MAX:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:129:PSA_KEY_ID_USER_MAX:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_CLOSE
 
 Persistent slot, check after destroying, id=max
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MAX:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:130:PSA_KEY_ID_USER_MAX:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_DESTROY
 
 Persistent slot, check after restart, id=max
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MAX:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_SHUTDOWN
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:131:PSA_KEY_ID_USER_MAX:0:0:0:PSA_KEY_TYPE_RAW_DATA:"0123456789abcdef0123456789abcdef":CLOSE_BY_SHUTDOWN
 
 Persistent slot: ECP keypair (ECDSA, exportable), close
 depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_CLOSE
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:132:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_CLOSE
 
 Persistent slot: ECP keypair (ECDSA, exportable), close+restart
 depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_CLOSE_WITH_SHUTDOWN
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:133:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_CLOSE_WITH_SHUTDOWN
 
 Persistent slot: ECP keypair (ECDSA, exportable), restart
 depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_SHUTDOWN
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:134:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_ECDSA_ANY:0:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_SHUTDOWN
 
 Persistent slot: ECP keypair (ECDH+ECDSA, exportable), close
 depends_on:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_CLOSE
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:135:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_CLOSE
 
 Persistent slot: ECP keypair (ECDH+ECDSA, exportable), close+restart
 depends_on:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_CLOSE_WITH_SHUTDOWN
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:136:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_CLOSE_WITH_SHUTDOWN
 
 Persistent slot: ECP keypair (ECDH+ECDSA, exportable), restart
 depends_on:MBEDTLS_ECDH_C:MBEDTLS_SHA256_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
-persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_SHUTDOWN
+persistent_slot_lifecycle:PSA_KEY_LIFETIME_PERSISTENT:137:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH:PSA_ALG_KEY_AGREEMENT(PSA_ALG_ECDH, PSA_ALG_HKDF(PSA_ALG_SHA_256)):PSA_ALG_ECDSA_ANY:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":CLOSE_BY_SHUTDOWN
 
 Attempt to overwrite: close before
-create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:CLOSE_BEFORE
+create_existent:PSA_KEY_LIFETIME_PERSISTENT:0x1736:1:CLOSE_BEFORE
 
 Attempt to overwrite: close after
-create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:CLOSE_AFTER
+create_existent:PSA_KEY_LIFETIME_PERSISTENT:0x7361:1:CLOSE_AFTER
 
 Attempt to overwrite: keep open
-create_existent:PSA_KEY_LIFETIME_PERSISTENT:1:KEEP_OPEN
+create_existent:PSA_KEY_LIFETIME_PERSISTENT:0x3617:1:KEEP_OPEN
 
 Open failure: invalid identifier (0)
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
@@ -118,23 +118,27 @@
 create_fail:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_NOT_SUPPORTED
 
 Copy volatile to volatile
-copy_across_lifetimes:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:0:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_USAGE_EXPORT:0:0
+copy_across_lifetimes:PSA_KEY_LIFETIME_VOLATILE:0x10:0:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:0:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_VOLATILE:0x10:0:PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_USAGE_EXPORT:0:0
 
 Copy volatile to persistent
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-copy_across_lifetimes:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:0:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_USAGE_EXPORT:0:0
+copy_across_lifetimes:PSA_KEY_LIFETIME_VOLATILE:0x100:0:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:0:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_PERSISTENT:0x100:1:PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_USAGE_EXPORT:0:0
 
 Copy persistent to volatile
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-copy_across_lifetimes:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:0:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_USAGE_EXPORT:0:0
+copy_across_lifetimes:PSA_KEY_LIFETIME_PERSISTENT:0x1000:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:0:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_VOLATILE:0x1000:0:PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_USAGE_EXPORT:0:0
 
 Copy persistent to persistent
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
-copy_across_lifetimes:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:0:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_PERSISTENT:2:PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_USAGE_EXPORT:0:0
+copy_across_lifetimes:PSA_KEY_LIFETIME_PERSISTENT:0x10000:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:0:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_PERSISTENT:0x10000:2:PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_USAGE_EXPORT:0:0
+
+Copy persistent to persistent, same id but different owner
+depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C:MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
+copy_across_lifetimes:PSA_KEY_LIFETIME_PERSISTENT:0x10000:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:0:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_PERSISTENT:0x10001:1:PSA_KEY_USAGE_EXPORT:0:0:PSA_KEY_USAGE_EXPORT:0:0
 
 Copy persistent to persistent with enrollment algorithm
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CTR:MBEDTLS_CIPHER_MODE_CBC
-copy_across_lifetimes:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:PSA_ALG_CTR:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_PERSISTENT:2:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_ALG_CBC_NO_PADDING:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_ALG_CBC_NO_PADDING
+copy_across_lifetimes:PSA_KEY_LIFETIME_PERSISTENT:0x100000:1:PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY:PSA_ALG_CTR:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"404142434445464748494a4b4c4d4e4f":PSA_KEY_LIFETIME_PERSISTENT:0x100000:2:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_ALG_CBC_NO_PADDING:PSA_KEY_USAGE_EXPORT:PSA_ALG_CTR:PSA_ALG_CBC_NO_PADDING
 
 Copy volatile to occupied
 depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C
diff --git a/tests/suites/test_suite_psa_crypto_slot_management.function b/tests/suites/test_suite_psa_crypto_slot_management.function
index 3a14b12..fa3dd6e 100644
--- a/tests/suites/test_suite_psa_crypto_slot_management.function
+++ b/tests/suites/test_suite_psa_crypto_slot_management.function
@@ -34,21 +34,22 @@
  * code. */
 
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-static psa_key_id_t key_ids_used_in_test[9];
+static mbedtls_svc_key_id_t key_ids_used_in_test[9];
 static size_t num_key_ids_used;
 
 /* Record a key id as potentially used in a test case. */
-static int test_uses_key_id( psa_key_id_t key_id )
+static int test_uses_key_id( mbedtls_svc_key_id_t key_id )
 {
     size_t i;
-    if( key_id > PSA_MAX_PERSISTENT_KEY_IDENTIFIER )
+    if( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key_id ) >
+        PSA_MAX_PERSISTENT_KEY_IDENTIFIER )
     {
         /* Don't touch key id values that designate non-key files. */
         return( 1 );
     }
     for( i = 0; i < num_key_ids_used ; i++ )
     {
-        if( key_id == key_ids_used_in_test[i] )
+        if( mbedtls_svc_key_id_equal( key_id, key_ids_used_in_test[i] ) )
             return( 1 );
     }
     if( num_key_ids_used == ARRAY_LENGTH( key_ids_used_in_test ) )
@@ -172,13 +173,13 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
-void persistent_slot_lifecycle( int lifetime_arg, int id_arg,
+void persistent_slot_lifecycle( int lifetime_arg, int owner_id_arg, int id_arg,
                                 int usage_arg, int alg_arg, int alg2_arg,
                                 int type_arg, data_t *key_data,
                                 int close_method_arg )
 {
     psa_key_lifetime_t lifetime = lifetime_arg;
-    psa_key_id_t id = id_arg;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( owner_id_arg, id_arg );
     psa_algorithm_t alg = alg_arg;
     psa_algorithm_t alg2 = alg2_arg;
     psa_key_usage_t usage_flags = usage_arg;
@@ -190,6 +191,12 @@
     uint8_t *reexported = NULL;
     size_t reexported_length = -1;
 
+#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+    mbedtls_svc_key_id_t wrong_owner_id =
+        mbedtls_svc_key_id_make( owner_id_arg + 1, id_arg );
+    psa_key_handle_t invalid_handle = 0;
+#endif
+
     TEST_USES_KEY_ID( id );
 
     PSA_ASSERT( psa_crypto_init( ) );
@@ -204,9 +211,16 @@
     PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
                                 &handle ) );
     TEST_ASSERT( handle != 0 );
+
+#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+    TEST_EQUAL( psa_open_key( wrong_owner_id, &invalid_handle ),
+                PSA_ERROR_DOES_NOT_EXIST );
+#endif
+
     PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
     TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
-    TEST_EQUAL( psa_get_key_id( &attributes ), id );
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes ), id ) );
     TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
     TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
     TEST_EQUAL( psa_get_key_enrollment_algorithm( &attributes ), alg2 );
@@ -214,10 +228,17 @@
 
     /* Close the key and reopen it. */
     PSA_ASSERT( psa_close_key( handle ) );
+
+#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+    TEST_EQUAL( psa_open_key( wrong_owner_id, &invalid_handle ),
+                PSA_ERROR_DOES_NOT_EXIST );
+#endif
+
     PSA_ASSERT( psa_open_key( id, &handle ) );
     PSA_ASSERT( psa_get_key_attributes( handle, &attributes ) );
     TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
-    TEST_EQUAL( psa_get_key_id( &attributes ), id );
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes ), id ) );
     TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
     TEST_EQUAL( psa_get_key_algorithm( &attributes ), alg );
     TEST_EQUAL( psa_get_key_enrollment_algorithm( &attributes ), alg2 );
@@ -247,8 +268,9 @@
             PSA_ASSERT( psa_get_key_attributes( handle, &read_attributes ) );
             TEST_EQUAL( psa_get_key_lifetime( &attributes ),
                         psa_get_key_lifetime( &read_attributes ) );
-            TEST_EQUAL( psa_get_key_id( &attributes ),
-                        psa_get_key_id( &read_attributes ) );
+            TEST_ASSERT( mbedtls_svc_key_id_equal(
+                             psa_get_key_id( &attributes ),
+                             psa_get_key_id( &read_attributes ) ) );
             TEST_EQUAL( psa_get_key_usage_flags( &attributes ), usage_flags );
             TEST_EQUAL( psa_get_key_algorithm( &attributes ),
                         psa_get_key_algorithm( &read_attributes ) );
@@ -292,11 +314,11 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
-void create_existent( int lifetime_arg, int id_arg,
+void create_existent( int lifetime_arg, int owner_id_arg, int id_arg,
                       int reopen_policy_arg )
 {
     psa_key_lifetime_t lifetime = lifetime_arg;
-    psa_key_id_t id = id_arg;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( owner_id_arg, id_arg );
     psa_key_handle_t handle1 = 0, handle2 = 0;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_type_t type1 = PSA_KEY_TYPE_RAW_DATA;
@@ -338,7 +360,8 @@
     /* Check that the original key hasn't changed. */
     psa_reset_key_attributes( &attributes );
     PSA_ASSERT( psa_get_key_attributes( handle1, &attributes ) );
-    TEST_EQUAL( psa_get_key_id( &attributes ), id );
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes ), id ) );
     TEST_EQUAL( psa_get_key_lifetime( &attributes ), lifetime );
     TEST_EQUAL( psa_get_key_type( &attributes ), type1 );
     TEST_EQUAL( psa_get_key_bits( &attributes ), bits1 );
@@ -363,7 +386,7 @@
 void open_fail( int id_arg,
                 int expected_status_arg )
 {
-    psa_key_id_t id = id_arg;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, id_arg );
     psa_status_t expected_status = expected_status_arg;
     psa_key_handle_t handle = 0xdead;
 
@@ -382,7 +405,7 @@
                   int expected_status_arg )
 {
     psa_key_lifetime_t lifetime = lifetime_arg;
-    psa_key_id_t id = id_arg;
+    mbedtls_svc_key_id_t id = mbedtls_svc_key_id_make( 1, id_arg );
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_status_t expected_status = expected_status_arg;
     psa_key_handle_t handle = 0xdead;
@@ -409,25 +432,27 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void copy_across_lifetimes( int source_lifetime_arg, int source_id_arg,
-                            int source_usage_arg,
+void copy_across_lifetimes( int source_lifetime_arg, int source_owner_id_arg,
+                            int source_id_arg, int source_usage_arg,
                             int source_alg_arg, int source_alg2_arg,
                             int type_arg, data_t *material,
-                            int target_lifetime_arg, int target_id_arg,
-                            int target_usage_arg,
+                            int target_lifetime_arg, int target_owner_id_arg,
+                            int target_id_arg, int target_usage_arg,
                             int target_alg_arg, int target_alg2_arg,
                             int expected_usage_arg,
                             int expected_alg_arg, int expected_alg2_arg )
 {
     psa_key_lifetime_t source_lifetime = source_lifetime_arg;
-    psa_key_id_t source_id = source_id_arg;
+    mbedtls_svc_key_id_t source_id =
+        mbedtls_svc_key_id_make( source_owner_id_arg, source_id_arg );
     psa_key_usage_t source_usage = source_usage_arg;
     psa_algorithm_t source_alg = source_alg_arg;
     psa_key_handle_t source_handle = 0;
     psa_key_attributes_t source_attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_key_type_t source_type = type_arg;
     psa_key_lifetime_t target_lifetime = target_lifetime_arg;
-    psa_key_id_t target_id = target_id_arg;
+    mbedtls_svc_key_id_t target_id =
+        mbedtls_svc_key_id_make( target_owner_id_arg, target_id_arg );
     psa_key_usage_t target_usage = target_usage_arg;
     psa_algorithm_t target_alg = target_alg_arg;
     psa_key_handle_t target_handle = 0;
@@ -443,11 +468,9 @@
     PSA_ASSERT( psa_crypto_init( ) );
 
     /* Populate the source slot. */
-    if( source_lifetime != PSA_KEY_LIFETIME_VOLATILE )
-    {
-        psa_set_key_id( &source_attributes, source_id );
-        psa_set_key_lifetime( &source_attributes, source_lifetime );
-    }
+    psa_set_key_id( &source_attributes, source_id );
+    psa_set_key_lifetime( &source_attributes, source_lifetime );
+
     psa_set_key_type( &source_attributes, source_type );
     psa_set_key_usage_flags( &source_attributes, source_usage );
     psa_set_key_algorithm( &source_attributes, source_alg );
@@ -459,11 +482,9 @@
     PSA_ASSERT( psa_get_key_attributes( source_handle, &source_attributes ) );
 
     /* Prepare the target slot. */
-    if( target_lifetime != PSA_KEY_LIFETIME_VOLATILE )
-    {
-        psa_set_key_id( &target_attributes, target_id );
-        psa_set_key_lifetime( &target_attributes, target_lifetime );
-    }
+    psa_set_key_id( &target_attributes, target_id );
+    psa_set_key_lifetime( &target_attributes, target_lifetime );
+
     psa_set_key_usage_flags( &target_attributes, target_usage );
     psa_set_key_algorithm( &target_attributes, target_alg );
     psa_set_key_enrollment_algorithm( &target_attributes, target_alg2_arg );
@@ -487,7 +508,21 @@
     /* Test that the target slot has the expected content. */
     psa_reset_key_attributes( &target_attributes );
     PSA_ASSERT( psa_get_key_attributes( target_handle, &target_attributes ) );
-    TEST_EQUAL( target_id, psa_get_key_id( &target_attributes ) );
+
+    if( target_lifetime != PSA_KEY_LIFETIME_VOLATILE )
+    {
+        TEST_ASSERT( mbedtls_svc_key_id_equal(
+                         target_id, psa_get_key_id( &target_attributes ) ) );
+    }
+    else
+    {
+#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+        TEST_EQUAL( MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( target_id ),
+                    target_owner_id_arg );
+#endif
+        TEST_EQUAL( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( target_id ), 0 );
+    }
+
     TEST_EQUAL( target_lifetime, psa_get_key_lifetime( &target_attributes ) );
     TEST_EQUAL( source_type, psa_get_key_type( &target_attributes ) );
     TEST_EQUAL( psa_get_key_bits( &source_attributes ),
@@ -534,13 +569,15 @@
                        int target_type_arg, data_t *target_material )
 {
     psa_key_lifetime_t source_lifetime = source_lifetime_arg;
-    psa_key_id_t source_id = source_id_arg;
+    mbedtls_svc_key_id_t source_id =
+        mbedtls_svc_key_id_make( 1, source_id_arg );
     psa_key_usage_t source_usage = source_usage_arg;
     psa_algorithm_t source_alg = source_alg_arg;
     psa_key_handle_t source_handle = 0;
     psa_key_type_t source_type = source_type_arg;
     psa_key_lifetime_t target_lifetime = target_lifetime_arg;
-    psa_key_id_t target_id = target_id_arg;
+    mbedtls_svc_key_id_t target_id =
+        mbedtls_svc_key_id_make( 1, target_id_arg );
     psa_key_usage_t target_usage = target_usage_arg;
     psa_algorithm_t target_alg = target_alg_arg;
     psa_key_handle_t target_handle = 0;
@@ -570,7 +607,7 @@
                                 &source_handle ) );
 
     /* Populate the target slot. */
-    if( target_id == source_id )
+    if( mbedtls_svc_key_id_equal( target_id, source_id ) )
     {
         target_handle = source_handle;
     }
@@ -597,8 +634,9 @@
 
     /* Test that the target slot is unaffected. */
     PSA_ASSERT( psa_get_key_attributes( target_handle, &attributes2 ) );
-    TEST_EQUAL( psa_get_key_id( &attributes1 ),
-                psa_get_key_id( &attributes2 ) );
+    TEST_ASSERT( mbedtls_svc_key_id_equal(
+                     psa_get_key_id( &attributes1 ),
+                     psa_get_key_id( &attributes2 ) ) );
     TEST_EQUAL( psa_get_key_lifetime( &attributes1 ),
                 psa_get_key_lifetime( &attributes2 ) );
     TEST_EQUAL( psa_get_key_type( &attributes1 ),
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index 1b79191..6e653ff 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -10398,6 +10398,132 @@
 depends_on:MBEDTLS_DES_C:MBEDTLS_SHA512_C:!MBEDTLS_SHA512_NO_SHA384
 ssl_decrypt_non_etm_cbc:MBEDTLS_CIPHER_DES_EDE3_CBC:MBEDTLS_MD_SHA384:1:255
 
+SSL TLS 1.3 Key schedule: Secret evolution #1
+# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/)
+# Initial secret to Early Secret
+depends_on:MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
+ssl_tls1_3_key_evolution:MBEDTLS_MD_SHA256:"":"":"33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a"
+
+SSL TLS 1.3 Key schedule: Secret evolution #2
+# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/)
+# Early secret to Handshake Secret
+ssl_tls1_3_key_evolution:MBEDTLS_MD_SHA256:"33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a":"df4a291baa1eb7cfa6934b29b474baad2697e29f1f920dcc77c8a0a088447624":"fb9fc80689b3a5d02c33243bf69a1b1b20705588a794304a6e7120155edf149a"
+
+SSL TLS 1.3 Key schedule: Secret evolution #3
+# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/)
+# Handshake secret to Master Secret
+ssl_tls1_3_key_evolution:MBEDTLS_MD_SHA256:"fb9fc80689b3a5d02c33243bf69a1b1b20705588a794304a6e7120155edf149a":"":"7f2882bb9b9a46265941653e9c2f19067118151e21d12e57a7b6aca1f8150c8d"
+
+SSL TLS 1.3 Key schedule: HKDF Expand Label #1
+# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/)
+# Server handshake traffic secret -> Server traffic key
+# HKDF-Expand-Label(server_handshake_secret, "key", "", 16)
+ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"a2067265e7f0652a923d5d72ab0467c46132eeb968b6a32d311c805868548814":tls1_3_label_key:"":16:"844780a7acad9f980fa25c114e43402a"
+
+SSL TLS 1.3 Key schedule: HKDF Expand Label #2
+# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/)
+# Server handshake traffic secret -> Server traffic IV
+# HKDF-Expand-Label(server_handshake_secret, "iv", "", 12)
+ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"a2067265e7f0652a923d5d72ab0467c46132eeb968b6a32d311c805868548814":tls1_3_label_iv:"":12:"4c042ddc120a38d1417fc815"
+
+SSL TLS 1.3 Key schedule: HKDF Expand Label #3
+# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/)
+# Client handshake traffic secret -> Client traffic key
+# HKDF-Expand-Label(client_handshake_secret, "key", "", 16)
+ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"ff0e5b965291c608c1e8cd267eefc0afcc5e98a2786373f0db47b04786d72aea":tls1_3_label_key:"":16:"7154f314e6be7dc008df2c832baa1d39"
+
+SSL TLS 1.3 Key schedule: HKDF Expand Label #4
+# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/)
+# Client handshake traffic secret -> Client traffic IV
+# HKDF-Expand-Label(client_handshake_secret, "iv", "", 12)
+ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"ff0e5b965291c608c1e8cd267eefc0afcc5e98a2786373f0db47b04786d72aea":tls1_3_label_iv:"":12:"71abc2cae4c699d47c600268"
+
+SSL TLS 1.3 Key schedule: HKDF Expand Label #5 (RFC 8448)
+# Vector from RFC 8448
+# Server handshake traffic secret -> Server traffic IV
+# HKDF-Expand-Label(server_handshake_secret, "iv", "", 12)
+ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"b67b7d690cc16c4e75e54213cb2d37b4e9c912bcded9105d42befd59d391ad38":tls1_3_label_iv:"":12:"5d313eb2671276ee13000b30"
+
+SSL TLS 1.3 Key schedule: HKDF Expand Label #6 (RFC 8448)
+# Vector from RFC 8448
+# Server handshake traffic secret -> Server traffic Key
+# HKDF-Expand-Label(server_handshake_secret, "key", "", 16)
+ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"b67b7d690cc16c4e75e54213cb2d37b4e9c912bcded9105d42befd59d391ad38":tls1_3_label_key:"":16:"3fce516009c21727d0f2e4e86ee403bc"
+
+SSL TLS 1.3 Key schedule: HKDF Expand Label #7 (RFC 8448)
+# Vector from RFC 8448
+# Client handshake traffic secret -> Client traffic IV
+# HKDF-Expand-Label(client_handshake_secret, "iv", "", 12)
+ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"b3eddb126e067f35a780b3abf45e2d8f3b1a950738f52e9600746a0e27a55a21":tls1_3_label_iv:"":12:"5bd3c71b836e0b76bb73265f"
+
+SSL TLS 1.3 Key schedule: HKDF Expand Label #8 (RFC 8448)
+# Vector from RFC 8448
+# Client handshake traffic secret -> Client traffic Key
+# HKDF-Expand-Label(client_handshake_secret, "key", "", 16)
+ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"b3eddb126e067f35a780b3abf45e2d8f3b1a950738f52e9600746a0e27a55a21":tls1_3_label_key:"":16:"dbfaa693d1762c5b666af5d950258d01"
+
+SSL TLS 1.3 Key schedule: HKDF Expand Label #9 (RFC 8448)
+# Calculation of finished_key
+ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"2faac08f851d35fea3604fcb4de82dc62c9b164a70974d0462e27f1ab278700f":tls1_3_label_finished:"":32:"5ace394c26980d581243f627d1150ae27e37fa52364e0a7f20ac686d09cd0e8e"
+
+SSL TLS 1.3 Key schedule: HKDF Expand Label #10 (RFC 8448)
+# Calculation of resumption key
+ssl_tls1_3_hkdf_expand_label:MBEDTLS_MD_SHA256:"7df235f2031d2a051287d02b0241b0bfdaf86cc856231f2d5aba46c434ec196c":tls1_3_label_resumption:"0000":32:"4ecd0eb6ec3b4d87f5d6028f922ca4c5851a277fd41311c9e62d2c9492e1c4f3"
+
+SSL TLS 1.3 Key schedule: Traffic key generation #1
+# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/)
+# Client/Server handshake traffic secrets -> Client/Server traffic {Key,IV}
+ssl_tls1_3_traffic_key_generation:MBEDTLS_MD_SHA256:"a2067265e7f0652a923d5d72ab0467c46132eeb968b6a32d311c805868548814":"ff0e5b965291c608c1e8cd267eefc0afcc5e98a2786373f0db47b04786d72aea":12:16:"844780a7acad9f980fa25c114e43402a":"4c042ddc120a38d1417fc815":"7154f314e6be7dc008df2c832baa1d39":"71abc2cae4c699d47c600268"
+
+SSL TLS 1.3 Key schedule: Traffic key generation #2 (RFC 8448)
+# Vector RFC 8448
+# Client/Server handshake traffic secrets -> Client/Server traffic {Key,IV}
+ssl_tls1_3_traffic_key_generation:MBEDTLS_MD_SHA256:"a2067265e7f0652a923d5d72ab0467c46132eeb968b6a32d311c805868548814":"ff0e5b965291c608c1e8cd267eefc0afcc5e98a2786373f0db47b04786d72aea":12:16:"844780a7acad9f980fa25c114e43402a":"4c042ddc120a38d1417fc815":"7154f314e6be7dc008df2c832baa1d39":"71abc2cae4c699d47c600268"
+
+SSL TLS 1.3 Key schedule: Derive-Secret( ., "derived", "")
+# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/)
+# Derive-Secret( Early-Secret, "derived", "")
+# Tests the case where context isn't yet hashed (empty string here,
+# but still needs to be hashed)
+ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"33ad0a1c607ec03b09e6cd9893680ce210adf300aa1f2660e1b22e10f170f92a":tls1_3_label_derived:"":32:MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED:"6f2615a108c702c5678f54fc9dbab69716c076189c48250cebeac3576c3611ba"
+
+SSL TLS 1.3 Key schedule: Derive-Secret( ., "s ap traffic", hash) #1
+# Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/)
+# Derive-Secret( MasterSecret, "s ap traffic", hash)
+# Tests the case where context is already hashed
+ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"7f2882bb9b9a46265941653e9c2f19067118151e21d12e57a7b6aca1f8150c8d":tls1_3_label_s_ap_traffic:"22844b930e5e0a59a09d5ac35fc032fc91163b193874a265236e568077378d8b":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"3fc35ea70693069a277956afa23b8f4543ce68ac595f2aace05cd7a1c92023d5"
+
+SSL TLS 1.3 Key schedule: Derive-Secret( ., "c e traffic", hash)
+# Vector from RFC 8448
+ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"9b2188e9b2fc6d64d71dc329900e20bb41915000f678aa839cbb797cb7d8332c":tls1_3_label_c_e_traffic:"08ad0fa05d7c7233b1775ba2ff9f4c5b8b59276b7f227f13a976245f5d960913":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"3fbbe6a60deb66c30a32795aba0eff7eaa10105586e7be5c09678d63b6caab62"
+
+SSL TLS 1.3 Key schedule: Derive-Secret( ., "e exp master", hash)
+# Vector from RFC 8448
+ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"9b2188e9b2fc6d64d71dc329900e20bb41915000f678aa839cbb797cb7d8332c":tls1_3_label_e_exp_master:"08ad0fa05d7c7233b1775ba2ff9f4c5b8b59276b7f227f13a976245f5d960913":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"b2026866610937d7423e5be90862ccf24c0e6091186d34f812089ff5be2ef7df"
+
+SSL TLS 1.3 Key schedule: Derive-Secret( ., "c hs traffic", hash)
+# Vector from RFC 8448
+ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"005cb112fd8eb4ccc623bb88a07c64b3ede1605363fc7d0df8c7ce4ff0fb4ae6":tls1_3_label_c_hs_traffic:"f736cb34fe25e701551bee6fd24c1cc7102a7daf9405cb15d97aafe16f757d03"::32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"2faac08f851d35fea3604fcb4de82dc62c9b164a70974d0462e27f1ab278700f"
+
+SSL TLS 1.3 Key schedule: Derive-Secret( ., "s hs traffic", hash)
+# Vector from RFC 8448
+ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"005cb112fd8eb4ccc623bb88a07c64b3ede1605363fc7d0df8c7ce4ff0fb4ae6":tls1_3_label_s_hs_traffic:"f736cb34fe25e701551bee6fd24c1cc7102a7daf9405cb15d97aafe16f757d03":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"fe927ae271312e8bf0275b581c54eef020450dc4ecffaa05a1a35d27518e7803"
+
+SSL TLS 1.3 Key schedule: Derive-Secret( ., "c ap traffic", hash)
+# Vector from RFC 8448
+ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"e2d32d4ed66dd37897a0e80c84107503ce58bf8aad4cb55a5002d77ecb890ece":tls1_3_label_c_ap_traffic:"b0aeffc46a2cfe33114e6fd7d51f9f04b1ca3c497dab08934a774a9d9ad7dbf3":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"2abbf2b8e381d23dbebe1dd2a7d16a8bf484cb4950d23fb7fb7fa8547062d9a1"
+
+SSL TLS 1.3 Key schedule: Derive-Secret( ., "s ap traffic", hash) #2
+# Vector from RFC 8448
+ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"e2d32d4ed66dd37897a0e80c84107503ce58bf8aad4cb55a5002d77ecb890ece":tls1_3_label_s_ap_traffic:"b0aeffc46a2cfe33114e6fd7d51f9f04b1ca3c497dab08934a774a9d9ad7dbf3":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"cc21f1bf8feb7dd5fa505bd9c4b468a9984d554a993dc49e6d285598fb672691"
+
+SSL TLS 1.3 Key schedule: Derive-Secret( ., "exp master", hash)
+# Vector from RFC 8448
+ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"e2d32d4ed66dd37897a0e80c84107503ce58bf8aad4cb55a5002d77ecb890ece":tls1_3_label_exp_master:"b0aeffc46a2cfe33114e6fd7d51f9f04b1ca3c497dab08934a774a9d9ad7dbf3":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"3fd93d4ffddc98e64b14dd107aedf8ee4add23f4510f58a4592d0b201bee56b4"
+
+SSL TLS 1.3 Key schedule: Derive-Secret( ., "res master", hash)
+# Vector from RFC 8448
+ssl_tls1_3_derive_secret:MBEDTLS_MD_SHA256:"e2d32d4ed66dd37897a0e80c84107503ce58bf8aad4cb55a5002d77ecb890ece":tls1_3_label_res_master:"c3c122e0bd907a4a3ff6112d8fd53dbf89c773d9552e8b6b9d56d361b3a97bf6":32:MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED:"5e95bdf1f89005ea2e9aa0ba85e728e3c19c5fe0c699e3f5bee59faebd0b5406"
 
 SSL TLS_PRF MBEDTLS_SSL_TLS_PRF_NONE
 ssl_tls_prf:MBEDTLS_SSL_TLS_PRF_NONE:"":"":"test tls_prf label":"":MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 7c4f865..9fcf367 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -6,11 +6,20 @@
 #include <mbedtls/certs.h>
 #include <mbedtls/timing.h>
 #include <mbedtls/debug.h>
+#include <ssl_tls13_keys.h>
 
 #include <ssl_invasive.h>
 
 #include <test/constant_flow.h>
 
+enum
+{
+#define MBEDTLS_SSL_TLS1_3_LABEL( name, string )   \
+     tls1_3_label_ ## name,
+MBEDTLS_SSL_TLS1_3_LABEL_LIST
+#undef MBEDTLS_SSL_TLS1_3_LABEL
+};
+
 typedef struct log_pattern
 {
     const char *pattern;
@@ -3669,6 +3678,150 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+void ssl_tls1_3_hkdf_expand_label( int hash_alg,
+                                   data_t *secret,
+                                   int label_idx,
+                                   data_t *ctx,
+                                   int desired_length,
+                                   data_t *expected )
+{
+    unsigned char dst[ 100 ];
+
+    unsigned char const *lbl = NULL;
+    size_t lbl_len;
+#define MBEDTLS_SSL_TLS1_3_LABEL( name, string )                        \
+    if( label_idx == (int) tls1_3_label_ ## name )                      \
+    {                                                                   \
+        lbl = mbedtls_ssl_tls1_3_labels.name;                           \
+        lbl_len = sizeof( mbedtls_ssl_tls1_3_labels.name );             \
+    }
+MBEDTLS_SSL_TLS1_3_LABEL_LIST
+#undef MBEDTLS_SSL_TLS1_3_LABEL
+    TEST_ASSERT( lbl != NULL );
+
+    /* Check sanity of test parameters. */
+    TEST_ASSERT( (size_t) desired_length <= sizeof(dst) );
+    TEST_ASSERT( (size_t) desired_length == expected->len );
+
+    TEST_ASSERT( mbedtls_ssl_tls1_3_hkdf_expand_label(
+                      (mbedtls_md_type_t) hash_alg,
+                      secret->x, secret->len,
+                      lbl, lbl_len,
+                      ctx->x, ctx->len,
+                      dst, desired_length ) == 0 );
+
+    ASSERT_COMPARE( dst, (size_t) desired_length,
+                    expected->x, (size_t) expected->len );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+void ssl_tls1_3_traffic_key_generation( int hash_alg,
+                                        data_t *server_secret,
+                                        data_t *client_secret,
+                                        int desired_iv_len,
+                                        int desired_key_len,
+                                        data_t *expected_server_write_key,
+                                        data_t *expected_server_write_iv,
+                                        data_t *expected_client_write_key,
+                                        data_t *expected_client_write_iv )
+{
+    mbedtls_ssl_key_set keys;
+
+    /* Check sanity of test parameters. */
+    TEST_ASSERT( client_secret->len == server_secret->len );
+    TEST_ASSERT( expected_client_write_iv->len == expected_server_write_iv->len &&
+                 expected_client_write_iv->len == (size_t) desired_iv_len );
+    TEST_ASSERT( expected_client_write_key->len == expected_server_write_key->len &&
+                 expected_client_write_key->len == (size_t) desired_key_len );
+
+    TEST_ASSERT( mbedtls_ssl_tls1_3_make_traffic_keys(
+                     (mbedtls_md_type_t) hash_alg,
+                     client_secret->x,
+                     server_secret->x,
+                     client_secret->len /* == server_secret->len */,
+                     desired_key_len, desired_iv_len,
+                     &keys ) == 0 );
+
+    ASSERT_COMPARE( keys.client_write_key,
+                    keys.key_len,
+                    expected_client_write_key->x,
+                    (size_t) desired_key_len );
+    ASSERT_COMPARE( keys.server_write_key,
+                    keys.key_len,
+                    expected_server_write_key->x,
+                    (size_t) desired_key_len );
+    ASSERT_COMPARE( keys.client_write_iv,
+                    keys.iv_len,
+                    expected_client_write_iv->x,
+                    (size_t) desired_iv_len );
+    ASSERT_COMPARE( keys.server_write_iv,
+                    keys.iv_len,
+                    expected_server_write_iv->x,
+                    (size_t) desired_iv_len );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+void ssl_tls1_3_derive_secret( int hash_alg,
+                               data_t *secret,
+                               int label_idx,
+                               data_t *ctx,
+                               int desired_length,
+                               int already_hashed,
+                               data_t *expected )
+{
+    unsigned char dst[ 100 ];
+
+    unsigned char const *lbl = NULL;
+    size_t lbl_len;
+#define MBEDTLS_SSL_TLS1_3_LABEL( name, string )                        \
+    if( label_idx == (int) tls1_3_label_ ## name )                      \
+    {                                                                   \
+        lbl = mbedtls_ssl_tls1_3_labels.name;                           \
+        lbl_len = sizeof( mbedtls_ssl_tls1_3_labels.name );             \
+    }
+MBEDTLS_SSL_TLS1_3_LABEL_LIST
+#undef MBEDTLS_SSL_TLS1_3_LABEL
+    TEST_ASSERT( lbl != NULL );
+
+    /* Check sanity of test parameters. */
+    TEST_ASSERT( (size_t) desired_length <= sizeof(dst) );
+    TEST_ASSERT( (size_t) desired_length == expected->len );
+
+    TEST_ASSERT( mbedtls_ssl_tls1_3_derive_secret(
+                      (mbedtls_md_type_t) hash_alg,
+                      secret->x, secret->len,
+                      lbl, lbl_len,
+                      ctx->x, ctx->len,
+                      already_hashed,
+                      dst, desired_length ) == 0 );
+
+    ASSERT_COMPARE( dst, desired_length,
+                    expected->x, desired_length );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+void ssl_tls1_3_key_evolution( int hash_alg,
+                               data_t *secret,
+                               data_t *input,
+                               data_t *expected )
+{
+    unsigned char secret_new[ MBEDTLS_MD_MAX_SIZE ];
+
+    TEST_ASSERT( mbedtls_ssl_tls1_3_evolve_secret(
+                      (mbedtls_md_type_t) hash_alg,
+                      secret->len ? secret->x : NULL,
+                      input->len ? input->x : NULL, input->len,
+                      secret_new ) == 0 );
+
+    ASSERT_COMPARE( secret_new, (size_t) expected->len,
+                    expected->x, (size_t) expected->len );
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void ssl_tls_prf( int type, data_t * secret, data_t * random,
                   char *label, data_t *result_hex_str, int exp_ret )
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 578289f..b243b73 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -238,8 +238,13 @@
     <ClInclude Include="..\..\tests\include\test\psa_crypto_helpers.h" />

     <ClInclude Include="..\..\tests\include\test\psa_helpers.h" />

     <ClInclude Include="..\..\tests\include\test\random.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\cipher.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\keygen.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\signature.h" />

+    <ClInclude Include="..\..\tests\include\test\drivers\test_driver.h" />

     <ClInclude Include="..\..\library\common.h" />

     <ClInclude Include="..\..\library\psa_crypto_core.h" />

+    <ClInclude Include="..\..\library\psa_crypto_driver_wrappers.h" />

     <ClInclude Include="..\..\library\psa_crypto_invasive.h" />

     <ClInclude Include="..\..\library\psa_crypto_its.h" />

     <ClInclude Include="..\..\library\psa_crypto_se.h" />

@@ -247,6 +252,7 @@
     <ClInclude Include="..\..\library\psa_crypto_slot_management.h" />

     <ClInclude Include="..\..\library\psa_crypto_storage.h" />

     <ClInclude Include="..\..\library\ssl_invasive.h" />

+    <ClInclude Include="..\..\library\ssl_tls13_keys.h" />

     <ClInclude Include="..\..\3rdparty\everest\include\everest\everest.h" />

     <ClInclude Include="..\..\3rdparty\everest\include\everest\Hacl_Curve25519.h" />

     <ClInclude Include="..\..\3rdparty\everest\include\everest\kremlib.h" />

@@ -307,6 +313,7 @@
     <ClCompile Include="..\..\library\platform_util.c" />

     <ClCompile Include="..\..\library\poly1305.c" />

     <ClCompile Include="..\..\library\psa_crypto.c" />

+    <ClCompile Include="..\..\library\psa_crypto_driver_wrappers.c" />

     <ClCompile Include="..\..\library\psa_crypto_se.c" />

     <ClCompile Include="..\..\library\psa_crypto_slot_management.c" />

     <ClCompile Include="..\..\library\psa_crypto_storage.c" />

@@ -325,6 +332,7 @@
     <ClCompile Include="..\..\library\ssl_srv.c" />

     <ClCompile Include="..\..\library\ssl_ticket.c" />

     <ClCompile Include="..\..\library\ssl_tls.c" />

+    <ClCompile Include="..\..\library\ssl_tls13_keys.c" />

     <ClCompile Include="..\..\library\threading.c" />

     <ClCompile Include="..\..\library\timing.c" />

     <ClCompile Include="..\..\library\version.c" />