Merge pull request #4959 from gilles-peskine-arm/psa-add-aria

Add ARIA to the PSA API
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 210aba4..cd990ab 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,6 +46,11 @@
 
 option(UNSAFE_BUILD "Allow unsafe builds. These builds ARE NOT SECURE." OFF)
 option(MBEDTLS_FATAL_WARNINGS "Compiler warnings treated as errors" ON)
+if(WIN32)
+    option(GEN_FILES "Generate the auto-generated files as needed" OFF)
+else()
+    option(GEN_FILES "Generate the auto-generated files as needed" ON)
+endif()
 
 string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}")
 string(REGEX MATCH "GNU" CMAKE_COMPILER_IS_GNU "${CMAKE_C_COMPILER_ID}")
@@ -135,6 +140,22 @@
     endif()
 endfunction(link_to_source)
 
+# Get the filename without the final extension (i.e. convert "a.b.c" to "a.b")
+function(get_name_without_last_ext dest_var full_name)
+    # Split into a list on '.' (but a cmake list is just a ';'-separated string)
+    string(REPLACE "." ";" ext_parts "${full_name}")
+    # Remove the last item if there are more than one
+    list(LENGTH ext_parts ext_parts_len)
+    if (${ext_parts_len} GREATER "1")
+        math(EXPR ext_parts_last_item "${ext_parts_len} - 1")
+        list(REMOVE_AT ext_parts ${ext_parts_last_item})
+    endif()
+    # Convert back to a string by replacing separators with '.'
+    string(REPLACE ";" "." no_ext_name "${ext_parts}")
+    # Copy into the desired variable
+    set(${dest_var} ${no_ext_name} PARENT_SCOPE)
+endfunction(get_name_without_last_ext)
+
 string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}")
 
 include(CheckCCompilerFlag)
diff --git a/ChangeLog.d/add_psa_m_aead.txt b/ChangeLog.d/add_psa_m_aead.txt
new file mode 100644
index 0000000..fa4e7ac
--- /dev/null
+++ b/ChangeLog.d/add_psa_m_aead.txt
@@ -0,0 +1,3 @@
+Features
+   * Implement the PSA multipart AEAD interface, currently supporting
+     ChaChaPoly and GCM.
diff --git a/ChangeLog.d/base64-ranges.txt b/ChangeLog.d/base64-ranges.txt
new file mode 100644
index 0000000..e3f3862
--- /dev/null
+++ b/ChangeLog.d/base64-ranges.txt
@@ -0,0 +1,4 @@
+Changes
+   * Improve the performance of base64 constant-flow code. The result is still
+     slower than the original non-constant-flow implementation, but much faster
+     than the previous constant-flow implementation. Fixes #4814.
diff --git a/ChangeLog.d/check-return.txt b/ChangeLog.d/check-return.txt
new file mode 100644
index 0000000..045b180
--- /dev/null
+++ b/ChangeLog.d/check-return.txt
@@ -0,0 +1,17 @@
+Bugfix
+   * Failures of alternative implementations of AES or DES single-block
+     functions enabled with MBEDTLS_AES_ENCRYPT_ALT, MBEDTLS_AES_DECRYPT_ALT,
+     MBEDTLS_DES_CRYPT_ECB_ALT or MBEDTLS_DES3_CRYPT_ECB_ALT were ignored.
+     This does not concern the implementation provided with Mbed TLS,
+     where this function cannot fail, or full-module replacements with
+     MBEDTLS_AES_ALT or MBEDTLS_DES_ALT. Reported by Armelle Duboc in #1092.
+
+Features
+   * Warn if errors from certain functions are ignored. This is currently
+     supported on GCC-like compilers and on MSVC and can be configured through
+     the macro MBEDTLS_CHECK_RETURN. The warnings are always enabled
+     (where supported) for critical functions where ignoring the return
+     value is almost always a bug. Enable the new configuration option
+     MBEDTLS_CHECK_RETURN_WARNING to get warnings for other functions. This
+     is currently implemented in the AES and DES modules, and will be extended
+     to other modules in the future.
diff --git a/ChangeLog.d/chunked_ccm.txt b/ChangeLog.d/chunked_ccm.txt
new file mode 100644
index 0000000..67faecc
--- /dev/null
+++ b/ChangeLog.d/chunked_ccm.txt
@@ -0,0 +1,8 @@
+Changes
+   * Implement multi-part CCM API.
+     The multi-part functions: mbedtls_ccm_starts(), mbedtls_ccm_set_lengths(),
+     mbedtls_ccm_update_ad(), mbedtls_ccm_update(), mbedtls_ccm_finish()
+     were introduced in mbedTLS 3.0 release, however their implementation was
+     postponed until now.
+     Implemented functions support chunked data input for both CCM and CCM*
+     algorithms.
diff --git a/ChangeLog.d/do-not-use-obsolete-header.txt b/ChangeLog.d/do-not-use-obsolete-header.txt
new file mode 100644
index 0000000..9a57ef1
--- /dev/null
+++ b/ChangeLog.d/do-not-use-obsolete-header.txt
@@ -0,0 +1,5 @@
+Bugfix
+   * Don't use the obsolete header path sys/fcntl.h in unit tests.
+     These header files cause compilation errors in musl.
+     Fixes #4969.
+
diff --git a/ChangeLog.d/fix-mbedtls_cipher_crypt-aes-ecb.txt b/ChangeLog.d/fix-mbedtls_cipher_crypt-aes-ecb.txt
new file mode 100644
index 0000000..6dc4724
--- /dev/null
+++ b/ChangeLog.d/fix-mbedtls_cipher_crypt-aes-ecb.txt
@@ -0,0 +1,2 @@
+Bugfix
+   * Fix mbedtls_cipher_crypt: AES-ECB when MBEDTLS_USE_PSA_CRYPTO is enabled.
diff --git a/ChangeLog.d/fix-psa_gen_key-status.txt b/ChangeLog.d/fix-psa_gen_key-status.txt
new file mode 100644
index 0000000..7860988
--- /dev/null
+++ b/ChangeLog.d/fix-psa_gen_key-status.txt
@@ -0,0 +1,2 @@
+Bugfix
+   * Fix the error returned by psa_generate_key() for a public key. Fixes #4551.
diff --git a/ChangeLog.d/issue5065.txt b/ChangeLog.d/issue5065.txt
new file mode 100644
index 0000000..943ee47
--- /dev/null
+++ b/ChangeLog.d/issue5065.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix compile-time or run-time errors in PSA
+     AEAD functions when ChachaPoly is disabled. Fixes #5065.
diff --git a/ChangeLog.d/muladdc-memory.txt b/ChangeLog.d/muladdc-memory.txt
new file mode 100644
index 0000000..218be5a
--- /dev/null
+++ b/ChangeLog.d/muladdc-memory.txt
@@ -0,0 +1,5 @@
+Bugfix
+   * Fix missing constraints on x86_64 and aarch64 assembly code
+     for bignum multiplication that broke some bignum operations with
+     (at least) Clang 12.
+     Fixes #4116, #4786, #4917, #4962.
diff --git a/ChangeLog.d/no-strerror.txt b/ChangeLog.d/no-strerror.txt
new file mode 100644
index 0000000..69743a8
--- /dev/null
+++ b/ChangeLog.d/no-strerror.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix the build of sample programs when neither MBEDTLS_ERROR_C nor
+     MBEDTLS_ERROR_STRERROR_DUMMY is enabled.
diff --git a/ChangeLog.d/psa_gcm_buffer_limitation.txt b/ChangeLog.d/psa_gcm_buffer_limitation.txt
new file mode 100644
index 0000000..0c07e24
--- /dev/null
+++ b/ChangeLog.d/psa_gcm_buffer_limitation.txt
@@ -0,0 +1,16 @@
+Bugfix
+   * Remove PSA'a AEAD finish/verify output buffer limitation for GCM.
+     The requirement of minimum 15 bytes for output buffer in
+     psa_aead_finish() and psa_aead_verify() does not apply to the built-in
+     implementation of GCM.
+   * Move GCM's update output buffer length verification from PSA AEAD to
+     the built-in implementation of the GCM.
+     The requirement for output buffer size to be equal or greater then
+     input buffer size is valid only for the built-in implementation of GCM.
+     Alternative GCM implementations can process whole blocks only.
+
+API changes
+   * New error code for GCM: MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL.
+     Alternative GCM implementations are expected to verify
+     the length of the provided output buffers and to return the
+     MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL in case the buffer length is too small.
diff --git a/ChangeLog.d/remove-greentea-support.txt b/ChangeLog.d/remove-greentea-support.txt
new file mode 100644
index 0000000..af4df4b
--- /dev/null
+++ b/ChangeLog.d/remove-greentea-support.txt
@@ -0,0 +1,3 @@
+Removals
+   * Remove the partial support for running unit tests via Greentea on Mbed OS,
+     which had been unmaintained since 2018.
diff --git a/ChangeLog.d/remove-ssl-export-keys.txt b/ChangeLog.d/remove-ssl-export-keys.txt
new file mode 100644
index 0000000..1a4b31d
--- /dev/null
+++ b/ChangeLog.d/remove-ssl-export-keys.txt
@@ -0,0 +1,5 @@
+Changes
+   * Remove MBEDTLS_SSL_EXPORT_KEYS, making it always on and increasing the
+     code size by about 80B on an M0 build. This option only gated an ability
+     to set a callback, but was deemed unnecessary as it was yet another define
+     to remember when writing tests, or test configurations. Fixes #4653.
diff --git a/README.md b/README.md
index b80ee11..e6924cb 100644
--- a/README.md
+++ b/README.md
@@ -67,6 +67,7 @@
 Any of the following methods are available to generate the configuration-independent files:
 
 * If not cross-compiling, running `make` with any target, or just `make`, will automatically generate required files.
+* On non-Windows systems, when not cross-compiling, CMake will generate the required files automatically.
 * Run `make generated_files` to generate all the configuration-independent files.
 * On Unix/POSIX systems, run `tests/scripts/check-generated-files.sh -u` to generate all the configuration-independent files.
 * On Windows, run `scripts\make_generated_files.bat` to generate all the configuration-independent files.
@@ -298,3 +299,10 @@
 ------------
 
 We gratefully accept bug reports and contributions from the community. Please see the [contributing guidelines](CONTRIBUTING.md) for details on how to do this.
+
+Contact
+-------
+
+* To report a security vulnerability in Mbed TLS, please email <mbed-tls-security@lists.trustedfirmware.org>. For more information, see [`SECURITY.md`](SECURITY.md).
+* To report a bug or request a feature in Mbed TLS, please [file an issue on GitHub](https://github.com/ARMmbed/mbedtls/issues/new/choose).
+* Please see [`SUPPORT.md`](SUPPORT.md) for other channels for discussion and support about Mbed TLS.
diff --git a/configs/config-thread.h b/configs/config-thread.h
index be889a1..36d8245 100644
--- a/configs/config-thread.h
+++ b/configs/config-thread.h
@@ -45,7 +45,6 @@
 #define MBEDTLS_SSL_PROTO_DTLS
 #define MBEDTLS_SSL_DTLS_ANTI_REPLAY
 #define MBEDTLS_SSL_DTLS_HELLO_VERIFY
-#define MBEDTLS_SSL_EXPORT_KEYS
 
 /* mbed TLS modules */
 #define MBEDTLS_AES_C
diff --git a/docs/.gitignore b/docs/.gitignore
index 33ae5ac..23f832b 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -1,3 +1,2 @@
 *.html
 *.pdf
-!PSACryptoDriverModelSpec.pdf
diff --git a/docs/PSACryptoDriverModelSpec.pdf b/docs/PSACryptoDriverModelSpec.pdf
deleted file mode 100644
index cf11380..0000000
--- a/docs/PSACryptoDriverModelSpec.pdf
+++ /dev/null
Binary files differ
diff --git a/docs/architecture/tls13-experimental.md b/docs/architecture/tls13-experimental.md
index 0009c68..88d0b73 100644
--- a/docs/architecture/tls13-experimental.md
+++ b/docs/architecture/tls13-experimental.md
@@ -66,3 +66,342 @@
   as part of `MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL`:
 
   - Reader ([`library/mps_reader.h`](../../library/mps_reader.h))
+
+
+MVP definition
+--------------
+
+- Overview
+
+  - The TLS 1.3 MVP implements only the client side of the protocol.
+
+  - The TLS 1.3 MVP supports ECDHE key establishment.
+
+  - The TLS 1.3 MVP does not support DHE key establishment.
+
+  - The TLS 1.3 MVP does not support pre-shared keys, including any form of
+    session resumption. This implies that it does not support sending early
+    data (0-RTT data).
+
+  - The TLS 1.3 MVP supports the authentication of the server by the client
+    but does not support authentication of the client by the server. In terms
+    of TLS 1.3 authentication messages, this means that the TLS 1.3 MVP
+    supports the processing of the Certificate and CertificateVerify messages
+    but not of the CertificateRequest message.
+
+  - The TLS 1.3 MVP does not support the handling of server HelloRetryRequest
+    message. In practice, this means that the handshake will fail if the MVP
+    does not provide in its ClientHello the shared secret associated to the
+    group selected by the server for key establishement. For more information,
+    see the comment associated to the `key_share` extension below.
+
+  - If the TLS 1.3 MVP receives a HelloRetryRequest or a CertificateRequest
+    message, it aborts the handshake with an handshake_failure closure alert
+    and the `mbedtls_ssl_handshake()` returns in error with the
+    `MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE` error code.
+
+- Supported cipher suites: depends on the library configuration. Potentially
+  all of them:
+  TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256,
+  TLS_AES_128_CCM_SHA256 and TLS_AES_128_CCM_8_SHA256.
+
+- Supported ClientHello extensions:
+
+  | Extension                    |   MVP   | Prototype (1) |
+  | ---------------------------- | ------- | ------------- |
+  | server_name                  | YES     | YES           |
+  | max_fragment_length          | no      | YES           |
+  | status_request               | no      | no            |
+  | supported_groups             | YES     | YES           |
+  | signature_algorithms         | YES     | YES           |
+  | use_srtp                     | no      | no            |
+  | heartbeat                    | no      | no            |
+  | apln                         | no      | YES           |
+  | signed_certificate_timestamp | no      | no            |
+  | client_certificate_type      | no      | no            |
+  | server_certificate_type      | no      | no            |
+  | padding                      | no      | no            |
+  | key_share                    | YES (2) | YES           |
+  | pre_shared_key               | no      | YES           |
+  | psk_key_exchange_modes       | no      | YES           |
+  | early_data                   | no      | YES           |
+  | cookie                       | no      | YES           |
+  | supported_versions           | YES (3) | YES           |
+  | certificate_authorities      | no      | no            |
+  | post_handshake_auth          | no      | no            |
+  | signature_algorithms_cert    | no      | no            |
+
+  (1) This is just for comparison.
+
+  (2) The MVP sends one shared secret corresponding to the configured preferred
+      group. The preferred group is the group of the first curve in the list of
+      allowed curves as defined by the configuration. The allowed curves are
+      by default ordered as follow: `secp256r1`, `x25519`, `secp384r1`
+      and finally `secp521r1`. This default order is aligned with the
+      list of mandatory-to-implement groups (in absence of an application
+      profile standard specifying otherwise) defined in section 9.1 of the
+      specification. The list of allowed curves can be changed through the
+      `mbedtls_ssl_conf_curves()` API.
+
+  (3) The MVP proposes only TLS 1.3 and does not support version negociation.
+      Out-of-protocol fallback is supported though if the Mbed TLS library
+      has been built to support both TLS 1.3 and TLS 1.2: just set the
+      maximum of the minor version of the SSL configuration to
+      MBEDTLS_SSL_MINOR_VERSION_3 (`mbedtls_ssl_conf_min_version()` API) and
+      re-initiate a server handshake.
+
+- Supported groups: depends on the library configuration.
+  Potentially all ECDHE groups but x448:
+  secp256r1, x25519, secp384r1 and secp521r1.
+
+  Finite field groups (DHE) are not supported.
+
+- Supported signature algorithms (both for certificates and CertificateVerify):
+  depends on the library configuration.
+  Potentially:
+  rsa_pkcs1_sha256, rsa_pss_rsae_sha256, ecdsa_secp256r1_sha256,
+  ecdsa_secp384r1_sha384 and ecdsa_secp521r1_sha512.
+
+  Note that in absence of an application profile standard specifying otherwise
+  the three first ones in the list above are mandatory (see section 9.1 of the
+  specification).
+
+- Supported versions: only TLS 1.3, version negotiation is not supported.
+
+- Compatibility with existing SSL/TLS build options:
+
+  The TLS 1.3 MVP is compatible with all TLS 1.2 configuration options in the
+  sense that when enabling the TLS 1.3 MVP in the library there is no need to
+  modify the configuration for TLS 1.2. Mbed TLS SSL/TLS related features are
+  not supported or not applicable to the TLS 1.3 MVP:
+
+  | Mbed TLS configuration option            | Support |
+  | ---------------------------------------- | ------- |
+  | MBEDTLS_SSL_ALL_ALERT_MESSAGES           | no      |
+  | MBEDTLS_SSL_ASYNC_PRIVATE                | no      |
+  | MBEDTLS_SSL_CONTEXT_SERIALIZATION        | no      |
+  | MBEDTLS_SSL_DEBUG_ALL                    | no      |
+  | MBEDTLS_SSL_ENCRYPT_THEN_MAC             | n/a     |
+  | MBEDTLS_SSL_EXTENDED_MASTER_SECRET       | n/a     |
+  | MBEDTLS_SSL_KEEP_PEER_CERTIFICATE        | no      |
+  | MBEDTLS_SSL_RENEGOTIATION                | n/a     |
+  | MBEDTLS_SSL_MAX_FRAGMENT_LENGTH          | no      |
+  |                                          |         |
+  | MBEDTLS_SSL_SESSION_TICKETS              | no      |
+  | MBEDTLS_SSL_EXPORT_KEYS                  | no (1)  |
+  | MBEDTLS_SSL_SERVER_NAME_INDICATION       | no      |
+  | MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH       | no      |
+  |                                          |         |
+  | MBEDTLS_ECP_RESTARTABLE                  | no      |
+  | MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED     | no      |
+  |                                          |         |
+  | MBEDTLS_KEY_EXCHANGE_PSK_ENABLED         | n/a (2) |
+  | MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED     | n/a     |
+  | MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED   | n/a     |
+  | MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED     | n/a     |
+  | MBEDTLS_KEY_EXCHANGE_RSA_ENABLED         | n/a     |
+  | MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED     | n/a     |
+  | MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED   | n/a     |
+  | MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED | n/a     |
+  | MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED  | n/a     |
+  | MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED    | n/a     |
+  | MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED     | n/a     |
+  |                                          |         |
+  | MBEDTLS_USE_PSA_CRYPTO                   | no      |
+
+  (1) Some support has already been upstreamed but it is incomplete.
+  (2) Key exchange configuration options for TLS 1.3 will likely to be
+      organized around the notion of key exchange mode along the line
+      of the MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_NONE/PSK/PSK_EPHEMERAL/EPHEMERAL
+      runtime configuration macros.
+
+- Quality considerations
+  - Standard Mbed TLS review bar
+  - Interoperability testing with OpenSSL and GnuTLS. Test with all the
+    cipher suites and signature algorithms supported by OpenSSL/GnuTLS server.
+  - Negative testing against OpenSSL/GnuTLS servers with which the
+    handshake fails due to incompatibility with the capabilities of the
+    MVP: TLS 1.2 or 1.1 server, server sending an HelloRetryRequest message in
+    response to the MVP ClientHello, server sending a CertificateRequest
+    message ...
+
+Coding rules checklist for TLS 1.3
+----------------------------------
+
+The following coding rules are aimed to be a checklist for TLS 1.3 upstreaming
+work to reduce review rounds and the number of comments in each round. They
+come along (do NOT replace) the project coding rules
+(https://tls.mbed.org/kb/development/mbedtls-coding-standards). They have been
+established and discussed following the review of #4882 that was the
+PR upstreaming the first part of TLS 1.3 ClientHello writing code.
+
+TLS 1.3 specific coding rules:
+
+  - TLS 1.3 specific C modules, headers, static functions names are prefixed
+    with `ssl_tls13_`. The same applies to structures and types that are
+    internal to C modules.
+
+  - TLS 1.3 specific exported functions, structures and types are
+    prefixed with `mbedtls_ssl_tls13_`.
+
+  - Use TLS1_3 in TLS 1.3 specific macros.
+
+  - The names of macros and variables related to a field or structure in the
+    TLS 1.3 specification should contain as far as possible the field name as
+    it is in the specification. If the field name is "too long" and we prefer
+    to introduce some kind of abbreviation of it, use the same abbreviation
+    everywhere in the code.
+
+    Example 1: #define CLIENT_HELLO_RANDOM_LEN 32, macro for the length of the
+        `random` field of the ClientHello message.
+
+    Example 2 (consistent abbreviation): `mbedtls_ssl_tls13_write_sig_alg_ext()`
+        and `MBEDTLS_TLS_EXT_SIG_ALG`, `sig_alg` standing for
+        `signature_algorithms`.
+
+  - Regarding vectors that are represented by a length followed by their value
+    in the data exchanged between servers and clients:
+
+    - Use `<vector name>_len` for the name of a variable used to compute the
+      length in bytes of the vector, where <vector name> is the name of the
+      vector as defined in the TLS 1.3 specification.
+
+    - Use `p_<vector_name>_len` for the name of a variable intended to hold
+      the address of the first byte of the vector length.
+
+    - Use `<vector_name>` for the name of a variable intended to hold the
+      address of the first byte of the vector value.
+
+    - Use `<vector_name>_end` for the name of a variable intended to hold
+      the address of the first byte past the vector value.
+
+    Those idioms should lower the risk of mis-using one of the address in place
+    of another one which could potentially lead to some nasty issues.
+
+    Example: `cipher_suites` vector of ClientHello in
+             `ssl_tls13_write_client_hello_cipher_suites()`
+    ```
+    size_t cipher_suites_len;
+    unsigned char *p_cipher_suites_len;
+    unsigned char *cipher_suites;
+    ```
+
+  - Where applicable, use:
+    - the macros to extract a byte from a multi-byte integer MBEDTLS_BYTE_{0-8}.
+    - the macros to write in memory in big-endian order a multi-byte integer
+      MBEDTLS_PUT_UINT{8|16|32|64}_BE.
+    - the macros to read from memory a multi-byte integer in big-endian order
+      MBEDTLS_GET_UINT{8|16|32|64}_BE.
+    - the macro to check for space when writing into an output buffer
+      `MBEDTLS_SSL_CHK_BUF_PTR`.
+    - the macro to check for data when reading from an input buffer
+      `MBEDTLS_SSL_CHK_BUF_READ_PTR`.
+
+    These macros were introduced after the prototype was written thus are
+    likely not to be used in prototype where we now would use them in
+    development.
+
+    The three first types, MBEDTLS_BYTE_{0-8}, MBEDTLS_PUT_UINT{8|16|32|64}_BE
+    and MBEDTLS_GET_UINT{8|16|32|64}_BE improve the readability of the code and
+    reduce the risk of writing or reading bytes in the wrong order.
+
+    The two last types, `MBEDTLS_SSL_CHK_BUF_PTR` and
+    `MBEDTLS_SSL_CHK_BUF_READ_PTR`, improve the readability of the code and
+    reduce the risk of error in the non-completely-trivial arithmetic to
+    check that we do not write or read past the end of a data buffer. The
+    usage of those macros combined with the following rule mitigate the risk
+    to read/write past the end of a data buffer.
+
+    Examples:
+    ```
+    hs_hdr[1] = MBEDTLS_BYTE_2( total_hs_len );
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, p, 0 );
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 7 );
+    ```
+
+  - To mitigate what happened here
+    (https://github.com/ARMmbed/mbedtls/pull/4882#discussion_r701704527) from
+    happening again, use always a local variable named `p` for the reading
+    pointer in functions parsing TLS 1.3 data, and for the writing pointer in
+    functions writing data into an output buffer and only that variable. The
+    name `p` has been chosen as it was already widely used in TLS code.
+
+  - When an TLS 1.3 structure is written or read by a function or as part of
+    a function, provide as documentation the definition of the structure as
+    it is in the TLS 1.3 specification.
+
+General coding rules:
+
+  - We prefer grouping "related statement lines" by not adding blank lines
+    between them.
+
+    Example 1:
+    ```
+    ret = ssl_tls13_write_client_hello_cipher_suites( ssl, buf, end, &output_len );
+    if( ret != 0 )
+        return( ret );
+    buf += output_len;
+    ```
+
+    Example 2:
+    ```
+    MBEDTLS_SSL_CHK_BUF_PTR( cipher_suites_iter, end, 2 );
+    MBEDTLS_PUT_UINT16_BE( cipher_suite, cipher_suites_iter, 0 );
+    cipher_suites_iter += 2;
+    ```
+
+  - Use macros for constants that are used in different functions, different
+    places in the code. When a constant is used only locally in a function
+    (like the length in bytes of the vector lengths in functions reading and
+    writing TLS handshake message) there is no need to define a macro for it.
+
+    Example: `#define CLIENT_HELLO_RANDOM_LEN 32`
+
+  - When declaring a pointer the dereferencing operator should be prepended to
+    the pointer name not appended to the pointer type:
+
+    Example: `mbedtls_ssl_context *ssl;`
+
+  - Maximum line length is 80 characters.
+
+    Exceptions:
+
+    - string literals can extend beyond 80 characters as we do not want to
+      split them to ease their search in the code base.
+
+    - A line can be more than 80 characters by a few characters if just looking
+      at the 80 first characters is enough to fully understand the line. For
+      example it is generally fine if some closure characters like ";" or ")"
+      are beyond the 80 characters limit.
+
+    If a line becomes too long due to a refactoring (for example renaming a
+    function to a longer name, or indenting a block more), avoid rewrapping
+    lines in the same commit: it makes the review harder. Make one commit with
+    the longer lines and another commit with just the rewrapping.
+
+  - When in successive lines, functions and macros parameters should be aligned
+    vertically.
+
+    Example:
+    ```
+    int mbedtls_ssl_tls13_start_handshake_msg( mbedtls_ssl_context *ssl,
+                                               unsigned hs_type,
+                                               unsigned char **buf,
+                                               size_t *buf_len );
+    ```
+
+  - When a function's parameters span several lines, group related parameters
+    together if possible.
+
+    For example, prefer:
+
+    ```
+    mbedtls_ssl_tls13_start_handshake_msg( ssl, hs_type,
+                                           buf, buf_len );
+    ```
+    over
+    ```
+    mbedtls_ssl_tls13_start_handshake_msg( ssl, hs_type, buf,
+                                           buf_len );
+    ```
+    even if it fits.
diff --git a/docs/use-psa-crypto.md b/docs/use-psa-crypto.md
new file mode 100644
index 0000000..6ec2dca
--- /dev/null
+++ b/docs/use-psa-crypto.md
@@ -0,0 +1,204 @@
+This document describes the compile-time configuration option
+`MBEDTLS_USE_PSA_CRYPTO` from a user's perspective, more specifically its
+current effects as well as the parts that aren't covered yet.
+
+Current effects
+===============
+
+General limitations
+-------------------
+
+Compile-time: enabling `MBEDTLS_USE_PSA_CRYPTO` requires
+`MBEDTLS_ECP_RESTARTABLE` and
+`MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER` to be disabled.
+
+Effect: `MBEDTLS_USE_PSA_CRYPTO` currently has no effect on TLS 1.3 (which is
+itself experimental and only partially supported so far): TLS 1.3 always uses
+the legacy APIs even when this option is set.
+
+Stability: any API that's only available when `MBEDTLS_USE_PSA_CRYPTO` is
+defined is considered experimental and may change in incompatible ways at any
+time. Said otherwise, these APIs are explicitly excluded from the usual API
+stability promises.
+
+New APIs / API extensions
+-------------------------
+
+Some of these APIs are meant for the application to use in place of
+pre-existing APIs, in order to get access to the benefits; in the sub-sections
+below these are indicated by "Use in (X.509 and) TLS: opt-in", meaning that
+this requires changes to the application code for the (X.509 and) TLS layers
+to pick up the improvements.
+
+Some of these APIs are mostly meant for internal use by the TLS (and X.509)
+layers; they are indicated below by "Use in (X.509 and) TLS: automatic",
+meaning that no changes to the application code are required for the TLS (and
+X.509) layers to pick up the improvements.
+
+### PSA-held (opaque) keys in the PK layer
+
+There is a new API function `mbedtls_pk_setup_opaque()` that can be used to
+wrap a PSA keypair into a PK context. The key can be used for private-key
+operations and its public part can be exported.
+
+Benefits: isolation of long-term secrets, use of PSA Crypto drivers.
+
+Limitations: only for private keys, only ECC. (That is, only ECDSA signature
+generation. Note: currently this will use randomized ECDSA while Mbed TLS uses
+deterministic ECDSA by default.) The following operations are not supported
+with a context set this way, while they would be available with a normal
+`ECKEY` context: `mbedtls_pk_verify()`, `mbedtls_pk_check_pair()`,
+`mbedtls_pk_debug()`.
+
+Use in X.509 and TLS: opt-in. The application needs to construct the PK context
+using the new API in order to get the benefits; it can then pass the
+resulting context to the following existing APIs:
+
+- `mbedtls_ssl_conf_own_cert()` or `mbedtls_ssl_set_hs_own_cert()` to use the
+  key together with a certificate for ECDSA-based key exchanges (note: while
+this is supported on both sides, it's currently only tested client-side);
+- `mbedtls_x509write_csr_set_key()` to generate a CSR (certificate signature
+  request).
+
+In the TLS and X.509 API, there are two other functions which accept a key or
+keypair as a PK context: `mbedtls_x509write_crt_set_subject_key()` and
+`mbedtls_x509write_crt_set_issuer_key()`. Use of opaque contexts here probably
+works but is so far untested.
+
+### PSA-held (opaque) keys for TLS pre-shared keys (PSK)
+
+There are two new API functions `mbedtls_ssl_conf_psk_opaque()` and
+`mbedtls_ssl_set_hs_psk_opaque()`. Call one of these from an application to
+register a PSA key for use with a PSK key exchange.
+
+Benefits: isolation of long-term secrets.
+
+Limitations: the key can only be used with "pure"
+PSK key exchanges (ciphersuites starting with `TLS_PSK_WITH_`), to the
+exclusion of RSA-PSK, DHE-PSK and ECDHE-PSK key exchanges. It is the responsibility of
+the user to make sure that when provisioning an opaque pre-shared key, the
+only PSK ciphersuites that can be negotiated are "pure" PSK; other XXX-PSK key
+exchanges will result in a handshake failure with the handshake function
+returning `MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE`.
+
+Use in TLS: opt-in. The application needs to register the key using the new
+APIs to get the benefits.
+
+### PSA-based operations in the Cipher layer
+
+There is a new API function `mbedtls_cipher_setup_psa()` to set up a context
+that will call PSA to store the key and perform the operations.
+
+Benefits: use of PSA Crypto drivers; partial isolation of short-term secrets
+(still generated outside of PSA, but then held by PSA).
+
+Limitations: the key is still passed in the clear by the application. The
+multi-part APIs are not supported, only the one-shot APIs. The only modes
+supported are ECB, CBC without padding, GCM and CCM (this excludes stream
+ciphers and ChachaPoly); the only cipher supported is AES (this excludes Aria,
+Camellia, and ChachaPoly). (Note: ECB is currently not tested.) (Note: it is
+possible to perform multiple one-shot operations with the same context;
+however this is not unit-tested, only tested via usage in TLS.)
+
+Use in TLS: automatic. Used when the cipher and mode is supported (with
+gracious fallback to the legacy API otherwise) in all places where a cipher is
+used. There are two such places: in `ssl_tls.c` for record protection, and in
+`ssl_ticket.c` for protecting tickets we issue.
+
+Internal changes
+----------------
+
+All of these internal changes are active as soon as `MBEDTLS_USE_PSA_CRYPTO`
+is enabled, no change required on the application side.
+
+### TLS: cipher operations based on PSA
+
+See "PSA-based operations in the Cipher layer" above.
+
+### PK layer: ECDSA verification based on PSA
+
+Scope: `mbedtls_pk_verify()` will call to PSA for ECDSA signature
+verification.
+
+Benefits: use of PSA Crypto drivers.
+
+Use in TLS and X.509: in all places where an ECDSA signature is verified.
+
+### TLS: ECDHE computation based on PSA
+
+Scope: Client-side, for ECDHE-RSA and ECDHE-ECDSA key exchanges, the
+computation of the ECDHE key exchange is done by PSA.
+
+Limitations: client-side only, ECDHE-PSK not covered
+
+Benefits: use of PSA Crypto drivers.
+
+### TLS: handshake hashes and PRF computed with PSA
+
+Scope: with TLS 1.2, the following are computed with PSA:
+- the running handshake hashes;
+- the hash of the ServerKeyExchange part that is signed;
+- the `verify_data` part of the Finished message;
+- the TLS PRF.
+
+Benefits: use of PSA Crypto drivers.
+
+### X.509: some hashes computed with PSA
+
+Scope: the following hashes are computed with PSA:
+- when verifying a certificate chain, hash of the child for verifying the
+  parent's signature;
+- when writing a CSR, hash of the request for self-signing the request.
+
+Benefits: use of PSA Crypto drivers.
+
+Parts that are not covered yet
+==============================
+
+This is only a high-level overview, grouped by theme
+
+TLS: 1.3 experimental support
+-----------------------------
+
+No part of the experimental support for TLS 1.3 is covered at the moment.
+
+TLS: key exchanges / asymmetric crypto
+--------------------------------------
+
+The following key exchanges are not covered at all:
+
+- RSA
+- DHE-RSA
+- DHE-PSK
+- RSA-PSK
+- ECDHE-PSK
+- ECDH-RSA
+- ECDH-ECDSA
+- ECJPAKE
+
+The following key exchanges are only partially covered:
+
+- ECDHE-RSA: RSA operations are not covered and, server-side, the ECDHE
+  operation isn't either
+- ECDHE-ECDSA: server-side, the ECDHE operation isn't covered. (ECDSA
+  signature generation is only covered if using `mbedtls_pk_setup_opaque()`.)
+
+PSK if covered when the application uses `mbedtls_ssl_conf_psk_opaque()` or
+`mbedtls_ssl_set_hs_psk_opaque()`.
+
+TLS: symmetric crypto
+---------------------
+
+- some ciphers not supported via PSA yet: ARIA, Camellia, ChachaPoly (silent
+  fallback to the legacy APIs)
+- the HMAC part of the CBC and NULL ciphersuites
+- the HMAC computation in `ssl_cookie.c`
+
+X.509
+-----
+
+- most hash operations are still done via the legacy API, except the few that
+  are documented above as using PSA
+- RSA PKCS#1 v1.5 signature generation (from PSA-held keys)
+- RSA PKCS#1 v1.5 signature verification
+- RSA-PSS signature verification
diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h
index 879c3f2..becbfae 100644
--- a/include/mbedtls/aes.h
+++ b/include/mbedtls/aes.h
@@ -42,6 +42,7 @@
 #include "mbedtls/private_access.h"
 
 #include "mbedtls/build_info.h"
+#include "mbedtls/platform_util.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -163,6 +164,7 @@
  * \return         \c 0 on success.
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
                     unsigned int keybits );
 
@@ -181,6 +183,7 @@
  * \return         \c 0 on success.
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
                     unsigned int keybits );
 
@@ -201,6 +204,7 @@
  * \return         \c 0 on success.
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
                                 const unsigned char *key,
                                 unsigned int keybits );
@@ -221,6 +225,7 @@
  * \return         \c 0 on success.
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
                                 const unsigned char *key,
                                 unsigned int keybits );
@@ -249,6 +254,7 @@
 
  * \return         \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
                     int mode,
                     const unsigned char input[16],
@@ -296,6 +302,7 @@
  * \return         #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
  *                 on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
                     int mode,
                     size_t length,
@@ -340,6 +347,7 @@
  *                     smaller than an AES block in size (16 Bytes) or if \p
  *                     length is larger than 2^20 blocks (16 MiB).
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
                            int mode,
                            size_t length,
@@ -388,6 +396,7 @@
  *
  * \return         \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
                        int mode,
                        size_t length,
@@ -432,6 +441,7 @@
  *
  * \return         \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
                     int mode,
                     size_t length,
@@ -486,6 +496,7 @@
  *
  * \return         \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
                        size_t length,
                        size_t *iv_off,
@@ -572,6 +583,7 @@
  *
  * \return                 \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
                        size_t length,
                        size_t *nc_off,
@@ -592,6 +604,7 @@
  *
  * \return          \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
                                   const unsigned char input[16],
                                   unsigned char output[16] );
@@ -607,6 +620,7 @@
  *
  * \return          \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
                                   const unsigned char input[16],
                                   unsigned char output[16] );
@@ -618,6 +632,7 @@
  * \return         \c 0 on success.
  * \return         \c 1 on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_aes_self_test( int verbose );
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/include/mbedtls/asn1.h b/include/mbedtls/asn1.h
index f45fc17..4746c1c 100644
--- a/include/mbedtls/asn1.h
+++ b/include/mbedtls/asn1.h
@@ -152,9 +152,9 @@
  */
 typedef struct mbedtls_asn1_buf
 {
-    int MBEDTLS_PRIVATE(tag);                /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */
-    size_t MBEDTLS_PRIVATE(len);             /**< ASN1 length, in octets. */
-    unsigned char *MBEDTLS_PRIVATE(p);       /**< ASN1 data, e.g. in ASCII. */
+    int tag;                /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */
+    size_t len;             /**< ASN1 length, in octets. */
+    unsigned char *p;       /**< ASN1 data, e.g. in ASCII. */
 }
 mbedtls_asn1_buf;
 
@@ -163,9 +163,9 @@
  */
 typedef struct mbedtls_asn1_bitstring
 {
-    size_t MBEDTLS_PRIVATE(len);                 /**< ASN1 length, in octets. */
-    unsigned char MBEDTLS_PRIVATE(unused_bits);  /**< Number of unused bits at the end of the string */
-    unsigned char *MBEDTLS_PRIVATE(p);           /**< Raw ASN1 data for the bit string */
+    size_t len;                 /**< ASN1 length, in octets. */
+    unsigned char unused_bits;  /**< Number of unused bits at the end of the string */
+    unsigned char *p;           /**< Raw ASN1 data for the bit string */
 }
 mbedtls_asn1_bitstring;
 
@@ -174,8 +174,16 @@
  */
 typedef struct mbedtls_asn1_sequence
 {
-    mbedtls_asn1_buf MBEDTLS_PRIVATE(buf);                   /**< Buffer containing the given ASN.1 item. */
-    struct mbedtls_asn1_sequence *MBEDTLS_PRIVATE(next);    /**< The next entry in the sequence. */
+    mbedtls_asn1_buf buf;                   /**< Buffer containing the given ASN.1 item. */
+
+    /** The next entry in the sequence.
+     *
+     * The details of memory management for sequences are not documented and
+     * may change in future versions. Set this field to \p NULL when
+     * initializing a structure, and do not modify it except via Mbed TLS
+     * library functions.
+     */
+    struct mbedtls_asn1_sequence *next;
 }
 mbedtls_asn1_sequence;
 
@@ -184,10 +192,24 @@
  */
 typedef struct mbedtls_asn1_named_data
 {
-    mbedtls_asn1_buf MBEDTLS_PRIVATE(oid);                   /**< The object identifier. */
-    mbedtls_asn1_buf MBEDTLS_PRIVATE(val);                   /**< The named value. */
-    struct mbedtls_asn1_named_data *MBEDTLS_PRIVATE(next);  /**< The next entry in the sequence. */
-    unsigned char MBEDTLS_PRIVATE(next_merged);      /**< Merge next item into the current one? */
+    mbedtls_asn1_buf oid;                   /**< The object identifier. */
+    mbedtls_asn1_buf val;                   /**< The named value. */
+
+    /** The next entry in the sequence.
+     *
+     * The details of memory management for named data sequences are not
+     * documented and may change in future versions. Set this field to \p NULL
+     * when initializing a structure, and do not modify it except via Mbed TLS
+     * library functions.
+     */
+    struct mbedtls_asn1_named_data *next;
+
+    /** Merge next item into the current one?
+     *
+     * This field exists for the sake of Mbed TLS's X.509 certificate parsing
+     * code and may change in future versions of the library.
+     */
+    unsigned char MBEDTLS_PRIVATE(next_merged);
 }
 mbedtls_asn1_named_data;
 
diff --git a/include/mbedtls/ccm.h b/include/mbedtls/ccm.h
index b3adecc..6f991fe 100644
--- a/include/mbedtls/ccm.h
+++ b/include/mbedtls/ccm.h
@@ -76,7 +76,27 @@
  */
 typedef struct mbedtls_ccm_context
 {
+    unsigned char MBEDTLS_PRIVATE(y)[16];    /*!< The Y working buffer */
+    unsigned char MBEDTLS_PRIVATE(ctr)[16];  /*!< The counter buffer */
     mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx);    /*!< The cipher context used. */
+    size_t MBEDTLS_PRIVATE(plaintext_len);   /*!< Total plaintext length */
+    size_t MBEDTLS_PRIVATE(add_len);         /*!< Total authentication data length */
+    size_t MBEDTLS_PRIVATE(tag_len);         /*!< Total tag length */
+    size_t MBEDTLS_PRIVATE(processed);       /*!< Track how many bytes of input data
+                                                  were processed (chunked input).
+                                                  Used independently for both auth data
+                                                  and plaintext/ciphertext.
+                                                  This variable is set to zero after
+                                                  auth data input is finished. */
+    unsigned char MBEDTLS_PRIVATE(q);        /*!< The Q working value */
+    unsigned char MBEDTLS_PRIVATE(mode);     /*!< The operation to perform:
+                                                  #MBEDTLS_CCM_ENCRYPT or
+                                                  #MBEDTLS_CCM_DECRYPT or
+                                                  #MBEDTLS_CCM_STAR_ENCRYPT or
+                                                  #MBEDTLS_CCM_STAR_DECRYPT. */
+    int MBEDTLS_PRIVATE(state);              /*!< Working value holding context's
+                                                  state. Used for chunked data
+                                                  input */
 }
 mbedtls_ccm_context;
 
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index 9c9a2e8..b4630f6 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -258,6 +258,13 @@
 /**
  * Cipher information. Allows calling cipher functions
  * in a generic way.
+ *
+ * \note        The library does not support custom cipher info structures,
+ *              only built-in structures returned by the functions
+ *              mbedtls_cipher_info_from_string(),
+ *              mbedtls_cipher_info_from_type(),
+ *              mbedtls_cipher_info_from_values(),
+ *              mbedtls_cipher_info_from_psa().
  */
 typedef struct mbedtls_cipher_info_t
 {
@@ -415,6 +422,82 @@
                                               const mbedtls_cipher_mode_t mode );
 
 /**
+ * \brief               Retrieve the identifier for a cipher info structure.
+ *
+ * \param[in] info      The cipher info structure to query.
+ *                      This may be \c NULL.
+ *
+ * \return              The full cipher identifier (\c MBEDTLS_CIPHER_xxx).
+ * \return              #MBEDTLS_CIPHER_NONE if \p info is \c NULL.
+ */
+static inline mbedtls_cipher_type_t mbedtls_cipher_info_get_type(
+    const mbedtls_cipher_info_t *info )
+{
+    if( info == NULL )
+        return( MBEDTLS_CIPHER_NONE );
+    else
+        return( info->MBEDTLS_PRIVATE(type) );
+}
+
+/**
+ * \brief               Retrieve the operation mode for a cipher info structure.
+ *
+ * \param[in] info      The cipher info structure to query.
+ *                      This may be \c NULL.
+ *
+ * \return              The cipher mode (\c MBEDTLS_MODE_xxx).
+ * \return              #MBEDTLS_MODE_NONE if \p info is \c NULL.
+ */
+static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode(
+    const mbedtls_cipher_info_t *info )
+{
+    if( info == NULL )
+        return( MBEDTLS_MODE_NONE );
+    else
+        return( info->MBEDTLS_PRIVATE(mode) );
+}
+
+/**
+ * \brief               Retrieve the key size for a cipher info structure.
+ *
+ * \param[in] info      The cipher info structure to query.
+ *                      This may be \c NULL.
+ *
+ * \return              The key length in bits.
+ *                      For variable-sized ciphers, this is the default length.
+ *                      For DES, this includes the parity bits.
+ * \return              \c 0 if \p info is \c NULL.
+ */
+static inline size_t mbedtls_cipher_info_get_key_bitlen(
+    const mbedtls_cipher_info_t *info )
+{
+    if( info == NULL )
+        return( 0 );
+    else
+        return( info->MBEDTLS_PRIVATE(key_bitlen) );
+}
+
+/**
+ * \brief               Retrieve the human-readable name for a
+ *                      cipher info structure.
+ *
+ * \param[in] info      The cipher info structure to query.
+ *                      This may be \c NULL.
+ *
+ * \return              The cipher name, which is a human readable string,
+ *                      with static storage duration.
+ * \return              \c NULL if \c info is \p NULL.
+ */
+static inline const char *mbedtls_cipher_info_get_name(
+    const mbedtls_cipher_info_t *info )
+{
+    if( info == NULL )
+        return( NULL );
+    else
+        return( info->MBEDTLS_PRIVATE(name) );
+}
+
+/**
  * \brief               This function initializes a \p cipher_context as NONE.
  *
  * \param ctx           The context to be initialized. This must not be \c NULL.
diff --git a/include/mbedtls/config_psa.h b/include/mbedtls/config_psa.h
index 87997c3..4a53154 100644
--- a/include/mbedtls/config_psa.h
+++ b/include/mbedtls/config_psa.h
@@ -601,7 +601,7 @@
 #define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1
 #define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1
 #define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW 1
-#endif /* MBEDTLSS_PKCS1_V15 */
+#endif /* MBEDTLS_PKCS1_V15 */
 #if defined(MBEDTLS_PKCS1_V21)
 #define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1
 #define PSA_WANT_ALG_RSA_OAEP 1
diff --git a/include/mbedtls/des.h b/include/mbedtls/des.h
index 63a8e00..be74cb1 100644
--- a/include/mbedtls/des.h
+++ b/include/mbedtls/des.h
@@ -29,6 +29,7 @@
 #include "mbedtls/private_access.h"
 
 #include "mbedtls/build_info.h"
+#include "mbedtls/platform_util.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -139,6 +140,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
 
 /**
@@ -152,6 +154,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
 
 /**
@@ -166,6 +169,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
 
 /**
@@ -180,6 +184,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
 
 /**
@@ -190,6 +195,7 @@
  *
  * \return         0
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
                       const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
 
@@ -201,6 +207,7 @@
  *
  * \return         0
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
                       const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
 
@@ -212,6 +219,7 @@
  *
  * \return         0
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
                       const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
 
@@ -223,6 +231,7 @@
  *
  * \return         0
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
                       const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
 
@@ -239,6 +248,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
                     const unsigned char input[8],
                     unsigned char output[8] );
@@ -266,6 +276,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
                     int mode,
                     size_t length,
@@ -283,6 +294,7 @@
  *
  * \return         0 if successful
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
                      const unsigned char input[8],
                      unsigned char output[8] );
@@ -308,6 +320,7 @@
  *
  * \return         0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
                      int mode,
                      size_t length,
@@ -338,6 +351,7 @@
  *
  * \return         0 if successful, or 1 if the test failed
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_des_self_test( int verbose );
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h
index 384d060..b2a2e32 100644
--- a/include/mbedtls/ecp.h
+++ b/include/mbedtls/ecp.h
@@ -147,13 +147,17 @@
 
 /**
  * Curve information, for use by other modules.
+ *
+ * The fields of this structure are part of the public API and can be
+ * accessed directly by applications. Future versions of the library may
+ * add extra fields or reorder existing fields.
  */
 typedef struct mbedtls_ecp_curve_info
 {
-    mbedtls_ecp_group_id MBEDTLS_PRIVATE(grp_id);    /*!< An internal identifier. */
-    uint16_t MBEDTLS_PRIVATE(tls_id);                /*!< The TLS NamedCurve identifier. */
-    uint16_t MBEDTLS_PRIVATE(bit_size);              /*!< The curve size in bits. */
-    const char *MBEDTLS_PRIVATE(name);               /*!< A human-friendly name. */
+    mbedtls_ecp_group_id grp_id;    /*!< An internal identifier. */
+    uint16_t tls_id;                /*!< The TLS NamedCurve identifier. */
+    uint16_t bit_size;              /*!< The curve size in bits. */
+    const char *name;               /*!< A human-friendly name. */
 } mbedtls_ecp_curve_info;
 
 /**
diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h
index 27420ce..8b2b9ea 100644
--- a/include/mbedtls/error.h
+++ b/include/mbedtls/error.h
@@ -56,7 +56,7 @@
  * Module   Nr  Codes assigned
  * ERROR     2  0x006E          0x0001
  * MPI       7  0x0002-0x0010
- * GCM       3  0x0012-0x0014   0x0013-0x0013
+ * GCM       3  0x0012-0x0016   0x0013-0x0013
  * THREADING 3  0x001A-0x001E
  * AES       5  0x0020-0x0022   0x0021-0x0025
  * CAMELLIA  3  0x0024-0x0026   0x0027-0x0027
diff --git a/include/mbedtls/gcm.h b/include/mbedtls/gcm.h
index 9d9155f..7dc9dfb 100644
--- a/include/mbedtls/gcm.h
+++ b/include/mbedtls/gcm.h
@@ -45,6 +45,8 @@
 #define MBEDTLS_ERR_GCM_AUTH_FAILED                       -0x0012
 /** Bad input parameters to function. */
 #define MBEDTLS_ERR_GCM_BAD_INPUT                         -0x0014
+/** An output buffer is too small. */
+#define MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL                  -0x0016
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index d470c00..c2f4587 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -521,6 +521,29 @@
 //#define MBEDTLS_CAMELLIA_SMALL_MEMORY
 
 /**
+ * \def MBEDTLS_CHECK_RETURN_WARNING
+ *
+ * If this macro is defined, emit a compile-time warning if application code
+ * calls a function without checking its return value, but the return value
+ * should generally be checked in portable applications.
+ *
+ * This is only supported on platforms where #MBEDTLS_CHECK_RETURN is
+ * implemented. Otherwise this option has no effect.
+ *
+ * Uncomment to get warnings on using fallible functions without checking
+ * their return value.
+ *
+ * \note  This feature is a work in progress.
+ *        Warnings will be added to more functions in the future.
+ *
+ * \note  A few functions are considered critical, and ignoring the return
+ *        value of these functions will trigger a warning even if this
+ *        macro is not defined. To completely disable return value check
+ *        warnings, define #MBEDTLS_CHECK_RETURN with an empty expansion.
+ */
+//#define MBEDTLS_CHECK_RETURN_WARNING
+
+/**
  * \def MBEDTLS_CIPHER_MODE_CBC
  *
  * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
@@ -1599,16 +1622,6 @@
 #define MBEDTLS_SSL_SESSION_TICKETS
 
 /**
- * \def MBEDTLS_SSL_EXPORT_KEYS
- *
- * Enable support for exporting key block and master secret.
- * This is required for certain users of TLS, e.g. EAP-TLS.
- *
- * Comment this macro to disable support for key export
- */
-#define MBEDTLS_SSL_EXPORT_KEYS
-
-/**
  * \def MBEDTLS_SSL_SERVER_NAME_INDICATION
  *
  * Enable support for RFC 6066 server name indication (SNI) in SSL.
@@ -1718,15 +1731,13 @@
  * will still continue to work as usual, so enabling this option should not
  * break backwards compatibility.
  *
- * \warning The PSA Crypto API is in beta stage. While you're welcome to
- * experiment using it, incompatible API changes are still possible, and some
- * parts may not have reached the same quality as the rest of Mbed TLS yet.
+ * \note See docs/use-psa-crypto.md for a complete description of what this
+ * option currently does, and of parts that are not affected by it so far.
  *
- * \warning This option enables new Mbed TLS APIs that are dependent on the
- * PSA Crypto API, so can't come with the same stability guarantees as the
- * rest of the Mbed TLS APIs. You're welcome to experiment with them, but for
- * now, access to these APIs is opt-in (via enabling the present option), in
- * order to clearly differentiate them from the stable Mbed TLS APIs.
+ * \warning This option enables new Mbed TLS APIs which are currently
+ * considered experimental and may change in incompatible ways at any time.
+ * That is, the APIs enabled by this option are not covered by the usual
+ * promises of API stability.
  *
  * Requires: MBEDTLS_PSA_CRYPTO_C.
  *
@@ -2592,10 +2603,6 @@
  *
  * Enable the Platform Security Architecture cryptography API.
  *
- * \warning The PSA Crypto API is still beta status. While you're welcome to
- * experiment using it, incompatible API changes are still possible, and some
- * parts may not have reached the same quality as the rest of Mbed TLS yet.
- *
  * Module:  library/psa_crypto.c
  *
  * Requires: either MBEDTLS_CTR_DRBG_C and MBEDTLS_ENTROPY_C,
@@ -3073,6 +3080,29 @@
 //#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO   mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
 //#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO  mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
 
+/** \def MBEDTLS_CHECK_RETURN
+ *
+ * This macro is used at the beginning of the declaration of a function
+ * to indicate that its return value should be checked. It should
+ * instruct the compiler to emit a warning or an error if the function
+ * is called without checking its return value.
+ *
+ * There is a default implementation for popular compilers in platform_util.h.
+ * You can override the default implementation by defining your own here.
+ *
+ * If the implementation here is empty, this will effectively disable the
+ * checking of functions' return values.
+ */
+//#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__))
+
+/** \def MBEDTLS_IGNORE_RETURN
+ *
+ * This macro requires one argument, which should be a C function call.
+ * If that function call would cause a #MBEDTLS_CHECK_RETURN warning, this
+ * warning is suppressed.
+ */
+//#define MBEDTLS_IGNORE_RETURN( result ) ((void) !(result))
+
 /* PSA options */
 /**
  * Use HMAC_DRBG with the specified hash algorithm for HMAC_DRBG for the
@@ -3179,7 +3209,7 @@
  * Maximum number of heap-allocated bytes for the purpose of
  * DTLS handshake message reassembly and future message buffering.
  *
- * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN
+ * This should be at least 9/8 * MBEDTLS_SSL_IN_CONTENT_LEN
  * to account for a reassembled handshake message of maximum size,
  * together with its reassembly bitmap.
  *
diff --git a/include/mbedtls/net_sockets.h b/include/mbedtls/net_sockets.h
index c8214a2..0c754b1 100644
--- a/include/mbedtls/net_sockets.h
+++ b/include/mbedtls/net_sockets.h
@@ -94,7 +94,13 @@
  */
 typedef struct mbedtls_net_context
 {
-    int MBEDTLS_PRIVATE(fd);             /**< The underlying file descriptor                 */
+    /** The underlying file descriptor.
+     *
+     * This field is only guaranteed to be present on POSIX/Unix-like platforms.
+     * On other platforms, it may have a different type, have a different
+     * meaning, or be absent altogether.
+     */
+    int fd;
 }
 mbedtls_net_context;
 
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index ded5222..5f9f29f 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -186,6 +186,10 @@
 
 /**
  * \brief           Public key information and operations
+ *
+ * \note        The library does not support custom pk info structures,
+ *              only built-in structures returned by
+ *              mbedtls_cipher_info_from_type().
  */
 typedef struct mbedtls_pk_info_t mbedtls_pk_info_t;
 
diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h
index 1a0a135..36e3718 100644
--- a/include/mbedtls/platform_util.h
+++ b/include/mbedtls/platform_util.h
@@ -60,6 +60,95 @@
 #endif /* MBEDTLS_DEPRECATED_WARNING */
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
 
+/* Implementation of the check-return facility.
+ * See the user documentation in mbedtls_config.h.
+ *
+ * Do not use this macro directly to annotate function: instead,
+ * use one of MBEDTLS_CHECK_RETURN_CRITICAL or MBEDTLS_CHECK_RETURN_TYPICAL
+ * depending on how important it is to check the return value.
+ */
+#if !defined(MBEDTLS_CHECK_RETURN)
+#if defined(__GNUC__)
+#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__))
+#elif defined(_MSC_VER) && _MSC_VER >= 1700
+#include <sal.h>
+#define MBEDTLS_CHECK_RETURN _Check_return_
+#else
+#define MBEDTLS_CHECK_RETURN
+#endif
+#endif
+
+/** Critical-failure function
+ *
+ * This macro appearing at the beginning of the declaration of a function
+ * indicates that its return value should be checked in all applications.
+ * Omitting the check is very likely to indicate a bug in the application
+ * and will result in a compile-time warning if #MBEDTLS_CHECK_RETURN
+ * is implemented for the compiler in use.
+ *
+ * \note  The use of this macro is a work in progress.
+ *        This macro may be added to more functions in the future.
+ *        Such an extension is not considered an API break, provided that
+ *        there are near-unavoidable circumstances under which the function
+ *        can fail. For example, signature/MAC/AEAD verification functions,
+ *        and functions that require a random generator, are considered
+ *        return-check-critical.
+ */
+#define MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_CHECK_RETURN
+
+/** Ordinary-failure function
+ *
+ * This macro appearing at the beginning of the declaration of a function
+ * indicates that its return value should be generally be checked in portable
+ * applications. Omitting the check will result in a compile-time warning if
+ * #MBEDTLS_CHECK_RETURN is implemented for the compiler in use and
+ * #MBEDTLS_CHECK_RETURN_WARNING is enabled in the compile-time configuration.
+ *
+ * You can use #MBEDTLS_IGNORE_RETURN to explicitly ignore the return value
+ * of a function that is annotated with #MBEDTLS_CHECK_RETURN.
+ *
+ * \note  The use of this macro is a work in progress.
+ *        This macro will be added to more functions in the future.
+ *        Eventually this should appear before most functions returning
+ *        an error code (as \c int in the \c mbedtls_xxx API or
+ *        as ::psa_status_t in the \c psa_xxx API).
+ */
+#if defined(MBEDTLS_CHECK_RETURN_WARNING)
+#define MBEDTLS_CHECK_RETURN_TYPICAL MBEDTLS_CHECK_RETURN
+#else
+#define MBEDTLS_CHECK_RETURN_TYPICAL
+#endif
+
+/** Benign-failure function
+ *
+ * This macro appearing at the beginning of the declaration of a function
+ * indicates that it is rarely useful to check its return value.
+ *
+ * This macro has an empty expansion. It exists for documentation purposes:
+ * a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function
+ * has been analyzed for return-check usefuless, whereas the lack of
+ * an annotation indicates that the function has not been analyzed and its
+ * return-check usefulness is unknown.
+ */
+#define MBEDTLS_CHECK_RETURN_OPTIONAL
+
+/** \def MBEDTLS_IGNORE_RETURN
+ *
+ * Call this macro with one argument, a function call, to suppress a warning
+ * from #MBEDTLS_CHECK_RETURN due to that function call.
+ */
+#if !defined(MBEDTLS_IGNORE_RETURN)
+/* GCC doesn't silence the warning with just (void)(result).
+ * (void)!(result) is known to work up at least up to GCC 10, as well
+ * as with Clang and MSVC.
+ *
+ * https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Non_002dbugs.html
+ * https://stackoverflow.com/questions/40576003/ignoring-warning-wunused-result
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425#c34
+ */
+#define MBEDTLS_IGNORE_RETURN(result) ( (void) !( result ) )
+#endif
+
 /**
  * \brief       Securely zeroize a buffer
  *
diff --git a/include/mbedtls/psa_util.h b/include/mbedtls/psa_util.h
index f6f2e58..80bcd72 100644
--- a/include/mbedtls/psa_util.h
+++ b/include/mbedtls/psa_util.h
@@ -57,6 +57,9 @@
         case MBEDTLS_CIPHER_AES_128_CBC:
         case MBEDTLS_CIPHER_AES_192_CBC:
         case MBEDTLS_CIPHER_AES_256_CBC:
+        case MBEDTLS_CIPHER_AES_128_ECB:
+        case MBEDTLS_CIPHER_AES_192_ECB:
+        case MBEDTLS_CIPHER_AES_256_ECB:
             return( PSA_KEY_TYPE_AES );
 
         /* ARIA not yet supported in PSA. */
@@ -369,7 +372,7 @@
     if( curve_info == NULL )
         return( 0 );
     return( PSA_KEY_TYPE_ECC_KEY_PAIR(
-                mbedtls_ecc_group_to_psa( curve_info->MBEDTLS_PRIVATE(grp_id), bits ) ) );
+                mbedtls_ecc_group_to_psa( curve_info->grp_id, bits ) ) );
 }
 #endif /* MBEDTLS_ECP_C */
 
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index f533859..288d9b3 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -170,6 +170,37 @@
 #define MBEDTLS_ERR_SSL_BAD_CONFIG                        -0x5E80
 
 /*
+ * TLS 1.3 NamedGroup values
+ *
+ * From RF 8446
+ *    enum {
+ *         // Elliptic Curve Groups (ECDHE)
+ *         secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
+ *         x25519(0x001D), x448(0x001E),
+ *         // Finite Field Groups (DHE)
+ *         ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
+ *         ffdhe6144(0x0103), ffdhe8192(0x0104),
+ *         // Reserved Code Points
+ *         ffdhe_private_use(0x01FC..0x01FF),
+ *         ecdhe_private_use(0xFE00..0xFEFF),
+ *         (0xFFFF)
+ *     } NamedGroup;
+ *
+ */
+/* Elliptic Curve Groups (ECDHE) */
+#define MBEDTLS_SSL_TLS13_NAMED_GROUP_SECP256R1     0x0017
+#define MBEDTLS_SSL_TLS13_NAMED_GROUP_SECP384R1     0x0018
+#define MBEDTLS_SSL_TLS13_NAMED_GROUP_SECP521R1     0x0019
+#define MBEDTLS_SSL_TLS13_NAMED_GROUP_X25519        0x001D
+#define MBEDTLS_SSL_TLS13_NAMED_GROUP_X448          0x001E
+/* Finite Field Groups (DHE) */
+#define MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE2048     0x0100
+#define MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE3072     0x0101
+#define MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE4096     0x0102
+#define MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE6144     0x0103
+#define MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE8192     0x0104
+
+/*
  * TLS 1.3 Key Exchange Modes
  *
  * Mbed TLS internal identifiers for use with the SSL configuration API
@@ -455,6 +486,7 @@
 #define MBEDTLS_SSL_HS_SERVER_HELLO             2
 #define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST     3
 #define MBEDTLS_SSL_HS_NEW_SESSION_TICKET       4
+#define MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS     8 // NEW IN TLS 1.3
 #define MBEDTLS_SSL_HS_CERTIFICATE             11
 #define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE     12
 #define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST     13
@@ -562,6 +594,9 @@
 
 #define MBEDTLS_PREMASTER_SIZE     sizeof( union mbedtls_ssl_premaster_secret )
 
+/* Length in number of bytes of the TLS sequence number */
+#define MBEDTLS_SSL_SEQUENCE_NUMBER_LEN 8
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -592,6 +627,7 @@
     MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT,
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
     MBEDTLS_SSL_ENCRYPTED_EXTENSIONS,
+    MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY,
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
 }
 mbedtls_ssl_states;
@@ -1108,7 +1144,6 @@
 }
 mbedtls_tls_prf_types;
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 typedef enum
 {
     MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET = 0,
@@ -1144,7 +1179,6 @@
                                         const unsigned char client_random[32],
                                         const unsigned char server_random[32],
                                         mbedtls_tls_prf_types tls_prf_type );
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 /**
  * SSL/TLS configuration to be shared between mbedtls_ssl_context structures.
@@ -1495,6 +1529,19 @@
     int MBEDTLS_PRIVATE(keep_current_message);   /*!< drop or reuse current message
                                      on next call to record layer? */
 
+    /* The following three variables indicate if and, if yes,
+     * what kind of alert is pending to be sent.
+     */
+    unsigned char MBEDTLS_PRIVATE(send_alert);   /*!< Determines if a fatal alert
+                                                should be sent. Values:
+                                                - \c 0 , no alert is to be sent.
+                                                - \c 1 , alert is to be sent. */
+    unsigned char MBEDTLS_PRIVATE(alert_type);   /*!< Type of alert if send_alert
+                                                 != 0 */
+    int MBEDTLS_PRIVATE(alert_reason);           /*!< The error code to be returned
+                                                 to the user once the fatal alert
+                                                 has been sent. */
+
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     uint8_t MBEDTLS_PRIVATE(disable_datagram_packing);  /*!< Disable packing multiple records
                                         *   within a single datagram.  */
@@ -1521,7 +1568,7 @@
     size_t MBEDTLS_PRIVATE(out_buf_len);         /*!< length of output buffer          */
 #endif
 
-    unsigned char MBEDTLS_PRIVATE(cur_out_ctr)[8]; /*!<  Outgoing record sequence  number. */
+    unsigned char MBEDTLS_PRIVATE(cur_out_ctr)[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!<  Outgoing record sequence  number. */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     uint16_t MBEDTLS_PRIVATE(mtu);               /*!< path mtu, used to fragment outgoing messages */
@@ -1586,11 +1633,9 @@
                             *   and #MBEDTLS_SSL_CID_DISABLED. */
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     /** Callback to export key block and master secret                      */
     mbedtls_ssl_export_keys_t *MBEDTLS_PRIVATE(f_export_keys);
     void *MBEDTLS_PRIVATE(p_export_keys);            /*!< context for key export callback    */
-#endif
 };
 
 /**
@@ -2163,7 +2208,6 @@
         void *p_ticket );
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 /**
  * \brief   Configure a key export callback.
  *          (Default: none.)
@@ -2185,7 +2229,6 @@
 void mbedtls_ssl_set_export_keys_cb( mbedtls_ssl_context *ssl,
                                      mbedtls_ssl_export_keys_t *f_export_keys,
                                      void *p_export_keys );
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
 /**
diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h
index df187cb..9a4be95 100644
--- a/include/mbedtls/x509.h
+++ b/include/mbedtls/x509.h
@@ -246,8 +246,8 @@
 /** Container for date and time (precision in seconds). */
 typedef struct mbedtls_x509_time
 {
-    int MBEDTLS_PRIVATE(year), MBEDTLS_PRIVATE(mon), MBEDTLS_PRIVATE(day);         /**< Date. */
-    int MBEDTLS_PRIVATE(hour), MBEDTLS_PRIVATE(min), MBEDTLS_PRIVATE(sec);         /**< Time. */
+    int year, mon, day;         /**< Date. */
+    int hour, min, sec;         /**< Time. */
 }
 mbedtls_x509_time;
 
diff --git a/include/mbedtls/x509_crl.h b/include/mbedtls/x509_crl.h
index 9331827..52bd43c 100644
--- a/include/mbedtls/x509_crl.h
+++ b/include/mbedtls/x509_crl.h
@@ -43,18 +43,30 @@
 /**
  * Certificate revocation list entry.
  * Contains the CA-specific serial numbers and revocation dates.
+ *
+ * Some fields of this structure are publicly readable. Do not modify
+ * them except via Mbed TLS library functions: the effect of modifying
+ * those fields or the data that those fields points to is unspecified.
  */
 typedef struct mbedtls_x509_crl_entry
 {
-    mbedtls_x509_buf MBEDTLS_PRIVATE(raw);
+    /** Direct access to the whole entry inside the containing buffer. */
+    mbedtls_x509_buf raw;
+    /** The serial number of the revoked certificate. */
+    mbedtls_x509_buf serial;
+    /** The revocation date of this entry. */
+    mbedtls_x509_time revocation_date;
+    /** Direct access to the list of CRL entry extensions
+     * (an ASN.1 constructed sequence).
+     *
+     * If there are no extensions, `entry_ext.len == 0` and
+     * `entry_ext.p == NULL`. */
+    mbedtls_x509_buf entry_ext;
 
-    mbedtls_x509_buf MBEDTLS_PRIVATE(serial);
-
-    mbedtls_x509_time MBEDTLS_PRIVATE(revocation_date);
-
-    mbedtls_x509_buf MBEDTLS_PRIVATE(entry_ext);
-
-    struct mbedtls_x509_crl_entry *MBEDTLS_PRIVATE(next);
+    /** Next element in the linked list of entries.
+     * \p NULL indicates the end of the list.
+     * Do not modify this field directly. */
+    struct mbedtls_x509_crl_entry *next;
 }
 mbedtls_x509_crl_entry;
 
@@ -64,22 +76,22 @@
  */
 typedef struct mbedtls_x509_crl
 {
-    mbedtls_x509_buf MBEDTLS_PRIVATE(raw);           /**< The raw certificate data (DER). */
-    mbedtls_x509_buf MBEDTLS_PRIVATE(tbs);           /**< The raw certificate body (DER). The part that is To Be Signed. */
+    mbedtls_x509_buf raw;           /**< The raw certificate data (DER). */
+    mbedtls_x509_buf tbs;           /**< The raw certificate body (DER). The part that is To Be Signed. */
 
-    int MBEDTLS_PRIVATE(version);            /**< CRL version (1=v1, 2=v2) */
-    mbedtls_x509_buf MBEDTLS_PRIVATE(sig_oid);       /**< CRL signature type identifier */
+    int version;            /**< CRL version (1=v1, 2=v2) */
+    mbedtls_x509_buf sig_oid;       /**< CRL signature type identifier */
 
-    mbedtls_x509_buf MBEDTLS_PRIVATE(issuer_raw);    /**< The raw issuer data (DER). */
+    mbedtls_x509_buf issuer_raw;    /**< The raw issuer data (DER). */
 
-    mbedtls_x509_name MBEDTLS_PRIVATE(issuer);       /**< The parsed issuer data (named information object). */
+    mbedtls_x509_name issuer;       /**< The parsed issuer data (named information object). */
 
-    mbedtls_x509_time MBEDTLS_PRIVATE(this_update);
-    mbedtls_x509_time MBEDTLS_PRIVATE(next_update);
+    mbedtls_x509_time this_update;
+    mbedtls_x509_time next_update;
 
-    mbedtls_x509_crl_entry MBEDTLS_PRIVATE(entry);   /**< The CRL entries containing the certificate revocation times for this CA. */
+    mbedtls_x509_crl_entry entry;   /**< The CRL entries containing the certificate revocation times for this CA. */
 
-    mbedtls_x509_buf MBEDTLS_PRIVATE(crl_ext);
+    mbedtls_x509_buf crl_ext;
 
     mbedtls_x509_buf MBEDTLS_PRIVATE(sig_oid2);
     mbedtls_x509_buf MBEDTLS_PRIVATE(sig);
@@ -87,7 +99,10 @@
     mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk);           /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */
     void *MBEDTLS_PRIVATE(sig_opts);             /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */
 
-    struct mbedtls_x509_crl *MBEDTLS_PRIVATE(next);
+    /** Next element in the linked list of CRL.
+     * \p NULL indicates the end of the list.
+     * Do not modify this field directly. */
+    struct mbedtls_x509_crl *next;
 }
 mbedtls_x509_crl;
 
diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index 49211a9..3c11a99 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -45,36 +45,40 @@
 
 /**
  * Container for an X.509 certificate. The certificate may be chained.
+ *
+ * Some fields of this structure are publicly readable. Do not modify
+ * them except via Mbed TLS library functions: the effect of modifying
+ * those fields or the data that those fields points to is unspecified.
  */
 typedef struct mbedtls_x509_crt
 {
     int MBEDTLS_PRIVATE(own_buffer);                     /**< Indicates if \c raw is owned
                                          *   by the structure or not.        */
-    mbedtls_x509_buf MBEDTLS_PRIVATE(raw);               /**< The raw certificate data (DER). */
-    mbedtls_x509_buf MBEDTLS_PRIVATE(tbs);               /**< The raw certificate body (DER). The part that is To Be Signed. */
+    mbedtls_x509_buf raw;               /**< The raw certificate data (DER). */
+    mbedtls_x509_buf tbs;               /**< The raw certificate body (DER). The part that is To Be Signed. */
 
-    int MBEDTLS_PRIVATE(version);                /**< The X.509 version. (1=v1, 2=v2, 3=v3) */
-    mbedtls_x509_buf MBEDTLS_PRIVATE(serial);            /**< Unique id for certificate issued by a specific CA. */
-    mbedtls_x509_buf MBEDTLS_PRIVATE(sig_oid);           /**< Signature algorithm, e.g. sha1RSA */
+    int version;                /**< The X.509 version. (1=v1, 2=v2, 3=v3) */
+    mbedtls_x509_buf serial;            /**< Unique id for certificate issued by a specific CA. */
+    mbedtls_x509_buf sig_oid;           /**< Signature algorithm, e.g. sha1RSA */
 
-    mbedtls_x509_buf MBEDTLS_PRIVATE(issuer_raw);        /**< The raw issuer data (DER). Used for quick comparison. */
-    mbedtls_x509_buf MBEDTLS_PRIVATE(subject_raw);       /**< The raw subject data (DER). Used for quick comparison. */
+    mbedtls_x509_buf issuer_raw;        /**< The raw issuer data (DER). Used for quick comparison. */
+    mbedtls_x509_buf subject_raw;       /**< The raw subject data (DER). Used for quick comparison. */
 
-    mbedtls_x509_name MBEDTLS_PRIVATE(issuer);           /**< The parsed issuer data (named information object). */
-    mbedtls_x509_name MBEDTLS_PRIVATE(subject);          /**< The parsed subject data (named information object). */
+    mbedtls_x509_name issuer;           /**< The parsed issuer data (named information object). */
+    mbedtls_x509_name subject;          /**< The parsed subject data (named information object). */
 
-    mbedtls_x509_time MBEDTLS_PRIVATE(valid_from);       /**< Start time of certificate validity. */
-    mbedtls_x509_time MBEDTLS_PRIVATE(valid_to);         /**< End time of certificate validity. */
+    mbedtls_x509_time valid_from;       /**< Start time of certificate validity. */
+    mbedtls_x509_time valid_to;         /**< End time of certificate validity. */
 
-    mbedtls_x509_buf MBEDTLS_PRIVATE(pk_raw);
-    mbedtls_pk_context MBEDTLS_PRIVATE(pk);              /**< Container for the public key context. */
+    mbedtls_x509_buf pk_raw;
+    mbedtls_pk_context pk;              /**< Container for the public key context. */
 
-    mbedtls_x509_buf MBEDTLS_PRIVATE(issuer_id);         /**< Optional X.509 v2/v3 issuer unique identifier. */
-    mbedtls_x509_buf MBEDTLS_PRIVATE(subject_id);        /**< Optional X.509 v2/v3 subject unique identifier. */
-    mbedtls_x509_buf MBEDTLS_PRIVATE(v3_ext);            /**< Optional X.509 v3 extensions.  */
-    mbedtls_x509_sequence MBEDTLS_PRIVATE(subject_alt_names);    /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */
+    mbedtls_x509_buf issuer_id;         /**< Optional X.509 v2/v3 issuer unique identifier. */
+    mbedtls_x509_buf subject_id;        /**< Optional X.509 v2/v3 subject unique identifier. */
+    mbedtls_x509_buf v3_ext;            /**< Optional X.509 v3 extensions.  */
+    mbedtls_x509_sequence subject_alt_names;    /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */
 
-    mbedtls_x509_sequence MBEDTLS_PRIVATE(certificate_policies); /**< Optional list of certificate policies (Only anyPolicy is printed and enforced, however the rest of the policies are still listed). */
+    mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy is printed and enforced, however the rest of the policies are still listed). */
 
     int MBEDTLS_PRIVATE(ext_types);              /**< Bit string containing detected and parsed extensions */
     int MBEDTLS_PRIVATE(ca_istrue);              /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */
@@ -82,7 +86,7 @@
 
     unsigned int MBEDTLS_PRIVATE(key_usage);     /**< Optional key usage extension value: See the values in x509.h */
 
-    mbedtls_x509_sequence MBEDTLS_PRIVATE(ext_key_usage); /**< Optional list of extended key usage OIDs. */
+    mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */
 
     unsigned char MBEDTLS_PRIVATE(ns_cert_type); /**< Optional Netscape certificate type extension value: See the values in x509.h */
 
@@ -91,7 +95,10 @@
     mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk);           /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */
     void *MBEDTLS_PRIVATE(sig_opts);             /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */
 
-    struct mbedtls_x509_crt *MBEDTLS_PRIVATE(next);     /**< Next certificate in the CA-chain. */
+    /** Next certificate in the linked list that constitutes the CA chain.
+     * \p NULL indicates the end of the list.
+     * Do not modify this field directly. */
+    struct mbedtls_x509_crt *next;
 }
 mbedtls_x509_crt;
 
@@ -100,6 +107,9 @@
  * OtherName ::= SEQUENCE {
  *      type-id    OBJECT IDENTIFIER,
  *      value      [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * Future versions of the library may add new fields to this structure or
+ * to its embedded union and structure.
  */
 typedef struct mbedtls_x509_san_other_name
 {
@@ -108,7 +118,7 @@
      * To check the value of the type id, you should use
      * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf.
      */
-    mbedtls_x509_buf MBEDTLS_PRIVATE(type_id);                   /**< The type id. */
+    mbedtls_x509_buf type_id;                   /**< The type id. */
     union
     {
         /**
@@ -119,26 +129,30 @@
          */
         struct
         {
-            mbedtls_x509_buf MBEDTLS_PRIVATE(oid);               /**< The object identifier. */
-            mbedtls_x509_buf MBEDTLS_PRIVATE(val);               /**< The named value. */
+            mbedtls_x509_buf oid;               /**< The object identifier. */
+            mbedtls_x509_buf val;               /**< The named value. */
         }
-        MBEDTLS_PRIVATE(hardware_module_name);
+        hardware_module_name;
     }
-    MBEDTLS_PRIVATE(value);
+    value;
 }
 mbedtls_x509_san_other_name;
 
 /**
- * A structure for holding the parsed Subject Alternative Name, according to type
+ * A structure for holding the parsed Subject Alternative Name,
+ * according to type.
+ *
+ * Future versions of the library may add new fields to this structure or
+ * to its embedded union and structure.
  */
 typedef struct mbedtls_x509_subject_alternative_name
 {
-    int MBEDTLS_PRIVATE(type);                              /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */
+    int type;                              /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */
     union {
-        mbedtls_x509_san_other_name MBEDTLS_PRIVATE(other_name); /**< The otherName supported type. */
-        mbedtls_x509_buf   MBEDTLS_PRIVATE(unstructured_name); /**< The buffer for the un constructed types. Only dnsName currently supported */
+        mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */
+        mbedtls_x509_buf   unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */
     }
-    MBEDTLS_PRIVATE(san); /**< A union of the supported SAN types */
+    san; /**< A union of the supported SAN types */
 }
 mbedtls_x509_subject_alternative_name;
 
diff --git a/include/mbedtls/x509_csr.h b/include/mbedtls/x509_csr.h
index 674f9ce..f80a1a1 100644
--- a/include/mbedtls/x509_csr.h
+++ b/include/mbedtls/x509_csr.h
@@ -42,20 +42,24 @@
 
 /**
  * Certificate Signing Request (CSR) structure.
+ *
+ * Some fields of this structure are publicly readable. Do not modify
+ * them except via Mbed TLS library functions: the effect of modifying
+ * those fields or the data that those fields point to is unspecified.
  */
 typedef struct mbedtls_x509_csr
 {
-    mbedtls_x509_buf MBEDTLS_PRIVATE(raw);           /**< The raw CSR data (DER). */
-    mbedtls_x509_buf MBEDTLS_PRIVATE(cri);           /**< The raw CertificateRequestInfo body (DER). */
+    mbedtls_x509_buf raw;           /**< The raw CSR data (DER). */
+    mbedtls_x509_buf cri;           /**< The raw CertificateRequestInfo body (DER). */
 
-    int MBEDTLS_PRIVATE(version);            /**< CSR version (1=v1). */
+    int version;            /**< CSR version (1=v1). */
 
-    mbedtls_x509_buf  MBEDTLS_PRIVATE(subject_raw);  /**< The raw subject data (DER). */
-    mbedtls_x509_name MBEDTLS_PRIVATE(subject);      /**< The parsed subject data (named information object). */
+    mbedtls_x509_buf  subject_raw;  /**< The raw subject data (DER). */
+    mbedtls_x509_name subject;      /**< The parsed subject data (named information object). */
 
-    mbedtls_pk_context MBEDTLS_PRIVATE(pk);          /**< Container for the public key context. */
+    mbedtls_pk_context pk;          /**< Container for the public key context. */
 
-    mbedtls_x509_buf MBEDTLS_PRIVATE(sig_oid);
+    mbedtls_x509_buf sig_oid;
     mbedtls_x509_buf MBEDTLS_PRIVATE(sig);
     mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md);       /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */
     mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk);       /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */
diff --git a/include/psa/crypto_builtin_composites.h b/include/psa/crypto_builtin_composites.h
index b05660f..8075caf 100644
--- a/include/psa/crypto_builtin_composites.h
+++ b/include/psa/crypto_builtin_composites.h
@@ -77,6 +77,41 @@
 
 #define MBEDTLS_PSA_MAC_OPERATION_INIT {0, {0}}
 
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+#define MBEDTLS_PSA_BUILTIN_AEAD  1
+#endif
+
+/* Context structure for the Mbed TLS AEAD implementation. */
+typedef struct
+{
+    psa_algorithm_t MBEDTLS_PRIVATE(alg);
+    psa_key_type_t MBEDTLS_PRIVATE(key_type);
+
+    unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1;
+
+    uint8_t MBEDTLS_PRIVATE(tag_length);
+
+    union
+    {
+        unsigned dummy; /* Enable easier initializing of the union. */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+        mbedtls_ccm_context MBEDTLS_PRIVATE(ccm);
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+        mbedtls_gcm_context MBEDTLS_PRIVATE(gcm);
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+        mbedtls_chachapoly_context MBEDTLS_PRIVATE(chachapoly);
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+
+    } ctx;
+
+} mbedtls_psa_aead_operation_t;
+
+#define MBEDTLS_PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, {0}}
+
 /*
  * BEYOND THIS POINT, TEST DRIVER DECLARATIONS ONLY.
  */
@@ -88,6 +123,10 @@
 #define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT MBEDTLS_PSA_MAC_OPERATION_INIT
 #define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT MBEDTLS_PSA_MAC_OPERATION_INIT
 
+typedef mbedtls_psa_aead_operation_t mbedtls_transparent_test_driver_aead_operation_t;
+
+#define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT MBEDTLS_PSA_AEAD_OPERATION_INIT
+
 #endif /* PSA_CRYPTO_DRIVER_TEST */
 
 #endif /* PSA_CRYPTO_BUILTIN_COMPOSITES_H */
diff --git a/include/psa/crypto_driver_contexts_composites.h b/include/psa/crypto_driver_contexts_composites.h
index 239fdcb..957986c2 100644
--- a/include/psa/crypto_driver_contexts_composites.h
+++ b/include/psa/crypto_driver_contexts_composites.h
@@ -58,5 +58,13 @@
 #endif
 } psa_driver_mac_context_t;
 
+typedef union {
+    unsigned dummy; /* Make sure this union is always non-empty */
+    mbedtls_psa_aead_operation_t mbedtls_ctx;
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+    mbedtls_transparent_test_driver_aead_operation_t transparent_test_driver_ctx;
+#endif
+} psa_driver_aead_context_t;
+
 #endif /* PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H */
 /* End of automatically generated file. */
diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h
index 381abf9..2689415 100644
--- a/include/psa/crypto_struct.h
+++ b/include/psa/crypto_struct.h
@@ -72,6 +72,8 @@
 
 #include "mbedtls/cmac.h"
 #include "mbedtls/gcm.h"
+#include "mbedtls/ccm.h"
+#include "mbedtls/chachapoly.h"
 
 /* Include the context definition for the compiled-in drivers for the primitive
  * algorithms. */
@@ -148,19 +150,31 @@
 
 struct psa_aead_operation_s
 {
+
+    /** 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_crypto_driver_wrappers.h
+     * ID value zero means the context is not valid or not assigned to
+     * any driver (i.e. none of the driver contexts are active). */
+    unsigned int MBEDTLS_PRIVATE(id);
+
     psa_algorithm_t MBEDTLS_PRIVATE(alg);
-    unsigned int MBEDTLS_PRIVATE(key_set) : 1;
-    unsigned int MBEDTLS_PRIVATE(iv_set) : 1;
-    uint8_t MBEDTLS_PRIVATE(iv_size);
-    uint8_t MBEDTLS_PRIVATE(block_size);
-    union
-    {
-        unsigned MBEDTLS_PRIVATE(dummy); /* Enable easier initializing of the union. */
-        mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher);
-    } MBEDTLS_PRIVATE(ctx);
+    psa_key_type_t MBEDTLS_PRIVATE(key_type);
+
+    size_t MBEDTLS_PRIVATE(ad_remaining);
+    size_t MBEDTLS_PRIVATE(body_remaining);
+
+    unsigned int MBEDTLS_PRIVATE(nonce_set) : 1;
+    unsigned int MBEDTLS_PRIVATE(lengths_set) : 1;
+    unsigned int MBEDTLS_PRIVATE(ad_started) : 1;
+    unsigned int MBEDTLS_PRIVATE(body_started) : 1;
+    unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1;
+
+    psa_driver_aead_context_t MBEDTLS_PRIVATE(ctx);
 };
 
-#define PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, 0, { 0 } }
+#define PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0}}
 static inline struct psa_aead_operation_s psa_aead_operation_init( void )
 {
     const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT;
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index a5d692c..18aff5a 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -109,6 +109,44 @@
     ssl_tls13_generic.c
 )
 
+if(GEN_FILES)
+    find_package(Perl REQUIRED)
+
+    file(GLOB error_headers ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls/*.h)
+    add_custom_command(
+        OUTPUT
+            ${CMAKE_CURRENT_BINARY_DIR}/error.c
+        COMMAND
+            ${PERL_EXECUTABLE}
+                ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_errors.pl
+                ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls
+                ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files
+                ${CMAKE_CURRENT_BINARY_DIR}/error.c
+        DEPENDS
+            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_errors.pl
+            ${error_headers}
+            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/error.fmt
+    )
+
+    add_custom_command(
+        OUTPUT
+            ${CMAKE_CURRENT_BINARY_DIR}/version_features.c
+        COMMAND
+            ${PERL_EXECUTABLE}
+                ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_features.pl
+                ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls
+                ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files
+                ${CMAKE_CURRENT_BINARY_DIR}/version_features.c
+        DEPENDS
+            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_features.pl
+            ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls/mbedtls_config.h
+            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/version_features.fmt
+    )
+else()
+    link_to_source(error.c)
+    link_to_source(version_features.c)
+endif()
+
 if(CMAKE_COMPILER_IS_GNUCC)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes")
 endif(CMAKE_COMPILER_IS_GNUCC)
diff --git a/library/aes.c b/library/aes.c
index 8e3358c..4afc3c4 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -1011,6 +1011,7 @@
                     unsigned char *output )
 {
     int i;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[16];
 
     AES_VALIDATE_RET( ctx != NULL );
@@ -1040,7 +1041,9 @@
         while( length > 0 )
         {
             memcpy( temp, input, 16 );
-            mbedtls_aes_crypt_ecb( ctx, mode, input, output );
+            ret = mbedtls_aes_crypt_ecb( ctx, mode, input, output );
+            if( ret != 0 )
+                goto exit;
 
             for( i = 0; i < 16; i++ )
                 output[i] = (unsigned char)( output[i] ^ iv[i] );
@@ -1059,7 +1062,9 @@
             for( i = 0; i < 16; i++ )
                 output[i] = (unsigned char)( input[i] ^ iv[i] );
 
-            mbedtls_aes_crypt_ecb( ctx, mode, output, output );
+            ret = mbedtls_aes_crypt_ecb( ctx, mode, output, output );
+            if( ret != 0 )
+                goto exit;
             memcpy( iv, output, 16 );
 
             input  += 16;
@@ -1067,8 +1072,10 @@
             length -= 16;
         }
     }
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -1222,6 +1229,7 @@
                        unsigned char *output )
 {
     int c;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
 
     AES_VALIDATE_RET( ctx != NULL );
@@ -1242,7 +1250,11 @@
         while( length-- )
         {
             if( n == 0 )
-                mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+            {
+                ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+                if( ret != 0 )
+                    goto exit;
+            }
 
             c = *input++;
             *output++ = (unsigned char)( c ^ iv[n] );
@@ -1256,7 +1268,11 @@
         while( length-- )
         {
             if( n == 0 )
-                mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+            {
+                ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+                if( ret != 0 )
+                    goto exit;
+            }
 
             iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
 
@@ -1265,8 +1281,10 @@
     }
 
     *iv_off = n;
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 
 /*
@@ -1279,6 +1297,7 @@
                             const unsigned char *input,
                             unsigned char *output )
 {
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char c;
     unsigned char ov[17];
 
@@ -1291,7 +1310,9 @@
     while( length-- )
     {
         memcpy( ov, iv, 16 );
-        mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+        ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+        if( ret != 0 )
+            goto exit;
 
         if( mode == MBEDTLS_AES_DECRYPT )
             ov[16] = *input;
@@ -1303,8 +1324,10 @@
 
         memcpy( iv, ov + 1, 16 );
     }
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
@@ -1366,6 +1389,7 @@
                        unsigned char *output )
 {
     int c, i;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
 
     AES_VALIDATE_RET( ctx != NULL );
@@ -1383,7 +1407,9 @@
     while( length-- )
     {
         if( n == 0 ) {
-            mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
+            ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
+            if( ret != 0 )
+                goto exit;
 
             for( i = 16; i > 0; i-- )
                 if( ++nonce_counter[i - 1] != 0 )
@@ -1396,8 +1422,10 @@
     }
 
     *nc_off = n;
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
diff --git a/library/base64.c b/library/base64.c
index 9cf5dd4..a516c1d 100644
--- a/library/base64.c
+++ b/library/base64.c
@@ -22,6 +22,7 @@
 #if defined(MBEDTLS_BASE64_C)
 
 #include "mbedtls/base64.h"
+#include "base64_invasive.h"
 
 #include <stdint.h>
 
@@ -35,127 +36,41 @@
 #endif /* MBEDTLS_PLATFORM_C */
 #endif /* MBEDTLS_SELF_TEST */
 
-static const unsigned char base64_enc_map[64] =
-{
-    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
-    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
-    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
-    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
-    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
-    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
-    '8', '9', '+', '/'
-};
-
-static const unsigned char base64_dec_map[128] =
-{
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
-     54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
-    127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
-      5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
-     15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
-     25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
-     29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
-     39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
-     49,  50,  51, 127, 127, 127, 127, 127
-};
-
 #define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
 
-/*
- * Constant flow conditional assignment to unsigned char
+/* Return 0xff if low <= c <= high, 0 otherwise.
+ *
+ * Constant flow with respect to c.
  */
-static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src,
-                                       unsigned char condition )
+MBEDTLS_STATIC_TESTABLE
+unsigned char mbedtls_base64_mask_of_range( unsigned char low,
+                                            unsigned char high,
+                                            unsigned char c )
 {
-    /* MSVC has a warning about unary minus on unsigned integer types,
-     * but this is well-defined and precisely what we want to do here. */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-
-    /* Generate bitmask from condition, mask will either be 0xFF or 0 */
-    unsigned char mask = ( condition | -condition );
-    mask >>= 7;
-    mask = -mask;
-
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
-    *dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask );
+    /* low_mask is: 0 if low <= c, 0x...ff if low > c */
+    unsigned low_mask = ( (unsigned) c - low ) >> 8;
+    /* high_mask is: 0 if c <= high, 0x...ff if c > high */
+    unsigned high_mask = ( (unsigned) high - c ) >> 8;
+    return( ~( low_mask | high_mask ) & 0xff );
 }
 
-/*
- * Constant flow conditional assignment to uint_32
+/* Given a value in the range 0..63, return the corresponding Base64 digit.
+ * The implementation assumes that letters are consecutive (e.g. ASCII
+ * but not EBCDIC).
  */
-static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src,
-                                       uint32_t condition )
+MBEDTLS_STATIC_TESTABLE
+unsigned char mbedtls_base64_enc_char( unsigned char val )
 {
-    /* MSVC has a warning about unary minus on unsigned integer types,
-     * but this is well-defined and precisely what we want to do here. */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-
-    /* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */
-    uint32_t mask = ( condition | -condition );
-    mask >>= 31;
-    mask = -mask;
-
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
-    *dest = ( src & mask ) | ( ( *dest ) & ~mask );
-}
-
-/*
- * Constant flow check for equality
- */
-static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b )
-{
-    size_t difference = in_a ^ in_b;
-
-    /* MSVC has a warning about unary minus on unsigned integer types,
-     * but this is well-defined and precisely what we want to do here. */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-
-    difference |= -difference;
-
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
-    /* cope with the varying size of size_t per platform */
-    difference >>= ( sizeof( difference ) * 8 - 1 );
-
-    return (unsigned char) ( 1 ^ difference );
-}
-
-/*
- * Constant flow lookup into table.
- */
-static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table,
-                                                 const size_t table_size, const size_t table_index )
-{
-    size_t i;
-    unsigned char result = 0;
-
-    for( i = 0; i < table_size; ++i )
-    {
-        mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) );
-    }
-
-    return result;
+    unsigned char digit = 0;
+    /* For each range of values, if val is in that range, mask digit with
+     * the corresponding value. Since val can only be in a single range,
+     * only at most one masking will change digit. */
+    digit |= mbedtls_base64_mask_of_range(  0, 25, val ) & ( 'A' + val );
+    digit |= mbedtls_base64_mask_of_range( 26, 51, val ) & ( 'a' + val - 26 );
+    digit |= mbedtls_base64_mask_of_range( 52, 61, val ) & ( '0' + val - 52 );
+    digit |= mbedtls_base64_mask_of_range( 62, 62, val ) & '+';
+    digit |= mbedtls_base64_mask_of_range( 63, 63, val ) & '/';
+    return( digit );
 }
 
 /*
@@ -198,17 +113,12 @@
         C2 = *src++;
         C3 = *src++;
 
-        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                            ( ( C1 >> 2 ) & 0x3F ) );
-
-        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                            ( ( ( ( C1 &  3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
-
-        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                            ( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) );
-
-        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                            ( C3 & 0x3F ) );
+        *p++ = mbedtls_base64_enc_char( ( C1 >> 2 ) & 0x3F );
+        *p++ = mbedtls_base64_enc_char( ( ( ( C1 &  3 ) << 4 ) + ( C2 >> 4 ) )
+                                        & 0x3F );
+        *p++ = mbedtls_base64_enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) )
+                                        & 0x3F );
+        *p++ = mbedtls_base64_enc_char( C3 & 0x3F );
     }
 
     if( i < slen )
@@ -216,15 +126,12 @@
         C1 = *src++;
         C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
 
-        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                            ( ( C1 >> 2 ) & 0x3F ) );
-
-        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                            ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
+        *p++ = mbedtls_base64_enc_char( ( C1 >> 2 ) & 0x3F );
+        *p++ = mbedtls_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) )
+                                        & 0x3F );
 
         if( ( i + 1 ) < slen )
-             *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                                 ( ( ( C2 & 15 ) << 2 ) & 0x3F ) );
+             *p++ = mbedtls_base64_enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F );
         else *p++ = '=';
 
         *p++ = '=';
@@ -236,26 +143,58 @@
     return( 0 );
 }
 
+/* Given a Base64 digit, return its value.
+ * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
+ * return -1.
+ *
+ * The implementation assumes that letters are consecutive (e.g. ASCII
+ * but not EBCDIC).
+ *
+ * The implementation is constant-flow (no branch or memory access depending
+ * on the value of c) unless the compiler inlines and optimizes a specific
+ * access.
+ */
+MBEDTLS_STATIC_TESTABLE
+signed char mbedtls_base64_dec_value( unsigned char c )
+{
+    unsigned char val = 0;
+    /* For each range of digits, if c is in that range, mask val with
+     * the corresponding value. Since c can only be in a single range,
+     * only at most one masking will change val. Set val to one plus
+     * the desired value so that it stays 0 if c is in none of the ranges. */
+    val |= mbedtls_base64_mask_of_range( 'A', 'Z', c ) & ( c - 'A' +  0 + 1 );
+    val |= mbedtls_base64_mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 );
+    val |= mbedtls_base64_mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 );
+    val |= mbedtls_base64_mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 );
+    val |= mbedtls_base64_mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 );
+    /* At this point, val is 0 if c is an invalid digit and v+1 if c is
+     * a digit with the value v. */
+    return( val - 1 );
+}
+
 /*
  * Decode a base64-formatted buffer
  */
 int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
                    const unsigned char *src, size_t slen )
 {
-    size_t i, n;
-    uint32_t j, x;
+    size_t i; /* index in source */
+    size_t n; /* number of digits or trailing = in source */
+    uint32_t x; /* value accumulator */
+    unsigned accumulated_digits = 0;
+    unsigned equals = 0;
+    int spaces_present = 0;
     unsigned char *p;
-    unsigned char dec_map_lookup;
 
     /* First pass: check for validity and get output length */
-    for( i = n = j = 0; i < slen; i++ )
+    for( i = n = 0; i < slen; i++ )
     {
         /* Skip spaces before checking for EOL */
-        x = 0;
+        spaces_present = 0;
         while( i < slen && src[i] == ' ' )
         {
             ++i;
-            ++x;
+            spaces_present = 1;
         }
 
         /* Spaces at end of buffer are OK */
@@ -270,20 +209,24 @@
             continue;
 
         /* Space inside a line is an error */
-        if( x != 0 )
+        if( spaces_present )
             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
 
-        if( src[i] == '=' && ++j > 2 )
+        if( src[i] > 127 )
             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
 
-        dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] );
-
-        if( src[i] > 127 || dec_map_lookup == 127 )
-            return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-
-        if( dec_map_lookup < 64 && j != 0 )
-            return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-
+        if( src[i] == '=' )
+        {
+            if( ++equals > 2 )
+                return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+        }
+        else
+        {
+            if( equals != 0 )
+                return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+            if( mbedtls_base64_dec_value( src[i] ) < 0 )
+                return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+        }
         n++;
     }
 
@@ -298,7 +241,7 @@
      *     n = ( ( n * 6 ) + 7 ) >> 3;
      */
     n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
-    n -= j;
+    n -= equals;
 
     if( dst == NULL || dlen < n )
     {
@@ -306,22 +249,24 @@
         return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
     }
 
-   for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
-   {
+    equals = 0;
+    for( x = 0, p = dst; i > 0; i--, src++ )
+    {
         if( *src == '\r' || *src == '\n' || *src == ' ' )
             continue;
 
-        dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src );
+        x = x << 6;
+        if( *src == '=' )
+            ++equals;
+        else
+            x |= mbedtls_base64_dec_value( *src );
 
-        mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) );
-        x  = ( x << 6 ) | ( dec_map_lookup & 0x3F );
-
-        if( ++n == 4 )
+        if( ++accumulated_digits == 4 )
         {
-            n = 0;
-            if( j > 0 ) *p++ = MBEDTLS_BYTE_2( x );
-            if( j > 1 ) *p++ = MBEDTLS_BYTE_1( x );
-            if( j > 2 ) *p++ = MBEDTLS_BYTE_0( x );
+            accumulated_digits = 0;
+            *p++ = MBEDTLS_BYTE_2( x );
+            if( equals <= 1 ) *p++ = MBEDTLS_BYTE_1( x );
+            if( equals <= 0 ) *p++ = MBEDTLS_BYTE_0( x );
         }
     }
 
diff --git a/library/base64_invasive.h b/library/base64_invasive.h
new file mode 100644
index 0000000..9e26471
--- /dev/null
+++ b/library/base64_invasive.h
@@ -0,0 +1,55 @@
+/**
+ * \file base_invasive.h
+ *
+ * \brief Base64 module: interfaces for invasive testing only.
+ *
+ * The interfaces in this file are intended for testing purposes only.
+ * They SHOULD NOT be made available in library integrations except when
+ * building the library for testing.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef MBEDTLS_BASE64_INVASIVE_H
+#define MBEDTLS_BASE64_INVASIVE_H
+
+#include "common.h"
+
+#if defined(MBEDTLS_TEST_HOOKS)
+/* Return 0xff if low <= c <= high, 0 otherwise.
+ *
+ * Constant flow with respect to c.
+ */
+unsigned char mbedtls_base64_mask_of_range( unsigned char low,
+                                            unsigned char high,
+                                            unsigned char c );
+
+/* Given a value in the range 0..63, return the corresponding Base64 digit.
+ *
+ * Operates in constant time (no branches or memory access depending on val).
+ */
+unsigned char mbedtls_base64_enc_char( unsigned char val );
+
+/* Given a Base64 digit, return its value.
+ * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
+ * return -1.
+ *
+ * Operates in constant time (no branches or memory access depending on c).
+ */
+signed char mbedtls_base64_dec_value( unsigned char c );
+#endif /* MBEDTLS_TEST_HOOKS */
+
+#endif /* MBEDTLS_SSL_INVASIVE_H */
diff --git a/library/bn_mul.h b/library/bn_mul.h
index 6ddffc4..b71ddd8 100644
--- a/library/bn_mul.h
+++ b/library/bn_mul.h
@@ -224,10 +224,10 @@
         "adcq   %%rdx, %%rcx\n"             \
         "addq   $8, %%rdi\n"
 
-#define MULADDC_STOP                        \
-        : "+c" (c), "+D" (d), "+S" (s)      \
-        : "b" (b)                           \
-        : "rax", "rdx", "r8"                \
+#define MULADDC_STOP                                                 \
+        : "+c" (c), "+D" (d), "+S" (s), "+m" (*(uint64_t (*)[16]) d) \
+        : "b" (b), "m" (*(const uint64_t (*)[16]) s)                 \
+        : "rax", "rdx", "r8"                                         \
     );
 
 #endif /* AMD64 */
@@ -240,18 +240,18 @@
 #define MULADDC_CORE                \
         "ldr x4, [%2], #8   \n\t"   \
         "ldr x5, [%1]       \n\t"   \
-        "mul x6, x4, %3     \n\t"   \
-        "umulh x7, x4, %3   \n\t"   \
+        "mul x6, x4, %4     \n\t"   \
+        "umulh x7, x4, %4   \n\t"   \
         "adds x5, x5, x6    \n\t"   \
         "adc x7, x7, xzr    \n\t"   \
         "adds x5, x5, %0    \n\t"   \
         "adc %0, x7, xzr    \n\t"   \
         "str x5, [%1], #8   \n\t"
 
-#define MULADDC_STOP                        \
-         : "+r" (c),  "+r" (d), "+r" (s)    \
-         : "r" (b)                          \
-         : "x4", "x5", "x6", "x7", "cc"     \
+#define MULADDC_STOP                                                    \
+         : "+r" (c),  "+r" (d), "+r" (s), "+m" (*(uint64_t (*)[16]) d)  \
+         : "r" (b), "m" (*(const uint64_t (*)[16]) s)                   \
+         : "x4", "x5", "x6", "x7", "cc"                                 \
     );
 
 #endif /* Aarch64 */
diff --git a/library/ccm.c b/library/ccm.c
index a21a37f..15efff7 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -36,31 +36,23 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
 #else
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
 #include <stdio.h>
 #define mbedtls_printf printf
-#endif /* MBEDTLS_PLATFORM_C */
 #endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
+#endif /* MBEDTLS_PLATFORM_C */
 
 #if !defined(MBEDTLS_CCM_ALT)
 
-#define CCM_VALIDATE_RET( cond ) \
-    MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT )
-#define CCM_VALIDATE( cond ) \
-    MBEDTLS_INTERNAL_VALIDATE( cond )
-
-#define CCM_ENCRYPT 0
-#define CCM_DECRYPT 1
 
 /*
  * Initialize context
  */
 void mbedtls_ccm_init( mbedtls_ccm_context *ctx )
 {
-    CCM_VALIDATE( ctx != NULL );
     memset( ctx, 0, sizeof( mbedtls_ccm_context ) );
 }
 
@@ -72,9 +64,6 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_cipher_info_t *cipher_info;
 
-    CCM_VALIDATE_RET( ctx != NULL );
-    CCM_VALIDATE_RET( key != NULL );
-
     cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
                                                    MBEDTLS_MODE_ECB );
     if( cipher_info == NULL )
@@ -108,82 +97,67 @@
     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
 }
 
-/*
- * Macros for common operations.
- * Results in smaller compiled code than static inline functions.
- */
-
-/*
- * Update the CBC-MAC state in y using a block in b
- * (Always using b as the source helps the compiler optimise a bit better.)
- */
-#define UPDATE_CBC_MAC                                                      \
-    for( i = 0; i < 16; i++ )                                               \
-        y[i] ^= b[i];                                                       \
-                                                                            \
-    if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
-        return( ret );
+#define CCM_STATE__CLEAR                0
+#define CCM_STATE__STARTED              (1 << 0)
+#define CCM_STATE__LENGHTS_SET          (1 << 1)
+#define CCM_STATE__AUTH_DATA_STARTED    (1 << 2)
+#define CCM_STATE__AUTH_DATA_FINISHED   (1 << 3)
+#define CCM_STATE__ERROR                (1 << 4)
 
 /*
  * Encrypt or decrypt a partial block with CTR
- * Warning: using b for temporary storage! src and dst must not be b!
- * This avoids allocating one more 16 bytes buffer while allowing src == dst.
  */
-#define CTR_CRYPT( dst, src, len  )                                            \
-    do                                                                  \
-    {                                                                   \
-        if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr,       \
-                                           16, b, &olen ) ) != 0 )      \
-        {                                                               \
-            return( ret );                                              \
-        }                                                               \
-                                                                        \
-        for( i = 0; i < (len); i++ )                                    \
-            (dst)[i] = (src)[i] ^ b[i];                                 \
-    } while( 0 )
+static int mbedtls_ccm_crypt( mbedtls_ccm_context *ctx,
+                              size_t offset, size_t use_len,
+                              const unsigned char *input,
+                              unsigned char *output )
+{
+    size_t i;
+    size_t olen = 0;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char tmp_buf[16] = {0};
 
-/*
- * Authenticated encryption or decryption
- */
-static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
-                           const unsigned char *iv, size_t iv_len,
-                           const unsigned char *add, size_t add_len,
-                           const unsigned char *input, unsigned char *output,
-                           unsigned char *tag, size_t tag_len )
+    if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->ctr, 16, tmp_buf,
+                                       &olen ) ) != 0 )
+    {
+        ctx->state |= CCM_STATE__ERROR;
+        mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf));
+        return ret;
+    }
+
+    for( i = 0; i < use_len; i++ )
+        output[i] = input[i] ^ tmp_buf[offset + i];
+
+    mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf));
+    return ret;
+}
+
+static void mbedtls_ccm_clear_state(mbedtls_ccm_context *ctx) {
+    ctx->state = CCM_STATE__CLEAR;
+    memset( ctx->y, 0, 16);
+    memset( ctx->ctr, 0, 16);
+}
+
+static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char i;
-    unsigned char q;
     size_t len_left, olen;
-    unsigned char b[16];
-    unsigned char y[16];
-    unsigned char ctr[16];
-    const unsigned char *src;
-    unsigned char *dst;
 
-    /*
-     * Check length requirements: SP800-38C A.1
-     * Additional requirement: a < 2^16 - 2^8 to simplify the code.
-     * 'length' checked later (when writing it to the first block)
-     *
-     * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
+    /* length calulcation can be done only after both
+     * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed
      */
-    if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+    if( !(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGHTS_SET) )
+        return 0;
 
-    /* Also implies q is within bounds */
-    if( iv_len < 7 || iv_len > 13 )
+    if( ctx->tag_len == 0 && \
+        ( ctx->mode == MBEDTLS_CCM_ENCRYPT || ctx->mode == MBEDTLS_CCM_DECRYPT ) )
         return( MBEDTLS_ERR_CCM_BAD_INPUT );
 
-    if( add_len >= 0xFF00 )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
-
-    q = 16 - 1 - (unsigned char) iv_len;
-
     /*
-     * First block B_0:
+     * First block:
      * 0        .. 0        flags
-     * 1        .. iv_len   nonce (aka iv)
+     * 1        .. iv_len   nonce (aka iv)  - set by: mbedtls_ccm_starts()
      * iv_len+1 .. 15       length
      *
      * With flags as (bits):
@@ -192,56 +166,40 @@
      * 5 .. 3   (t - 2) / 2
      * 2 .. 0   q - 1
      */
-    b[0] = 0;
-    b[0] |= ( add_len > 0 ) << 6;
-    b[0] |= ( ( tag_len - 2 ) / 2 ) << 3;
-    b[0] |= q - 1;
+    ctx->y[0] |= ( ctx->add_len > 0 ) << 6;
+    ctx->y[0] |= ( ( ctx->tag_len - 2 ) / 2 ) << 3;
+    ctx->y[0] |= ctx->q - 1;
 
-    memcpy( b + 1, iv, iv_len );
-
-    for( i = 0, len_left = length; i < q; i++, len_left >>= 8 )
-        b[15-i] = MBEDTLS_BYTE_0( len_left );
+    for( i = 0, len_left = ctx->plaintext_len; i < ctx->q; i++, len_left >>= 8 )
+        ctx->y[15-i] = MBEDTLS_BYTE_0( len_left );
 
     if( len_left > 0 )
+    {
+        ctx->state |= CCM_STATE__ERROR;
+        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+    }
+
+    /* Start CBC-MAC with first block*/
+    if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen ) ) != 0 )
+    {
+        ctx->state |= CCM_STATE__ERROR;
+        return( ret );
+    }
+
+    return (0);
+}
+
+int mbedtls_ccm_starts( mbedtls_ccm_context *ctx,
+                        int mode,
+                        const unsigned char *iv,
+                        size_t iv_len )
+{
+    /* Also implies q is within bounds */
+    if( iv_len < 7 || iv_len > 13 )
         return( MBEDTLS_ERR_CCM_BAD_INPUT );
 
-
-    /* Start CBC-MAC with first block */
-    memset( y, 0, 16 );
-    UPDATE_CBC_MAC;
-
-    /*
-     * If there is additional data, update CBC-MAC with
-     * add_len, add, 0 (padding to a block boundary)
-     */
-    if( add_len > 0 )
-    {
-        size_t use_len;
-        len_left = add_len;
-        src = add;
-
-        memset( b, 0, 16 );
-        MBEDTLS_PUT_UINT16_BE( add_len, b, 0 );
-
-        use_len = len_left < 16 - 2 ? len_left : 16 - 2;
-        memcpy( b + 2, src, use_len );
-        len_left -= use_len;
-        src += use_len;
-
-        UPDATE_CBC_MAC;
-
-        while( len_left > 0 )
-        {
-            use_len = len_left > 16 ? 16 : len_left;
-
-            memset( b, 0, 16 );
-            memcpy( b, src, use_len );
-            UPDATE_CBC_MAC;
-
-            len_left -= use_len;
-            src += use_len;
-        }
-    }
+    ctx->mode = mode;
+    ctx->q = 16 - 1 - (unsigned char) iv_len;
 
     /*
      * Prepare counter block for encryption:
@@ -253,62 +211,290 @@
      * 7 .. 3   0
      * 2 .. 0   q - 1
      */
-    ctr[0] = q - 1;
-    memcpy( ctr + 1, iv, iv_len );
-    memset( ctr + 1 + iv_len, 0, q );
-    ctr[15] = 1;
+    memset( ctx->ctr, 0, 16);
+    ctx->ctr[0] = ctx->q - 1;
+    memcpy( ctx->ctr + 1, iv, iv_len );
+    memset( ctx->ctr + 1 + iv_len, 0, ctx->q );
+    ctx->ctr[15] = 1;
 
     /*
-     * Authenticate and {en,de}crypt the message.
-     *
-     * The only difference between encryption and decryption is
-     * the respective order of authentication and {en,de}cryption.
+     * See ccm_calculate_first_block_if_ready() for block layout description
      */
-    len_left = length;
-    src = input;
-    dst = output;
+    memcpy( ctx->y + 1, iv, iv_len );
 
-    while( len_left > 0 )
+    ctx->state |= CCM_STATE__STARTED;
+    return ccm_calculate_first_block_if_ready(ctx);
+}
+
+int mbedtls_ccm_set_lengths( mbedtls_ccm_context *ctx,
+                             size_t total_ad_len,
+                             size_t plaintext_len,
+                             size_t tag_len )
+{
+    /*
+     * Check length requirements: SP800-38C A.1
+     * Additional requirement: a < 2^16 - 2^8 to simplify the code.
+     * 'length' checked later (when writing it to the first block)
+     *
+     * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
+     */
+    if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 )
+        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+
+    if( total_ad_len >= 0xFF00 )
+        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+
+    ctx->plaintext_len = plaintext_len;
+    ctx->add_len = total_ad_len;
+    ctx->tag_len = tag_len;
+    ctx->processed = 0;
+
+    ctx->state |= CCM_STATE__LENGHTS_SET;
+    return ccm_calculate_first_block_if_ready(ctx);
+}
+
+int mbedtls_ccm_update_ad( mbedtls_ccm_context *ctx,
+                           const unsigned char *add,
+                           size_t add_len )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char i;
+    size_t olen, use_len, offset;
+
+    if( ctx->state & CCM_STATE__ERROR )
     {
-        size_t use_len = len_left > 16 ? 16 : len_left;
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
 
-        if( mode == CCM_ENCRYPT )
+    if( add_len > 0 )
+    {
+        if( ctx->state & CCM_STATE__AUTH_DATA_FINISHED )
         {
-            memset( b, 0, 16 );
-            memcpy( b, src, use_len );
-            UPDATE_CBC_MAC;
+            return MBEDTLS_ERR_CCM_BAD_INPUT;
         }
 
-        CTR_CRYPT( dst, src, use_len );
-
-        if( mode == CCM_DECRYPT )
+        if( !(ctx->state & CCM_STATE__AUTH_DATA_STARTED) )
         {
-            memset( b, 0, 16 );
-            memcpy( b, dst, use_len );
-            UPDATE_CBC_MAC;
+            if ( add_len > ctx->add_len )
+            {
+                return MBEDTLS_ERR_CCM_BAD_INPUT;
+            }
+
+            ctx->y[0] ^= (unsigned char)( ( ctx->add_len >> 8 ) & 0xFF );
+            ctx->y[1] ^= (unsigned char)( ( ctx->add_len      ) & 0xFF );
+
+            ctx->state |= CCM_STATE__AUTH_DATA_STARTED;
+        }
+        else if ( ctx->processed + add_len > ctx->add_len )
+        {
+            return MBEDTLS_ERR_CCM_BAD_INPUT;
         }
 
-        dst += use_len;
-        src += use_len;
-        len_left -= use_len;
+        while( add_len > 0 )
+        {
+            offset = (ctx->processed + 2) % 16; /* account for y[0] and y[1]
+                                                 * holding total auth data length */
+            use_len = 16 - offset;
 
-        /*
-         * Increment counter.
-         * No need to check for overflow thanks to the length check above.
-         */
-        for( i = 0; i < q; i++ )
-            if( ++ctr[15-i] != 0 )
+            if( use_len > add_len )
+                use_len = add_len;
+
+            for( i = 0; i < use_len; i++ )
+                ctx->y[i + offset] ^= add[i];
+
+            ctx->processed += use_len;
+            add_len -= use_len;
+            add += use_len;
+
+            if( use_len + offset == 16 || ctx->processed == ctx->add_len )
+            {
+                if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen ) ) != 0 )
+                {
+                    ctx->state |= CCM_STATE__ERROR;
+                    return( ret );
+                }
+            }
+        }
+
+        if( ctx->processed == ctx->add_len )
+        {
+            ctx->state |= CCM_STATE__AUTH_DATA_FINISHED;
+            ctx->processed = 0; // prepare for mbedtls_ccm_update()
+        }
+    }
+
+    return (0);
+}
+
+int mbedtls_ccm_update( mbedtls_ccm_context *ctx,
+                        const unsigned char *input, size_t input_len,
+                        unsigned char *output, size_t output_size,
+                        size_t *output_len )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char i;
+    size_t use_len, offset, olen;
+
+    unsigned char local_output[16];
+
+    if( ctx->state & CCM_STATE__ERROR )
+    {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    if( ctx->processed + input_len > ctx->plaintext_len )
+    {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    if( output_size < input_len )
+        return( MBEDTLS_ERR_CCM_BAD_INPUT );
+    *output_len = input_len;
+
+    ret = 0;
+
+    while ( input_len > 0 )
+    {
+        offset = ctx->processed % 16;
+
+        use_len = 16 - offset;
+
+        if( use_len > input_len )
+            use_len = input_len;
+
+        ctx->processed += use_len;
+
+        if( ctx->mode == MBEDTLS_CCM_ENCRYPT || \
+            ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT )
+        {
+            for( i = 0; i < use_len; i++ )
+                ctx->y[i + offset] ^= input[i];
+
+            if( use_len + offset == 16 || ctx->processed == ctx->plaintext_len )
+            {
+                if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen ) ) != 0 )
+                {
+                    ctx->state |= CCM_STATE__ERROR;
+                    goto exit;
+                }
+            }
+
+            ret = mbedtls_ccm_crypt( ctx, offset, use_len, input, output );
+            if( ret != 0 )
+                goto exit;
+        }
+
+        if( ctx->mode == MBEDTLS_CCM_DECRYPT || \
+            ctx->mode == MBEDTLS_CCM_STAR_DECRYPT )
+        {
+            /* Since output may be in shared memory, we cannot be sure that
+             * it will contain what we wrote to it. Therefore, we should avoid using
+             * it as input to any operations.
+             * Write decrypted data to local_output to avoid using output variable as
+             * input in the XOR operation for Y.
+             */
+            ret = mbedtls_ccm_crypt( ctx, offset, use_len, input, local_output );
+            if( ret != 0 )
+                goto exit;
+
+            for( i = 0; i < use_len; i++ )
+                ctx->y[i + offset] ^= local_output[i];
+
+            memcpy( output, local_output, use_len );
+            mbedtls_platform_zeroize( local_output, 16 );
+
+            if( use_len + offset == 16 || ctx->processed == ctx->plaintext_len )
+            {
+                if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen ) ) != 0 )
+                {
+                    ctx->state |= CCM_STATE__ERROR;
+                    goto exit;
+                }
+            }
+        }
+
+        if( use_len + offset == 16 || ctx->processed == ctx->plaintext_len )
+        {
+            for( i = 0; i < ctx->q; i++ )
+            if( ++(ctx->ctr)[15-i] != 0 )
                 break;
+        }
+
+        input_len -= use_len;
+        input += use_len;
+        output += use_len;
+    }
+
+exit:
+    mbedtls_platform_zeroize( local_output, 16 );
+
+    return ret;
+}
+
+int mbedtls_ccm_finish( mbedtls_ccm_context *ctx,
+                        unsigned char *tag, size_t tag_len )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char i;
+
+    if( ctx->state & CCM_STATE__ERROR )
+    {
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    }
+
+    if( ctx->add_len > 0 && !( ctx->state & CCM_STATE__AUTH_DATA_FINISHED ) )
+    {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    if( ctx->plaintext_len > 0 && ctx->processed != ctx->plaintext_len )
+    {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
     }
 
     /*
      * Authentication: reset counter and crypt/mask internal tag
      */
-    for( i = 0; i < q; i++ )
-        ctr[15-i] = 0;
+    for( i = 0; i < ctx->q; i++ )
+        ctx->ctr[15-i] = 0;
 
-    CTR_CRYPT( y, y, 16 );
-    memcpy( tag, y, tag_len );
+    ret = mbedtls_ccm_crypt( ctx, 0, 16, ctx->y, ctx->y );
+    if( ret != 0 )
+        return ret;
+    if( tag != NULL )
+        memcpy( tag, ctx->y, tag_len );
+    mbedtls_ccm_clear_state(ctx);
+
+    return( 0 );
+}
+
+/*
+ * Authenticated encryption or decryption
+ */
+static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
+                           const unsigned char *iv, size_t iv_len,
+                           const unsigned char *add, size_t add_len,
+                           const unsigned char *input, unsigned char *output,
+                           unsigned char *tag, size_t tag_len )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t olen;
+
+    if( ( ret = mbedtls_ccm_starts( ctx, mode, iv, iv_len ) ) != 0 )
+        return( ret );
+
+    if( ( ret = mbedtls_ccm_set_lengths( ctx, add_len, length, tag_len ) ) != 0 )
+        return( ret );
+
+    if( ( ret = mbedtls_ccm_update_ad( ctx, add, add_len ) ) != 0 )
+        return( ret );
+
+    if( ( ret = mbedtls_ccm_update( ctx, input, length,
+                                    output, length, &olen ) ) != 0 )
+        return( ret );
+
+    if( ( ret = mbedtls_ccm_finish( ctx, tag, tag_len ) ) != 0 )
+        return( ret );
 
     return( 0 );
 }
@@ -322,13 +508,7 @@
                          const unsigned char *input, unsigned char *output,
                          unsigned char *tag, size_t tag_len )
 {
-    CCM_VALIDATE_RET( ctx != NULL );
-    CCM_VALIDATE_RET( iv != NULL );
-    CCM_VALIDATE_RET( add_len == 0 || add != NULL );
-    CCM_VALIDATE_RET( length == 0 || input != NULL );
-    CCM_VALIDATE_RET( length == 0 || output != NULL );
-    CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
-    return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len,
+    return( ccm_auth_crypt( ctx, MBEDTLS_CCM_STAR_ENCRYPT, length, iv, iv_len,
                             add, add_len, input, output, tag, tag_len ) );
 }
 
@@ -338,78 +518,75 @@
                          const unsigned char *input, unsigned char *output,
                          unsigned char *tag, size_t tag_len )
 {
-    CCM_VALIDATE_RET( ctx != NULL );
-    CCM_VALIDATE_RET( iv != NULL );
-    CCM_VALIDATE_RET( add_len == 0 || add != NULL );
-    CCM_VALIDATE_RET( length == 0 || input != NULL );
-    CCM_VALIDATE_RET( length == 0 || output != NULL );
-    CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
-    if( tag_len == 0 )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
-
-    return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add,
-                add_len, input, output, tag, tag_len ) );
+    return( ccm_auth_crypt( ctx, MBEDTLS_CCM_ENCRYPT, length, iv, iv_len,
+                            add, add_len, input, output, tag, tag_len ) );
 }
 
 /*
  * Authenticated decryption
  */
-int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
-                      const unsigned char *iv, size_t iv_len,
-                      const unsigned char *add, size_t add_len,
-                      const unsigned char *input, unsigned char *output,
-                      const unsigned char *tag, size_t tag_len )
+static int mbedtls_ccm_compare_tags(const unsigned char *tag1, const unsigned char *tag2, size_t tag_len)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char check_tag[16];
     unsigned char i;
     int diff;
 
-    CCM_VALIDATE_RET( ctx != NULL );
-    CCM_VALIDATE_RET( iv != NULL );
-    CCM_VALIDATE_RET( add_len == 0 || add != NULL );
-    CCM_VALIDATE_RET( length == 0 || input != NULL );
-    CCM_VALIDATE_RET( length == 0 || output != NULL );
-    CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
+    /* Check tag in "constant-time" */
+    for( diff = 0, i = 0; i < tag_len; i++ )
+        diff |= tag1[i] ^ tag2[i];
 
-    if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
+    if( diff != 0 )
+    {
+        return( MBEDTLS_ERR_CCM_AUTH_FAILED );
+    }
+
+    return( 0 );
+}
+
+static int ccm_auth_decrypt( mbedtls_ccm_context *ctx, int mode, size_t length,
+                             const unsigned char *iv, size_t iv_len,
+                             const unsigned char *add, size_t add_len,
+                             const unsigned char *input, unsigned char *output,
+                             const unsigned char *tag, size_t tag_len )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char check_tag[16];
+
+    if( ( ret = ccm_auth_crypt( ctx, mode, length,
                                 iv, iv_len, add, add_len,
                                 input, output, check_tag, tag_len ) ) != 0 )
     {
         return( ret );
     }
 
-    /* Check tag in "constant-time" */
-    for( diff = 0, i = 0; i < tag_len; i++ )
-        diff |= tag[i] ^ check_tag[i];
-
-    if( diff != 0 )
+    if( ( ret = mbedtls_ccm_compare_tags( tag, check_tag, tag_len ) ) != 0 )
     {
         mbedtls_platform_zeroize( output, length );
-        return( MBEDTLS_ERR_CCM_AUTH_FAILED );
+        return( ret );
     }
 
     return( 0 );
 }
 
+int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
+                      const unsigned char *iv, size_t iv_len,
+                      const unsigned char *add, size_t add_len,
+                      const unsigned char *input, unsigned char *output,
+                      const unsigned char *tag, size_t tag_len )
+{
+    return ccm_auth_decrypt( ctx, MBEDTLS_CCM_STAR_DECRYPT, length,
+                             iv, iv_len, add, add_len,
+                             input, output, tag, tag_len );
+}
+
 int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
                       const unsigned char *iv, size_t iv_len,
                       const unsigned char *add, size_t add_len,
                       const unsigned char *input, unsigned char *output,
                       const unsigned char *tag, size_t tag_len )
 {
-    CCM_VALIDATE_RET( ctx != NULL );
-    CCM_VALIDATE_RET( iv != NULL );
-    CCM_VALIDATE_RET( add_len == 0 || add != NULL );
-    CCM_VALIDATE_RET( length == 0 || input != NULL );
-    CCM_VALIDATE_RET( length == 0 || output != NULL );
-    CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
-
-    if( tag_len == 0 )
-        return( MBEDTLS_ERR_CCM_BAD_INPUT );
-
-    return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add,
-                add_len, input, output, tag, tag_len ) );
+    return ccm_auth_decrypt( ctx, MBEDTLS_CCM_DECRYPT, length,
+                             iv, iv_len, add, add_len,
+                             input, output, tag, tag_len );
 }
 #endif /* !MBEDTLS_CCM_ALT */
 
diff --git a/library/cipher.c b/library/cipher.c
index 546cace..dc80189 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -1266,9 +1266,12 @@
         if( status != PSA_SUCCESS )
             return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED );
 
-        status = psa_cipher_set_iv( &cipher_op, iv, iv_len );
-        if( status != PSA_SUCCESS )
-            return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED );
+        if( ctx->cipher_info->mode != MBEDTLS_MODE_ECB )
+        {
+            status = psa_cipher_set_iv( &cipher_op, iv, iv_len );
+            if( status != PSA_SUCCESS )
+                return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED );
+        }
 
         status = psa_cipher_update( &cipher_op,
                                     input, ilen,
diff --git a/library/common.h b/library/common.h
index 780ce37..a630fcc 100644
--- a/library/common.h
+++ b/library/common.h
@@ -87,7 +87,7 @@
  * big-endian order (MSB first).
  *
  * \param   data    Base address of the memory to get the four bytes from.
- * \param   offset  Offset from \p base of the first and most significant
+ * \param   offset  Offset from \p data of the first and most significant
  *                  byte of the four bytes to build the 32 bits unsigned
  *                  integer from.
  */
@@ -107,7 +107,7 @@
  * \param   n       32 bits unsigned integer to put in memory.
  * \param   data    Base address of the memory where to put the 32
  *                  bits unsigned integer in.
- * \param   offset  Offset from \p base where to put the most significant
+ * \param   offset  Offset from \p data where to put the most significant
  *                  byte of the 32 bits unsigned integer \p n.
  */
 #ifndef MBEDTLS_PUT_UINT32_BE
@@ -125,7 +125,7 @@
  * little-endian order (LSB first).
  *
  * \param   data    Base address of the memory to get the four bytes from.
- * \param   offset  Offset from \p base of the first and least significant
+ * \param   offset  Offset from \p data of the first and least significant
  *                  byte of the four bytes to build the 32 bits unsigned
  *                  integer from.
  */
@@ -145,7 +145,7 @@
  * \param   n       32 bits unsigned integer to put in memory.
  * \param   data    Base address of the memory where to put the 32
  *                  bits unsigned integer in.
- * \param   offset  Offset from \p base where to put the least significant
+ * \param   offset  Offset from \p data where to put the least significant
  *                  byte of the 32 bits unsigned integer \p n.
  */
 #ifndef MBEDTLS_PUT_UINT32_LE
@@ -163,7 +163,7 @@
  * little-endian order (LSB first).
  *
  * \param   data    Base address of the memory to get the two bytes from.
- * \param   offset  Offset from \p base of the first and least significant
+ * \param   offset  Offset from \p data of the first and least significant
  *                  byte of the two bytes to build the 16 bits unsigned
  *                  integer from.
  */
@@ -181,7 +181,7 @@
  * \param   n       16 bits unsigned integer to put in memory.
  * \param   data    Base address of the memory where to put the 16
  *                  bits unsigned integer in.
- * \param   offset  Offset from \p base where to put the least significant
+ * \param   offset  Offset from \p data where to put the least significant
  *                  byte of the 16 bits unsigned integer \p n.
  */
 #ifndef MBEDTLS_PUT_UINT16_LE
@@ -197,7 +197,7 @@
  * big-endian order (MSB first).
  *
  * \param   data    Base address of the memory to get the two bytes from.
- * \param   offset  Offset from \p base of the first and most significant
+ * \param   offset  Offset from \p data of the first and most significant
  *                  byte of the two bytes to build the 16 bits unsigned
  *                  integer from.
  */
@@ -215,7 +215,7 @@
  * \param   n       16 bits unsigned integer to put in memory.
  * \param   data    Base address of the memory where to put the 16
  *                  bits unsigned integer in.
- * \param   offset  Offset from \p base where to put the most significant
+ * \param   offset  Offset from \p data where to put the most significant
  *                  byte of the 16 bits unsigned integer \p n.
  */
 #ifndef MBEDTLS_PUT_UINT16_BE
@@ -227,11 +227,83 @@
 #endif
 
 /**
+ * Get the unsigned 24 bits integer corresponding to three bytes in
+ * big-endian order (MSB first).
+ *
+ * \param   data    Base address of the memory to get the three bytes from.
+ * \param   offset  Offset from \p data of the first and most significant
+ *                  byte of the three bytes to build the 24 bits unsigned
+ *                  integer from.
+ */
+#ifndef MBEDTLS_GET_UINT24_BE
+#define MBEDTLS_GET_UINT24_BE( data , offset )                  \
+    (                                                           \
+          ( (uint32_t) ( data )[( offset )    ] << 16 )         \
+        | ( (uint32_t) ( data )[( offset ) + 1] << 8  )         \
+        | ( (uint32_t) ( data )[( offset ) + 2]       )         \
+    )
+#endif
+
+/**
+ * Put in memory a 24 bits unsigned integer in big-endian order.
+ *
+ * \param   n       24 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 24
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p data where to put the most significant
+ *                  byte of the 24 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT24_BE
+#define MBEDTLS_PUT_UINT24_BE( n, data, offset )                \
+{                                                               \
+    ( data )[( offset )    ] = MBEDTLS_BYTE_2( n );             \
+    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
+    ( data )[( offset ) + 2] = MBEDTLS_BYTE_0( n );             \
+}
+#endif
+
+/**
+ * Get the unsigned 24 bits integer corresponding to three bytes in
+ * little-endian order (LSB first).
+ *
+ * \param   data    Base address of the memory to get the three bytes from.
+ * \param   offset  Offset from \p data of the first and least significant
+ *                  byte of the three bytes to build the 24 bits unsigned
+ *                  integer from.
+ */
+#ifndef MBEDTLS_GET_UINT24_LE
+#define MBEDTLS_GET_UINT24_LE( data, offset )                   \
+    (                                                           \
+          ( (uint32_t) ( data )[( offset )    ]       )         \
+        | ( (uint32_t) ( data )[( offset ) + 1] <<  8 )         \
+        | ( (uint32_t) ( data )[( offset ) + 2] << 16 )         \
+    )
+#endif
+
+/**
+ * Put in memory a 24 bits unsigned integer in little-endian order.
+ *
+ * \param   n       24 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 24
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p data where to put the least significant
+ *                  byte of the 24 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT24_LE
+#define MBEDTLS_PUT_UINT24_LE( n, data, offset )                \
+{                                                               \
+    ( data )[( offset )    ] = MBEDTLS_BYTE_0( n );             \
+    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
+    ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n );             \
+}
+#endif
+
+/**
  * Get the unsigned 64 bits integer corresponding to eight bytes in
  * big-endian order (MSB first).
  *
  * \param   data    Base address of the memory to get the eight bytes from.
- * \param   offset  Offset from \p base of the first and most significant
+ * \param   offset  Offset from \p data of the first and most significant
  *                  byte of the eight bytes to build the 64 bits unsigned
  *                  integer from.
  */
@@ -255,7 +327,7 @@
  * \param   n       64 bits unsigned integer to put in memory.
  * \param   data    Base address of the memory where to put the 64
  *                  bits unsigned integer in.
- * \param   offset  Offset from \p base where to put the most significant
+ * \param   offset  Offset from \p data where to put the most significant
  *                  byte of the 64 bits unsigned integer \p n.
  */
 #ifndef MBEDTLS_PUT_UINT64_BE
@@ -277,7 +349,7 @@
  * little-endian order (LSB first).
  *
  * \param   data    Base address of the memory to get the eight bytes from.
- * \param   offset  Offset from \p base of the first and least significant
+ * \param   offset  Offset from \p data of the first and least significant
  *                  byte of the eight bytes to build the 64 bits unsigned
  *                  integer from.
  */
@@ -301,7 +373,7 @@
  * \param   n       64 bits unsigned integer to put in memory.
  * \param   data    Base address of the memory where to put the 64
  *                  bits unsigned integer in.
- * \param   offset  Offset from \p base where to put the least significant
+ * \param   offset  Offset from \p data where to put the least significant
  *                  byte of the 64 bits unsigned integer \p n.
  */
 #ifndef MBEDTLS_PUT_UINT64_LE
@@ -318,4 +390,12 @@
 }
 #endif
 
+/* Fix MSVC C99 compatible issue
+ *      MSVC support __func__ from visual studio 2015( 1900 )
+ *      Use MSVC predefine macro to avoid name check fail.
+ */
+#if (defined(_MSC_VER) && ( _MSC_VER <= 1900 ))
+#define /*no-check-names*/ __func__ __FUNCTION__
+#endif
+
 #endif /* MBEDTLS_LIBRARY_COMMON_H */
diff --git a/library/des.c b/library/des.c
index 7f90faa..91d22b5 100644
--- a/library/des.c
+++ b/library/des.c
@@ -28,6 +28,7 @@
 #if defined(MBEDTLS_DES_C)
 
 #include "mbedtls/des.h"
+#include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 
 #include <string.h>
@@ -642,6 +643,7 @@
                     unsigned char *output )
 {
     int i;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[8];
 
     if( length % 8 )
@@ -654,7 +656,9 @@
             for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( input[i] ^ iv[i] );
 
-            mbedtls_des_crypt_ecb( ctx, output, output );
+            ret = mbedtls_des_crypt_ecb( ctx, output, output );
+            if( ret != 0 )
+                goto exit;
             memcpy( iv, output, 8 );
 
             input  += 8;
@@ -667,7 +671,9 @@
         while( length > 0 )
         {
             memcpy( temp, input, 8 );
-            mbedtls_des_crypt_ecb( ctx, input, output );
+            ret = mbedtls_des_crypt_ecb( ctx, input, output );
+            if( ret != 0 )
+                goto exit;
 
             for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( output[i] ^ iv[i] );
@@ -679,8 +685,10 @@
             length -= 8;
         }
     }
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -741,6 +749,7 @@
                      unsigned char *output )
 {
     int i;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[8];
 
     if( length % 8 )
@@ -753,7 +762,9 @@
             for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( input[i] ^ iv[i] );
 
-            mbedtls_des3_crypt_ecb( ctx, output, output );
+            ret = mbedtls_des3_crypt_ecb( ctx, output, output );
+            if( ret != 0 )
+                goto exit;
             memcpy( iv, output, 8 );
 
             input  += 8;
@@ -766,7 +777,9 @@
         while( length > 0 )
         {
             memcpy( temp, input, 8 );
-            mbedtls_des3_crypt_ecb( ctx, input, output );
+            ret = mbedtls_des3_crypt_ecb( ctx, input, output );
+            if( ret != 0 )
+                goto exit;
 
             for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( output[i] ^ iv[i] );
@@ -778,8 +791,10 @@
             length -= 8;
         }
     }
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -872,39 +887,43 @@
         switch( i )
         {
         case 0:
-            mbedtls_des_setkey_dec( &ctx, des3_test_keys );
+            ret = mbedtls_des_setkey_dec( &ctx, des3_test_keys );
             break;
 
         case 1:
-            mbedtls_des_setkey_enc( &ctx, des3_test_keys );
+            ret = mbedtls_des_setkey_enc( &ctx, des3_test_keys );
             break;
 
         case 2:
-            mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
             break;
 
         case 3:
-            mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
             break;
 
         case 4:
-            mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
             break;
 
         case 5:
-            mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
             break;
 
         default:
             return( 1 );
         }
+        if( ret != 0 )
+            goto exit;
 
         for( j = 0; j < 100; j++ )
         {
             if( u == 0 )
-                mbedtls_des_crypt_ecb( &ctx, buf, buf );
+                ret = mbedtls_des_crypt_ecb( &ctx, buf, buf );
             else
-                mbedtls_des3_crypt_ecb( &ctx3, buf, buf );
+                ret = mbedtls_des3_crypt_ecb( &ctx3, buf, buf );
+            if( ret != 0 )
+                goto exit;
         }
 
         if( ( v == MBEDTLS_DES_DECRYPT &&
@@ -947,41 +966,45 @@
         switch( i )
         {
         case 0:
-            mbedtls_des_setkey_dec( &ctx, des3_test_keys );
+            ret = mbedtls_des_setkey_dec( &ctx, des3_test_keys );
             break;
 
         case 1:
-            mbedtls_des_setkey_enc( &ctx, des3_test_keys );
+            ret = mbedtls_des_setkey_enc( &ctx, des3_test_keys );
             break;
 
         case 2:
-            mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
             break;
 
         case 3:
-            mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
             break;
 
         case 4:
-            mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
             break;
 
         case 5:
-            mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
             break;
 
         default:
             return( 1 );
         }
+        if( ret != 0 )
+            goto exit;
 
         if( v == MBEDTLS_DES_DECRYPT )
         {
             for( j = 0; j < 100; j++ )
             {
                 if( u == 0 )
-                    mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                    ret = mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
                 else
-                    mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+                    ret = mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+                if( ret != 0 )
+                    goto exit;
             }
         }
         else
@@ -991,9 +1014,11 @@
                 unsigned char tmp[8];
 
                 if( u == 0 )
-                    mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                    ret = mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
                 else
-                    mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+                    ret = mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+                if( ret != 0 )
+                    goto exit;
 
                 memcpy( tmp, prv, 8 );
                 memcpy( prv, buf, 8 );
@@ -1027,6 +1052,8 @@
     mbedtls_des_free( &ctx );
     mbedtls_des3_free( &ctx3 );
 
+    if( ret != 0 )
+        ret = 1;
     return( ret );
 }
 
diff --git a/library/ecdh.c b/library/ecdh.c
index 9dfa868..ddd4ef5 100644
--- a/library/ecdh.c
+++ b/library/ecdh.c
@@ -32,6 +32,8 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
+#include "ecdh_misc.h"
+
 #include <string.h>
 
 /* Parameter validation macros based on platform_util.h */
@@ -726,4 +728,138 @@
 #endif
 }
 
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
+
+static int ecdh_tls13_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
+                size_t *olen, int point_format, unsigned char *buf, size_t blen,
+                int ( *f_rng )( void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if( ctx->grp.pbits == 0 )
+        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+
+    if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
+                                         f_rng, p_rng ) ) != 0 )
+        return( ret );
+
+    ret = mbedtls_ecp_point_write_binary( &ctx->grp, &ctx->Q, point_format,
+                                          olen, buf, blen );
+    if( ret != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
+int mbedtls_ecdh_tls13_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
+                            unsigned char *buf, size_t blen,
+                            int ( *f_rng )( void *, unsigned char *, size_t ),
+                            void *p_rng )
+{
+    ECDH_VALIDATE_RET( ctx != NULL );
+    ECDH_VALIDATE_RET( olen != NULL );
+    ECDH_VALIDATE_RET( buf != NULL );
+    ECDH_VALIDATE_RET( f_rng != NULL );
+
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+    if( ctx-> restart_enabled )
+        return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#endif
+
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+    return( ecdh_tls13_make_params_internal( ctx, olen, ctx->point_format,
+                                             buf, blen, f_rng, p_rng ) );
+#else
+    switch( ctx->var )
+    {
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+        case MBEDTLS_ECDH_VARIANT_EVEREST:
+            return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#endif
+        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
+            return( ecdh_tls13_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
+                                               ctx->point_format, buf, blen,
+                                               f_rng, p_rng ) );
+        default:
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+#endif
+}
+
+/*
+ * Setup context without Everest
+ */
+int mbedtls_ecdh_setup_no_everest( mbedtls_ecdh_context *ctx,
+                                   mbedtls_ecp_group_id grp_id )
+{
+    ECDH_VALIDATE_RET( ctx != NULL );
+
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+    return( ecdh_setup_internal( ctx, grp_id ) );
+#else
+    ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
+    ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
+    ctx->grp_id = grp_id;
+    ecdh_init_internal( &ctx->ctx.mbed_ecdh );
+    return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
+#endif
+}
+
+static int ecdh_tls13_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
+                                            const unsigned char *buf,
+                                            size_t buf_len )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *p = buf;
+    size_t data_len;
+
+    if( buf_len < 3 )
+        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+
+    data_len = MBEDTLS_GET_UINT16_BE( p, 0 );
+    p += 2;
+
+    if( data_len < 1 || data_len != ( buf_len - 2 ) )
+        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+
+    if( ( ret = mbedtls_ecp_point_read_binary( &ctx->grp,
+                                               &ctx->Qp, p, data_len ) ) != 0)
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Parse and import the client's TLS 1.3 public value
+ */
+int mbedtls_ecdh_tls13_read_public( mbedtls_ecdh_context *ctx,
+                                    const unsigned char *buf,
+                                    size_t buf_len )
+{
+    ECDH_VALIDATE_RET( ctx != NULL );
+    ECDH_VALIDATE_RET( buf != NULL );
+
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+    return( ecdh_tls13_read_public_internal( ctx, buf, buf_len ) );
+#else
+    switch( ctx->var )
+    {
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+        case MBEDTLS_ECDH_VARIANT_EVEREST:
+            return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#endif
+        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
+            return( ecdh_tls13_read_public_internal( &ctx->ctx.mbed_ecdh,
+                                                     buf, buf_len ) );
+        default:
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+#endif
+}
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+
 #endif /* MBEDTLS_ECDH_C */
diff --git a/library/ecdh_misc.h b/library/ecdh_misc.h
new file mode 100644
index 0000000..d0f338a
--- /dev/null
+++ b/library/ecdh_misc.h
@@ -0,0 +1,57 @@
+/**
+ * \file ecdh_misc.h
+ *
+ * \brief Internal functions shared by the ECDH module
+ */
+/*
+ *  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_ECDH_MISC_H)
+#define MBEDTLS_ECDH_MISC_H
+
+#include "mbedtls/ecdh.h"
+#include "mbedtls/ecp.h"
+
+#if defined(MBEDTLS_ECDH_C)
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
+
+/*
+ * Setup context without Everest
+ */
+int mbedtls_ecdh_setup_no_everest( mbedtls_ecdh_context *ctx,
+                                   mbedtls_ecp_group_id grp_id );
+
+/*
+ * TLS 1.3 version of mbedtls_ecdh_make_params
+ */
+int mbedtls_ecdh_tls13_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
+                                    unsigned char *buf, size_t buf_len,
+                                    int ( *f_rng )( void *, unsigned char *, size_t ),
+                                    void *p_rng );
+
+/*
+ * TLS 1.3 version of mbedtls_ecdh_read_public
+ */
+int mbedtls_ecdh_tls13_read_public( mbedtls_ecdh_context *ctx,
+                                    const unsigned char *buf,
+                                    size_t buf_len );
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+
+#endif /* MBEDTLS_ECDH_C */
+
+#endif /* !MBEDTLS_ECDH_MISC_H */
diff --git a/library/gcm.c b/library/gcm.c
index 910646b..6d62564 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -431,7 +431,7 @@
     unsigned char ectr[16];
 
     if( output_size < input_length )
-        return( MBEDTLS_ERR_GCM_BAD_INPUT );
+        return( MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL );
     GCM_VALIDATE_RET( output_length != NULL );
     *output_length = input_length;
 
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 95a9427..3670071 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -201,6 +201,8 @@
 
         case MBEDTLS_ERR_GCM_AUTH_FAILED:
             return( PSA_ERROR_INVALID_SIGNATURE );
+        case MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL:
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
         case MBEDTLS_ERR_GCM_BAD_INPUT:
             return( PSA_ERROR_INVALID_ARGUMENT );
 
@@ -3615,6 +3617,51 @@
 /* AEAD */
 /****************************************************************/
 
+/* Helper function to get the base algorithm from its variants. */
+static psa_algorithm_t psa_aead_get_base_algorithm( psa_algorithm_t alg )
+{
+    return PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG( alg );
+}
+
+/* Helper function to perform common nonce length checks. */
+static psa_status_t psa_aead_check_nonce_length( psa_algorithm_t alg,
+                                                 size_t nonce_length )
+{
+    psa_algorithm_t base_alg = psa_aead_get_base_algorithm( alg );
+
+    switch(base_alg)
+    {
+#if defined(PSA_WANT_ALG_GCM)
+        case PSA_ALG_GCM:
+            /* Not checking max nonce size here as GCM spec allows almost
+            * arbitrarily large nonces. Please note that we do not generally
+            * recommend the usage of nonces of greater length than
+            * PSA_AEAD_NONCE_MAX_SIZE, as large nonces are hashed to a shorter
+            * size, which can then lead to collisions if you encrypt a very
+            * large number of messages.*/
+            if( nonce_length != 0 )
+                return( PSA_SUCCESS );
+            break;
+#endif /* PSA_WANT_ALG_GCM */
+#if defined(PSA_WANT_ALG_CCM)
+        case PSA_ALG_CCM:
+            if( nonce_length >= 7 && nonce_length <= 13 )
+                return( PSA_SUCCESS );
+            break;
+#endif /* PSA_WANT_ALG_CCM */
+#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
+        case PSA_ALG_CHACHA20_POLY1305:
+            if( nonce_length == 12 )
+                return( PSA_SUCCESS );
+            break;
+#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
+        default:
+            break;
+    }
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
 psa_status_t psa_aead_encrypt( mbedtls_svc_key_id_t key,
                                psa_algorithm_t alg,
                                const uint8_t *nonce,
@@ -3644,6 +3691,10 @@
       .core = slot->attr
     };
 
+    status = psa_aead_check_nonce_length( alg, nonce_length );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
     status = psa_driver_wrapper_aead_encrypt(
         &attributes, slot->key.data, slot->key.bytes,
         alg,
@@ -3655,6 +3706,7 @@
     if( status != PSA_SUCCESS && ciphertext_size != 0 )
         memset( ciphertext, 0, ciphertext_size );
 
+exit:
     psa_unlock_key_slot( slot );
 
     return( status );
@@ -3689,6 +3741,10 @@
       .core = slot->attr
     };
 
+    status = psa_aead_check_nonce_length( alg, nonce_length );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
     status = psa_driver_wrapper_aead_decrypt(
         &attributes, slot->key.data, slot->key.bytes,
         alg,
@@ -3700,11 +3756,474 @@
     if( status != PSA_SUCCESS && plaintext_size != 0 )
         memset( plaintext, 0, plaintext_size );
 
+exit:
     psa_unlock_key_slot( slot );
 
     return( status );
 }
 
+/* Set the key for a multipart authenticated operation. */
+static psa_status_t psa_aead_setup( psa_aead_operation_t *operation,
+                                    int is_encrypt,
+                                    mbedtls_svc_key_id_t key,
+                                    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot = NULL;
+    psa_key_usage_t key_usage = 0;
+
+    if( !PSA_ALG_IS_AEAD( alg ) || PSA_ALG_IS_WILDCARD( alg ) )
+    {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    if( operation->id != 0 )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if( operation->nonce_set || operation->lengths_set ||
+        operation->ad_started || operation->body_started )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if( is_encrypt )
+        key_usage = PSA_KEY_USAGE_ENCRYPT;
+    else
+        key_usage = PSA_KEY_USAGE_DECRYPT;
+
+    status = psa_get_and_lock_key_slot_with_policy( key, &slot, key_usage,
+                                                    alg );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    psa_key_attributes_t attributes = {
+        .core = slot->attr
+    };
+
+    if( is_encrypt )
+        status = psa_driver_wrapper_aead_encrypt_setup( operation,
+                                                        &attributes,
+                                                        slot->key.data,
+                                                        slot->key.bytes,
+                                                        alg );
+    else
+        status = psa_driver_wrapper_aead_decrypt_setup( operation,
+                                                        &attributes,
+                                                        slot->key.data,
+                                                        slot->key.bytes,
+                                                        alg );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    operation->key_type = psa_get_key_type( &attributes );
+
+exit:
+    unlock_status = psa_unlock_key_slot( slot );
+
+    if( status == PSA_SUCCESS )
+    {
+        status = unlock_status;
+        operation->alg = psa_aead_get_base_algorithm( alg );
+        operation->is_encrypt = is_encrypt;
+    }
+    else
+        psa_aead_abort( operation );
+
+    return( status );
+}
+
+/* Set the key for a multipart authenticated encryption operation. */
+psa_status_t psa_aead_encrypt_setup( psa_aead_operation_t *operation,
+                                     mbedtls_svc_key_id_t key,
+                                     psa_algorithm_t alg )
+{
+    return( psa_aead_setup( operation, 1, key, alg ) );
+}
+
+/* Set the key for a multipart authenticated decryption operation. */
+psa_status_t psa_aead_decrypt_setup( psa_aead_operation_t *operation,
+                                     mbedtls_svc_key_id_t key,
+                                     psa_algorithm_t alg )
+{
+    return( psa_aead_setup( operation, 0, key, alg ) );
+}
+
+/* Generate a random nonce / IV for multipart AEAD operation */
+psa_status_t psa_aead_generate_nonce( psa_aead_operation_t *operation,
+                                      uint8_t *nonce,
+                                      size_t nonce_size,
+                                      size_t *nonce_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t required_nonce_size;
+
+    *nonce_length = 0;
+
+    if( operation->id == 0 )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if( operation->nonce_set || !operation->is_encrypt )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    required_nonce_size = PSA_AEAD_NONCE_LENGTH( operation->key_type,
+                                                 operation->alg );
+    if( nonce_size < required_nonce_size )
+    {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+    status = psa_generate_random( nonce, required_nonce_size );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    status = psa_aead_set_nonce( operation, nonce, required_nonce_size );
+
+exit:
+    if( status == PSA_SUCCESS )
+        *nonce_length = required_nonce_size;
+    else
+        psa_aead_abort( operation );
+
+    return( status );
+}
+
+/* Set the nonce for a multipart authenticated encryption or decryption
+   operation.*/
+psa_status_t psa_aead_set_nonce( psa_aead_operation_t *operation,
+                                 const uint8_t *nonce,
+                                 size_t nonce_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if( operation->id == 0 )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if( operation->nonce_set )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    status = psa_aead_check_nonce_length( operation->alg, nonce_length );
+    if( status != PSA_SUCCESS )
+    {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_aead_set_nonce( operation, nonce,
+                                                nonce_length );
+
+exit:
+    if( status == PSA_SUCCESS )
+        operation->nonce_set = 1;
+    else
+        psa_aead_abort( operation );
+
+    return( status );
+}
+
+/* Declare the lengths of the message and additional data for multipart AEAD. */
+psa_status_t psa_aead_set_lengths( psa_aead_operation_t *operation,
+                                   size_t ad_length,
+                                   size_t plaintext_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if( operation->id == 0 )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if( operation->lengths_set || operation->ad_started ||
+        operation->body_started )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    switch(operation->alg)
+    {
+#if defined(PSA_WANT_ALG_GCM)
+        case PSA_ALG_GCM:
+            /* Lengths can only be too large for GCM if size_t is bigger than 32
+            * bits. Without the guard this code will generate warnings on 32bit
+            * builds. */
+#if SIZE_MAX > UINT32_MAX
+            if( (( uint64_t ) ad_length ) >> 61 != 0 ||
+                (( uint64_t ) plaintext_length ) > 0xFFFFFFFE0ull )
+            {
+                status = PSA_ERROR_INVALID_ARGUMENT;
+                goto exit;
+            }
+#endif
+            break;
+#endif /* PSA_WANT_ALG_GCM */
+#if defined(PSA_WANT_ALG_CCM)
+        case PSA_ALG_CCM:
+            if( ad_length > 0xFF00 )
+            {
+                status = PSA_ERROR_INVALID_ARGUMENT;
+                goto exit;
+            }
+            break;
+#endif /* PSA_WANT_ALG_CCM */
+#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
+        case PSA_ALG_CHACHA20_POLY1305:
+            /* No length restrictions for ChaChaPoly. */
+            break;
+#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
+        default:
+            break;
+    }
+
+    status = psa_driver_wrapper_aead_set_lengths( operation, ad_length,
+                                                  plaintext_length );
+
+exit:
+    if( status == PSA_SUCCESS )
+    {
+        operation->ad_remaining = ad_length;
+        operation->body_remaining = plaintext_length;
+        operation->lengths_set = 1;
+    }
+    else
+        psa_aead_abort( operation );
+
+    return( status );
+}
+
+/* Pass additional data to an active multipart AEAD operation. */
+psa_status_t psa_aead_update_ad( psa_aead_operation_t *operation,
+                                 const uint8_t *input,
+                                 size_t input_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if( operation->id == 0 )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if( !operation->nonce_set || operation->body_started )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if( operation->lengths_set )
+    {
+        if( operation->ad_remaining < input_length )
+        {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            goto exit;
+        }
+
+        operation->ad_remaining -= input_length;
+    }
+
+    status = psa_driver_wrapper_aead_update_ad( operation, input,
+                                                input_length );
+
+exit:
+    if( status == PSA_SUCCESS )
+        operation->ad_started = 1;
+    else
+        psa_aead_abort( operation );
+
+    return( status );
+}
+
+/* Encrypt or decrypt a message fragment in an active multipart AEAD
+   operation.*/
+psa_status_t psa_aead_update( psa_aead_operation_t *operation,
+                              const uint8_t *input,
+                              size_t input_length,
+                              uint8_t *output,
+                              size_t output_size,
+                              size_t *output_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    *output_length = 0;
+
+    if( operation->id == 0 )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if( !operation->nonce_set )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if( operation->lengths_set )
+    {
+        /* Additional data length was supplied, but not all the additional
+           data was supplied.*/
+        if( operation->ad_remaining != 0 )
+        {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            goto exit;
+        }
+
+        /* Too much data provided. */
+        if( operation->body_remaining < input_length )
+        {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            goto exit;
+        }
+
+        operation->body_remaining -= input_length;
+    }
+
+    status = psa_driver_wrapper_aead_update( operation, input, input_length,
+                                             output, output_size,
+                                             output_length );
+
+exit:
+    if( status == PSA_SUCCESS )
+        operation->body_started = 1;
+    else
+        psa_aead_abort( operation );
+
+    return( status );
+}
+
+static psa_status_t psa_aead_final_checks( const psa_aead_operation_t *operation )
+{
+    if( operation->id == 0 || !operation->nonce_set )
+        return( PSA_ERROR_BAD_STATE );
+
+    if( operation->lengths_set && ( operation->ad_remaining != 0 ||
+                                   operation->body_remaining != 0 ) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
+    return( PSA_SUCCESS );
+}
+
+/* Finish encrypting a message in a multipart AEAD operation. */
+psa_status_t psa_aead_finish( psa_aead_operation_t *operation,
+                              uint8_t *ciphertext,
+                              size_t ciphertext_size,
+                              size_t *ciphertext_length,
+                              uint8_t *tag,
+                              size_t tag_size,
+                              size_t *tag_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    *ciphertext_length = 0;
+    *tag_length = tag_size;
+
+    status = psa_aead_final_checks( operation );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    if( !operation->is_encrypt )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_aead_finish( operation, ciphertext,
+                                             ciphertext_size,
+                                             ciphertext_length,
+                                             tag, tag_size, tag_length );
+
+exit:
+    /* In case the operation fails and the user fails to check for failure or
+     * the zero tag size, make sure the tag is set to something implausible.
+     * Even if the operation succeeds, make sure we clear the rest of the
+     * buffer to prevent potential leakage of anything previously placed in
+     * the same buffer.*/
+    if( tag != NULL )
+    {
+        if( status != PSA_SUCCESS )
+            memset( tag, '!', tag_size );
+        else if( *tag_length < tag_size )
+            memset( tag + *tag_length, '!', ( tag_size - *tag_length ) );
+    }
+
+    psa_aead_abort( operation );
+
+    return( status );
+}
+
+/* Finish authenticating and decrypting a message in a multipart AEAD
+   operation.*/
+psa_status_t psa_aead_verify( psa_aead_operation_t *operation,
+                              uint8_t *plaintext,
+                              size_t plaintext_size,
+                              size_t *plaintext_length,
+                              const uint8_t *tag,
+                              size_t tag_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    *plaintext_length = 0;
+
+    status = psa_aead_final_checks( operation );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    if( operation->is_encrypt )
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_aead_verify( operation, plaintext,
+                                             plaintext_size,
+                                             plaintext_length,
+                                             tag, tag_length );
+
+exit:
+    psa_aead_abort( operation );
+
+    return( status );
+}
+
+/* Abort an AEAD operation. */
+psa_status_t psa_aead_abort( psa_aead_operation_t *operation )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if( operation->id == 0 )
+    {
+        /* 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 );
+    }
+
+    status = psa_driver_wrapper_aead_abort( operation );
+
+    memset( operation, 0, sizeof( *operation ) );
+
+    return( status );
+}
+
 /****************************************************************/
 /* Generators */
 /****************************************************************/
@@ -5193,6 +5712,10 @@
     if( psa_get_key_bits( attributes ) == 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
+    /* Reject any attempt to create a public key. */
+    if( PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->core.type) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
     status = psa_start_key_creation( PSA_KEY_CREATION_GENERATE, attributes,
                                      &slot, &driver );
     if( status != PSA_SUCCESS )
diff --git a/library/psa_crypto_aead.c b/library/psa_crypto_aead.c
index 356679c..c7f7352 100644
--- a/library/psa_crypto_aead.c
+++ b/library/psa_crypto_aead.c
@@ -25,58 +25,24 @@
 #include "psa_crypto_aead.h"
 #include "psa_crypto_core.h"
 
+#include <string.h>
+#include "mbedtls/platform.h"
+#if !defined(MBEDTLS_PLATFORM_C)
+#define mbedtls_calloc calloc
+#define mbedtls_free   free
+#endif
+
 #include "mbedtls/ccm.h"
 #include "mbedtls/chachapoly.h"
 #include "mbedtls/cipher.h"
 #include "mbedtls/gcm.h"
-
-typedef struct
-{
-    union
-    {
-        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
-        mbedtls_ccm_context ccm;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
-        mbedtls_gcm_context gcm;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
-        mbedtls_chachapoly_context chachapoly;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
-    } ctx;
-    psa_algorithm_t core_alg;
-    uint8_t tag_length;
-} aead_operation_t;
-
-#define AEAD_OPERATION_INIT {{0}, 0, 0}
-
-static void psa_aead_abort_internal( aead_operation_t *operation )
-{
-    switch( operation->core_alg )
-    {
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
-        case PSA_ALG_CCM:
-            mbedtls_ccm_free( &operation->ctx.ccm );
-            break;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
-        case PSA_ALG_GCM:
-            mbedtls_gcm_free( &operation->ctx.gcm );
-            break;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
-        case PSA_ALG_CHACHA20_POLY1305:
-            mbedtls_chachapoly_free( &operation->ctx.chachapoly );
-            break;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
-    }
-}
+#include "mbedtls/error.h"
 
 static psa_status_t psa_aead_setup(
-    aead_operation_t *operation,
+    mbedtls_psa_aead_operation_t *operation,
     const psa_key_attributes_t *attributes,
     const uint8_t *key_buffer,
+    size_t key_buffer_size,
     psa_algorithm_t alg )
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
@@ -85,6 +51,8 @@
     mbedtls_cipher_id_t cipher_id;
     size_t full_tag_length = 0;
 
+    ( void ) key_buffer_size;
+
     key_bits = attributes->core.bits;
 
     cipher_info = mbedtls_cipher_info_from_psa( alg,
@@ -97,7 +65,7 @@
     {
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
         case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ):
-            operation->core_alg = PSA_ALG_CCM;
+            operation->alg = PSA_ALG_CCM;
             full_tag_length = 16;
             /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
              * The call to mbedtls_ccm_encrypt_and_tag or
@@ -116,7 +84,7 @@
 
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
         case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ):
-            operation->core_alg = PSA_ALG_GCM;
+            operation->alg = PSA_ALG_GCM;
             full_tag_length = 16;
             /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
              * The call to mbedtls_gcm_crypt_and_tag or
@@ -135,7 +103,7 @@
 
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
         case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ):
-            operation->core_alg = PSA_ALG_CHACHA20_POLY1305;
+            operation->alg = PSA_ALG_CHACHA20_POLY1305;
             full_tag_length = 16;
             /* We only support the default tag length. */
             if( alg != PSA_ALG_CHACHA20_POLY1305 )
@@ -159,7 +127,9 @@
         > full_tag_length )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
-    operation->tag_length = PSA_AEAD_TAG_LENGTH( attributes->core.type,
+    operation->key_type = psa_get_key_type( attributes );
+
+    operation->tag_length = PSA_AEAD_TAG_LENGTH( operation->key_type,
                                                  key_bits,
                                                  alg );
 
@@ -176,11 +146,12 @@
     uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length )
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    aead_operation_t operation = AEAD_OPERATION_INIT;
+    mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
     uint8_t *tag;
-    (void) key_buffer_size;
 
-    status = psa_aead_setup( &operation, attributes, key_buffer, alg );
+    status = psa_aead_setup( &operation, attributes, key_buffer,
+                             key_buffer_size, alg );
+
     if( status != PSA_SUCCESS )
         goto exit;
 
@@ -194,7 +165,7 @@
     tag = ciphertext + plaintext_length;
 
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
-    if( operation.core_alg == PSA_ALG_CCM )
+    if( operation.alg == PSA_ALG_CCM )
     {
         status = mbedtls_to_psa_error(
             mbedtls_ccm_encrypt_and_tag( &operation.ctx.ccm,
@@ -208,7 +179,7 @@
     else
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
-    if( operation.core_alg == PSA_ALG_GCM )
+    if( operation.alg == PSA_ALG_GCM )
     {
         status = mbedtls_to_psa_error(
             mbedtls_gcm_crypt_and_tag( &operation.ctx.gcm,
@@ -222,9 +193,9 @@
     else
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
-    if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
+    if( operation.alg == PSA_ALG_CHACHA20_POLY1305 )
     {
-        if( nonce_length != 12 || operation.tag_length != 16 )
+        if( operation.tag_length != 16 )
         {
             status = PSA_ERROR_NOT_SUPPORTED;
             goto exit;
@@ -250,7 +221,7 @@
         *ciphertext_length = plaintext_length + operation.tag_length;
 
 exit:
-    psa_aead_abort_internal( &operation );
+    mbedtls_psa_aead_abort( &operation );
 
     return( status );
 }
@@ -286,11 +257,12 @@
     uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length )
 {
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    aead_operation_t operation = AEAD_OPERATION_INIT;
+    mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
     const uint8_t *tag = NULL;
-    (void) key_buffer_size;
 
-    status = psa_aead_setup( &operation, attributes, key_buffer, alg );
+    status = psa_aead_setup( &operation, attributes, key_buffer,
+                             key_buffer_size, alg );
+
     if( status != PSA_SUCCESS )
         goto exit;
 
@@ -301,7 +273,7 @@
         goto exit;
 
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
-    if( operation.core_alg == PSA_ALG_CCM )
+    if( operation.alg == PSA_ALG_CCM )
     {
         status = mbedtls_to_psa_error(
             mbedtls_ccm_auth_decrypt( &operation.ctx.ccm,
@@ -315,7 +287,7 @@
     else
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
-    if( operation.core_alg == PSA_ALG_GCM )
+    if( operation.alg == PSA_ALG_GCM )
     {
         status = mbedtls_to_psa_error(
             mbedtls_gcm_auth_decrypt( &operation.ctx.gcm,
@@ -329,9 +301,9 @@
     else
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
-    if( operation.core_alg == PSA_ALG_CHACHA20_POLY1305 )
+    if( operation.alg == PSA_ALG_CHACHA20_POLY1305 )
     {
-        if( nonce_length != 12 || operation.tag_length != 16 )
+        if( operation.tag_length != 16 )
         {
             status = PSA_ERROR_NOT_SUPPORTED;
             goto exit;
@@ -356,12 +328,314 @@
         *plaintext_length = ciphertext_length - operation.tag_length;
 
 exit:
-    psa_aead_abort_internal( &operation );
+    mbedtls_psa_aead_abort( &operation );
 
     if( status == PSA_SUCCESS )
         *plaintext_length = ciphertext_length - operation.tag_length;
     return( status );
 }
 
+/* Set the key and algorithm for a multipart authenticated encryption
+ * operation. */
+psa_status_t mbedtls_psa_aead_encrypt_setup(
+    mbedtls_psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+    if( operation->alg == PSA_ALG_CCM )
+    {
+        return( PSA_ERROR_NOT_SUPPORTED );
+    }
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+
+    status = psa_aead_setup( operation, attributes, key_buffer,
+                             key_buffer_size, alg );
+
+    if( status == PSA_SUCCESS )
+        operation->is_encrypt = 1;
+
+    return ( status );
+}
+
+/* Set the key and algorithm for a multipart authenticated decryption
+ * operation. */
+psa_status_t mbedtls_psa_aead_decrypt_setup(
+    mbedtls_psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+    if( operation->alg == PSA_ALG_CCM )
+    {
+        return( PSA_ERROR_NOT_SUPPORTED );
+    }
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+
+    status = psa_aead_setup( operation, attributes, key_buffer,
+                             key_buffer_size, alg );
+
+    if( status == PSA_SUCCESS )
+        operation->is_encrypt = 0;
+
+    return ( status );
+}
+
+/* Set a nonce for the multipart AEAD operation*/
+psa_status_t mbedtls_psa_aead_set_nonce(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *nonce,
+    size_t nonce_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+    if( operation->alg == PSA_ALG_GCM )
+    {
+        status = mbedtls_to_psa_error(
+                 mbedtls_gcm_starts( &operation->ctx.gcm,
+                                     operation->is_encrypt ?
+                                     MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT,
+                                     nonce,
+                                     nonce_length ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+    if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
+    {
+        /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to
+         * allocate a buffer in the operation, copy the nonce to it and pad
+         * it, so for now check the nonce is 12 bytes, as
+         * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the
+         * passed in buffer. */
+        if( nonce_length != 12 )
+        {
+            return( PSA_ERROR_INVALID_ARGUMENT );
+        }
+
+        status = mbedtls_to_psa_error(
+           mbedtls_chachapoly_starts( &operation->ctx.chachapoly,
+                                      nonce,
+                                      operation->is_encrypt ?
+                                      MBEDTLS_CHACHAPOLY_ENCRYPT :
+                                      MBEDTLS_CHACHAPOLY_DECRYPT ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    {
+        ( void ) nonce;
+
+        return ( PSA_ERROR_NOT_SUPPORTED );
+    }
+
+    return( status );
+}
+
+ /* Declare the lengths of the message and additional data for AEAD. */
+psa_status_t mbedtls_psa_aead_set_lengths(
+    mbedtls_psa_aead_operation_t *operation,
+    size_t ad_length,
+    size_t plaintext_length )
+{
+    /* Nothing here yet, work is currently done in PSA Core, however support
+     * for CCM will require this function. */
+    ( void ) operation;
+    ( void ) ad_length;
+    ( void ) plaintext_length;
+
+    return ( PSA_SUCCESS );
+}
+
+/* Pass additional data to an active multipart AEAD operation. */
+psa_status_t mbedtls_psa_aead_update_ad(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+    if( operation->alg == PSA_ALG_GCM )
+    {
+        status = mbedtls_to_psa_error(
+            mbedtls_gcm_update_ad( &operation->ctx.gcm, input, input_length ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+    if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
+    {
+        status = mbedtls_to_psa_error(
+           mbedtls_chachapoly_update_aad( &operation->ctx.chachapoly,
+                                          input,
+                                          input_length ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    {
+        ( void ) operation;
+        ( void ) input;
+        ( void ) input_length;
+
+        return ( PSA_ERROR_NOT_SUPPORTED );
+    }
+
+    return ( status );
+}
+
+/* Encrypt or decrypt a message fragment in an active multipart AEAD
+ * operation.*/
+psa_status_t mbedtls_psa_aead_update(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length )
+{
+    size_t update_output_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    update_output_length = input_length;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+    if( operation->alg == PSA_ALG_GCM )
+    {
+        status =  mbedtls_to_psa_error(
+            mbedtls_gcm_update( &operation->ctx.gcm,
+                                input, input_length,
+                                output, output_size,
+                                &update_output_length ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+    if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
+    {
+        if( output_size < input_length )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+        status = mbedtls_to_psa_error(
+           mbedtls_chachapoly_update( &operation->ctx.chachapoly,
+                                      input_length,
+                                      input,
+                                      output ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    {
+        ( void ) input;
+        ( void ) input_length;
+
+        return ( PSA_ERROR_NOT_SUPPORTED );
+    }
+
+    if( status == PSA_SUCCESS )
+        *output_length = update_output_length;
+
+    return( status );
+}
+
+/* Finish encrypting a message in a multipart AEAD operation. */
+psa_status_t mbedtls_psa_aead_finish(
+    mbedtls_psa_aead_operation_t *operation,
+    uint8_t *ciphertext,
+    size_t ciphertext_size,
+    size_t *ciphertext_length,
+    uint8_t *tag,
+    size_t tag_size,
+    size_t *tag_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t finish_output_size = 0;
+
+    if( tag_size < operation->tag_length )
+        return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+    if( operation->alg == PSA_ALG_GCM )
+    {
+        status =  mbedtls_to_psa_error(
+            mbedtls_gcm_finish( &operation->ctx.gcm,
+                                ciphertext, ciphertext_size, ciphertext_length,
+                                tag, operation->tag_length ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+    if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
+    {
+        /* Belt and braces. Although the above tag_size check should have
+         * already done this, if we later start supporting smaller tag sizes
+         * for chachapoly, then passing a tag buffer smaller than 16 into here
+         * could cause a buffer overflow, so better safe than sorry. */
+        if( tag_size < 16 )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+        status = mbedtls_to_psa_error(
+            mbedtls_chachapoly_finish( &operation->ctx.chachapoly,
+                                       tag ) );
+    }
+    else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    {
+        ( void ) ciphertext;
+        ( void ) ciphertext_size;
+        ( void ) ciphertext_length;
+        ( void ) tag;
+        ( void ) tag_size;
+        ( void ) tag_length;
+
+        return ( PSA_ERROR_NOT_SUPPORTED );
+    }
+
+    if( status == PSA_SUCCESS )
+    {
+        /* This will be zero for all supported algorithms currently, but left
+         * here for future support. */
+        *ciphertext_length = finish_output_size;
+        *tag_length = operation->tag_length;
+    }
+
+    return ( status );
+}
+
+/* Abort an AEAD operation */
+psa_status_t mbedtls_psa_aead_abort(
+   mbedtls_psa_aead_operation_t *operation )
+{
+    switch( operation->alg )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+        case PSA_ALG_CCM:
+            mbedtls_ccm_free( &operation->ctx.ccm );
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+        case PSA_ALG_GCM:
+            mbedtls_gcm_free( &operation->ctx.gcm );
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+        case PSA_ALG_CHACHA20_POLY1305:
+            mbedtls_chachapoly_free( &operation->ctx.chachapoly );
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    }
+
+    operation->is_encrypt = 0;
+
+    return( PSA_SUCCESS );
+}
+
 #endif /* MBEDTLS_PSA_CRYPTO_C */
 
diff --git a/library/psa_crypto_aead.h b/library/psa_crypto_aead.h
index aab0f83..e82e1cc 100644
--- a/library/psa_crypto_aead.h
+++ b/library/psa_crypto_aead.h
@@ -148,4 +148,364 @@
     const uint8_t *ciphertext, size_t ciphertext_length,
     uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length );
 
+/** Set the key for a multipart authenticated encryption operation.
+ *
+ *  \note The signature of this function is that of a PSA driver
+ *       aead_encrypt_setup entry point. This function behaves as an
+ *       aead_encrypt_setup entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * If an error occurs at any step after a call to
+ * mbedtls_psa_aead_encrypt_setup(), the operation is reset by the PSA core by a
+ * call to mbedtls_psa_aead_abort(). The PSA core may call
+ * mbedtls_psa_aead_abort() at any time after the operation has been
+ * initialized, and is required to when the operation is no longer needed.
+ *
+ * \param[in,out] operation     The operation object to set up. It must have
+ *                              been initialized as per the documentation for
+ *                              #mbedtls_psa_aead_operation_t and not yet in
+ *                              use.
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param      key_buffer_size  Size of the \p key_buffer buffer in bytes.
+                                It must be consistent with the size in bits
+                                recorded in \p attributes.
+ * \param alg                   The AEAD algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_AEAD(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         An invalid block length was supplied.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         Failed to allocate memory for key material
+ */
+psa_status_t mbedtls_psa_aead_encrypt_setup(
+    mbedtls_psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+/** Set the key for a multipart authenticated decryption operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       aead_decrypt_setup entry point. This function behaves as an
+ *       aead_decrypt_setup entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * If an error occurs at any step after a call to
+ * mbedtls_psa_aead_decrypt_setup(), the PSA core resets the operation by a
+ * call to mbedtls_psa_aead_abort(). The PSA core may call
+ * mbedtls_psa_aead_abort() at any time after the operation has been
+ * initialized, and is required to when the operation is no longer needed.
+ *
+ * \param[in,out] operation     The operation object to set up. It must have
+ *                              been initialized as per the documentation for
+ *                              #mbedtls_psa_aead_operation_t and not yet in
+ *                              use.
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param      key_buffer_size  Size of the \p key_buffer buffer in bytes.
+                                It must be consistent with the size in bits
+                                recorded in \p attributes.
+ * \param alg                   The AEAD algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_AEAD(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         An invalid block length was supplied.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         Failed to allocate memory for key material
+ */
+psa_status_t mbedtls_psa_aead_decrypt_setup(
+    mbedtls_psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+/** Set the nonce for an authenticated encryption or decryption operation.
+ *
+ * \note The signature of this function is that of a PSA driver aead_set_nonce
+ *       entry point. This function behaves as an aead_set_nonce entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * This function sets the nonce for the authenticated
+ * encryption or decryption operation.
+ *
+ * The PSA core calls mbedtls_psa_aead_encrypt_setup() or
+ * mbedtls_psa_aead_decrypt_setup() before calling this function.
+ *
+ * If this function returns an error status, the PSA core will call
+ * mbedtls_psa_aead_abort().
+ *
+ * \param[in,out] operation     Active AEAD operation.
+ * \param[in] nonce             Buffer containing the nonce to use.
+ * \param nonce_length          Size of the nonce in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The size of \p nonce is not acceptable for the chosen algorithm.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         Algorithm previously set is not supported in this configuration of
+ *         the library.
+ */
+psa_status_t mbedtls_psa_aead_set_nonce(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *nonce,
+    size_t nonce_length );
+
+/** Declare the lengths of the message and additional data for AEAD.
+ *
+ * \note The signature of this function is that of a PSA driver aead_set_lengths
+ *       entry point. This function behaves as an aead_set_lengths entry point
+ *       as defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * The PSA core calls this function before calling mbedtls_psa_aead_update_ad()
+ * or mbedtls_psa_aead_update() if the algorithm for the operation requires it.
+ * If the algorithm does not require it, calling this function is optional, but
+ * if this function is called then the implementation must enforce the lengths.
+ *
+ * The PSA core may call this function before or after setting the nonce with
+ * mbedtls_psa_aead_set_nonce().
+ *
+ * - For #PSA_ALG_CCM, calling this function is required.
+ * - For the other AEAD algorithms defined in this specification, calling
+ *   this function is not required.
+ *
+ * If this function returns an error status, the PSA core calls
+ * mbedtls_psa_aead_abort().
+ *
+ * \param[in,out] operation     Active AEAD operation.
+ * \param ad_length             Size of the non-encrypted additional
+ *                              authenticated data in bytes.
+ * \param plaintext_length      Size of the plaintext to encrypt in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         At least one of the lengths is not acceptable for the chosen
+ *         algorithm.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         Algorithm previously set is not supported in this configuration of
+ *         the library.
+ */
+psa_status_t mbedtls_psa_aead_set_lengths(
+    mbedtls_psa_aead_operation_t *operation,
+    size_t ad_length,
+    size_t plaintext_length );
+
+/** Pass additional data to an active AEAD operation.
+ *
+ *  \note The signature of this function is that of a PSA driver
+ *       aead_update_ad entry point. This function behaves as an aead_update_ad
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * Additional data is authenticated, but not encrypted.
+ *
+ * The PSA core can call this function multiple times to pass successive
+ * fragments of the additional data. It will not call this function after
+ * passing data to encrypt or decrypt with mbedtls_psa_aead_update().
+ *
+ * Before calling this function, the PSA core will:
+ *    1. Call either mbedtls_psa_aead_encrypt_setup() or
+ *       mbedtls_psa_aead_decrypt_setup().
+ *    2. Set the nonce with mbedtls_psa_aead_set_nonce().
+ *
+ * If this function returns an error status, the PSA core will call
+ * mbedtls_psa_aead_abort().
+ *
+ * \param[in,out] operation     Active AEAD operation.
+ * \param[in] input             Buffer containing the fragment of
+ *                              additional data.
+ * \param input_length          Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         Algorithm previously set is not supported in this configuration of
+ *         the library.
+ */
+psa_status_t mbedtls_psa_aead_update_ad(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+/** Encrypt or decrypt a message fragment in an active AEAD operation.
+ *
+ *  \note The signature of this function is that of a PSA driver
+ *       aead_update entry point. This function behaves as an aead_update entry
+ *       point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * Before calling this function, the PSA core will:
+ *    1. Call either mbedtls_psa_aead_encrypt_setup() or
+ *       mbedtls_psa_aead_decrypt_setup(). The choice of setup function
+ *       determines whether this function encrypts or decrypts its input.
+ *    2. Set the nonce with mbedtls_psa_aead_set_nonce().
+ *    3. Call mbedtls_psa_aead_update_ad() to pass all the additional data.
+ *
+ * If this function returns an error status, the PSA core will call
+ * mbedtls_psa_aead_abort().
+ *
+ * This function does not require the input to be aligned to any
+ * particular block boundary. If the implementation can only process
+ * a whole block at a time, it must consume all the input provided, but
+ * it may delay the end of the corresponding output until a subsequent
+ * call to mbedtls_psa_aead_update(), mbedtls_psa_aead_finish() provides
+ * sufficient input. The amount of data that can be delayed in this way is
+ * bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE.
+ *
+ * \param[in,out] operation     Active AEAD operation.
+ * \param[in] input             Buffer containing the message fragment to
+ *                              encrypt or decrypt.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[out] output           Buffer where the output is to be written.
+ * \param output_size           Size of the \p output buffer in bytes.
+ *                              This must be appropriate for the selected
+ *                                algorithm and key:
+ *                                - A sufficient output size is
+ *                                  #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type,
+ *                                  \c alg, \p input_length) where
+ *                                  \c key_type is the type of key and \c alg is
+ *                                  the algorithm that were used to set up the
+ *                                  operation.
+ *                                - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p
+ *                                  input_length) evaluates to the maximum
+ *                                  output size of any supported AEAD
+ *                                  algorithm.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ *
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ *         #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or
+ *         #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to
+ *         determine the required buffer size.
+ */
+psa_status_t mbedtls_psa_aead_update(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length );
+
+/** Finish encrypting a message in an AEAD operation.
+ *
+ *  \note The signature of this function is that of a PSA driver
+ *       aead_finish entry point. This function behaves as an aead_finish entry
+ *       point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * The operation must have been set up by the PSA core with
+ * mbedtls_psa_aead_encrypt_setup().
+ *
+ * This function finishes the authentication of the additional data
+ * formed by concatenating the inputs passed to preceding calls to
+ * mbedtls_psa_aead_update_ad() with the plaintext formed by concatenating the
+ * inputs passed to preceding calls to mbedtls_psa_aead_update().
+ *
+ * This function has two output buffers:
+ * - \p ciphertext contains trailing ciphertext that was buffered from
+ *   preceding calls to mbedtls_psa_aead_update().
+ * - \p tag contains the authentication tag.
+ *
+ * Whether or not this function returns successfuly, the PSA core subsequently
+ * calls mbedtls_psa_aead_abort() to deactivate the operation.
+ *
+ * \param[in,out] operation     Active AEAD operation.
+ * \param[out] ciphertext       Buffer where the last part of the ciphertext
+ *                              is to be written.
+ * \param ciphertext_size       Size of the \p ciphertext buffer in bytes.
+ *                              This must be appropriate for the selected
+ *                              algorithm and key:
+ *                              - A sufficient output size is
+ *                                #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type,
+ *                                \c alg) where \c key_type is the type of key
+ *                                and \c alg is the algorithm that were used to
+ *                                set up the operation.
+ *                              - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to
+ *                                the maximum output size of any supported AEAD
+ *                                algorithm.
+ * \param[out] ciphertext_length On success, the number of bytes of
+ *                              returned ciphertext.
+ * \param[out] tag              Buffer where the authentication tag is
+ *                              to be written.
+ * \param tag_size              Size of the \p tag buffer in bytes.
+ *                              This must be appropriate for the selected
+ *                              algorithm and key:
+ *                              - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c
+ *                                key_type, \c key_bits, \c alg) where
+ *                                \c key_type and \c key_bits are the type and
+ *                                bit-size of the key, and \c alg are the
+ *                                algorithm that were used in the call to
+ *                                mbedtls_psa_aead_encrypt_setup().
+ *                              - #PSA_AEAD_TAG_MAX_SIZE evaluates to the
+ *                                maximum tag size of any supported AEAD
+ *                                algorithm.
+ * \param[out] tag_length       On success, the number of bytes
+ *                              that make up the returned tag.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p tag buffer is too small.
+ *         #PSA_AEAD_TAG_LENGTH(\c key_type, key_bits, \c alg) or
+ *         #PSA_AEAD_TAG_MAX_SIZE can be used to determine the required \p tag
+ *         buffer size.
+ */
+psa_status_t mbedtls_psa_aead_finish(
+    mbedtls_psa_aead_operation_t *operation,
+    uint8_t *ciphertext,
+    size_t ciphertext_size,
+    size_t *ciphertext_length,
+    uint8_t *tag,
+    size_t tag_size,
+    size_t *tag_length );
+
+/** Abort an AEAD operation.
+ *
+ *  \note The signature of this function is that of a PSA driver
+ *       aead_abort entry point. This function behaves as an aead_abort entry
+ *       point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by the PSA core by it calling
+ * mbedtls_psa_aead_encrypt_setup() or mbedtls_psa_aead_decrypt_setup() again.
+ *
+ * The PSA core may call this function any time after the operation object has
+ * been initialized as described in #mbedtls_psa_aead_operation_t.
+ *
+ * In particular, calling mbedtls_psa_aead_abort() after the operation has been
+ * terminated by a call to mbedtls_psa_aead_abort() or
+ * mbedtls_psa_aead_finish() is safe and has no effect.
+ *
+ * \param[in,out] operation     Initialized AEAD operation.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ */
+psa_status_t mbedtls_psa_aead_abort(
+    mbedtls_psa_aead_operation_t *operation );
+
 #endif /* PSA_CRYPTO_AEAD */
diff --git a/library/psa_crypto_driver_wrappers.c b/library/psa_crypto_driver_wrappers.c
index 4123d8a..cfc77fb 100644
--- a/library/psa_crypto_driver_wrappers.c
+++ b/library/psa_crypto_driver_wrappers.c
@@ -1565,6 +1565,381 @@
     }
 }
 
+psa_status_t psa_driver_wrapper_aead_encrypt_setup(
+   psa_aead_operation_t *operation,
+   const psa_key_attributes_t *attributes,
+   const uint8_t *key_buffer, size_t key_buffer_size,
+   psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
+
+    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_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID;
+            status = mbedtls_test_transparent_aead_encrypt_setup(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        attributes, key_buffer, key_buffer_size,
+                        alg );
+
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+            status = mbedtls_psa_aead_encrypt_setup(
+                        &operation->ctx.mbedtls_ctx, attributes,
+                        key_buffer, key_buffer_size,
+                        alg );
+
+            return( status );
+
+        /* Add cases for opaque driver here */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+psa_status_t psa_driver_wrapper_aead_decrypt_setup(
+   psa_aead_operation_t *operation,
+   const psa_key_attributes_t *attributes,
+   const uint8_t *key_buffer, size_t key_buffer_size,
+   psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime );
+
+    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_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID;
+            status = mbedtls_test_transparent_aead_decrypt_setup(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        attributes,
+                        key_buffer, key_buffer_size,
+                        alg );
+
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+            status = mbedtls_psa_aead_decrypt_setup(
+                        &operation->ctx.mbedtls_ctx,
+                        attributes,
+                        key_buffer, key_buffer_size,
+                        alg );
+
+            return( status );
+
+        /* Add cases for opaque driver here */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+psa_status_t psa_driver_wrapper_aead_set_nonce(
+   psa_aead_operation_t *operation,
+   const uint8_t *nonce,
+   size_t nonce_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_aead_set_nonce( &operation->ctx.mbedtls_ctx,
+                                                nonce,
+                                                nonce_length ) );
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_set_nonce(
+                         &operation->ctx.transparent_test_driver_ctx,
+                         nonce, nonce_length ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)nonce;
+    (void)nonce_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+psa_status_t psa_driver_wrapper_aead_set_lengths(
+   psa_aead_operation_t *operation,
+   size_t ad_length,
+   size_t plaintext_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_aead_set_lengths( &operation->ctx.mbedtls_ctx,
+                                                  ad_length,
+                                                  plaintext_length ) );
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_set_lengths(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        ad_length, plaintext_length ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)ad_length;
+    (void)plaintext_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+psa_status_t psa_driver_wrapper_aead_update_ad(
+   psa_aead_operation_t *operation,
+   const uint8_t *input,
+   size_t input_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_aead_update_ad( &operation->ctx.mbedtls_ctx,
+                                                input,
+                                                input_length ) );
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_update_ad(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        input, input_length ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)input;
+    (void)input_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+psa_status_t psa_driver_wrapper_aead_update(
+   psa_aead_operation_t *operation,
+   const uint8_t *input,
+   size_t input_length,
+   uint8_t *output,
+   size_t output_size,
+   size_t *output_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_aead_update( &operation->ctx.mbedtls_ctx,
+                                             input, input_length,
+                                             output, output_size,
+                                             output_length ) );
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_update(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        input, input_length, output, output_size,
+                        output_length ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)input;
+    (void)input_length;
+    (void)output;
+    (void)output_size;
+    (void)output_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+psa_status_t psa_driver_wrapper_aead_finish(
+   psa_aead_operation_t *operation,
+   uint8_t *ciphertext,
+   size_t ciphertext_size,
+   size_t *ciphertext_length,
+   uint8_t *tag,
+   size_t tag_size,
+   size_t *tag_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx,
+                                             ciphertext,
+                                             ciphertext_size,
+                                             ciphertext_length, tag,
+                                             tag_size, tag_length ) );
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_finish(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        ciphertext, ciphertext_size,
+                        ciphertext_length, tag, tag_size, tag_length ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)ciphertext;
+    (void)ciphertext_size;
+    (void)ciphertext_length;
+    (void)tag;
+    (void)tag_size;
+    (void)tag_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+psa_status_t psa_driver_wrapper_aead_verify(
+   psa_aead_operation_t *operation,
+   uint8_t *plaintext,
+   size_t plaintext_size,
+   size_t *plaintext_length,
+   const uint8_t *tag,
+   size_t tag_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            {
+                psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+                uint8_t check_tag[PSA_AEAD_TAG_MAX_SIZE];
+                size_t check_tag_length;
+
+                status = mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx,
+                                                  plaintext,
+                                                  plaintext_size,
+                                                  plaintext_length,
+                                                  check_tag,
+                                                  sizeof( check_tag ),
+                                                  &check_tag_length );
+
+                if( status == PSA_SUCCESS )
+                {
+                    if( tag_length != check_tag_length ||
+                        mbedtls_psa_safer_memcmp( tag, check_tag, tag_length )
+                        != 0 )
+                        status = PSA_ERROR_INVALID_SIGNATURE;
+                }
+
+                mbedtls_platform_zeroize( check_tag, sizeof( check_tag ) );
+
+                return( status );
+            }
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_verify(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        plaintext, plaintext_size,
+                        plaintext_length, tag, tag_length ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)plaintext;
+    (void)plaintext_size;
+    (void)plaintext_length;
+    (void)tag;
+    (void)tag_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+psa_status_t psa_driver_wrapper_aead_abort(
+   psa_aead_operation_t *operation )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_aead_abort( &operation->ctx.mbedtls_ctx ) );
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_abort(
+               &operation->ctx.transparent_test_driver_ctx ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
 
 /*
  * MAC functions
diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h
index c6e3d51..0873b73 100644
--- a/library/psa_crypto_driver_wrappers.h
+++ b/library/psa_crypto_driver_wrappers.h
@@ -219,6 +219,61 @@
     const uint8_t *ciphertext, size_t ciphertext_length,
     uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length );
 
+psa_status_t psa_driver_wrapper_aead_encrypt_setup(
+    psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t psa_driver_wrapper_aead_decrypt_setup(
+    psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t psa_driver_wrapper_aead_set_nonce(
+    psa_aead_operation_t *operation,
+    const uint8_t *nonce,
+    size_t nonce_length );
+
+psa_status_t psa_driver_wrapper_aead_set_lengths(
+    psa_aead_operation_t *operation,
+    size_t ad_length,
+    size_t plaintext_length );
+
+psa_status_t psa_driver_wrapper_aead_update_ad(
+    psa_aead_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+psa_status_t psa_driver_wrapper_aead_update(
+    psa_aead_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length );
+
+psa_status_t psa_driver_wrapper_aead_finish(
+    psa_aead_operation_t *operation,
+    uint8_t *ciphertext,
+    size_t ciphertext_size,
+    size_t *ciphertext_length,
+    uint8_t *tag,
+    size_t tag_size,
+    size_t *tag_length );
+
+psa_status_t psa_driver_wrapper_aead_verify(
+    psa_aead_operation_t *operation,
+    uint8_t *plaintext,
+    size_t plaintext_size,
+    size_t *plaintext_length,
+    const uint8_t *tag,
+    size_t tag_length );
+
+psa_status_t psa_driver_wrapper_aead_abort(
+    psa_aead_operation_t *operation );
+
 /*
  * MAC functions
  */
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
index a5c43b1..a18350e 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -479,7 +479,8 @@
 
 psa_status_t psa_open_key( mbedtls_svc_key_id_t key, psa_key_handle_t *handle )
 {
-#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \
+    defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
     psa_status_t status;
     psa_key_slot_t *slot;
 
@@ -497,11 +498,11 @@
 
     return( psa_unlock_key_slot( slot ) );
 
-#else /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
     (void) key;
     *handle = PSA_KEY_HANDLE_INIT;
     return( PSA_ERROR_NOT_SUPPORTED );
-#endif /* !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
 }
 
 psa_status_t psa_close_key( psa_key_handle_t handle )
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 7035c27..66fb26c 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -307,6 +307,11 @@
       + ( MBEDTLS_SSL_CID_OUT_LEN_MAX ) )
 #endif
 
+#define MBEDTLS_TLS1_3_MD_MAX_SIZE         MBEDTLS_MD_MAX_SIZE
+
+#define MBEDTLS_CLIENT_HELLO_RANDOM_LEN 32
+#define MBEDTLS_SERVER_HELLO_RANDOM_LEN 32
+
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
 /**
  * \brief          Return the maximum fragment length (payload, in bytes) for
@@ -409,6 +414,32 @@
         }                                                                \
     } while( 0 )
 
+/**
+ * \brief        This macro checks if the remaining length in an input buffer is
+ *               greater or equal than a needed length. If it is not the case, it
+ *               returns #MBEDTLS_ERR_SSL_DECODE_ERROR error and pends a
+ *               #MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR alert message.
+ *
+ *               This is a function-like macro. It is guaranteed to evaluate each
+ *               argument exactly once.
+ *
+ * \param cur    Pointer to the current position in the buffer.
+ * \param end    Pointer to one past the end of the buffer.
+ * \param need   Needed length in bytes.
+ *
+ */
+#define MBEDTLS_SSL_CHK_BUF_READ_PTR( cur, end, need )                          \
+    do {                                                                        \
+        if( mbedtls_ssl_chk_buf_ptr( ( cur ), ( end ), ( need ) ) != 0 )        \
+        {                                                                       \
+            MBEDTLS_SSL_DEBUG_MSG( 1,                                           \
+                                   ( "missing input data in %s", __func__ ) );  \
+            MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,   \
+                                          MBEDTLS_ERR_SSL_DECODE_ERROR );       \
+            return( MBEDTLS_ERR_SSL_DECODE_ERROR );                             \
+        }                                                                       \
+    } while( 0 )
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -478,6 +509,27 @@
 };
 typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set;
 
+typedef struct
+{
+    unsigned char binder_key                  [ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+    unsigned char client_early_traffic_secret [ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+    unsigned char early_exporter_master_secret[ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+} mbedtls_ssl_tls1_3_early_secrets;
+
+typedef struct
+{
+    unsigned char client_handshake_traffic_secret[ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+    unsigned char server_handshake_traffic_secret[ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+} mbedtls_ssl_tls1_3_handshake_secrets;
+
+typedef struct
+{
+    unsigned char client_application_traffic_secret_N[ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+    unsigned char server_application_traffic_secret_N[ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+    unsigned char exporter_master_secret             [ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+    unsigned char resumption_master_secret           [ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+} mbedtls_ssl_tls1_3_application_secrets;
+
 /*
  * This structure contains the parameters only needed during handshake.
  */
@@ -486,6 +538,9 @@
     /*
      * Handshake specific crypto variables
      */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
+    int tls1_3_kex_modes; /*!< key exchange modes for TLS 1.3 */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
     defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
@@ -573,8 +628,8 @@
                                               flight being received          */
     mbedtls_ssl_transform *alt_transform_out;   /*!<  Alternative transform for
                                               resending messages             */
-    unsigned char alt_out_ctr[8];       /*!<  Alternative record epoch/counter
-                                              for resending messages         */
+    unsigned char alt_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!<  Alternative record epoch/counter
+                                                                      for resending messages         */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     /* The state of CID configuration in this handshake. */
@@ -649,11 +704,23 @@
     void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int);
     mbedtls_ssl_tls_prf_cb *tls_prf;
 
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
+    uint16_t offered_group_id; /* The NamedGroup value for the group
+                                * that is being used for ephemeral
+                                * key exchange.
+                                *
+                                * On the client: Defaults to the first
+                                * entry in the client's group list,
+                                * but can be overwritten by the HRR. */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+
     mbedtls_ssl_ciphersuite_t const *ciphersuite_info;
 
     size_t pmslen;                      /*!<  premaster length        */
 
-    unsigned char randbytes[64];        /*!<  random bytes            */
+    unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN +
+                            MBEDTLS_SERVER_HELLO_RANDOM_LEN];
+                                        /*!<  random bytes            */
     unsigned char premaster[MBEDTLS_PREMASTER_SIZE];
                                         /*!<  premaster secret        */
 
@@ -665,6 +732,15 @@
     int extensions_present;             /*!< extension presence; Each bitfield
                                              represents an extension and defined
                                              as \c MBEDTLS_SSL_EXT_XXX */
+
+    union
+    {
+        unsigned char early    [MBEDTLS_TLS1_3_MD_MAX_SIZE];
+        unsigned char handshake[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+        unsigned char app      [MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    } tls1_3_master_secrets;
+
+    mbedtls_ssl_tls1_3_handshake_secrets tls13_hs_secrets;
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
@@ -809,7 +885,9 @@
     /* We need the Hello random bytes in order to re-derive keys from the
      * Master Secret and other session info,
      * see ssl_tls12_populate_transform() */
-    unsigned char randbytes[64]; /*!< ServerHello.random+ClientHello.random */
+    unsigned char randbytes[MBEDTLS_SERVER_HELLO_RANDOM_LEN +
+                            MBEDTLS_CLIENT_HELLO_RANDOM_LEN];
+                            /*!< ServerHello.random+ClientHello.random */
 #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
 };
 
@@ -856,14 +934,14 @@
 
 typedef struct
 {
-    uint8_t ctr[8];         /* In TLS:  The implicit record sequence number.
-                             * In DTLS: The 2-byte epoch followed by
-                             *          the 6-byte sequence number.
-                             * This is stored as a raw big endian byte array
-                             * as opposed to a uint64_t because we rarely
-                             * need to perform arithmetic on this, but do
-                             * need it as a Byte array for the purpose of
-                             * MAC computations.                             */
+    uint8_t ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN];  /* In TLS:  The implicit record sequence number.
+                                                    * In DTLS: The 2-byte epoch followed by
+                                                    *          the 6-byte sequence number.
+                                                    * This is stored as a raw big endian byte array
+                                                    * as opposed to a uint64_t because we rarely
+                                                    * need to perform arithmetic on this, but do
+                                                    * need it as a Byte array for the purpose of
+                                                    * MAC computations.                             */
     uint8_t type;           /* The record content type.                      */
     uint8_t ver[2];         /* SSL/TLS version as present on the wire.
                              * Convert to internal presentation of versions
@@ -946,6 +1024,14 @@
  */
 void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl );
 
+/* set inbound transform of ssl context */
+void mbedtls_ssl_set_inbound_transform( mbedtls_ssl_context *ssl,
+                                        mbedtls_ssl_transform *transform );
+
+/* set outbound transform of ssl context */
+void mbedtls_ssl_set_outbound_transform( mbedtls_ssl_context *ssl,
+                                         mbedtls_ssl_transform *transform );
+
 int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl );
 int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl );
 void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl );
@@ -1332,6 +1418,22 @@
 
 int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial );
 
+/*
+ * Send pending alert
+ */
+int mbedtls_ssl_handle_pending_alert( mbedtls_ssl_context *ssl );
+
+/*
+ * Set pending fatal alert flag.
+ */
+void mbedtls_ssl_pend_fatal_alert( mbedtls_ssl_context *ssl,
+                                   unsigned char alert_type,
+                                   int alert_reason );
+
+/* Alias of mbedtls_ssl_pend_fatal_alert */
+#define MBEDTLS_SSL_PEND_FATAL_ALERT( type, user_return_value )         \
+            mbedtls_ssl_pend_fatal_alert( ssl, type, user_return_value )
+
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
 void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl );
 #endif
@@ -1348,6 +1450,96 @@
 void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight );
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
+
+/*
+ * Helper functions around key exchange modes.
+ */
+static inline unsigned mbedtls_ssl_conf_tls13_check_kex_modes( mbedtls_ssl_context *ssl,
+                                                               int kex_mode_mask )
+{
+    return( ( ssl->conf->tls13_kex_modes & kex_mode_mask ) != 0 );
+}
+
+static inline int mbedtls_ssl_conf_tls13_psk_enabled( mbedtls_ssl_context *ssl )
+{
+    return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK ) );
+}
+
+static inline int mbedtls_ssl_conf_tls13_psk_ephemeral_enabled( mbedtls_ssl_context *ssl )
+{
+    return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK_EPHEMERAL ) );
+}
+
+static inline int mbedtls_ssl_conf_tls13_ephemeral_enabled( mbedtls_ssl_context *ssl )
+{
+    return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_EPHEMERAL ) );
+}
+
+static inline int mbedtls_ssl_conf_tls13_some_ephemeral_enabled( mbedtls_ssl_context *ssl )
+{
+    return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_EPHEMERAL_ALL ) );
+}
+
+static inline int mbedtls_ssl_conf_tls13_some_psk_enabled( mbedtls_ssl_context *ssl )
+{
+    return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK_ALL ) );
+}
+
+/**
+ * Given a list of key exchange modes, check if at least one of them is
+ * supported.
+ *
+ * \param[in] ssl  SSL context
+ * \param kex_modes_mask  Mask of the key exchange modes to check
+ *
+ * \return 0 if at least one of the key exchange modes is supported,
+ *         !=0 otherwise.
+ */
+static inline unsigned mbedtls_ssl_tls1_3_check_kex_modes( mbedtls_ssl_context *ssl,
+                                                           int kex_modes_mask )
+{
+    return( ( ssl->handshake->tls1_3_kex_modes & kex_modes_mask ) == 0 );
+}
+
+static inline int mbedtls_ssl_tls1_3_psk_enabled( mbedtls_ssl_context *ssl )
+{
+    return( ! mbedtls_ssl_tls1_3_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK ) );
+}
+
+static inline int mbedtls_ssl_tls1_3_psk_ephemeral_enabled(
+                                                    mbedtls_ssl_context *ssl )
+{
+    return( ! mbedtls_ssl_tls1_3_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK_EPHEMERAL ) );
+}
+
+static inline int mbedtls_ssl_tls1_3_ephemeral_enabled( mbedtls_ssl_context *ssl )
+{
+    return( ! mbedtls_ssl_tls1_3_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_EPHEMERAL ) );
+}
+
+static inline int mbedtls_ssl_tls1_3_some_ephemeral_enabled( mbedtls_ssl_context *ssl )
+{
+    return( ! mbedtls_ssl_tls1_3_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_EPHEMERAL_ALL ) );
+}
+
+static inline int mbedtls_ssl_tls1_3_some_psk_enabled( mbedtls_ssl_context *ssl )
+{
+    return( ! mbedtls_ssl_tls1_3_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK_ALL ) );
+}
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
+
 /**
  * ssl utils functions for checking configuration.
  */
@@ -1396,6 +1588,24 @@
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
 
+/*
+ * Helper functions for NamedGroup.
+ */
+static inline int mbedtls_ssl_tls13_named_group_is_ecdhe( uint16_t named_group )
+{
+    return( named_group == MBEDTLS_SSL_TLS13_NAMED_GROUP_SECP256R1 ||
+            named_group == MBEDTLS_SSL_TLS13_NAMED_GROUP_SECP384R1 ||
+            named_group == MBEDTLS_SSL_TLS13_NAMED_GROUP_SECP521R1 ||
+            named_group == MBEDTLS_SSL_TLS13_NAMED_GROUP_X25519    ||
+            named_group == MBEDTLS_SSL_TLS13_NAMED_GROUP_X448 );
+}
+
+static inline int mbedtls_ssl_tls13_named_group_is_dhe( uint16_t named_group )
+{
+    return( named_group >= MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE2048 &&
+            named_group <= MBEDTLS_SSL_TLS13_NAMED_GROUP_FFDHE8192 );
+}
+
 static inline void mbedtls_ssl_handshake_set_state( mbedtls_ssl_context *ssl,
                                                     mbedtls_ssl_states state )
 {
@@ -1403,6 +1613,14 @@
 }
 
 /*
+ * Fetch TLS 1.3 handshake message header
+ */
+int mbedtls_ssl_tls1_3_fetch_handshake_msg( mbedtls_ssl_context *ssl,
+                                            unsigned hs_type,
+                                            unsigned char **buf,
+                                            size_t *buf_len );
+
+/*
  * Write TLS 1.3 handshake message header
  */
 int mbedtls_ssl_tls13_start_handshake_msg( mbedtls_ssl_context *ssl,
@@ -1415,13 +1633,19 @@
 int mbedtls_ssl_tls13_finish_handshake_msg( mbedtls_ssl_context *ssl,
                                             size_t buf_len,
                                             size_t msg_len );
-/*
- * Update checksum with handshake header
- */
+
 void mbedtls_ssl_tls13_add_hs_hdr_to_checksum( mbedtls_ssl_context *ssl,
                                                unsigned hs_type,
                                                size_t total_hs_len );
 
+/*
+ * Update checksum of handshake messages.
+ */
+void mbedtls_ssl_tls1_3_add_hs_msg_to_checksum( mbedtls_ssl_context *ssl,
+                                                unsigned hs_type,
+                                                unsigned char const *msg,
+                                                size_t msg_len );
+
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
 /*
  * Write TLS 1.3 Signature Algorithm extension
@@ -1430,8 +1654,16 @@
                                          unsigned char *buf,
                                          unsigned char *end,
                                          size_t *olen);
+
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
 
+/* Get handshake transcript */
+int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl,
+                                          const mbedtls_md_type_t md,
+                                          unsigned char *dst,
+                                          size_t dst_len,
+                                          size_t *olen );
+
 #endif /* ssl_misc.h */
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index 2fe801a..3795c65 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -2101,7 +2101,7 @@
 static int ssl_swap_epochs( mbedtls_ssl_context *ssl )
 {
     mbedtls_ssl_transform *tmp_transform;
-    unsigned char tmp_out_ctr[8];
+    unsigned char tmp_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN];
 
     if( ssl->transform_out == ssl->handshake->alt_transform_out )
     {
@@ -2117,9 +2117,11 @@
     ssl->handshake->alt_transform_out = tmp_transform;
 
     /* Swap epoch + sequence_number */
-    memcpy( tmp_out_ctr,                 ssl->cur_out_ctr,            8 );
-    memcpy( ssl->cur_out_ctr,            ssl->handshake->alt_out_ctr, 8 );
-    memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr,                 8 );
+    memcpy( tmp_out_ctr, ssl->cur_out_ctr, sizeof( tmp_out_ctr ) );
+    memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr,
+            sizeof( ssl->cur_out_ctr ) );
+    memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr,
+            sizeof( ssl->handshake->alt_out_ctr ) );
 
     /* Adjust to the newly activated transform */
     mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
@@ -2562,7 +2564,7 @@
         mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
                            ssl->conf->transport, ssl->out_hdr + 1 );
 
-        memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 );
+        memcpy( ssl->out_ctr, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN );
         MBEDTLS_PUT_UINT16_BE( len, ssl->out_len, 0);
 
         if( ssl->transform_out != NULL )
@@ -2574,7 +2576,7 @@
             rec.data_len    = ssl->out_msglen;
             rec.data_offset = ssl->out_msg - rec.buf;
 
-            memcpy( &rec.ctr[0], ssl->out_ctr, 8 );
+            memcpy( &rec.ctr[0], ssl->out_ctr, sizeof( rec.ctr ) );
             mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
                                        ssl->conf->transport, rec.ver );
             rec.type = ssl->out_msgtype;
@@ -3649,9 +3651,12 @@
 #endif
         {
             unsigned i;
-            for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- )
+            for( i = MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
+                 i > mbedtls_ssl_ep_len( ssl ); i-- )
+            {
                 if( ++ssl->in_ctr[i - 1] != 0 )
                     break;
+            }
 
             /* The loop goes to its end iff the counter is wrapping */
             if( i == mbedtls_ssl_ep_len( ssl ) )
@@ -4791,7 +4796,7 @@
     }
     else
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
-    memset( ssl->in_ctr, 0, 8 );
+    memset( ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN );
 
     mbedtls_ssl_update_in_pointers( ssl );
 
@@ -4827,12 +4832,12 @@
     {
         ssl->out_ctr = ssl->out_hdr +  3;
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-        ssl->out_cid = ssl->out_ctr +  8;
+        ssl->out_cid = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
         ssl->out_len = ssl->out_cid;
         if( transform != NULL )
             ssl->out_len += transform->out_cid_len;
 #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-        ssl->out_len = ssl->out_ctr + 8;
+        ssl->out_len = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
         ssl->out_iv  = ssl->out_len + 2;
     }
@@ -4881,17 +4886,17 @@
          * ssl_parse_record_header(). */
         ssl->in_ctr = ssl->in_hdr +  3;
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-        ssl->in_cid = ssl->in_ctr +  8;
+        ssl->in_cid = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
         ssl->in_len = ssl->in_cid; /* Default: no CID */
 #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-        ssl->in_len = ssl->in_ctr + 8;
+        ssl->in_len = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
         ssl->in_iv  = ssl->in_len + 2;
     }
     else
 #endif
     {
-        ssl->in_ctr = ssl->in_hdr - 8;
+        ssl->in_ctr = ssl->in_hdr - MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
         ssl->in_len = ssl->in_hdr + 3;
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
         ssl->in_cid = ssl->in_len;
@@ -5065,9 +5070,11 @@
     }
 
     in_ctr_cmp = memcmp( ssl->in_ctr + ep_len,
-                        ssl->conf->renego_period + ep_len, 8 - ep_len );
-    out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len,
-                          ssl->conf->renego_period + ep_len, 8 - ep_len );
+                         &ssl->conf->renego_period[ep_len],
+                         MBEDTLS_SSL_SEQUENCE_NUMBER_LEN - ep_len );
+    out_ctr_cmp = memcmp( &ssl->cur_out_ctr[ep_len],
+                          &ssl->conf->renego_period[ep_len],
+                          sizeof( ssl->cur_out_ctr ) - ep_len );
 
     if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 )
     {
@@ -5551,6 +5558,20 @@
     mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) );
 }
 
+void mbedtls_ssl_set_inbound_transform( mbedtls_ssl_context *ssl,
+                                        mbedtls_ssl_transform *transform )
+{
+    ssl->transform_in = transform;
+    memset( ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN );
+}
+
+void mbedtls_ssl_set_outbound_transform( mbedtls_ssl_context *ssl,
+                                         mbedtls_ssl_transform *transform )
+{
+    ssl->transform_out = transform;
+    memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) );
+}
+
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 
 void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl )
@@ -5639,4 +5660,48 @@
     }
 }
 
+/*
+ * Send pending fatal alert.
+ * 0,   No alert message.
+ * !0,  if mbedtls_ssl_send_alert_message() returned in error, the error code it
+ *      returned, ssl->alert_reason otherwise.
+ */
+int mbedtls_ssl_handle_pending_alert( mbedtls_ssl_context *ssl )
+{
+    int ret;
+
+    /* No pending alert, return success*/
+    if( ssl->send_alert == 0 )
+        return( 0 );
+
+    ret = mbedtls_ssl_send_alert_message( ssl,
+                                MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                ssl->alert_type );
+
+    /* If mbedtls_ssl_send_alert_message() returned with MBEDTLS_ERR_SSL_WANT_WRITE,
+     * do not clear the alert to be able to send it later.
+     */
+    if( ret != MBEDTLS_ERR_SSL_WANT_WRITE )
+    {
+        ssl->send_alert = 0;
+    }
+
+    if( ret != 0 )
+        return( ret );
+
+    return( ssl->alert_reason );
+}
+
+/*
+ * Set pending fatal alert flag.
+ */
+void mbedtls_ssl_pend_fatal_alert( mbedtls_ssl_context *ssl,
+                                   unsigned char alert_type,
+                                   int alert_reason )
+{
+    ssl->send_alert = 1;
+    ssl->alert_type = alert_type;
+    ssl->alert_reason = alert_reason;
+}
+
 #endif /* MBEDTLS_SSL_TLS_C */
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index b8c4314..e27fdff 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -1220,7 +1220,8 @@
             return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
         }
 
-        memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 );
+        memcpy( &ssl->cur_out_ctr[2], ssl->in_ctr + 2,
+                sizeof( ssl->cur_out_ctr ) - 2 );
 
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
         if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c
index bce9a1c..e998111 100644
--- a/library/ssl_ticket.c
+++ b/library/ssl_ticket.c
@@ -138,16 +138,14 @@
     ctx->ticket_lifetime = lifetime;
 
     cipher_info = mbedtls_cipher_info_from_type( cipher);
-    if( cipher_info == NULL )
-        return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
-    if( cipher_info->mode != MBEDTLS_MODE_GCM &&
-        cipher_info->mode != MBEDTLS_MODE_CCM )
+    if( mbedtls_cipher_info_get_mode( cipher_info ) != MBEDTLS_MODE_GCM &&
+        mbedtls_cipher_info_get_mode( cipher_info ) != MBEDTLS_MODE_CCM )
     {
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
 
-    if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES )
+    if( mbedtls_cipher_info_get_key_bitlen( cipher_info ) > 8 * MAX_KEY_BYTES )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 3604192..c507950 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -587,7 +587,6 @@
 #endif /* MBEDTLS_USE_PSA_CRYPTO &&
           MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 static mbedtls_tls_prf_types tls_prf_get_type( mbedtls_ssl_tls_prf_cb *tls_prf )
 {
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
@@ -608,7 +607,6 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
     return( MBEDTLS_SSL_TLS_PRF_NONE );
 }
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 int  mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf,
                           const unsigned char *secret, size_t slen,
@@ -660,8 +658,9 @@
  * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random
  * - [in] minor_ver: SSL/TLS minor version
  * - [in] endpoint: client or server
- * - [in] ssl: optionally used for:
- *        - MBEDTLS_SSL_EXPORT_KEYS: ssl->conf->{f,p}_export_keys
+ * - [in] ssl: used for:
+ *        - ssl->conf->{f,p}_export_keys
+ *      [in] optionally used for:
  *        - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg
  */
 static int ssl_tls12_populate_transform( mbedtls_ssl_transform *transform,
@@ -689,15 +688,18 @@
     unsigned char *mac_dec;
     size_t mac_key_len = 0;
     size_t iv_copy_len;
-    unsigned keylen;
+    size_t keylen;
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
     const mbedtls_cipher_info_t *cipher_info;
     const mbedtls_md_info_t *md_info;
 
-#if !defined(MBEDTLS_SSL_EXPORT_KEYS) && \
-    !defined(MBEDTLS_DEBUG_C)
-    ssl = NULL; /* make sure we don't use it except for those cases */
-    (void) ssl;
+#if !defined(MBEDTLS_DEBUG_C) && \
+    !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    if( ssl->f_export_keys == NULL )
+    {
+        ssl = NULL; /* make sure we don't use it except for these cases */
+        (void) ssl;
+    }
 #endif
 
     /*
@@ -789,14 +791,14 @@
      * Determine the appropriate key, IV and MAC length.
      */
 
-    keylen = cipher_info->key_bitlen / 8;
+    keylen = mbedtls_cipher_info_get_key_bitlen( cipher_info ) / 8;
 
 #if defined(MBEDTLS_GCM_C) ||                           \
     defined(MBEDTLS_CCM_C) ||                           \
     defined(MBEDTLS_CHACHAPOLY_C)
-    if( cipher_info->mode == MBEDTLS_MODE_GCM ||
-        cipher_info->mode == MBEDTLS_MODE_CCM ||
-        cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
+    if( mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_GCM ||
+        mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_CCM ||
+        mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_CHACHAPOLY )
     {
         size_t explicit_ivlen;
 
@@ -814,7 +816,7 @@
          *   sequence number).
          */
         transform->ivlen = 12;
-        if( cipher_info->mode == MBEDTLS_MODE_CHACHAPOLY )
+        if( mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_CHACHAPOLY )
             transform->fixed_ivlen = 12;
         else
             transform->fixed_ivlen = 4;
@@ -826,8 +828,8 @@
     else
 #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
 #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
-    if( cipher_info->mode == MBEDTLS_MODE_STREAM ||
-        cipher_info->mode == MBEDTLS_MODE_CBC )
+    if( mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_STREAM ||
+        mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_CBC )
     {
         /* Initialize HMAC contexts */
         if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 ||
@@ -845,7 +847,7 @@
         transform->ivlen = cipher_info->iv_size;
 
         /* Minimum length */
-        if( cipher_info->mode == MBEDTLS_MODE_STREAM )
+        if( mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_STREAM )
             transform->minlen = transform->maclen;
         else
         {
@@ -960,8 +962,7 @@
     ((void) mac_dec);
     ((void) mac_enc);
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
-    if( ssl->f_export_keys != NULL )
+    if( ssl != NULL && ssl->f_export_keys != NULL )
     {
         ssl->f_export_keys( ssl->p_export_keys,
                             MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET,
@@ -970,42 +971,26 @@
                             randbytes,
                             tls_prf_get_type( tls_prf ) );
     }
-#endif
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-
-    /* Only use PSA-based ciphers for TLS-1.2.
-     * That's relevant at least for TLS-1.0, where
-     * we assume that mbedtls_cipher_crypt() updates
-     * the structure field for the IV, which the PSA-based
-     * implementation currently doesn't. */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+    ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc,
+                                    cipher_info, transform->taglen );
+    if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
     {
-        ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc,
-                                        cipher_info, transform->taglen );
-        if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
-            goto end;
-        }
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
+        goto end;
+    }
 
-        if( ret == 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based encryption cipher context" ) );
-            psa_fallthrough = 0;
-        }
-        else
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record encryption - fall through to default setup." ) );
-            psa_fallthrough = 1;
-        }
+    if( ret == 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based encryption cipher context" ) );
+        psa_fallthrough = 0;
     }
     else
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record encryption - fall through to default setup." ) );
         psa_fallthrough = 1;
-#else
-    psa_fallthrough = 1;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    }
 
     if( psa_fallthrough == 1 )
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
@@ -1017,38 +1002,24 @@
     }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    /* Only use PSA-based ciphers for TLS-1.2.
-     * That's relevant at least for TLS-1.0, where
-     * we assume that mbedtls_cipher_crypt() updates
-     * the structure field for the IV, which the PSA-based
-     * implementation currently doesn't. */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+    ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec,
+                                    cipher_info, transform->taglen );
+    if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
     {
-        ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec,
-                                        cipher_info, transform->taglen );
-        if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
-            goto end;
-        }
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
+        goto end;
+    }
 
-        if( ret == 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based decryption cipher context" ) );
-            psa_fallthrough = 0;
-        }
-        else
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record decryption - fall through to default setup." ) );
-            psa_fallthrough = 1;
-        }
+    if( ret == 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based decryption cipher context" ) );
+        psa_fallthrough = 0;
     }
     else
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record decryption - fall through to default setup." ) );
         psa_fallthrough = 1;
-#else
-    psa_fallthrough = 1;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    }
 
     if( psa_fallthrough == 1 )
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
@@ -1060,7 +1031,7 @@
     }
 
     if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1,
-                               cipher_info->key_bitlen,
+                               (int) mbedtls_cipher_info_get_key_bitlen( cipher_info ),
                                MBEDTLS_ENCRYPT ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret );
@@ -1068,7 +1039,7 @@
     }
 
     if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2,
-                               cipher_info->key_bitlen,
+                               (int) mbedtls_cipher_info_get_key_bitlen( cipher_info ),
                                MBEDTLS_DECRYPT ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret );
@@ -1076,7 +1047,7 @@
     }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-    if( cipher_info->mode == MBEDTLS_MODE_CBC )
+    if( mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_CBC )
     {
         if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_enc,
                                              MBEDTLS_PADDING_NONE ) ) != 0 )
@@ -2820,10 +2791,12 @@
 
         /* Remember current epoch settings for resending */
         ssl->handshake->alt_transform_out = ssl->transform_out;
-        memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 );
+        memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr,
+                sizeof( ssl->handshake->alt_out_ctr ) );
 
         /* Set sequence_number to zero */
-        memset( ssl->cur_out_ctr + 2, 0, 6 );
+        memset( &ssl->cur_out_ctr[2], 0, sizeof( ssl->cur_out_ctr ) - 2 );
+
 
         /* Increment epoch */
         for( i = 2; i > 0; i-- )
@@ -2839,7 +2812,7 @@
     }
     else
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
-    memset( ssl->cur_out_ctr, 0, 8 );
+    memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) );
 
     ssl->transform_out = ssl->transform_negotiate;
     ssl->session_out = ssl->session_negotiate;
@@ -4229,7 +4202,6 @@
 #endif
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 void mbedtls_ssl_set_export_keys_cb( mbedtls_ssl_context *ssl,
                                      mbedtls_ssl_export_keys_t *f_export_keys,
                                      void *p_export_keys )
@@ -4237,7 +4209,6 @@
     ssl->f_export_keys = f_export_keys;
     ssl->p_export_keys = p_export_keys;
 }
-#endif
 
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
 void mbedtls_ssl_conf_async_private_cb(
@@ -5170,6 +5141,10 @@
     if( ret != 0 )
         return( ret );
 
+    ret = mbedtls_ssl_handle_pending_alert( ssl );
+    if( ret != 0 )
+        goto cleanup;
+
 #if defined(MBEDTLS_SSL_CLI_C)
     if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
     {
@@ -5199,6 +5174,19 @@
     }
 #endif
 
+    if( ret != 0 )
+    {
+        /* handshake_step return error. And it is same
+         * with alert_reason.
+         */
+        if( ssl->send_alert )
+        {
+            ret = mbedtls_ssl_handle_pending_alert( ssl );
+            goto cleanup;
+        }
+    }
+
+cleanup:
     return( ret );
 }
 
@@ -5775,11 +5763,11 @@
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    used += 8;
+    used += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
     if( used <= buf_len )
     {
-        memcpy( p, ssl->cur_out_ctr, 8 );
-        p += 8;
+        memcpy( p, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN );
+        p += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
     }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -6035,11 +6023,10 @@
     ssl->disable_datagram_packing = *p++;
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    if( (size_t)( end - p ) < 8 )
+    if( (size_t)( end - p ) < sizeof( ssl->cur_out_ctr ) )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    memcpy( ssl->cur_out_ctr, p, 8 );
-    p += 8;
+    memcpy( ssl->cur_out_ctr, p, sizeof( ssl->cur_out_ctr ) );
+    p += sizeof( ssl->cur_out_ctr );
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if( (size_t)( end - p ) < 2 )
@@ -6978,4 +6965,106 @@
 
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl,
+                                          const mbedtls_md_type_t md,
+                                          unsigned char *dst,
+                                          size_t dst_len,
+                                          size_t *olen )
+{
+    ((void) ssl);
+    ((void) md);
+    ((void) dst);
+    ((void) dst_len);
+    *olen = 0;
+    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE);
+}
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_SHA384_C)
+static int ssl_get_handshake_transcript_sha384( mbedtls_ssl_context *ssl,
+                                                unsigned char *dst,
+                                                size_t dst_len,
+                                                size_t *olen )
+{
+    int ret;
+    mbedtls_sha512_context sha512;
+
+    if( dst_len < 48 )
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+
+    mbedtls_sha512_init( &sha512 );
+    mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 );
+
+    if( ( ret = mbedtls_sha512_finish( &sha512, dst ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha512_finish", ret );
+        goto exit;
+    }
+
+    *olen = 48;
+
+exit:
+
+    mbedtls_sha512_free( &sha512 );
+    return( ret );
+}
+#endif /* MBEDTLS_SHA384_C */
+
+#if defined(MBEDTLS_SHA256_C)
+static int ssl_get_handshake_transcript_sha256( mbedtls_ssl_context *ssl,
+                                                unsigned char *dst,
+                                                size_t dst_len,
+                                                size_t *olen )
+{
+    int ret;
+    mbedtls_sha256_context sha256;
+
+    if( dst_len < 32 )
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+
+    mbedtls_sha256_init( &sha256 );
+    mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 );
+
+    if( ( ret = mbedtls_sha256_finish( &sha256, dst ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha256_finish", ret );
+        goto exit;
+    }
+
+    *olen = 32;
+
+exit:
+
+    mbedtls_sha256_free( &sha256 );
+    return( ret );
+}
+#endif /* MBEDTLS_SHA256_C */
+
+int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl,
+                                          const mbedtls_md_type_t md,
+                                          unsigned char *dst,
+                                          size_t dst_len,
+                                          size_t *olen )
+{
+    switch( md )
+    {
+
+#if defined(MBEDTLS_SHA384_C)
+    case MBEDTLS_MD_SHA384:
+        return( ssl_get_handshake_transcript_sha384( ssl, dst, dst_len, olen ) );
+#endif /* MBEDTLS_SHA384_C */
+
+#if defined(MBEDTLS_SHA256_C)
+    case MBEDTLS_MD_SHA256:
+        return( ssl_get_handshake_transcript_sha256( ssl, dst, dst_len, olen ) );
+#endif /* MBEDTLS_SHA256_C */
+
+    default:
+        break;
+    }
+    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+}
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+
 #endif /* MBEDTLS_SSL_TLS_C */
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 41c7a4d..5ed01aa 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -27,10 +27,13 @@
 
 #include <string.h>
 
-#include "ssl_misc.h"
-#include <mbedtls/debug.h>
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
+#include "mbedtls/platform.h"
 
-#define CLIENT_HELLO_RANDOM_LEN 32
+#include "ssl_misc.h"
+#include "ecdh_misc.h"
+#include "ssl_tls13_keys.h"
 
 /* Write extensions */
 
@@ -52,13 +55,11 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported versions extension" ) );
 
-    /*
-     * Check space for extension header.
-     *
-     * extension_type           2
-     * extension_data_length    2
-     * version_length           1
-     * versions                 2
+    /* Check if we have space to write the extension:
+     * - extension_type         (2 bytes)
+     * - extension_data_length  (2 bytes)
+     * - versions_length        (1 byte )
+     * - versions               (2 bytes)
      */
     MBEDTLS_SSL_CHK_BUF_PTR( p, end, 7 );
 
@@ -91,37 +92,509 @@
     return( 0 );
 }
 
+static int ssl_tls13_parse_supported_versions_ext( mbedtls_ssl_context *ssl,
+                                                   const unsigned char *buf,
+                                                   const unsigned char *end )
+{
+    ((void) ssl);
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, 2);
+    if( buf[0] != MBEDTLS_SSL_MAJOR_VERSION_3 ||
+        buf[1] != MBEDTLS_SSL_MINOR_VERSION_4 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "unexpected version" ) );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+
+    return( 0 );
+}
+
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
 
+/*
+ * Functions for writing supported_groups extension.
+ *
+ * Stucture of supported_groups:
+ *      enum {
+ *          secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
+ *          x25519(0x001D), x448(0x001E),
+ *          ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
+ *          ffdhe6144(0x0103), ffdhe8192(0x0104),
+ *          ffdhe_private_use(0x01FC..0x01FF),
+ *          ecdhe_private_use(0xFE00..0xFEFF),
+ *          (0xFFFF)
+ *      } NamedGroup;
+ *      struct {
+ *          NamedGroup named_group_list<2..2^16-1>;
+ *      } NamedGroupList;
+ */
+#if defined(MBEDTLS_ECDH_C)
+/*
+ * In versions of TLS prior to TLS 1.3, this extension was named
+ * 'elliptic_curves' and only contained elliptic curve groups.
+ */
+static int ssl_tls13_write_named_group_list_ecdhe( mbedtls_ssl_context *ssl,
+                                            unsigned char *buf,
+                                            unsigned char *end,
+                                            size_t *olen )
+{
+    unsigned char *p = buf;
+
+    *olen = 0;
+
+    if( ssl->conf->curve_list == NULL )
+        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
+
+    for ( const mbedtls_ecp_group_id *grp_id = ssl->conf->curve_list;
+          *grp_id != MBEDTLS_ECP_DP_NONE;
+          grp_id++ )
+    {
+        const mbedtls_ecp_curve_info *info;
+        info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
+        if( info == NULL )
+            continue;
+
+        if( !mbedtls_ssl_tls13_named_group_is_ecdhe( info->tls_id ) )
+            continue;
+
+        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2);
+        MBEDTLS_PUT_UINT16_BE( info->tls_id, p, 0 );
+        p += 2;
+
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "NamedGroup: %s ( %x )",
+                  mbedtls_ecp_curve_info_from_tls_id( info->tls_id )->name,
+                  info->tls_id ) );
+    }
+
+    *olen = p - buf;
+
+    return( 0 );
+}
+#else
+static int ssl_tls13_write_named_group_list_ecdhe( mbedtls_ssl_context *ssl,
+                                            unsigned char *buf,
+                                            unsigned char *end,
+                                            size_t *olen )
+{
+    ((void) ssl);
+    ((void) buf);
+    ((void) end);
+    *olen = 0;
+    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+}
+#endif /* MBEDTLS_ECDH_C */
+
+static int ssl_tls13_write_named_group_list_dhe( mbedtls_ssl_context *ssl,
+                                        unsigned char *buf,
+                                        unsigned char *end,
+                                        size_t *olen )
+{
+    ((void) ssl);
+    ((void) buf);
+    ((void) end);
+    *olen = 0;
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "write_named_group_dhe is not implemented" ) );
+    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+}
+
 static int ssl_tls13_write_supported_groups_ext( mbedtls_ssl_context *ssl,
                                                  unsigned char *buf,
                                                  unsigned char *end,
                                                  size_t *olen )
 {
-    ((void) ssl);
-    ((void) buf);
-    ((void) end);
-    ((void) olen);
-    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+    unsigned char *p = buf ;
+    unsigned char *named_group_list_ptr; /* Start of named_group_list */
+    size_t named_group_list_len;         /* Length of named_group_list */
+    size_t output_len = 0;
+    int ret_ecdhe, ret_dhe;
+
+    *olen = 0;
+
+    if( !mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) )
+        return( 0 );
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_groups extension" ) );
+
+    /* Check if we have space for header and length fields:
+     * - extension_type         (2 bytes)
+     * - extension_data_length  (2 bytes)
+     * - named_group_list_length   (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 );
+    p += 6;
+
+    named_group_list_ptr = p;
+    ret_ecdhe = ssl_tls13_write_named_group_list_ecdhe( ssl, p, end, &output_len );
+    if( ret_ecdhe != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_write_named_group_list_ecdhe", ret_ecdhe );
+    }
+    p += output_len;
+
+    ret_dhe = ssl_tls13_write_named_group_list_dhe( ssl, p, end, &output_len );
+    if( ret_dhe != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_write_named_group_list_dhe", ret_dhe );
+    }
+    p += output_len;
+
+    /* Both ECDHE and DHE failed. */
+    if( ret_ecdhe != 0 && ret_dhe != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Both ECDHE and DHE groups are fail. " ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    /* Length of named_group_list*/
+    named_group_list_len = p - named_group_list_ptr;
+    if( named_group_list_len == 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "No group available." ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    /* Write extension_type */
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, buf, 0 );
+    /* Write extension_data_length */
+    MBEDTLS_PUT_UINT16_BE( named_group_list_len + 2, buf, 2 );
+    /* Write length of named_group_list */
+    MBEDTLS_PUT_UINT16_BE( named_group_list_len, buf, 4 );
+
+    MBEDTLS_SSL_DEBUG_BUF( 3, "Supported groups extension", buf + 4, named_group_list_len + 2 );
+
+    *olen = p - buf;
+
+    ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SUPPORTED_GROUPS;
+
+    return( 0 );
 }
 
-static int ssl_tls13_write_key_shares_ext( mbedtls_ssl_context *ssl,
-                                           unsigned char *buf,
-                                           unsigned char *end,
-                                           size_t *olen )
+/*
+ * Functions for writing key_share extension.
+ */
+#if defined(MBEDTLS_ECDH_C)
+static int ssl_tls13_generate_and_write_ecdh_key_exchange(
+                mbedtls_ssl_context *ssl,
+                uint16_t named_group,
+                unsigned char *buf,
+                unsigned char *end,
+                size_t *olen )
 {
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const mbedtls_ecp_curve_info *curve_info =
+        mbedtls_ecp_curve_info_from_tls_id( named_group );
+
+    if( curve_info == NULL )
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "offer curve %s", curve_info->name ) );
+
+    if( ( ret = mbedtls_ecdh_setup_no_everest( &ssl->handshake->ecdh_ctx,
+                                               curve_info->grp_id ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_setup_no_everest", ret );
+        return( ret );
+    }
+
+    ret = mbedtls_ecdh_tls13_make_params( &ssl->handshake->ecdh_ctx, olen,
+                                           buf, end - buf,
+                                           ssl->conf->f_rng, ssl->conf->p_rng );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_tls13_make_params", ret );
+        return( ret );
+    }
+
+    MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
+                            MBEDTLS_DEBUG_ECDH_Q );
+    return( 0 );
+}
+#endif /* MBEDTLS_ECDH_C */
+
+static int ssl_tls13_get_default_group_id( mbedtls_ssl_context *ssl,
+                                           uint16_t *group_id )
+{
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+
+
+#if defined(MBEDTLS_ECDH_C)
+    /* Pick first available ECDHE group compatible with TLS 1.3 */
+    if( ssl->conf->curve_list == NULL )
+        return( MBEDTLS_ERR_SSL_BAD_CONFIG );
+
+    for ( const mbedtls_ecp_group_id *grp_id = ssl->conf->curve_list;
+          *grp_id != MBEDTLS_ECP_DP_NONE;
+          grp_id++ )
+    {
+        const mbedtls_ecp_curve_info *info;
+        info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
+        if( info != NULL &&
+            mbedtls_ssl_tls13_named_group_is_ecdhe( info->tls_id ) )
+        {
+            *group_id = info->tls_id;
+            return( 0 );
+        }
+    }
+#else
     ((void) ssl);
-    ((void) buf);
-    ((void) end);
-    ((void) olen);
-    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+    ((void) group_id);
+#endif /* MBEDTLS_ECDH_C */
+
+    /*
+     * Add DHE named groups here.
+     * Pick first available DHE group compatible with TLS 1.3
+     */
+
+    return( ret );
+}
+
+/*
+ * ssl_tls13_write_key_share_ext
+ *
+ * Structure of key_share extension in ClientHello:
+ *
+ *  struct {
+ *          NamedGroup group;
+ *          opaque key_exchange<1..2^16-1>;
+ *      } KeyShareEntry;
+ *  struct {
+ *          KeyShareEntry client_shares<0..2^16-1>;
+ *      } KeyShareClientHello;
+ */
+static int ssl_tls13_write_key_share_ext( mbedtls_ssl_context *ssl,
+                                          unsigned char *buf,
+                                          unsigned char *end,
+                                          size_t *olen )
+{
+    unsigned char *p = buf;
+    unsigned char *client_shares_ptr; /* Start of client_shares */
+    size_t client_shares_len;         /* Length of client_shares */
+    uint16_t group_id;
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+
+    *olen = 0;
+
+    if( !mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) )
+        return( 0 );
+
+    /* Check if we have space for header and length fields:
+     * - extension_type         (2 bytes)
+     * - extension_data_length  (2 bytes)
+     * - client_shares_length   (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 );
+    p += 6;
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello: adding key share extension" ) );
+
+    /* HRR could already have requested something else. */
+    group_id = ssl->handshake->offered_group_id;
+    if( !mbedtls_ssl_tls13_named_group_is_ecdhe( group_id ) &&
+        !mbedtls_ssl_tls13_named_group_is_dhe( group_id ) )
+    {
+        MBEDTLS_SSL_PROC_CHK( ssl_tls13_get_default_group_id( ssl,
+                                                              &group_id ) );
+    }
+
+    /*
+     * Dispatch to type-specific key generation function.
+     *
+     * So far, we're only supporting ECDHE. With the introduction
+     * of PQC KEMs, we'll want to have multiple branches, one per
+     * type of KEM, and dispatch to the corresponding crypto. And
+     * only one key share entry is allowed.
+     */
+    client_shares_ptr = p;
+#if defined(MBEDTLS_ECDH_C)
+    if( mbedtls_ssl_tls13_named_group_is_ecdhe( group_id ) )
+    {
+        /* Pointer to group */
+        unsigned char *group_ptr = p;
+        /* Length of key_exchange */
+        size_t key_exchange_len;
+
+        /* Check there is space for header of KeyShareEntry
+         * - group                  (2 bytes)
+         * - key_exchange_length    (2 bytes)
+         */
+        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 );
+        p += 4;
+        ret = ssl_tls13_generate_and_write_ecdh_key_exchange( ssl, group_id,
+                                                              p, end,
+                                                              &key_exchange_len );
+        p += key_exchange_len;
+        if( ret != 0 )
+            return( ret );
+
+        /* Write group */
+        MBEDTLS_PUT_UINT16_BE( group_id, group_ptr, 0 );
+        /* Write key_exchange_length */
+        MBEDTLS_PUT_UINT16_BE( key_exchange_len, group_ptr, 2 );
+    }
+    else
+#endif /* MBEDTLS_ECDH_C */
+    if( 0 /* other KEMs? */ )
+    {
+        /* Do something */
+    }
+    else
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+
+    /* Length of client_shares */
+    client_shares_len = p - client_shares_ptr;
+    if( client_shares_len == 0)
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "No key share defined." ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+    /* Write extension_type */
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0 );
+    /* Write extension_data_length */
+    MBEDTLS_PUT_UINT16_BE( client_shares_len + 2, buf, 2 );
+    /* Write client_shares_length */
+    MBEDTLS_PUT_UINT16_BE( client_shares_len, buf, 4 );
+
+    /* Update offered_group_id field */
+    ssl->handshake->offered_group_id = group_id;
+
+    /* Output the total length of key_share extension. */
+    *olen = p - buf;
+
+    MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, key_share extension", buf, *olen );
+
+    ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_KEY_SHARE;
+
+cleanup:
+
+    return( ret );
+}
+
+#if defined(MBEDTLS_ECDH_C)
+
+static int ssl_tls13_check_ecdh_params( const mbedtls_ssl_context *ssl )
+{
+    const mbedtls_ecp_curve_info *curve_info;
+    mbedtls_ecp_group_id grp_id;
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+    grp_id = ssl->handshake->ecdh_ctx.grp.id;
+#else
+    grp_id = ssl->handshake->ecdh_ctx.grp_id;
+#endif
+
+    curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id );
+    if( curve_info == NULL )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) );
+
+    if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 )
+        return( -1 );
+
+    MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
+                            MBEDTLS_DEBUG_ECDH_QP );
+
+    return( 0 );
+}
+
+static int ssl_tls13_read_public_ecdhe_share( mbedtls_ssl_context *ssl,
+                                              const unsigned char *buf,
+                                              size_t buf_len )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    ret = mbedtls_ecdh_tls13_read_public( &ssl->handshake->ecdh_ctx,
+                                          buf, buf_len );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_tls13_read_public" ), ret );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+
+    if( ssl_tls13_check_ecdh_params( ssl ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "ssl_tls13_check_ecdh_params() failed!" ) );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_ECDH_C */
+
+/*
+ * ssl_tls13_parse_key_share_ext()
+ *      Parse key_share extension in Server Hello
+ *
+ * struct {
+ *        KeyShareEntry server_share;
+ * } KeyShareServerHello;
+ * struct {
+ *        NamedGroup group;
+ *        opaque key_exchange<1..2^16-1>;
+ * } KeyShareEntry;
+ */
+static int ssl_tls13_parse_key_share_ext( mbedtls_ssl_context *ssl,
+                                          const unsigned char *buf,
+                                          const unsigned char *end )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *p = buf;
+    uint16_t group, offered_group;
+
+    /* ...
+     * NamedGroup group; (2 bytes)
+     * ...
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
+    group = MBEDTLS_GET_UINT16_BE( p, 0 );
+    p += 2;
+
+    /* Check that the chosen group matches the one we offered. */
+    offered_group = ssl->handshake->offered_group_id;
+    if( offered_group != group )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "Invalid server key share, our group %u, their group %u",
+              (unsigned) offered_group, (unsigned) group ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+                                      MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+        return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+    }
+
+#if defined(MBEDTLS_ECDH_C)
+    if( mbedtls_ssl_tls13_named_group_is_ecdhe( group ) )
+    {
+        /* Complete ECDHE key agreement */
+        ret = ssl_tls13_read_public_ecdhe_share( ssl, p, end - p );
+        if( ret != 0 )
+            return( ret );
+    }
+    else
+#endif /* MBEDTLS_ECDH_C */
+    if( 0 /* other KEMs? */ )
+    {
+        /* Do something */
+    }
+    else
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+
+    ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_KEY_SHARE;
+    return( ret );
 }
 
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
-/*
- * Functions for writing ClientHello message.
- */
 /* Write cipher_suites
  * CipherSuite cipher_suites<2..2^16-2>;
  */
@@ -233,11 +706,11 @@
     p += 2;
 
     /* Write the random bytes ( random ).*/
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, CLIENT_HELLO_RANDOM_LEN );
-    memcpy( p, ssl->handshake->randbytes, CLIENT_HELLO_RANDOM_LEN );
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, MBEDTLS_CLIENT_HELLO_RANDOM_LEN );
+    memcpy( p, ssl->handshake->randbytes, MBEDTLS_CLIENT_HELLO_RANDOM_LEN );
     MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes",
-                           p, CLIENT_HELLO_RANDOM_LEN );
-    p += CLIENT_HELLO_RANDOM_LEN;
+                           p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN );
+    p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN;
 
     /*
      * Write legacy_session_id
@@ -311,7 +784,7 @@
      * 3) Or, in case all ciphers are supported ( which includes #1 and #2
      *    from above )
      */
-    ret = ssl_tls13_write_key_shares_ext( ssl, p, end, &output_len );
+    ret = ssl_tls13_write_key_share_ext( ssl, p, end, &output_len );
     if( ret != 0 )
         return( ret );
     p += output_len;
@@ -340,7 +813,7 @@
     return( 0 );
 }
 
-static int ssl_tls13_finalize_client_hello( mbedtls_ssl_context* ssl )
+static int ssl_tls13_finalize_client_hello( mbedtls_ssl_context *ssl )
 {
     mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_HELLO );
     return( 0 );
@@ -358,7 +831,7 @@
 
     if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng,
                                   ssl->handshake->randbytes,
-                                  CLIENT_HELLO_RANDOM_LEN ) ) != 0 )
+                                  MBEDTLS_CLIENT_HELLO_RANDOM_LEN ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret );
         return( ret );
@@ -369,6 +842,7 @@
 
 /*
  * Write ClientHello handshake message.
+ * Handler for MBEDTLS_SSL_CLIENT_HELLO
  */
 static int ssl_tls13_write_client_hello( mbedtls_ssl_context *ssl )
 {
@@ -404,11 +878,750 @@
     return ret;
 }
 
+/*
+ * Functions for parsing and processing Server Hello
+ */
+/* Returns a negative value on failure, and otherwise
+ * - SSL_SERVER_HELLO_COORDINATE_HELLO or
+ * - SSL_SERVER_HELLO_COORDINATE_HRR
+ * to indicate which message is expected and to be parsed next. */
+#define SSL_SERVER_HELLO_COORDINATE_HELLO 0
+#define SSL_SERVER_HELLO_COORDINATE_HRR 1
+static int ssl_server_hello_is_hrr( mbedtls_ssl_context *ssl,
+                                    const unsigned char *buf,
+                                    const unsigned char *end )
+{
+    static const unsigned char magic_hrr_string[MBEDTLS_SERVER_HELLO_RANDOM_LEN] =
+        { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
+          0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
+          0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
+          0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33 ,0x9C };
+
+    /* Check whether this message is a HelloRetryRequest ( HRR ) message.
+     *
+     * Server Hello and HRR are only distinguished by Random set to the
+     * special value of the SHA-256 of "HelloRetryRequest".
+     *
+     * struct {
+     *    ProtocolVersion legacy_version = 0x0303;
+     *    Random random;
+     *    opaque legacy_session_id_echo<0..32>;
+     *    CipherSuite cipher_suite;
+     *    uint8 legacy_compression_method = 0;
+     *    Extension extensions<6..2^16-1>;
+     * } ServerHello;
+     *
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, 2 + sizeof( magic_hrr_string ) );
+
+    if( memcmp( buf + 2, magic_hrr_string, sizeof( magic_hrr_string ) ) == 0 )
+    {
+        return( SSL_SERVER_HELLO_COORDINATE_HRR );
+    }
+
+    return( SSL_SERVER_HELLO_COORDINATE_HELLO );
+}
+
+/* Fetch and preprocess
+ * Returns a negative value on failure, and otherwise
+ * - SSL_SERVER_HELLO_COORDINATE_HELLO or
+ * - SSL_SERVER_HELLO_COORDINATE_HRR
+ */
+static int ssl_tls13_server_hello_coordinate( mbedtls_ssl_context *ssl,
+                                              unsigned char **buf,
+                                              size_t *buf_len )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_read_record( ssl, 0 ) );
+
+    if( ( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) ||
+        ( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "unexpected message" ) );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
+                                      MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    *buf = ssl->in_msg + 4;
+    *buf_len = ssl->in_hslen - 4;
+
+    ret = ssl_server_hello_is_hrr( ssl, *buf, *buf + *buf_len );
+    switch( ret )
+    {
+        case SSL_SERVER_HELLO_COORDINATE_HELLO:
+            MBEDTLS_SSL_DEBUG_MSG( 2, ( "received ServerHello message" ) );
+            break;
+        case SSL_SERVER_HELLO_COORDINATE_HRR:
+            MBEDTLS_SSL_DEBUG_MSG( 2, ( "received HelloRetryRequest message" ) );
+            break;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+static int ssl_tls13_check_server_hello_session_id_echo( mbedtls_ssl_context *ssl,
+                                                         const unsigned char **buf,
+                                                         const unsigned char *end )
+{
+    const unsigned char *p = *buf;
+    size_t legacy_session_id_echo_len;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 1 );
+    legacy_session_id_echo_len = *p++ ;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, legacy_session_id_echo_len );
+
+    /* legacy_session_id_echo */
+    if( ssl->session_negotiate->id_len != legacy_session_id_echo_len ||
+        memcmp( ssl->session_negotiate->id, p , legacy_session_id_echo_len ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_BUF( 3, "Expected Session ID",
+                               ssl->session_negotiate->id,
+                               ssl->session_negotiate->id_len );
+        MBEDTLS_SSL_DEBUG_BUF( 3, "Received Session ID", p,
+                               legacy_session_id_echo_len );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+
+    p += legacy_session_id_echo_len;
+    *buf = p;
+
+    MBEDTLS_SSL_DEBUG_BUF( 3, "Session ID", ssl->session_negotiate->id,
+                            ssl->session_negotiate->id_len );
+    return( 0 );
+}
+
+static int ssl_tls13_cipher_suite_is_offered( mbedtls_ssl_context *ssl,
+                                              int cipher_suite )
+{
+    const int *ciphersuite_list = ssl->conf->ciphersuite_list;
+
+    /* Check whether we have offered this ciphersuite */
+    for ( size_t i = 0; ciphersuite_list[i] != 0; i++ )
+    {
+        if( ciphersuite_list[i] == cipher_suite )
+        {
+            return( 1 );
+        }
+    }
+    return( 0 );
+}
+
+/* Parse ServerHello message and configure context
+ *
+ * struct {
+ *    ProtocolVersion legacy_version = 0x0303; // TLS 1.2
+ *    Random random;
+ *    opaque legacy_session_id_echo<0..32>;
+ *    CipherSuite cipher_suite;
+ *    uint8 legacy_compression_method = 0;
+ *    Extension extensions<6..2^16-1>;
+ * } ServerHello;
+ */
+static int ssl_tls13_parse_server_hello( mbedtls_ssl_context *ssl,
+                                         const unsigned char *buf,
+                                         const unsigned char *end )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *p = buf;
+    size_t extensions_len;
+    const unsigned char *extensions_end;
+    uint16_t cipher_suite;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+
+    /*
+     * Check there is space for minimal fields
+     *
+     * - legacy_version             ( 2 bytes)
+     * - random                     (MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes)
+     * - legacy_session_id_echo     ( 1 byte ), minimum size
+     * - cipher_suite               ( 2 bytes)
+     * - legacy_compression_method  ( 1 byte )
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 6 );
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "server hello", p, end - p );
+    MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", p, 2 );
+
+    /* ...
+     * ProtocolVersion legacy_version = 0x0303; // TLS 1.2
+     * ...
+     * with ProtocolVersion defined as:
+     * uint16 ProtocolVersion;
+     */
+    if( !( p[0] == MBEDTLS_SSL_MAJOR_VERSION_3 &&
+           p[1] == MBEDTLS_SSL_MINOR_VERSION_3 ) )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Unsupported version of TLS." ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION,
+                                      MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION );
+        return( MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION );
+    }
+    p += 2;
+
+    /* ...
+     * Random random;
+     * ...
+     * with Random defined as:
+     * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN];
+     */
+    memcpy( &ssl->handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], p,
+            MBEDTLS_SERVER_HELLO_RANDOM_LEN );
+    MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes",
+                           p, MBEDTLS_SERVER_HELLO_RANDOM_LEN );
+    p += MBEDTLS_SERVER_HELLO_RANDOM_LEN;
+
+    /* ...
+     * opaque legacy_session_id_echo<0..32>;
+     * ...
+     */
+    if( ssl_tls13_check_server_hello_session_id_echo( ssl, &p, end ) != 0 )
+    {
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+
+    /* ...
+     * CipherSuite cipher_suite;
+     * ...
+     * with CipherSuite defined as:
+     * uint8 CipherSuite[2];
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
+    cipher_suite = MBEDTLS_GET_UINT16_BE( p, 0 );
+    p += 2;
+
+
+    /*
+     * Check whether this ciphersuite is supported and offered.
+     * Via the force_ciphersuite version we may have instructed the client
+     * to use a different ciphersuite.
+     */
+    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( cipher_suite );
+    if( ciphersuite_info == NULL ||
+        ssl_tls13_cipher_suite_is_offered( ssl, cipher_suite ) == 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite(%04x) not found or not offered",
+                                    cipher_suite ) );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+
+
+    /* Configure ciphersuites */
+    mbedtls_ssl_optimize_checksum( ssl, ciphersuite_info );
+
+    ssl->handshake->ciphersuite_info = ciphersuite_info;
+    ssl->session_negotiate->ciphersuite = cipher_suite;
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: ( %04x ) - %s",
+                                 cipher_suite, ciphersuite_info->name ) );
+
+#if defined(MBEDTLS_HAVE_TIME)
+    ssl->session_negotiate->start = time( NULL );
+#endif /* MBEDTLS_HAVE_TIME */
+
+    /* ...
+     * uint8 legacy_compression_method = 0;
+     * ...
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 1 );
+    if( p[0] != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad legacy compression method" ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+    p++;
+
+    /* ...
+     * Extension extensions<6..2^16-1>;
+     * ...
+     * struct {
+     *      ExtensionType extension_type; (2 bytes)
+     *      opaque extension_data<0..2^16-1>;
+     * } Extension;
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
+    extensions_len = MBEDTLS_GET_UINT16_BE( p, 0 );
+    p += 2;
+
+    /* Check extensions do not go beyond the buffer of data. */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, extensions_len );
+    extensions_end = p + extensions_len;
+
+    MBEDTLS_SSL_DEBUG_BUF( 3, "server hello extensions", p, extensions_len );
+
+    while( p < extensions_end )
+    {
+        unsigned int extension_type;
+        size_t extension_data_len;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, 4 );
+        extension_type = MBEDTLS_GET_UINT16_BE( p, 0 );
+        extension_data_len = MBEDTLS_GET_UINT16_BE( p, 2 );
+        p += 4;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, extension_data_len );
+
+        switch( extension_type )
+        {
+            case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS:
+                MBEDTLS_SSL_DEBUG_MSG( 3,
+                            ( "found supported_versions extension" ) );
+
+                ret = ssl_tls13_parse_supported_versions_ext( ssl,
+                                                              p,
+                                                              p + extension_data_len );
+                if( ret != 0 )
+                    return( ret );
+                break;
+
+            case MBEDTLS_TLS_EXT_PRE_SHARED_KEY:
+                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found pre_shared_key extension." ) );
+                MBEDTLS_SSL_DEBUG_MSG( 3, ( "pre_shared_key:Not supported yet" ) );
+
+                MBEDTLS_SSL_PEND_FATAL_ALERT(
+                    MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT,
+                    MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION );
+                return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION );
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+            case MBEDTLS_TLS_EXT_KEY_SHARE:
+                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found key_shares extension" ) );
+                if( ( ret = ssl_tls13_parse_key_share_ext( ssl,
+                                            p, p + extension_data_len ) ) != 0 )
+                {
+                    MBEDTLS_SSL_DEBUG_RET( 1,
+                                           "ssl_tls13_parse_key_share_ext",
+                                           ret );
+                    return( ret );
+                }
+                break;
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
+            default:
+                MBEDTLS_SSL_DEBUG_MSG(
+                    3,
+                    ( "unknown extension found: %u ( ignoring )",
+                      extension_type ) );
+
+                MBEDTLS_SSL_PEND_FATAL_ALERT(
+                    MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT,
+                    MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION );
+                return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION );
+        }
+
+        p += extension_data_len;
+    }
+
+    return( 0 );
+}
+
+static int ssl_tls13_finalize_server_hello( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_key_set traffic_keys;
+    mbedtls_ssl_transform *transform_handshake = NULL;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    /* Determine the key exchange mode:
+     * 1) If both the pre_shared_key and key_share extensions were received
+     *    then the key exchange mode is PSK with EPHEMERAL.
+     * 2) If only the pre_shared_key extension was received then the key
+     *    exchange mode is PSK-only.
+     * 3) If only the key_share extension was received then the key
+     *    exchange mode is EPHEMERAL-only.
+     */
+    switch( handshake->extensions_present &
+            ( MBEDTLS_SSL_EXT_PRE_SHARED_KEY | MBEDTLS_SSL_EXT_KEY_SHARE ) )
+    {
+        /* Only the pre_shared_key extension was received */
+        case MBEDTLS_SSL_EXT_PRE_SHARED_KEY:
+            handshake->tls1_3_kex_modes = MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK;
+            break;
+
+        /* Only the key_share extension was received */
+        case MBEDTLS_SSL_EXT_KEY_SHARE:
+            handshake->tls1_3_kex_modes = MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_EPHEMERAL;
+            break;
+
+        /* Both the pre_shared_key and key_share extensions were received */
+        case ( MBEDTLS_SSL_EXT_PRE_SHARED_KEY | MBEDTLS_SSL_EXT_KEY_SHARE ):
+            handshake->tls1_3_kex_modes = MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
+            break;
+
+        /* Neither pre_shared_key nor key_share extension was received */
+        default:
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Unknown key exchange." ) );
+            ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+            goto cleanup;
+    }
+
+    /* Start the TLS 1.3 key schedule: Set the PSK and derive early secret.
+     *
+     * TODO: We don't have to do this in case we offered 0-RTT and the
+     *       server accepted it. In this case, we could skip generating
+     *       the early secret. */
+    ret = mbedtls_ssl_tls1_3_key_schedule_stage_early( ssl );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_key_schedule_stage_early_data",
+                               ret );
+        goto cleanup;
+    }
+
+    /* Compute handshake secret */
+    ret = mbedtls_ssl_tls13_key_schedule_stage_handshake( ssl );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_derive_master_secret", ret );
+        goto cleanup;
+    }
+
+    /* Next evolution in key schedule: Establish handshake secret and
+     * key material. */
+    ret = mbedtls_ssl_tls13_generate_handshake_keys( ssl, &traffic_keys );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_generate_handshake_keys",
+                               ret );
+        goto cleanup;
+    }
+
+    transform_handshake = mbedtls_calloc( 1, sizeof( mbedtls_ssl_transform ) );
+    if( transform_handshake == NULL )
+    {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto cleanup;
+    }
+
+    ret = mbedtls_ssl_tls13_populate_transform( transform_handshake,
+                              ssl->conf->endpoint,
+                              ssl->session_negotiate->ciphersuite,
+                              &traffic_keys,
+                              ssl );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_populate_transform", ret );
+        goto cleanup;
+    }
+
+    handshake->transform_handshake = transform_handshake;
+    mbedtls_ssl_set_inbound_transform( ssl, transform_handshake );
+
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to handshake keys for inbound traffic" ) );
+    ssl->session_in = ssl->session_negotiate;
+
+    /*
+     * State machine update
+     */
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS );
+
+cleanup:
+
+    mbedtls_platform_zeroize( &traffic_keys, sizeof( traffic_keys ) );
+    if( ret != 0 )
+    {
+        mbedtls_free( transform_handshake );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+            MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+    }
+    return( ret );
+}
+
+/*
+ * Wait and parse ServerHello handshake message.
+ * Handler for MBEDTLS_SSL_SERVER_HELLO
+ */
+static int ssl_tls1_3_process_server_hello( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *buf;
+    size_t buf_len;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> %s", __func__ ) );
+
+    /* Coordination step
+     * - Fetch record
+     * - Make sure it's either a ServerHello or a HRR.
+     * - Switch processing routine in case of HRR
+     */
+    ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3;
+    ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE;
+
+    ret = ssl_tls13_server_hello_coordinate( ssl, &buf, &buf_len );
+    /* Parsing step
+     * We know what message to expect by now and call
+     * the respective parsing function.
+     */
+    if( ret == SSL_SERVER_HELLO_COORDINATE_HELLO )
+    {
+        MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_server_hello( ssl, buf,
+                                                            buf + buf_len ) );
+
+        mbedtls_ssl_tls1_3_add_hs_msg_to_checksum( ssl,
+                                                   MBEDTLS_SSL_HS_SERVER_HELLO,
+                                                   buf, buf_len );
+
+        MBEDTLS_SSL_PROC_CHK( ssl_tls13_finalize_server_hello( ssl ) );
+    }
+    else if( ret == SSL_SERVER_HELLO_COORDINATE_HRR )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "HRR not supported" ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ,
+                                      MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+        ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+cleanup:
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= %s", __func__ ) );
+    return( ret );
+}
+
+/*
+ *
+ * EncryptedExtensions message
+ *
+ * The EncryptedExtensions message contains any extensions which
+ * should be protected, i.e., any which are not needed to establish
+ * the cryptographic context.
+ */
+
+/*
+ * Overview
+ */
+
+/* Main entry point; orchestrates the other functions */
+static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl );
+
+static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl,
+                                                 const unsigned char *buf,
+                                                 const unsigned char *end );
+static int ssl_tls13_postprocess_encrypted_extensions( mbedtls_ssl_context *ssl );
+
+/*
+ * Handler for  MBEDTLS_SSL_ENCRYPTED_EXTENSIONS
+ */
+static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl )
+{
+    int ret;
+    unsigned char *buf;
+    size_t buf_len;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse encrypted extensions" ) );
+
+    MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls1_3_fetch_handshake_msg( ssl,
+                                             MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                                             &buf, &buf_len ) );
+
+    /* Process the message contents */
+    MBEDTLS_SSL_PROC_CHK(
+        ssl_tls13_parse_encrypted_extensions( ssl, buf, buf + buf_len ) );
+
+    mbedtls_ssl_tls1_3_add_hs_msg_to_checksum(
+        ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, buf_len );
+
+    MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_encrypted_extensions( ssl ) );
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse encrypted extensions" ) );
+    return( ret );
+
+}
+
+/* Parse EncryptedExtensions message
+ * struct {
+ *     Extension extensions<0..2^16-1>;
+ * } EncryptedExtensions;
+ */
+static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl,
+                                                 const unsigned char *buf,
+                                                 const unsigned char *end )
+{
+    int ret = 0;
+    size_t extensions_len;
+    const unsigned char *p = buf;
+    const unsigned char *extensions_end;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
+    extensions_len = MBEDTLS_GET_UINT16_BE( p, 0 );
+    p += 2;
+
+    MBEDTLS_SSL_DEBUG_BUF( 3, "encrypted extensions", p, extensions_len );
+    extensions_end = p + extensions_len;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, extensions_len );
+
+    while( p < extensions_end )
+    {
+        unsigned int extension_type;
+        size_t extension_data_len;
+
+        /*
+         * struct {
+         *     ExtensionType extension_type; (2 bytes)
+         *     opaque extension_data<0..2^16-1>;
+         * } Extension;
+         */
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, 4 );
+        extension_type = MBEDTLS_GET_UINT16_BE( p, 0 );
+        extension_data_len = MBEDTLS_GET_UINT16_BE( p, 2 );
+        p += 4;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, extension_data_len );
+
+        /* The client MUST check EncryptedExtensions for the
+         * presence of any forbidden extensions and if any are found MUST abort
+         * the handshake with an "unsupported_extension" alert.
+         */
+        switch( extension_type )
+        {
+
+            case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS:
+                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extensions supported groups" ) );
+                break;
+
+            default:
+                MBEDTLS_SSL_DEBUG_MSG(
+                    3, ( "unsupported extension found: %u ", extension_type) );
+                MBEDTLS_SSL_PEND_FATAL_ALERT(
+                    MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT,   \
+                    MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION );
+                return ( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION );
+        }
+
+        p += extension_data_len;
+    }
+
+    /* Check that we consumed all the message. */
+    if( p != end )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "EncryptedExtension lengths misaligned" ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,   \
+                                      MBEDTLS_ERR_SSL_DECODE_ERROR );
+        return( MBEDTLS_ERR_SSL_DECODE_ERROR );
+    }
+
+    return( ret );
+}
+
+static int ssl_tls13_postprocess_encrypted_extensions( mbedtls_ssl_context *ssl )
+{
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST );
+    return( 0 );
+}
+
+/*
+ * Handler for  MBEDTLS_SSL_CERTIFICATE_REQUEST
+ */
+static int ssl_tls1_3_process_certificate_request( mbedtls_ssl_context *ssl )
+{
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_CERTIFICATE );
+    return( 0 );
+}
+
+/*
+ * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE
+ */
+static int ssl_tls1_3_process_server_certificate( mbedtls_ssl_context *ssl )
+{
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY );
+    return( 0 );
+}
+
+/*
+ * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY
+ */
+static int ssl_tls1_3_process_certificate_verify( mbedtls_ssl_context *ssl )
+{
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED );
+    return( 0 );
+}
+
+/*
+ * Handler for MBEDTLS_SSL_SERVER_FINISHED
+ */
+static int ssl_tls1_3_process_server_finished( mbedtls_ssl_context *ssl )
+{
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE );
+    return( 0 );
+}
+
+/*
+ * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE
+ */
+static int ssl_tls1_3_write_client_certificate( mbedtls_ssl_context *ssl )
+{
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY );
+    return( 0 );
+}
+
+/*
+ * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY
+ */
+static int ssl_tls1_3_write_client_certificate_verify( mbedtls_ssl_context *ssl )
+{
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED );
+    return( 0 );
+}
+
+/*
+ * Handler for MBEDTLS_SSL_CLIENT_FINISHED
+ */
+static int ssl_tls1_3_write_client_finished( mbedtls_ssl_context *ssl )
+{
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_FLUSH_BUFFERS );
+    return( 0 );
+}
+
+/*
+ * Handler for MBEDTLS_SSL_FLUSH_BUFFERS
+ */
+static int ssl_tls1_3_flush_buffers( mbedtls_ssl_context *ssl )
+{
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP );
+    return( 0 );
+}
+
+/*
+ * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP
+ */
+static int ssl_tls1_3_handshake_wrapup( mbedtls_ssl_context *ssl )
+{
+    ((void) ssl);
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
+    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+}
+
 int mbedtls_ssl_tls13_handshake_client_step( mbedtls_ssl_context *ssl )
 {
     int ret = 0;
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) );
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "tls1_3 client state: %d", ssl->state ) );
 
     switch( ssl->state )
     {
@@ -422,9 +1635,47 @@
             break;
 
         case MBEDTLS_SSL_SERVER_HELLO:
-            // Stop here : we haven't finished whole flow
-            ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-            mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS );
+            ret = ssl_tls1_3_process_server_hello( ssl );
+            break;
+
+        case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS:
+            ret = ssl_tls13_process_encrypted_extensions( ssl );
+            break;
+
+        case MBEDTLS_SSL_CERTIFICATE_REQUEST:
+            ret = ssl_tls1_3_process_certificate_request( ssl );
+            break;
+
+        case MBEDTLS_SSL_SERVER_CERTIFICATE:
+            ret = ssl_tls1_3_process_server_certificate( ssl );
+            break;
+
+        case MBEDTLS_SSL_CERTIFICATE_VERIFY:
+            ret = ssl_tls1_3_process_certificate_verify( ssl );
+            break;
+
+        case MBEDTLS_SSL_SERVER_FINISHED:
+            ret = ssl_tls1_3_process_server_finished( ssl );
+            break;
+
+        case MBEDTLS_SSL_CLIENT_CERTIFICATE:
+            ret = ssl_tls1_3_write_client_certificate( ssl );
+            break;
+
+        case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY:
+            ret = ssl_tls1_3_write_client_certificate_verify( ssl );
+            break;
+
+        case MBEDTLS_SSL_CLIENT_FINISHED:
+            ret = ssl_tls1_3_write_client_finished( ssl );
+            break;
+
+        case MBEDTLS_SSL_FLUSH_BUFFERS:
+            ret = ssl_tls1_3_flush_buffers( ssl );
+            break;
+
+        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
+            ret = ssl_tls1_3_handshake_wrapup( ssl );
             break;
 
         default:
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index ca4c167..b3a4a09 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -24,9 +24,48 @@
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
 
 #include "mbedtls/error.h"
+#include "mbedtls/debug.h"
 
 #include "ssl_misc.h"
 
+int mbedtls_ssl_tls1_3_fetch_handshake_msg( mbedtls_ssl_context *ssl,
+                                            unsigned hs_type,
+                                            unsigned char **buf,
+                                            size_t *buflen )
+{
+    int ret;
+
+    if( ( ret = mbedtls_ssl_read_record( ssl, 0 ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
+        goto cleanup;
+    }
+
+    if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ||
+        ssl->in_msg[0]  != hs_type )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Receive unexpected handshake message." ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
+                                      MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+        ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+        goto cleanup;
+    }
+
+    /*
+     * Jump handshake header (4 bytes, see Section 4 of RFC 8446).
+     *    ...
+     *    HandshakeType msg_type;
+     *    uint24 length;
+     *    ...
+     */
+    *buf    = ssl->in_msg   + 4;
+    *buflen = ssl->in_hslen - 4;
+
+cleanup:
+
+    return( ret );
+}
+
 int mbedtls_ssl_tls13_start_handshake_msg( mbedtls_ssl_context *ssl,
                                            unsigned hs_type,
                                            unsigned char **buf,
@@ -65,6 +104,15 @@
     return( ret );
 }
 
+void mbedtls_ssl_tls1_3_add_hs_msg_to_checksum( mbedtls_ssl_context *ssl,
+                                                unsigned hs_type,
+                                                unsigned char const *msg,
+                                                size_t msg_len )
+{
+    mbedtls_ssl_tls13_add_hs_hdr_to_checksum( ssl, hs_type, msg_len );
+    ssl->handshake->update_checksum( ssl, msg, msg_len );
+}
+
 void mbedtls_ssl_tls13_add_hs_hdr_to_checksum( mbedtls_ssl_context *ssl,
                                                unsigned hs_type,
                                                size_t total_hs_len )
@@ -99,17 +147,70 @@
  *
  * Only if we handle at least one key exchange that needs signatures.
  */
-
 int mbedtls_ssl_tls13_write_sig_alg_ext( mbedtls_ssl_context *ssl,
                                          unsigned char *buf,
                                          unsigned char *end,
                                          size_t *olen )
 {
-    ((void) ssl);
-    ((void) buf);
-    ((void) end);
-    ((void) olen);
-    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+    unsigned char *p = buf;
+    unsigned char *supported_sig_alg_ptr; /* Start of supported_signature_algorithms */
+    size_t supported_sig_alg_len = 0;     /* Length of supported_signature_algorithms */
+
+    *olen = 0;
+
+    /* Skip the extension on the client if all allowed key exchanges
+     * are PSK-based. */
+#if defined(MBEDTLS_SSL_CLI_C)
+    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+        !mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) )
+    {
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CLI_C */
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding signature_algorithms extension" ) );
+
+    /* Check if we have space for header and length field:
+     * - extension_type         (2 bytes)
+     * - extension_data_length  (2 bytes)
+     * - supported_signature_algorithms_length   (2 bytes)
+     */
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 );
+    p += 6;
+
+    /*
+     * Write supported_signature_algorithms
+     */
+    supported_sig_alg_ptr = p;
+    for( const uint16_t *sig_alg = ssl->conf->tls13_sig_algs;
+         *sig_alg != MBEDTLS_TLS13_SIG_NONE; sig_alg++ )
+    {
+        MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
+        MBEDTLS_PUT_UINT16_BE( *sig_alg, p, 0 );
+        p += 2;
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "signature scheme [%x]", *sig_alg ) );
+    }
+
+    /* Length of supported_signature_algorithms */
+    supported_sig_alg_len = p - supported_sig_alg_ptr;
+    if( supported_sig_alg_len == 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "No signature algorithms defined." ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    /* Write extension_type */
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SIG_ALG, buf, 0 );
+    /* Write extension_data_length */
+    MBEDTLS_PUT_UINT16_BE( supported_sig_alg_len + 2, buf, 2 );
+    /* Write length of supported_signature_algorithms */
+    MBEDTLS_PUT_UINT16_BE( supported_sig_alg_len, buf, 4 );
+
+    /* Output the total length of signature algorithms extension. */
+    *olen = p - buf;
+
+    ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SIG_ALG;
+    return( 0 );
 }
 
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
diff --git a/library/ssl_tls13_keys.c b/library/ssl_tls13_keys.c
index 7aec21d..96f5310 100644
--- a/library/ssl_tls13_keys.c
+++ b/library/ssl_tls13_keys.c
@@ -21,14 +21,16 @@
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
 
-#include "mbedtls/hkdf.h"
-#include "ssl_misc.h"
-#include "ssl_tls13_keys.h"
-#include "mbedtls/debug.h"
-
 #include <stdint.h>
 #include <string.h>
 
+#include "mbedtls/hkdf.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
+
+#include "ssl_misc.h"
+#include "ssl_tls13_keys.h"
+
 #define MBEDTLS_SSL_TLS1_3_LABEL( name, string )       \
     .name = string,
 
@@ -820,4 +822,210 @@
     return( 0 );
 }
 
+int mbedtls_ssl_tls1_3_key_schedule_stage_early( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_type_t md_type;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    if( handshake->ciphersuite_info == NULL )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher suite info not found" ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    md_type = handshake->ciphersuite_info->mac;
+
+    ret = mbedtls_ssl_tls1_3_evolve_secret( md_type, NULL, NULL, 0,
+                                            handshake->tls1_3_master_secrets.early );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_evolve_secret", ret );
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+/* mbedtls_ssl_tls13_generate_handshake_keys() generates keys necessary for
+ * protecting the handshake messages, as described in Section 7 of TLS 1.3. */
+int mbedtls_ssl_tls13_generate_handshake_keys( mbedtls_ssl_context *ssl,
+                                               mbedtls_ssl_key_set *traffic_keys )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    mbedtls_md_type_t md_type;
+    mbedtls_md_info_t const *md_info;
+    size_t md_size;
+
+    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    size_t transcript_len;
+
+    mbedtls_cipher_info_t const *cipher_info;
+    size_t keylen, ivlen;
+
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info;
+    mbedtls_ssl_tls1_3_handshake_secrets *tls13_hs_secrets = &handshake->tls13_hs_secrets;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_tls13_generate_handshake_keys" ) );
+
+    cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
+    keylen = cipher_info->key_bitlen >> 3;
+    ivlen = cipher_info->iv_size;
+
+    md_type = ciphersuite_info->mac;
+    md_info = mbedtls_md_info_from_type( md_type );
+    md_size = mbedtls_md_get_size( md_info );
+
+    ret = mbedtls_ssl_get_handshake_transcript( ssl, md_type,
+                                                transcript,
+                                                sizeof( transcript ),
+                                                &transcript_len );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1,
+                               "mbedtls_ssl_get_handshake_transcript",
+                               ret );
+        return( ret );
+    }
+
+    ret = mbedtls_ssl_tls1_3_derive_handshake_secrets( md_type,
+                                    handshake->tls1_3_master_secrets.handshake,
+                                    transcript, transcript_len, tls13_hs_secrets );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_derive_handshake_secrets",
+                               ret );
+        return( ret );
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "Client handshake traffic secret",
+                    tls13_hs_secrets->client_handshake_traffic_secret,
+                    md_size );
+    MBEDTLS_SSL_DEBUG_BUF( 4, "Server handshake traffic secret",
+                    tls13_hs_secrets->server_handshake_traffic_secret,
+                    md_size );
+
+    /*
+     * Export client handshake traffic secret
+     */
+    if( ssl->f_export_keys != NULL )
+    {
+        ssl->f_export_keys( ssl->p_export_keys,
+                MBEDTLS_SSL_KEY_EXPORT_TLS13_CLIENT_HANDSHAKE_TRAFFIC_SECRET,
+                tls13_hs_secrets->client_handshake_traffic_secret,
+                md_size,
+                handshake->randbytes + 32,
+                handshake->randbytes,
+                MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */ );
+
+        ssl->f_export_keys( ssl->p_export_keys,
+                MBEDTLS_SSL_KEY_EXPORT_TLS13_SERVER_HANDSHAKE_TRAFFIC_SECRET,
+                tls13_hs_secrets->server_handshake_traffic_secret,
+                md_size,
+                handshake->randbytes + 32,
+                handshake->randbytes,
+                MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */ );
+    }
+
+    ret = mbedtls_ssl_tls1_3_make_traffic_keys( md_type,
+                            tls13_hs_secrets->client_handshake_traffic_secret,
+                            tls13_hs_secrets->server_handshake_traffic_secret,
+                            md_size, keylen, ivlen, traffic_keys );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_make_traffic_keys", ret );
+        goto exit;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "client_handshake write_key",
+                           traffic_keys->client_write_key,
+                           traffic_keys->key_len);
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "server_handshake write_key",
+                           traffic_keys->server_write_key,
+                           traffic_keys->key_len);
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "client_handshake write_iv",
+                           traffic_keys->client_write_iv,
+                           traffic_keys->iv_len);
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "server_handshake write_iv",
+                           traffic_keys->server_write_iv,
+                           traffic_keys->iv_len);
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_tls13_generate_handshake_keys" ) );
+
+exit:
+
+    return( ret );
+}
+
+int mbedtls_ssl_tls13_key_schedule_stage_handshake( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    mbedtls_md_type_t const md_type = handshake->ciphersuite_info->mac;
+    size_t ephemeral_len = 0;
+    unsigned char ecdhe[MBEDTLS_ECP_MAX_BYTES];
+#if defined(MBEDTLS_DEBUG_C)
+    mbedtls_md_info_t const * const md_info = mbedtls_md_info_from_type( md_type );
+    size_t const md_size = mbedtls_md_get_size( md_info );
+#endif /* MBEDTLS_DEBUG_C */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
+    /*
+     * Compute ECDHE secret used to compute the handshake secret from which
+     * client_handshake_traffic_secret and server_handshake_traffic_secret
+     * are derived in the handshake secret derivation stage.
+     */
+    if( mbedtls_ssl_tls1_3_ephemeral_enabled( ssl ) )
+    {
+        if( mbedtls_ssl_tls13_named_group_is_ecdhe( handshake->offered_group_id ) )
+        {
+#if defined(MBEDTLS_ECDH_C)
+            ret = mbedtls_ecdh_calc_secret( &handshake->ecdh_ctx,
+                                            &ephemeral_len, ecdhe, sizeof( ecdhe ),
+                                            ssl->conf->f_rng,
+                                            ssl->conf->p_rng );
+            if( ret != 0 )
+            {
+                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret );
+                return( ret );
+            }
+#endif /* MBEDTLS_ECDH_C */
+        }
+        else if( mbedtls_ssl_tls13_named_group_is_dhe( handshake->offered_group_id ) )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHE not supported." ) );
+            return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+        }
+    }
+#else
+    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */
+
+    /*
+     * Compute the Handshake Secret
+     */
+    ret = mbedtls_ssl_tls1_3_evolve_secret( md_type,
+                                            handshake->tls1_3_master_secrets.early,
+                                            ecdhe, ephemeral_len,
+                                            handshake->tls1_3_master_secrets.handshake );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_evolve_secret", ret );
+        return( ret );
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "Handshake secret",
+                           handshake->tls1_3_master_secrets.handshake, md_size );
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
+    mbedtls_platform_zeroize( ecdhe, sizeof( ecdhe ) );
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */
+    return( 0 );
+}
+
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
diff --git a/library/ssl_tls13_keys.h b/library/ssl_tls13_keys.h
index ca892b1..384f433 100644
--- a/library/ssl_tls13_keys.h
+++ b/library/ssl_tls13_keys.h
@@ -70,27 +70,6 @@
 #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN  \
     MBEDTLS_MD_MAX_SIZE
 
-typedef struct
-{
-    unsigned char binder_key                  [ MBEDTLS_MD_MAX_SIZE ];
-    unsigned char client_early_traffic_secret [ MBEDTLS_MD_MAX_SIZE ];
-    unsigned char early_exporter_master_secret[ MBEDTLS_MD_MAX_SIZE ];
-} mbedtls_ssl_tls1_3_early_secrets;
-
-typedef struct
-{
-    unsigned char client_handshake_traffic_secret[ MBEDTLS_MD_MAX_SIZE ];
-    unsigned char server_handshake_traffic_secret[ MBEDTLS_MD_MAX_SIZE ];
-} mbedtls_ssl_tls1_3_handshake_secrets;
-
-typedef struct
-{
-    unsigned char client_application_traffic_secret_N[ MBEDTLS_MD_MAX_SIZE ];
-    unsigned char server_application_traffic_secret_N[ MBEDTLS_MD_MAX_SIZE ];
-    unsigned char exporter_master_secret             [ MBEDTLS_MD_MAX_SIZE ];
-    unsigned char resumption_master_secret           [ MBEDTLS_MD_MAX_SIZE ];
-} mbedtls_ssl_tls1_3_application_secrets;
-
 /* Maximum desired length for expanded key material generated
  * by HKDF-Expand-Label.
  *
@@ -531,4 +510,59 @@
                                           mbedtls_ssl_key_set const *traffic_keys,
                                           mbedtls_ssl_context *ssl );
 
+/*
+ * TLS 1.3 key schedule evolutions
+ *
+ *   Early -> Handshake -> Application
+ *
+ * Small wrappers around mbedtls_ssl_tls1_3_evolve_secret().
+ */
+
+/**
+ * \brief Begin TLS 1.3 key schedule by calculating early secret.
+ *
+ *        The TLS 1.3 key schedule can be viewed as a simple state machine
+ *        with states Initial -> Early -> Handshake -> Application, and
+ *        this function represents the Initial -> Early transition.
+ *
+ * \param ssl  The SSL context to operate on.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+int mbedtls_ssl_tls1_3_key_schedule_stage_early( mbedtls_ssl_context *ssl );
+
+/**
+ * \brief Transition into handshake stage of TLS 1.3 key schedule.
+ *
+ *        The TLS 1.3 key schedule can be viewed as a simple state machine
+ *        with states Initial -> Early -> Handshake -> Application, and
+ *        this function represents the Early -> Handshake transition.
+ *
+ *        In the handshake stage, mbedtls_ssl_tls13_generate_handshake_keys()
+ *        can be used to derive the handshake traffic keys.
+ *
+ * \param ssl  The SSL context to operate on. This must be in key schedule
+ *             stage \c Early.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+int mbedtls_ssl_tls13_key_schedule_stage_handshake( mbedtls_ssl_context *ssl );
+
+/**
+ * \brief Compute TLS 1.3 handshake traffic keys.
+ *
+ * \param ssl  The SSL context to operate on. This must be in
+ *             key schedule stage \c Handshake, see
+ *             mbedtls_ssl_tls13_key_schedule_stage_handshake().
+ * \param traffic_keys The address at which to store the handshake traffic key
+ *                     keys. This must be writable but may be uninitialized.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+int mbedtls_ssl_tls13_generate_handshake_keys( mbedtls_ssl_context *ssl,
+                                               mbedtls_ssl_key_set *traffic_keys );
+
 #endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 0dcd7ed..86f44cb 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -23,11 +23,15 @@
 
 #if defined(MBEDTLS_SSL_SRV_C)
 
+#include "mbedtls/debug.h"
+
 #include "ssl_misc.h"
 
 int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl )
 {
     ((void) ssl);
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "tls1_3 server state: %d", ssl->state ) );
+
     return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
 }
 
diff --git a/programs/.gitignore b/programs/.gitignore
index d8eb6ba..deb104a 100644
--- a/programs/.gitignore
+++ b/programs/.gitignore
@@ -69,6 +69,7 @@
 x509/cert_req
 x509/cert_write
 x509/crl_app
+x509/load_roots
 x509/req_app
 
 # Generated data files
diff --git a/programs/Makefile b/programs/Makefile
index 02eb5a1..7f9d11e 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -110,6 +110,7 @@
 	x509/cert_req \
 	x509/cert_write \
 	x509/crl_app \
+	x509/load_roots \
 	x509/req_app \
 # End of APPS
 
@@ -387,6 +388,10 @@
 	echo "  CC    x509/cert_req.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/cert_req.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+x509/load_roots$(EXEXT): x509/load_roots.c $(DEP)
+	echo "  CC    x509/load_roots.c"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/load_roots.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 x509/req_app$(EXEXT): x509/req_app.c $(DEP)
 	echo "  CC    x509/req_app.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/req_app.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c
index a8026a3..5ed2ece 100644
--- a/programs/aes/crypt_and_hash.c
+++ b/programs/aes/crypt_and_hash.c
@@ -124,7 +124,7 @@
         while( *list )
         {
             cipher_info = mbedtls_cipher_info_from_type( *list );
-            mbedtls_printf( "  %s\n", cipher_info->MBEDTLS_PRIVATE(name) );
+            mbedtls_printf( "  %s\n", mbedtls_cipher_info_get_name( cipher_info ) );
             list++;
         }
 
@@ -309,7 +309,9 @@
 
         }
 
-        if( mbedtls_cipher_setkey( &cipher_ctx, digest, cipher_info->MBEDTLS_PRIVATE(key_bitlen),
+        if( mbedtls_cipher_setkey( &cipher_ctx,
+                                   digest,
+                                   (int) mbedtls_cipher_info_get_key_bitlen( cipher_info ),
                            MBEDTLS_ENCRYPT ) != 0 )
         {
             mbedtls_fprintf( stderr, "mbedtls_cipher_setkey() returned error\n");
@@ -408,7 +410,7 @@
         /*
          * Check the file size.
          */
-        if( cipher_info->MBEDTLS_PRIVATE(mode) != MBEDTLS_MODE_GCM &&
+        if( mbedtls_cipher_info_get_mode( cipher_info ) != MBEDTLS_MODE_GCM &&
             ( ( filesize - mbedtls_md_get_size( md_info ) ) %
                 mbedtls_cipher_get_block_size( &cipher_ctx ) ) != 0 )
         {
@@ -448,7 +450,9 @@
             mbedtls_md_finish( &md_ctx, digest );
         }
 
-        if( mbedtls_cipher_setkey( &cipher_ctx, digest, cipher_info->MBEDTLS_PRIVATE(key_bitlen),
+        if( mbedtls_cipher_setkey( &cipher_ctx,
+                                   digest,
+                                   (int) mbedtls_cipher_info_get_key_bitlen( cipher_info ),
                            MBEDTLS_DECRYPT ) != 0 )
         {
             mbedtls_fprintf( stderr, "mbedtls_cipher_setkey() returned error\n" );
diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c
index eccb42a..d633e4d 100644
--- a/programs/pkey/dh_client.c
+++ b/programs/pkey/dh_client.c
@@ -270,7 +270,9 @@
     mbedtls_printf( "...\n  . Receiving and decrypting the ciphertext" );
     fflush( stdout );
 
-    mbedtls_aes_setkey_dec( &aes, buf, 256 );
+    ret = mbedtls_aes_setkey_dec( &aes, buf, 256 );
+    if( ret != 0 )
+        goto exit;
 
     memset( buf, 0, sizeof( buf ) );
 
@@ -280,7 +282,9 @@
         goto exit;
     }
 
-    mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, buf, buf );
+    ret = mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, buf, buf );
+    if( ret != 0 )
+        goto exit;
     buf[16] = '\0';
     mbedtls_printf( "\n  . Plaintext is \"%s\"\n\n", (char *) buf );
 
diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c
index 0ddb85c..75713ff 100644
--- a/programs/pkey/dh_server.c
+++ b/programs/pkey/dh_server.c
@@ -290,9 +290,13 @@
     mbedtls_printf( "...\n  . Encrypting and sending the ciphertext" );
     fflush( stdout );
 
-    mbedtls_aes_setkey_enc( &aes, buf, 256 );
+    ret = mbedtls_aes_setkey_enc( &aes, buf, 256 );
+    if( ret != 0 )
+        goto exit;
     memcpy( buf, PLAINTEXT, 16 );
-    mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_ENCRYPT, buf, buf );
+    ret = mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_ENCRYPT, buf, buf );
+    if( ret != 0 )
+        goto exit;
 
     if( ( ret = mbedtls_net_send( &client_fd, buf, 16 ) ) != 16 )
     {
diff --git a/programs/pkey/ecdsa.c b/programs/pkey/ecdsa.c
index 6b6e951..550a230 100644
--- a/programs/pkey/ecdsa.c
+++ b/programs/pkey/ecdsa.c
@@ -51,7 +51,7 @@
 #define ECPARAMS    MBEDTLS_ECP_DP_SECP192R1
 
 #if !defined(ECPARAMS)
-#define ECPARAMS    mbedtls_ecp_curve_list()->MBEDTLS_PRIVATE(grp_id)
+#define ECPARAMS    mbedtls_ecp_curve_list()->grp_id
 #endif
 
 #if !defined(MBEDTLS_ECDSA_C) || !defined(MBEDTLS_SHA256_C) || \
diff --git a/programs/pkey/gen_key.c b/programs/pkey/gen_key.c
index 4043dfa..7535eee 100644
--- a/programs/pkey/gen_key.c
+++ b/programs/pkey/gen_key.c
@@ -86,7 +86,7 @@
 #endif
 
 #if defined(MBEDTLS_ECP_C)
-#define DFL_EC_CURVE            mbedtls_ecp_curve_list()->MBEDTLS_PRIVATE(grp_id)
+#define DFL_EC_CURVE            mbedtls_ecp_curve_list()->grp_id
 #else
 #define DFL_EC_CURVE            0
 #endif
@@ -219,9 +219,9 @@
 #if defined(MBEDTLS_ECP_C)
         mbedtls_printf( " available ec_curve values:\n" );
         curve_info = mbedtls_ecp_curve_list();
-        mbedtls_printf( "    %s (default)\n", curve_info->MBEDTLS_PRIVATE(name) );
-        while( ( ++curve_info )->MBEDTLS_PRIVATE(name) != NULL )
-            mbedtls_printf( "    %s\n", curve_info->MBEDTLS_PRIVATE(name) );
+        mbedtls_printf( "    %s (default)\n", curve_info->name );
+        while( ( ++curve_info )->name != NULL )
+            mbedtls_printf( "    %s\n", curve_info->name );
 #endif /* MBEDTLS_ECP_C */
         goto exit;
     }
@@ -270,7 +270,7 @@
         {
             if( ( curve_info = mbedtls_ecp_curve_info_from_name( q ) ) == NULL )
                 goto usage;
-            opt.ec_curve = curve_info->MBEDTLS_PRIVATE(grp_id);
+            opt.ec_curve = curve_info->grp_id;
         }
 #endif
         else if( strcmp( p, "filename" ) == 0 )
@@ -391,7 +391,7 @@
     {
         mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( key );
         mbedtls_printf( "curve: %s\n",
-                mbedtls_ecp_curve_info_from_grp_id( ecp->MBEDTLS_PRIVATE(grp).id )->MBEDTLS_PRIVATE(name) );
+                mbedtls_ecp_curve_info_from_grp_id( ecp->MBEDTLS_PRIVATE(grp).id )->name );
         mbedtls_mpi_write_file( "X_Q:   ", &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), 16, NULL );
         mbedtls_mpi_write_file( "Y_Q:   ", &ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), 16, NULL );
         mbedtls_mpi_write_file( "D:     ", &ecp->MBEDTLS_PRIVATE(d)  , 16, NULL );
diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c
index 8a09af5..ed6addf 100644
--- a/programs/pkey/key_app_writer.c
+++ b/programs/pkey/key_app_writer.c
@@ -202,7 +202,9 @@
 {
     int ret = 1;
     int exit_code = MBEDTLS_EXIT_FAILURE;
-    char buf[1024];
+#if defined(MBEDTLS_ERROR_C)
+    char buf[200];
+#endif
     int i;
     char *p, *q;
 
@@ -220,7 +222,9 @@
     mbedtls_ctr_drbg_init( &ctr_drbg );
 
     mbedtls_pk_init( &key );
+#if defined(MBEDTLS_ERROR_C)
     memset( buf, 0, sizeof( buf ) );
+#endif
 
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q );
     mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP );
@@ -316,8 +320,7 @@
                                         mbedtls_ctr_drbg_random, &ctr_drbg );
         if( ret != 0 )
         {
-            mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
-            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
+            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned -0x%04x", (unsigned int) -ret );
             goto exit;
         }
 
@@ -377,8 +380,7 @@
 
         if( ret != 0 )
         {
-            mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
-            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_public_key returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
+            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_public_key returned -0x%04x", (unsigned int) -ret );
             goto exit;
         }
 
diff --git a/programs/psa/CMakeLists.txt b/programs/psa/CMakeLists.txt
index 23e85fe..26ca73c 100644
--- a/programs/psa/CMakeLists.txt
+++ b/programs/psa/CMakeLists.txt
@@ -4,6 +4,25 @@
     psa_constant_names
 )
 
+if(GEN_FILES)
+    add_custom_command(
+        OUTPUT
+            ${CMAKE_CURRENT_BINARY_DIR}/psa_constant_names_generated.c
+        COMMAND
+            ${MBEDTLS_PYTHON_EXECUTABLE}
+                ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/generate_psa_constants.py
+                ${CMAKE_CURRENT_BINARY_DIR}
+        WORKING_DIRECTORY
+            ${CMAKE_CURRENT_SOURCE_DIR}/../..
+        DEPENDS
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/generate_psa_constants.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../include/psa/crypto_values.h
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../include/psa/crypto_extra.h
+    )
+else()
+    link_to_source(psa_constant_names_generated.c)
+endif()
+
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
     target_link_libraries(${exe} ${mbedcrypto_target})
@@ -11,6 +30,11 @@
 endforeach()
 
 target_include_directories(psa_constant_names PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
+if(GEN_FILES)
+    add_custom_target(generate_psa_constant_names_generated_c
+        DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/psa_constant_names_generated.c)
+    add_dependencies(psa_constant_names generate_psa_constant_names_generated_c)
+endif()
 
 install(TARGETS ${executables}
         DESTINATION "bin"
diff --git a/programs/ssl/CMakeLists.txt b/programs/ssl/CMakeLists.txt
index def9c7c..280bbcf 100644
--- a/programs/ssl/CMakeLists.txt
+++ b/programs/ssl/CMakeLists.txt
@@ -18,23 +18,38 @@
     ssl_server2
 )
 
+if(GEN_FILES)
+    # Inform CMake that the following file will be generated as part of the build
+    # process, so it doesn't complain that it doesn't exist yet. Starting from
+    # CMake 3.20, this will no longer be necessary as CMake will automatically
+    # propagate this information across the tree, for now it's only visible
+    # inside the same directory, so we need to propagate manually.
+    set_source_files_properties(
+        ${CMAKE_CURRENT_BINARY_DIR}/../test/query_config.c
+        PROPERTIES GENERATED TRUE)
+endif()
+
 foreach(exe IN LISTS executables)
     set(extra_sources "")
     if(exe STREQUAL "ssl_client2" OR exe STREQUAL "ssl_server2")
         list(APPEND extra_sources
-            ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
+            ssl_test_lib.c
+            ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.h
+            ${CMAKE_CURRENT_BINARY_DIR}/../test/query_config.c)
     endif()
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>
         ${extra_sources})
     target_link_libraries(${exe} ${libs})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
+    if(exe STREQUAL "ssl_client2" OR exe STREQUAL "ssl_server2")
+        if(GEN_FILES)
+            add_dependencies(${exe} generate_query_config_c)
+        endif()
+        target_include_directories(${exe}
+            PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../test)
+    endif()
 endforeach()
 
-set_property(TARGET ssl_client2 APPEND PROPERTY SOURCES
-    ssl_test_lib.c ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
-set_property(TARGET ssl_server2 APPEND PROPERTY SOURCES
-    ssl_test_lib.c ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
-
 if(THREADS_FOUND)
     add_executable(ssl_pthread_server ssl_pthread_server.c $<TARGET_OBJECTS:mbedtls_test>)
     target_include_directories(ssl_pthread_server PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
diff --git a/programs/ssl/dtls_server.c b/programs/ssl/dtls_server.c
index f257049..5d1cccb 100644
--- a/programs/ssl/dtls_server.c
+++ b/programs/ssl/dtls_server.c
@@ -226,7 +226,7 @@
                                    mbedtls_ssl_cache_set );
 #endif
 
-    mbedtls_ssl_conf_ca_chain( &conf, srvcert.MBEDTLS_PRIVATE(next), NULL );
+    mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL );
    if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 )
     {
         printf( " failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
diff --git a/programs/ssl/mini_client.c b/programs/ssl/mini_client.c
index 1e0bef6..97bfe68 100644
--- a/programs/ssl/mini_client.c
+++ b/programs/ssl/mini_client.c
@@ -246,13 +246,13 @@
     addr.sin_addr.s_addr = *((char *) &ret) == ret ? ADDR_LE : ADDR_BE;
     ret = 0;
 
-    if( ( server_fd.MBEDTLS_PRIVATE(fd) = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
+    if( ( server_fd.fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
     {
         ret = socket_failed;
         goto exit;
     }
 
-    if( connect( server_fd.MBEDTLS_PRIVATE(fd),
+    if( connect( server_fd.fd,
                 (const struct sockaddr *) &addr, sizeof( addr ) ) < 0 )
     {
         ret = connect_failed;
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index a970503..f872e60 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -207,7 +207,6 @@
 #define USAGE_TICKETS ""
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 #define USAGE_EAP_TLS                                       \
     "    eap_tls=%%d          default: 0 (disabled)\n"
 #define USAGE_NSS_KEYLOG                                    \
@@ -230,12 +229,6 @@
 #else /* MBEDTLS_SSL_DTLS_SRTP */
 #define USAGE_SRTP ""
 #endif
-#else /* MBEDTLS_SSL_EXPORT_KEYS */
-#define USAGE_EAP_TLS ""
-#define USAGE_NSS_KEYLOG ""
-#define USAGE_NSS_KEYLOG_FILE ""
-#define USAGE_SRTP ""
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
 #define USAGE_MAX_FRAG_LEN                                      \
@@ -729,7 +722,6 @@
     unsigned char *context_buf = NULL;
     size_t context_buf_len;
 #endif
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     unsigned char eap_tls_keymaterial[16];
     unsigned char eap_tls_iv[8];
     const char* eap_tls_label = "client EAP encryption";
@@ -747,7 +739,6 @@
         MBEDTLS_TLS_SRTP_UNSET
     };
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
@@ -1692,7 +1683,7 @@
     if( opt.key_opaque != 0 )
     {
         if( ( ret = mbedtls_pk_wrap_as_opaque( &pkey, &key_slot,
-                                               PSA_ALG_SHA_256 ) ) != 0 )
+                                               PSA_ALG_ANY_HASH ) ) != 0 )
         {
             mbedtls_printf( " failed\n  !  "
                             "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", (unsigned int)  -ret );
@@ -1962,7 +1953,6 @@
         goto exit;
     }
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     if( opt.eap_tls != 0 )
     {
         mbedtls_ssl_set_export_keys_cb( &ssl, eap_tls_key_derivation,
@@ -1981,7 +1971,6 @@
                                         &dtls_srtp_keying );
     }
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
     if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 )
@@ -2169,7 +2158,6 @@
     }
 #endif
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     if( opt.eap_tls != 0  )
     {
         size_t j = 0;
@@ -2286,7 +2274,6 @@
         }
     }
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
     if( opt.reconnect != 0 )
     {
         mbedtls_printf("  . Saving session for reuse..." );
diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c
index 542a334..694fc3b 100644
--- a/programs/ssl/ssl_fork_server.c
+++ b/programs/ssl/ssl_fork_server.c
@@ -190,7 +190,7 @@
     mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
     mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
 
-    mbedtls_ssl_conf_ca_chain( &conf, srvcert.MBEDTLS_PRIVATE(next), NULL );
+    mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL );
     if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 )
     {
         mbedtls_printf( " failed!  mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c
index ace657c..95557fb 100644
--- a/programs/ssl/ssl_server.c
+++ b/programs/ssl/ssl_server.c
@@ -212,7 +212,7 @@
                                    mbedtls_ssl_cache_set );
 #endif
 
-    mbedtls_ssl_conf_ca_chain( &conf, srvcert.MBEDTLS_PRIVATE(next), NULL );
+    mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL );
     if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 )
     {
         mbedtls_printf( " failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index e8e4ed8..c0f3196 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -80,6 +80,7 @@
 #define DFL_CA_PATH             ""
 #define DFL_CRT_FILE            ""
 #define DFL_KEY_FILE            ""
+#define DFL_KEY_OPAQUE          0
 #define DFL_KEY_PWD             ""
 #define DFL_CRT_FILE2           ""
 #define DFL_KEY_FILE2           ""
@@ -200,6 +201,13 @@
 #else
 #define USAGE_IO ""
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_X509_CRT_PARSE_C)
+#define USAGE_KEY_OPAQUE \
+    "    key_opaque=%%d       Handle your private keys as if they were opaque\n" \
+    "                        default: 0 (disabled)\n"
+#else
+#define USAGE_KEY_OPAQUE ""
+#endif
 
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
 #define USAGE_SSL_ASYNC \
@@ -278,7 +286,6 @@
 #define USAGE_TICKETS ""
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 #define USAGE_EAP_TLS                                       \
     "    eap_tls=%%d          default: 0 (disabled)\n"
 #define USAGE_NSS_KEYLOG                                    \
@@ -299,12 +306,6 @@
 #else /* MBEDTLS_SSL_DTLS_SRTP */
 #define USAGE_SRTP ""
 #endif
-#else /* MBEDTLS_SSL_EXPORT_KEYS */
-#define USAGE_EAP_TLS ""
-#define USAGE_NSS_KEYLOG ""
-#define USAGE_NSS_KEYLOG_FILE ""
-#define USAGE_SRTP ""
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_CACHE_C)
 #define USAGE_CACHE                                             \
@@ -483,6 +484,7 @@
     "    cert_req_ca_list=%%d default: 1 (send ca list)\n"  \
     "                        options: 1 (send ca list), 0 (don't send)\n" \
     USAGE_IO                                                \
+    USAGE_KEY_OPAQUE                                        \
     "\n"                                                    \
     USAGE_PSK                                               \
     USAGE_CA_CALLBACK                                       \
@@ -567,6 +569,7 @@
     const char *ca_path;        /* the path with the CA certificate(s) reside */
     const char *crt_file;       /* the file with the server certificate     */
     const char *key_file;       /* the file with the server key             */
+    int key_opaque;             /* handle private key as if it were opaque  */
     const char *key_pwd;        /* the password for the server key          */
     const char *crt_file2;      /* the file with the 2nd server certificate */
     const char *key_file2;      /* the file with the 2nd server key         */
@@ -1315,6 +1318,10 @@
     mbedtls_pk_context pkey;
     mbedtls_x509_crt srvcert2;
     mbedtls_pk_context pkey2;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_key_id_t key_slot = 0; /* invalid key slot */
+    psa_key_id_t key_slot2 = 0; /* invalid key slot */
+#endif
     int key_cert_init = 0, key_cert_init2 = 0;
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
     ssl_async_key_context_t ssl_async_keys;
@@ -1365,7 +1372,6 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_status_t status;
 #endif
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     unsigned char eap_tls_keymaterial[16];
     unsigned char eap_tls_iv[8];
     const char* eap_tls_label = "client EAP encryption";
@@ -1383,7 +1389,6 @@
          MBEDTLS_TLS_SRTP_UNSET
      };
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
@@ -1491,6 +1496,7 @@
     opt.ca_path             = DFL_CA_PATH;
     opt.crt_file            = DFL_CRT_FILE;
     opt.key_file            = DFL_KEY_FILE;
+    opt.key_opaque          = DFL_KEY_OPAQUE;
     opt.key_pwd             = DFL_KEY_PWD;
     opt.crt_file2           = DFL_CRT_FILE2;
     opt.key_file2           = DFL_KEY_FILE2;
@@ -1622,6 +1628,10 @@
             opt.key_file = q;
         else if( strcmp( p, "key_pwd" ) == 0 )
             opt.key_pwd = q;
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_X509_CRT_PARSE_C)
+        else if( strcmp( p, "key_opaque" ) == 0 )
+            opt.key_opaque = atoi( q );
+#endif
         else if( strcmp( p, "crt_file2" ) == 0 )
             opt.crt_file2 = q;
         else if( strcmp( p, "key_file2" ) == 0 )
@@ -2477,7 +2487,34 @@
 #endif /* MBEDTLS_ECDSA_C */
     }
 
-    mbedtls_printf( " ok\n" );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if( opt.key_opaque != 0 )
+    {
+        if ( mbedtls_pk_get_type( &pkey ) == MBEDTLS_PK_ECKEY )
+        {
+            if( ( ret = mbedtls_pk_wrap_as_opaque( &pkey, &key_slot,
+                                                PSA_ALG_ANY_HASH ) ) != 0 )
+            {
+                mbedtls_printf( " failed\n  !  "
+                                "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", (unsigned int)  -ret );
+                goto exit;
+            }
+        }
+
+        if ( mbedtls_pk_get_type( &pkey2 ) == MBEDTLS_PK_ECKEY )
+        {
+            if( ( ret = mbedtls_pk_wrap_as_opaque( &pkey2, &key_slot2,
+                                                PSA_ALG_ANY_HASH ) ) != 0 )
+            {
+                mbedtls_printf( " failed\n  !  "
+                                "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", (unsigned int)  -ret );
+                goto exit;
+            }
+        }
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    mbedtls_printf( " ok (key types: %s - %s)\n", mbedtls_pk_get_name( &pkey ), mbedtls_pk_get_name( &pkey2 ) );
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
 #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO)
@@ -2966,7 +3003,6 @@
         goto exit;
     }
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     if( opt.eap_tls != 0 )
     {
         mbedtls_ssl_set_export_keys_cb( &ssl, eap_tls_key_derivation,
@@ -2985,7 +3021,6 @@
                                         &dtls_srtp_keying );
     }
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
     io_ctx.ssl = &ssl;
     io_ctx.net = &client_fd;
@@ -3251,7 +3286,6 @@
 #endif /* MBEDTLS_X509_REMOVE_INFO */
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     if( opt.eap_tls != 0 )
     {
         size_t j = 0;
@@ -3369,7 +3403,6 @@
         }
     }
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     ret = report_cid_usage( &ssl, "initial handshake" );
@@ -3923,6 +3956,10 @@
     mbedtls_pk_free( &pkey );
     mbedtls_x509_crt_free( &srvcert2 );
     mbedtls_pk_free( &pkey2 );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_destroy_key( key_slot );
+    psa_destroy_key( key_slot2 );
+#endif
 #endif
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
     for( i = 0; (size_t) i < ssl_async_keys.slots_used; i++ )
diff --git a/programs/ssl/ssl_test_common_source.c b/programs/ssl/ssl_test_common_source.c
index 6ec4171..62cd35d 100644
--- a/programs/ssl/ssl_test_common_source.c
+++ b/programs/ssl/ssl_test_common_source.c
@@ -24,7 +24,6 @@
  *  limitations under the License.
  */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 void eap_tls_key_derivation( void *p_expkey,
                              mbedtls_ssl_key_export_type secret_type,
                              const unsigned char *secret,
@@ -140,8 +139,6 @@
 }
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
 
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
-
 int ssl_check_record( mbedtls_ssl_context const *ssl,
                       unsigned char const *buf, size_t len )
 {
diff --git a/programs/ssl/ssl_test_lib.h b/programs/ssl/ssl_test_lib.h
index f9e031b..6b9e7b8 100644
--- a/programs/ssl/ssl_test_lib.h
+++ b/programs/ssl/ssl_test_lib.h
@@ -95,8 +95,6 @@
 
 #include "../test/query_config.h"
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
-
 typedef struct eap_tls_keys
 {
     unsigned char master_secret[48];
@@ -122,8 +120,6 @@
 
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
 
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
-
 typedef struct
 {
     mbedtls_ssl_context *ssl;
diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt
index a0a1b76..142a831 100644
--- a/programs/test/CMakeLists.txt
+++ b/programs/test/CMakeLists.txt
@@ -27,15 +27,44 @@
     target_link_libraries(cpp_dummy_build ${mbedcrypto_target})
 endif()
 
+if(GEN_FILES)
+    find_package(Perl REQUIRED)
+
+    add_custom_command(
+        OUTPUT
+            ${CMAKE_CURRENT_BINARY_DIR}/query_config.c
+        COMMAND
+            ${PERL}
+                ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/generate_query_config.pl
+                ${CMAKE_CURRENT_SOURCE_DIR}/../../include/mbedtls/mbedtls_config.h
+                ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/data_files/query_config.fmt
+                ${CMAKE_CURRENT_BINARY_DIR}/query_config.c
+        DEPENDS
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/generate_query_config.pl
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../include/mbedtls/mbedtls_config.h
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/data_files/query_config.fmt
+    )
+    # this file will also be used in another directory, so create a target, see
+    # https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#how-can-i-add-a-dependency-to-a-source-file-which-is-generated-in-a-subdirectory
+    add_custom_target(generate_query_config_c
+        DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/query_config.c)
+else()
+    link_to_source(query_config.c)
+endif()
+
 foreach(exe IN LISTS executables_libs executables_mbedcrypto)
     set(extra_sources "")
     if(exe STREQUAL "query_compile_time_config")
         list(APPEND extra_sources
-            ${CMAKE_CURRENT_SOURCE_DIR}/query_config.c)
+            ${CMAKE_CURRENT_SOURCE_DIR}/query_config.h
+            ${CMAKE_CURRENT_BINARY_DIR}/query_config.c)
     endif()
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>
         ${extra_sources})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
+    if(exe STREQUAL "query_compile_time_config")
+        target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
+    endif()
 
     # This emulates "if ( ... IN_LIST ... )" which becomes available in CMake 3.3
     list(FIND executables_libs ${exe} exe_index)
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 5985caf..d3faad9 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -674,7 +674,8 @@
     {
         mbedtls_des3_context des3;
         mbedtls_des3_init( &des3 );
-        mbedtls_des3_set3key_enc( &des3, tmp );
+        if( mbedtls_des3_set3key_enc( &des3, tmp ) != 0 )
+            mbedtls_exit( 1 );
         TIME_AND_TSC( "3DES",
                 mbedtls_des3_crypt_cbc( &des3, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
         mbedtls_des3_free( &des3 );
@@ -684,7 +685,8 @@
     {
         mbedtls_des_context des;
         mbedtls_des_init( &des );
-        mbedtls_des_setkey_enc( &des, tmp );
+        if( mbedtls_des_setkey_enc( &des, tmp ) != 0 )
+            mbedtls_exit( 1 );
         TIME_AND_TSC( "DES",
                 mbedtls_des_crypt_cbc( &des, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
         mbedtls_des_free( &des );
@@ -722,7 +724,7 @@
 
             memset( buf, 0, sizeof( buf ) );
             memset( tmp, 0, sizeof( tmp ) );
-            mbedtls_aes_setkey_enc( &aes, tmp, keysize );
+            CHECK_AND_CONTINUE( mbedtls_aes_setkey_enc( &aes, tmp, keysize ) );
 
             TIME_AND_TSC( title,
                 mbedtls_aes_crypt_cbc( &aes, MBEDTLS_AES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
@@ -743,7 +745,7 @@
 
             memset( buf, 0, sizeof( buf ) );
             memset( tmp, 0, sizeof( tmp ) );
-            mbedtls_aes_xts_setkey_enc( &ctx, tmp, keysize * 2 );
+            CHECK_AND_CONTINUE( mbedtls_aes_xts_setkey_enc( &ctx, tmp, keysize * 2 ) );
 
             TIME_AND_TSC( title,
                     mbedtls_aes_crypt_xts( &ctx, MBEDTLS_AES_ENCRYPT, BUFSIZE,
diff --git a/programs/x509/CMakeLists.txt b/programs/x509/CMakeLists.txt
index a04fa8b..5876b8d 100644
--- a/programs/x509/CMakeLists.txt
+++ b/programs/x509/CMakeLists.txt
@@ -7,6 +7,7 @@
     cert_req
     cert_write
     crl_app
+    load_roots
     req_app
 )
 
diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c
index aab15db..3d8f37b 100644
--- a/programs/x509/cert_app.c
+++ b/programs/x509/cert_app.c
@@ -331,7 +331,7 @@
 
             mbedtls_printf( "%s\n", buf );
 
-            cur = cur->MBEDTLS_PRIVATE(next);
+            cur = cur->next;
         }
 
         /*
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index 9a20d63..763f868 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -514,7 +514,7 @@
         }
 
         ret = mbedtls_x509_dn_gets( issuer_name, sizeof(issuer_name),
-                                 &issuer_crt.MBEDTLS_PRIVATE(subject) );
+                                 &issuer_crt.subject );
         if( ret < 0 )
         {
             mbedtls_strerror( ret, buf, 1024 );
@@ -548,7 +548,7 @@
         }
 
         ret = mbedtls_x509_dn_gets( subject_name, sizeof(subject_name),
-                                 &csr.MBEDTLS_PRIVATE(subject) );
+                                 &csr.subject );
         if( ret < 0 )
         {
             mbedtls_strerror( ret, buf, 1024 );
@@ -558,7 +558,7 @@
         }
 
         opt.subject_name = subject_name;
-        subject_key = &csr.MBEDTLS_PRIVATE(pk);
+        subject_key = &csr.pk;
 
         mbedtls_printf( " ok\n" );
     }
@@ -602,7 +602,7 @@
     //
     if( strlen( opt.issuer_crt ) )
     {
-        if( mbedtls_pk_check_pair( &issuer_crt.MBEDTLS_PRIVATE(pk), issuer_key,
+        if( mbedtls_pk_check_pair( &issuer_crt.pk, issuer_key,
                                    mbedtls_ctr_drbg_random, &ctr_drbg ) != 0 )
         {
             mbedtls_printf( " failed\n  !  issuer_key does not match "
diff --git a/programs/x509/load_roots.c b/programs/x509/load_roots.c
new file mode 100644
index 0000000..e07bed7
--- /dev/null
+++ b/programs/x509/load_roots.c
@@ -0,0 +1,213 @@
+/*
+ *  Root CA reading application
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ *
+ *  This file is provided under the Apache License 2.0, or the
+ *  GNU General Public License v2.0 or later.
+ *
+ *  **********
+ *  Apache License 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.
+ *
+ *  **********
+ *
+ *  **********
+ *  GNU General Public License v2.0 or later:
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  **********
+ */
+
+#include "mbedtls/build_info.h"
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define mbedtls_time            time
+#define mbedtls_time_t          time_t
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define mbedtls_exit            exit
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
+
+#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) ||  \
+    !defined(MBEDTLS_TIMING_C)
+int main( void )
+{
+    mbedtls_printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_FS_IO and/or "
+           "MBEDTLS_TIMING_C not defined.\n");
+    mbedtls_exit( 0 );
+}
+#else
+
+#include "mbedtls/error.h"
+#include "mbedtls/timing.h"
+#include "mbedtls/x509_crt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DFL_ITERATIONS          1
+#define DFL_PRIME_CACHE         1
+
+#define USAGE \
+    "\n usage: load_roots param=<>... [--] FILE...\n"   \
+    "\n acceptable parameters:\n"                       \
+    "    iterations=%%d        Iteration count (not including cache priming); default: 1\n"  \
+    "    prime=%%d             Prime the disk read cache? Default: 1 (yes)\n"  \
+    "\n"
+
+
+/*
+ * global options
+ */
+struct options
+{
+    const char **filenames;     /* NULL-terminated list of file names */
+    unsigned iterations;        /* Number of iterations to time */
+    int prime_cache;            /* Prime the disk read cache? */
+} opt;
+
+
+int read_certificates( const char *const *filenames )
+{
+    mbedtls_x509_crt cas;
+    int ret = 0;
+    const char *const *cur;
+
+    mbedtls_x509_crt_init( &cas );
+
+    for( cur = filenames; *cur != NULL; cur++ )
+    {
+        ret = mbedtls_x509_crt_parse_file( &cas, *cur );
+        if( ret != 0 )
+        {
+#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
+            char error_message[200];
+            mbedtls_strerror( ret, error_message, sizeof( error_message ) );
+            printf( "\n%s: -0x%04x (%s)\n",
+                    *cur, (unsigned) -ret, error_message );
+#else
+            printf( "\n%s: -0x%04x\n",
+                    *cur, (unsigned) -ret );
+#endif
+            goto exit;
+        }
+    }
+
+exit:
+    mbedtls_x509_crt_free( &cas );
+    return( ret == 0 );
+}
+
+int main( int argc, char *argv[] )
+{
+    int exit_code = MBEDTLS_EXIT_FAILURE;
+    unsigned i, j;
+    struct mbedtls_timing_hr_time timer;
+    unsigned long ms;
+
+    if( argc <= 1 )
+    {
+        mbedtls_printf( USAGE );
+        goto exit;
+    }
+
+    opt.filenames = NULL;
+    opt.iterations = DFL_ITERATIONS;
+    opt.prime_cache = DFL_PRIME_CACHE;
+
+    for( i = 1; i < (unsigned) argc; i++ )
+    {
+        char *p = argv[i];
+        char *q = NULL;
+
+        if( strcmp( p, "--" ) == 0 )
+            break;
+        if( ( q = strchr( p, '=' ) ) == NULL )
+            break;
+        *q++ = '\0';
+
+        for( j = 0; p + j < q; j++ )
+        {
+            if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' )
+                argv[i][j] |= 0x20;
+        }
+
+        if( strcmp( p, "iterations" ) == 0 )
+        {
+            opt.iterations = atoi( q );
+        }
+        else if( strcmp( p, "prime" ) == 0 )
+        {
+            opt.iterations = atoi( q ) != 0;
+        }
+        else
+        {
+            mbedtls_printf( "Unknown option: %s\n", p );
+            mbedtls_printf( USAGE );
+            goto exit;
+        }
+    }
+
+    opt.filenames = (const char**) argv + i;
+    if( *opt.filenames == 0 )
+    {
+        mbedtls_printf( "Missing list of certificate files to parse\n" );
+        goto exit;
+    }
+
+    mbedtls_printf( "Parsing %u certificates", argc - i );
+    if( opt.prime_cache )
+    {
+        if( ! read_certificates( opt.filenames ) )
+            goto exit;
+        mbedtls_printf( " " );
+    }
+
+    (void) mbedtls_timing_get_timer( &timer, 1 );
+    for( i = 1; i <= opt.iterations; i++ )
+    {
+        if( ! read_certificates( opt.filenames ) )
+            goto exit;
+        mbedtls_printf( "." );
+    }
+    ms = mbedtls_timing_get_timer( &timer, 0 );
+    mbedtls_printf( "\n%u iterations -> %lu ms\n", opt.iterations, ms );
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
+exit:
+    mbedtls_exit( exit_code );
+}
+#endif /* necessary configuration */
diff --git a/scripts/generate_query_config.pl b/scripts/generate_query_config.pl
index e3bbaa0..7855c7c 100755
--- a/scripts/generate_query_config.pl
+++ b/scripts/generate_query_config.pl
@@ -14,7 +14,8 @@
 # information is used to automatically generate the body of the query_config()
 # function by using the template in scripts/data_files/query_config.fmt.
 #
-# Usage: ./scripts/generate_query_config.pl without arguments
+# Usage: scripts/generate_query_config.pl without arguments, or
+# generate_query_config.pl config_file template_file output_file
 #
 # Copyright The Mbed TLS Contributors
 # SPDX-License-Identifier: Apache-2.0
@@ -33,15 +34,24 @@
 
 use strict;
 
-my $config_file = "./include/mbedtls/mbedtls_config.h";
+my ($config_file, $query_config_format_file, $query_config_file);
 
-my $query_config_format_file = "./scripts/data_files/query_config.fmt";
-my $query_config_file = "./programs/test/query_config.c";
+if( @ARGV ) {
+    die "Invalid number of arguments - usage: $0 [CONFIG_FILE TEMPLATE_FILE OUTPUT_FILE]" if scalar @ARGV != 3;
+    ($config_file, $query_config_format_file, $query_config_file) = @ARGV;
 
-unless( -f $config_file && -f $query_config_format_file ) {
-    chdir '..' or die;
-    -f $config_file && -f $query_config_format_file
-      or die "Without arguments, must be run from root or a subdirectory\n";
+    -f $config_file or die "No such file: $config_file";
+    -f $query_config_format_file or die "No such file: $query_config_format_file";
+} else {
+    $config_file = "./include/mbedtls/mbedtls_config.h";
+    $query_config_format_file = "./scripts/data_files/query_config.fmt";
+    $query_config_file = "./programs/test/query_config.c";
+
+    unless( -f $config_file && -f $query_config_format_file ) {
+        chdir '..' or die;
+        -f $config_file && -f $query_config_format_file
+          or die "No arguments supplied, must be run from project root or a first-level subdirectory\n";
+    }
 }
 
 # Excluded macros from the generated query_config.c. For example, macros that
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index fbd746e..41dceed 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -13,10 +13,48 @@
     message(FATAL_ERROR "Cannot build test suites without Python 3")
 endif()
 
-# Enable definition of various functions used throughout the testsuite
-# (gethostname, strdup, fileno...) even when compiling with -std=c99. Harmless
-# on non-POSIX platforms.
-add_definitions("-D_POSIX_C_SOURCE=200809L")
+# generated .data files will go there
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/suites)
+
+# Get base names for generated files (starting at "suites/")
+execute_process(
+    COMMAND
+        ${MBEDTLS_PYTHON_EXECUTABLE}
+        ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_psa_tests.py
+        --list-for-cmake
+        --directory suites
+    WORKING_DIRECTORY
+        ${CMAKE_CURRENT_SOURCE_DIR}/..
+    OUTPUT_VARIABLE
+        base_generated_data_files)
+
+# Derive generated file paths in the build directory
+set(generated_data_files "")
+foreach(file ${base_generated_data_files})
+    list(APPEND generated_data_files ${CMAKE_CURRENT_BINARY_DIR}/${file})
+endforeach()
+
+if(GEN_FILES)
+    add_custom_command(
+        OUTPUT
+            ${generated_data_files}
+        WORKING_DIRECTORY
+            ${CMAKE_CURRENT_SOURCE_DIR}/..
+        COMMAND
+            ${MBEDTLS_PYTHON_EXECUTABLE}
+            ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_psa_tests.py
+            --directory ${CMAKE_CURRENT_BINARY_DIR}/suites
+        DEPENDS
+            ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_psa_tests.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../include/psa/crypto_config.h
+            ${CMAKE_CURRENT_SOURCE_DIR}/../include/psa/crypto_values.h
+            ${CMAKE_CURRENT_SOURCE_DIR}/../include/psa/crypto_extra.h
+    )
+else()
+    foreach(file ${base_generated_data_files})
+        link_to_source(${file})
+    endforeach()
+endif()
 
 # Test suites caught by SKIP_TEST_SUITES are built but not executed.
 # "foo" as a skip pattern skips "test_suite_foo" and "test_suite_foo.bar"
@@ -32,10 +70,52 @@
         set(data_name ${suite_name})
     endif()
 
+    # Get the test names of the tests with generated .data files
+    # from the generated_data_files list in parent scope.
+    set(generated_data_names "")
+    foreach(generated_data_file ${generated_data_files})
+        # Get the plain filename
+        get_filename_component(generated_data_name ${generated_data_file} NAME)
+        # Remove the ".data" extension
+        get_name_without_last_ext(generated_data_name ${generated_data_name})
+        # Remove leading "test_suite_"
+        string(SUBSTRING ${generated_data_name} 11 -1 generated_data_name)
+        list(APPEND generated_data_names ${generated_data_name})
+    endforeach()
+
+    if(";${generated_data_names};" MATCHES ";${data_name};")
+        set(data_file
+            ${CMAKE_CURRENT_BINARY_DIR}/suites/test_suite_${data_name}.data)
+    else()
+        set(data_file
+            ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${data_name}.data)
+    endif()
+
     add_custom_command(
-        OUTPUT test_suite_${data_name}.c
-        COMMAND ${MBEDTLS_PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py -f ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function -d ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${data_name}.data -t ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function -p ${CMAKE_CURRENT_SOURCE_DIR}/suites/host_test.function -s ${CMAKE_CURRENT_SOURCE_DIR}/suites --helpers-file ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function -o .
-        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py ${mbedtls_target} ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/host_test.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${data_name}.data
+        OUTPUT
+            # The output filename of generate_test_code.py is derived from the -d
+            # input argument.
+            test_suite_${data_name}.c
+        COMMAND
+            ${MBEDTLS_PYTHON_EXECUTABLE}
+            ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py
+            -f ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function
+            -d ${data_file}
+            -t ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function
+            -p ${CMAKE_CURRENT_SOURCE_DIR}/suites/host_test.function
+            -s ${CMAKE_CURRENT_SOURCE_DIR}/suites
+            --helpers-file ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function
+            -o .
+        DEPENDS
+            ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function
+            ${data_file}
+            ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function
+            ${CMAKE_CURRENT_SOURCE_DIR}/suites/host_test.function
+            ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function
+            ${mbedtls_target}
+        BYPRODUCTS
+            test_suite_${data_name}.datax
     )
 
     add_executable(test_suite_${data_name} test_suite_${data_name}.c $<TARGET_OBJECTS:mbedtls_test>)
@@ -55,6 +135,11 @@
     endif()
 endfunction(add_test_suite)
 
+# Enable definition of various functions used throughout the testsuite
+# (gethostname, strdup, fileno...) even when compiling with -std=c99. Harmless
+# on non-POSIX platforms.
+add_definitions("-D_POSIX_C_SOURCE=200809L")
+
 if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function")
 endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
@@ -170,5 +255,4 @@
     link_to_source(data_files)
     link_to_source(scripts)
     link_to_source(ssl-opt.sh)
-    link_to_source(suites)
 endif()
diff --git a/tests/Makefile b/tests/Makefile
index 449fca2..77a3172 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -5,6 +5,9 @@
 WARNING_CFLAGS ?= -Wall -Wextra -Wformat=2 -Wno-format-nonliteral
 LDFLAGS ?=
 
+# Set this to -v to see the details of failing test cases
+TEST_FLAGS ?= $(if $(filter-out 0 OFF Off off NO No no FALSE False false N n,$(CTEST_OUTPUT_ON_FAILURE)),-v,)
+
 default: all
 
 # Include public header files from ../include, test-specific header files
@@ -170,7 +173,7 @@
 
 clean:
 ifndef WINDOWS
-	rm -rf $(BINARIES) *.c *.datax TESTS
+	rm -rf $(BINARIES) *.c *.datax
 	rm -f src/*.o src/drivers/*.o src/libmbed*
 	rm -f include/test/instrument_record_status.h
 else
@@ -181,9 +184,6 @@
 	if exist src/drivers/*.o del /Q /F src/drivers/*.o
 	if exist src/libmbed* del /Q /F src/libmed*
 	if exist include/test/instrument_record_status.h del /Q /F include/test/instrument_record_status.h
-ifneq ($(wildcard TESTS/.*),)
-	rmdir /Q /S TESTS
-endif
 endif
 
 neat: clean
@@ -195,44 +195,10 @@
 
 # Test suites caught by SKIP_TEST_SUITES are built but not executed.
 check: $(BINARIES)
-	perl scripts/run-test-suites.pl --skip=$(SKIP_TEST_SUITES)
+	perl scripts/run-test-suites.pl $(TEST_FLAGS) --skip=$(SKIP_TEST_SUITES)
 
 test: check
 
-# Create separate targets for generating embedded tests.
-EMBEDDED_TESTS := $(addprefix embedded_,$(APPS))
-
-# Generate test code for target.
-
-.SECONDEXPANSION:
-$(EMBEDDED_TESTS): embedded_%: suites/$$(firstword $$(subst ., ,$$*)).function suites/%.data scripts/generate_test_code.py suites/helpers.function suites/main_test.function suites/target_test.function
-	echo "  Gen  ./TESTS/mbedtls/$*/$*.c"
-	$(PYTHON) scripts/generate_test_code.py -f suites/$(firstword $(subst ., ,$*)).function \
-		-d suites/$*.data \
-		-t suites/main_test.function \
-		-p suites/target_test.function \
-		-s suites  \
-		--helpers-file suites/helpers.function \
-		-o ./TESTS/mbedtls/$*
-
-generate-target-tests: $(EMBEDDED_TESTS)
-
-define copy_header_to_target
-TESTS/mbedtls/$(1)/$(2): include/test/$(2)
-	echo "  Copy ./$$@"
-ifndef WINDOWS
-	mkdir -p $$(@D)
-	cp $$< $$@
-else
-	mkdir $$(@D)
-	copy $$< $$@
-endif
-
-endef
-$(foreach app, $(APPS), $(foreach file, $(notdir $(wildcard include/test/*.h)), \
-	$(eval $(call copy_header_to_target,$(app),$(file)))))
-$(addprefix embedded_,$(filter test_suite_psa_%, $(APPS))): embedded_%: $(patsubst TESTS/mbedtls/%, include/test/%, $(wildcard include/test/*. include/test/*/*.h))
-
 ifdef RECORD_PSA_STATUS_COVERAGE_LOG
 include/test/instrument_record_status.h: ../include/psa/crypto.h Makefile
 	echo "  Gen  $@"
diff --git a/tests/compat.sh b/tests/compat.sh
index c2bef26..f4c611a 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -236,60 +236,46 @@
     G_CIPHERS=""
 }
 
+check_translation()
+{
+    if [ $1 -ne 0 ]; then
+        echo "translate_ciphers.py failed with exit code $1" >&2
+        echo "$2" >&2
+        exit 1
+    fi
+}
+
 # Ciphersuites that can be used with all peers.
 # Since we currently have three possible peers, each ciphersuite should appear
 # three times: in each peer's list (with the name that this peer uses).
 add_common_ciphersuites()
 {
+    CIPHERS=""
     case $TYPE in
 
         "ECDSA")
             if [ `minor_ver "$MODE"` -gt 0 ]
             then
-                M_CIPHERS="$M_CIPHERS                       \
+                CIPHERS="$CIPHERS                           \
                     TLS-ECDHE-ECDSA-WITH-NULL-SHA           \
                     TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA   \
                     TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA    \
                     TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA    \
                     "
-                G_CIPHERS="$G_CIPHERS                       \
-                    +ECDHE-ECDSA:+NULL:+SHA1                \
-                    +ECDHE-ECDSA:+3DES-CBC:+SHA1            \
-                    +ECDHE-ECDSA:+AES-128-CBC:+SHA1         \
-                    +ECDHE-ECDSA:+AES-256-CBC:+SHA1         \
-                    "
-                O_CIPHERS="$O_CIPHERS               \
-                    ECDHE-ECDSA-NULL-SHA            \
-                    ECDHE-ECDSA-DES-CBC3-SHA        \
-                    ECDHE-ECDSA-AES128-SHA          \
-                    ECDHE-ECDSA-AES256-SHA          \
-                    "
             fi
             if [ `minor_ver "$MODE"` -ge 3 ]
             then
-                M_CIPHERS="$M_CIPHERS                               \
+                CIPHERS="$CIPHERS                                   \
                     TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256         \
                     TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384         \
                     TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256         \
                     TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384         \
                     "
-                G_CIPHERS="$G_CIPHERS                               \
-                    +ECDHE-ECDSA:+AES-128-CBC:+SHA256               \
-                    +ECDHE-ECDSA:+AES-256-CBC:+SHA384               \
-                    +ECDHE-ECDSA:+AES-128-GCM:+AEAD                 \
-                    +ECDHE-ECDSA:+AES-256-GCM:+AEAD                 \
-                    "
-                O_CIPHERS="$O_CIPHERS               \
-                    ECDHE-ECDSA-AES128-SHA256       \
-                    ECDHE-ECDSA-AES256-SHA384       \
-                    ECDHE-ECDSA-AES128-GCM-SHA256   \
-                    ECDHE-ECDSA-AES256-GCM-SHA384   \
-                    "
             fi
             ;;
 
         "RSA")
-            M_CIPHERS="$M_CIPHERS                       \
+            CIPHERS="$CIPHERS                           \
                 TLS-DHE-RSA-WITH-AES-128-CBC-SHA        \
                 TLS-DHE-RSA-WITH-AES-256-CBC-SHA        \
                 TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA   \
@@ -303,58 +289,18 @@
                 TLS-RSA-WITH-NULL-MD5                   \
                 TLS-RSA-WITH-NULL-SHA                   \
                 "
-            G_CIPHERS="$G_CIPHERS                       \
-                +DHE-RSA:+AES-128-CBC:+SHA1             \
-                +DHE-RSA:+AES-256-CBC:+SHA1             \
-                +DHE-RSA:+CAMELLIA-128-CBC:+SHA1        \
-                +DHE-RSA:+CAMELLIA-256-CBC:+SHA1        \
-                +DHE-RSA:+3DES-CBC:+SHA1                \
-                +RSA:+AES-256-CBC:+SHA1                 \
-                +RSA:+CAMELLIA-256-CBC:+SHA1            \
-                +RSA:+AES-128-CBC:+SHA1                 \
-                +RSA:+CAMELLIA-128-CBC:+SHA1            \
-                +RSA:+3DES-CBC:+SHA1                    \
-                +RSA:+NULL:+MD5                         \
-                +RSA:+NULL:+SHA1                        \
-                "
-            O_CIPHERS="$O_CIPHERS               \
-                DHE-RSA-AES128-SHA              \
-                DHE-RSA-AES256-SHA              \
-                DHE-RSA-CAMELLIA128-SHA         \
-                DHE-RSA-CAMELLIA256-SHA         \
-                EDH-RSA-DES-CBC3-SHA            \
-                AES256-SHA                      \
-                CAMELLIA256-SHA                 \
-                AES128-SHA                      \
-                CAMELLIA128-SHA                 \
-                DES-CBC3-SHA                    \
-                NULL-MD5                        \
-                NULL-SHA                        \
-                "
             if [ `minor_ver "$MODE"` -gt 0 ]
             then
-                M_CIPHERS="$M_CIPHERS                       \
+                CIPHERS="$CIPHERS                           \
                     TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA      \
                     TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA      \
                     TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA     \
                     TLS-ECDHE-RSA-WITH-NULL-SHA             \
                     "
-                G_CIPHERS="$G_CIPHERS                       \
-                    +ECDHE-RSA:+AES-128-CBC:+SHA1           \
-                    +ECDHE-RSA:+AES-256-CBC:+SHA1           \
-                    +ECDHE-RSA:+3DES-CBC:+SHA1              \
-                    +ECDHE-RSA:+NULL:+SHA1                  \
-                    "
-                O_CIPHERS="$O_CIPHERS               \
-                    ECDHE-RSA-AES256-SHA            \
-                    ECDHE-RSA-AES128-SHA            \
-                    ECDHE-RSA-DES-CBC3-SHA          \
-                    ECDHE-RSA-NULL-SHA              \
-                    "
             fi
             if [ `minor_ver "$MODE"` -ge 3 ]
             then
-                M_CIPHERS="$M_CIPHERS                       \
+                CIPHERS="$CIPHERS                           \
                     TLS-RSA-WITH-AES-128-CBC-SHA256         \
                     TLS-DHE-RSA-WITH-AES-128-CBC-SHA256     \
                     TLS-RSA-WITH-AES-256-CBC-SHA256         \
@@ -367,62 +313,36 @@
                     TLS-DHE-RSA-WITH-AES-256-GCM-SHA384     \
                     TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256   \
                     TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384   \
-                    "
-                G_CIPHERS="$G_CIPHERS                       \
-                    +RSA:+AES-128-CBC:+SHA256               \
-                    +DHE-RSA:+AES-128-CBC:+SHA256           \
-                    +RSA:+AES-256-CBC:+SHA256               \
-                    +DHE-RSA:+AES-256-CBC:+SHA256           \
-                    +ECDHE-RSA:+AES-128-CBC:+SHA256         \
-                    +ECDHE-RSA:+AES-256-CBC:+SHA384         \
-                    +RSA:+AES-128-GCM:+AEAD                 \
-                    +RSA:+AES-256-GCM:+AEAD                 \
-                    +DHE-RSA:+AES-128-GCM:+AEAD             \
-                    +DHE-RSA:+AES-256-GCM:+AEAD             \
-                    +ECDHE-RSA:+AES-128-GCM:+AEAD           \
-                    +ECDHE-RSA:+AES-256-GCM:+AEAD           \
-                    "
-                O_CIPHERS="$O_CIPHERS           \
-                    NULL-SHA256                 \
-                    AES128-SHA256               \
-                    DHE-RSA-AES128-SHA256       \
-                    AES256-SHA256               \
-                    DHE-RSA-AES256-SHA256       \
-                    ECDHE-RSA-AES128-SHA256     \
-                    ECDHE-RSA-AES256-SHA384     \
-                    AES128-GCM-SHA256           \
-                    DHE-RSA-AES128-GCM-SHA256   \
-                    AES256-GCM-SHA384           \
-                    DHE-RSA-AES256-GCM-SHA384   \
-                    ECDHE-RSA-AES128-GCM-SHA256 \
-                    ECDHE-RSA-AES256-GCM-SHA384 \
+                    TLS-RSA-WITH-NULL-SHA256                \
                     "
             fi
             ;;
 
         "PSK")
-            M_CIPHERS="$M_CIPHERS                       \
+            CIPHERS="$CIPHERS                           \
                 TLS-PSK-WITH-3DES-EDE-CBC-SHA           \
                 TLS-PSK-WITH-AES-128-CBC-SHA            \
                 TLS-PSK-WITH-AES-256-CBC-SHA            \
                 "
-            G_CIPHERS="$G_CIPHERS                       \
-                +PSK:+3DES-CBC:+SHA1                    \
-                +PSK:+AES-128-CBC:+SHA1                 \
-                +PSK:+AES-256-CBC:+SHA1                 \
-                "
-            O_CIPHERS="$O_CIPHERS               \
-                PSK-3DES-EDE-CBC-SHA            \
-                PSK-AES128-CBC-SHA              \
-                PSK-AES256-CBC-SHA              \
-                "
             ;;
     esac
+
+    M_CIPHERS="$M_CIPHERS $CIPHERS"
+
+    T=$(./scripts/translate_ciphers.py g $CIPHERS)
+    check_translation $? "$T"
+    G_CIPHERS="$G_CIPHERS $T"
+
+    T=$(./scripts/translate_ciphers.py o $CIPHERS)
+    check_translation $? "$T"
+    O_CIPHERS="$O_CIPHERS $T"
 }
 
 # Ciphersuites usable only with Mbed TLS and OpenSSL
-# Each ciphersuite should appear two times, once with its OpenSSL name, once
-# with its Mbed TLS name.
+# A list of ciphersuites in the Mbed TLS convention is compiled and
+# appended to the list of Mbed TLS ciphersuites $M_CIPHERS. The same list
+# is translated to the OpenSSL naming convention and appended to the list of
+# OpenSSL ciphersuites $O_CIPHERS.
 #
 # NOTE: for some reason RSA-PSK doesn't work with OpenSSL,
 # so RSA-PSK ciphersuites need to go in other sections, see
@@ -432,28 +352,23 @@
 # GnuTLS in 3.5.0 and the CI only has 3.4.x so far.
 add_openssl_ciphersuites()
 {
+    CIPHERS=""
     case $TYPE in
 
         "ECDSA")
             if [ `minor_ver "$MODE"` -gt 0 ]
             then
-                M_CIPHERS="$M_CIPHERS                       \
-                    TLS-ECDH-ECDSA-WITH-NULL-SHA            \
+                CIPHERS="$CIPHERS                           \
+                    TLS-ECDH-ECDSA-WITH-NULL-SHA       \
                     TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA    \
                     TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA     \
                     TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA     \
                     "
-                O_CIPHERS="$O_CIPHERS               \
-                    ECDH-ECDSA-NULL-SHA             \
-                    ECDH-ECDSA-DES-CBC3-SHA         \
-                    ECDH-ECDSA-AES128-SHA           \
-                    ECDH-ECDSA-AES256-SHA           \
-                    "
             fi
             if [ `minor_ver "$MODE"` -ge 3 ]
             then
-                M_CIPHERS="$M_CIPHERS                               \
-                    TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256          \
+                CIPHERS="$CIPHERS                           \
+                    TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256     \
                     TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384          \
                     TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256          \
                     TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384          \
@@ -461,31 +376,18 @@
                     TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256        \
                     TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256   \
                     "
-                O_CIPHERS="$O_CIPHERS               \
-                    ECDH-ECDSA-AES128-SHA256        \
-                    ECDH-ECDSA-AES256-SHA384        \
-                    ECDH-ECDSA-AES128-GCM-SHA256    \
-                    ECDH-ECDSA-AES256-GCM-SHA384    \
-                    ECDHE-ECDSA-ARIA256-GCM-SHA384  \
-                    ECDHE-ECDSA-ARIA128-GCM-SHA256  \
-                    ECDHE-ECDSA-CHACHA20-POLY1305   \
-                    "
             fi
             ;;
 
         "RSA")
-            M_CIPHERS="$M_CIPHERS                       \
-                TLS-RSA-WITH-DES-CBC-SHA                \
+            CIPHERS="$CIPHERS                           \
+                TLS-RSA-WITH-DES-CBC-SHA           \
                 TLS-DHE-RSA-WITH-DES-CBC-SHA            \
                 "
-            O_CIPHERS="$O_CIPHERS               \
-                DES-CBC-SHA                     \
-                EDH-RSA-DES-CBC-SHA             \
-                "
             if [ `minor_ver "$MODE"` -ge 3 ]
             then
-                M_CIPHERS="$M_CIPHERS                               \
-                    TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384          \
+                CIPHERS="$CIPHERS                           \
+                    TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384     \
                     TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384            \
                     TLS-RSA-WITH-ARIA-256-GCM-SHA384                \
                     TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256          \
@@ -494,24 +396,14 @@
                     TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256       \
                     TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256     \
                     "
-                O_CIPHERS="$O_CIPHERS               \
-                    ECDHE-ARIA256-GCM-SHA384        \
-                    DHE-RSA-ARIA256-GCM-SHA384      \
-                    ARIA256-GCM-SHA384              \
-                    ECDHE-ARIA128-GCM-SHA256        \
-                    DHE-RSA-ARIA128-GCM-SHA256      \
-                    ARIA128-GCM-SHA256              \
-                    DHE-RSA-CHACHA20-POLY1305       \
-                    ECDHE-RSA-CHACHA20-POLY1305     \
-                    "
             fi
             ;;
 
         "PSK")
             if [ `minor_ver "$MODE"` -ge 3 ]
             then
-                M_CIPHERS="$M_CIPHERS                               \
-                    TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384            \
+                CIPHERS="$CIPHERS                           \
+                    TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384       \
                     TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256            \
                     TLS-PSK-WITH-ARIA-256-GCM-SHA384                \
                     TLS-PSK-WITH-ARIA-128-GCM-SHA256                \
@@ -519,66 +411,47 @@
                     TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256     \
                     TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256       \
                     "
-                O_CIPHERS="$O_CIPHERS               \
-                    DHE-PSK-ARIA256-GCM-SHA384      \
-                    DHE-PSK-ARIA128-GCM-SHA256      \
-                    PSK-ARIA256-GCM-SHA384          \
-                    PSK-ARIA128-GCM-SHA256          \
-                    DHE-PSK-CHACHA20-POLY1305       \
-                    ECDHE-PSK-CHACHA20-POLY1305     \
-                    PSK-CHACHA20-POLY1305           \
-                    "
             fi
             ;;
     esac
+
+    M_CIPHERS="$M_CIPHERS $CIPHERS"
+
+    T=$(./scripts/translate_ciphers.py o $CIPHERS)
+    check_translation $? "$T"
+    O_CIPHERS="$O_CIPHERS $T"
 }
 
 # Ciphersuites usable only with Mbed TLS and GnuTLS
-# Each ciphersuite should appear two times, once with its GnuTLS name, once
-# with its Mbed TLS name.
+# A list of ciphersuites in the Mbed TLS convention is compiled and
+# appended to the list of Mbed TLS ciphersuites $M_CIPHERS. The same list
+# is translated to the GnuTLS naming convention and appended to the list of
+# GnuTLS ciphersuites $G_CIPHERS.
 add_gnutls_ciphersuites()
 {
+    CIPHERS=""
     case $TYPE in
 
         "ECDSA")
             if [ `minor_ver "$MODE"` -ge 3 ]
             then
-                M_CIPHERS="$M_CIPHERS                               \
-                    TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256    \
-                    TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384    \
-                    TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256    \
-                    TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384    \
-                    TLS-ECDHE-ECDSA-WITH-AES-128-CCM                \
-                    TLS-ECDHE-ECDSA-WITH-AES-256-CCM                \
-                    TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8              \
-                    TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8              \
-                   "
-                G_CIPHERS="$G_CIPHERS                               \
-                    +ECDHE-ECDSA:+CAMELLIA-128-CBC:+SHA256          \
-                    +ECDHE-ECDSA:+CAMELLIA-256-CBC:+SHA384          \
-                    +ECDHE-ECDSA:+CAMELLIA-128-GCM:+AEAD            \
-                    +ECDHE-ECDSA:+CAMELLIA-256-GCM:+AEAD            \
-                    +ECDHE-ECDSA:+AES-128-CCM:+AEAD                 \
-                    +ECDHE-ECDSA:+AES-256-CCM:+AEAD                 \
-                    +ECDHE-ECDSA:+AES-128-CCM-8:+AEAD               \
-                    +ECDHE-ECDSA:+AES-256-CCM-8:+AEAD               \
+                CIPHERS="$CIPHERS                           \
+                    TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256   \
+                    TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384        \
+                    TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256        \
+                    TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384        \
+                    TLS-ECDHE-ECDSA-WITH-AES-128-CCM                    \
+                    TLS-ECDHE-ECDSA-WITH-AES-256-CCM                    \
+                    TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8                  \
+                    TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8                  \
                    "
             fi
             ;;
 
         "RSA")
-            if [ `minor_ver "$MODE"` -gt 0 ]
-            then
-                M_CIPHERS="$M_CIPHERS                           \
-                    TLS-RSA-WITH-NULL-SHA256                    \
-                    "
-                G_CIPHERS="$G_CIPHERS                           \
-                    +RSA:+NULL:+SHA256                          \
-                    "
-            fi
             if [ `minor_ver "$MODE"` -ge 3 ]
             then
-                M_CIPHERS="$M_CIPHERS                           \
+                CIPHERS="$CIPHERS                               \
                     TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256  \
                     TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384  \
                     TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256        \
@@ -600,45 +473,18 @@
                     TLS-DHE-RSA-WITH-AES-128-CCM-8              \
                     TLS-DHE-RSA-WITH-AES-256-CCM-8              \
                     "
-                G_CIPHERS="$G_CIPHERS                           \
-                    +ECDHE-RSA:+CAMELLIA-128-CBC:+SHA256        \
-                    +ECDHE-RSA:+CAMELLIA-256-CBC:+SHA384        \
-                    +RSA:+CAMELLIA-128-CBC:+SHA256              \
-                    +RSA:+CAMELLIA-256-CBC:+SHA256              \
-                    +DHE-RSA:+CAMELLIA-128-CBC:+SHA256          \
-                    +DHE-RSA:+CAMELLIA-256-CBC:+SHA256          \
-                    +ECDHE-RSA:+CAMELLIA-128-GCM:+AEAD          \
-                    +ECDHE-RSA:+CAMELLIA-256-GCM:+AEAD          \
-                    +DHE-RSA:+CAMELLIA-128-GCM:+AEAD            \
-                    +DHE-RSA:+CAMELLIA-256-GCM:+AEAD            \
-                    +RSA:+CAMELLIA-128-GCM:+AEAD                \
-                    +RSA:+CAMELLIA-256-GCM:+AEAD                \
-                    +RSA:+AES-128-CCM:+AEAD                     \
-                    +RSA:+AES-256-CCM:+AEAD                     \
-                    +RSA:+AES-128-CCM-8:+AEAD                   \
-                    +RSA:+AES-256-CCM-8:+AEAD                   \
-                    +DHE-RSA:+AES-128-CCM:+AEAD                 \
-                    +DHE-RSA:+AES-256-CCM:+AEAD                 \
-                    +DHE-RSA:+AES-128-CCM-8:+AEAD               \
-                    +DHE-RSA:+AES-256-CCM-8:+AEAD               \
-                    "
             fi
             ;;
 
         "PSK")
-            M_CIPHERS="$M_CIPHERS                               \
-                TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA               \
-                TLS-DHE-PSK-WITH-AES-128-CBC-SHA                \
-                TLS-DHE-PSK-WITH-AES-256-CBC-SHA                \
-                "
-            G_CIPHERS="$G_CIPHERS                               \
-                +DHE-PSK:+3DES-CBC:+SHA1                        \
-                +DHE-PSK:+AES-128-CBC:+SHA1                     \
-                +DHE-PSK:+AES-256-CBC:+SHA1                     \
+            CIPHERS="$CIPHERS                                 \
+                TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA             \
+                TLS-DHE-PSK-WITH-AES-128-CBC-SHA              \
+                TLS-DHE-PSK-WITH-AES-256-CBC-SHA              \
                 "
             if [ `minor_ver "$MODE"` -gt 0 ]
             then
-                M_CIPHERS="$M_CIPHERS                           \
+                CIPHERS="$CIPHERS                               \
                     TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA          \
                     TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA          \
                     TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA         \
@@ -646,18 +492,10 @@
                     TLS-RSA-PSK-WITH-AES-256-CBC-SHA            \
                     TLS-RSA-PSK-WITH-AES-128-CBC-SHA            \
                     "
-                G_CIPHERS="$G_CIPHERS                           \
-                    +ECDHE-PSK:+3DES-CBC:+SHA1                  \
-                    +ECDHE-PSK:+AES-128-CBC:+SHA1               \
-                    +ECDHE-PSK:+AES-256-CBC:+SHA1               \
-                    +RSA-PSK:+3DES-CBC:+SHA1                    \
-                    +RSA-PSK:+AES-256-CBC:+SHA1                 \
-                    +RSA-PSK:+AES-128-CBC:+SHA1                 \
-                    "
             fi
             if [ `minor_ver "$MODE"` -ge 3 ]
             then
-                M_CIPHERS="$M_CIPHERS                           \
+                CIPHERS="$CIPHERS                               \
                     TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384       \
                     TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384  \
                     TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256       \
@@ -703,55 +541,15 @@
                     TLS-RSA-PSK-WITH-AES-256-GCM-SHA384         \
                     TLS-RSA-PSK-WITH-AES-128-GCM-SHA256         \
                     "
-                G_CIPHERS="$G_CIPHERS                           \
-                    +ECDHE-PSK:+AES-256-CBC:+SHA384             \
-                    +ECDHE-PSK:+CAMELLIA-256-CBC:+SHA384        \
-                    +ECDHE-PSK:+AES-128-CBC:+SHA256             \
-                    +ECDHE-PSK:+CAMELLIA-128-CBC:+SHA256        \
-                    +PSK:+AES-128-CBC:+SHA256                   \
-                    +PSK:+AES-256-CBC:+SHA384                   \
-                    +DHE-PSK:+AES-128-CBC:+SHA256               \
-                    +DHE-PSK:+AES-256-CBC:+SHA384               \
-                    +RSA-PSK:+AES-256-CBC:+SHA384               \
-                    +RSA-PSK:+AES-128-CBC:+SHA256               \
-                    +DHE-PSK:+CAMELLIA-128-CBC:+SHA256          \
-                    +DHE-PSK:+CAMELLIA-256-CBC:+SHA384          \
-                    +PSK:+CAMELLIA-128-CBC:+SHA256              \
-                    +PSK:+CAMELLIA-256-CBC:+SHA384              \
-                    +RSA-PSK:+CAMELLIA-256-CBC:+SHA384          \
-                    +RSA-PSK:+CAMELLIA-128-CBC:+SHA256          \
-                    +PSK:+AES-128-GCM:+AEAD                     \
-                    +PSK:+AES-256-GCM:+AEAD                     \
-                    +DHE-PSK:+AES-128-GCM:+AEAD                 \
-                    +DHE-PSK:+AES-256-GCM:+AEAD                 \
-                    +PSK:+AES-128-CCM:+AEAD                     \
-                    +PSK:+AES-256-CCM:+AEAD                     \
-                    +DHE-PSK:+AES-128-CCM:+AEAD                 \
-                    +DHE-PSK:+AES-256-CCM:+AEAD                 \
-                    +PSK:+AES-128-CCM-8:+AEAD                   \
-                    +PSK:+AES-256-CCM-8:+AEAD                   \
-                    +DHE-PSK:+AES-128-CCM-8:+AEAD               \
-                    +DHE-PSK:+AES-256-CCM-8:+AEAD               \
-                    +RSA-PSK:+CAMELLIA-128-GCM:+AEAD            \
-                    +RSA-PSK:+CAMELLIA-256-GCM:+AEAD            \
-                    +PSK:+CAMELLIA-128-GCM:+AEAD                \
-                    +PSK:+CAMELLIA-256-GCM:+AEAD                \
-                    +DHE-PSK:+CAMELLIA-128-GCM:+AEAD            \
-                    +DHE-PSK:+CAMELLIA-256-GCM:+AEAD            \
-                    +RSA-PSK:+AES-256-GCM:+AEAD                 \
-                    +RSA-PSK:+AES-128-GCM:+AEAD                 \
-                    +ECDHE-PSK:+NULL:+SHA384                    \
-                    +ECDHE-PSK:+NULL:+SHA256                    \
-                    +PSK:+NULL:+SHA256                          \
-                    +PSK:+NULL:+SHA384                          \
-                    +DHE-PSK:+NULL:+SHA256                      \
-                    +DHE-PSK:+NULL:+SHA384                      \
-                    +RSA-PSK:+NULL:+SHA256                      \
-                    +RSA-PSK:+NULL:+SHA384                      \
-                    "
             fi
             ;;
     esac
+
+    M_CIPHERS="$M_CIPHERS $CIPHERS"
+
+    T=$(./scripts/translate_ciphers.py g $CIPHERS)
+    check_translation $? "$T"
+    G_CIPHERS="$G_CIPHERS $T"
 }
 
 # Ciphersuites usable only with Mbed TLS (not currently supported by another
diff --git a/tests/configs/user-config-for-test.h b/tests/configs/user-config-for-test.h
new file mode 100644
index 0000000..444a4bf
--- /dev/null
+++ b/tests/configs/user-config-for-test.h
@@ -0,0 +1,57 @@
+/* MBEDTLS_USER_CONFIG_FILE for testing.
+ * Only used for a few test configurations.
+ *
+ * Typical usage (note multiple levels of quoting):
+ *     make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/user-config-for-test.h\"'"
+ */
+
+/*
+ *  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(PSA_CRYPTO_DRIVER_TEST_ALL)
+
+/* Enable the use of the test driver in the library, and build the generic
+ * part of the test driver. */
+#define PSA_CRYPTO_DRIVER_TEST
+
+/* Use the accelerator driver for all cryptographic mechanisms for which
+ * the test driver implemented. */
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_AES
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR
+#define MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING
+#define MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7
+#define MBEDTLS_PSA_ACCEL_ALG_CTR
+#define MBEDTLS_PSA_ACCEL_ALG_CFB
+#define MBEDTLS_PSA_ACCEL_ALG_ECDSA
+#define MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA
+#define MBEDTLS_PSA_ACCEL_ALG_MD5
+#define MBEDTLS_PSA_ACCEL_ALG_OFB
+#define MBEDTLS_PSA_ACCEL_ALG_RIPEMD160
+#define MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN
+#define MBEDTLS_PSA_ACCEL_ALG_RSA_PSS
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_1
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_224
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_256
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_384
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_512
+#define MBEDTLS_PSA_ACCEL_ALG_XTS
+#define MBEDTLS_PSA_ACCEL_ALG_CMAC
+#define MBEDTLS_PSA_ACCEL_ALG_HMAC
+
+#endif  /* PSA_CRYPTO_DRIVER_TEST_ALL */
diff --git a/tests/include/test/drivers/aead.h b/tests/include/test/drivers/aead.h
index 0830229..2421560 100644
--- a/tests/include/test/drivers/aead.h
+++ b/tests/include/test/drivers/aead.h
@@ -30,12 +30,23 @@
      * function call. */
     psa_status_t forced_status;
     /* Count the amount of times AEAD driver functions are called. */
-    unsigned long hits;
+    unsigned long hits_encrypt;
+    unsigned long hits_decrypt;
+    unsigned long hits_encrypt_setup;
+    unsigned long hits_decrypt_setup;
+    unsigned long hits_set_nonce;
+    unsigned long hits_set_lengths;
+    unsigned long hits_update_ad;
+    unsigned long hits_update;
+    unsigned long hits_finish;
+    unsigned long hits_verify;
+    unsigned long hits_abort;
+
     /* Status returned by the last AEAD driver function call. */
     psa_status_t driver_status;
 } mbedtls_test_driver_aead_hooks_t;
 
-#define MBEDTLS_TEST_DRIVER_AEAD_INIT { 0, 0, 0 }
+#define MBEDTLS_TEST_DRIVER_AEAD_INIT { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 static inline mbedtls_test_driver_aead_hooks_t
     mbedtls_test_driver_aead_hooks_init( void )
 {
@@ -63,5 +74,60 @@
     const uint8_t *ciphertext, size_t ciphertext_length,
     uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length );
 
+psa_status_t mbedtls_test_transparent_aead_encrypt_setup(
+    mbedtls_psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t mbedtls_test_transparent_aead_decrypt_setup(
+    mbedtls_psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg );
+
+psa_status_t mbedtls_test_transparent_aead_set_nonce(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *nonce,
+    size_t nonce_length );
+
+psa_status_t mbedtls_test_transparent_aead_set_lengths(
+    mbedtls_psa_aead_operation_t *operation,
+    size_t ad_length,
+    size_t plaintext_length );
+
+psa_status_t mbedtls_test_transparent_aead_update_ad(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length );
+
+psa_status_t mbedtls_test_transparent_aead_update(
+   mbedtls_psa_aead_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 mbedtls_test_transparent_aead_finish(
+   mbedtls_psa_aead_operation_t *operation,
+   uint8_t *ciphertext,
+   size_t ciphertext_size,
+   size_t *ciphertext_length,
+   uint8_t *tag,
+   size_t tag_size,
+   size_t *tag_length );
+
+psa_status_t mbedtls_test_transparent_aead_verify(
+   mbedtls_psa_aead_operation_t *operation,
+   uint8_t *plaintext,
+   size_t plaintext_size,
+   size_t *plaintext_length,
+   const uint8_t *tag,
+   size_t tag_length );
+
+psa_status_t mbedtls_test_transparent_aead_abort(
+   mbedtls_psa_aead_operation_t *operation );
+
 #endif /* PSA_CRYPTO_DRIVER_TEST */
 #endif /* PSA_CRYPTO_TEST_DRIVERS_AEAD_H */
diff --git a/tests/include/test/helpers.h b/tests/include/test/helpers.h
index 27e5599..ef32cdf 100644
--- a/tests/include/test/helpers.h
+++ b/tests/include/test/helpers.h
@@ -73,6 +73,8 @@
     const char *filename;
     int line_no;
     unsigned long step;
+    char line1[76];
+    char line2[76];
 #if defined(MBEDTLS_TEST_MUTEX_USAGE)
     const char *mutex_usage_error;
 #endif
@@ -132,6 +134,27 @@
 void mbedtls_test_info_reset( void );
 
 /**
+ * \brief           Record the current test case as a failure if two integers
+ *                  have a different value.
+ *
+ *                  This function is usually called via the macro
+ *                  #TEST_EQUAL.
+ *
+ * \param test      Description of the failure or assertion that failed. This
+ *                  MUST be a string literal. This normally has the form
+ *                  "EXPR1 == EXPR2" where EXPR1 has the value \p value1
+ *                  and EXPR2 has the value \p value2.
+ * \param line_no   Line number where the failure originated.
+ * \param filename  Filename where the failure originated.
+ * \param value1    The first value to compare.
+ * \param value2    The second value to compare.
+ *
+ * \return          \c 1 if the values are equal, otherwise \c 0.
+ */
+int mbedtls_test_equal( const char *test, int line_no, const char* filename,
+                        unsigned long long value1, unsigned long long value2 );
+
+/**
  * \brief          This function decodes the hexadecimal representation of
  *                 data.
  *
diff --git a/tests/include/test/macros.h b/tests/include/test/macros.h
index 9b3fc9c..a88b2e8 100644
--- a/tests/include/test/macros.h
+++ b/tests/include/test/macros.h
@@ -73,15 +73,21 @@
        }                                                    \
     } while( 0 )
 
-/** Evaluate two expressions and fail the test case if they have different
- * values.
+/** Evaluate two integer expressions and fail the test case if they have
+ * different values.
  *
- * \param expr1     An expression to evaluate.
- * \param expr2     The expected value of \p expr1. This can be any
- *                  expression, but it is typically a constant.
+ * The two expressions should have the same signedness, otherwise the
+ * comparison is not meaningful if the signed value is negative.
+ *
+ * \param expr1     An integral-typed expression to evaluate.
+ * \param expr2     Another integral-typed expression to evaluate.
  */
-#define TEST_EQUAL( expr1, expr2 )              \
-    TEST_ASSERT( ( expr1 ) == ( expr2 ) )
+#define TEST_EQUAL( expr1, expr2 )                                      \
+    do {                                                                \
+        if( ! mbedtls_test_equal( #expr1 " == " #expr2, __LINE__, __FILE__, \
+                                  expr1, expr2 ) )                      \
+            goto exit;                                                  \
+    } while( 0 )
 
 /** Allocate memory dynamically and fail the test case if this fails.
  * The allocated memory will be filled with zeros.
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 9944a85..c148cf1 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -175,10 +175,10 @@
 
     # if MAKEFLAGS is not set add the -j option to speed up invocations of make
     if [ -z "${MAKEFLAGS+set}" ]; then
-        export MAKEFLAGS="-j"
+        export MAKEFLAGS="-j$(all_sh_nproc)"
     fi
 
-    # Include more verbose output for failing tests run by CMake
+    # Include more verbose output for failing tests run by CMake or make
     export CTEST_OUTPUT_ON_FAILURE=1
 
     # CFLAGS and LDFLAGS for Asan builds that don't use CMake
@@ -292,7 +292,8 @@
            -iname CMakeFiles -exec rm -rf {} \+ -o \
            \( -iname cmake_install.cmake -o \
               -iname CTestTestfile.cmake -o \
-              -iname CMakeCache.txt \) -exec rm -f {} \+
+              -iname CMakeCache.txt -o \
+              -path './cmake/*.cmake' \) -exec rm -f {} \+
     # Recover files overwritten by in-tree CMake builds
     rm -f include/Makefile include/mbedtls/Makefile programs/*/Makefile
 
@@ -343,6 +344,18 @@
 trap 'fatal_signal INT' INT
 trap 'fatal_signal TERM' TERM
 
+# Number of processors on this machine. Used as the default setting
+# for parallel make.
+all_sh_nproc ()
+{
+    {
+        nproc || # Linux
+        sysctl -n hw.ncpuonline || # NetBSD, OpenBSD
+        sysctl -n hw.ncpu || # FreeBSD
+        echo 1
+    } 2>/dev/null
+}
+
 msg()
 {
     if [ -n "${current_component:-}" ]; then
@@ -841,7 +854,7 @@
 
 component_check_names () {
     msg "Check: declared and exported names (builds the library)" # < 3s
-    tests/scripts/check-names.sh -v
+    tests/scripts/check_names.py -v
 }
 
 component_check_test_cases () {
@@ -986,7 +999,16 @@
 
 component_test_ref_configs () {
     msg "test/build: ref-configs (ASan build)" # ~ 6 min 20s
-    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+    # test-ref-configs works by overwriting mbedtls_config.h; this makes cmake
+    # want to re-generate generated files that depend on it, quite correctly.
+    # However this doesn't work as the generation script expects a specific
+    # format for mbedtls_config.h, which the other files don't follow. Also,
+    # cmake can't know this, but re-generation is actually not necessary as
+    # the generated files only depend on the list of available options, not
+    # whether they're on or off. So, disable cmake's (over-sensitive here)
+    # dependency resolution for generated files and just rely on them being
+    # present (thanks to pre_generate_files) by turning GEN_FILES off.
+    CC=gcc cmake -D GEN_FILES=Off -D CMAKE_BUILD_TYPE:String=Asan .
     tests/scripts/test-ref-configs.pl
 }
 
@@ -1283,7 +1305,7 @@
 component_test_full_cmake_clang () {
     msg "build: cmake, full config, clang" # ~ 50s
     scripts/config.py full
-    CC=clang cmake -D CMAKE_BUILD_TYPE:String=Check -D ENABLE_TESTING=On .
+    CC=clang cmake -D CMAKE_BUILD_TYPE:String=Release -D ENABLE_TESTING=On .
     make
 
     msg "test: main suites (full config, clang)" # ~ 5s
@@ -1560,31 +1582,8 @@
     scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_KEY_TYPE_DES
     scripts/config.py unset MBEDTLS_DES_C
 
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    loc_cflags="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_KEY_TYPE_AES"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_CTR"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_CFB"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_ECDSA"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_MD5"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_OFB"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_RIPEMD160"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_RSA_PSS"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_1"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_224"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_256"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_384"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_512"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_XTS"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_CMAC"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_HMAC"
+    loc_cflags="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST_ALL"
+    loc_cflags="${loc_cflags} '-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/user-config-for-test.h\"'"
     loc_cflags="${loc_cflags} -I../tests/include -O2"
 
     make CC=gcc CFLAGS="$loc_cflags" LDFLAGS="$ASAN_CFLAGS"
@@ -1607,6 +1606,19 @@
     make test
 }
 
+component_test_psa_crypto_config_chachapoly_disabled() {
+    # full minus MBEDTLS_CHACHAPOLY_C without PSA_WANT_ALG_GCM and PSA_WANT_ALG_CHACHA20_POLY1305
+    msg "build: full minus MBEDTLS_CHACHAPOLY_C without PSA_WANT_ALG_GCM and PSA_WANT_ALG_CHACHA20_POLY1305"
+    scripts/config.py full
+    scripts/config.py unset MBEDTLS_CHACHAPOLY_C
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_GCM
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_CHACHA20_POLY1305
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
+
+    msg "test: full minus MBEDTLS_CHACHAPOLY_C without PSA_WANT_ALG_GCM and PSA_WANT_ALG_CHACHA20_POLY1305"
+    make test
+}
+
 # This should be renamed to test and updated once the accelerator ECDSA code is in place and ready to test.
 component_build_psa_accel_alg_ecdsa() {
     # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_ALG_ECDSA
@@ -1949,7 +1961,8 @@
     scripts/config.py set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
     scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
     scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -Os'
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Check .
+    make
 }
 
 component_build_no_ssl_srv () {
@@ -1982,7 +1995,7 @@
     scripts/config.py set MBEDTLS_PLATFORM_MEMORY
     scripts/config.py set MBEDTLS_MEMORY_BACKTRACE
     scripts/config.py set MBEDTLS_MEMORY_DEBUG
-    CC=gcc cmake .
+    CC=gcc cmake -DCMAKE_BUILD_TYPE:String=Release .
     make
 
     msg "test: MBEDTLS_MEMORY_BUFFER_ALLOC_C and MBEDTLS_MEMORY_BACKTRACE"
@@ -1993,7 +2006,7 @@
     msg "build: default config with memory buffer allocator"
     scripts/config.py set MBEDTLS_MEMORY_BUFFER_ALLOC_C
     scripts/config.py set MBEDTLS_PLATFORM_MEMORY
-    CC=gcc cmake .
+    CC=gcc cmake -DCMAKE_BUILD_TYPE:String=Release .
     make
 
     msg "test: MBEDTLS_MEMORY_BUFFER_ALLOC_C"
@@ -2083,6 +2096,18 @@
     tests/compat.sh
 }
 
+component_test_CID_no_debug() {
+    msg "build: Connection ID enabled, debug disabled"
+    scripts/config.py unset MBEDTLS_DEBUG_C
+    scripts/config.py set MBEDTLS_SSL_DTLS_CONNECTION_ID
+
+    CC=gcc cmake .
+    make
+
+    msg "test: Connection ID enabled, debug disabled"
+    make test
+}
+
 component_test_ssl_alloc_buffer_and_mfl () {
     msg "build: default config with memory buffer allocator and MFL extension"
     scripts/config.py set MBEDTLS_MEMORY_BUFFER_ALLOC_C
@@ -2090,7 +2115,7 @@
     scripts/config.py set MBEDTLS_MEMORY_DEBUG
     scripts/config.py set MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
     scripts/config.py set MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
-    CC=gcc cmake .
+    CC=gcc cmake -DCMAKE_BUILD_TYPE:String=Release .
     make
 
     msg "test: MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH, MBEDTLS_MEMORY_BUFFER_ALLOC_C, MBEDTLS_MEMORY_DEBUG and MBEDTLS_SSL_MAX_FRAGMENT_LENGTH"
@@ -2117,7 +2142,7 @@
 component_test_no_date_time () {
     msg "build: default config without MBEDTLS_HAVE_TIME_DATE"
     scripts/config.py unset MBEDTLS_HAVE_TIME_DATE
-    CC=gcc cmake
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Check .
     make
 
     msg "test: !MBEDTLS_HAVE_TIME_DATE - main suites"
@@ -2237,31 +2262,8 @@
     scripts/config.py full
     scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
     scripts/config.py set MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS
-    # Need to define the correct symbol and include the test driver header path in order to build with the test driver
-    loc_cflags="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_KEY_TYPE_AES"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_CTR"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_CFB"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_ECDSA"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_MD5"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_OFB"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_RIPEMD160"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_RSA_PSS"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_1"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_224"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_256"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_384"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_SHA_512"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_XTS"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_CMAC"
-    loc_cflags="${loc_cflags} -DMBEDTLS_PSA_ACCEL_ALG_HMAC"
+    loc_cflags="$ASAN_CFLAGS -DPSA_CRYPTO_DRIVER_TEST_ALL"
+    loc_cflags="${loc_cflags} '-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/user-config-for-test.h\"'"
     loc_cflags="${loc_cflags} -I../tests/include -O2"
 
     make CC=gcc CFLAGS="${loc_cflags}" LDFLAGS="$ASAN_CFLAGS"
@@ -2321,7 +2323,8 @@
 }
 
 component_test_m32_o0 () {
-    # Build once with -O0, to compile out the i386 specific inline assembly
+    # Build without optimization, so as to use portable C code (in a 32-bit
+    # build) and not the i386-specific inline assembly.
     msg "build: i386, make, gcc -O0 (ASan build)" # ~ 30s
     scripts/config.py full
     make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O0" LDFLAGS="-m32 $ASAN_CFLAGS"
@@ -2336,19 +2339,20 @@
     esac
 }
 
-component_test_m32_o1 () {
-    # Build again with -O1, to compile in the i386 specific inline assembly
-    msg "build: i386, make, gcc -O1 (ASan build)" # ~ 30s
+component_test_m32_o2 () {
+    # Build with optimization, to use the i386 specific inline assembly
+    # and go faster for tests.
+    msg "build: i386, make, gcc -O2 (ASan build)" # ~ 30s
     scripts/config.py full
-    make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O1" LDFLAGS="-m32 $ASAN_CFLAGS"
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O2" LDFLAGS="-m32 $ASAN_CFLAGS"
 
-    msg "test: i386, make, gcc -O1 (ASan build)"
+    msg "test: i386, make, gcc -O2 (ASan build)"
     make test
 
-    msg "test ssl-opt.sh, i386, make, gcc-O1"
+    msg "test ssl-opt.sh, i386, make, gcc-O2"
     tests/ssl-opt.sh
 }
-support_test_m32_o1 () {
+support_test_m32_o2 () {
     support_test_m32_o0 "$@"
 }
 
@@ -2457,7 +2461,7 @@
     scripts/config.pl full
     scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
     scripts/config.pl set MBEDTLS_X509_REMOVE_INFO
-    make CFLAGS='-Werror -O1'
+    make CFLAGS='-Werror -O2'
 
     msg "test: full + MBEDTLS_X509_REMOVE_INFO" # ~ 10s
     make test
@@ -2565,6 +2569,8 @@
     make
     msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL enabled, without padding"
     make test
+    msg "ssl-opt.sh (TLS 1.3 experimental)"
+    if_build_succeeded tests/ssl-opt.sh
 }
 
 component_test_tls13_experimental_with_padding () {
@@ -2579,6 +2585,31 @@
     if_build_succeeded tests/ssl-opt.sh
 }
 
+component_test_tls13_experimental_with_ecp_restartable () {
+    msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL enabled, with ecp_restartable"
+    scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
+    scripts/config.py set MBEDTLS_ECP_RESTARTABLE
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+    make
+    msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL enabled, with ecp_restartable"
+    make test
+    msg "ssl-opt.sh (TLS 1.3 experimental)"
+    if_build_succeeded tests/ssl-opt.sh
+}
+
+component_test_tls13_experimental_with_everest () {
+    msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL enabled, with Everest"
+    scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
+    scripts/config.py set MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED
+    scripts/config.py unset MBEDTLS_ECP_RESTARTABLE
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+    make
+    msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL enabled, with Everest"
+    make test
+    msg "ssl-opt.sh (TLS 1.3 experimental)"
+    if_build_succeeded tests/ssl-opt.sh
+}
+
 component_build_mingw () {
     msg "build: Windows cross build - mingw64, make (Link Library)" # ~ 30s
     make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 lib programs
@@ -2650,7 +2681,7 @@
     MBEDTLS_ROOT_DIR="$PWD"
     mkdir "$OUT_OF_SOURCE_DIR"
     cd "$OUT_OF_SOURCE_DIR"
-    cmake "$MBEDTLS_ROOT_DIR"
+    cmake -D CMAKE_BUILD_TYPE:String=Check "$MBEDTLS_ROOT_DIR"
     make
 
     msg "test: cmake 'out-of-source' build"
@@ -2743,12 +2774,15 @@
     tests/scripts/check-python-files.sh
 }
 
-component_check_generate_test_code () {
-    msg "uint test: generate_test_code.py"
+component_check_test_helpers () {
+    msg "unit test: generate_test_code.py"
     # unittest writes out mundane stuff like number or tests run on stderr.
     # Our convention is to reserve stderr for actual errors, and write
     # harmless info on stdout so it can be suppress with --quiet.
     ./tests/scripts/test_generate_test_code.py 2>&1
+
+    msg "unit test: translate_ciphers.py"
+    python3 -m unittest tests/scripts/translate_ciphers.py 2>&1
 }
 
 ################################################################
diff --git a/tests/scripts/check-names.sh b/tests/scripts/check-names.sh
deleted file mode 100755
index 2a06adc..0000000
--- a/tests/scripts/check-names.sh
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/bin/sh
-#
-# 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.
-
-set -eu
-
-if [ $# -ne 0 ] && [ "$1" = "--help" ]; then
-    cat <<EOF
-$0 [-v]
-This script confirms that the naming of all symbols and identifiers in mbed
-TLS are consistent with the house style and are also self-consistent.
-
-  -v    If the script fails unexpectedly, print a command trace.
-EOF
-    exit
-fi
-
-trace=
-if [ $# -ne 0 ] && [ "$1" = "-v" ]; then
-  shift
-  trace='-x'
-  exec 2>check-names.err
-  trap 'echo "FAILED UNEXPECTEDLY, status=$?";
-        cat check-names.err' EXIT
-  set -x
-fi
-
-printf "Analysing source code...\n"
-
-sh $trace tests/scripts/list-macros.sh
-tests/scripts/list-enum-consts.pl
-sh $trace tests/scripts/list-identifiers.sh
-sh $trace tests/scripts/list-symbols.sh
-
-FAIL=0
-
-printf "\nExported symbols declared in header: "
-UNDECLARED=$( diff exported-symbols identifiers | sed -n -e 's/^< //p' )
-if [ "x$UNDECLARED" = "x" ]; then
-    echo "PASS"
-else
-    echo "FAIL"
-    echo "$UNDECLARED"
-    FAIL=1
-fi
-
-diff macros identifiers | sed -n -e 's/< //p' > actual-macros
-
-for THING in actual-macros enum-consts; do
-    printf 'Names of %s: ' "$THING"
-    test -r $THING
-    BAD=$( grep -E -v '^(MBEDTLS|PSA)_[0-9A-Z_]*[0-9A-Z]$' $THING || true )
-    UNDERSCORES=$( grep -E '.*__.*' $THING || true )
-
-    if [ "x$BAD" = "x" ] && [ "x$UNDERSCORES" = "x" ]; then
-        echo "PASS"
-    else
-        echo "FAIL"
-        echo "$BAD"
-        echo "$UNDERSCORES"
-        FAIL=1
-    fi
-done
-
-for THING in identifiers; do
-    printf 'Names of %s: ' "$THING"
-    test -r $THING
-    BAD=$( grep -E -v '^(mbedtls|psa)_[0-9a-z_]*[0-9a-z]$' $THING || true )
-    if [ "x$BAD" = "x" ]; then
-        echo "PASS"
-    else
-        echo "FAIL"
-        echo "$BAD"
-        FAIL=1
-    fi
-done
-
-printf "Likely typos: "
-sort -u actual-macros enum-consts > _caps
-HEADERS=$( ls include/mbedtls/*.h include/psa/*.h | egrep -v 'compat-2\.x\.h' )
-HEADERS="$HEADERS library/*.h"
-HEADERS="$HEADERS 3rdparty/everest/include/everest/everest.h 3rdparty/everest/include/everest/x25519.h"
-LIBRARY="$( ls library/*.c )"
-LIBRARY="$LIBRARY 3rdparty/everest/library/everest.c 3rdparty/everest/library/x25519.c"
-NL='
-'
-cat $HEADERS $LIBRARY \
-    | grep -v -e '//no-check-names' -e '#error' \
-    | sed -n 's/MBED..._[A-Z0-9_]*/\'"$NL"'&\'"$NL"/gp \
-    | grep MBEDTLS | sort -u > _MBEDTLS_XXX
-TYPOS=$( diff _caps _MBEDTLS_XXX | sed -n 's/^> //p' \
-            | egrep -v 'XXX|__|_$|^MBEDTLS_.*CONFIG_FILE$' || true )
-rm _MBEDTLS_XXX _caps
-if [ "x$TYPOS" = "x" ]; then
-    echo "PASS"
-else
-    echo "FAIL"
-    echo "$TYPOS"
-    FAIL=1
-fi
-
-if [ -n "$trace" ]; then
-  set +x
-  trap - EXIT
-  rm check-names.err
-fi
-
-printf "\nOverall: "
-if [ "$FAIL" -eq 0 ]; then
-    rm macros actual-macros enum-consts identifiers exported-symbols
-    echo "PASSED"
-    exit 0
-else
-    echo "FAILED"
-    exit 1
-fi
diff --git a/tests/scripts/check_names.py b/tests/scripts/check_names.py
new file mode 100755
index 0000000..ac2490f
--- /dev/null
+++ b/tests/scripts/check_names.py
@@ -0,0 +1,862 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+"""
+This script confirms that the naming of all symbols and identifiers in Mbed TLS
+are consistent with the house style and are also self-consistent. It only runs
+on Linux and macOS since it depends on nm.
+
+It contains two major Python classes, CodeParser and NameChecker. They both have
+a comprehensive "run-all" function (comprehensive_parse() and perform_checks())
+but the individual functions can also be used for specific needs.
+
+CodeParser makes heavy use of regular expressions to parse the code, and is
+dependent on the current code formatting. Many Python C parser libraries require
+preprocessed C code, which means no macro parsing. Compiler tools are also not
+very helpful when we want the exact location in the original source (which
+becomes impossible when e.g. comments are stripped).
+
+NameChecker performs the following checks:
+
+- All exported and available symbols in the library object files, are explicitly
+  declared in the header files. This uses the nm command.
+- All macros, constants, and identifiers (function names, struct names, etc)
+  follow the required regex pattern.
+- Typo checking: All words that begin with MBED exist as macros or constants.
+
+The script returns 0 on success, 1 on test failure, and 2 if there is a script
+error. It must be run from Mbed TLS root.
+"""
+
+import abc
+import argparse
+import fnmatch
+import glob
+import textwrap
+import os
+import sys
+import traceback
+import re
+import enum
+import shutil
+import subprocess
+import logging
+
+# Naming patterns to check against. These are defined outside the NameCheck
+# class for ease of modification.
+MACRO_PATTERN = r"^(MBEDTLS|PSA)_[0-9A-Z_]*[0-9A-Z]$"
+CONSTANTS_PATTERN = MACRO_PATTERN
+IDENTIFIER_PATTERN = r"^(mbedtls|psa)_[0-9a-z_]*[0-9a-z]$"
+
+class Match(): # pylint: disable=too-few-public-methods
+    """
+    A class representing a match, together with its found position.
+
+    Fields:
+    * filename: the file that the match was in.
+    * line: the full line containing the match.
+    * line_no: the line number.
+    * pos: a tuple of (start, end) positions on the line where the match is.
+    * name: the match itself.
+    """
+    def __init__(self, filename, line, line_no, pos, name):
+        # pylint: disable=too-many-arguments
+        self.filename = filename
+        self.line = line
+        self.line_no = line_no
+        self.pos = pos
+        self.name = name
+
+    def __str__(self):
+        """
+        Return a formatted code listing representation of the erroneous line.
+        """
+        gutter = format(self.line_no, "4d")
+        underline = self.pos[0] * " " + (self.pos[1] - self.pos[0]) * "^"
+
+        return (
+            " {0} |\n".format(" " * len(gutter)) +
+            " {0} | {1}".format(gutter, self.line) +
+            " {0} | {1}\n".format(" " * len(gutter), underline)
+        )
+
+class Problem(abc.ABC): # pylint: disable=too-few-public-methods
+    """
+    An abstract parent class representing a form of static analysis error.
+    It extends an Abstract Base Class, which means it is not instantiable, and
+    it also mandates certain abstract methods to be implemented in subclasses.
+    """
+    # Class variable to control the quietness of all problems
+    quiet = False
+    def __init__(self):
+        self.textwrapper = textwrap.TextWrapper()
+        self.textwrapper.width = 80
+        self.textwrapper.initial_indent = "    > "
+        self.textwrapper.subsequent_indent = "      "
+
+    def __str__(self):
+        """
+        Unified string representation method for all Problems.
+        """
+        if self.__class__.quiet:
+            return self.quiet_output()
+        return self.verbose_output()
+
+    @abc.abstractmethod
+    def quiet_output(self):
+        """
+        The output when --quiet is enabled.
+        """
+        pass
+
+    @abc.abstractmethod
+    def verbose_output(self):
+        """
+        The default output with explanation and code snippet if appropriate.
+        """
+        pass
+
+class SymbolNotInHeader(Problem): # pylint: disable=too-few-public-methods
+    """
+    A problem that occurs when an exported/available symbol in the object file
+    is not explicitly declared in header files. Created with
+    NameCheck.check_symbols_declared_in_header()
+
+    Fields:
+    * symbol_name: the name of the symbol.
+    """
+    def __init__(self, symbol_name):
+        self.symbol_name = symbol_name
+        Problem.__init__(self)
+
+    def quiet_output(self):
+        return "{0}".format(self.symbol_name)
+
+    def verbose_output(self):
+        return self.textwrapper.fill(
+            "'{0}' was found as an available symbol in the output of nm, "
+            "however it was not declared in any header files."
+            .format(self.symbol_name))
+
+class PatternMismatch(Problem): # pylint: disable=too-few-public-methods
+    """
+    A problem that occurs when something doesn't match the expected pattern.
+    Created with NameCheck.check_match_pattern()
+
+    Fields:
+    * pattern: the expected regex pattern
+    * match: the Match object in question
+    """
+    def __init__(self, pattern, match):
+        self.pattern = pattern
+        self.match = match
+        Problem.__init__(self)
+
+
+    def quiet_output(self):
+        return (
+            "{0}:{1}:{2}"
+            .format(self.match.filename, self.match.line_no, self.match.name)
+        )
+
+    def verbose_output(self):
+        return self.textwrapper.fill(
+            "{0}:{1}: '{2}' does not match the required pattern '{3}'."
+            .format(
+                self.match.filename,
+                self.match.line_no,
+                self.match.name,
+                self.pattern
+            )
+        ) + "\n" + str(self.match)
+
+class Typo(Problem): # pylint: disable=too-few-public-methods
+    """
+    A problem that occurs when a word using MBED doesn't appear to be defined as
+    constants nor enum values. Created with NameCheck.check_for_typos()
+
+    Fields:
+    * match: the Match object of the MBED name in question.
+    """
+    def __init__(self, match):
+        self.match = match
+        Problem.__init__(self)
+
+    def quiet_output(self):
+        return (
+            "{0}:{1}:{2}"
+            .format(self.match.filename, self.match.line_no, self.match.name)
+        )
+
+    def verbose_output(self):
+        return self.textwrapper.fill(
+            "{0}:{1}: '{2}' looks like a typo. It was not found in any "
+            "macros or any enums. If this is not a typo, put "
+            "//no-check-names after it."
+            .format(self.match.filename, self.match.line_no, self.match.name)
+        ) + "\n" + str(self.match)
+
+class CodeParser():
+    """
+    Class for retrieving files and parsing the code. This can be used
+    independently of the checks that NameChecker performs, for example for
+    list_internal_identifiers.py.
+    """
+    def __init__(self, log):
+        self.log = log
+        self.check_repo_path()
+
+        # Memo for storing "glob expression": set(filepaths)
+        self.files = {}
+
+        # Globally excluded filenames.
+        # Note that "*" can match directory separators in exclude lists.
+        self.excluded_files = ["*/bn_mul", "*/compat-2.x.h"]
+
+    @staticmethod
+    def check_repo_path():
+        """
+        Check that the current working directory is the project root, and throw
+        an exception if not.
+        """
+        if not all(os.path.isdir(d) for d in ["include", "library", "tests"]):
+            raise Exception("This script must be run from Mbed TLS root")
+
+    def comprehensive_parse(self):
+        """
+        Comprehensive ("default") function to call each parsing function and
+        retrieve various elements of the code, together with the source location.
+
+        Returns a dict of parsed item key to the corresponding List of Matches.
+        """
+        self.log.info("Parsing source code...")
+        self.log.debug(
+            "The following files are excluded from the search: {}"
+            .format(str(self.excluded_files))
+        )
+
+        all_macros = self.parse_macros([
+            "include/mbedtls/*.h",
+            "include/psa/*.h",
+            "library/*.h",
+            "tests/include/test/drivers/*.h",
+            "3rdparty/everest/include/everest/everest.h",
+            "3rdparty/everest/include/everest/x25519.h"
+        ])
+        enum_consts = self.parse_enum_consts([
+            "include/mbedtls/*.h",
+            "library/*.h",
+            "3rdparty/everest/include/everest/everest.h",
+            "3rdparty/everest/include/everest/x25519.h"
+        ])
+        identifiers = self.parse_identifiers([
+            "include/mbedtls/*.h",
+            "include/psa/*.h",
+            "library/*.h",
+            "3rdparty/everest/include/everest/everest.h",
+            "3rdparty/everest/include/everest/x25519.h"
+        ])
+        mbed_words = self.parse_mbed_words([
+            "include/mbedtls/*.h",
+            "include/psa/*.h",
+            "library/*.h",
+            "3rdparty/everest/include/everest/everest.h",
+            "3rdparty/everest/include/everest/x25519.h",
+            "library/*.c",
+            "3rdparty/everest/library/everest.c",
+            "3rdparty/everest/library/x25519.c"
+        ])
+        symbols = self.parse_symbols()
+
+        # Remove identifier macros like mbedtls_printf or mbedtls_calloc
+        identifiers_justname = [x.name for x in identifiers]
+        actual_macros = []
+        for macro in all_macros:
+            if macro.name not in identifiers_justname:
+                actual_macros.append(macro)
+
+        self.log.debug("Found:")
+        # Aligns the counts on the assumption that none exceeds 4 digits
+        self.log.debug("  {:4} Total Macros".format(len(all_macros)))
+        self.log.debug("  {:4} Non-identifier Macros".format(len(actual_macros)))
+        self.log.debug("  {:4} Enum Constants".format(len(enum_consts)))
+        self.log.debug("  {:4} Identifiers".format(len(identifiers)))
+        self.log.debug("  {:4} Exported Symbols".format(len(symbols)))
+        return {
+            "macros": actual_macros,
+            "enum_consts": enum_consts,
+            "identifiers": identifiers,
+            "symbols": symbols,
+            "mbed_words": mbed_words
+        }
+
+    def is_file_excluded(self, path, exclude_wildcards):
+        """Whether the given file path is excluded."""
+        # exclude_wildcards may be None. Also, consider the global exclusions.
+        exclude_wildcards = (exclude_wildcards or []) + self.excluded_files
+        for pattern in exclude_wildcards:
+            if fnmatch.fnmatch(path, pattern):
+                return True
+        return False
+
+    def get_files(self, include_wildcards, exclude_wildcards):
+        """
+        Get all files that match any of the UNIX-style wildcards. While the
+        check_names script is designed only for use on UNIX/macOS (due to nm),
+        this function alone would work fine on Windows even with forward slashes
+        in the wildcard.
+
+        Args:
+        * include_wildcards: a List of shell-style wildcards to match filepaths.
+        * exclude_wildcards: a List of shell-style wildcards to exclude.
+
+        Returns a List of relative filepaths.
+        """
+        accumulator = set()
+
+        for include_wildcard in include_wildcards:
+            accumulator = accumulator.union(glob.iglob(include_wildcard))
+
+        return list(path for path in accumulator
+                    if not self.is_file_excluded(path, exclude_wildcards))
+
+    def parse_macros(self, include, exclude=None):
+        """
+        Parse all macros defined by #define preprocessor directives.
+
+        Args:
+        * include: A List of glob expressions to look for files through.
+        * exclude: A List of glob expressions for excluding files.
+
+        Returns a List of Match objects for the found macros.
+        """
+        macro_regex = re.compile(r"# *define +(?P<macro>\w+)")
+        exclusions = (
+            "asm", "inline", "EMIT", "_CRT_SECURE_NO_DEPRECATE", "MULADDC_"
+        )
+
+        files = self.get_files(include, exclude)
+        self.log.debug("Looking for macros in {} files".format(len(files)))
+
+        macros = []
+        for header_file in files:
+            with open(header_file, "r", encoding="utf-8") as header:
+                for line_no, line in enumerate(header):
+                    for macro in macro_regex.finditer(line):
+                        if macro.group("macro").startswith(exclusions):
+                            continue
+
+                        macros.append(Match(
+                            header_file,
+                            line,
+                            line_no,
+                            macro.span("macro"),
+                            macro.group("macro")))
+
+        return macros
+
+    def parse_mbed_words(self, include, exclude=None):
+        """
+        Parse all words in the file that begin with MBED, in and out of macros,
+        comments, anything.
+
+        Args:
+        * include: A List of glob expressions to look for files through.
+        * exclude: A List of glob expressions for excluding files.
+
+        Returns a List of Match objects for words beginning with MBED.
+        """
+        # Typos of TLS are common, hence the broader check below than MBEDTLS.
+        mbed_regex = re.compile(r"\bMBED.+?_[A-Z0-9_]*")
+        exclusions = re.compile(r"// *no-check-names|#error")
+
+        files = self.get_files(include, exclude)
+        self.log.debug("Looking for MBED words in {} files".format(len(files)))
+
+        mbed_words = []
+        for filename in files:
+            with open(filename, "r", encoding="utf-8") as fp:
+                for line_no, line in enumerate(fp):
+                    if exclusions.search(line):
+                        continue
+
+                    for name in mbed_regex.finditer(line):
+                        mbed_words.append(Match(
+                            filename,
+                            line,
+                            line_no,
+                            name.span(0),
+                            name.group(0)))
+
+        return mbed_words
+
+    def parse_enum_consts(self, include, exclude=None):
+        """
+        Parse all enum value constants that are declared.
+
+        Args:
+        * include: A List of glob expressions to look for files through.
+        * exclude: A List of glob expressions for excluding files.
+
+        Returns a List of Match objects for the findings.
+        """
+        files = self.get_files(include, exclude)
+        self.log.debug("Looking for enum consts in {} files".format(len(files)))
+
+        # Emulate a finite state machine to parse enum declarations.
+        # OUTSIDE_KEYWORD = outside the enum keyword
+        # IN_BRACES = inside enum opening braces
+        # IN_BETWEEN = between enum keyword and opening braces
+        states = enum.Enum("FSM", ["OUTSIDE_KEYWORD", "IN_BRACES", "IN_BETWEEN"])
+        enum_consts = []
+        for header_file in files:
+            state = states.OUTSIDE_KEYWORD
+            with open(header_file, "r", encoding="utf-8") as header:
+                for line_no, line in enumerate(header):
+                    # Match typedefs and brackets only when they are at the
+                    # beginning of the line -- if they are indented, they might
+                    # be sub-structures within structs, etc.
+                    if (state == states.OUTSIDE_KEYWORD and
+                            re.search(r"^(typedef +)?enum +{", line)):
+                        state = states.IN_BRACES
+                    elif (state == states.OUTSIDE_KEYWORD and
+                          re.search(r"^(typedef +)?enum", line)):
+                        state = states.IN_BETWEEN
+                    elif (state == states.IN_BETWEEN and
+                          re.search(r"^{", line)):
+                        state = states.IN_BRACES
+                    elif (state == states.IN_BRACES and
+                          re.search(r"^}", line)):
+                        state = states.OUTSIDE_KEYWORD
+                    elif (state == states.IN_BRACES and
+                          not re.search(r"^ *#", line)):
+                        enum_const = re.search(r"^ *(?P<enum_const>\w+)", line)
+                        if not enum_const:
+                            continue
+
+                        enum_consts.append(Match(
+                            header_file,
+                            line,
+                            line_no,
+                            enum_const.span("enum_const"),
+                            enum_const.group("enum_const")))
+
+        return enum_consts
+
+    def parse_identifiers(self, include, exclude=None):
+        """
+        Parse all lines of a header where a function/enum/struct/union/typedef
+        identifier is declared, based on some regex and heuristics. Highly
+        dependent on formatting style.
+
+        Args:
+        * include: A List of glob expressions to look for files through.
+        * exclude: A List of glob expressions for excluding files.
+
+        Returns a List of Match objects with identifiers.
+        """
+        identifier_regex = re.compile(
+            # Match " something(a" or " *something(a". Functions.
+            # Assumptions:
+            # - function definition from return type to one of its arguments is
+            #   all on one line
+            # - function definition line only contains alphanumeric, asterisk,
+            #   underscore, and open bracket
+            r".* \**(\w+) *\( *\w|"
+            # Match "(*something)(".
+            r".*\( *\* *(\w+) *\) *\(|"
+            # Match names of named data structures.
+            r"(?:typedef +)?(?:struct|union|enum) +(\w+)(?: *{)?$|"
+            # Match names of typedef instances, after closing bracket.
+            r"}? *(\w+)[;[].*"
+        )
+        # The regex below is indented for clarity.
+        exclusion_lines = re.compile(
+            r"^("
+                r"extern +\"C\"|" # pylint: disable=bad-continuation
+                r"(typedef +)?(struct|union|enum)( *{)?$|"
+                r"} *;?$|"
+                r"$|"
+                r"//|"
+                r"#"
+            r")"
+        )
+
+        files = self.get_files(include, exclude)
+        self.log.debug("Looking for identifiers in {} files".format(len(files)))
+
+        identifiers = []
+        for header_file in files:
+            with open(header_file, "r", encoding="utf-8") as header:
+                in_block_comment = False
+                # The previous line variable is used for concatenating lines
+                # when identifiers are formatted and spread across multiple
+                # lines.
+                previous_line = ""
+
+                for line_no, line in enumerate(header):
+                    # Skip parsing this line if a block comment ends on it,
+                    # but don't skip if it has just started -- there is a chance
+                    # it ends on the same line.
+                    if re.search(r"/\*", line):
+                        in_block_comment = not in_block_comment
+                    if re.search(r"\*/", line):
+                        in_block_comment = not in_block_comment
+                        continue
+
+                    if in_block_comment:
+                        previous_line = ""
+                        continue
+
+                    if exclusion_lines.search(line):
+                        previous_line = ""
+                        continue
+
+                    # If the line contains only space-separated alphanumeric
+                    # characters (or underscore, asterisk, or, open bracket),
+                    # and nothing else, high chance it's a declaration that
+                    # continues on the next line
+                    if re.search(r"^([\w\*\(]+\s+)+$", line):
+                        previous_line += line
+                        continue
+
+                    # If previous line seemed to start an unfinished declaration
+                    # (as above), concat and treat them as one.
+                    if previous_line:
+                        line = previous_line.strip() + " " + line.strip() + "\n"
+                        previous_line = ""
+
+                    # Skip parsing if line has a space in front = heuristic to
+                    # skip function argument lines (highly subject to formatting
+                    # changes)
+                    if line[0] == " ":
+                        continue
+
+                    identifier = identifier_regex.search(line)
+
+                    if not identifier:
+                        continue
+
+                    # Find the group that matched, and append it
+                    for group in identifier.groups():
+                        if not group:
+                            continue
+
+                        identifiers.append(Match(
+                            header_file,
+                            line,
+                            line_no,
+                            identifier.span(),
+                            group))
+
+        return identifiers
+
+    def parse_symbols(self):
+        """
+        Compile the Mbed TLS libraries, and parse the TLS, Crypto, and x509
+        object files using nm to retrieve the list of referenced symbols.
+        Exceptions thrown here are rethrown because they would be critical
+        errors that void several tests, and thus needs to halt the program. This
+        is explicitly done for clarity.
+
+        Returns a List of unique symbols defined and used in the libraries.
+        """
+        self.log.info("Compiling...")
+        symbols = []
+
+        # Back up the config and atomically compile with the full configratuion.
+        shutil.copy(
+            "include/mbedtls/mbedtls_config.h",
+            "include/mbedtls/mbedtls_config.h.bak"
+        )
+        try:
+            # Use check=True in all subprocess calls so that failures are raised
+            # as exceptions and logged.
+            subprocess.run(
+                ["python3", "scripts/config.py", "full"],
+                universal_newlines=True,
+                check=True
+            )
+            my_environment = os.environ.copy()
+            my_environment["CFLAGS"] = "-fno-asynchronous-unwind-tables"
+            # Run make clean separately to lib to prevent unwanted behavior when
+            # make is invoked with parallelism.
+            subprocess.run(
+                ["make", "clean"],
+                universal_newlines=True,
+                check=True
+            )
+            subprocess.run(
+                ["make", "lib"],
+                env=my_environment,
+                universal_newlines=True,
+                stdout=subprocess.PIPE,
+                stderr=subprocess.STDOUT,
+                check=True
+            )
+
+            # Perform object file analysis using nm
+            symbols = self.parse_symbols_from_nm([
+                "library/libmbedcrypto.a",
+                "library/libmbedtls.a",
+                "library/libmbedx509.a"
+            ])
+
+            subprocess.run(
+                ["make", "clean"],
+                universal_newlines=True,
+                check=True
+            )
+        except subprocess.CalledProcessError as error:
+            self.log.debug(error.output)
+            raise error
+        finally:
+            # Put back the original config regardless of there being errors.
+            # Works also for keyboard interrupts.
+            shutil.move(
+                "include/mbedtls/mbedtls_config.h.bak",
+                "include/mbedtls/mbedtls_config.h"
+            )
+
+        return symbols
+
+    def parse_symbols_from_nm(self, object_files):
+        """
+        Run nm to retrieve the list of referenced symbols in each object file.
+        Does not return the position data since it is of no use.
+
+        Args:
+        * object_files: a List of compiled object filepaths to search through.
+
+        Returns a List of unique symbols defined and used in any of the object
+        files.
+        """
+        nm_undefined_regex = re.compile(r"^\S+: +U |^$|^\S+:$")
+        nm_valid_regex = re.compile(r"^\S+( [0-9A-Fa-f]+)* . _*(?P<symbol>\w+)")
+        exclusions = ("FStar", "Hacl")
+
+        symbols = []
+
+        # Gather all outputs of nm
+        nm_output = ""
+        for lib in object_files:
+            nm_output += subprocess.run(
+                ["nm", "-og", lib],
+                universal_newlines=True,
+                stdout=subprocess.PIPE,
+                stderr=subprocess.STDOUT,
+                check=True
+            ).stdout
+
+        for line in nm_output.splitlines():
+            if not nm_undefined_regex.search(line):
+                symbol = nm_valid_regex.search(line)
+                if (symbol and not symbol.group("symbol").startswith(exclusions)):
+                    symbols.append(symbol.group("symbol"))
+                else:
+                    self.log.error(line)
+
+        return symbols
+
+class NameChecker():
+    """
+    Representation of the core name checking operation performed by this script.
+    """
+    def __init__(self, parse_result, log):
+        self.parse_result = parse_result
+        self.log = log
+
+    def perform_checks(self, quiet=False):
+        """
+        A comprehensive checker that performs each check in order, and outputs
+        a final verdict.
+
+        Args:
+        * quiet: whether to hide detailed problem explanation.
+        """
+        self.log.info("=============")
+        Problem.quiet = quiet
+        problems = 0
+        problems += self.check_symbols_declared_in_header()
+
+        pattern_checks = [
+            ("macros", MACRO_PATTERN),
+            ("enum_consts", CONSTANTS_PATTERN),
+            ("identifiers", IDENTIFIER_PATTERN)
+        ]
+        for group, check_pattern in pattern_checks:
+            problems += self.check_match_pattern(group, check_pattern)
+
+        problems += self.check_for_typos()
+
+        self.log.info("=============")
+        if problems > 0:
+            self.log.info("FAIL: {0} problem(s) to fix".format(str(problems)))
+            if quiet:
+                self.log.info("Remove --quiet to see explanations.")
+            else:
+                self.log.info("Use --quiet for minimal output.")
+            return 1
+        else:
+            self.log.info("PASS")
+            return 0
+
+    def check_symbols_declared_in_header(self):
+        """
+        Perform a check that all detected symbols in the library object files
+        are properly declared in headers.
+        Assumes parse_names_in_source() was called before this.
+
+        Returns the number of problems that need fixing.
+        """
+        problems = []
+
+        for symbol in self.parse_result["symbols"]:
+            found_symbol_declared = False
+            for identifier_match in self.parse_result["identifiers"]:
+                if symbol == identifier_match.name:
+                    found_symbol_declared = True
+                    break
+
+            if not found_symbol_declared:
+                problems.append(SymbolNotInHeader(symbol))
+
+        self.output_check_result("All symbols in header", problems)
+        return len(problems)
+
+    def check_match_pattern(self, group_to_check, check_pattern):
+        """
+        Perform a check that all items of a group conform to a regex pattern.
+        Assumes parse_names_in_source() was called before this.
+
+        Args:
+        * group_to_check: string key to index into self.parse_result.
+        * check_pattern: the regex to check against.
+
+        Returns the number of problems that need fixing.
+        """
+        problems = []
+
+        for item_match in self.parse_result[group_to_check]:
+            if not re.search(check_pattern, item_match.name):
+                problems.append(PatternMismatch(check_pattern, item_match))
+            # Double underscore should not be used for names
+            if re.search(r".*__.*", item_match.name):
+                problems.append(
+                    PatternMismatch("no double underscore allowed", item_match))
+
+        self.output_check_result(
+            "Naming patterns of {}".format(group_to_check),
+            problems)
+        return len(problems)
+
+    def check_for_typos(self):
+        """
+        Perform a check that all words in the soure code beginning with MBED are
+        either defined as macros, or as enum constants.
+        Assumes parse_names_in_source() was called before this.
+
+        Returns the number of problems that need fixing.
+        """
+        problems = []
+
+        # Set comprehension, equivalent to a list comprehension wrapped by set()
+        all_caps_names = {
+            match.name
+            for match
+            in self.parse_result["macros"] + self.parse_result["enum_consts"]}
+        typo_exclusion = re.compile(r"XXX|__|_$|^MBEDTLS_.*CONFIG_FILE$")
+
+        for name_match in self.parse_result["mbed_words"]:
+            found = name_match.name in all_caps_names
+
+            # Since MBEDTLS_PSA_ACCEL_XXX defines are defined by the
+            # PSA driver, they will not exist as macros. However, they
+            # should still be checked for typos using the equivalent
+            # BUILTINs that exist.
+            if "MBEDTLS_PSA_ACCEL_" in name_match.name:
+                found = name_match.name.replace(
+                    "MBEDTLS_PSA_ACCEL_",
+                    "MBEDTLS_PSA_BUILTIN_") in all_caps_names
+
+            if not found and not typo_exclusion.search(name_match.name):
+                problems.append(Typo(name_match))
+
+        self.output_check_result("Likely typos", problems)
+        return len(problems)
+
+    def output_check_result(self, name, problems):
+        """
+        Write out the PASS/FAIL status of a performed check depending on whether
+        there were problems.
+
+        Args:
+        * name: the name of the test
+        * problems: a List of encountered Problems
+        """
+        if problems:
+            self.log.info("{}: FAIL\n".format(name))
+            for problem in problems:
+                self.log.warning(str(problem))
+        else:
+            self.log.info("{}: PASS".format(name))
+
+def main():
+    """
+    Perform argument parsing, and create an instance of CodeParser and
+    NameChecker to begin the core operation.
+    """
+    parser = argparse.ArgumentParser(
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+        description=(
+            "This script confirms that the naming of all symbols and identifiers "
+            "in Mbed TLS are consistent with the house style and are also "
+            "self-consistent.\n\n"
+            "Expected to be run from the MbedTLS root directory.")
+    )
+    parser.add_argument(
+        "-v", "--verbose",
+        action="store_true",
+        help="show parse results"
+    )
+    parser.add_argument(
+        "-q", "--quiet",
+        action="store_true",
+        help="hide unnecessary text, explanations, and highlighs"
+    )
+
+    args = parser.parse_args()
+
+    # Configure the global logger, which is then passed to the classes below
+    log = logging.getLogger()
+    log.setLevel(logging.DEBUG if args.verbose else logging.INFO)
+    log.addHandler(logging.StreamHandler())
+
+    try:
+        code_parser = CodeParser(log)
+        parse_result = code_parser.comprehensive_parse()
+    except Exception: # pylint: disable=broad-except
+        traceback.print_exc()
+        sys.exit(2)
+
+    name_checker = NameChecker(parse_result, log)
+    return_code = name_checker.perform_checks(quiet=args.quiet)
+
+    sys.exit(return_code)
+
+if __name__ == "__main__":
+    main()
diff --git a/tests/scripts/generate_psa_tests.py b/tests/scripts/generate_psa_tests.py
index c788ce6..39fb210 100755
--- a/tests/scripts/generate_psa_tests.py
+++ b/tests/scripts/generate_psa_tests.py
@@ -155,8 +155,30 @@
     tc.set_arguments([key_type] + list(args))
     return tc
 
+def test_case_for_key_type_invalid_argument(
+        verb: str, key_type: str, bits: int,
+        dependencies: List[str],
+        *args: str,
+        param_descr: str = ''
+) -> test_case.TestCase:
+    """Return one test case exercising a key creation method
+    for an invalid argument when key is public.
+    """
+    hack_dependencies_not_implemented(dependencies)
+    tc = test_case.TestCase()
+    short_key_type = re.sub(r'PSA_(KEY_TYPE|ECC_FAMILY)_', r'', key_type)
+    adverb = 'not' if dependencies else 'never'
+    if param_descr:
+        adverb = param_descr + ' ' + adverb
+    tc.set_description('PSA {} {} {}-bit invalid argument'
+                       .format(verb, short_key_type, bits))
+    tc.set_function(verb + '_invalid_argument')
+    tc.set_dependencies(dependencies)
+    tc.set_arguments([key_type] + list(args))
+    return tc
+
 class NotSupported:
-    """Generate test cases for when something is not supported."""
+    """Generate test cases for when something is not supported or argument is inavlid."""
 
     def __init__(self, info: Information) -> None:
         self.constructors = info.constructors
@@ -171,11 +193,13 @@
             param: Optional[int] = None,
             param_descr: str = '',
     ) -> Iterator[test_case.TestCase]:
-        """Return test cases exercising key creation when the given type is unsupported.
+        """Return test cases exercising key creation when the given type is unsupported
+        or argument is invalid.
 
         If param is present and not None, emit test cases conditioned on this
         parameter not being supported. If it is absent or None, emit test cases
-        conditioned on the base type not being supported.
+        conditioned on the base type not being supported. If key is public emit test
+        case for invalid argument.
         """
         if kt.name in self.ALWAYS_SUPPORTED:
             # Don't generate test cases for key types that are always supported.
@@ -203,12 +227,20 @@
                 # supported or not depending on implementation capabilities,
                 # only generate the test case once.
                 continue
-            yield test_case_for_key_type_not_supported(
-                'generate', kt.expression, bits,
-                finish_family_dependencies(generate_dependencies, bits),
-                str(bits),
-                param_descr=param_descr,
-            )
+            if kt.name.endswith('_PUBLIC_KEY'):
+                yield test_case_for_key_type_invalid_argument(
+                    'generate', kt.expression, bits,
+                    finish_family_dependencies(generate_dependencies, bits),
+                    str(bits),
+                    param_descr=param_descr,
+                )
+            else:
+                yield test_case_for_key_type_not_supported(
+                    'generate', kt.expression, bits,
+                    finish_family_dependencies(generate_dependencies, bits),
+                    str(bits),
+                    param_descr=param_descr,
+                )
             # To be added: derive
 
     ECC_KEY_TYPES = ('PSA_KEY_TYPE_ECC_KEY_PAIR',
@@ -229,7 +261,6 @@
                 yield from self.test_cases_for_key_type_not_supported(
                     kt, 0, param_descr='curve')
 
-
 class StorageKey(psa_storage.Key):
     """Representation of a key for storage format testing."""
 
@@ -668,6 +699,10 @@
     parser = argparse.ArgumentParser(description=__doc__)
     parser.add_argument('--list', action='store_true',
                         help='List available targets and exit')
+    parser.add_argument('--list-for-cmake', action='store_true',
+                        help='Print \';\'-separated list of available targets and exit')
+    parser.add_argument('--directory', metavar='DIR',
+                        help='Output directory (default: tests/suites)')
     parser.add_argument('targets', nargs='*', metavar='TARGET',
                         help='Target file to generate (default: all; "-": none)')
     options = parser.parse_args(args)
@@ -677,6 +712,11 @@
         for name in sorted(generator.TARGETS):
             print(generator.filename_for(name))
         return
+    # List in a cmake list format (i.e. ';'-separated)
+    if options.list_for_cmake:
+        print(';'.join(generator.filename_for(name)
+                       for name in sorted(generator.TARGETS)), end='')
+        return
     if options.targets:
         # Allow "-" as a special case so you can run
         # ``generate_psa_tests.py - $targets`` and it works uniformly whether
diff --git a/tests/scripts/generate_test_code.py b/tests/scripts/generate_test_code.py
index 7382fb6..f5750aa 100755
--- a/tests/scripts/generate_test_code.py
+++ b/tests/scripts/generate_test_code.py
@@ -106,10 +106,6 @@
 Platform file contains platform specific setup code and test case
 dispatch code. For example, host_test.function reads test data
 file from host's file system and dispatches tests.
-In case of on-target target_test.function tests are not dispatched
-on target. Target code is kept minimum and only test functions are
-dispatched. Test case dispatch is done on the host using tools like
-Greentea.
 
 Template file:
 ---------
diff --git a/tests/scripts/list-enum-consts.pl b/tests/scripts/list-enum-consts.pl
deleted file mode 100755
index 6d93693..0000000
--- a/tests/scripts/list-enum-consts.pl
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env perl
-#
-# 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.
-
-use warnings;
-use strict;
-
-use utf8;
-use open qw(:std utf8);
-
--d 'include/mbedtls' or die "$0: must be run from root\n";
-
-@ARGV = grep { ! /compat-2\.x\.h/ } <include/mbedtls/*.h>;
-push @ARGV, "3rdparty/everest/include/everest/everest.h";
-push @ARGV, "3rdparty/everest/include/everest/x25519.h";
-push @ARGV, glob("library/*.h");
-
-my @consts;
-my $state = 'out';
-while (<>)
-{
-    if( $state eq 'out' and /^(typedef )?enum \{/ ) {
-        $state = 'in';
-    } elsif( $state eq 'out' and /^(typedef )?enum/ ) {
-        $state = 'start';
-    } elsif( $state eq 'start' and /{/ ) {
-        $state = 'in';
-    } elsif( $state eq 'in' and /}/ ) {
-        $state = 'out';
-    } elsif( $state eq 'in' and not /^#/) {
-        s/=.*//; s!/\*.*!!; s/,.*//; s/\s+//g; chomp;
-        push @consts, $_ if $_;
-    }
-}
-
-open my $fh, '>', 'enum-consts' or die;
-print $fh "$_\n" for sort @consts;
-close $fh or die;
-
-printf "%8d enum-consts\n", scalar @consts;
diff --git a/tests/scripts/list-identifiers.sh b/tests/scripts/list-identifiers.sh
index 9698fc8..9b93080 100755
--- a/tests/scripts/list-identifiers.sh
+++ b/tests/scripts/list-identifiers.sh
@@ -1,8 +1,11 @@
 #!/bin/bash
 #
 # Create a file named identifiers containing identifiers from internal header
-# files or all header files, based on --internal flag.
+# files, based on the --internal flag.
 # Outputs the line count of the file to stdout.
+# A very thin wrapper around list_internal_identifiers.py for backwards
+# compatibility.
+# Must be run from Mbed TLS root.
 #
 # Usage: list-identifiers.sh [ -i | --internal ]
 #
@@ -24,7 +27,7 @@
 set -eu
 
 if [ -d include/mbedtls ]; then :; else
-    echo "$0: must be run from root" >&2
+    echo "$0: Must be run from Mbed TLS root" >&2
     exit 1
 fi
 
@@ -47,32 +50,17 @@
 
 if [ $INTERNAL ]
 then
-    HEADERS=$( ls include/mbedtls/*_internal.h library/*.h | egrep -v 'compat-2\.x\.h' )
+    tests/scripts/list_internal_identifiers.py
+    wc -l identifiers
 else
-    HEADERS=$( ls include/mbedtls/*.h include/psa/*.h library/*.h | egrep -v 'compat-2\.x\.h' )
-    HEADERS="$HEADERS 3rdparty/everest/include/everest/everest.h 3rdparty/everest/include/everest/x25519.h"
+    cat <<EOF
+Sorry, this script has to be called with --internal.
+
+This script exists solely for backwards compatibility with the previous
+iteration of list-identifiers.sh, of which only the --internal option remains in
+use. It is a thin wrapper around list_internal_identifiers.py.
+
+check-names.sh, which used to depend on this script, has been replaced with
+check_names.py and is now self-complete.
+EOF
 fi
-
-rm -f identifiers
-
-grep '^[^ /#{]' $HEADERS | \
-    sed -e 's/^[^:]*://' | \
-    egrep -v '^(extern "C"|(typedef )?(struct|union|enum)( {)?$|};?$)' \
-    > _decls
-
-if true; then
-sed -n -e 's/.* \**\([a-zA-Z_][a-zA-Z0-9_]*\)(.*/\1/p' \
-       -e 's/.*(\*\(.*\))(.*/\1/p' _decls
-grep -v '(' _decls | sed -e 's/\([a-zA-Z0-9_]*\)[;[].*/\1/' -e 's/.* \**//'
-fi > _identifiers
-
-if [ $( wc -l < _identifiers ) -eq $( wc -l < _decls ) ]; then
-    rm _decls
-    egrep -v '^(u?int(16|32|64)_t)$' _identifiers | sort > identifiers
-    rm _identifiers
-else
-    echo "$0: oops, lost some identifiers" 2>&1
-    exit 1
-fi
-
-wc -l identifiers
diff --git a/tests/scripts/list-macros.sh b/tests/scripts/list-macros.sh
deleted file mode 100755
index 2e62359..0000000
--- a/tests/scripts/list-macros.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/sh
-#
-# 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.
-
-set -eu
-
-if [ -d include/mbedtls ]; then :; else
-    echo "$0: must be run from root" >&2
-    exit 1
-fi
-
-HEADERS=$( ls include/mbedtls/*.h include/psa/*.h tests/include/test/drivers/*.h | egrep -v 'compat-2\.x\.h' )
-HEADERS="$HEADERS library/*.h"
-HEADERS="$HEADERS 3rdparty/everest/include/everest/everest.h 3rdparty/everest/include/everest/x25519.h"
-
-sed -n -e 's/.*#define \([a-zA-Z0-9_]*\).*/\1/p' $HEADERS \
-    | egrep -v '^(asm|inline|EMIT|_CRT_SECURE_NO_DEPRECATE)$|^MULADDC_' \
-    | sort -u > macros
-
-# For include/mbedtls/config_psa.h need to ignore the MBEDTLS_xxx define
-# in that file since they may not be defined in include/psa/crypto_config.h
-# This line renames the potentially missing defines to ones that should
-# be present.
-sed -ne 's/^MBEDTLS_PSA_BUILTIN_/MBEDTLS_PSA_ACCEL_/p' <macros >>macros
-
-wc -l macros
diff --git a/tests/scripts/list-symbols.sh b/tests/scripts/list-symbols.sh
deleted file mode 100755
index 4a5d035..0000000
--- a/tests/scripts/list-symbols.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/sh
-#
-# 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.
-
-set -eu
-
-if [ -d include/mbedtls ]; then :; else
-    echo "$0: must be run from root" >&2
-    exit 1
-fi
-
-if grep -i cmake Makefile >/dev/null; then
-    echo "$0: not compatible with cmake" >&2
-    exit 1
-fi
-
-cp include/mbedtls/mbedtls_config.h include/mbedtls/mbedtls_config.h.bak
-scripts/config.py full
-make clean
-make_ret=
-CFLAGS=-fno-asynchronous-unwind-tables make lib \
-      >list-symbols.make.log 2>&1 ||
-  {
-    make_ret=$?
-    echo "Build failure: CFLAGS=-fno-asynchronous-unwind-tables make lib"
-    cat list-symbols.make.log >&2
-  }
-rm list-symbols.make.log
-mv include/mbedtls/mbedtls_config.h.bak include/mbedtls/mbedtls_config.h
-if [ -n "$make_ret" ]; then
-    exit "$make_ret"
-fi
-
-if uname | grep -F Darwin >/dev/null; then
-    nm -gUj library/libmbed*.a 2>/dev/null | sed -n -e 's/^_//p' | grep -v -e ^FStar -e ^Hacl
-elif uname | grep -F Linux >/dev/null; then
-    nm -og library/libmbed*.a | grep -v '^[^ ]*: *U \|^$\|^[^ ]*:$' | sed 's/^[^ ]* . //' | grep -v -e ^FStar -e ^Hacl
-fi | sort > exported-symbols
-make clean
-
-wc -l exported-symbols
diff --git a/tests/scripts/list_internal_identifiers.py b/tests/scripts/list_internal_identifiers.py
new file mode 100755
index 0000000..779a16f
--- /dev/null
+++ b/tests/scripts/list_internal_identifiers.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python3
+#
+# 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.
+
+"""
+This script generates a file called identifiers that contains all Mbed TLS
+identifiers found on internal headers. This is the equivalent of what was
+previously `list-identifiers.sh --internal`, and is useful for generating an
+exclusion file list for ABI/API checking, since we do not promise compatibility
+for them.
+
+It uses the CodeParser class from check_names.py to perform the parsing.
+
+The script returns 0 on success, 1 if there is a script error.
+Must be run from Mbed TLS root.
+"""
+
+import argparse
+import logging
+from check_names import CodeParser
+
+def main():
+    parser = argparse.ArgumentParser(
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+        description=(
+            "This script writes a list of parsed identifiers in internal "
+            "headers to \"identifiers\". This is useful for generating a list "
+            "of names to exclude from API/ABI compatibility checking. "))
+
+    parser.parse_args()
+
+    name_check = CodeParser(logging.getLogger())
+    result = name_check.parse_identifiers([
+        "include/mbedtls/*_internal.h",
+        "library/*.h"
+    ])
+    result.sort(key=lambda x: x.name)
+
+    identifiers = ["{}\n".format(match.name) for match in result]
+    with open("identifiers", "w", encoding="utf-8") as f:
+        f.writelines(identifiers)
+
+if __name__ == "__main__":
+    main()
diff --git a/tests/scripts/mbedtls_test.py b/tests/scripts/mbedtls_test.py
deleted file mode 100755
index 64f12bb..0000000
--- a/tests/scripts/mbedtls_test.py
+++ /dev/null
@@ -1,382 +0,0 @@
-#!/usr/bin/env python3
-
-# Greentea host test script for Mbed TLS on-target test suite testing.
-#
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-"""
-Mbed TLS on-target test suite tests are implemented as Greentea
-tests. Greentea tests are implemented in two parts: target test and
-host test. Target test is a C application that is built for the
-target platform and executes on the target. Host test is a Python
-class derived from mbed_host_tests.BaseHostTest. Target communicates
-with the host over serial for the test data and sends back the result.
-
-Python tool mbedgt (Greentea) is responsible for flashing the test
-binary on to the target and dynamically loading this host test module.
-
-Greentea documentation can be found here:
-https://github.com/ARMmbed/greentea
-"""
-
-
-import re
-import os
-import binascii
-
-from mbed_host_tests import BaseHostTest, event_callback # type: ignore # pylint: disable=import-error
-
-
-class TestDataParserError(Exception):
-    """Indicates error in test data, read from .data file."""
-    pass
-
-
-class TestDataParser:
-    """
-    Parses test name, dependencies, test function name and test parameters
-    from the data file.
-    """
-
-    def __init__(self):
-        """
-        Constructor
-        """
-        self.tests = []
-
-    def parse(self, data_file):
-        """
-        Data file parser.
-
-        :param data_file: Data file path
-        """
-        with open(data_file, 'r') as data_f:
-            self.__parse(data_f)
-
-    @staticmethod
-    def __escaped_split(inp_str, split_char):
-        """
-        Splits inp_str on split_char except when escaped.
-
-        :param inp_str: String to split
-        :param split_char: Split character
-        :return: List of splits
-        """
-        split_colon_fn = lambda x: re.sub(r'\\' + split_char, split_char, x)
-        if len(split_char) > 1:
-            raise ValueError('Expected split character. Found string!')
-        out = list(map(split_colon_fn, re.split(r'(?<!\\)' + split_char, inp_str)))
-        out = [x for x in out if x]
-        return out
-
-    def __parse(self, data_f):
-        """
-        Parses data file using supplied file object.
-
-        :param data_f: Data file object
-        :return:
-        """
-        for line in data_f:
-            line = line.strip()
-            if not line:
-                continue
-            # Read test name
-            name = line
-
-            # Check dependencies
-            dependencies = []
-            line = next(data_f).strip()
-            match = re.search('depends_on:(.*)', line)
-            if match:
-                dependencies = [int(x) for x in match.group(1).split(':')]
-                line = next(data_f).strip()
-
-            # Read test vectors
-            line = line.replace('\\n', '\n')
-            parts = self.__escaped_split(line, ':')
-            function_name = int(parts[0])
-            args = parts[1:]
-            args_count = len(args)
-            if args_count % 2 != 0:
-                err_str_fmt = "Number of test arguments({}) should be even: {}"
-                raise TestDataParserError(err_str_fmt.format(args_count, line))
-            grouped_args = [(args[i * 2], args[(i * 2) + 1])
-                            for i in range(int(len(args)/2))]
-            self.tests.append((name, function_name, dependencies,
-                               grouped_args))
-
-    def get_test_data(self):
-        """
-        Returns test data.
-        """
-        return self.tests
-
-
-class MbedTlsTest(BaseHostTest):
-    """
-    Host test for Mbed TLS unit tests. This script is loaded at
-    run time by Greentea for executing Mbed TLS test suites. Each
-    communication from the target is received in this object as
-    an event, which is then handled by the event handler method
-    decorated by the associated event. Ex: @event_callback('GO').
-
-    Target test sends requests for dispatching next test. It reads
-    tests from the intermediate data file and sends test function
-    identifier, dependency identifiers, expression identifiers and
-    the test data in binary form. Target test checks dependencies
-    , evaluate integer constant expressions and dispatches the test
-    function with received test parameters. After test function is
-    finished, target sends the result. This class handles the result
-    event and prints verdict in the form that Greentea understands.
-
-    """
-    # status/error codes from suites/helpers.function
-    DEPENDENCY_SUPPORTED = 0
-    KEY_VALUE_MAPPING_FOUND = DEPENDENCY_SUPPORTED
-    DISPATCH_TEST_SUCCESS = DEPENDENCY_SUPPORTED
-
-    KEY_VALUE_MAPPING_NOT_FOUND = -1    # Expression Id not found.
-    DEPENDENCY_NOT_SUPPORTED = -2       # Dependency not supported.
-    DISPATCH_TEST_FN_NOT_FOUND = -3     # Test function not found.
-    DISPATCH_INVALID_TEST_DATA = -4     # Invalid parameter type.
-    DISPATCH_UNSUPPORTED_SUITE = -5     # Test suite not supported/enabled.
-
-    def __init__(self):
-        """
-        Constructor initialises test index to 0.
-        """
-        super(MbedTlsTest, self).__init__()
-        self.tests = []
-        self.test_index = -1
-        self.dep_index = 0
-        self.suite_passed = True
-        self.error_str = dict()
-        self.error_str[self.DEPENDENCY_SUPPORTED] = \
-            'DEPENDENCY_SUPPORTED'
-        self.error_str[self.KEY_VALUE_MAPPING_NOT_FOUND] = \
-            'KEY_VALUE_MAPPING_NOT_FOUND'
-        self.error_str[self.DEPENDENCY_NOT_SUPPORTED] = \
-            'DEPENDENCY_NOT_SUPPORTED'
-        self.error_str[self.DISPATCH_TEST_FN_NOT_FOUND] = \
-            'DISPATCH_TEST_FN_NOT_FOUND'
-        self.error_str[self.DISPATCH_INVALID_TEST_DATA] = \
-            'DISPATCH_INVALID_TEST_DATA'
-        self.error_str[self.DISPATCH_UNSUPPORTED_SUITE] = \
-            'DISPATCH_UNSUPPORTED_SUITE'
-
-    def setup(self):
-        """
-        Setup hook implementation. Reads test suite data file and parses out
-        tests.
-        """
-        binary_path = self.get_config_item('image_path')
-        script_dir = os.path.split(os.path.abspath(__file__))[0]
-        suite_name = os.path.splitext(os.path.basename(binary_path))[0]
-        data_file = ".".join((suite_name, 'datax'))
-        data_file = os.path.join(script_dir, '..', 'mbedtls',
-                                 suite_name, data_file)
-        if os.path.exists(data_file):
-            self.log("Running tests from %s" % data_file)
-            parser = TestDataParser()
-            parser.parse(data_file)
-            self.tests = parser.get_test_data()
-            self.print_test_info()
-        else:
-            self.log("Data file not found: %s" % data_file)
-            self.notify_complete(False)
-
-    def print_test_info(self):
-        """
-        Prints test summary read by Greentea to detect test cases.
-        """
-        self.log('{{__testcase_count;%d}}' % len(self.tests))
-        for name, _, _, _ in self.tests:
-            self.log('{{__testcase_name;%s}}' % name)
-
-    @staticmethod
-    def align_32bit(data_bytes):
-        """
-        4 byte aligns input byte array.
-
-        :return:
-        """
-        data_bytes += bytearray((4 - (len(data_bytes))) % 4)
-
-    @staticmethod
-    def hex_str_bytes(hex_str):
-        """
-        Converts Hex string representation to byte array
-
-        :param hex_str: Hex in string format.
-        :return: Output Byte array
-        """
-        if hex_str[0] != '"' or hex_str[len(hex_str) - 1] != '"':
-            raise TestDataParserError("HEX test parameter missing '\"':"
-                                      " %s" % hex_str)
-        hex_str = hex_str.strip('"')
-        if len(hex_str) % 2 != 0:
-            raise TestDataParserError("HEX parameter len should be mod of "
-                                      "2: %s" % hex_str)
-
-        data_bytes = binascii.unhexlify(hex_str)
-        return data_bytes
-
-    @staticmethod
-    def int32_to_big_endian_bytes(i):
-        """
-        Coverts i to byte array in big endian format.
-
-        :param i: Input integer
-        :return: Output bytes array in big endian or network order
-        """
-        data_bytes = bytearray([((i >> x) & 0xff) for x in [24, 16, 8, 0]])
-        return data_bytes
-
-    def test_vector_to_bytes(self, function_id, dependencies, parameters):
-        """
-        Converts test vector into a byte array that can be sent to the target.
-
-        :param function_id: Test Function Identifier
-        :param dependencies: Dependency list
-        :param parameters: Test function input parameters
-        :return: Byte array and its length
-        """
-        data_bytes = bytearray([len(dependencies)])
-        if dependencies:
-            data_bytes += bytearray(dependencies)
-        data_bytes += bytearray([function_id, len(parameters)])
-        for typ, param in parameters:
-            if typ in ('int', 'exp'):
-                i = int(param, 0)
-                data_bytes += b'I' if typ == 'int' else b'E'
-                self.align_32bit(data_bytes)
-                data_bytes += self.int32_to_big_endian_bytes(i)
-            elif typ == 'char*':
-                param = param.strip('"')
-                i = len(param) + 1  # + 1 for null termination
-                data_bytes += b'S'
-                self.align_32bit(data_bytes)
-                data_bytes += self.int32_to_big_endian_bytes(i)
-                data_bytes += bytearray(param, encoding='ascii')
-                data_bytes += b'\0'   # Null terminate
-            elif typ == 'hex':
-                binary_data = self.hex_str_bytes(param)
-                data_bytes += b'H'
-                self.align_32bit(data_bytes)
-                i = len(binary_data)
-                data_bytes += self.int32_to_big_endian_bytes(i)
-                data_bytes += binary_data
-        length = self.int32_to_big_endian_bytes(len(data_bytes))
-        return data_bytes, length
-
-    def run_next_test(self):
-        """
-        Fetch next test information and execute the test.
-
-        """
-        self.test_index += 1
-        self.dep_index = 0
-        if self.test_index < len(self.tests):
-            name, function_id, dependencies, args = self.tests[self.test_index]
-            self.run_test(name, function_id, dependencies, args)
-        else:
-            self.notify_complete(self.suite_passed)
-
-    def run_test(self, name, function_id, dependencies, args):
-        """
-        Execute the test on target by sending next test information.
-
-        :param name: Test name
-        :param function_id: function identifier
-        :param dependencies: Dependencies list
-        :param args: test parameters
-        :return:
-        """
-        self.log("Running: %s" % name)
-
-        param_bytes, length = self.test_vector_to_bytes(function_id,
-                                                        dependencies, args)
-        self.send_kv(
-            ''.join('{:02x}'.format(x) for x in length),
-            ''.join('{:02x}'.format(x) for x in param_bytes)
-        )
-
-    @staticmethod
-    def get_result(value):
-        """
-        Converts result from string type to integer
-        :param value: Result code in string
-        :return: Integer result code. Value is from the test status
-                 constants defined under the MbedTlsTest class.
-        """
-        try:
-            return int(value)
-        except ValueError:
-            ValueError("Result should return error number. "
-                       "Instead received %s" % value)
-
-    @event_callback('GO')
-    def on_go(self, _key, _value, _timestamp):
-        """
-        Sent by the target to start first test.
-
-        :param _key: Event key
-        :param _value: Value. ignored
-        :param _timestamp: Timestamp ignored.
-        :return:
-        """
-        self.run_next_test()
-
-    @event_callback("R")
-    def on_result(self, _key, value, _timestamp):
-        """
-        Handle result. Prints test start, finish required by Greentea
-        to detect test execution.
-
-        :param _key: Event key
-        :param value: Value. ignored
-        :param _timestamp: Timestamp ignored.
-        :return:
-        """
-        int_val = self.get_result(value)
-        name, _, _, _ = self.tests[self.test_index]
-        self.log('{{__testcase_start;%s}}' % name)
-        self.log('{{__testcase_finish;%s;%d;%d}}' % (name, int_val == 0,
-                                                     int_val != 0))
-        if int_val != 0:
-            self.suite_passed = False
-        self.run_next_test()
-
-    @event_callback("F")
-    def on_failure(self, _key, value, _timestamp):
-        """
-        Handles test execution failure. That means dependency not supported or
-        Test function not supported. Hence marking test as skipped.
-
-        :param _key: Event key
-        :param value: Value. ignored
-        :param _timestamp: Timestamp ignored.
-        :return:
-        """
-        int_val = self.get_result(value)
-        if int_val in self.error_str:
-            err = self.error_str[int_val]
-        else:
-            err = 'Unknown error'
-        # For skip status, do not write {{__testcase_finish;...}}
-        self.log("Error: %s" % err)
-        self.run_next_test()
diff --git a/tests/scripts/translate_ciphers.py b/tests/scripts/translate_ciphers.py
new file mode 100755
index 0000000..d5f847f
--- /dev/null
+++ b/tests/scripts/translate_ciphers.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python3
+
+# translate_ciphers.py
+#
+# 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.
+
+"""
+Translate ciphersuite names in Mbed TLS format to OpenSSL and GNUTLS
+standards.
+
+To test the translation functions run:
+python3 -m unittest translate_cipher.py
+"""
+
+import re
+import argparse
+import unittest
+
+class TestTranslateCiphers(unittest.TestCase):
+    """
+    Ensure translate_ciphers.py translates and formats ciphersuite names
+    correctly
+    """
+    def test_translate_all_cipher_names(self):
+        """
+        Translate MbedTLS ciphersuite names to their OpenSSL and
+        GnuTLS counterpart. Use only a small subset of ciphers
+        that exercise each step of the translate functions
+        """
+        ciphers = [
+            ("TLS-ECDHE-ECDSA-WITH-NULL-SHA",
+             "+ECDHE-ECDSA:+NULL:+SHA1",
+             "ECDHE-ECDSA-NULL-SHA"),
+            ("TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
+             "+ECDHE-ECDSA:+AES-128-GCM:+AEAD",
+             "ECDHE-ECDSA-AES128-GCM-SHA256"),
+            ("TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA",
+             "+DHE-RSA:+3DES-CBC:+SHA1",
+             "EDH-RSA-DES-CBC3-SHA"),
+            ("TLS-RSA-WITH-AES-256-CBC-SHA",
+             "+RSA:+AES-256-CBC:+SHA1",
+             "AES256-SHA"),
+            ("TLS-PSK-WITH-3DES-EDE-CBC-SHA",
+             "+PSK:+3DES-CBC:+SHA1",
+             "PSK-3DES-EDE-CBC-SHA"),
+            ("TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256",
+             None,
+             "ECDHE-ECDSA-CHACHA20-POLY1305"),
+            ("TLS-ECDHE-ECDSA-WITH-AES-128-CCM",
+             "+ECDHE-ECDSA:+AES-128-CCM:+AEAD",
+             None),
+            ("TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384",
+             None,
+             "ECDHE-ARIA256-GCM-SHA384"),
+        ]
+
+        for m, g_exp, o_exp in ciphers:
+
+            if g_exp is not None:
+                g = translate_gnutls(m)
+                self.assertEqual(g, g_exp)
+
+            if o_exp is not None:
+                o = translate_ossl(m)
+                self.assertEqual(o, o_exp)
+
+def translate_gnutls(m_cipher):
+    """
+    Translate m_cipher from Mbed TLS ciphersuite naming convention
+    and return the GnuTLS naming convention
+    """
+
+    m_cipher = re.sub(r'\ATLS-', '+', m_cipher)
+    m_cipher = m_cipher.replace("-WITH-", ":+")
+    m_cipher = m_cipher.replace("-EDE", "")
+
+    # SHA in Mbed TLS == SHA1 GnuTLS,
+    # if the last 3 chars are SHA append 1
+    if m_cipher[-3:] == "SHA":
+        m_cipher = m_cipher+"1"
+
+    # CCM or CCM-8 should be followed by ":+AEAD"
+    # Replace "GCM:+SHAxyz" with "GCM:+AEAD"
+    if "CCM" in m_cipher or "GCM" in m_cipher:
+        m_cipher = re.sub(r"GCM-SHA\d\d\d", "GCM", m_cipher)
+        m_cipher = m_cipher+":+AEAD"
+
+    # Replace the last "-" with ":+"
+    else:
+        index = m_cipher.rindex("-")
+        m_cipher = m_cipher[:index] + ":+" + m_cipher[index+1:]
+
+    return m_cipher
+
+def translate_ossl(m_cipher):
+    """
+    Translate m_cipher from Mbed TLS ciphersuite naming convention
+    and return the OpenSSL naming convention
+    """
+
+    m_cipher = re.sub(r'^TLS-', '', m_cipher)
+    m_cipher = m_cipher.replace("-WITH", "")
+
+    # Remove the "-" from "ABC-xyz"
+    m_cipher = m_cipher.replace("AES-", "AES")
+    m_cipher = m_cipher.replace("CAMELLIA-", "CAMELLIA")
+    m_cipher = m_cipher.replace("ARIA-", "ARIA")
+
+    # Remove "RSA" if it is at the beginning
+    m_cipher = re.sub(r'^RSA-', r'', m_cipher)
+
+    # For all circumstances outside of PSK
+    if "PSK" not in m_cipher:
+        m_cipher = m_cipher.replace("-EDE", "")
+        m_cipher = m_cipher.replace("3DES-CBC", "DES-CBC3")
+
+        # Remove "CBC" if it is not prefixed by DES
+        m_cipher = re.sub(r'(?<!DES-)CBC-', r'', m_cipher)
+
+    # ECDHE-RSA-ARIA does not exist in OpenSSL
+    m_cipher = m_cipher.replace("ECDHE-RSA-ARIA", "ECDHE-ARIA")
+
+    # POLY1305 should not be followed by anything
+    if "POLY1305" in m_cipher:
+        index = m_cipher.rindex("POLY1305")
+        m_cipher = m_cipher[:index+8]
+
+    # If DES is being used, Replace DHE with EDH
+    if "DES" in m_cipher and "DHE" in m_cipher and "ECDHE" not in m_cipher:
+        m_cipher = m_cipher.replace("DHE", "EDH")
+
+    return m_cipher
+
+def format_ciphersuite_names(mode, names):
+    t = {"g": translate_gnutls, "o": translate_ossl}[mode]
+    return " ".join(t(c) for c in names)
+
+def main(target, names):
+    print(format_ciphersuite_names(target, names))
+
+if __name__ == "__main__":
+    PARSER = argparse.ArgumentParser()
+    PARSER.add_argument('target', metavar='TARGET', choices=['o', 'g'])
+    PARSER.add_argument('names', metavar='NAMES', nargs='+')
+    ARGS = PARSER.parse_args()
+    main(ARGS.target, ARGS.names)
diff --git a/tests/src/drivers/test_driver_aead.c b/tests/src/drivers/test_driver_aead.c
index ce9ce37..6befe7c 100644
--- a/tests/src/drivers/test_driver_aead.c
+++ b/tests/src/drivers/test_driver_aead.c
@@ -21,6 +21,7 @@
 
 #if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
 #include "psa_crypto_aead.h"
+#include "psa_crypto_core.h"
 
 #include "test/drivers/aead.h"
 
@@ -36,7 +37,7 @@
     const uint8_t *plaintext, size_t plaintext_length,
     uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length )
 {
-    mbedtls_test_driver_aead_hooks.hits++;
+    mbedtls_test_driver_aead_hooks.hits_encrypt++;
 
     if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
     {
@@ -67,7 +68,7 @@
     const uint8_t *ciphertext, size_t ciphertext_length,
     uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length )
 {
-    mbedtls_test_driver_aead_hooks.hits++;
+    mbedtls_test_driver_aead_hooks.hits_decrypt++;
 
     if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
     {
@@ -89,4 +90,229 @@
     return( mbedtls_test_driver_aead_hooks.driver_status );
 }
 
+psa_status_t mbedtls_test_transparent_aead_encrypt_setup(
+    mbedtls_transparent_test_driver_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    mbedtls_test_driver_aead_hooks.hits_encrypt_setup++;
+
+    if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_aead_hooks.driver_status =
+             mbedtls_test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_aead_hooks.driver_status =
+            mbedtls_psa_aead_encrypt_setup( operation, attributes, key_buffer,
+                                            key_buffer_size, alg );
+    }
+
+    return( mbedtls_test_driver_aead_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_aead_decrypt_setup(
+    mbedtls_transparent_test_driver_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    mbedtls_test_driver_aead_hooks.hits_decrypt_setup++;
+
+    if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_aead_hooks.driver_status =
+             mbedtls_test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_aead_hooks.driver_status =
+            mbedtls_psa_aead_decrypt_setup( operation, attributes, key_buffer,
+                                            key_buffer_size, alg );
+    }
+
+    return( mbedtls_test_driver_aead_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_aead_set_nonce(
+    mbedtls_transparent_test_driver_aead_operation_t *operation,
+    const uint8_t *nonce,
+    size_t nonce_length )
+{
+    mbedtls_test_driver_aead_hooks.hits_set_nonce++;
+
+    if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_aead_hooks.driver_status =
+             mbedtls_test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_aead_hooks.driver_status =
+            mbedtls_psa_aead_set_nonce( operation, nonce, nonce_length );
+    }
+
+    return( mbedtls_test_driver_aead_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_aead_set_lengths(
+    mbedtls_transparent_test_driver_aead_operation_t *operation,
+    size_t ad_length,
+    size_t plaintext_length )
+{
+    mbedtls_test_driver_aead_hooks.hits_set_lengths++;
+
+    if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_aead_hooks.driver_status =
+             mbedtls_test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_aead_hooks.driver_status =
+            mbedtls_psa_aead_set_lengths( operation, ad_length,
+                                          plaintext_length );
+    }
+
+    return( mbedtls_test_driver_aead_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_aead_update_ad(
+    mbedtls_transparent_test_driver_aead_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    mbedtls_test_driver_aead_hooks.hits_update_ad++;
+
+    if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_aead_hooks.driver_status =
+             mbedtls_test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_aead_hooks.driver_status =
+            mbedtls_psa_aead_update_ad( operation, input, input_length );
+    }
+
+    return( mbedtls_test_driver_aead_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_aead_update(
+   mbedtls_transparent_test_driver_aead_operation_t *operation,
+   const uint8_t *input,
+   size_t input_length,
+   uint8_t *output,
+   size_t output_size,
+   size_t *output_length )
+{
+    mbedtls_test_driver_aead_hooks.hits_update++;
+
+    if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_aead_hooks.driver_status =
+             mbedtls_test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_aead_hooks.driver_status =
+            mbedtls_psa_aead_update( operation, input, input_length, output,
+                                    output_size, output_length );
+    }
+
+    return( mbedtls_test_driver_aead_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_aead_finish(
+   mbedtls_transparent_test_driver_aead_operation_t *operation,
+   uint8_t *ciphertext,
+   size_t ciphertext_size,
+   size_t *ciphertext_length,
+   uint8_t *tag,
+   size_t tag_size,
+   size_t *tag_length )
+{
+   mbedtls_test_driver_aead_hooks.hits_finish++;
+
+    if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_aead_hooks.driver_status =
+             mbedtls_test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_aead_hooks.driver_status =
+            mbedtls_psa_aead_finish( operation, ciphertext, ciphertext_size,
+                                     ciphertext_length, tag, tag_size,
+                                     tag_length );
+    }
+
+    return( mbedtls_test_driver_aead_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_aead_verify(
+   mbedtls_transparent_test_driver_aead_operation_t *operation,
+   uint8_t *plaintext,
+   size_t plaintext_size,
+   size_t *plaintext_length,
+   const uint8_t *tag,
+   size_t tag_length )
+{
+   mbedtls_test_driver_aead_hooks.hits_verify++;
+
+    if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_aead_hooks.driver_status =
+             mbedtls_test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+       uint8_t check_tag[PSA_AEAD_TAG_MAX_SIZE];
+       size_t check_tag_length;
+
+       mbedtls_test_driver_aead_hooks.driver_status =
+          mbedtls_psa_aead_finish( operation,
+                                   plaintext,
+                                   plaintext_size,
+                                   plaintext_length,
+                                   check_tag,
+                                   sizeof( check_tag ),
+                                   &check_tag_length );
+
+       if( mbedtls_test_driver_aead_hooks.driver_status == PSA_SUCCESS )
+       {
+          if( tag_length != check_tag_length ||
+              mbedtls_psa_safer_memcmp( tag, check_tag, tag_length )
+              != 0 )
+             mbedtls_test_driver_aead_hooks.driver_status =
+                                                    PSA_ERROR_INVALID_SIGNATURE;
+       }
+
+       mbedtls_platform_zeroize( check_tag, sizeof( check_tag ) );
+    }
+
+    return( mbedtls_test_driver_aead_hooks.driver_status );
+}
+
+psa_status_t mbedtls_test_transparent_aead_abort(
+   mbedtls_transparent_test_driver_aead_operation_t *operation )
+{
+   mbedtls_test_driver_aead_hooks.hits_abort++;
+
+    if( mbedtls_test_driver_aead_hooks.forced_status != PSA_SUCCESS )
+    {
+         mbedtls_test_driver_aead_hooks.driver_status =
+             mbedtls_test_driver_aead_hooks.forced_status;
+    }
+    else
+    {
+        mbedtls_test_driver_aead_hooks.driver_status =
+            mbedtls_psa_aead_abort( operation );
+    }
+
+    return( mbedtls_test_driver_aead_hooks.driver_status );
+}
+
 #endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/tests/src/helpers.c b/tests/src/helpers.c
index 4d3d53d..ec4d84e 100644
--- a/tests/src/helpers.c
+++ b/tests/src/helpers.c
@@ -95,6 +95,31 @@
     mbedtls_test_info.test = 0;
     mbedtls_test_info.line_no = 0;
     mbedtls_test_info.filename = 0;
+    memset( mbedtls_test_info.line1, 0, sizeof( mbedtls_test_info.line1 ) );
+    memset( mbedtls_test_info.line2, 0, sizeof( mbedtls_test_info.line2 ) );
+}
+
+int mbedtls_test_equal( const char *test, int line_no, const char* filename,
+                        unsigned long long value1, unsigned long long value2 )
+{
+    if( value1 == value2 )
+        return( 1 );
+    if( mbedtls_test_info.result == MBEDTLS_TEST_RESULT_FAILED )
+    {
+        /* We've already recorded the test as having failed. Don't
+         * overwrite any previous information about the failure. */
+        return( 0 );
+    }
+    mbedtls_test_fail( test, line_no, filename );
+    (void) mbedtls_snprintf( mbedtls_test_info.line1,
+                             sizeof( mbedtls_test_info.line1 ),
+                             "lhs = 0x%016llx = %lld",
+                             value1, (long long) value1 );
+    (void) mbedtls_snprintf( mbedtls_test_info.line2,
+                             sizeof( mbedtls_test_info.line2 ),
+                             "rhs = 0x%016llx = %lld",
+                             value2, (long long) value2 );
+    return( 0 );
 }
 
 int mbedtls_test_unhexify( unsigned char *obuf,
diff --git a/tests/src/psa_exercise_key.c b/tests/src/psa_exercise_key.c
index e4e55c9..923d2c1 100644
--- a/tests/src/psa_exercise_key.c
+++ b/tests/src/psa_exercise_key.c
@@ -663,7 +663,7 @@
         TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
                                           MBEDTLS_ASN1_SEQUENCE |
                                           MBEDTLS_ASN1_CONSTRUCTED ), 0 );
-        TEST_EQUAL( p + len, end );
+        TEST_EQUAL( len, end - p );
         if( ! mbedtls_test_asn1_skip_integer( &p, end, 0, 0, 0 ) )
             goto exit;
         if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
@@ -684,7 +684,7 @@
             goto exit;
         if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
             goto exit;
-        TEST_EQUAL( p, end );
+        TEST_EQUAL( p - end, 0 );
 
         TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE );
     }
@@ -716,12 +716,12 @@
                                           MBEDTLS_ASN1_SEQUENCE |
                                           MBEDTLS_ASN1_CONSTRUCTED ),
                     0 );
-        TEST_EQUAL( p + len, end );
+        TEST_EQUAL( len, end - p );
         if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
             goto exit;
         if( ! mbedtls_test_asn1_skip_integer( &p, end, 2, bits, 1 ) )
             goto exit;
-        TEST_EQUAL( p, end );
+        TEST_EQUAL( p - end, 0 );
 
 
         TEST_ASSERT( exported_length <=
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 3e199e2..f9bfec2 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -552,6 +552,32 @@
     fi
 }
 
+# True if the presence of the given pattern in a log definitely indicates
+# that the test has failed. False if the presence is inconclusive.
+#
+# Inputs:
+# * $1: pattern found in the logs
+# * $TIMES_LEFT: >0 if retrying is an option
+#
+# Outputs:
+# * $outcome: set to a retry reason if the pattern is inconclusive,
+#             unchanged otherwise.
+# * Return value: 1 if the pattern is inconclusive,
+#                 0 if the failure is definitive.
+log_pattern_presence_is_conclusive() {
+    # If we've run out of attempts, then don't retry no matter what.
+    if [ $TIMES_LEFT -eq 0 ]; then
+        return 0
+    fi
+    case $1 in
+        "resend")
+            # An undesired resend may have been caused by the OS dropping or
+            # delaying a packet at an inopportune time.
+            outcome="RETRY(resend)"
+            return 1;;
+    esac
+}
+
 # fail <message>
 fail() {
     record_outcome "FAIL" "$1"
@@ -626,6 +652,8 @@
 # Wait for process $2 named $3 to be listening on port $1. Print error to $4.
 if type lsof >/dev/null 2>/dev/null; then
     wait_app_start() {
+        newline='
+'
         START_TIME=$(date +%s)
         if [ "$DTLS" -eq 1 ]; then
             proto=UDP
@@ -633,7 +661,15 @@
             proto=TCP
         fi
         # Make a tight loop, server normally takes less than 1s to start.
-        while ! lsof -a -n -b -i "$proto:$1" -p "$2" >/dev/null 2>/dev/null; do
+        while true; do
+              SERVER_PIDS=$(lsof -a -n -b -i "$proto:$1" -F p)
+              # When we use a proxy, it will be listening on the same port we
+              # are checking for as well as the server and lsof will list both.
+              # If multiple PIDs are returned, each one will be on a separate
+              # line, each prepended with 'p'.
+             case ${newline}${SERVER_PIDS}${newline} in
+                  *${newline}p${2}${newline}*) break;;
+              esac
               if [ $(( $(date +%s) - $START_TIME )) -gt $DOG_DELAY ]; then
                   echo "$3 START TIMEOUT"
                   echo "$3 START TIMEOUT" >> $4
@@ -753,7 +789,7 @@
 # check if the given command uses dtls and sets global variable DTLS
 detect_dtls() {
     case "$1" in
-        *dtls=1*|-dtls|-u) DTLS=1;;
+        *dtls=1*|*-dtls*|*-u*) DTLS=1;;
         *) DTLS=0;;
     esac
 }
@@ -795,6 +831,271 @@
     SKIP_HANDSHAKE_CHECK="YES"
 }
 
+# Analyze the commands that will be used in a test.
+#
+# Analyze and possibly instrument $PXY_CMD, $CLI_CMD, $SRV_CMD to pass
+# extra arguments or go through wrappers.
+# Set $DTLS (0=TLS, 1=DTLS).
+analyze_test_commands() {
+    # update DTLS variable
+    detect_dtls "$SRV_CMD"
+
+    # if the test uses DTLS but no custom proxy, add a simple proxy
+    # as it provides timing info that's useful to debug failures
+    if [ -z "$PXY_CMD" ] && [ "$DTLS" -eq 1 ]; then
+        PXY_CMD="$P_PXY"
+        case " $SRV_CMD " in
+            *' server_addr=::1 '*)
+                PXY_CMD="$PXY_CMD server_addr=::1 listen_addr=::1";;
+        esac
+    fi
+
+    # update CMD_IS_GNUTLS variable
+    is_gnutls "$SRV_CMD"
+
+    # if the server uses gnutls but doesn't set priority, explicitly
+    # set the default priority
+    if [ "$CMD_IS_GNUTLS" -eq 1 ]; then
+        case "$SRV_CMD" in
+              *--priority*) :;;
+              *) SRV_CMD="$SRV_CMD --priority=NORMAL";;
+        esac
+    fi
+
+    # update CMD_IS_GNUTLS variable
+    is_gnutls "$CLI_CMD"
+
+    # if the client uses gnutls but doesn't set priority, explicitly
+    # set the default priority
+    if [ "$CMD_IS_GNUTLS" -eq 1 ]; then
+        case "$CLI_CMD" in
+              *--priority*) :;;
+              *) CLI_CMD="$CLI_CMD --priority=NORMAL";;
+        esac
+    fi
+
+    # fix client port
+    if [ -n "$PXY_CMD" ]; then
+        CLI_CMD=$( echo "$CLI_CMD" | sed s/+SRV_PORT/$PXY_PORT/g )
+    else
+        CLI_CMD=$( echo "$CLI_CMD" | sed s/+SRV_PORT/$SRV_PORT/g )
+    fi
+
+    # prepend valgrind to our commands if active
+    if [ "$MEMCHECK" -gt 0 ]; then
+        if is_polar "$SRV_CMD"; then
+            SRV_CMD="valgrind --leak-check=full $SRV_CMD"
+        fi
+        if is_polar "$CLI_CMD"; then
+            CLI_CMD="valgrind --leak-check=full $CLI_CMD"
+        fi
+    fi
+}
+
+# Check for failure conditions after a test case.
+#
+# Inputs from run_test:
+# * positional parameters: test options (see run_test documentation)
+# * $CLI_EXIT: client return code
+# * $CLI_EXPECT: expected client return code
+# * $SRV_RET: server return code
+# * $CLI_OUT, $SRV_OUT, $PXY_OUT: files containing client/server/proxy logs
+# * $TIMES_LEFT: if nonzero, a RETRY outcome is allowed
+#
+# Outputs:
+# * $outcome: one of PASS/RETRY*/FAIL
+check_test_failure() {
+    outcome=FAIL
+
+    if [ $TIMES_LEFT -gt 0 ] &&
+       grep '===CLIENT_TIMEOUT===' $CLI_OUT >/dev/null
+    then
+        outcome="RETRY(client-timeout)"
+        return
+    fi
+
+    # check if the client and server went at least to the handshake stage
+    # (useful to avoid tests with only negative assertions and non-zero
+    # expected client exit to incorrectly succeed in case of catastrophic
+    # failure)
+    if [ "X$SKIP_HANDSHAKE_CHECK" != "XYES" ]
+    then
+        if is_polar "$SRV_CMD"; then
+            if grep "Performing the SSL/TLS handshake" $SRV_OUT >/dev/null; then :;
+            else
+                fail "server or client failed to reach handshake stage"
+                return
+            fi
+        fi
+        if is_polar "$CLI_CMD"; then
+            if grep "Performing the SSL/TLS handshake" $CLI_OUT >/dev/null; then :;
+            else
+                fail "server or client failed to reach handshake stage"
+                return
+            fi
+        fi
+    fi
+
+    SKIP_HANDSHAKE_CHECK="NO"
+    # Check server exit code (only for Mbed TLS: GnuTLS and OpenSSL don't
+    # exit with status 0 when interrupted by a signal, and we don't really
+    # care anyway), in case e.g. the server reports a memory leak.
+    if [ $SRV_RET != 0 ] && is_polar "$SRV_CMD"; then
+        fail "Server exited with status $SRV_RET"
+        return
+    fi
+
+    # check client exit code
+    if [ \( "$CLI_EXPECT" = 0 -a "$CLI_EXIT" != 0 \) -o \
+         \( "$CLI_EXPECT" != 0 -a "$CLI_EXIT" = 0 \) ]
+    then
+        fail "bad client exit code (expected $CLI_EXPECT, got $CLI_EXIT)"
+        return
+    fi
+
+    # check other assertions
+    # lines beginning with == are added by valgrind, ignore them
+    # lines with 'Serious error when reading debug info', are valgrind issues as well
+    while [ $# -gt 0 ]
+    do
+        case $1 in
+            "-s")
+                if grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then :; else
+                    fail "pattern '$2' MUST be present in the Server output"
+                    return
+                fi
+                ;;
+
+            "-c")
+                if grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then :; else
+                    fail "pattern '$2' MUST be present in the Client output"
+                    return
+                fi
+                ;;
+
+            "-S")
+                if grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then
+                    if log_pattern_presence_is_conclusive "$2"; then
+                        fail "pattern '$2' MUST NOT be present in the Server output"
+                    fi
+                    return
+                fi
+                ;;
+
+            "-C")
+                if grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then
+                    if log_pattern_presence_is_conclusive "$2"; then
+                        fail "pattern '$2' MUST NOT be present in the Client output"
+                    fi
+                    return
+                fi
+                ;;
+
+                # The filtering in the following two options (-u and -U) do the following
+                #   - ignore valgrind output
+                #   - filter out everything but lines right after the pattern occurrences
+                #   - keep one of each non-unique line
+                #   - count how many lines remain
+                # A line with '--' will remain in the result from previous outputs, so the number of lines in the result will be 1
+                # if there were no duplicates.
+            "-U")
+                if [ $(grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep -A1 "$2" | grep -v "$2" | sort | uniq -d | wc -l) -gt 1 ]; then
+                    fail "lines following pattern '$2' must be unique in Server output"
+                    return
+                fi
+                ;;
+
+            "-u")
+                if [ $(grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep -A1 "$2" | grep -v "$2" | sort | uniq -d | wc -l) -gt 1 ]; then
+                    fail "lines following pattern '$2' must be unique in Client output"
+                    return
+                fi
+                ;;
+            "-F")
+                if ! $2 "$SRV_OUT"; then
+                    fail "function call to '$2' failed on Server output"
+                    return
+                fi
+                ;;
+            "-f")
+                if ! $2 "$CLI_OUT"; then
+                    fail "function call to '$2' failed on Client output"
+                    return
+                fi
+                ;;
+            "-g")
+                if ! eval "$2 '$SRV_OUT' '$CLI_OUT'"; then
+                    fail "function call to '$2' failed on Server and Client output"
+                    return
+                fi
+                ;;
+
+            *)
+                echo "Unknown test: $1" >&2
+                exit 1
+        esac
+        shift 2
+    done
+
+    # check valgrind's results
+    if [ "$MEMCHECK" -gt 0 ]; then
+        if is_polar "$SRV_CMD" && has_mem_err $SRV_OUT; then
+            fail "Server has memory errors"
+            return
+        fi
+        if is_polar "$CLI_CMD" && has_mem_err $CLI_OUT; then
+            fail "Client has memory errors"
+            return
+        fi
+    fi
+
+    # if we're here, everything is ok
+    outcome=PASS
+}
+
+# Run the current test case: start the server and if applicable the proxy, run
+# the client, wait for all processes to finish or time out.
+#
+# Inputs:
+# * $NAME: test case name
+# * $CLI_CMD, $SRV_CMD, $PXY_CMD: commands to run
+# * $CLI_OUT, $SRV_OUT, $PXY_OUT: files to contain client/server/proxy logs
+#
+# Outputs:
+# * $CLI_EXIT: client return code
+# * $SRV_RET: server return code
+do_run_test_once() {
+    # run the commands
+    if [ -n "$PXY_CMD" ]; then
+        printf "# %s\n%s\n" "$NAME" "$PXY_CMD" > $PXY_OUT
+        $PXY_CMD >> $PXY_OUT 2>&1 &
+        PXY_PID=$!
+        wait_proxy_start "$PXY_PORT" "$PXY_PID"
+    fi
+
+    check_osrv_dtls
+    printf '# %s\n%s\n' "$NAME" "$SRV_CMD" > $SRV_OUT
+    provide_input | $SRV_CMD >> $SRV_OUT 2>&1 &
+    SRV_PID=$!
+    wait_server_start "$SRV_PORT" "$SRV_PID"
+
+    printf '# %s\n%s\n' "$NAME" "$CLI_CMD" > $CLI_OUT
+    eval "$CLI_CMD" >> $CLI_OUT 2>&1 &
+    wait_client_done
+
+    sleep 0.05
+
+    # terminate the server (and the proxy)
+    kill $SRV_PID
+    wait $SRV_PID
+    SRV_RET=$?
+
+    if [ -n "$PXY_CMD" ]; then
+        kill $PXY_PID >/dev/null 2>&1
+        wait $PXY_PID
+    fi
+}
+
 # Usage: run_test name [-p proxy_cmd] srv_cmd cli_cmd cli_exit [option [...]]
 # Options:  -s pattern  pattern that must be present in server output
 #           -c pattern  pattern that must be present in client output
@@ -857,234 +1158,23 @@
         return
     fi
 
-    # update DTLS variable
-    detect_dtls "$SRV_CMD"
-
-    # if the test uses DTLS but no custom proxy, add a simple proxy
-    # as it provides timing info that's useful to debug failures
-    if [ -z "$PXY_CMD" ] && [ "$DTLS" -eq 1 ]; then
-        PXY_CMD="$P_PXY"
-        case " $SRV_CMD " in
-            *' server_addr=::1 '*)
-                PXY_CMD="$PXY_CMD server_addr=::1 listen_addr=::1";;
-        esac
-    fi
-
-    # update CMD_IS_GNUTLS variable
-    is_gnutls "$SRV_CMD"
-
-    # if the server uses gnutls but doesn't set priority, explicitly
-    # set the default priority
-    if [ "$CMD_IS_GNUTLS" -eq 1 ]; then
-        case "$SRV_CMD" in
-              *--priority*) :;;
-              *) SRV_CMD="$SRV_CMD --priority=NORMAL";;
-        esac
-    fi
-
-    # update CMD_IS_GNUTLS variable
-    is_gnutls "$CLI_CMD"
-
-    # if the client uses gnutls but doesn't set priority, explicitly
-    # set the default priority
-    if [ "$CMD_IS_GNUTLS" -eq 1 ]; then
-        case "$CLI_CMD" in
-              *--priority*) :;;
-              *) CLI_CMD="$CLI_CMD --priority=NORMAL";;
-        esac
-    fi
-
-    # fix client port
-    if [ -n "$PXY_CMD" ]; then
-        CLI_CMD=$( echo "$CLI_CMD" | sed s/+SRV_PORT/$PXY_PORT/g )
-    else
-        CLI_CMD=$( echo "$CLI_CMD" | sed s/+SRV_PORT/$SRV_PORT/g )
-    fi
-
-    # prepend valgrind to our commands if active
-    if [ "$MEMCHECK" -gt 0 ]; then
-        if is_polar "$SRV_CMD"; then
-            SRV_CMD="valgrind --leak-check=full $SRV_CMD"
-        fi
-        if is_polar "$CLI_CMD"; then
-            CLI_CMD="valgrind --leak-check=full $CLI_CMD"
-        fi
-    fi
+    analyze_test_commands "$@"
 
     TIMES_LEFT=2
     while [ $TIMES_LEFT -gt 0 ]; do
         TIMES_LEFT=$(( $TIMES_LEFT - 1 ))
 
-        # run the commands
-        if [ -n "$PXY_CMD" ]; then
-            printf "# %s\n%s\n" "$NAME" "$PXY_CMD" > $PXY_OUT
-            $PXY_CMD >> $PXY_OUT 2>&1 &
-            PXY_PID=$!
-            wait_proxy_start "$PXY_PORT" "$PXY_PID"
-        fi
+        do_run_test_once
 
-        check_osrv_dtls
-        printf '# %s\n%s\n' "$NAME" "$SRV_CMD" > $SRV_OUT
-        provide_input | $SRV_CMD >> $SRV_OUT 2>&1 &
-        SRV_PID=$!
-        wait_server_start "$SRV_PORT" "$SRV_PID"
-
-        printf '# %s\n%s\n' "$NAME" "$CLI_CMD" > $CLI_OUT
-        eval "$CLI_CMD" >> $CLI_OUT 2>&1 &
-        wait_client_done
-
-        sleep 0.05
-
-        # terminate the server (and the proxy)
-        kill $SRV_PID
-        wait $SRV_PID
-        SRV_RET=$?
-
-        if [ -n "$PXY_CMD" ]; then
-            kill $PXY_PID >/dev/null 2>&1
-            wait $PXY_PID
-        fi
-
-        # retry only on timeouts
-        if grep '===CLIENT_TIMEOUT===' $CLI_OUT >/dev/null; then
-            printf "RETRY "
-        else
-            TIMES_LEFT=0
-        fi
-    done
-
-    # check if the client and server went at least to the handshake stage
-    # (useful to avoid tests with only negative assertions and non-zero
-    # expected client exit to incorrectly succeed in case of catastrophic
-    # failure)
-    if [ "X$SKIP_HANDSHAKE_CHECK" != "XYES" ]
-    then
-        if is_polar "$SRV_CMD"; then
-            if grep "Performing the SSL/TLS handshake" $SRV_OUT >/dev/null; then :;
-            else
-                fail "server or client failed to reach handshake stage"
-                return
-            fi
-        fi
-        if is_polar "$CLI_CMD"; then
-            if grep "Performing the SSL/TLS handshake" $CLI_OUT >/dev/null; then :;
-            else
-                fail "server or client failed to reach handshake stage"
-                return
-            fi
-        fi
-    fi
-
-    SKIP_HANDSHAKE_CHECK="NO"
-    # Check server exit code (only for Mbed TLS: GnuTLS and OpenSSL don't
-    # exit with status 0 when interrupted by a signal, and we don't really
-    # care anyway), in case e.g. the server reports a memory leak.
-    if [ $SRV_RET != 0 ] && is_polar "$SRV_CMD"; then
-        fail "Server exited with status $SRV_RET"
-        return
-    fi
-
-    # check client exit code
-    if [ \( "$CLI_EXPECT" = 0 -a "$CLI_EXIT" != 0 \) -o \
-         \( "$CLI_EXPECT" != 0 -a "$CLI_EXIT" = 0 \) ]
-    then
-        fail "bad client exit code (expected $CLI_EXPECT, got $CLI_EXIT)"
-        return
-    fi
-
-    # check other assertions
-    # lines beginning with == are added by valgrind, ignore them
-    # lines with 'Serious error when reading debug info', are valgrind issues as well
-    while [ $# -gt 0 ]
-    do
-        case $1 in
-            "-s")
-                if grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then :; else
-                    fail "pattern '$2' MUST be present in the Server output"
-                    return
-                fi
-                ;;
-
-            "-c")
-                if grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then :; else
-                    fail "pattern '$2' MUST be present in the Client output"
-                    return
-                fi
-                ;;
-
-            "-S")
-                if grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then
-                    fail "pattern '$2' MUST NOT be present in the Server output"
-                    return
-                fi
-                ;;
-
-            "-C")
-                if grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then
-                    fail "pattern '$2' MUST NOT be present in the Client output"
-                    return
-                fi
-                ;;
-
-                # The filtering in the following two options (-u and -U) do the following
-                #   - ignore valgrind output
-                #   - filter out everything but lines right after the pattern occurrences
-                #   - keep one of each non-unique line
-                #   - count how many lines remain
-                # A line with '--' will remain in the result from previous outputs, so the number of lines in the result will be 1
-                # if there were no duplicates.
-            "-U")
-                if [ $(grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep -A1 "$2" | grep -v "$2" | sort | uniq -d | wc -l) -gt 1 ]; then
-                    fail "lines following pattern '$2' must be unique in Server output"
-                    return
-                fi
-                ;;
-
-            "-u")
-                if [ $(grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep -A1 "$2" | grep -v "$2" | sort | uniq -d | wc -l) -gt 1 ]; then
-                    fail "lines following pattern '$2' must be unique in Client output"
-                    return
-                fi
-                ;;
-            "-F")
-                if ! $2 "$SRV_OUT"; then
-                    fail "function call to '$2' failed on Server output"
-                    return
-                fi
-                ;;
-            "-f")
-                if ! $2 "$CLI_OUT"; then
-                    fail "function call to '$2' failed on Client output"
-                    return
-                fi
-                ;;
-            "-g")
-                if ! eval "$2 '$SRV_OUT' '$CLI_OUT'"; then
-                    fail "function call to '$2' failed on Server and Client output"
-                    return
-                fi
-                ;;
-
-            *)
-                echo "Unknown test: $1" >&2
-                exit 1
+        check_test_failure "$@"
+        case $outcome in
+            PASS) break;;
+            RETRY*) printf "$outcome ";;
+            FAIL) return;;
         esac
-        shift 2
     done
 
-    # check valgrind's results
-    if [ "$MEMCHECK" -gt 0 ]; then
-        if is_polar "$SRV_CMD" && has_mem_err $SRV_OUT; then
-            fail "Server has memory errors"
-            return
-        fi
-        if is_polar "$CLI_CMD" && has_mem_err $CLI_OUT; then
-            fail "Client has memory errors"
-            return
-        fi
-    fi
-
-    # if we're here, everything is ok
+    # If we get this far, the test case passed.
     record_outcome "PASS"
     if [ "$PRESERVE_LOGS" -gt 0 ]; then
         mv $SRV_OUT o-srv-${TESTS}.log
@@ -1309,17 +1399,24 @@
 
 # fix commands to use this port, force IPv4 while at it
 # +SRV_PORT will be replaced by either $SRV_PORT or $PXY_PORT later
+# Note: Using 'localhost' rather than 127.0.0.1 here is unwise, as on many
+# machines that will resolve to ::1, and we don't want ipv6 here.
 P_SRV="$P_SRV server_addr=127.0.0.1 server_port=$SRV_PORT"
 P_CLI="$P_CLI server_addr=127.0.0.1 server_port=+SRV_PORT"
 P_PXY="$P_PXY server_addr=127.0.0.1 server_port=$SRV_PORT listen_addr=127.0.0.1 listen_port=$PXY_PORT ${SEED:+"seed=$SEED"}"
 O_SRV="$O_SRV -accept $SRV_PORT"
-O_CLI="$O_CLI -connect localhost:+SRV_PORT"
+O_CLI="$O_CLI -connect 127.0.0.1:+SRV_PORT"
 G_SRV="$G_SRV -p $SRV_PORT"
 G_CLI="$G_CLI -p +SRV_PORT"
 
 if [ -n "${OPENSSL_LEGACY:-}" ]; then
     O_LEGACY_SRV="$O_LEGACY_SRV -accept $SRV_PORT -dhparam data_files/dhparams.pem"
-    O_LEGACY_CLI="$O_LEGACY_CLI -connect localhost:+SRV_PORT"
+    O_LEGACY_CLI="$O_LEGACY_CLI -connect 127.0.0.1:+SRV_PORT"
+fi
+
+if [ -n "${OPENSSL_NEXT:-}" ]; then
+    O_NEXT_SRV="$O_NEXT_SRV -accept $SRV_PORT"
+    O_NEXT_CLI="$O_NEXT_CLI -connect 127.0.0.1:+SRV_PORT"
 fi
 
 if [ -n "${GNUTLS_NEXT_SERV:-}" ]; then
@@ -1430,12 +1527,53 @@
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SHA256_C
 run_test    "Opaque key for client authentication" \
-            "$P_SRV auth_mode=required" \
+            "$P_SRV auth_mode=required crt_file=data_files/server5.crt \
+             key_file=data_files/server5.key" \
             "$P_CLI key_opaque=1 crt_file=data_files/server5.crt \
              key_file=data_files/server5.key" \
             0 \
             -c "key type: Opaque" \
+            -c "Ciphersuite is TLS-ECDHE-ECDSA" \
             -s "Verifying peer X.509 certificate... ok" \
+            -s "Ciphersuite is TLS-ECDHE-ECDSA" \
+            -S "error" \
+            -C "error"
+
+# Test using an opaque private key for server authentication
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+requires_config_enabled MBEDTLS_X509_CRT_PARSE_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SHA256_C
+run_test    "Opaque key for server authentication" \
+            "$P_SRV auth_mode=required key_opaque=1 crt_file=data_files/server5.crt \
+             key_file=data_files/server5.key" \
+            "$P_CLI crt_file=data_files/server5.crt \
+             key_file=data_files/server5.key" \
+            0 \
+            -c "Verifying peer X.509 certificate... ok" \
+            -c "Ciphersuite is TLS-ECDHE-ECDSA" \
+            -s "key types: Opaque - invalid PK" \
+            -s "Ciphersuite is TLS-ECDHE-ECDSA" \
+            -S "error" \
+            -C "error"
+
+# Test using an opaque private key for client/server authentication
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+requires_config_enabled MBEDTLS_X509_CRT_PARSE_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SHA256_C
+run_test    "Opaque key for client/server authentication" \
+            "$P_SRV auth_mode=required key_opaque=1 crt_file=data_files/server5.crt \
+             key_file=data_files/server5.key" \
+            "$P_CLI key_opaque=1 crt_file=data_files/server5.crt \
+             key_file=data_files/server5.key" \
+            0 \
+            -c "key type: Opaque" \
+            -c "Verifying peer X.509 certificate... ok" \
+            -c "Ciphersuite is TLS-ECDHE-ECDSA" \
+            -s "key types: Opaque - invalid PK" \
+            -s "Verifying peer X.509 certificate... ok" \
+            -s "Ciphersuite is TLS-ECDHE-ECDSA" \
             -S "error" \
             -C "error"
 
@@ -2689,10 +2827,13 @@
             -c "parse new session ticket" \
             -c "a session has been resumed"
 
+# For reasons that aren't fully understood, this test randomly fails with high
+# probability with OpenSSL 1.0.2g on the CI, see #5012.
+requires_openssl_next
 run_test    "Session resume using tickets, DTLS: openssl client" \
             "$P_SRV dtls=1 debug_level=3 tickets=1" \
-            "( $O_CLI -dtls -sess_out $SESSION; \
-               $O_CLI -dtls -sess_in $SESSION; \
+            "( $O_NEXT_CLI -dtls -sess_out $SESSION; \
+               $O_NEXT_CLI -dtls -sess_in $SESSION; \
                rm -f $SESSION )" \
             0 \
             -s "found session ticket extension" \
@@ -2889,10 +3030,13 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+# For reasons that aren't fully understood, this test randomly fails with high
+# probability with OpenSSL 1.0.2g on the CI, see #5012.
+requires_openssl_next
 run_test    "Session resume using cache, DTLS: openssl client" \
             "$P_SRV dtls=1 debug_level=3 tickets=0" \
-            "( $O_CLI -dtls -sess_out $SESSION; \
-               $O_CLI -dtls -sess_in $SESSION; \
+            "( $O_NEXT_CLI -dtls -sess_out $SESSION; \
+               $O_NEXT_CLI -dtls -sess_in $SESSION; \
                rm -f $SESSION )" \
             0 \
             -s "found session ticket extension" \
@@ -8608,7 +8752,6 @@
             -s "Extra-header:" \
             -c "Extra-header:"
 
-requires_config_enabled MBEDTLS_SSL_EXPORT_KEYS
 run_test    "export keys functionality" \
             "$P_SRV eap_tls=1 debug_level=3" \
             "$P_CLI eap_tls=1 debug_level=3" \
@@ -8655,11 +8798,65 @@
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
 run_test    "TLS1.3: handshake dispatch test: tls1_3 only" \
-            "$P_SRV min_version=tls1_3 max_version=tls1_3" \
-            "$P_CLI min_version=tls1_3 max_version=tls1_3" \
+            "$P_SRV debug_level=2 min_version=tls1_3 max_version=tls1_3" \
+            "$P_CLI debug_level=2 min_version=tls1_3 max_version=tls1_3" \
             1 \
-            -s "SSL - The requested feature is not available" \
-            -c "SSL - The requested feature is not available"
+            -s "tls1_3 server state: 0"     \
+            -c "tls1_3 client state: 0"
+
+requires_openssl_tls1_3
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
+requires_config_disabled MBEDTLS_USE_PSA_CRYPTO
+run_test    "TLS1.3: Test client hello msg work - openssl" \
+            "$O_NEXT_SRV -tls1_3 -msg -no_middlebox" \
+            "$P_CLI debug_level=3 min_version=tls1_3 max_version=tls1_3" \
+            1 \
+            -c "SSL - The requested feature is not available" \
+            -s "ServerHello"                \
+            -c "tls1_3 client state: 0"     \
+            -c "tls1_3 client state: 2"     \
+            -c "tls1_3 client state: 19"    \
+            -c "tls1_3 client state: 5"     \
+            -c "tls1_3 client state: 3"     \
+            -c "tls1_3 client state: 9"     \
+            -c "tls1_3 client state: 13"    \
+            -c "tls1_3 client state: 7"     \
+            -c "tls1_3 client state: 20"    \
+            -c "tls1_3 client state: 11"    \
+            -c "tls1_3 client state: 14"    \
+            -c "tls1_3 client state: 15"    \
+            -c "<= ssl_tls1_3_process_server_hello" \
+            -c "server hello, chosen ciphersuite: ( 1301 ) - TLS1-3-AES-128-GCM-SHA256" \
+            -c "ECDH curve: x25519"         \
+            -c "=> ssl_tls1_3_process_server_hello" \
+            -c "<= parse encrypted extensions"
+
+requires_gnutls_tls1_3
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
+requires_config_disabled MBEDTLS_USE_PSA_CRYPTO
+run_test    "TLS1.3: Test client hello msg work - gnutls" \
+            "$G_NEXT_SRV --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:%DISABLE_TLS13_COMPAT_MODE --debug=4" \
+            "$P_CLI debug_level=3 min_version=tls1_3 max_version=tls1_3" \
+            1 \
+            -c "SSL - The requested feature is not available" \
+            -s "SERVER HELLO was queued"    \
+            -c "tls1_3 client state: 0"     \
+            -c "tls1_3 client state: 2"     \
+            -c "tls1_3 client state: 19"    \
+            -c "tls1_3 client state: 5"     \
+            -c "tls1_3 client state: 3"     \
+            -c "tls1_3 client state: 9"     \
+            -c "tls1_3 client state: 13"    \
+            -c "tls1_3 client state: 7"     \
+            -c "tls1_3 client state: 20"    \
+            -c "tls1_3 client state: 11"    \
+            -c "tls1_3 client state: 14"    \
+            -c "tls1_3 client state: 15"    \
+            -c "<= ssl_tls1_3_process_server_hello" \
+            -c "server hello, chosen ciphersuite: ( 1301 ) - TLS1-3-AES-128-GCM-SHA256" \
+            -c "ECDH curve: x25519"         \
+            -c "=> ssl_tls1_3_process_server_hello" \
+            -c "<= parse encrypted extensions"
 
 # Test heap memory usage after handshake
 requires_config_enabled MBEDTLS_MEMORY_DEBUG
diff --git a/tests/suites/host_test.function b/tests/suites/host_test.function
index a5fd717..17926eb 100644
--- a/tests/suites/host_test.function
+++ b/tests/suites/host_test.function
@@ -778,6 +778,12 @@
                     mbedtls_fprintf( stdout, "line %d, %s",
                                      mbedtls_test_info.line_no,
                                      mbedtls_test_info.filename );
+                    if( mbedtls_test_info.line1[0] != 0 )
+                        mbedtls_fprintf( stdout, "\n  %s",
+                                         mbedtls_test_info.line1 );
+                    if( mbedtls_test_info.line2[0] != 0 )
+                        mbedtls_fprintf( stdout, "\n  %s",
+                                         mbedtls_test_info.line2 );
                 }
                 fflush( stdout );
             }
diff --git a/tests/suites/target_test.function b/tests/suites/target_test.function
deleted file mode 100644
index 637a79d..0000000
--- a/tests/suites/target_test.function
+++ /dev/null
@@ -1,449 +0,0 @@
-#line 2 "suites/target_test.function"
-
-#include "greentea-client/test_env.h"
-
-/**
- * \brief       Increments pointer and asserts that it does not overflow.
- *
- * \param p     Pointer to byte array
- * \param start Pointer to start of byte array
- * \param len   Length of byte array
- * \param step  Increment size
- *
- */
-#define INCR_ASSERT(p, start, len, step) do                     \
-{                                                               \
-    TEST_HELPER_ASSERT( ( p ) >= ( start ) );                               \
-    TEST_HELPER_ASSERT( sizeof( *( p ) ) == sizeof( *( start ) ) );         \
-    /* <= is checked to support use inside a loop where         \
-       pointer is incremented after reading data.       */      \
-    TEST_HELPER_ASSERT( (uint32_t)( ( ( p ) - ( start ) ) + ( step ) ) <= ( len ) );\
-    ( p ) += ( step );                                          \
-}                                                               \
-while( 0 )
-
-
-/**
- * \brief       4 byte align unsigned char pointer
- *
- * \param p     Pointer to byte array
- * \param start Pointer to start of byte array
- * \param len   Length of byte array
- *
- */
-#define ALIGN_32BIT(p, start, len) do               \
-{                                                   \
-    uint32_t align = ( - (uintptr_t)( p ) ) % 4;    \
-    INCR_ASSERT( ( p ), ( start ), ( len ), align );\
-}                                                   \
-while( 0 )
-
-
-/**
- * \brief       Verify dependencies. Dependency identifiers are
- *              encoded in the buffer as 8 bit unsigned integers.
- *
- * \param count     Number of dependencies.
- * \param dep_p     Pointer to buffer.
- *
- * \return          DEPENDENCY_SUPPORTED if success else DEPENDENCY_NOT_SUPPORTED.
- */
-int verify_dependencies( uint8_t count, uint8_t * dep_p )
-{
-    uint8_t i;
-    for ( i = 0; i < count; i++ )
-    {
-        if ( dep_check( (int)(dep_p[i]) ) != DEPENDENCY_SUPPORTED )
-            return( DEPENDENCY_NOT_SUPPORTED );
-    }
-    return( DEPENDENCY_SUPPORTED );
-}
-
-/**
- * \brief       Receives hex string on serial interface, and converts to a byte.
- *
- * \param none
- *
- * \return      unsigned int8
- */
-uint8_t receive_byte()
-{
-    uint8_t byte;
-    uint8_t c[3];
-    size_t len;
-
-    c[0] = greentea_getc();
-    c[1] = greentea_getc();
-    c[2] = '\0';
-
-    TEST_HELPER_ASSERT( mbedtls_test_unhexify( &byte, sizeof( byte ),
-                                               c, &len ) == 0 );
-    TEST_HELPER_ASSERT( len != 2 );
-
-    return( byte );
-}
-
-/**
- * \brief       Receives unsigned integer on serial interface.
- *              Integers are encoded in network order, and sent as hex ascii string.
- *
- * \param none
- *
- * \return      unsigned int
- */
-uint32_t receive_uint32()
-{
-    uint32_t value;
-    size_t len;
-    const uint8_t c_be[8] = { greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc()
-                             };
-    const uint8_t c[9] = { c_be[6], c_be[7], c_be[4], c_be[5], c_be[2],
-                           c_be[3], c_be[0], c_be[1], '\0' };
-
-    TEST_HELPER_ASSERT( mbedtls_test_unhexify( (uint8_t*)&value, sizeof( value ),
-                                               c, &len ) == 0 );
-    TEST_HELPER_ASSERT( len != 8 );
-
-    return( value );
-}
-
-/**
- * \brief       Parses out an unsigned 32 int value from the byte array.
- *              Integers are encoded in network order.
- *
- * \param p     Pointer to byte array
- *
- * \return      unsigned int
- */
-uint32_t parse_uint32( uint8_t * p )
-{
-    uint32_t value;
-    value =  *p++ << 24;
-    value |= *p++ << 16;
-    value |= *p++ << 8;
-    value |= *p;
-    return( value );
-}
-
-
-/**
- * \brief       Receives test data on serial as greentea key,value pair:
- *              {{<length>;<byte array>}}
- *
- * \param data_len  Out pointer to hold received data length.
- *
- * \return      Byte array.
- */
-uint8_t * receive_data( uint32_t * data_len )
-{
-    uint32_t i = 0, errors = 0;
-    char c;
-    uint8_t * data = NULL;
-
-    /* Read opening braces */
-    i = 0;
-    while ( i < 2 )
-    {
-        c = greentea_getc();
-        /* Ignore any prevous CR LF characters */
-        if ( c == '\n' || c == '\r' )
-            continue;
-        i++;
-        if ( c != '{' )
-            return( NULL );
-    }
-
-    /* Read data length */
-    *data_len = receive_uint32();
-    data = (uint8_t *)malloc( *data_len );
-    TEST_HELPER_ASSERT( data != NULL );
-
-    greentea_getc(); // read ';' received after key i.e. *data_len
-
-    for( i = 0; i < *data_len; i++ )
-        data[i] = receive_byte();
-
-    /* Read closing braces */
-    for( i = 0; i < 2; i++ )
-    {
-        c = greentea_getc();
-        if ( c != '}' )
-        {
-            errors++;
-            break;
-        }
-    }
-
-    if ( errors )
-    {
-        free( data );
-        data = NULL;
-        *data_len = 0;
-    }
-
-    return( data );
-}
-
-/**
- * \brief       Parse the received byte array and count the number of arguments
- *              to the test function passed as type hex.
- *
- * \param count     Parameter count
- * \param data      Received Byte array
- * \param data_len  Byte array length
- *
- * \return      count of hex params
- */
-uint32_t find_hex_count( uint8_t count, uint8_t * data, uint32_t data_len )
-{
-    uint32_t i = 0, sz = 0;
-    char c;
-    uint8_t * p = NULL;
-    uint32_t hex_count = 0;
-
-    p = data;
-
-    for( i = 0; i < count; i++ )
-    {
-        c = (char)*p;
-        INCR_ASSERT( p, data, data_len, 1 );
-
-        /* Align p to 4 bytes for int, expression, string len or hex length */
-        ALIGN_32BIT( p, data, data_len );
-
-        /* Network to host conversion */
-        sz = (int32_t)parse_uint32( p );
-
-        INCR_ASSERT( p, data, data_len, sizeof( int32_t ) );
-
-        if ( c == 'H' || c == 'S' )
-        {
-            INCR_ASSERT( p, data, data_len, sz );
-            hex_count += ( c == 'H' )?1:0;
-        }
-    }
-
-    return( hex_count );
-}
-
-/**
- * \brief       Parses received byte array for test parameters.
- *
- * \param count     Parameter count
- * \param data      Received Byte array
- * \param data_len  Byte array length
- * \param error     Parsing error out variable.
- *
- * \return      Array of parsed parameters allocated on heap.
- *              Note: Caller has the responsibility to delete
- *                    the memory after use.
- */
-void ** parse_parameters( uint8_t count, uint8_t * data, uint32_t data_len,
-                          int * error )
-{
-    uint32_t i = 0, hex_count = 0;
-    char c;
-    void ** params = NULL;
-    void ** cur = NULL;
-    uint8_t * p = NULL;
-
-    hex_count = find_hex_count(count, data, data_len);
-
-    params = (void **)malloc( sizeof( void *) * ( count + hex_count ) );
-    TEST_HELPER_ASSERT( params != NULL );
-    cur = params;
-
-    p = data;
-
-    /* Parameters */
-    for( i = 0; i < count; i++ )
-    {
-        c = (char)*p;
-        INCR_ASSERT( p, data, data_len, 1 );
-
-        /* Align p to 4 bytes for int, expression, string len or hex length */
-        ALIGN_32BIT( p, data, data_len );
-
-        /* Network to host conversion */
-        *( (int32_t *)p ) = (int32_t)parse_uint32( p );
-
-        switch( c )
-        {
-            case 'E':
-                {
-                    if ( get_expression( *( (int32_t *)p ), (int32_t *)p ) )
-                    {
-                        *error = KEY_VALUE_MAPPING_NOT_FOUND;
-                        goto exit;
-                    }
-                } /* Intentional fall through */
-            case 'I':
-                {
-                    *cur++ = (void *)p;
-                    INCR_ASSERT( p, data, data_len, sizeof( int32_t ) );
-                }
-                break;
-            case 'H': /* Intentional fall through */
-            case 'S':
-                {
-                    uint32_t * sz = (uint32_t *)p;
-                    INCR_ASSERT( p, data, data_len, sizeof( int32_t ) );
-                    *cur++ = (void *)p;
-                    if ( c == 'H' )
-                        *cur++ = (void *)sz;
-                    INCR_ASSERT( p, data, data_len, ( *sz ) );
-                }
-                break;
-            default:
-                    {
-                        *error = DISPATCH_INVALID_TEST_DATA;
-                        goto exit;
-                    }
-                break;
-        }
-    }
-
-exit:
-    if ( *error )
-    {
-        free( params );
-        params = NULL;
-    }
-
-    return( params );
-}
-
-/**
- * \brief       Sends greentea key and int value pair to host.
- *
- * \param key   key string
- * \param value integer value
- *
- * \return      void
- */
-void send_key_integer( char * key, int value )
-{
-    char str[50];
-    snprintf( str, sizeof( str ), "%d", value );
-    greentea_send_kv( key, str );
-}
-
-/**
- * \brief       Sends test setup failure to the host.
- *
- * \param failure   Test set failure
- *
- * \return      void
- */
-void send_failure( int failure )
-{
-    send_key_integer( "F", failure );
-}
-
-/**
- * \brief       Sends test status to the host.
- *
- * \param status    Test status (PASS=0/FAIL=!0)
- *
- * \return      void
- */
-void send_status( int status )
-{
-    send_key_integer( "R", status );
-}
-
-
-/**
- * \brief       Embedded implementation of execute_tests().
- *              Ignores command line and received test data
- *              on serial.
- *
- * \param argc  not used
- * \param argv  not used
- *
- * \return      Program exit status.
- */
-int execute_tests( int args, const char ** argv )
-{
-    int ret = 0;
-    uint32_t data_len = 0;
-    uint8_t count = 0, function_id;
-    void ** params = NULL;
-    uint8_t * data = NULL, * p = NULL;
-
-    GREENTEA_SETUP( 800, "mbedtls_test" );
-    greentea_send_kv( "GO", " " );
-
-    while ( 1 )
-    {
-        ret = 0;
-        mbedtls_test_info_reset( );
-        data_len = 0;
-
-        data = receive_data( &data_len );
-        if ( data == NULL )
-            continue;
-        p = data;
-
-        do
-        {
-            /* Read dependency count */
-            count = *p;
-            TEST_HELPER_ASSERT( count < data_len );
-            INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
-            ret = verify_dependencies( count, p );
-            if ( ret != DEPENDENCY_SUPPORTED )
-                break;
-
-            if ( count )
-                INCR_ASSERT( p, data, data_len, count );
-
-            /* Read function id */
-            function_id = *p;
-            INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
-            if ( ( ret = check_test( function_id ) ) != DISPATCH_TEST_SUCCESS )
-                break;
-
-            /* Read number of parameters */
-            count = *p;
-            INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
-
-            /* Parse parameters if present */
-            if ( count )
-            {
-                params = parse_parameters( count, p, data_len - ( p - data ), &ret );
-                if ( ret )
-                    break;
-            }
-
-            ret = dispatch_test( function_id, params );
-        }
-        while ( 0 );
-
-        if ( data )
-        {
-            free( data );
-            data = NULL;
-        }
-
-        if ( params )
-        {
-            free( params );
-            params = NULL;
-        }
-
-        if ( ret )
-            send_failure( ret );
-        else
-            send_status( mbedtls_test_info.result );
-    }
-    return( 0 );
-}
-
diff --git a/tests/suites/test_suite_aes.function b/tests/suites/test_suite_aes.function
index 1892c25..52af8e0 100644
--- a/tests/suites/test_suite_aes.function
+++ b/tests/suites/test_suite_aes.function
@@ -67,7 +67,7 @@
 
     mbedtls_aes_init( &ctx );
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cbc( &ctx, MBEDTLS_AES_ENCRYPT, src_str->len, iv_str->x, src_str->x, output ) == cbc_result );
     if( cbc_result == 0 )
     {
@@ -92,7 +92,7 @@
     memset(output, 0x00, 100);
     mbedtls_aes_init( &ctx );
 
-    mbedtls_aes_setkey_dec( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_dec( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cbc( &ctx, MBEDTLS_AES_DECRYPT, src_str->len, iv_str->x, src_str->x, output ) == cbc_result );
     if( cbc_result == 0)
     {
@@ -241,7 +241,7 @@
     mbedtls_aes_init( &ctx );
 
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cfb128( &ctx, MBEDTLS_AES_ENCRYPT, 16, &iv_offset, iv_str->x, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x, 16, dst->len ) == 0 );
@@ -263,7 +263,7 @@
     mbedtls_aes_init( &ctx );
 
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cfb128( &ctx, MBEDTLS_AES_DECRYPT, 16, &iv_offset, iv_str->x, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x, 16, dst->len ) == 0 );
@@ -284,7 +284,7 @@
     mbedtls_aes_init( &ctx );
 
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cfb8( &ctx, MBEDTLS_AES_ENCRYPT, src_str->len, iv_str->x, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x,
@@ -306,7 +306,7 @@
     mbedtls_aes_init( &ctx );
 
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cfb8( &ctx, MBEDTLS_AES_DECRYPT, src_str->len, iv_str->x, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x,
diff --git a/tests/suites/test_suite_base64.data b/tests/suites/test_suite_base64.data
index 3a892f4..5556668 100644
--- a/tests/suites/test_suite_base64.data
+++ b/tests/suites/test_suite_base64.data
@@ -1,3 +1,33 @@
+mask_of_range empty (1..0)
+mask_of_range:1:0
+
+mask_of_range empty (255..0)
+mask_of_range:255:0
+
+mask_of_range empty (42..7)
+mask_of_range:42:7
+
+mask_of_range 0..0
+mask_of_range:0:0
+
+mask_of_range 42..42
+mask_of_range:42:42
+
+mask_of_range 255..255
+mask_of_range:255:255
+
+mask_of_range 0..255
+mask_of_range:0:255
+
+mask_of_range 'A'..'Z'
+mask_of_range:65:90
+
+enc_char (all digits)
+enc_chars:
+
+dec_value (all characters)
+dec_chars:
+
 Test case mbedtls_base64_encode #1 buffer just right
 mbedtls_base64_encode:"":"":0:0
 
diff --git a/tests/suites/test_suite_base64.function b/tests/suites/test_suite_base64.function
index be9b6e8..67fbb67 100644
--- a/tests/suites/test_suite_base64.function
+++ b/tests/suites/test_suite_base64.function
@@ -1,6 +1,13 @@
 /* BEGIN_HEADER */
 #include "mbedtls/base64.h"
+#include "base64_invasive.h"
 #include <test/constant_flow.h>
+
+#if defined(MBEDTLS_TEST_HOOKS)
+static const char base64_digits[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#endif /* MBEDTLS_TEST_HOOKS */
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -8,6 +15,65 @@
  * END_DEPENDENCIES
  */
 
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
+void mask_of_range( int low_arg, int high_arg )
+{
+    unsigned char low = low_arg, high = high_arg;
+    unsigned c;
+    for( c = 0; c <= 0xff; c++ )
+    {
+        mbedtls_test_set_step( c );
+        TEST_CF_SECRET( &c, sizeof( c ) );
+        unsigned char m = mbedtls_base64_mask_of_range( low, high, c );
+        TEST_CF_PUBLIC( &c, sizeof( c ) );
+        TEST_CF_PUBLIC( &m, sizeof( m ) );
+        if( low <= c && c <= high )
+            TEST_EQUAL( m, 0xff );
+        else
+            TEST_EQUAL( m, 0 );
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
+void enc_chars( )
+{
+    for( unsigned value = 0; value < 64; value++ )
+    {
+        mbedtls_test_set_step( value );
+        TEST_CF_SECRET( &value, sizeof( value ) );
+        unsigned char digit = mbedtls_base64_enc_char( value );
+        TEST_CF_PUBLIC( &value, sizeof( value ) );
+        TEST_CF_PUBLIC( &digit, sizeof( digit ) );
+        TEST_EQUAL( digit, base64_digits[value] );
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
+void dec_chars( )
+{
+    char *p;
+    signed char expected;
+
+    for( unsigned c = 0; c <= 0xff; c++ )
+    {
+        mbedtls_test_set_step( c );
+        /* base64_digits is 0-terminated. sizeof()-1 excludes the trailing 0. */
+        p = memchr( base64_digits, c, sizeof( base64_digits ) - 1 );
+        if( p == NULL )
+            expected = -1;
+        else
+            expected = p - base64_digits;
+        TEST_CF_SECRET( &c, sizeof( c ) );
+        signed char actual = mbedtls_base64_dec_value( c );
+        TEST_CF_PUBLIC( &c, sizeof( c ) );
+        TEST_CF_PUBLIC( &actual, sizeof( actual ) );
+        TEST_EQUAL( actual, expected );
+    }
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void mbedtls_base64_encode( char * src_string, char * dst_string,
                             int dst_buf_size, int result )
diff --git a/tests/suites/test_suite_ccm.data b/tests/suites/test_suite_ccm.data
index a14d4be..591e0d9 100644
--- a/tests/suites/test_suite_ccm.data
+++ b/tests/suites/test_suite_ccm.data
@@ -174,6 +174,10 @@
 depends_on:MBEDTLS_AES_C
 mbedtls_ccm_encrypt_and_tag:MBEDTLS_CIPHER_ID_AES:"D7828D13B2B0BDC325A76236DF93CC6B":"ABF21C0B02FEB88F856DF4A37381BCE3CC128517D4":"008D493B30AE8B3C9696766CFA":"6E37A6EF546D955D34AB6059":"F32905B88A641B04B9C9FFB58CC390900F3DA12AB16DCE9E82EFA16DA62059"
 
+CCM encrypt and tag AES-128 (P=0, N=13, A=0, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_encrypt_and_tag:MBEDTLS_CIPHER_ID_AES:"54caf96ef6d448734700aadab50faf7a":"":"a3803e752ae849c910d8da36af":"":"eba8347baa6d61f87b67c2dd7c6d2053"
+
 CCM encrypt and tag NIST VTT AES-128 #1 (P=24, N=13, A=32, T=4)
 depends_on:MBEDTLS_AES_C
 mbedtls_ccm_encrypt_and_tag:MBEDTLS_CIPHER_ID_AES:"43b1a6bc8d0d22d6d1ca95c18593cca5":"a2b381c7d1545c408fe29817a21dc435a154c87256346b05":"9882578e750b9682c6ca7f8f86":"2084f3861c9ad0ccee7c63a7e05aece5db8b34bd8724cc06b4ca99a7f9c4914f":"cc69ed76985e0ed4c8365a72775e5a19bfccc71aeb116c85a8c74677"
@@ -1517,3 +1521,226 @@
 CCM-Camellia encrypt and tag RFC 5528 #24
 depends_on:MBEDTLS_CAMELLIA_C
 mbedtls_ccm_encrypt_and_tag:MBEDTLS_CIPHER_ID_CAMELLIA:"D75C2778078CA93D971F96FDE720F4CD":"9DC9EDAE2FF5DF8636E8C6DE0EED55F7867E33337D":"003B8FD8D3A937B160B6A31C1C":"A4D499F78419728C19178B0C":"4B198156393B0F7796086AAFB454F8C3F034CCA966945F1FCEA7E11BEE6A2F"
+
+CCM encrypt, skip ad AES-128 (P=0, N=13, A=0, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"54caf96ef6d448734700aadab50faf7a":"":"a3803e752ae849c910d8da36af":"":"eba8347baa6d61f87b67c2dd7c6d2053"
+
+CCM* encrypt, skip ad AES-128 (P=0, N=13, A=0, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"54caf96ef6d448734700aadab50faf7a":"":"a3803e752ae849c910d8da36af":"":"eba8347baa6d61f87b67c2dd7c6d2053"
+
+CCM decrypt, skip ad AES-128 (P=0, N=13, A=0, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"54caf96ef6d448734700aadab50faf7a":"":"a3803e752ae849c910d8da36af":"":"eba8347baa6d61f87b67c2dd7c6d2053"
+
+CCM* decrypt, skip ad AES-128 (P=0, N=13, A=0, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"54caf96ef6d448734700aadab50faf7a":"":"a3803e752ae849c910d8da36af":"":"eba8347baa6d61f87b67c2dd7c6d2053"
+
+CCM encrypt, skip ad NIST VADT AES-128 (P=24, N=13, A=0, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"d24a3d3dde8c84830280cb87abad0bb3":"7c86135ed9c2a515aaae0e9a208133897269220f30870006":"f1100035bb24a8d26004e0e24b":"1faeb0ee2ca2cd52f0aa3966578344f24e69b742c4ab37ab":"1123301219c70599b7c373ad4b3ad67b"
+
+CCM* encrypt, skip ad NIST VADT AES-128 (P=24, N=13, A=0, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"d24a3d3dde8c84830280cb87abad0bb3":"7c86135ed9c2a515aaae0e9a208133897269220f30870006":"f1100035bb24a8d26004e0e24b":"1faeb0ee2ca2cd52f0aa3966578344f24e69b742c4ab37ab":"1123301219c70599b7c373ad4b3ad67b"
+
+CCM decrypt, skip ad NIST DVPT AES-192 (P=24, N=7, A=0, T=4)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa":"411986d04d6463100bff03f7d0bde7ea2c3488784378138c":"5a8aa485c316e9":"3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22":"ddc93a54"
+
+CCM* decrypt, skip ad NIST DVPT AES-192 (P=24, N=7, A=0, T=4)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"19ebfde2d5468ba0a3031bde629b11fd4094afcb205393fa":"411986d04d6463100bff03f7d0bde7ea2c3488784378138c":"5a8aa485c316e9":"3796cf51b8726652a4204733b8fbb047cf00fb91a9837e22":"ddc93a54"
+
+CCM encrypt, skip update AES-128 (P=0, N=13, A=0, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"54caf96ef6d448734700aadab50faf7a":"a3803e752ae849c910d8da36af":"":"eba8347baa6d61f87b67c2dd7c6d2053"
+
+CCM decrypt, skip update AES-128 (P=0, N=13, A=0, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"54caf96ef6d448734700aadab50faf7a":"a3803e752ae849c910d8da36af":"":"eba8347baa6d61f87b67c2dd7c6d2053"
+
+CCM* encrypt, skip update AES-128 (P=0, N=13, A=0, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"54caf96ef6d448734700aadab50faf7a":"a3803e752ae849c910d8da36af":"":"eba8347baa6d61f87b67c2dd7c6d2053"
+
+CCM* decrypt, skip update AES-128 (P=0, N=13, A=0, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"54caf96ef6d448734700aadab50faf7a":"a3803e752ae849c910d8da36af":"":"eba8347baa6d61f87b67c2dd7c6d2053"
+
+CCM encrypt, skip update NIST VPT AES-128 #1 (P=0, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"2ebf60f0969013a54a3dedb19d20f6c8":"1de8c5e21f9db33123ff870add":"e1de6c6119d7db471136285d10b47a450221b16978569190ef6a22b055295603":"0ead29ef205fbb86d11abe5ed704b880"
+
+CCM* encrypt, skip update NIST VPT AES-128 #1 (P=0, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"2ebf60f0969013a54a3dedb19d20f6c8":"1de8c5e21f9db33123ff870add":"e1de6c6119d7db471136285d10b47a450221b16978569190ef6a22b055295603":"0ead29ef205fbb86d11abe5ed704b880"
+
+CCM decrypt, skip update NIST DVPT AES-256 #23 (P=0, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a":"a544218dadd3c10583db49cf39":"3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907":"867b0d87cf6e0f718200a97b4f6d5ad5"
+
+CCM* decrypt, skip update NIST DVPT AES-256 #23 (P=0, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_skip_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"8c5cf3457ff22228c39c051c4e05ed4093657eb303f859a9d4b0f8be0127d88a":"a544218dadd3c10583db49cf39":"3c0e2815d37d844f7ac240ba9d6e3a0b2a86f706e885959e09a1005e024f6907":"867b0d87cf6e0f718200a97b4f6d5ad5"
+
+CCM encrypt, overflow ad NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_overflow_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM encrypt, incomplete ad NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM encrypt, full ad and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_full_ad_and_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM encrypt, incomplete ad and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_ad_and_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM encrypt, overflow update NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_overflow_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM encrypt, incomplete update NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM encrypt, full update and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_full_update_and_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM encrypt, incomplete update and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_update_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM decrypt, overflow ad NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_overflow_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM decrypt, incomplete ad NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM decrypt, full ad and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_full_ad_and_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM decrypt, incomplete ad and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_ad_and_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM decrypt, overflow update NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16))
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_overflow_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM decrypt, incomplete update NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16))
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM decrypt, full update and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_full_update_and_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM decrypt, incomplete update and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_update_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM* encrypt, overflow ad NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_overflow_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM* encrypt, incomplete ad NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM* encrypt, full ad and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_full_ad_and_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM* encrypt, overflow update NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_overflow_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM* encrypt, incomplete ad and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_ad_and_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM* encrypt, incomplete update NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM* encrypt, full update and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_full_update_and_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM* encrypt, incomplete update and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_update_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM* decrypt, overflow ad NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_overflow_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM* decrypt, incomplete ad NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_ad:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM* decrypt, full ad and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_full_ad_and_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM* decrypt, incomplete ad and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_ad_and_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"a6f73242f2f227350c0277e4e72cdaa6"
+
+CCM* decrypt, overflow update NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_overflow_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM* decrypt, incomplete update NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_update:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM* decrypt, full update and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_full_update_and_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM* decrypt, incomplete update and overflow NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_incomplete_update_overflow:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM encrypt, instant finish NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+mbedtls_ccm_instant_finish:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98"
+
+CCM decrypt, instant finish NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+mbedtls_ccm_instant_finish:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98"
+
+CCM* encrypt, instant finish NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+mbedtls_ccm_instant_finish:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98"
+
+CCM* decrypt, instant finish NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+mbedtls_ccm_instant_finish:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98"
+
+CCM encrypt, instant finish AES-128 (P=0, N=13, A=0, T=16)
+mbedtls_ccm_instant_finish:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"54caf96ef6d448734700aadab50faf7a":"a3803e752ae849c910d8da36af"
+
+CCM decrypt, instant finish AES-128 (P=0, N=13, A=0, T=16)
+mbedtls_ccm_instant_finish:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_DECRYPT:"54caf96ef6d448734700aadab50faf7a":"a3803e752ae849c910d8da36af"
+
+CCM* encrypt, instant finish AES-128 (P=0, N=13, A=0, T=16)
+mbedtls_ccm_instant_finish:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_ENCRYPT:"54caf96ef6d448734700aadab50faf7a":"a3803e752ae849c910d8da36af"
+
+CCM* decrypt, instant finish AES-128 (P=0, N=13, A=0, T=16)
+mbedtls_ccm_instant_finish:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_STAR_DECRYPT:"54caf96ef6d448734700aadab50faf7a":"a3803e752ae849c910d8da36af"
+
+CCM pass unexpected auth data, NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+mbedtls_ccm_unexpected_ad::MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
+
+CCM encrypt, unexpected ciphertext/plaintext data, NIST VPT AES-128 #14 (P=13, N=13, A=32, T=16)
+depends_on:MBEDTLS_AES_C
+mbedtls_ccm_unexpected_text:MBEDTLS_CIPHER_ID_AES:MBEDTLS_CCM_ENCRYPT:"d32088d50df9aba14d9022c870a0cb85":"4b10788c1a03bca656f04f1f98":"e16c69861efc206e85aab1255e":"0eff7d7bcceb873c3203a8df74f4e91b04bd607ec11202f96cfeb99f5bcdb7aa"
diff --git a/tests/suites/test_suite_ccm.function b/tests/suites/test_suite_ccm.function
index 840583c..e48b1f9 100644
--- a/tests/suites/test_suite_ccm.function
+++ b/tests/suites/test_suite_ccm.function
@@ -1,5 +1,64 @@
 /* BEGIN_HEADER */
 #include "mbedtls/ccm.h"
+
+/* Use the multipart interface to process the encrypted data in two parts
+ * and check that the output matches the expected output.
+ * The context must have been set up with the key. */
+static int check_multipart( mbedtls_ccm_context *ctx,
+                            int mode,
+                            const data_t *iv,
+                            const data_t *add,
+                            const data_t *input,
+                            const data_t *expected_output,
+                            const data_t *tag,
+                            size_t n1,
+                            size_t n1_add)
+{
+    int ok = 0;
+    uint8_t *output = NULL;
+    size_t n2 = input->len - n1;
+    size_t n2_add = add->len - n1_add;
+    size_t olen;
+
+    /* Sanity checks on the test data */
+    TEST_ASSERT( n1 <= input->len );
+    TEST_ASSERT( n1_add <= add->len );
+    TEST_EQUAL( input->len, expected_output->len );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( ctx, mode, iv->x, iv->len ) );
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( ctx, add->len, input->len, tag->len ) );
+    TEST_EQUAL( 0, mbedtls_ccm_update_ad( ctx, add->x, n1_add) );
+    TEST_EQUAL( 0, mbedtls_ccm_update_ad( ctx, add->x + n1_add, n2_add ) );
+
+    /* Allocate a tight buffer for each update call. This way, if the function
+     * tries to write beyond the advertised required buffer size, this will
+     * count as an overflow for memory sanitizers and static checkers. */
+    ASSERT_ALLOC( output, n1 );
+    olen = 0xdeadbeef;
+    TEST_EQUAL( 0, mbedtls_ccm_update( ctx, input->x, n1, output, n1, &olen ) );
+    TEST_EQUAL( n1, olen );
+    ASSERT_COMPARE( output, olen, expected_output->x, n1 );
+    mbedtls_free( output );
+    output = NULL;
+
+    ASSERT_ALLOC( output, n2 );
+    olen = 0xdeadbeef;
+    TEST_EQUAL( 0, mbedtls_ccm_update( ctx, input->x + n1, n2, output, n2, &olen ) );
+    TEST_EQUAL( n2, olen );
+    ASSERT_COMPARE( output, olen, expected_output->x + n1, n2 );
+    mbedtls_free( output );
+    output = NULL;
+
+    ASSERT_ALLOC( output, tag->len );
+    TEST_EQUAL( 0, mbedtls_ccm_finish( ctx, output, tag->len ) );
+    ASSERT_COMPARE( output, tag->len, tag->x, tag->len );
+    mbedtls_free( output );
+    output = NULL;
+
+    ok = 1;
+exit:
+    mbedtls_free( output );
+    return( ok );
+}
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -122,71 +181,115 @@
                                   data_t * add, data_t * result )
 {
     mbedtls_ccm_context ctx;
-    size_t tag_len;
-    uint8_t * msg_n_tag = (uint8_t *)malloc( result->len + 2 );
+    size_t n1, n1_add;
+    uint8_t* io_msg_buf = NULL;
+    uint8_t* tag_buf = NULL;
+    const size_t expected_tag_len = result->len - msg->len;
+    const uint8_t* expected_tag = result->x + msg->len;
+
+    /* Prepare input/output message buffer */
+    ASSERT_ALLOC( io_msg_buf, msg->len );
+    if( msg->len != 0 )
+        memcpy( io_msg_buf, msg->x, msg->len );
+
+    /* Prepare tag buffer */
+    ASSERT_ALLOC( tag_buf, expected_tag_len );
 
     mbedtls_ccm_init( &ctx );
-
-    memset( msg_n_tag, 0, result->len + 2 );
-    memcpy( msg_n_tag, msg->x, msg->len );
-
-    tag_len = result->len - msg->len;
-
-    TEST_ASSERT( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ) == 0 );
-
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
     /* Test with input == output */
-    TEST_ASSERT( mbedtls_ccm_encrypt_and_tag( &ctx, msg->len, iv->x, iv->len, add->x, add->len,
-                 msg_n_tag, msg_n_tag, msg_n_tag + msg->len, tag_len ) == 0 );
+    TEST_EQUAL( mbedtls_ccm_encrypt_and_tag( &ctx, msg->len, iv->x, iv->len, add->x, add->len,
+                io_msg_buf, io_msg_buf, tag_buf, expected_tag_len ), 0);
 
-    TEST_ASSERT( memcmp( msg_n_tag, result->x, result->len ) == 0 );
+    ASSERT_COMPARE( io_msg_buf, msg->len, result->x, msg->len );
+    ASSERT_COMPARE( tag_buf, expected_tag_len, expected_tag, expected_tag_len );
 
-    /* Check we didn't write past the end */
-    TEST_ASSERT( msg_n_tag[result->len] == 0 && msg_n_tag[result->len + 1] == 0 );
+    /* Prepare data_t structures for multipart testing */
+    const data_t encrypted_expected = { .x = result->x,
+                                        .len = msg->len };
+    const data_t tag_expected = { .x = (uint8_t*) expected_tag, /* cast to conform with data_t x type */
+                                  .len = expected_tag_len };
+
+    for( n1 = 0; n1 <= msg->len; n1 += 1 )
+    {
+        for( n1_add = 0; n1_add <= add->len; n1_add += 1 )
+        {
+            mbedtls_test_set_step( n1 * 10000 + n1_add );
+            if( !check_multipart( &ctx, MBEDTLS_CCM_ENCRYPT,
+                                  iv, add, msg,
+                                  &encrypted_expected,
+                                  &tag_expected,
+                                  n1, n1_add ) )
+                goto exit;
+        }
+    }
 
 exit:
     mbedtls_ccm_free( &ctx );
-    free( msg_n_tag );
+    mbedtls_free( io_msg_buf );
+    mbedtls_free( tag_buf );
 }
 /* END_CASE */
 
 /* BEGIN_CASE */
 void mbedtls_ccm_auth_decrypt( int cipher_id, data_t * key,
                                data_t * msg, data_t * iv,
-                               data_t * add, int tag_len, int result,
+                               data_t * add, int expected_tag_len, int result,
                                data_t * expected_msg )
 {
-    unsigned char tag[16];
     mbedtls_ccm_context ctx;
+    size_t n1, n1_add;
+
+    const size_t expected_msg_len = msg->len - expected_tag_len;
+    const uint8_t* expected_tag = msg->x + expected_msg_len;
+
+    /* Prepare input/output message buffer */
+    uint8_t* io_msg_buf = NULL;
+    ASSERT_ALLOC( io_msg_buf, expected_msg_len );
+    if( expected_msg_len )
+        memcpy( io_msg_buf, msg->x, expected_msg_len );
 
     mbedtls_ccm_init( &ctx );
-
-    memset( tag, 0x00, sizeof( tag ) );
-
-    msg->len -= tag_len;
-    memcpy( tag, msg->x + msg->len, tag_len );
-
-    TEST_ASSERT( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ) == 0 );
-
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
     /* Test with input == output */
-    TEST_ASSERT( mbedtls_ccm_auth_decrypt( &ctx, msg->len, iv->x, iv->len, add->x, add->len,
-                 msg->x, msg->x, msg->x + msg->len, tag_len ) == result );
+    TEST_EQUAL( mbedtls_ccm_auth_decrypt( &ctx, expected_msg_len, iv->x, iv->len, add->x, add->len,
+                io_msg_buf, io_msg_buf, expected_tag, expected_tag_len ), result );
 
     if( result == 0 )
     {
-        TEST_ASSERT( memcmp( msg->x, expected_msg->x, expected_msg->len ) == 0 );
+        ASSERT_COMPARE( io_msg_buf, expected_msg_len, expected_msg->x, expected_msg_len );
+
+         /* Prepare data_t structures for multipart testing */
+        const data_t encrypted = { .x = msg->x,
+                                   .len = expected_msg_len };
+
+        const data_t tag_expected = { .x = (uint8_t*) expected_tag,
+                                      .len = expected_tag_len };
+
+        for( n1 = 0; n1 <= expected_msg_len; n1 += 1 )
+        {
+            for( n1_add = 0; n1_add <= add->len; n1_add += 1 )
+            {
+                mbedtls_test_set_step( n1 * 10000 + n1_add );
+                if( !check_multipart( &ctx, MBEDTLS_CCM_DECRYPT,
+                                iv, add, &encrypted,
+                                expected_msg,
+                                &tag_expected,
+                                n1, n1_add ) )
+                    goto exit;
+           }
+        }
     }
     else
     {
         size_t i;
 
-        for( i = 0; i < msg->len; i++ )
-            TEST_ASSERT( msg->x[i] == 0 );
+        for( i = 0; i < expected_msg_len; i++ )
+            TEST_EQUAL( io_msg_buf[i], 0 );
     }
 
-    /* Check we didn't write past the end (where the original tag is) */
-    TEST_ASSERT( memcmp( msg->x + msg->len, tag, tag_len ) == 0 );
-
 exit:
+    mbedtls_free(io_msg_buf);
     mbedtls_ccm_free( &ctx );
 }
 /* END_CASE */
@@ -199,20 +302,32 @@
                             data_t *expected_result, int output_ret )
 {
     unsigned char iv[13];
-    unsigned char result[50];
     mbedtls_ccm_context ctx;
-    size_t iv_len, tag_len;
-    int ret;
+    size_t iv_len, expected_tag_len;
+    size_t n1, n1_add;
+    uint8_t* io_msg_buf = NULL;
+    uint8_t* tag_buf = NULL;
 
-    mbedtls_ccm_init( &ctx );
+    const uint8_t* expected_tag = expected_result->x + msg->len;
 
-    memset( result, 0x00, sizeof( result ) );
-
+    /* Calculate tag length */
     if( sec_level % 4 == 0)
-        tag_len = 0;
+        expected_tag_len = 0;
     else
-        tag_len = 1 << ( sec_level % 4 + 1);
+        expected_tag_len = 1 << ( sec_level % 4 + 1);
 
+    /* Prepare input/output message buffer */
+    ASSERT_ALLOC( io_msg_buf, msg->len );
+    if( msg->len )
+        memcpy( io_msg_buf, msg->x, msg->len );
+
+    /* Prepare tag buffer */
+    if( expected_tag_len == 0 )
+        ASSERT_ALLOC( tag_buf, 16 );
+    else
+        ASSERT_ALLOC( tag_buf, expected_tag_len );
+
+    /* Calculate iv */
     TEST_ASSERT( source_address->len == 8 );
     TEST_ASSERT( frame_counter->len == 4 );
     memcpy( iv, source_address->x, source_address->len );
@@ -220,24 +335,46 @@
     iv[source_address->len + frame_counter->len] = sec_level;
     iv_len = sizeof( iv );
 
-    TEST_ASSERT( mbedtls_ccm_setkey( &ctx, cipher_id,
-                                     key->x, key->len * 8 ) == 0 );
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id,
+                                     key->x, key->len * 8 ), 0 );
+    /* Test with input == output */
+    TEST_EQUAL( mbedtls_ccm_star_encrypt_and_tag( &ctx, msg->len, iv, iv_len,
+                                            add->x, add->len, io_msg_buf,
+                                            io_msg_buf, tag_buf, expected_tag_len), output_ret );
 
-    ret = mbedtls_ccm_star_encrypt_and_tag( &ctx, msg->len, iv, iv_len,
-                                            add->x, add->len, msg->x,
-                                            result, result + msg->len, tag_len );
+    ASSERT_COMPARE( io_msg_buf, msg->len, expected_result->x, msg->len );
+    ASSERT_COMPARE( tag_buf, expected_tag_len, expected_tag, expected_tag_len );
 
-    TEST_ASSERT( ret == output_ret );
+    if( output_ret == 0 )
+    {
+        const data_t iv_data = { .x = iv,
+                                 .len = iv_len };
 
-    TEST_ASSERT( memcmp( result,
-                         expected_result->x, expected_result->len ) == 0 );
+        const data_t encrypted_expected = { .x = expected_result->x,
+                                            .len = msg->len };
+        const data_t tag_expected = { .x = (uint8_t*)expected_tag,
+                                      .len = expected_tag_len };
 
-    /* Check we didn't write past the end */
-    TEST_ASSERT( result[expected_result->len] == 0 &&
-                 result[expected_result->len + 1] == 0 );
+        for( n1 = 0; n1 <= msg->len; n1 += 1 )
+        {
+            for( n1_add = 0; n1_add <= add->len; n1_add += 1 )
+            {
+                mbedtls_test_set_step( n1 * 10000 + n1_add );
+                if( !check_multipart( &ctx, MBEDTLS_CCM_STAR_ENCRYPT,
+                                      &iv_data, add, msg,
+                                      &encrypted_expected,
+                                      &tag_expected,
+                                      n1, n1_add ) )
+                    goto exit;
+            }
+        }
+    }
 
 exit:
     mbedtls_ccm_free( &ctx );
+    mbedtls_free( io_msg_buf );
+    mbedtls_free( tag_buf );
 }
 /* END_CASE */
 
@@ -249,21 +386,27 @@
                             data_t *expected_result, int output_ret )
 {
     unsigned char iv[13];
-    unsigned char result[50];
     mbedtls_ccm_context ctx;
-    size_t iv_len, tag_len;
-    int ret;
+    size_t iv_len, expected_tag_len;
+    size_t n1, n1_add;
 
-    mbedtls_ccm_init( &ctx );
-
-    memset( iv, 0x00, sizeof( iv ) );
-    memset( result, '+', sizeof( result ) );
-
+    /* Calculate tag length */
     if( sec_level % 4 == 0)
-        tag_len = 0;
+        expected_tag_len = 0;
     else
-        tag_len = 1 << ( sec_level % 4 + 1);
+        expected_tag_len = 1 << ( sec_level % 4 + 1);
 
+    const size_t expected_msg_len = msg->len - expected_tag_len;
+    const uint8_t* expected_tag = msg->x + expected_msg_len;
+
+    /* Prepare input/output message buffer */
+    uint8_t* io_msg_buf = NULL;
+    ASSERT_ALLOC( io_msg_buf, expected_msg_len );
+    if( expected_msg_len )
+        memcpy( io_msg_buf, msg->x, expected_msg_len );
+
+    /* Calculate iv */
+    memset( iv, 0x00, sizeof( iv ) );
     TEST_ASSERT( source_address->len == 8 );
     TEST_ASSERT( frame_counter->len == 4 );
     memcpy( iv, source_address->x, source_address->len );
@@ -271,23 +414,405 @@
     iv[source_address->len + frame_counter->len] = sec_level;
     iv_len = sizeof( iv );
 
+    mbedtls_ccm_init( &ctx );
     TEST_ASSERT( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ) == 0 );
+    /* Test with input == output */
+    TEST_EQUAL( mbedtls_ccm_star_auth_decrypt( &ctx, expected_msg_len, iv, iv_len,
+                                         add->x, add->len, io_msg_buf, io_msg_buf,
+                                         expected_tag, expected_tag_len ), output_ret );
 
-    ret = mbedtls_ccm_star_auth_decrypt( &ctx, msg->len - tag_len, iv, iv_len,
-                                         add->x, add->len, msg->x, result,
-                                         msg->x + msg->len - tag_len, tag_len );
+    ASSERT_COMPARE( io_msg_buf, expected_msg_len, expected_result->x, expected_msg_len );
 
-    TEST_ASSERT( ret == output_ret );
+    if( output_ret == 0 )
+    {
+        const data_t iv_data = { .x = iv,
+                                 .len = iv_len };
 
-    TEST_ASSERT( memcmp( result, expected_result->x,
-                                 expected_result->len ) == 0 );
+        const data_t encrypted = { .x = msg->x,
+                                   .len = expected_msg_len} ;
 
-    /* Check we didn't write past the end (where the original tag is) */
-    TEST_ASSERT( ( msg->len + 2 ) <= sizeof( result ) );
-    TEST_EQUAL( result[msg->len], '+' );
-    TEST_EQUAL( result[msg->len + 1], '+' );
+        const data_t tag_expected = { .x = (uint8_t*) expected_tag,
+                                      .len = expected_tag_len };
+
+        for( n1 = 0; n1 <= expected_msg_len; n1 += 1 )
+        {
+            for( n1_add = 0; n1_add <= add->len; n1_add += 1 )
+            {
+                mbedtls_test_set_step( n1 * 10000 + n1_add );
+                if( !check_multipart( &ctx, MBEDTLS_CCM_STAR_DECRYPT,
+                                &iv_data, add, &encrypted,
+                                expected_result,
+                                &tag_expected,
+                                n1, n1_add ) )
+                    goto exit;
+           }
+        }
+    }
 
 exit:
     mbedtls_ccm_free( &ctx );
+    mbedtls_free( io_msg_buf );
+}
+/* END_CASE */
+
+/* Skip auth data, provide full text */
+/* BEGIN_CASE */
+void mbedtls_ccm_skip_ad( int cipher_id, int mode,
+                            data_t * key, data_t * msg, data_t * iv,
+                            data_t * result, data_t * tag )
+{
+    mbedtls_ccm_context ctx;
+    uint8_t *output = NULL;
+    size_t olen;
+
+    /* Sanity checks on the test data */
+    TEST_EQUAL( msg->len, result->len );
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, 0, msg->len, tag->len ) );
+
+    ASSERT_ALLOC( output, result->len );
+    olen = 0xdeadbeef;
+    TEST_EQUAL( 0, mbedtls_ccm_update( &ctx, msg->x, msg->len, output, result->len, &olen ) );
+    TEST_EQUAL( result->len, olen );
+    ASSERT_COMPARE( output, olen, result->x, result->len );
+    mbedtls_free( output );
+    output = NULL;
+
+    ASSERT_ALLOC( output, tag->len );
+    TEST_EQUAL( 0, mbedtls_ccm_finish( &ctx, output, tag->len ) );
+    ASSERT_COMPARE( output, tag->len, tag->x, tag->len );
+    mbedtls_free( output );
+    output = NULL;
+
+exit:
+    mbedtls_free( output );
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* Provide auth data, skip full text */
+/* BEGIN_CASE */
+void mbedtls_ccm_skip_update( int cipher_id, int mode,
+                              data_t * key, data_t * iv, data_t* add,
+                              data_t * tag )
+{
+    mbedtls_ccm_context ctx;
+    uint8_t *output = NULL;
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, add->len, 0, tag->len ) );
+
+    TEST_EQUAL( 0, mbedtls_ccm_update_ad( &ctx, add->x, add->len) );
+
+    ASSERT_ALLOC( output, tag->len );
+    TEST_EQUAL( 0, mbedtls_ccm_finish( &ctx, output, tag->len ) );
+    ASSERT_COMPARE( output, tag->len, tag->x, tag->len );
+    mbedtls_free( output );
+    output = NULL;
+
+exit:
+    mbedtls_free( output );
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* Provide too much auth data */
+/* BEGIN_CASE */
+void mbedtls_ccm_overflow_ad( int cipher_id, int mode,
+                                 data_t * key, data_t * iv,
+                                 data_t * add )
+{
+    mbedtls_ccm_context ctx;
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    // use hardcoded values for msg length and tag length. They are not a part of this test
+    // subtract 1 from configured auth data length to provoke an overflow
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, add->len - 1, 16, 16 ) );
+
+    TEST_EQUAL( MBEDTLS_ERR_CCM_BAD_INPUT, mbedtls_ccm_update_ad( &ctx, add->x, add->len) );
+exit:
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* Provide unexpected auth data */
+/* BEGIN_CASE */
+void mbedtls_ccm_unexpected_ad( int cipher_id, int mode,
+                                 data_t * key, data_t * iv,
+                                 data_t * add )
+{
+    mbedtls_ccm_context ctx;
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    // use hardcoded values for msg length and tag length. They are not a part of this test
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, 0, 16, 16 ) );
+
+    TEST_EQUAL( MBEDTLS_ERR_CCM_BAD_INPUT, mbedtls_ccm_update_ad( &ctx, add->x, add->len) );
+exit:
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* Provide unexpected plaintext/ciphertext data */
+/* BEGIN_CASE */
+void mbedtls_ccm_unexpected_text( int cipher_id, int mode,
+                                  data_t * key, data_t * msg, data_t * iv,
+                                  data_t * add )
+{
+    mbedtls_ccm_context ctx;
+    uint8_t *output = NULL;
+    size_t olen;
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    // use hardcoded value for tag length. It is not a part of this test
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, add->len, 0, 16 ) );
+
+    TEST_EQUAL( 0, mbedtls_ccm_update_ad( &ctx, add->x, add->len) );
+
+    ASSERT_ALLOC( output, msg->len );
+    olen = 0xdeadbeef;
+    TEST_EQUAL( MBEDTLS_ERR_CCM_BAD_INPUT, mbedtls_ccm_update( &ctx, msg->x, msg->len, output, msg->len, &olen ) );
+exit:
+    mbedtls_free( output );
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* Provide incomplete auth data and finish */
+/* BEGIN_CASE */
+void mbedtls_ccm_incomplete_ad( int cipher_id, int mode,
+                                data_t * key, data_t * iv, data_t* add )
+{
+    mbedtls_ccm_context ctx;
+    uint8_t *output = NULL;
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    // use hardcoded values for msg length and tag length. They are not a part of this test
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, add->len, 0, 16 ) );
+
+    TEST_EQUAL( 0, mbedtls_ccm_update_ad( &ctx, add->x, add->len - 1) );
+
+    ASSERT_ALLOC( output, 16 );
+    TEST_EQUAL( MBEDTLS_ERR_CCM_BAD_INPUT, mbedtls_ccm_finish( &ctx, output, 16 ) );
+
+exit:
+    mbedtls_free( output );
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* Provide complete auth data on first update_ad.
+ * Provide unexpected auth data on second update_ad */
+/* BEGIN_CASE */
+void mbedtls_ccm_full_ad_and_overflow( int cipher_id, int mode,
+                                       data_t * key, data_t * iv,
+                                       data_t * add )
+{
+    mbedtls_ccm_context ctx;
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    // use hardcoded values for msg length and tag length. They are not a part of this test
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, add->len, 16, 16 ) );
+
+    // pass full auth data
+    TEST_EQUAL( 0, mbedtls_ccm_update_ad( &ctx, add->x, add->len) );
+    // pass 1 extra byte
+    TEST_EQUAL( MBEDTLS_ERR_CCM_BAD_INPUT, mbedtls_ccm_update_ad( &ctx, add->x, 1) );
+exit:
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* Provide incomplete auth data on first update_ad.
+ * Provide too much auth data on second update_ad */
+/* BEGIN_CASE */
+void mbedtls_ccm_incomplete_ad_and_overflow( int cipher_id, int mode,
+                                             data_t * key, data_t * iv,
+                                             data_t * add )
+{
+    mbedtls_ccm_context ctx;
+    uint8_t add_second_buffer[2];
+
+    add_second_buffer[0] = add->x[ add->len - 1 ];
+    add_second_buffer[1] = 0xAB; // some magic value
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    // use hardcoded values for msg length and tag length. They are not a part of this test
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, add->len, 16, 16 ) );
+
+    // pass incomplete auth data
+    TEST_EQUAL( 0, mbedtls_ccm_update_ad( &ctx, add->x, add->len - 1) );
+    // pass 2 extra bytes (1 missing byte from previous incomplete pass, and 1 unexpected byte)
+    TEST_EQUAL( MBEDTLS_ERR_CCM_BAD_INPUT, mbedtls_ccm_update_ad( &ctx, add_second_buffer, 2) );
+exit:
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* Provide too much plaintext/ciphertext */
+/* BEGIN_CASE */
+void mbedtls_ccm_overflow_update( int cipher_id, int mode,
+                                  data_t * key, data_t * msg, data_t * iv,
+                                  data_t * add )
+{
+    mbedtls_ccm_context ctx;
+    uint8_t *output = NULL;
+    size_t olen;
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    // use hardcoded value for tag length. It is a not a part of this test
+    // subtract 1 from configured msg length to provoke an overflow
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, add->len, msg->len - 1, 16 ) );
+
+    TEST_EQUAL( 0, mbedtls_ccm_update_ad( &ctx, add->x, add->len) );
+
+    ASSERT_ALLOC( output, msg->len );
+    TEST_EQUAL( MBEDTLS_ERR_CCM_BAD_INPUT, \
+                mbedtls_ccm_update( &ctx, msg->x, msg->len, output, msg->len, &olen ) );
+exit:
+    mbedtls_free( output );
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* Provide incomplete plaintext/ciphertext and finish */
+/* BEGIN_CASE */
+void mbedtls_ccm_incomplete_update( int cipher_id, int mode,
+                                    data_t * key, data_t * msg, data_t * iv,
+                                    data_t * add )
+{
+    mbedtls_ccm_context ctx;
+    uint8_t *output = NULL;
+    size_t olen;
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    // use hardcoded value for tag length. It is not a part of this test
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, add->len, msg->len, 16 ) );
+
+    TEST_EQUAL( 0, mbedtls_ccm_update_ad( &ctx, add->x, add->len) );
+
+    ASSERT_ALLOC( output, msg->len );
+    olen = 0xdeadbeef;
+    TEST_EQUAL( 0, mbedtls_ccm_update( &ctx, msg->x, msg->len - 1, output, msg->len, &olen ) );
+    mbedtls_free( output );
+    output = NULL;
+
+    ASSERT_ALLOC( output, 16 );
+    TEST_EQUAL( MBEDTLS_ERR_CCM_BAD_INPUT, mbedtls_ccm_finish( &ctx, output, 16 ) );
+
+exit:
+    mbedtls_free( output );
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* Provide full plaintext/ciphertext of first update
+ * Provide unexpected plaintext/ciphertext on second update */
+/* BEGIN_CASE */
+void mbedtls_ccm_full_update_and_overflow( int cipher_id, int mode,
+                                           data_t * key, data_t * msg, data_t * iv,
+                                           data_t * add )
+{
+    mbedtls_ccm_context ctx;
+    uint8_t *output = NULL;
+    size_t olen;
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    // use hardcoded value for tag length. It is a not a part of this test
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, add->len, msg->len, 16 ) );
+
+    TEST_EQUAL( 0, mbedtls_ccm_update_ad( &ctx, add->x, add->len) );
+
+    ASSERT_ALLOC( output, msg->len );
+    // pass full text
+    TEST_EQUAL( 0, mbedtls_ccm_update( &ctx, msg->x, msg->len, output, msg->len, &olen ) );
+    // pass 1 extra byte
+    TEST_EQUAL( MBEDTLS_ERR_CCM_BAD_INPUT, \
+                mbedtls_ccm_update( &ctx, msg->x, 1, output, 1, &olen ) );
+exit:
+    mbedtls_free( output );
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* Provide incomplete plaintext/ciphertext of first update
+ * Provide too much plaintext/ciphertext on second update */
+/* BEGIN_CASE */
+void mbedtls_ccm_incomplete_update_overflow( int cipher_id, int mode,
+                                             data_t * key, data_t * msg, data_t * iv,
+                                             data_t * add )
+{
+    mbedtls_ccm_context ctx;
+    uint8_t *output = NULL;
+    size_t olen;
+    uint8_t msg_second_buffer[2];
+
+    msg_second_buffer[0] = msg->x[ msg->len - 1 ];
+    msg_second_buffer[1] = 0xAB; // some magic value
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    // use hardcoded value for tag length. It is a not a part of this test
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, add->len, msg->len, 16 ) );
+
+    TEST_EQUAL( 0, mbedtls_ccm_update_ad( &ctx, add->x, add->len) );
+
+    ASSERT_ALLOC( output, msg->len + 1 );
+    // pass incomplete text
+    TEST_EQUAL( 0, mbedtls_ccm_update( &ctx, msg->x, msg->len - 1, output, msg->len + 1, &olen ) );
+    // pass 2 extra bytes (1 missing byte from previous incomplete pass, and 1 unexpected byte)
+    TEST_EQUAL( MBEDTLS_ERR_CCM_BAD_INPUT, \
+                mbedtls_ccm_update( &ctx, msg_second_buffer, 2, output +  msg->len - 1, 2, &olen ) );
+exit:
+    mbedtls_free( output );
+    mbedtls_ccm_free( &ctx );
+}
+/* END_CASE */
+
+/* Finish without passing any auth data or plaintext/ciphertext input */
+/* BEGIN_CASE */
+void mbedtls_ccm_instant_finish( int cipher_id, int mode,
+                                 data_t * key, data_t * iv )
+{
+    mbedtls_ccm_context ctx;
+    uint8_t *output = NULL;
+
+    mbedtls_ccm_init( &ctx );
+    TEST_EQUAL( mbedtls_ccm_setkey( &ctx, cipher_id, key->x, key->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_ccm_starts( &ctx, mode, iv->x, iv->len ) );
+    // use hardcoded values for add length, msg length and tag length.
+    // They are not a part of this test
+    TEST_EQUAL( 0, mbedtls_ccm_set_lengths( &ctx, 16, 16, 16 ) );
+
+    ASSERT_ALLOC( output, 16 );
+    TEST_EQUAL( MBEDTLS_ERR_CCM_BAD_INPUT, mbedtls_ccm_finish( &ctx, output, 16 ) );
+
+exit:
+    mbedtls_free( output );
+    mbedtls_ccm_free( &ctx );
 }
 /* END_CASE */
diff --git a/tests/suites/test_suite_cipher.aes.data b/tests/suites/test_suite_cipher.aes.data
index 4dbdd52..c8fbca2 100644
--- a/tests/suites/test_suite_cipher.aes.data
+++ b/tests/suites/test_suite_cipher.aes.data
@@ -1798,6 +1798,102 @@
 depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC
 test_vec_crypt:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"5c9d844ed46f9885085e5d6a4f94c7d7":"014730f80ac625fe84f026c60bfd547d":0:1
 
+AES-128-ECB crypt Encrypt NIST KAT #1 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_ENCRYPT:"00000000000000000000000000000000":"":"80000000000000000000000000000000":"3ad78e726c1ec02b7ebfe92b23d9ec34":0:1
+
+AES-128-ECB crypt Encrypt NIST KAT #2 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_ENCRYPT:"ffffffffffffffffffffffffffffe000":"":"00000000000000000000000000000000":"323994cfb9da285a5d9642e1759b224a":0:1
+
+AES-128-ECB crypt Encrypt NIST KAT #3 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_ENCRYPT:"10a58869d74be5a374cf867cfb473859":"":"00000000000000000000000000000000":"6d251e6944b051e04eaa6fb4dbf78465":0:1
+
+AES-128-ECB crypt Encrypt NIST KAT #4 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_ENCRYPT:"00000000000000000000000000000000":"":"f34481ec3cc627bacd5dc3fb08f273e6":"0336763e966d92595a567cc9ce537f5e":0:1
+
+AES-128-ECB crypt Decrypt NIST KAT #1 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_DECRYPT:"00000000000000000000000000000000":"":"3ad78e726c1ec02b7ebfe92b23d9ec34":"80000000000000000000000000000000":0:1
+
+AES-128-ECB crypt Decrypt NIST KAT #2 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_DECRYPT:"ffffc000000000000000000000000000":"":"df556a33438db87bc41b1752c55e5e49":"00000000000000000000000000000000":0:1
+
+AES-128-ECB crypt Decrypt NIST KAT #3 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_DECRYPT:"10a58869d74be5a374cf867cfb473859":"":"6d251e6944b051e04eaa6fb4dbf78465":"00000000000000000000000000000000":0:1
+
+AES-128-ECB crypt Decrypt NIST KAT #4 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_128_ECB:MBEDTLS_DECRYPT:"00000000000000000000000000000000":"":"0336763e966d92595a567cc9ce537f5e":"f34481ec3cc627bacd5dc3fb08f273e6":0:1
+
+AES-192-ECB crypt Encrypt NIST KAT #1 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_ENCRYPT:"000000000000000000000000000000000000000000000000":"":"80000000000000000000000000000000":"6cd02513e8d4dc986b4afe087a60bd0c":0:1
+
+AES-192-ECB crypt Encrypt NIST KAT #2 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_ENCRYPT:"ff0000000000000000000000000000000000000000000000":"":"00000000000000000000000000000000":"833f71258d53036b02952c76c744f5a1":0:1
+
+AES-192-ECB crypt Encrypt NIST KAT #3 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_ENCRYPT:"e9f065d7c13573587f7875357dfbb16c53489f6a4bd0f7cd":"":"00000000000000000000000000000000":"0956259c9cd5cfd0181cca53380cde06":0:1
+
+AES-192-ECB crypt Encrypt NIST KAT #4 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_ENCRYPT:"000000000000000000000000000000000000000000000000":"":"1b077a6af4b7f98229de786d7516b639":"275cfc0413d8ccb70513c3859b1d0f72":0:1
+
+AES-192-ECB crypt Decrypt NIST KAT #1 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_DECRYPT:"000000000000000000000000000000000000000000000000":"":"6cd02513e8d4dc986b4afe087a60bd0c":"80000000000000000000000000000000":0:1
+
+AES-192-ECB crypt Decrypt NIST KAT #2 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_DECRYPT:"ffe000000000000000000000000000000000000000000000":"":"7ababc4b3f516c9aafb35f4140b548f9":"00000000000000000000000000000000":0:1
+
+AES-192-ECB crypt Decrypt NIST KAT #3 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_DECRYPT:"e9f065d7c13573587f7875357dfbb16c53489f6a4bd0f7cd":"":"0956259c9cd5cfd0181cca53380cde06":"00000000000000000000000000000000":0:1
+
+AES-192-ECB crypt Decrypt NIST KAT #4 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_192_ECB:MBEDTLS_DECRYPT:"000000000000000000000000000000000000000000000000":"":"275cfc0413d8ccb70513c3859b1d0f72":"1b077a6af4b7f98229de786d7516b639":0:1
+
+AES-256-ECB crypt Encrypt NIST KAT #1 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"":"80000000000000000000000000000000":"ddc6bf790c15760d8d9aeb6f9a75fd4e":0:1
+
+AES-256-ECB crypt Encrypt NIST KAT #2 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_ENCRYPT:"ff00000000000000000000000000000000000000000000000000000000000000":"":"00000000000000000000000000000000":"ec52a212f80a09df6317021bc2a9819e":0:1
+
+AES-256-ECB crypt Encrypt NIST KAT #3 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_ENCRYPT:"c47b0294dbbbee0fec4757f22ffeee3587ca4730c3d33b691df38bab076bc558":"":"00000000000000000000000000000000":"46f2fb342d6f0ab477476fc501242c5f":0:1
+
+AES-256-ECB crypt Encrypt NIST KAT #4 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"":"014730f80ac625fe84f026c60bfd547d":"5c9d844ed46f9885085e5d6a4f94c7d7":0:1
+
+AES-256-ECB crypt Decrypt NIST KAT #1 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"":"ddc6bf790c15760d8d9aeb6f9a75fd4e":"80000000000000000000000000000000":0:1
+
+AES-256-ECB crypt Decrypt NIST KAT #2 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"ffe0000000000000000000000000000000000000000000000000000000000000":"":"d1ccb9b1337002cbac42c520b5d67722":"00000000000000000000000000000000":0:1
+
+AES-256-ECB crypt Decrypt NIST KAT #3 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"c47b0294dbbbee0fec4757f22ffeee3587ca4730c3d33b691df38bab076bc558":"":"46f2fb342d6f0ab477476fc501242c5f":"00000000000000000000000000000000":0:1
+
+AES-256-ECB crypt Decrypt NIST KAT #4 PSA
+depends_on:MBEDTLS_USE_PSA_CRYPTO:MBEDTLS_AES_C
+test_vec_crypt:MBEDTLS_CIPHER_AES_256_ECB:MBEDTLS_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"":"5c9d844ed46f9885085e5d6a4f94c7d7":"014730f80ac625fe84f026c60bfd547d":0:1
+
 Cipher Corner Case behaviours
 depends_on:MBEDTLS_AES_C
 cipher_special_behaviours:
diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function
index 674349f..c809d9a 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -13,6 +13,59 @@
 #define MBEDTLS_CIPHER_AUTH_CRYPT
 #endif
 
+/* Check the internal consistency of a cipher info structure, and
+ * check it against mbedtls_cipher_info_from_xxx(). */
+static int check_cipher_info( mbedtls_cipher_type_t type,
+                              const mbedtls_cipher_info_t *info )
+{
+    size_t key_bitlen;
+
+    TEST_ASSERT( info != NULL );
+    TEST_EQUAL( type, mbedtls_cipher_info_get_type( info ) );
+    TEST_EQUAL( type, info->type );
+    TEST_ASSERT( mbedtls_cipher_info_from_type( type ) == info );
+
+    TEST_EQUAL( info->mode, mbedtls_cipher_info_get_mode( info ) );
+
+    /* Insist that get_name() return the string from the structure and
+     * not a copy. A copy would have an unknown storage duration. */
+    TEST_ASSERT( mbedtls_cipher_info_get_name( info ) == info->name );
+    TEST_ASSERT( mbedtls_cipher_info_from_string( info->name ) == info );
+
+    key_bitlen = mbedtls_cipher_info_get_key_bitlen( info );
+    if( info->type == MBEDTLS_CIPHER_NULL )
+        TEST_ASSERT( key_bitlen == 0 );
+    else if( info->mode == MBEDTLS_MODE_XTS )
+    {
+        TEST_ASSERT( key_bitlen == 256 ||
+                     key_bitlen == 384 ||
+                     key_bitlen == 512 );
+    }
+    else if( ! strncmp( info->name, "DES-EDE3-", 9 ) )
+    {
+        TEST_ASSERT( key_bitlen == 192 );
+    }
+    else if( ! strncmp( info->name, "DES-EDE-", 8 ) )
+    {
+        TEST_ASSERT( key_bitlen == 128 );
+    }
+    else if( ! strncmp( info->name, "DES-", 4 ) )
+    {
+        TEST_ASSERT( key_bitlen == 64 );
+    }
+    else
+    {
+        TEST_ASSERT( key_bitlen == 128 ||
+                     key_bitlen == 192 ||
+                     key_bitlen == 256 );
+    }
+
+    return( 1 );
+
+exit:
+    return( 0 );
+}
+
 #if defined(MBEDTLS_CIPHER_AUTH_CRYPT)
 /* Helper for resetting key/direction
  *
@@ -81,7 +134,13 @@
     const int *cipher_type;
 
     for( cipher_type = mbedtls_cipher_list(); *cipher_type != 0; cipher_type++ )
-        TEST_ASSERT( mbedtls_cipher_info_from_type( *cipher_type ) != NULL );
+    {
+        const mbedtls_cipher_info_t *info =
+            mbedtls_cipher_info_from_type( *cipher_type );
+        mbedtls_test_set_step( *cipher_type );
+        if( ! check_cipher_info( *cipher_type, info ) )
+            goto exit;
+    }
 }
 /* END_CASE */
 
@@ -309,6 +368,8 @@
     cipher_info = mbedtls_cipher_info_from_type( cipher_id );
     TEST_ASSERT( NULL != cipher_info );
     TEST_ASSERT( mbedtls_cipher_info_from_string( cipher_string ) == cipher_info );
+    TEST_ASSERT( strcmp( mbedtls_cipher_info_get_name( cipher_info ),
+                         cipher_string ) == 0 );
 
     /* Initialise enc and dec contexts */
     TEST_ASSERT( 0 == mbedtls_cipher_setup( &ctx_dec, cipher_info ) );
diff --git a/tests/suites/test_suite_des.function b/tests/suites/test_suite_des.function
index 5b24935..7256fb5 100644
--- a/tests/suites/test_suite_des.function
+++ b/tests/suites/test_suite_des.function
@@ -24,7 +24,7 @@
     mbedtls_des_init( &ctx );
 
 
-    mbedtls_des_setkey_enc( &ctx, key_str->x );
+    TEST_ASSERT( mbedtls_des_setkey_enc( &ctx, key_str->x ) == 0 );
     TEST_ASSERT( mbedtls_des_crypt_ecb( &ctx, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x, 8, dst->len ) == 0 );
@@ -44,7 +44,7 @@
     mbedtls_des_init( &ctx );
 
 
-    mbedtls_des_setkey_dec( &ctx, key_str->x );
+    TEST_ASSERT( mbedtls_des_setkey_dec( &ctx, key_str->x ) == 0 );
     TEST_ASSERT( mbedtls_des_crypt_ecb( &ctx, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x, 8, dst->len ) == 0 );
@@ -65,7 +65,7 @@
     mbedtls_des_init( &ctx );
 
 
-    mbedtls_des_setkey_enc( &ctx, key_str->x );
+    TEST_ASSERT( mbedtls_des_setkey_enc( &ctx, key_str->x ) == 0 );
     TEST_ASSERT( mbedtls_des_crypt_cbc( &ctx, MBEDTLS_DES_ENCRYPT, src_str->len, iv_str->x, src_str->x, output ) == cbc_result );
     if( cbc_result == 0 )
     {
@@ -91,7 +91,7 @@
     mbedtls_des_init( &ctx );
 
 
-    mbedtls_des_setkey_dec( &ctx, key_str->x );
+    TEST_ASSERT( mbedtls_des_setkey_dec( &ctx, key_str->x ) == 0 );
     TEST_ASSERT( mbedtls_des_crypt_cbc( &ctx, MBEDTLS_DES_DECRYPT, src_str->len, iv_str->x, src_str->x, output ) == cbc_result );
     if( cbc_result == 0 )
     {
@@ -117,9 +117,9 @@
 
 
     if( key_count == 2 )
-        mbedtls_des3_set2key_enc( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set2key_enc( &ctx, key_str->x ) == 0 );
     else if( key_count == 3 )
-        mbedtls_des3_set3key_enc( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set3key_enc( &ctx, key_str->x ) == 0 );
     else
         TEST_ASSERT( 0 );
 
@@ -144,9 +144,9 @@
 
 
     if( key_count == 2 )
-        mbedtls_des3_set2key_dec( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set2key_dec( &ctx, key_str->x ) == 0 );
     else if( key_count == 3 )
-        mbedtls_des3_set3key_dec( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set3key_dec( &ctx, key_str->x ) == 0 );
     else
         TEST_ASSERT( 0 );
 
@@ -172,9 +172,9 @@
 
 
     if( key_count == 2 )
-        mbedtls_des3_set2key_enc( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set2key_enc( &ctx, key_str->x ) == 0 );
     else if( key_count == 3 )
-        mbedtls_des3_set3key_enc( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set3key_enc( &ctx, key_str->x ) == 0 );
     else
         TEST_ASSERT( 0 );
 
@@ -205,9 +205,9 @@
 
 
     if( key_count == 2 )
-        mbedtls_des3_set2key_dec( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set2key_dec( &ctx, key_str->x ) == 0 );
     else if( key_count == 3 )
-        mbedtls_des3_set3key_dec( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set3key_dec( &ctx, key_str->x ) == 0 );
     else
         TEST_ASSERT( 0 );
 
diff --git a/tests/suites/test_suite_gcm.aes128_de.data b/tests/suites/test_suite_gcm.aes128_de.data
index 3df31e5..ede6f24 100644
--- a/tests/suites/test_suite_gcm.aes128_de.data
+++ b/tests/suites/test_suite_gcm.aes128_de.data
@@ -726,6 +726,10 @@
 depends_on:MBEDTLS_AES_C
 gcm_bad_parameters:MBEDTLS_CIPHER_ID_AES:MBEDTLS_GCM_DECRYPT:"d0194b6ee68f0ed8adc4b22ed15dbf14":"":"":"":32:MBEDTLS_ERR_GCM_BAD_INPUT
 
+AES-GCM, output buffer too small, NIST Validation (AES-128,128,1024,0,128) #0
+depends_on:MBEDTLS_AES_C
+gcm_update_output_buffer_too_small:MBEDTLS_CIPHER_ID_AES:MBEDTLS_GCM_DECRYPT:"0dd358bc3f992f26e81e3a2f3aa2d517":"87cc4fd75788c9d5cc83bae5d764dd249d178ab23224049795d4288b5ed9ea3f317068a39a7574b300c8544226e87b08e008fbe241d094545c211d56ac44437d41491a438272738968c8d371aa7787b5f606c8549a9d868d8a71380e9657d3c0337979feb01de5991fc1470dfc59eb02511efbbff3fcb479a862ba3844a25aaa":"d8c750bb443ee1a169dfe97cfe4d855b"
+
 AES-GCM Selftest
 depends_on:MBEDTLS_AES_C
 gcm_selftest:
diff --git a/tests/suites/test_suite_gcm.aes128_en.data b/tests/suites/test_suite_gcm.aes128_en.data
index d60c458..273642c 100644
--- a/tests/suites/test_suite_gcm.aes128_en.data
+++ b/tests/suites/test_suite_gcm.aes128_en.data
@@ -726,6 +726,9 @@
 depends_on:MBEDTLS_AES_C
 gcm_bad_parameters:MBEDTLS_CIPHER_ID_AES:MBEDTLS_GCM_ENCRYPT:"d0194b6ee68f0ed8adc4b22ed15dbf14":"":"":"":32:MBEDTLS_ERR_GCM_BAD_INPUT
 
+AES-GCM, output buffer too small, NIST Validation (AES-128,128,1024,0,128) #0
+gcm_update_output_buffer_too_small:MBEDTLS_CIPHER_ID_AES:MBEDTLS_GCM_ENCRYPT:"ce0f8cfe9d64c4f4c045d11b97c2d918":"dfff250d380f363880963b42d6913c1ba11e8edf7c4ab8b76d79ccbaac628f548ee542f48728a9a2620a0d69339c8291e8d398440d740e310908cdee7c273cc91275ce7271ba12f69237998b07b789b3993aaac8dc4ec1914432a30f5172f79ea0539bd1f70b36d437e5170bc63039a5280816c05e1e41760b58e35696cebd55":"ad4c3627a494fc628316dc03faf81db8"
+
 AES-GCM Selftest
 depends_on:MBEDTLS_AES_C
 gcm_selftest:
diff --git a/tests/suites/test_suite_gcm.function b/tests/suites/test_suite_gcm.function
index c530e6b..5696679 100644
--- a/tests/suites/test_suite_gcm.function
+++ b/tests/suites/test_suite_gcm.function
@@ -431,6 +431,29 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE */
+void gcm_update_output_buffer_too_small( int cipher_id, int mode,
+                                         data_t * key_str, const data_t *input,
+                                         const data_t *iv )
+{
+    mbedtls_gcm_context ctx;
+    uint8_t *output = NULL;
+    size_t olen = 0;
+    size_t output_len = input->len - 1;
+
+    mbedtls_gcm_init( &ctx );
+    TEST_EQUAL( mbedtls_gcm_setkey( &ctx, cipher_id, key_str->x, key_str->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_gcm_starts( &ctx, mode, iv->x, iv->len ) );
+
+    ASSERT_ALLOC( output, output_len );
+    TEST_EQUAL( MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL, mbedtls_gcm_update( &ctx, input->x, input->len, output, output_len, &olen ) );
+
+exit:
+    mbedtls_free( output );
+    mbedtls_gcm_free( &ctx );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
 void gcm_selftest(  )
 {
diff --git a/tests/suites/test_suite_net.function b/tests/suites/test_suite_net.function
index f429fc9..513b723 100644
--- a/tests/suites/test_suite_net.function
+++ b/tests/suites/test_suite_net.function
@@ -9,11 +9,11 @@
 #endif
 
 #if defined(MBEDTLS_PLATFORM_IS_UNIXLIKE)
-#include <sys/fcntl.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <fcntl.h>
 #include <unistd.h>
 #endif
 
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index d9eafc0..820bed7 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -2482,6 +2482,22 @@
 depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 18 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
 
+PSA AEAD decrypt: AES-CCM, invalid nonce length 6
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c090693056":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD decrypt: AES-CCM, invalid nonce length 14
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_CCM:"48c0906930561e0ab0ef4cd97200":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD decrypt: AES-CCM_8, invalid nonce length 6
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 8 ):"48c090693056":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD decrypt: AES-CCM_8, invalid nonce length 14
+depends_on:PSA_WANT_ALG_CCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"4189351B5CAEA375A0299E81C621BF43":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 8 ):"48c0906930561e0ab0ef4cd97200":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_NOT_SUPPORTED
+
 PSA AEAD encrypt/decrypt, AES-GCM, 19 bytes #1
 depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":PSA_ALG_GCM:"000102030405060708090A0B0C0D0E0F":"000102030405060708090A0B":"0C0D0E0F101112131415161718191A1B1C1D1E":PSA_SUCCESS
@@ -2634,6 +2650,14 @@
 depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 2 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
 
+PSA AEAD decrypt: AES-GCM, nonce=0 (bad)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD decrypt: AES-GCM, nonce=0 (bad), TAG=12
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 12 ):"":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"":PSA_ERROR_NOT_SUPPORTED
+
 PSA AEAD decrypt: AES-GCM, invalid tag length 18
 depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
 aead_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 18 ):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"4535d12b4377928a7c0a61c9f825a48671ea05910748c8ef":PSA_ERROR_INVALID_ARGUMENT
@@ -2738,6 +2762,18 @@
 depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
 aead_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"":"a0784d7a4716f3feb4f64e7f4b39bf04":"":PSA_SUCCESS
 
+PSA AEAD decrypt: ChaCha20-Poly1305 (nonce=8, not supported)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"0700000040414243":"":"a0784d7a4716f3feb4f64e7f4b39bf04":"":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD decrypt: ChaCha20-Poly1305 (nonce=11, too short)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"0700000040414243444546":"":"a0784d7a4716f3feb4f64e7f4b39bf04":"":PSA_ERROR_NOT_SUPPORTED
+
+PSA AEAD decrypt: ChaCha20-Poly1305 (nonce=13, too long)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"07000000404142434445464700":"":"a0784d7a4716f3feb4f64e7f4b39bf04":"":PSA_ERROR_NOT_SUPPORTED
+
 PSA AEAD encrypt/decrypt: invalid algorithm (CTR)
 depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
 aead_encrypt_decrypt:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CTR:"000102030405060708090A0B0C0D0E0F":"":"":PSA_ERROR_NOT_SUPPORTED
@@ -2746,6 +2782,614 @@
 depends_on:MBEDTLS_CHACHA20_C
 aead_encrypt_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_STREAM_CIPHER:"":"":"":PSA_ERROR_NOT_SUPPORTED
 
+PSA Multipart AEAD encrypt, AES-GCM, 128 bytes #1
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":0:"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96"
+
+PSA Multipart AEAD encrypt, AES-GCM, 128 bytes #1 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":1:"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96"
+
+PSA Multipart AEAD encrypt, AES-GCM, 128 bytes #2
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"fe96eab10ff48c7942025422583d0377":PSA_ALG_GCM:"97ce3f848276783599c6875de324361e":"127628b6dcbce6fc8a8ef60798eb67b2088415635119697d20bb878c24d9c6f9c29e148521cb5e0feff892c7855d4f1c0bfb32ad33420976714dce87a0bbc18e4378bd1ef35197d0ca73051148f1199010f63caf122df5f71ad8d9c71df3eb2fbe3b2529d0ba657570358d3776f687bdb9c96d5e0e9e00c4b42d5d7a268d6a08":"194c8bbbfae4a671386b8cd38f390f46f9df6b8661b470c310921a1c858a938045834bb10380037fbf5f5e00688554537be0fcafe8270b9b59068fa056ab1268fc166c2d729243a06650a171c929c7845c85330c04568d62977eedf3b1ba9dca13bdb8f9522817c8cb99e635e37465ec1c9f6f148d51437aa9f994a62e1bd013":0:"12495120056ca3cac70d583603a476821bac6c57c9733b81cfb83538dc9e850f8bdf46065069591c23ebcbc6d1e2523375fb7efc80c09507fa25477ed07cee54fc4eb90168b3ef988f651fc40652474a644b1b311decf899660aef2347bb081af48950f06ebf799911e37120de94c55c20e5f0a77119be06e2b6e557f872fa0f6bac793bdc2190a195122c98544ccf56"
+
+PSA Multipart AEAD encrypt, AES-GCM, 128 bytes #2 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"fe96eab10ff48c7942025422583d0377":PSA_ALG_GCM:"97ce3f848276783599c6875de324361e":"127628b6dcbce6fc8a8ef60798eb67b2088415635119697d20bb878c24d9c6f9c29e148521cb5e0feff892c7855d4f1c0bfb32ad33420976714dce87a0bbc18e4378bd1ef35197d0ca73051148f1199010f63caf122df5f71ad8d9c71df3eb2fbe3b2529d0ba657570358d3776f687bdb9c96d5e0e9e00c4b42d5d7a268d6a08":"194c8bbbfae4a671386b8cd38f390f46f9df6b8661b470c310921a1c858a938045834bb10380037fbf5f5e00688554537be0fcafe8270b9b59068fa056ab1268fc166c2d729243a06650a171c929c7845c85330c04568d62977eedf3b1ba9dca13bdb8f9522817c8cb99e635e37465ec1c9f6f148d51437aa9f994a62e1bd013":1:"12495120056ca3cac70d583603a476821bac6c57c9733b81cfb83538dc9e850f8bdf46065069591c23ebcbc6d1e2523375fb7efc80c09507fa25477ed07cee54fc4eb90168b3ef988f651fc40652474a644b1b311decf899660aef2347bb081af48950f06ebf799911e37120de94c55c20e5f0a77119be06e2b6e557f872fa0f6bac793bdc2190a195122c98544ccf56"
+
+PSA Multipart AEAD encrypt, AES-GCM, 128 bytes #1, T=4
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":0:"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847f"
+
+PSA Multipart AEAD encrypt, AES-GCM, 128 bytes #1, T=4 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":1:"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847f"
+
+PSA Multipart AEAD encrypt, AES-GCM, 128 bytes #1, T=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":0:"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a"
+
+PSA Multipart AEAD encrypt, AES-GCM, 128 bytes #1, T=15 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":1:"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a"
+
+PSA Multipart AEAD encrypt, AES-GCM, 128 bytes #1, T=16
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":0:"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96"
+
+PSA Multipart AEAD encrypt, AES-GCM, 128 bytes #1, T=16 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826":1:"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=0, AAD=0, TAG=16,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"ab2265b4c168955561f04315":"":"":0:"f149e2b5f0adaa9842ca5f45b768a8fc"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=0, AAD=0, TAG=16, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"ab2265b4c168955561f04315":"":"":1:"f149e2b5f0adaa9842ca5f45b768a8fc"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=0, AAD=16, TAG=16,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"41c5da8667ef725220ffe39ae0ac590ac9fca729ab60ada0":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"05ad13a5e2c2ab667e1a6fbc":"8b5c124bef6e2f0fe4d8c95cd5fa4cf1":"":0:"204bdb1bd62154bf08922aaa54eed705"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=0, AAD=16, TAG=16, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"41c5da8667ef725220ffe39ae0ac590ac9fca729ab60ada0":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"05ad13a5e2c2ab667e1a6fbc":"8b5c124bef6e2f0fe4d8c95cd5fa4cf1":"":1:"204bdb1bd62154bf08922aaa54eed705"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=0, AAD=20, TAG=16,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"093ef7551ebbff8eb0c0a8a4a62b198f0c2e838de10eeeee":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"e656e93930ed5210ba3f0322":"3da22dacfd11b21b0a713157f60aec0cd22f1add":"":0:"1b2d2764573e20ae640bf29d48e5fe05"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=0, AAD=20, TAG=16, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"093ef7551ebbff8eb0c0a8a4a62b198f0c2e838de10eeeee":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"e656e93930ed5210ba3f0322":"3da22dacfd11b21b0a713157f60aec0cd22f1add":"":1:"1b2d2764573e20ae640bf29d48e5fe05"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=0, AAD=48, TAG=15,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"31389612d244c9792a510eca3f9c94f9f48c97ed67ae965a":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"df6b54ec8b58114df5b09279":"0863bec42ee93385efbec665adfc46dafcd793f29e859e3b531c15b168f1888dd13e905cd7d5bc03f9f1f6495717df62":"":0:"77e5682a49243d5b9016eb1adafa2d"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=0, AAD=48, TAG=15, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"31389612d244c9792a510eca3f9c94f9f48c97ed67ae965a":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"df6b54ec8b58114df5b09279":"0863bec42ee93385efbec665adfc46dafcd793f29e859e3b531c15b168f1888dd13e905cd7d5bc03f9f1f6495717df62":"":1:"77e5682a49243d5b9016eb1adafa2d"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=0, TAG=16,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"fbc0b4c56a714c83217b2d1bcadd2ed2e9efb0dcac6cc19f":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"5f4b43e811da9c470d6a9b01":"":"d2ae38c4375954835d75b8e4c2f9bbb4":0:"69482957e6be5c54882d00314e0259cf191e9f29bef63a26860c1e020a21137e"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=0, TAG=16, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"fbc0b4c56a714c83217b2d1bcadd2ed2e9efb0dcac6cc19f":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"5f4b43e811da9c470d6a9b01":"":"d2ae38c4375954835d75b8e4c2f9bbb4":1:"69482957e6be5c54882d00314e0259cf191e9f29bef63a26860c1e020a21137e"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=0, TAG=8,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"c50ac59e50556e47b834380018c0dc0380af9df3bf6714e6":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 8 ):"f303bf4b6cfbba7104cd9436":"":"d3f3f57033df30c22860231334b099cb":0:"2269c72d77f2b6f9d57da1820ec5a5d3d62d4491e3e4e9e7"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=0, TAG=8, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"c50ac59e50556e47b834380018c0dc0380af9df3bf6714e6":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 8 ):"f303bf4b6cfbba7104cd9436":"":"d3f3f57033df30c22860231334b099cb":1:"2269c72d77f2b6f9d57da1820ec5a5d3d62d4491e3e4e9e7"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=16, TAG=14,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"8ef391e4b7a2fe05b959be27823357080f963ed2f64b9e59":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"0080052a2a5bb0e95222a419":"290322092d57479e20f6281e331d95a9":"e7fb0631eebf9bdba87045b33650c4ce":0:"88d674044031414af7ba9da8b89dd68e69897d99d8e1706f38c613896c18"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=16, TAG=14, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"8ef391e4b7a2fe05b959be27823357080f963ed2f64b9e59":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"0080052a2a5bb0e95222a419":"290322092d57479e20f6281e331d95a9":"e7fb0631eebf9bdba87045b33650c4ce":1:"88d674044031414af7ba9da8b89dd68e69897d99d8e1706f38c613896c18"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=16, TAG=4,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"1cb5a0db778d3eb430b2816ceef9e455f519a8977b074183":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"c1df5e9e2e3165c54242a306":"7134e5ddc396c2a8a7da23906c8f7b40":"636871d4c0aae3da7b55abd8b5f21297":0:"14eb02562aa1d963d0033626cdc8a5c8972f4bdf"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=16, TAG=4, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"1cb5a0db778d3eb430b2816ceef9e455f519a8977b074183":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"c1df5e9e2e3165c54242a306":"7134e5ddc396c2a8a7da23906c8f7b40":"636871d4c0aae3da7b55abd8b5f21297":1:"14eb02562aa1d963d0033626cdc8a5c8972f4bdf"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=20, TAG=13,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"45148f42669f8ab8fad689d9b9180e39d7ea8fc95696297e":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 13 ):"5afcb134acc78b4eb9d11e79":"aec409e5fd82e50b824ebc1f45e75188d80615c6":"3d952be11deb421b56e0ce9d7ce99553":0:"077c0d53869869e191df116fd7baa8a293d2b577a29b0953c91b5d3b9d"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=20, TAG=13, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"45148f42669f8ab8fad689d9b9180e39d7ea8fc95696297e":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 13 ):"5afcb134acc78b4eb9d11e79":"aec409e5fd82e50b824ebc1f45e75188d80615c6":"3d952be11deb421b56e0ce9d7ce99553":1:"077c0d53869869e191df116fd7baa8a293d2b577a29b0953c91b5d3b9d"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=48, TAG=15,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"5255428457fe75e64447971ec5af0d13c5b60a07ee2d07b0":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"40cb6ebafc202f82223db097":"b2da2bd05ab1f3e39613efc8d80c5d0f240ee08f6abad5791649e9c1d0f48fa3dc59c1e535d1db1a4d3fa2263f5a1117":"fdd8a462c86d4365c8bfee0e25fc8a62":0:"9ca4a6d08267038f6f7999c84105bb5eaf8f7b3b9310ec688e033088a03482"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=24, IV=12, IN=16, AAD=48, TAG=15, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"5255428457fe75e64447971ec5af0d13c5b60a07ee2d07b0":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"40cb6ebafc202f82223db097":"b2da2bd05ab1f3e39613efc8d80c5d0f240ee08f6abad5791649e9c1d0f48fa3dc59c1e535d1db1a4d3fa2263f5a1117":"fdd8a462c86d4365c8bfee0e25fc8a62":1:"9ca4a6d08267038f6f7999c84105bb5eaf8f7b3b9310ec688e033088a03482"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=0, TAG=16,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"b52c505a37d78eda5dd34f20c22540ea1b58963cf8e5bf8ffa85f9f2492505b4":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"516c33929df5a3284ff463d7":"":"":0:"bdc1ac884d332457a1d2664f168c76f0"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=0, TAG=16, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"b52c505a37d78eda5dd34f20c22540ea1b58963cf8e5bf8ffa85f9f2492505b4":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"516c33929df5a3284ff463d7":"":"":1:"bdc1ac884d332457a1d2664f168c76f0"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=0, TAG=12,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"98ebf7a58db8b8371d9069171190063cc1fdc1927e49a3385f890d41a838619c":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 12 ):"3e6db953bd4e641de644e50a":"":"":0:"2fb9c3e41fff24ef07437c47"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=0, TAG=12, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"98ebf7a58db8b8371d9069171190063cc1fdc1927e49a3385f890d41a838619c":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 12 ):"3e6db953bd4e641de644e50a":"":"":1:"2fb9c3e41fff24ef07437c47"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=20, TAG=16,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"886cff5f3e6b8d0e1ad0a38fcdb26de97e8acbe79f6bed66959a598fa5047d65":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"3a8efa1cd74bbab5448f9945":"519fee519d25c7a304d6c6aa1897ee1eb8c59655":"":0:"f6d47505ec96c98a42dc3ae719877b87"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=20, TAG=16, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"886cff5f3e6b8d0e1ad0a38fcdb26de97e8acbe79f6bed66959a598fa5047d65":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"3a8efa1cd74bbab5448f9945":"519fee519d25c7a304d6c6aa1897ee1eb8c59655":"":1:"f6d47505ec96c98a42dc3ae719877b87"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=20, TAG=13,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"a7c928738b89c3258b910ac31bc465338b2e133b143fd52d9c9859eb1d01f2a0":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 13 ):"a483a7e94fbb2d694d3c4a8d":"bdb613cd3c2f0edd37b3ed43041bacb949ee51fa":"":0:"5233f95bdcf5d666fb957acdcb"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=20, TAG=13, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"a7c928738b89c3258b910ac31bc465338b2e133b143fd52d9c9859eb1d01f2a0":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 13 ):"a483a7e94fbb2d694d3c4a8d":"bdb613cd3c2f0edd37b3ed43041bacb949ee51fa":"":1:"5233f95bdcf5d666fb957acdcb"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=48, TAG=15,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"16a5b58a1dbb273a8fc6a4af722d46dbb898dd86ab128cb93d8388a8647a80a3":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"59e0c40d6675923cf5e004d5":"5b4b4ffc9c66bd394abeed3f03b695b949b3b69a42198cc3bfad971174915df913b967ccf36ee1f001f54efbcd117b68":"":0:"d57e27914ecb4a764359d3c0f8d4d6"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=48, TAG=15, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"16a5b58a1dbb273a8fc6a4af722d46dbb898dd86ab128cb93d8388a8647a80a3":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"59e0c40d6675923cf5e004d5":"5b4b4ffc9c66bd394abeed3f03b695b949b3b69a42198cc3bfad971174915df913b967ccf36ee1f001f54efbcd117b68":"":1:"d57e27914ecb4a764359d3c0f8d4d6"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=48, TAG=4,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"5dd13092dd695b90ab835ed6343031c4cdb710d32f4d3804d72b46d921fcfa18":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"1de4bd816c8ec6bffc1e6453":"1b63d6278702abacf8b6c2faf542a808659fd5da03cdc1061a8593ea8ce9fc8ff54ffef6ebf3e15f7a832b4ae750a6ce":"":0:"72901467"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=0, AAD=48, TAG=4, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"5dd13092dd695b90ab835ed6343031c4cdb710d32f4d3804d72b46d921fcfa18":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"1de4bd816c8ec6bffc1e6453":"1b63d6278702abacf8b6c2faf542a808659fd5da03cdc1061a8593ea8ce9fc8ff54ffef6ebf3e15f7a832b4ae750a6ce":"":1:"72901467"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=16, AAD=0, TAG=15,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"ef9f9284cf599eac3b119905a7d18851e7e374cf63aea04358586b0f757670f8":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"b6ac8e4963f49207ffd6374c":"":"722ee47da4b77424733546c2d400c4e5":0:"1224dfefb72a20d49e09256908874979882eafea22adf8dbed06a2265f907b"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=16, AAD=0, TAG=15, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"ef9f9284cf599eac3b119905a7d18851e7e374cf63aea04358586b0f757670f8":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"b6ac8e4963f49207ffd6374c":"":"722ee47da4b77424733546c2d400c4e5":1:"1224dfefb72a20d49e09256908874979882eafea22adf8dbed06a2265f907b"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=16, AAD=0, TAG=12,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"b33b0e4c5b9f7ef77cec1a29ed5844bda3853238bdf7766e7645029931f169f0":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 12 ):"f226d65e8654fdf5193ed721":"":"bcf48ddcfe9d011a1003973d68d2d78a":0:"d2eb20898a301b5d8e69e9926272021393af01abb6a970047a7fc010"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=16, AAD=0, TAG=12, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"b33b0e4c5b9f7ef77cec1a29ed5844bda3853238bdf7766e7645029931f169f0":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 12 ):"f226d65e8654fdf5193ed721":"":"bcf48ddcfe9d011a1003973d68d2d78a":1:"d2eb20898a301b5d8e69e9926272021393af01abb6a970047a7fc010"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=16, AAD=16, TAG=14,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"c6e126a65faec77ab62318e30d8a50c39a664670039a66ae5a6874201bc68f9f":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"0ba5193b2d3a8378d67163ce":"5844b289dc74327f9fd93f7aae1c3d39":"c37aada3d4408e880d47e41df77da9b9":0:"b5cd7563989b460a2fe187e90c41fc3179c73d0d1e3a4484909969de93b0"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=16, AAD=16, TAG=14, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"c6e126a65faec77ab62318e30d8a50c39a664670039a66ae5a6874201bc68f9f":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"0ba5193b2d3a8378d67163ce":"5844b289dc74327f9fd93f7aae1c3d39":"c37aada3d4408e880d47e41df77da9b9":1:"b5cd7563989b460a2fe187e90c41fc3179c73d0d1e3a4484909969de93b0"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=16, AAD=48, TAG=15,
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"2e6942d537f1a98444c2f9dbdb5d8db42a503a00a17b57d516399569e044a703":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"7eb67721581ed52cfcfc2c4d":"a96cc73451502c7278b467ac85d5fc14fc1a2f51bc685645b173f0cd9af02d383095de063e6eaa50374ce9bc951e9e61":"e5f410fe939e79b7ad33fbd3aaf5856f":0:"727f5e19a5582e5782bbbe73517f0c04c492319abf12b03b380724ff1483a3"
+
+PSA Multipart AEAD encrypt, AES-GCM, CAVS 14.0, KEY=32, IV=12, IN=16, AAD=48, TAG=15, (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_encrypt:PSA_KEY_TYPE_AES:"2e6942d537f1a98444c2f9dbdb5d8db42a503a00a17b57d516399569e044a703":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"7eb67721581ed52cfcfc2c4d":"a96cc73451502c7278b467ac85d5fc14fc1a2f51bc685645b173f0cd9af02d383095de063e6eaa50374ce9bc951e9e61":"e5f410fe939e79b7ad33fbd3aaf5856f":1:"727f5e19a5582e5782bbbe73517f0c04c492319abf12b03b380724ff1483a3"
+
+PSA Multipart AEAD decrypt, AES - GCM, 144 bytes #1
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":0:"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826"
+
+PSA Multipart AEAD decrypt, AES - GCM, 144 bytes #1 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_GCM:"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":1:"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826"
+
+PSA Multipart AEAD decrypt, AES - GCM, 144 bytes #2
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"fe96eab10ff48c7942025422583d0377":PSA_ALG_GCM:"97ce3f848276783599c6875de324361e":"127628b6dcbce6fc8a8ef60798eb67b2088415635119697d20bb878c24d9c6f9c29e148521cb5e0feff892c7855d4f1c0bfb32ad33420976714dce87a0bbc18e4378bd1ef35197d0ca73051148f1199010f63caf122df5f71ad8d9c71df3eb2fbe3b2529d0ba657570358d3776f687bdb9c96d5e0e9e00c4b42d5d7a268d6a08":"12495120056ca3cac70d583603a476821bac6c57c9733b81cfb83538dc9e850f8bdf46065069591c23ebcbc6d1e2523375fb7efc80c09507fa25477ed07cee54fc4eb90168b3ef988f651fc40652474a644b1b311decf899660aef2347bb081af48950f06ebf799911e37120de94c55c20e5f0a77119be06e2b6e557f872fa0f6bac793bdc2190a195122c98544ccf56":0:"194c8bbbfae4a671386b8cd38f390f46f9df6b8661b470c310921a1c858a938045834bb10380037fbf5f5e00688554537be0fcafe8270b9b59068fa056ab1268fc166c2d729243a06650a171c929c7845c85330c04568d62977eedf3b1ba9dca13bdb8f9522817c8cb99e635e37465ec1c9f6f148d51437aa9f994a62e1bd013"
+
+PSA Multipart AEAD decrypt, AES - GCM, 144 bytes #2 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"fe96eab10ff48c7942025422583d0377":PSA_ALG_GCM:"97ce3f848276783599c6875de324361e":"127628b6dcbce6fc8a8ef60798eb67b2088415635119697d20bb878c24d9c6f9c29e148521cb5e0feff892c7855d4f1c0bfb32ad33420976714dce87a0bbc18e4378bd1ef35197d0ca73051148f1199010f63caf122df5f71ad8d9c71df3eb2fbe3b2529d0ba657570358d3776f687bdb9c96d5e0e9e00c4b42d5d7a268d6a08":"12495120056ca3cac70d583603a476821bac6c57c9733b81cfb83538dc9e850f8bdf46065069591c23ebcbc6d1e2523375fb7efc80c09507fa25477ed07cee54fc4eb90168b3ef988f651fc40652474a644b1b311decf899660aef2347bb081af48950f06ebf799911e37120de94c55c20e5f0a77119be06e2b6e557f872fa0f6bac793bdc2190a195122c98544ccf56":1:"194c8bbbfae4a671386b8cd38f390f46f9df6b8661b470c310921a1c858a938045834bb10380037fbf5f5e00688554537be0fcafe8270b9b59068fa056ab1268fc166c2d729243a06650a171c929c7845c85330c04568d62977eedf3b1ba9dca13bdb8f9522817c8cb99e635e37465ec1c9f6f148d51437aa9f994a62e1bd013"
+
+PSA Multipart AEAD decrypt, AES - GCM, 144 bytes, T = 4
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,4):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847f":0:"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826"
+
+PSA Multipart AEAD decrypt, AES - GCM, 144 bytes, T = 4 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,4):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847f":1:"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826"
+
+PSA Multipart AEAD decrypt, AES - GCM, 144 bytes, T = 15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,15):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a":0:"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826"
+
+PSA Multipart AEAD decrypt, AES - GCM, 144 bytes, T = 15 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,15):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a":1:"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826"
+
+PSA Multipart AEAD decrypt, AES-GCM, 144 bytes, T=16
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":0:"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826"
+
+PSA Multipart AEAD decrypt, AES-GCM, 144 bytes, T=16 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c872814365847fe0b7b7fbed325953df344a96":1:"5431d93278c35cfcd7ffa9ce2de5c6b922edffd5055a9eaa5b54cae088db007cf2d28efaf9edd1569341889073e87c0a88462d77016744be62132fd14a243ed6e30e12cd2f7d08a8daeec161691f3b27d4996df8745d74402ee208e4055615a8cb069d495cf5146226490ac615d7b17ab39fb4fdd098e4e7ee294d34c1312826"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=0, AAD=0, TAG=16
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"0e5d6e68f82f32bea3f0b69498c1a31ef6d955cd3d27a2a8":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"caf72ee1e62e1001e8cfbc63":"":"db1a74ffb5f7de26f5742e0942b1b9cb":0:""
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=0, AAD=0, TAG=16 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"0e5d6e68f82f32bea3f0b69498c1a31ef6d955cd3d27a2a8":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"caf72ee1e62e1001e8cfbc63":"":"db1a74ffb5f7de26f5742e0942b1b9cb":1:""
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=0, AAD=48, TAG=14
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"e79fb7defce4f650402e6b521170686d3eb2a0b9514f3a64":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"40e0d2d836c0519e7042419b":"41c5b5d971c0723bc1b63a259fe7e06c2961de1241bc34c13965f43636e4da3da8c75ed5956abe3a42f3039af005925a":"434ff68f2436f48418fd69f52158":0:""
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=0, AAD=48, TAG=14 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"e79fb7defce4f650402e6b521170686d3eb2a0b9514f3a64":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"40e0d2d836c0519e7042419b":"41c5b5d971c0723bc1b63a259fe7e06c2961de1241bc34c13965f43636e4da3da8c75ed5956abe3a42f3039af005925a":"434ff68f2436f48418fd69f52158":1:""
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=16, AAD=0, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"e41d1f533d5b342ffe434b94b1372683bfd5d9d8cb79f9ee":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"5fe11a596dfcd3a305c1d711":"":"1847f64fff986476d1d2f758692f856da4a0ff98c0c1101694c84fd86680c9":0:"b03c2c20f758a93a8d1220232ad87098"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=16, AAD=0, TAG=15 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"e41d1f533d5b342ffe434b94b1372683bfd5d9d8cb79f9ee":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"5fe11a596dfcd3a305c1d711":"":"1847f64fff986476d1d2f758692f856da4a0ff98c0c1101694c84fd86680c9":1:"b03c2c20f758a93a8d1220232ad87098"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=16, AAD=20, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"8e7da473c057a2a4669a0d22bf9b7c9913fba48930ca0c9b":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"f9ff8ef80d76c50f9ca0e9ff":"f141bae18a1b54f065554fd34aa02c91c90f505c":"5deb093b6e7c766a64bb9d5170af1ff8bf130b64eebdce06a9bdb2cf1da15a":0:"b22b2dcdcc18adc30d16297b84b459d8"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=16, AAD=20, TAG=15 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"8e7da473c057a2a4669a0d22bf9b7c9913fba48930ca0c9b":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"f9ff8ef80d76c50f9ca0e9ff":"f141bae18a1b54f065554fd34aa02c91c90f505c":"5deb093b6e7c766a64bb9d5170af1ff8bf130b64eebdce06a9bdb2cf1da15a":1:"b22b2dcdcc18adc30d16297b84b459d8"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=16, AAD=48, TAG=12
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"01bf150add51bb11623e3bfbebd62a7ea81c5b192b8eb6de":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 12 ):"dfacbc6791b785d324c646b7":"e35412a625324257bef35399a7eacca34fec2d2d24166e6bb3e94d96f5c57599ded45e2a74503f07116caa1692398a07":"77579db3c6da769e17731faac4732d7cce65d960a49f94f6b583e54a":0:"7e5fd8b595ddc4753676107951d900e2"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=16, AAD=48, TAG=12 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"01bf150add51bb11623e3bfbebd62a7ea81c5b192b8eb6de":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 12 ):"dfacbc6791b785d324c646b7":"e35412a625324257bef35399a7eacca34fec2d2d24166e6bb3e94d96f5c57599ded45e2a74503f07116caa1692398a07":"77579db3c6da769e17731faac4732d7cce65d960a49f94f6b583e54a":1:"7e5fd8b595ddc4753676107951d900e2"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=16, AAD=48, TAG=8
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"551266c4ed166fe1c43761927801ed50cb9c0b3864fc97df":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 8 ):"e711afbeccd567f866340abb":"562d1697237ebc563941076d459727dfa094eb9ac00d30ed5836825d163dd27517c7660a01056b2d868c7fc5d0343830":"2b54cc27f6ee71882e8b1ead207d2b042d262e87eac97b58":0:"37245449db8f72b1ecdb420f629d3d80"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=16, AAD=48, TAG=8 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"551266c4ed166fe1c43761927801ed50cb9c0b3864fc97df":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 8 ):"e711afbeccd567f866340abb":"562d1697237ebc563941076d459727dfa094eb9ac00d30ed5836825d163dd27517c7660a01056b2d868c7fc5d0343830":"2b54cc27f6ee71882e8b1ead207d2b042d262e87eac97b58":1:"37245449db8f72b1ecdb420f629d3d80"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=13, AAD=0, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"78fa4a2a5b5b1b1d9580ea527f2e1653e9336e15cc5462f5":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"98b774f7110e0bea624b487f":"":"a642aabed8b99e15e297ee705a40c3e2e506cb889727b327b7e044a8":0:"496909523f574b205d757659c5"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=13, AAD=0, TAG=15 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"78fa4a2a5b5b1b1d9580ea527f2e1653e9336e15cc5462f5":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"98b774f7110e0bea624b487f":"":"a642aabed8b99e15e297ee705a40c3e2e506cb889727b327b7e044a8":1:"496909523f574b205d757659c5"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=13, AAD=16, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"61f4c2e55d729c4657e503dfe2b604e2853675dbdeb0982a":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"0c4d5548aa2d8d54964e1e63":"5affdf8886dabb14790aff3dbfcbdd80":"0d4eacc3db304f46cb7a9eba6ec105bf86d9dc0639b7cebbd5260f47":0:"b6e056de521a27266dffbc0d96"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=13, AAD=16, TAG=15 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"61f4c2e55d729c4657e503dfe2b604e2853675dbdeb0982a":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"0c4d5548aa2d8d54964e1e63":"5affdf8886dabb14790aff3dbfcbdd80":"0d4eacc3db304f46cb7a9eba6ec105bf86d9dc0639b7cebbd5260f47":1:"b6e056de521a27266dffbc0d96"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=13, AAD=20, TAG=13
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"73245c4f115a74fe71d6fefb9094c57c75f28033a3c7372b":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 13 ):"536a82485999b93b0bb7ef24":"64dcad870a42eeec0730fd7a7e4154638a85d739":"29333e87bfe65d0e37da2936f695824d4e3f37fab3b8e2b868f6":0:"f6d56f8c86f27d957fa63aea22"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=13, AAD=20, TAG=13 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"73245c4f115a74fe71d6fefb9094c57c75f28033a3c7372b":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 13 ):"536a82485999b93b0bb7ef24":"64dcad870a42eeec0730fd7a7e4154638a85d739":"29333e87bfe65d0e37da2936f695824d4e3f37fab3b8e2b868f6":1:"f6d56f8c86f27d957fa63aea22"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=13, AAD=48, TAG=4
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"9002e74638e09dd1f091439518e1460cdd5905bd9e1a37ae":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"76c81a95d24be5c8bac63b50":"aa3ae4531aaac8f3eb07f748712c55a680bc8df5cf845edc66d09049500b41688b8023f5746879b45bdd586af29c4ede":"31bf37acbc53ca3fdbc9e5eaaebbb85a7f":0:"bd94b34511bc65ae47684805cb"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=24, IV=12, IN=13, AAD=48, TAG=4 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"9002e74638e09dd1f091439518e1460cdd5905bd9e1a37ae":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"76c81a95d24be5c8bac63b50":"aa3ae4531aaac8f3eb07f748712c55a680bc8df5cf845edc66d09049500b41688b8023f5746879b45bdd586af29c4ede":"31bf37acbc53ca3fdbc9e5eaaebbb85a7f":1:"bd94b34511bc65ae47684805cb"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=0, AAD=0, TAG=16
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"f5a2b27c74355872eb3ef6c5feafaa740e6ae990d9d48c3bd9bb8235e589f010":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"58d2240f580a31c1d24948e9":"":"15e051a5e4a5f5da6cea92e2ebee5bac":0:""
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=0, AAD=0, TAG=16 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"f5a2b27c74355872eb3ef6c5feafaa740e6ae990d9d48c3bd9bb8235e589f010":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"58d2240f580a31c1d24948e9":"":"15e051a5e4a5f5da6cea92e2ebee5bac":1:""
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=0, AAD=16, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"3395a1485315c5b5e6353acb05ae9499c440a2e9f5c57494662f827235ea314c":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"3b7e632571602456b49880f0":"f283f80226dacb69c8af089ec6b59e81":"84c8beff4b0d160ee68ac613097f51":0:""
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=0, AAD=16, TAG=15 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"3395a1485315c5b5e6353acb05ae9499c440a2e9f5c57494662f827235ea314c":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"3b7e632571602456b49880f0":"f283f80226dacb69c8af089ec6b59e81":"84c8beff4b0d160ee68ac613097f51":1:""
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=0, AAD=20, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"4dc46ca55c1c1fcb4720c274c0e675c2ac5bf93d8dd5e951ca9f6b61f884edc9":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"6473ab77dc885127422f5594":"e2cf8172ab4cf77eba45cd2c8ff939b938080a90":"8d6351f18d873242204c20144e2b83":0:""
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=0, AAD=20, TAG=15 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"4dc46ca55c1c1fcb4720c274c0e675c2ac5bf93d8dd5e951ca9f6b61f884edc9":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"6473ab77dc885127422f5594":"e2cf8172ab4cf77eba45cd2c8ff939b938080a90":"8d6351f18d873242204c20144e2b83":1:""
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=0, AAD=48, TAG=14
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"a7f95798434f9a0fe6fd8acd30b8bad96dbdcfacee4594f01cbf26479be7d154":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"9ef5a77b02137b46e8461d09":"5595a16fa12d4dcdba6b128480dce2d39c1211c3fb6068cde6013f6a80dfcda5eb92af8879e40ee9c177fd0e446fc8ca":"3bfd3d99fe2063e8ef8255519fe0":0:""
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=0, AAD=48, TAG=14 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"a7f95798434f9a0fe6fd8acd30b8bad96dbdcfacee4594f01cbf26479be7d154":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"9ef5a77b02137b46e8461d09":"5595a16fa12d4dcdba6b128480dce2d39c1211c3fb6068cde6013f6a80dfcda5eb92af8879e40ee9c177fd0e446fc8ca":"3bfd3d99fe2063e8ef8255519fe0":1:""
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=16, AAD=0, TAG=16
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"4c8ebfe1444ec1b2d503c6986659af2c94fafe945f72c1e8486a5acfedb8a0f8":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"473360e0ad24889959858995":"":"d2c78110ac7e8f107c0df0570bd7c90cc26a379b6d98ef2852ead8ce83a833a7":0:"7789b41cb3ee548814ca0b388c10b343"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=16, AAD=0, TAG=16 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"4c8ebfe1444ec1b2d503c6986659af2c94fafe945f72c1e8486a5acfedb8a0f8":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 16 ):"473360e0ad24889959858995":"":"d2c78110ac7e8f107c0df0570bd7c90cc26a379b6d98ef2852ead8ce83a833a7":1:"7789b41cb3ee548814ca0b388c10b343"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=16, AAD=0, TAG=4
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"57805f98aae1b8b64bb49756529ab8181b3ada674a90c55422e9eb26c48bcd7b":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"9735945d8ca161777206632a":"":"58375442ab1c0e6a8952c83d128d9fc5f45bb315":0:"4860116a6d2deb9bf794bfd6ac5bbbd6"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=16, AAD=0, TAG=4 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"57805f98aae1b8b64bb49756529ab8181b3ada674a90c55422e9eb26c48bcd7b":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 4 ):"9735945d8ca161777206632a":"":"58375442ab1c0e6a8952c83d128d9fc5f45bb315":1:"4860116a6d2deb9bf794bfd6ac5bbbd6"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=16, AAD=16, TAG=8
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"f913bb823a1d0c10b0b72d56866907b893f2266f15de1abc17f93600824db55a":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 8 ):"d4fe686a14592b6ca1bd6b42":"e35d880c1c53688eb83869de9dd8a473":"35af9b502ea6b56269f896bf98affdd59c2aa418b38bc7fd":0:"ff426dd751190ff826e8b4a0792d746e"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=16, AAD=16, TAG=8 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"f913bb823a1d0c10b0b72d56866907b893f2266f15de1abc17f93600824db55a":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 8 ):"d4fe686a14592b6ca1bd6b42":"e35d880c1c53688eb83869de9dd8a473":"35af9b502ea6b56269f896bf98affdd59c2aa418b38bc7fd":1:"ff426dd751190ff826e8b4a0792d746e"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=16, AAD=20, TAG=14
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"74e9d9d7cd0728cea94e169af485f21f9d2447e022f16008f803dcf5c4f7cc0c":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"ecba39edc96667da726122c0":"ae9ab021f86f5b81bb2e0fcbd4b855e1501e9f82":"e5745ce0e02dbba05363b548c3ac7047eacca7e61db6f72fc9b9e5bdb2bb":0:"0a0b284515694188b6b6c15bc8a09036"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=16, AAD=20, TAG=14 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"74e9d9d7cd0728cea94e169af485f21f9d2447e022f16008f803dcf5c4f7cc0c":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"ecba39edc96667da726122c0":"ae9ab021f86f5b81bb2e0fcbd4b855e1501e9f82":"e5745ce0e02dbba05363b548c3ac7047eacca7e61db6f72fc9b9e5bdb2bb":1:"0a0b284515694188b6b6c15bc8a09036"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=13, AAD=0, TAG=14
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"60667fce64b8c7169ddf45f335e46951248f69abc4e0f4f292d0ffe3dfd5219f":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"1057322a39f08ef761c3c8fc":"":"501b033c841acb430c52d88fe9cb44c751f2f1641d1e801a534ac8":0:"f386b28e7eb4c2fb8eb5dc66a2"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=13, AAD=0, TAG=14 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"60667fce64b8c7169ddf45f335e46951248f69abc4e0f4f292d0ffe3dfd5219f":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 14 ):"1057322a39f08ef761c3c8fc":"":"501b033c841acb430c52d88fe9cb44c751f2f1641d1e801a534ac8":1:"f386b28e7eb4c2fb8eb5dc66a2"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=13, AAD=20, TAG=15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"e67590da399cbcdcddcc56110562ade8665b50287a8ab38e8b9ee7520531b560":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"2c36ab6b686a66fba1805196":"823493d42f4f60b2d1433ad75eccaafd7e7c7d12":"cff6b6f03c67152f3ce1030653d9bd9a6559f5b04b48d77c2a1fc364":0:"da1c61fbfcdb73445ad4c7d889"
+
+PSA Multipart AEAD decrypt, CAVS14.0, AES-GCM, KEY=32, IV=12, IN=13, AAD=20, TAG=15 (lengths set)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_decrypt:PSA_KEY_TYPE_AES:"e67590da399cbcdcddcc56110562ade8665b50287a8ab38e8b9ee7520531b560":PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 15 ):"2c36ab6b686a66fba1805196":"823493d42f4f60b2d1433ad75eccaafd7e7c7d12":"cff6b6f03c67152f3ce1030653d9bd9a6559f5b04b48d77c2a1fc364":1:"da1c61fbfcdb73445ad4c7d889"
+
+PSA Multipart AEAD encrypt: ChaCha20-Poly1305 (RFC7539)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_encrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":0:"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691"
+
+PSA Multipart AEAD encrypt: ChaCha20-Poly1305 (RFC7539) (lengths set)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_encrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":1:"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691"
+
+PSA Multipart AEAD encrypt: ChaCha20-Poly1305 (zero-length input)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_encrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"":"":0:"a0784d7a4716f3feb4f64e7f4b39bf04"
+
+PSA Multipart AEAD encrypt: ChaCha20-Poly1305 (zero-length input) (lengths set)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_encrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"":"":1:"a0784d7a4716f3feb4f64e7f4b39bf04"
+
+PSA Multipart AEAD decrypt: ChaCha20 - Poly1305 (RFC7539, good tag)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691":0:"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e"
+
+PSA Multipart AEAD decrypt: ChaCha20 - Poly1305 (RFC7539, good tag) (lengths set)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691":1:"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e"
+
+PSA Multipart AEAD decrypt: ChaCha20 - Poly1305 (good tag, zero - length input)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"":"a0784d7a4716f3feb4f64e7f4b39bf04":0:""
+
+PSA Multipart AEAD decrypt: ChaCha20 - Poly1305 (good tag, zero - length input) (lengths set)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_decrypt:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"":"a0784d7a4716f3feb4f64e7f4b39bf04":1:""
+
+PSA Multipart AEAD verify, AES - GCM, invalid signature
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_verify:PSA_KEY_TYPE_AES:"fe96eab10ff48c7942025422583d0377":PSA_ALG_GCM:"97ce3f848276783599c6875de324361e":"127628b6dcbce6fc8a8ef60798eb67b2088415635119697d20bb878c24d9c6f9c29e148521cb5e0feff892c7855d4f1c0bfb32ad33420976714dce87a0bbc18e4378bd1ef35197d0ca73051148f1199010f63caf122df5f71ad8d9c71df3eb2fbe3b2529d0ba657570358d3776f687bdb9c96d5e0e9e00c4b42d5d7a268d6a08":"12195120056ca3cac70d583603a476821bac6c57c9733b81cfb83538dc9e850f8bdf46065069591c23ebcbc6d1e2523375fb7efc80c09507fa25477ed07cee54fc4eb90168b3ef988f651fc40652474a644b1b311decf899660aef2347bb081af48950f06ebf799911e37120de94c55c20e5f0a77119be06e2b6e557f872fa0f":"6bac793bdc2190a195122c98544ccf56":1:PSA_ERROR_INVALID_SIGNATURE
+
+PSA Multipart AEAD verify, AES - GCM, T = 15 but passing 16 bytes
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_verify:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,15):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c87281":"4365847fe0b7b7fbed325953df344a96":1:PSA_ERROR_INVALID_SIGNATURE
+
+PSA Multipart AEAD verify, AES - GCM, T = 15 but passing 14 bytes
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_verify:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,15):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c87281":"4365847fe0b7b7fbed325953df34":1:PSA_ERROR_INVALID_SIGNATURE
+
+PSA Multipart AEAD verify, AES - GCM, T = 15 but passing 0 bytes (valid buffer)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_verify:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,15):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c87281":"":1:PSA_ERROR_INVALID_SIGNATURE
+
+PSA Multipart AEAD verify, AES - GCM, T = 15 but passing 0 bytes (NULL buffer)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_verify:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,15):"00e440846db73a490573deaf3728c94f":"a3cfcb832e935eb5bc3812583b3a1b2e82920c07fda3668a35d939d8f11379bb606d39e6416b2ef336fffb15aec3f47a71e191f4ff6c56ff15913562619765b26ae094713d60bab6ab82bfc36edaaf8c7ce2cf5906554dcc5933acdb9cb42c1d24718efdc4a09256020b024b224cfe602772bd688c6c8f1041a46f7ec7d51208":"3b6de52f6e582d317f904ee768895bd4d0790912efcf27b58651d0eb7eb0b2f07222c6ffe9f7e127d98ccb132025b098a67dc0ec0083235e9f83af1ae1297df4319547cbcb745cebed36abc1f32a059a05ede6c00e0da097521ead901ad6a73be20018bda4c323faa135169e21581e5106ac20853642e9d6b17f1dd925c87281":"":0:PSA_ERROR_INVALID_SIGNATURE
+
+PSA Multipart AEAD verify: AES - GCM, invalid tag length 0
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_verify:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,0):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd10b6":"":1:PSA_ERROR_INVALID_ARGUMENT
+
+PSA Multipart AEAD verify: AES - GCM, invalid tag length 2
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_verify:PSA_KEY_TYPE_AES:"a0ec7b0052541d9e9c091fb7fc481409":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,2):"48c0906930561e0ab0ef4cd972":"40a27c1d1e23ea3dbe8056b2774861a4a201cce49f19997d19206d8c8a343951":"26c56961c035a7e452cce61bc6ee220d77b3f94d18fd":"10b6":1:PSA_ERROR_INVALID_ARGUMENT
+
+PSA Multipart AEAD verify: ChaCha20 - Poly1305 (RFC7539, bad tag)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_verify:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116":"1ae10b594f09e26a7e902ecbd0600690":1:PSA_ERROR_INVALID_SIGNATURE
+
+PSA Multipart Nonce Generation, AES - GCM, NONCE = (Req 12 / Expect 12)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_generate_nonce:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_GCM:12:12:"290322092d57479e20f6281e331d95a9":"e7fb0631eebf9bdba87045b33650c4ce":PSA_SUCCESS
+
+PSA Multipart Nonce Generation, AES - GCM, NONCE = (Req 11 / Expect 0)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_generate_nonce:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_GCM:11:0:"290322092d57479e20f6281e331d95a9":"e7fb0631eebf9bdba87045b33650c4ce":PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA Multipart Nonce Generation, AES - GCM, NONCE = (Req 0 / Expect 0)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_generate_nonce:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_GCM:0:0:"":"":PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA Multipart Nonce Generation, AES - GCM, NONCE = (Req 16 / Expect 12)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_generate_nonce:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_GCM:16:12:"290322092d57479e20f6281e331d95a9":"e7fb0631eebf9bdba87045b33650c4ce":PSA_SUCCESS
+
+PSA Multipart Nonce Generation: ChaCha20 - Poly1305, NONCE = (Req 12 / Expect 12)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_generate_nonce:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:12:12:"50515253c0c1c2c3c4c5c6c7":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":PSA_SUCCESS
+
+PSA Multipart Nonce Generation: ChaCha20 - Poly1305, NONCE = (Req 11 / Expect 0)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_generate_nonce:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:11:0:"":"":PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA Multipart Nonce Generation: ChaCha20 - Poly1305, NONCE = (Req 0 / Expect 0)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_generate_nonce:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:0:0:"":"":PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA Multipart Nonce Generation: ChaCha20 - Poly1305, NONCE = (Req 16 / Expect 12)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_generate_nonce:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:16:12:"":"":PSA_SUCCESS
+
+PSA Multipart Set Nonce, AES - GCM, NONCE = 0 (NULL)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_set_nonce:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_GCM:0:"":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA Multipart Set Nonce, AES - GCM, NONCE = 0 (Non-NULL)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_set_nonce:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_GCM:-1:"":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA Multipart Set Nonce, AES - GCM, NONCE = 16
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_set_nonce:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_GCM:16:"290322092d57479e20f6281e331d95a9":"e7fb0631eebf9bdba87045b33650c4ce":PSA_SUCCESS
+
+PSA Multipart Set Nonce, AES - GCM, NONCE = 20
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_set_nonce:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_GCM:20:"290322092d57479e20f6281e331d95a9":"e7fb0631eebf9bdba87045b33650c4ce":PSA_SUCCESS
+
+PSA Multipart Set Nonce, AES - GCM_12, NONCE = 0 (NULL)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_set_nonce:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,12):0:"":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA Multipart Set Nonce, AES - GCM_12, NONCE = 0 (Non-NULL)
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_set_nonce:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,12):-1:"":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA Multipart Set Nonce, AES - GCM_12, NONCE = 16
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_set_nonce:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,12):16:"290322092d57479e20f6281e331d95a9":"e7fb0631eebf9bdba87045b33650c4ce":PSA_SUCCESS
+
+PSA Multipart Set Nonce, AES - GCM_12, NONCE = 20
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_set_nonce:PSA_KEY_TYPE_AES:"aa740abfadcda779220d3b406c5d7ec09a77fe9d94104539":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM,12):20:"290322092d57479e20f6281e331d95a9":"e7fb0631eebf9bdba87045b33650c4ce":PSA_SUCCESS
+
+PSA Multipart Set Nonce: ChaCha20 - Poly1305, NONCE = 11
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_set_nonce:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:11:"50515253c0c1c2c3c4c5c6c7":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":PSA_ERROR_INVALID_ARGUMENT
+
+PSA Multipart Set Nonce: ChaCha20 - Poly1305, NONCE = 12
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_set_nonce:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:12:"50515253c0c1c2c3c4c5c6c7":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":PSA_SUCCESS
+
+PSA Multipart Set Nonce: ChaCha20 - Poly1305, NONCE = 13
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_set_nonce:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:13:"50515253c0c1c2c3c4c5c6c7":"4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e":PSA_ERROR_INVALID_ARGUMENT
+
+PSA Multipart Set Nonce: ChaCha20 - Poly1305, NONCE = 0 (NULL)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_set_nonce:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:0:"":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA Multipart Set Nonce: ChaCha20 - Poly1305, NONCE = 0 (Non-NULL)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_set_nonce:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:-1:"":"":PSA_ERROR_INVALID_ARGUMENT
+
+PSA AEAD output buffer test: AES - GCM, IN = 16, BUF = 15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_update_buffer_test:PSA_KEY_TYPE_AES:"fbc0b4c56a714c83217b2d1bcadd2ed2e9efb0dcac6cc19f":PSA_ALG_GCM:15:"5f4b43e811da9c470d6a9b01":"":"d2ae38c4375954835d75b8e4c2f9bbb4":PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA AEAD output buffer test: AES - GCM, IN = 16, BUF = 0
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_update_buffer_test:PSA_KEY_TYPE_AES:"fbc0b4c56a714c83217b2d1bcadd2ed2e9efb0dcac6cc19f":PSA_ALG_GCM:0:"5f4b43e811da9c470d6a9b01":"":"d2ae38c4375954835d75b8e4c2f9bbb4":PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA AEAD output buffer test: ChaCha20 - Poly1305 IN = 130, BUF = 129
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_update_buffer_test:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:129:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691":PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA AEAD output buffer test: ChaCha20 - Poly1305 IN = 130, BUF = 0
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_update_buffer_test:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:0:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691":PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA AEAD finish buffer test: AES - GCM, BUF = 8, TAG = 16
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_finish_buffer_test:PSA_KEY_TYPE_AES:"fbc0b4c56a714c83217b2d1bcadd2ed2e9efb0dcac6cc19f":PSA_ALG_GCM:8:16:"5f4b43e811da9c470d6a9b01":"":"d2ae38c4375954835d75b8e4c2f9bbb4":PSA_SUCCESS
+
+PSA AEAD finish buffer test: AES - GCM, BUF = 15, TAG = 20
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_finish_buffer_test:PSA_KEY_TYPE_AES:"fbc0b4c56a714c83217b2d1bcadd2ed2e9efb0dcac6cc19f":PSA_ALG_GCM:15:20:"5f4b43e811da9c470d6a9b01":"":"d2ae38c4375954835d75b8e4c2f9bbb4":PSA_SUCCESS
+
+PSA AEAD finish buffer test: AES - GCM, BUF = 15, TAG = 15
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_finish_buffer_test:PSA_KEY_TYPE_AES:"fbc0b4c56a714c83217b2d1bcadd2ed2e9efb0dcac6cc19f":PSA_ALG_GCM:15:15:"5f4b43e811da9c470d6a9b01":"":"d2ae38c4375954835d75b8e4c2f9bbb4":PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA AEAD finish buffer test: AES - GCM, BUF = 15, TAG = 0
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_finish_buffer_test:PSA_KEY_TYPE_AES:"fbc0b4c56a714c83217b2d1bcadd2ed2e9efb0dcac6cc19f":PSA_ALG_GCM:15:0:"5f4b43e811da9c470d6a9b01":"":"d2ae38c4375954835d75b8e4c2f9bbb4":PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA AEAD finish buffer test: ChaCha20 - Poly1305, BUF = 0, TAG = 20
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_finish_buffer_test:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:0:20:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691":PSA_SUCCESS
+
+PSA AEAD finish buffer test: ChaCha20 - Poly1305, BUF = 0, TAG = 15
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_finish_buffer_test:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:0:15:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691":PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA AEAD finish buffer test: ChaCha20 - Poly1305, BUF = 0, TAG = 0
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_finish_buffer_test:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_CHACHA20_POLY1305:0:0:"070000004041424344454647":"50515253c0c1c2c3c4c5c6c7":"d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691":PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA AEAD setup: invalid algorithm (CTR)
+depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
+aead_multipart_setup:PSA_KEY_TYPE_AES:"D7828D13B2B0BDC325A76236DF93CC6B":PSA_ALG_CTR:PSA_ERROR_INVALID_ARGUMENT
+
+PSA AEAD setup: invalid algorithm (ChaCha20)
+depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_setup:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_STREAM_CIPHER:PSA_ERROR_INVALID_ARGUMENT
+
+PSA AEAD setup: invalid algorithm (ChaCha20 - Poly1305 with short tag)
+depends_on:PSA_WANT_ALG_CHACHA20_POLY1305:PSA_WANT_KEY_TYPE_CHACHA20
+aead_multipart_setup:PSA_KEY_TYPE_CHACHA20:"808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f":PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305,12):PSA_ERROR_NOT_SUPPORTED
+
+PSA Multipart State Checks, AES - GCM
+depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
+aead_multipart_state_test:PSA_KEY_TYPE_AES:"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF":PSA_ALG_GCM:"000102030405060708090A0B0C0D0E0F":"000102030405060708090A0B":"0C0D0E0F101112131415161718191A1B1C1D1E"
+
 PSA signature size: RSA keypair, 1024 bits, PKCS#1 v1.5 raw
 depends_on:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR
 signature_size:PSA_KEY_TYPE_RSA_KEY_PAIR:1024:PSA_ALG_RSA_PKCS1V15_SIGN_RAW:128
@@ -3778,19 +4422,19 @@
 
 PSA key derivation: HKDF SHA-256, request maximum capacity
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
-derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":255 * 32:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865":""
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256):"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865":""
 
 PSA key derivation: HKDF SHA-1, request maximum capacity
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1
-derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):PSA_KEY_DERIVATION_INPUT_SALT:"":PSA_KEY_DERIVATION_INPUT_SECRET:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":PSA_KEY_DERIVATION_INPUT_INFO:"":255 * 20:"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48":""
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):PSA_KEY_DERIVATION_INPUT_SALT:"":PSA_KEY_DERIVATION_INPUT_SECRET:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":PSA_KEY_DERIVATION_INPUT_INFO:"":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_1):"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48":""
 
 PSA key derivation: HKDF SHA-256, request too much capacity
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
-derive_set_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_256):255 * 32 + 1:PSA_ERROR_INVALID_ARGUMENT
+derive_set_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_256):255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256) + 1:PSA_ERROR_INVALID_ARGUMENT
 
 PSA key derivation: HKDF SHA-1, request too much capacity
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1
-derive_set_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_1):255 * 20 + 1:PSA_ERROR_INVALID_ARGUMENT
+derive_set_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_1):255 * PSA_HASH_LENGTH(PSA_ALG_SHA_1) + 1:PSA_ERROR_INVALID_ARGUMENT
 
 PSA key derivation: over capacity 42: output 42+1
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
@@ -3810,19 +4454,19 @@
 
 PSA key derivation: HKDF SHA-256, read maximum capacity minus 1
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
-derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32 - 1
+derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256) - 1
 
 PSA key derivation: HKDF SHA-256, read maximum capacity
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
-derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32
+derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256)
 
 PSA key derivation: TLS 1.2 PRF SHA-256, read maximum capacity minus 1
 depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
-derive_full:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32 - 1
+derive_full:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256) - 1
 
 PSA key derivation: TLS 1.2 PRF SHA-256, read maximum capacity
 depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
-derive_full:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32
+derive_full:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256)
 
 PSA key derivation: HKDF SHA-256, exercise AES128-CTR
 depends_on:PSA_WANT_ALG_CTR:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES
@@ -4061,7 +4705,7 @@
 
 PSA generate key: bad type (RSA public key)
 depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
-generate_key:PSA_KEY_TYPE_RSA_PUBLIC_KEY:512:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED:0
+generate_key:PSA_KEY_TYPE_RSA_PUBLIC_KEY:512:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT:0
 
 PSA generate key: raw data, 0 bits: invalid argument
 # The spec allows either INVALID_ARGUMENT or NOT_SUPPORTED
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 01e5d59..591c296 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -278,6 +278,316 @@
     DERIVE_KEY = 2
 } generate_method;
 
+typedef enum
+{
+    DO_NOT_SET_LENGTHS = 0,
+    SET_LENGTHS_BEFORE_NONCE = 1,
+    SET_LENGTHS_AFTER_NONCE = 2
+} set_lengths_method_t;
+
+typedef enum
+{
+    USE_NULL_TAG = 0,
+    USE_GIVEN_TAG = 1,
+} tag_usage_method_t;
+
+/*!
+ * \brief                           Internal Function for AEAD multipart tests.
+ * \param key_type_arg              Type of key passed in
+ * \param key_data                  The encryption / decryption key data
+ * \param alg_arg                   The type of algorithm used
+ * \param nonce                     Nonce data
+ * \param additional_data           Additional data
+ * \param ad_part_len_arg           If not -1, the length of chunks to
+ *                                  feed additional data in to be encrypted /
+ *                                  decrypted. If -1, no chunking.
+ * \param input_data                Data to encrypt / decrypt
+ * \param data_part_len_arg         If not -1, the length of chunks to feed
+ *                                  the data in to be encrypted / decrypted. If
+ *                                  -1, no chunking
+ * \param set_lengths_method        A member of the set_lengths_method_t enum is
+ *                                  expected here, this controls whether or not
+ *                                  to set lengths, and in what order with
+ *                                  respect to set nonce.
+ * \param expected_output           Expected output
+ * \param is_encrypt                If non-zero this is an encryption operation.
+ * \param do_zero_parts             If non-zero, interleave zero length chunks
+ *                                  with normal length chunks.
+ * \return int                      Zero on failure, non-zero on success.
+ */
+static int aead_multipart_internal_func( int key_type_arg, data_t *key_data,
+                                         int alg_arg,
+                                         data_t *nonce,
+                                         data_t *additional_data,
+                                         int ad_part_len_arg,
+                                         data_t *input_data,
+                                         int data_part_len_arg,
+                                         set_lengths_method_t set_lengths_method,
+                                         data_t *expected_output,
+                                         int is_encrypt,
+                                         int do_zero_parts )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
+    unsigned char *output_data = NULL;
+    unsigned char *part_data = NULL;
+    unsigned char *final_data = NULL;
+    size_t data_true_size = 0;
+    size_t part_data_size = 0;
+    size_t output_size = 0;
+    size_t final_output_size = 0;
+    size_t output_length = 0;
+    size_t key_bits = 0;
+    size_t tag_length = 0;
+    size_t part_offset = 0;
+    size_t part_length = 0;
+    size_t output_part_length = 0;
+    size_t tag_size = 0;
+    size_t ad_part_len = 0;
+    size_t data_part_len = 0;
+    uint8_t tag_buffer[PSA_AEAD_TAG_MAX_SIZE];
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+
+    int test_ok = 0;
+    size_t part_count = 0;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    if( is_encrypt )
+        psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_ENCRYPT  );
+    else
+        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_data->x, key_data->len,
+                                &key ) );
+
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
+
+    tag_length = PSA_AEAD_TAG_LENGTH( key_type, key_bits, alg );
+
+    if( is_encrypt )
+    {
+        /* Tag gets written at end of buffer. */
+        output_size = PSA_AEAD_UPDATE_OUTPUT_SIZE( key_type, alg,
+                                                   ( input_data->len +
+                                                    tag_length ) );
+        data_true_size = input_data->len;
+    }
+    else
+    {
+        output_size = PSA_AEAD_UPDATE_OUTPUT_SIZE( key_type, alg,
+                                                   ( input_data->len -
+                                                    tag_length ) );
+
+        /* Do not want to attempt to decrypt tag. */
+        data_true_size = input_data->len - tag_length;
+    }
+
+    ASSERT_ALLOC( output_data, output_size );
+
+    if( is_encrypt )
+    {
+        final_output_size = PSA_AEAD_FINISH_OUTPUT_SIZE( key_type, alg );
+        TEST_ASSERT( final_output_size <= PSA_AEAD_FINISH_OUTPUT_MAX_SIZE );
+    }
+    else
+    {
+        final_output_size = PSA_AEAD_VERIFY_OUTPUT_SIZE( key_type, alg );
+        TEST_ASSERT( final_output_size <= PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE );
+    }
+
+    ASSERT_ALLOC( final_data, final_output_size );
+
+    if( is_encrypt )
+        status = psa_aead_encrypt_setup( &operation, key, alg );
+    else
+        status = psa_aead_decrypt_setup( &operation, key, alg );
+
+    /* If the operation is not supported, just skip and not fail in case the
+     * encryption involves a common limitation of cryptography hardwares and
+     * an alternative implementation. */
+    if( status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192( key_type, key_data->len * 8 );
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE( alg, nonce->len );
+    }
+
+    PSA_ASSERT( status );
+
+    if( set_lengths_method ==  DO_NOT_SET_LENGTHS )
+        PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+    else if( set_lengths_method == SET_LENGTHS_BEFORE_NONCE )
+    {
+        PSA_ASSERT( psa_aead_set_lengths( &operation, additional_data->len,
+                                          data_true_size ) );
+        PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+    }
+    else if( set_lengths_method ==  SET_LENGTHS_AFTER_NONCE )
+    {
+        PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+        PSA_ASSERT( psa_aead_set_lengths( &operation, additional_data->len,
+                                          data_true_size ) );
+    }
+
+    if( ad_part_len_arg != -1 )
+    {
+        /* Pass additional data in parts */
+        ad_part_len = (size_t) ad_part_len_arg;
+
+        for( part_offset = 0, part_count = 0;
+             part_offset < additional_data->len;
+             part_offset += part_length, part_count++ )
+        {
+            if( do_zero_parts && ( part_count & 0x01 ) )
+            {
+                part_length = 0;
+            }
+            else if( additional_data->len - part_offset < ad_part_len )
+            {
+                part_length = additional_data->len - part_offset;
+            }
+            else
+            {
+                part_length = ad_part_len;
+            }
+
+            PSA_ASSERT( psa_aead_update_ad( &operation,
+                                            additional_data->x + part_offset,
+                                            part_length ) );
+
+        }
+    }
+    else
+    {
+        /* Pass additional data in one go. */
+        PSA_ASSERT( psa_aead_update_ad( &operation, additional_data->x,
+                                        additional_data->len ) );
+    }
+
+    if( data_part_len_arg != -1 )
+    {
+        /* Pass data in parts */
+        data_part_len = ( size_t ) data_part_len_arg;
+        part_data_size = PSA_AEAD_UPDATE_OUTPUT_SIZE( key_type, alg,
+                                                      ( size_t ) data_part_len );
+
+        ASSERT_ALLOC( part_data, part_data_size );
+
+        for( part_offset = 0, part_count = 0;
+             part_offset < data_true_size;
+             part_offset += part_length, part_count++ )
+        {
+            if( do_zero_parts && ( part_count & 0x01 ) )
+            {
+                part_length = 0;
+            }
+            else if( ( data_true_size - part_offset ) < data_part_len )
+            {
+                part_length = ( data_true_size - part_offset );
+            }
+            else
+            {
+                part_length = data_part_len;
+            }
+
+            PSA_ASSERT( psa_aead_update( &operation,
+                                         ( input_data->x + part_offset ),
+                                         part_length, part_data,
+                                         part_data_size,
+                                         &output_part_length ) );
+
+            if( output_data && output_part_length )
+            {
+                memcpy( ( output_data + part_offset ), part_data,
+                        output_part_length );
+            }
+
+            output_length += output_part_length;
+        }
+    }
+    else
+    {
+        /* Pass all data in one go. */
+        PSA_ASSERT( psa_aead_update( &operation, input_data->x,
+                                     data_true_size, output_data,
+                                     output_size, &output_length ) );
+    }
+
+    if( is_encrypt )
+        PSA_ASSERT( psa_aead_finish( &operation, final_data,
+                                     final_output_size,
+                                     &output_part_length,
+                                     tag_buffer, tag_length,
+                                     &tag_size ) );
+    else
+    {
+        PSA_ASSERT( psa_aead_verify( &operation, final_data,
+                                     final_output_size,
+                                     &output_part_length,
+                                     ( input_data->x + data_true_size ),
+                                     tag_length ) );
+    }
+
+    if( output_data && output_part_length )
+        memcpy( ( output_data + output_length ), final_data,
+                output_part_length );
+
+    output_length += output_part_length;
+
+
+    /* For all currently defined algorithms, PSA_AEAD_xxx_OUTPUT_SIZE
+     * should be exact.*/
+    if( is_encrypt )
+    {
+        TEST_EQUAL( tag_length, tag_size );
+
+        if( output_data && tag_length )
+            memcpy( ( output_data + output_length ), tag_buffer,
+                    tag_length );
+
+        output_length += tag_length;
+
+        TEST_EQUAL( output_length,
+                      PSA_AEAD_ENCRYPT_OUTPUT_SIZE( key_type, alg,
+                                                    input_data->len ) );
+        TEST_ASSERT( output_length <=
+                      PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE( input_data->len ) );
+    }
+    else
+    {
+       TEST_EQUAL( output_length,
+                      PSA_AEAD_DECRYPT_OUTPUT_SIZE( key_type, alg,
+                                                    input_data->len ) );
+       TEST_ASSERT( output_length <=
+                      PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE( input_data->len ) );
+    }
+
+
+    ASSERT_COMPARE( expected_output->x, expected_output->len,
+                    output_data, output_length );
+
+
+    test_ok = 1;
+
+exit:
+    psa_destroy_key( key );
+    psa_aead_abort( &operation );
+    mbedtls_free( output_data );
+    mbedtls_free( part_data );
+    mbedtls_free( final_data );
+    PSA_DONE( );
+
+    return( test_ok );
+}
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -3474,6 +3784,1209 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void aead_multipart_encrypt( int key_type_arg, data_t *key_data,
+                             int alg_arg,
+                             data_t *nonce,
+                             data_t *additional_data,
+                             data_t *input_data,
+                             int do_set_lengths,
+                             data_t *expected_output )
+{
+    size_t ad_part_len = 0;
+    size_t data_part_len = 0;
+    set_lengths_method_t set_lengths_method = DO_NOT_SET_LENGTHS;
+
+    for( ad_part_len = 1; ad_part_len <= additional_data->len; ad_part_len++ )
+    {
+        mbedtls_test_set_step( ad_part_len );
+
+        if( do_set_lengths )
+        {
+            if( ad_part_len & 0x01 )
+                set_lengths_method = SET_LENGTHS_AFTER_NONCE;
+            else
+                set_lengths_method = SET_LENGTHS_BEFORE_NONCE;
+        }
+
+        /* Split ad into length(ad_part_len) parts. */
+        if( !aead_multipart_internal_func( key_type_arg, key_data,
+                                           alg_arg, nonce,
+                                           additional_data,
+                                           ad_part_len,
+                                           input_data, -1,
+                                           set_lengths_method,
+                                           expected_output,
+                                           1, 0 ) )
+            break;
+
+        /* length(0) part, length(ad_part_len) part, length(0) part... */
+        mbedtls_test_set_step( 1000 + ad_part_len );
+
+        if( !aead_multipart_internal_func( key_type_arg, key_data,
+                                           alg_arg, nonce,
+                                           additional_data,
+                                           ad_part_len,
+                                           input_data, -1,
+                                           set_lengths_method,
+                                           expected_output,
+                                           1, 1 ) )
+            break;
+    }
+
+    for( data_part_len = 1; data_part_len <= input_data->len; data_part_len++ )
+    {
+        /* Split data into length(data_part_len) parts. */
+        mbedtls_test_set_step( 2000 + data_part_len );
+
+        if( do_set_lengths )
+        {
+            if( data_part_len & 0x01 )
+                set_lengths_method = SET_LENGTHS_AFTER_NONCE;
+            else
+                set_lengths_method = SET_LENGTHS_BEFORE_NONCE;
+        }
+
+        if( !aead_multipart_internal_func( key_type_arg, key_data,
+                                           alg_arg, nonce,
+                                           additional_data, -1,
+                                           input_data, data_part_len,
+                                           set_lengths_method,
+                                           expected_output,
+                                           1, 0 ) )
+            break;
+
+        /* length(0) part, length(data_part_len) part, length(0) part... */
+        mbedtls_test_set_step( 3000 + data_part_len );
+
+        if( !aead_multipart_internal_func( key_type_arg, key_data,
+                                           alg_arg, nonce,
+                                           additional_data, -1,
+                                           input_data, data_part_len,
+                                           set_lengths_method,
+                                           expected_output,
+                                           1, 1 ) )
+            break;
+    }
+
+    /* Goto is required to silence warnings about unused labels, as we
+     * don't actually do any test assertions in this function. */
+    goto exit;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_multipart_decrypt( int key_type_arg, data_t *key_data,
+                             int alg_arg,
+                             data_t *nonce,
+                             data_t *additional_data,
+                             data_t *input_data,
+                             int do_set_lengths,
+                             data_t *expected_output )
+{
+    size_t ad_part_len = 0;
+    size_t data_part_len = 0;
+    set_lengths_method_t set_lengths_method = DO_NOT_SET_LENGTHS;
+
+    for( ad_part_len = 1; ad_part_len <= additional_data->len; ad_part_len++ )
+    {
+        /* Split ad into length(ad_part_len) parts. */
+        mbedtls_test_set_step( ad_part_len );
+
+        if( do_set_lengths )
+        {
+            if( ad_part_len & 0x01 )
+                set_lengths_method = SET_LENGTHS_AFTER_NONCE;
+            else
+                set_lengths_method = SET_LENGTHS_BEFORE_NONCE;
+        }
+
+        if( !aead_multipart_internal_func( key_type_arg, key_data,
+                                           alg_arg, nonce,
+                                           additional_data,
+                                           ad_part_len,
+                                           input_data, -1,
+                                           set_lengths_method,
+                                           expected_output,
+                                           0, 0 ) )
+            break;
+
+        /* length(0) part, length(ad_part_len) part, length(0) part... */
+        mbedtls_test_set_step( 1000 + ad_part_len );
+
+        if( !aead_multipart_internal_func( key_type_arg, key_data,
+                                           alg_arg, nonce,
+                                           additional_data,
+                                           ad_part_len,
+                                           input_data, -1,
+                                           set_lengths_method,
+                                           expected_output,
+                                           0, 1 ) )
+            break;
+    }
+
+    for( data_part_len = 1; data_part_len <= input_data->len; data_part_len++ )
+    {
+        /* Split data into length(data_part_len) parts. */
+        mbedtls_test_set_step( 2000 + data_part_len );
+
+        if( do_set_lengths )
+        {
+            if( data_part_len & 0x01 )
+                set_lengths_method = SET_LENGTHS_AFTER_NONCE;
+            else
+                set_lengths_method = SET_LENGTHS_BEFORE_NONCE;
+        }
+
+        if( !aead_multipart_internal_func( key_type_arg, key_data,
+                                           alg_arg, nonce,
+                                           additional_data, -1,
+                                           input_data, data_part_len,
+                                           set_lengths_method,
+                                           expected_output,
+                                           0, 0 ) )
+            break;
+
+        /* length(0) part, length(data_part_len) part, length(0) part... */
+        mbedtls_test_set_step( 3000 + data_part_len );
+
+        if( !aead_multipart_internal_func( key_type_arg, key_data,
+                                           alg_arg, nonce,
+                                           additional_data, -1,
+                                           input_data, data_part_len,
+                                           set_lengths_method,
+                                           expected_output,
+                                           0, 1 ) )
+            break;
+    }
+
+    /* Goto is required to silence warnings about unused labels, as we
+     * don't actually do any test assertions in this function. */
+    goto exit;
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_multipart_generate_nonce( int key_type_arg, data_t *key_data,
+                                    int alg_arg,
+                                    int nonce_length,
+                                    int expected_nonce_length_arg,
+                                    data_t *additional_data,
+                                    data_t *input_data,
+                                    int expected_status_arg )
+{
+
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
+    uint8_t nonce_buffer[PSA_AEAD_NONCE_MAX_SIZE];
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    psa_status_t expected_status = expected_status_arg;
+    size_t actual_nonce_length = 0;
+    size_t expected_nonce_length = expected_nonce_length_arg;
+    unsigned char *output = NULL;
+    unsigned char *ciphertext = NULL;
+    size_t output_size = 0;
+    size_t ciphertext_size = 0;
+    size_t ciphertext_length = 0;
+    size_t tag_length = 0;
+    uint8_t tag_buffer[PSA_AEAD_TAG_MAX_SIZE];
+
+    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_data->x, key_data->len,
+                                &key ) );
+
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+
+    output_size = PSA_AEAD_UPDATE_OUTPUT_SIZE( key_type, alg, input_data->len );
+
+    ASSERT_ALLOC( output, output_size );
+
+    ciphertext_size = PSA_AEAD_FINISH_OUTPUT_SIZE( key_type, alg );
+
+    TEST_ASSERT( ciphertext_size <= PSA_AEAD_FINISH_OUTPUT_MAX_SIZE );
+
+    ASSERT_ALLOC( ciphertext, ciphertext_size );
+
+    status = psa_aead_encrypt_setup( &operation, key, alg );
+
+    /* If the operation is not supported, just skip and not fail in case the
+     * encryption involves a common limitation of cryptography hardwares and
+     * an alternative implementation. */
+    if( status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192( key_type, key_data->len * 8 );
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE( alg, nonce_length );
+    }
+
+    PSA_ASSERT( status );
+
+    status = psa_aead_generate_nonce( &operation, nonce_buffer,
+                                      nonce_length,
+                                      &actual_nonce_length );
+
+    TEST_EQUAL( status, expected_status );
+
+    TEST_EQUAL( actual_nonce_length, expected_nonce_length );
+
+    if( expected_status == PSA_SUCCESS )
+        TEST_EQUAL( actual_nonce_length, PSA_AEAD_NONCE_LENGTH( key_type,
+                                                                alg ) );
+
+    TEST_ASSERT( actual_nonce_length < PSA_AEAD_NONCE_MAX_SIZE );
+
+    if( expected_status == PSA_SUCCESS )
+    {
+
+        /* Ensure we can still complete operation. */
+
+        PSA_ASSERT( psa_aead_update_ad( &operation, additional_data->x,
+                                        additional_data->len ) );
+
+        PSA_ASSERT( psa_aead_update( &operation, input_data->x, input_data->len,
+                                     output, output_size,
+                                     &ciphertext_length ) );
+
+        PSA_ASSERT( psa_aead_finish( &operation, ciphertext, ciphertext_size,
+                                     &ciphertext_length, tag_buffer,
+                                     PSA_AEAD_TAG_MAX_SIZE, &tag_length ) );
+    }
+
+exit:
+    psa_destroy_key( key );
+    mbedtls_free( output );
+    mbedtls_free( ciphertext );
+    psa_aead_abort( &operation );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_multipart_set_nonce( int key_type_arg, data_t *key_data,
+                               int alg_arg,
+                               int nonce_length_arg,
+                               data_t *additional_data,
+                               data_t *input_data,
+                               int expected_status_arg )
+{
+
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
+    uint8_t *nonce_buffer = NULL;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    psa_status_t expected_status = expected_status_arg;
+    unsigned char *output = NULL;
+    unsigned char *ciphertext = NULL;
+    size_t nonce_length;
+    size_t output_size = 0;
+    size_t ciphertext_size = 0;
+    size_t ciphertext_length = 0;
+    size_t tag_length = 0;
+    uint8_t tag_buffer[PSA_AEAD_TAG_MAX_SIZE];
+    size_t index = 0;
+
+    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_data->x, key_data->len,
+                                &key ) );
+
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+
+    output_size = PSA_AEAD_UPDATE_OUTPUT_SIZE( key_type, alg, input_data->len );
+
+    ASSERT_ALLOC( output, output_size );
+
+    ciphertext_size = PSA_AEAD_FINISH_OUTPUT_SIZE( key_type, alg );
+
+    TEST_ASSERT( ciphertext_size <= PSA_AEAD_FINISH_OUTPUT_MAX_SIZE );
+
+    ASSERT_ALLOC( ciphertext, ciphertext_size );
+
+    status = psa_aead_encrypt_setup( &operation, key, alg );
+
+    /* If the operation is not supported, just skip and not fail in case the
+     * encryption involves a common limitation of cryptography hardwares and
+     * an alternative implementation. */
+    if( status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192( key_type, key_data->len * 8 );
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE( alg, nonce_length_arg );
+    }
+
+    PSA_ASSERT( status );
+
+    /* -1 == zero length and valid buffer, 0 = zero length and NULL buffer. */
+    if( nonce_length_arg == -1 )
+    {
+         /* Arbitrary size buffer, to test zero length valid buffer. */
+         ASSERT_ALLOC( nonce_buffer, 4 );
+         nonce_length = 0;
+    }
+    else
+    {
+        /* If length is zero, then this will return NULL. */
+        nonce_length = ( size_t ) nonce_length_arg;
+        ASSERT_ALLOC( nonce_buffer, nonce_length );
+
+        if( nonce_buffer )
+        {
+            for( index = 0; index < nonce_length - 1; ++index )
+            {
+                nonce_buffer[index] = 'a' + index;
+            }
+        }
+    }
+
+    status = psa_aead_set_nonce( &operation, nonce_buffer, nonce_length );
+
+    TEST_EQUAL( status, expected_status );
+
+    if( expected_status == PSA_SUCCESS )
+    {
+        /* Ensure we can still complete operation. */
+
+        PSA_ASSERT( psa_aead_update_ad( &operation, additional_data->x,
+                                        additional_data->len ) );
+
+        PSA_ASSERT( psa_aead_update( &operation, input_data->x, input_data->len,
+                                     output, output_size,
+                                     &ciphertext_length ) );
+
+        PSA_ASSERT( psa_aead_finish( &operation, ciphertext, ciphertext_size,
+                                     &ciphertext_length, tag_buffer,
+                                     PSA_AEAD_TAG_MAX_SIZE, &tag_length ) );
+    }
+
+exit:
+    psa_destroy_key( key );
+    mbedtls_free( output );
+    mbedtls_free( ciphertext );
+    mbedtls_free( nonce_buffer );
+    psa_aead_abort( &operation );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_multipart_update_buffer_test( int key_type_arg, data_t *key_data,
+                                       int alg_arg,
+                                       int output_size_arg,
+                                       data_t *nonce,
+                                       data_t *additional_data,
+                                       data_t *input_data,
+                                       int expected_status_arg )
+{
+
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    psa_status_t expected_status = expected_status_arg;
+    unsigned char *output = NULL;
+    unsigned char *ciphertext = NULL;
+    size_t output_size = output_size_arg;
+    size_t ciphertext_size = 0;
+    size_t ciphertext_length = 0;
+    size_t tag_length = 0;
+    uint8_t tag_buffer[PSA_AEAD_TAG_MAX_SIZE];
+
+    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_data->x, key_data->len,
+                                &key ) );
+
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+
+    ASSERT_ALLOC( output, output_size );
+
+    ciphertext_size = PSA_AEAD_FINISH_OUTPUT_SIZE( key_type, alg );
+
+    ASSERT_ALLOC( ciphertext, ciphertext_size );
+
+    status = psa_aead_encrypt_setup( &operation, key, alg );
+
+    /* If the operation is not supported, just skip and not fail in case the
+     * encryption involves a common limitation of cryptography hardwares and
+     * an alternative implementation. */
+    if( status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192( key_type, key_data->len * 8 );
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE( alg, nonce->len );
+    }
+
+    PSA_ASSERT( status );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_update_ad( &operation, additional_data->x,
+                                    additional_data->len ) );
+
+    status = psa_aead_update( &operation, input_data->x, input_data->len,
+                              output, output_size, &ciphertext_length );
+
+    TEST_EQUAL( status, expected_status );
+
+    if( expected_status == PSA_SUCCESS )
+    {
+        /* Ensure we can still complete operation. */
+        PSA_ASSERT( psa_aead_finish( &operation, ciphertext, ciphertext_size,
+                                     &ciphertext_length, tag_buffer,
+                                     PSA_AEAD_TAG_MAX_SIZE, &tag_length ) );
+    }
+
+exit:
+    psa_destroy_key( key );
+    mbedtls_free( output );
+    mbedtls_free( ciphertext );
+    psa_aead_abort( &operation );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_multipart_finish_buffer_test( int key_type_arg, data_t *key_data,
+                                        int alg_arg,
+                                        int finish_ciphertext_size_arg,
+                                        int tag_size_arg,
+                                        data_t *nonce,
+                                        data_t *additional_data,
+                                        data_t *input_data,
+                                        int expected_status_arg )
+{
+
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    psa_status_t expected_status = expected_status_arg;
+    unsigned char *ciphertext = NULL;
+    unsigned char *finish_ciphertext = NULL;
+    unsigned char *tag_buffer = NULL;
+    size_t ciphertext_size = 0;
+    size_t ciphertext_length = 0;
+    size_t finish_ciphertext_size = ( size_t ) finish_ciphertext_size_arg;
+    size_t tag_size = ( size_t ) tag_size_arg;
+    size_t tag_length = 0;
+
+    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_data->x, key_data->len,
+                                &key ) );
+
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+
+    ciphertext_size = PSA_AEAD_UPDATE_OUTPUT_SIZE( key_type, alg, input_data->len );
+
+    ASSERT_ALLOC( ciphertext, ciphertext_size );
+
+    ASSERT_ALLOC( finish_ciphertext, finish_ciphertext_size );
+
+    ASSERT_ALLOC( tag_buffer, tag_size );
+
+    status = psa_aead_encrypt_setup( &operation, key, alg );
+
+    /* If the operation is not supported, just skip and not fail in case the
+     * encryption involves a common limitation of cryptography hardwares and
+     * an alternative implementation. */
+    if( status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192( key_type, key_data->len * 8 );
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE( alg, nonce->len );
+    }
+
+    PSA_ASSERT( status );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_update_ad( &operation, additional_data->x,
+                                    additional_data->len ) );
+
+    PSA_ASSERT( psa_aead_update( &operation, input_data->x, input_data->len,
+                              ciphertext, ciphertext_size, &ciphertext_length ) );
+
+    /* Ensure we can still complete operation. */
+    status = psa_aead_finish( &operation, finish_ciphertext,
+                              finish_ciphertext_size,
+                              &ciphertext_length, tag_buffer,
+                              tag_size, &tag_length );
+
+    TEST_EQUAL( status, expected_status );
+
+exit:
+    psa_destroy_key( key );
+    mbedtls_free( ciphertext );
+    mbedtls_free( finish_ciphertext );
+    mbedtls_free( tag_buffer );
+    psa_aead_abort( &operation );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_multipart_verify( int key_type_arg, data_t *key_data,
+                            int alg_arg,
+                            data_t *nonce,
+                            data_t *additional_data,
+                            data_t *input_data,
+                            data_t *tag,
+                            int tag_usage_arg,
+                            int expected_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    psa_status_t expected_status = expected_status_arg;
+    unsigned char *plaintext = NULL;
+    unsigned char *finish_plaintext = NULL;
+    size_t plaintext_size = 0;
+    size_t plaintext_length = 0;
+    size_t verify_plaintext_size = 0;
+    tag_usage_method_t tag_usage = tag_usage_arg;
+    unsigned char *tag_buffer = NULL;
+    size_t tag_size = 0;
+
+    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_data->x, key_data->len,
+                                &key ) );
+
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+
+    plaintext_size = PSA_AEAD_UPDATE_OUTPUT_SIZE( key_type, alg,
+                                                  input_data->len );
+
+    ASSERT_ALLOC( plaintext, plaintext_size );
+
+    verify_plaintext_size = PSA_AEAD_VERIFY_OUTPUT_SIZE( key_type, alg );
+
+    ASSERT_ALLOC( finish_plaintext, verify_plaintext_size );
+
+    status = psa_aead_decrypt_setup( &operation, key, alg );
+
+    /* If the operation is not supported, just skip and not fail in case the
+     * encryption involves a common limitation of cryptography hardwares and
+     * an alternative implementation. */
+    if( status == PSA_ERROR_NOT_SUPPORTED )
+    {
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192( key_type, key_data->len * 8 );
+        MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE( alg, nonce->len );
+    }
+
+    PSA_ASSERT( status );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_update_ad( &operation, additional_data->x,
+                                    additional_data->len ) );
+
+    PSA_ASSERT( psa_aead_update( &operation, input_data->x,
+                                 input_data->len,
+                                 plaintext, plaintext_size,
+                                 &plaintext_length ) );
+
+    if( tag_usage == USE_GIVEN_TAG )
+    {
+        tag_buffer = tag->x;
+        tag_size = tag->len;
+    }
+
+    status = psa_aead_verify( &operation, finish_plaintext,
+                              verify_plaintext_size,
+                              &plaintext_length,
+                              tag_buffer, tag_size );
+
+    TEST_EQUAL( status, expected_status );
+
+exit:
+    psa_destroy_key( key );
+    mbedtls_free( plaintext );
+    mbedtls_free( finish_plaintext );
+    psa_aead_abort( &operation );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_multipart_setup( int key_type_arg, data_t *key_data,
+                           int alg_arg, int expected_status_arg )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    psa_status_t expected_status = expected_status_arg;
+
+    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_data->x, key_data->len,
+                                &key ) );
+
+    status = psa_aead_encrypt_setup( &operation, key, alg );
+
+    TEST_EQUAL( status, expected_status );
+
+    psa_aead_abort( &operation );
+
+    status = psa_aead_decrypt_setup( &operation, key, alg );
+
+    TEST_EQUAL(status, expected_status );
+
+exit:
+    psa_destroy_key( key );
+    psa_aead_abort( &operation );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void aead_multipart_state_test( int key_type_arg, data_t *key_data,
+                                int alg_arg,
+                                data_t *nonce,
+                                data_t *additional_data,
+                                data_t *input_data )
+{
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_type_t key_type = key_type_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
+    unsigned char *output_data = NULL;
+    unsigned char *final_data = NULL;
+    size_t output_size = 0;
+    size_t finish_output_size = 0;
+    size_t output_length = 0;
+    size_t key_bits = 0;
+    size_t tag_length = 0;
+    size_t tag_size = 0;
+    size_t nonce_length = 0;
+    uint8_t nonce_buffer[PSA_AEAD_NONCE_MAX_SIZE];
+    uint8_t tag_buffer[PSA_AEAD_TAG_MAX_SIZE];
+    size_t output_part_length = 0;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+
+    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_data->x, key_data->len,
+                                &key ) );
+
+    PSA_ASSERT( psa_get_key_attributes( key, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
+
+    tag_length = PSA_AEAD_TAG_LENGTH( key_type, key_bits, alg );
+
+    TEST_ASSERT( tag_length <= PSA_AEAD_TAG_MAX_SIZE );
+
+    output_size = PSA_AEAD_UPDATE_OUTPUT_SIZE( key_type, alg, input_data->len );
+
+    ASSERT_ALLOC( output_data, output_size );
+
+    finish_output_size = PSA_AEAD_FINISH_OUTPUT_SIZE( key_type, alg );
+
+    TEST_ASSERT( finish_output_size <= PSA_AEAD_FINISH_OUTPUT_MAX_SIZE );
+
+    ASSERT_ALLOC( final_data, finish_output_size );
+
+    /* Test all operations error without calling setup first. */
+
+    TEST_EQUAL( psa_aead_set_nonce( &operation, nonce->x, nonce->len ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    TEST_EQUAL( psa_aead_generate_nonce( &operation, nonce_buffer,
+                                         PSA_AEAD_NONCE_MAX_SIZE,
+                                         &nonce_length ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    TEST_EQUAL( psa_aead_set_lengths( &operation, additional_data->len,
+                                      input_data->len ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    TEST_EQUAL( psa_aead_update_ad( &operation, additional_data->x,
+                                    additional_data->len ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    TEST_EQUAL( psa_aead_update( &operation, input_data->x,
+                                 input_data->len, output_data,
+                                 output_size, &output_length ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    TEST_EQUAL( psa_aead_finish( &operation, final_data,
+                                 finish_output_size,
+                                 &output_part_length,
+                                 tag_buffer, tag_length,
+                                 &tag_size ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    TEST_EQUAL( psa_aead_verify( &operation, final_data,
+                                 finish_output_size,
+                                 &output_part_length,
+                                 tag_buffer,
+                                 tag_length ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* Test for double setups. */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    TEST_EQUAL( psa_aead_encrypt_setup( &operation, key, alg ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    PSA_ASSERT( psa_aead_decrypt_setup( &operation, key, alg ) );
+
+    TEST_EQUAL( psa_aead_decrypt_setup( &operation, key, alg ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    TEST_EQUAL( psa_aead_decrypt_setup( &operation, key, alg ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    PSA_ASSERT( psa_aead_decrypt_setup( &operation, key, alg ) );
+
+    TEST_EQUAL( psa_aead_encrypt_setup( &operation, key, alg ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* Test for not setting a nonce. */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    TEST_EQUAL( psa_aead_update_ad( &operation, additional_data->x,
+                                    additional_data->len ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    TEST_EQUAL( psa_aead_update( &operation, input_data->x,
+                                 input_data->len, output_data,
+                                 output_size, &output_length ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    TEST_EQUAL( psa_aead_finish( &operation, final_data,
+                                 finish_output_size,
+                                 &output_part_length,
+                                 tag_buffer, tag_length,
+                                 &tag_size ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    PSA_ASSERT( psa_aead_decrypt_setup( &operation, key, alg ) );
+
+    TEST_EQUAL( psa_aead_verify( &operation, final_data,
+                                 finish_output_size,
+                                 &output_part_length,
+                                 tag_buffer,
+                                 tag_length ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* Test for double setting nonce. */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    TEST_EQUAL( psa_aead_set_nonce( &operation, nonce->x, nonce->len ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* Test for double generating nonce. */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_generate_nonce( &operation, nonce_buffer,
+                                         PSA_AEAD_NONCE_MAX_SIZE,
+                                         &nonce_length ) );
+
+    TEST_EQUAL( psa_aead_generate_nonce( &operation, nonce_buffer,
+                                         PSA_AEAD_NONCE_MAX_SIZE,
+                                         &nonce_length ),
+                PSA_ERROR_BAD_STATE );
+
+
+    psa_aead_abort( &operation );
+
+    /* Test for generate nonce then set and vice versa */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_generate_nonce( &operation, nonce_buffer,
+                                         PSA_AEAD_NONCE_MAX_SIZE,
+                                         &nonce_length ) );
+
+    TEST_EQUAL( psa_aead_set_nonce( &operation, nonce->x, nonce->len ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    TEST_EQUAL( psa_aead_generate_nonce( &operation, nonce_buffer,
+                                         PSA_AEAD_NONCE_MAX_SIZE,
+                                         &nonce_length ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* Test for generating nonce in decrypt setup. */
+
+    PSA_ASSERT( psa_aead_decrypt_setup( &operation, key, alg ) );
+
+    TEST_EQUAL( psa_aead_generate_nonce( &operation, nonce_buffer,
+                                         PSA_AEAD_NONCE_MAX_SIZE,
+                                         &nonce_length ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* Test for setting lengths twice. */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_set_lengths( &operation, additional_data->len,
+                                      input_data->len ) );
+
+    TEST_EQUAL( psa_aead_set_lengths( &operation, additional_data->len,
+                                      input_data->len ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* Test for setting lengths after already starting data. */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_update_ad( &operation, additional_data->x,
+                                    additional_data->len ) );
+
+    TEST_EQUAL( psa_aead_set_lengths( &operation, additional_data->len,
+                                      input_data->len ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_update( &operation, input_data->x,
+                                 input_data->len, output_data,
+                                 output_size, &output_length ) );
+
+    TEST_EQUAL( psa_aead_set_lengths( &operation, additional_data->len,
+                                      input_data->len ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* Test for not sending any additional data or data after setting non zero
+     * lengths for them. (encrypt) */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_set_lengths( &operation, additional_data->len,
+                                      input_data->len ) );
+
+    TEST_EQUAL( psa_aead_finish( &operation, final_data,
+                                 finish_output_size,
+                                 &output_part_length,
+                                 tag_buffer, tag_length,
+                                 &tag_size ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    psa_aead_abort( &operation );
+
+    /* Test for not sending any additional data or data after setting non-zero
+     * lengths for them. (decrypt) */
+
+    PSA_ASSERT( psa_aead_decrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_set_lengths( &operation, additional_data->len,
+                                      input_data->len ) );
+
+    TEST_EQUAL( psa_aead_verify( &operation, final_data,
+                                 finish_output_size,
+                                 &output_part_length,
+                                 tag_buffer,
+                                 tag_length ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    psa_aead_abort( &operation );
+
+    /* Test for not sending any additional data after setting a non-zero length
+     * for it. */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_set_lengths( &operation, additional_data->len,
+                                      input_data->len ) );
+
+    TEST_EQUAL( psa_aead_update( &operation, input_data->x,
+                                 input_data->len, output_data,
+                                 output_size, &output_length ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    psa_aead_abort( &operation );
+
+    /* Test for not sending any data after setting a non-zero length for it.*/
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_set_lengths( &operation, additional_data->len,
+                                      input_data->len ) );
+
+    PSA_ASSERT( psa_aead_update_ad( &operation, additional_data->x,
+                                    additional_data->len ) );
+
+    TEST_EQUAL( psa_aead_finish( &operation, final_data,
+                                 finish_output_size,
+                                 &output_part_length,
+                                 tag_buffer, tag_length,
+                                 &tag_size ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    psa_aead_abort( &operation );
+
+    /* Test for sending too much additional data after setting lengths. */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_set_lengths( &operation, 0, 0 ) );
+
+
+    TEST_EQUAL( psa_aead_update_ad( &operation, additional_data->x,
+                                    additional_data->len ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_set_lengths( &operation, additional_data->len,
+                                      input_data->len ) );
+
+    PSA_ASSERT( psa_aead_update_ad( &operation, additional_data->x,
+                                    additional_data->len ) );
+
+    TEST_EQUAL( psa_aead_update_ad( &operation, additional_data->x,
+                                    1 ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    psa_aead_abort( &operation );
+
+    /* Test for sending too much data after setting lengths. */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_set_lengths( &operation, 0, 0 ) );
+
+    TEST_EQUAL( psa_aead_update( &operation, input_data->x,
+                                 input_data->len, output_data,
+                                 output_size, &output_length ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    psa_aead_abort( &operation );
+
+    /* ------------------------------------------------------- */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_set_lengths( &operation, additional_data->len,
+                                      input_data->len ) );
+
+    PSA_ASSERT( psa_aead_update_ad( &operation, additional_data->x,
+                                    additional_data->len ) );
+
+    PSA_ASSERT( psa_aead_update( &operation, input_data->x,
+                                 input_data->len, output_data,
+                                 output_size, &output_length ) );
+
+    TEST_EQUAL( psa_aead_update( &operation, input_data->x,
+                                 1, output_data,
+                                 output_size, &output_length ),
+                PSA_ERROR_INVALID_ARGUMENT );
+
+    psa_aead_abort( &operation );
+
+    /* Test sending additional data after data. */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    PSA_ASSERT( psa_aead_update( &operation, input_data->x,
+                                 input_data->len, output_data,
+                                 output_size, &output_length ) );
+
+    TEST_EQUAL( psa_aead_update_ad( &operation, additional_data->x,
+                                    additional_data->len ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* Test calling finish on decryption. */
+
+    PSA_ASSERT( psa_aead_decrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    TEST_EQUAL( psa_aead_finish( &operation, final_data,
+                                 finish_output_size,
+                                 &output_part_length,
+                                 tag_buffer, tag_length,
+                                 &tag_size ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+    /* Test calling verify on encryption. */
+
+    PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
+
+    PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
+
+    TEST_EQUAL( psa_aead_verify( &operation, final_data,
+                                 finish_output_size,
+                                 &output_part_length,
+                                 tag_buffer,
+                                 tag_length ),
+                PSA_ERROR_BAD_STATE );
+
+    psa_aead_abort( &operation );
+
+
+exit:
+    psa_destroy_key( key );
+    psa_aead_abort( &operation );
+    mbedtls_free( output_data );
+    mbedtls_free( final_data );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void signature_size( int type_arg,
                      int bits,
                      int alg_arg,
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
index 6d78ad5..bc6ff34 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
@@ -1063,7 +1063,7 @@
                                input_data->x, input_data->len,
                                output_data, output_size,
                                &output_length );
-    TEST_EQUAL( mbedtls_test_driver_aead_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_aead_hooks.hits_encrypt, 1 );
     TEST_EQUAL( mbedtls_test_driver_aead_hooks.driver_status, forced_status );
 
     TEST_EQUAL( status, ( forced_status == PSA_ERROR_NOT_SUPPORTED ) ?
@@ -1127,7 +1127,7 @@
                                input_data->x, input_data->len,
                                output_data, output_size,
                                &output_length );
-    TEST_EQUAL( mbedtls_test_driver_aead_hooks.hits, 1 );
+    TEST_EQUAL( mbedtls_test_driver_aead_hooks.hits_decrypt, 1 );
     TEST_EQUAL( mbedtls_test_driver_aead_hooks.driver_status, forced_status );
 
     TEST_EQUAL( status, ( forced_status == PSA_ERROR_NOT_SUPPORTED ) ?
diff --git a/tests/suites/test_suite_psa_crypto_not_supported.function b/tests/suites/test_suite_psa_crypto_not_supported.function
index e3253d8..0665230 100644
--- a/tests/suites/test_suite_psa_crypto_not_supported.function
+++ b/tests/suites/test_suite_psa_crypto_not_supported.function
@@ -50,3 +50,22 @@
     PSA_DONE( );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void generate_invalid_argument( int key_type, int bits )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = INVALID_KEY_ID;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    psa_set_key_type( &attributes, key_type );
+    psa_set_key_bits( &attributes, bits );
+    TEST_EQUAL( psa_generate_key( &attributes, &key_id ),
+                PSA_ERROR_INVALID_ARGUMENT );
+    TEST_ASSERT( mbedtls_svc_key_id_equal( key_id, MBEDTLS_SVC_KEY_ID_INIT ) );
+
+exit:
+    psa_destroy_key( key_id );
+    PSA_DONE( );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_psa_crypto_slot_management.data b/tests/suites/test_suite_psa_crypto_slot_management.data
index 68b196d..1477734 100644
--- a/tests/suites/test_suite_psa_crypto_slot_management.data
+++ b/tests/suites/test_suite_psa_crypto_slot_management.data
@@ -160,7 +160,7 @@
 create_fail:PSA_KEY_LIFETIME_PERSISTENT:PSA_KEY_ID_USER_MAX + 1:PSA_ERROR_INVALID_ARGUMENT
 
 Open not supported
-depends_on:!MBEDTLS_PSA_CRYPTO_STORAGE_C
+depends_on:!MBEDTLS_PSA_CRYPTO_STORAGE_C:!MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS
 open_fail:1:PSA_ERROR_NOT_SUPPORTED
 
 Create not supported