Merge pull request #6666 from daverodgman/fast_unaligned

Fast unaligned memory access macros
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 94fb020..50a4901 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -14,6 +14,6 @@
 
 ## Notes for the submitter
 
-Please refer to the [contributing guidelines](../CONTRIBUTING.md), especially the
+Please refer to the [contributing guidelines](https://github.com/Mbed-TLS/mbedtls/blob/development/CONTRIBUTING.md), especially the
 checklist for PR contributors.
 
diff --git a/.uncrustify.cfg b/.uncrustify.cfg
new file mode 100644
index 0000000..ac9173e
--- /dev/null
+++ b/.uncrustify.cfg
@@ -0,0 +1,254 @@
+# Configuration options for Uncrustify specifying the Mbed TLS code style.
+#
+# Note: The code style represented by this file has not yet been introduced
+# to Mbed TLS.
+#
+# 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.
+
+
+# Line length options
+
+# Wrap lines at 100 characters
+code_width = 100
+
+# Allow splitting long for statements between the condition statements
+ls_for_split_full = true
+
+# Allow splitting function calls between arguments
+ls_func_split_full = true
+
+input_tab_size = 4
+
+# Spaces-only indentation
+indent_with_tabs = 0
+
+indent_columns = 4
+
+# Indent 'case' 1 level from 'switch'
+indent_switch_case = indent_columns
+
+# Line-up strings broken by '\'
+indent_align_string = true
+
+# Braces on the same line (Egyptian-style braces)
+nl_enum_brace = remove
+nl_union_brace = remove
+nl_struct_brace = remove
+nl_do_brace = remove
+nl_if_brace = remove
+nl_for_brace = remove
+nl_else_brace = remove
+nl_while_brace = remove
+nl_switch_brace = remove
+
+# Braces on same line as keywords that follow them - 'else' and the 'while' in 'do {} while ()';
+nl_brace_else = remove
+nl_brace_while = remove
+# Space before else on the same line
+sp_brace_else = add
+# If else is on the same line as '{', force exactly 1 space between them
+sp_else_brace = force
+
+# Functions are the exception and have braces on the next line
+nl_fcall_brace = add
+nl_fdef_brace = add
+
+# Force exactly one space between ')' and '{' in statements
+sp_sparen_brace = force
+
+# At least 1 space around assignment
+sp_assign = add
+
+# Remove spaces around the preprocessor '##' token-concatenate
+sp_pp_concat = ignore
+
+# At least 1 space around '||' and '&&'
+sp_bool = add
+
+# But no space after the '!' operator
+sp_not = remove
+
+# No space after the bitwise-not '~' operator
+sp_inv = remove
+
+# No space after the addressof '&' operator
+sp_addr = remove
+
+# No space around the member '.' and '->' operators
+sp_member = remove
+
+# No space after the dereference '*' operator
+sp_deref = remove
+
+# No space after a unary negation '-'
+sp_sign = remove
+
+# No space between the '++'/'--' operator and its operand
+sp_incdec = remove
+
+# At least 1 space around comparison operators
+sp_compare = add
+
+# Remove spaces inside all kinds of parentheses:
+
+# Remove spaces inside parentheses
+sp_inside_paren = remove
+
+# No spaces inside statement parentheses
+sp_inside_sparen = remove
+
+# No spaces inside cast parentheses '( char )x' -> '(char)x'
+sp_inside_paren_cast = remove
+
+# No spaces inside function parentheses
+sp_inside_fparen = remove
+# (The case where the function has no parameters/arguments)
+sp_inside_fparens = remove
+
+# No spaces inside the first parentheses in a function type
+sp_inside_tparen = remove
+
+# (Uncrustify >= 0.74.0) No spaces inside parens in for statements
+sp_inside_for = remove
+
+# Remove spaces between nested parentheses '( (' -> '(('
+sp_paren_paren = remove
+# (Uncrustify >= 0.74.0)
+sp_sparen_paren = remove
+
+# Remove spaces between ')' and adjacent '('
+sp_cparen_oparen = remove
+
+# (Uncrustify >= 0.73.0) space between 'do' and '{'
+sp_do_brace_open = force
+
+# (Uncrustify >= 0.73.0) space between '}' and 'while'
+sp_brace_close_while = force
+
+# At least 1 space before a '*' pointer star
+sp_before_ptr_star = add
+
+# Remove spaces between pointer stars
+sp_between_ptr_star = remove
+
+# No space after a pointer star
+sp_after_ptr_star = remove
+
+# But allow a space in the case of e.g. char * const x;
+sp_after_ptr_star_qualifier = ignore
+
+# Remove space after star in a function return type
+sp_after_ptr_star_func = remove
+
+# At least 1 space after a type in variable definition etc
+sp_after_type = add
+
+# Force exactly 1 space between a statement keyword (e.g. 'if') and an opening parenthesis
+sp_before_sparen = force
+
+# Remove a space before a ';'
+sp_before_semi = remove
+# (Uncrustify >= 0.73.0) Remove space before a semi in a non-empty for
+sp_before_semi_for = remove
+# (Uncrustify >= 0.73.0) Remove space in empty first statement of a for
+sp_before_semi_for_empty = remove
+# (Uncrustify >= 0.74.0) Remove space in empty middle statement of a for
+sp_between_semi_for_empty = remove
+
+# Add a space after a ';' (unless a comment follows)
+sp_after_semi = add
+# (Uncrustify >= 0.73.0) Add a space after a semi in non-empty for statements
+sp_after_semi_for = add
+# (Uncrustify >= 0.73.0) No space after final semi in empty for statements
+sp_after_semi_for_empty = remove
+
+# Remove spaces on the inside of square brackets '[]'
+sp_inside_square = remove
+
+# Must have at least 1 space after a comma
+sp_after_comma = add
+
+# Must not have a space before a comma
+sp_before_comma = remove
+
+# No space before the ':' in a case statement
+sp_before_case_colon = remove
+
+# No space after a cast - '(char) x' -> '(char)x'
+sp_after_cast = remove
+
+# No space between 'sizeof' and '('
+sp_sizeof_paren = remove
+
+# At least 1 space inside '{ }'
+sp_inside_braces = add
+
+# At least 1 space inside '{ }' in an enum
+sp_inside_braces_enum = add
+
+# At least 1 space inside '{ }' in a struct
+sp_inside_braces_struct = add
+
+# At least 1 space between a function return type and the function name
+sp_type_func = add
+
+# No space between a function name and its arguments/parameters
+sp_func_proto_paren = remove
+sp_func_def_paren = remove
+sp_func_call_paren = remove
+
+# No space between '__attribute__' and '('
+sp_attribute_paren = remove
+
+# No space between 'defined' and '(' in preprocessor conditions
+sp_defined_paren = remove
+
+# At least 1 space between a macro's name and its definition
+sp_macro = add
+sp_macro_func = add
+
+# Force exactly 1 space between a '}' and the name of a typedef if on the same line
+sp_brace_typedef = force
+
+# At least 1 space before a '\' line continuation
+sp_before_nl_cont = add
+
+# At least 1 space around '?' and ':' in ternary statements
+sp_cond_colon = add
+sp_cond_question = add
+
+# Space between #else/#endif and comment afterwards
+sp_endif_cmt = add
+
+# Remove newlines at the start of a file
+nl_start_of_file = remove
+
+# At least 1 newline at the end of a file
+nl_end_of_file = add
+nl_end_of_file_min = 1
+
+# Add braces in single-line statements
+mod_full_brace_do = add
+mod_full_brace_for = add
+mod_full_brace_if = add
+mod_full_brace_while = add
+
+# Remove parentheses from return statements
+mod_paren_on_return = remove
+
+# Disable removal of leading spaces in a multi-line comment if the first and
+# last lines are the same length
+cmt_multi_check_last = false
diff --git a/ChangeLog b/ChangeLog
index 80b8617..cb277dc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,7 +3,7 @@
 = Mbed TLS 3.2.1 branch released 2022-07-12
 
 Bugfix
-   *  Re-add missing generated file library/ssl_debug_helpers_generated.c
+   *  Re-add missing generated file library/psa_crypto_driver_wrappers.c
 
 = Mbed TLS 3.2.0 branch released 2022-07-11
 
diff --git a/ChangeLog.d/LMS.txt b/ChangeLog.d/LMS.txt
index 6de374f..785bfcf 100644
--- a/ChangeLog.d/LMS.txt
+++ b/ChangeLog.d/LMS.txt
@@ -3,9 +3,9 @@
       Signature verification is production-ready, but generation is for testing
       purposes only. This currently only supports one parameter set
       (LMS_SHA256_M32_H10), meaning that each private key can be used to sign
-      1024 messages. As such, it is not intended for use in TLS, but instead for
-      verification of assets transmitted over an insecure channel, particularly
-      firmware images.
+      1024 messages. As such, it is not intended for use in TLS, but instead
+      for verification of assets transmitted over an insecure channel,
+      particularly firmware images.
     * Add the LM-OTS post-quantum-safe one-time signature scheme, which is
-      required for LMS. This can be used independently, but each key can only be
-      used to sign one message so is impractical for most circumstances.
+      required for LMS. This can be used independently, but each key can only
+      be used to sign one message so is impractical for most circumstances.
diff --git a/ChangeLog.d/add-rsa-pss-rsae-support-for-tls12.txt b/ChangeLog.d/add-rsa-pss-rsae-support-for-tls12.txt
index f88eb9e..0d40968 100644
--- a/ChangeLog.d/add-rsa-pss-rsae-support-for-tls12.txt
+++ b/ChangeLog.d/add-rsa-pss-rsae-support-for-tls12.txt
@@ -1,8 +1,8 @@
 Features
-   * When GnuTLS/Openssl server is configured in TLS 1.2 mode with a certificate
-     declaring an RSA public key and Mbed TLS is configured in hybrid mode, if
-     `rsa_pss_rsae_*` algorithms are before `rsa_pkcs1_*` ones in this list then
-     the GnuTLS/Openssl server chooses an `rsa_pss_rsae_*` signature algorithm
-     for its signature in the key exchange message. As Mbed TLS 1.2 does not
-     support them, the handshake fails. Add `rsa_pss_rsae_*` support for TLS 1.2
-     to resolve the compitablity issue.
+   * Support rsa_pss_rsae_* signature algorithms in TLS 1.2.
+Bugfix
+   * Fix an interoperability failure between an Mbed TLS client with both
+     TLS 1.2 and TLS 1.3 support, and a TLS 1.2 server that supports
+     rsa_pss_rsae_* signature algorithms. This failed because Mbed TLS
+     advertised support for PSS in both TLS 1.2 and 1.3, but only
+     actually supported PSS in TLS 1.3.
diff --git a/ChangeLog.d/dtls-connection-id.txt b/ChangeLog.d/dtls-connection-id.txt
new file mode 100644
index 0000000..840f837
--- /dev/null
+++ b/ChangeLog.d/dtls-connection-id.txt
@@ -0,0 +1,17 @@
+Features
+   * Add support for DTLS Connection ID as defined by RFC 9146, controlled by
+     MBEDTLS_SSL_DTLS_CONNECTION_ID (enabled by default) and configured with
+     mbedtls_ssl_set_cid().
+
+Default behavior changes
+   * Previously the macro MBEDTLS_SSL_DTLS_CONNECTION_ID implemented version 05
+     of the IETF draft, and was marked experimental and disabled by default.
+     It is now no longer experimental, and implements the final version from
+     RFC 9146, which is not interoperable with the draft-05 version.
+     If you need to communicate with peers that use earlier versions of
+     Mbed TLS, then you need to define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT
+     to 1, but then you won't be able to communicate with peers that use the
+     standard (non-draft) version.
+     If you need to interoperate with both classes of peers with the
+     same build of Mbed TLS, please let us know about your situation on the
+     mailing list or GitHub.
diff --git a/ChangeLog.d/extend-query_compile_time_config-to-psa_want.txt b/ChangeLog.d/extend-query_compile_time_config-to-psa_want.txt
index b268fd4..99b2ec4 100644
--- a/ChangeLog.d/extend-query_compile_time_config-to-psa_want.txt
+++ b/ChangeLog.d/extend-query_compile_time_config-to-psa_want.txt
@@ -1,2 +1,2 @@
 Changes
-   * Add the ability to query PSA_WANT_xxx macros to query_compile_time_config
+   * Add the ability to query PSA_WANT_xxx macros to query_compile_time_config.
diff --git a/ChangeLog.d/fix-tls12server-sent-sigalgs.txt b/ChangeLog.d/fix-tls12server-sent-sigalgs.txt
index 9abde2b..b74c6ec 100644
--- a/ChangeLog.d/fix-tls12server-sent-sigalgs.txt
+++ b/ChangeLog.d/fix-tls12server-sent-sigalgs.txt
@@ -1,5 +1,5 @@
 Bugfix
-    * Fix a bug whereby the the list of signature algorithms sent as part of the
-      TLS 1.2 server certificate request would get corrupted, meaning the first
-      algorithm would not get sent and an entry consisting of two random bytes
-      would be sent instead. Found by Serban Bejan and Dudek Sebastian.
+    * Fix a bug whereby the list of signature algorithms sent as part of
+      the TLS 1.2 server certificate request would get corrupted, meaning the
+      first algorithm would not get sent and an entry consisting of two random
+      bytes would be sent instead. Found by Serban Bejan and Dudek Sebastian.
diff --git a/ChangeLog.d/fix_arm_compile_erorr.txt b/ChangeLog.d/fix_arm_compile_erorr.txt
new file mode 100644
index 0000000..28c1d45
--- /dev/null
+++ b/ChangeLog.d/fix_arm_compile_erorr.txt
@@ -0,0 +1,3 @@
+Bugfix
+    * Fix a build error when compiling the bignum module for some Arm platforms.
+      Fixes #6089, #6124, #6217.
diff --git a/ChangeLog.d/fix_build_error_for_mbedtls_deprecated_removed.txt b/ChangeLog.d/fix_build_error_for_mbedtls_deprecated_removed.txt
index a70521a..f0fa000 100644
--- a/ChangeLog.d/fix_build_error_for_mbedtls_deprecated_removed.txt
+++ b/ChangeLog.d/fix_build_error_for_mbedtls_deprecated_removed.txt
@@ -1,3 +1,3 @@
 Bugfix
-    * Fix build error due to missing prototype
-      warning when MBEDTLS_DEPRECATED_REMOVED is enabled
+    * Fix a build error due to a missing prototype warning when
+      MBEDTLS_DEPRECATED_REMOVED is enabled.
diff --git a/ChangeLog.d/fix_build_tls1_2_with_single_encryption_type.txt b/ChangeLog.d/fix_build_tls1_2_with_single_encryption_type.txt
index bac4910..c7d2691 100644
--- a/ChangeLog.d/fix_build_tls1_2_with_single_encryption_type.txt
+++ b/ChangeLog.d/fix_build_tls1_2_with_single_encryption_type.txt
@@ -1,4 +1,3 @@
 Bugfix
-    * Fix bugs and missing dependencies when
-      building and testing configurations with
-      only one encryption type enabled in TLS 1.2.
+    * Fix bugs and missing dependencies when building and testing
+      configurations with only one encryption type enabled in TLS 1.2.
diff --git a/ChangeLog.d/fix_cmake_gen_files b/ChangeLog.d/fix_cmake_gen_files
deleted file mode 100644
index 3b2c099..0000000
--- a/ChangeLog.d/fix_cmake_gen_files
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix an issue in releases with GEN_FILES turned off whereby missing
-     generated files could be turned into symlinks to themselves.
diff --git a/ChangeLog.d/fix_cmake_gen_files.txt b/ChangeLog.d/fix_cmake_gen_files.txt
new file mode 100644
index 0000000..cdec6e8
--- /dev/null
+++ b/ChangeLog.d/fix_cmake_gen_files.txt
@@ -0,0 +1,4 @@
+Bugfix
+   * Fix an issue with in-tree CMake builds in releases with GEN_FILES
+     turned off: if a shipped file was missing from the working directory,
+     it could be turned into a symbolic link to itself.
diff --git a/ChangeLog.d/fix_cmake_using_iar_toolchain.txt b/ChangeLog.d/fix_cmake_using_iar_toolchain.txt
index ecc09c2..9ec6e0d 100644
--- a/ChangeLog.d/fix_cmake_using_iar_toolchain.txt
+++ b/ChangeLog.d/fix_cmake_using_iar_toolchain.txt
@@ -1,3 +1,3 @@
 Bugfix
-   * Fixed an issue that cause compile error using CMake IAR toolchain.
+   * Fix a compilation error when using CMake with an IAR toolchain.
      Fixes #5964.
diff --git a/ChangeLog.d/fix_hard_link_across_drives b/ChangeLog.d/fix_hard_link_across_drives
deleted file mode 100644
index 0c55c30..0000000
--- a/ChangeLog.d/fix_hard_link_across_drives
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix a build issue on Windows where the source and build directory could not be on
-     different drives (#5751).
diff --git a/ChangeLog.d/fix_hard_link_across_drives.txt b/ChangeLog.d/fix_hard_link_across_drives.txt
new file mode 100644
index 0000000..46d05c0
--- /dev/null
+++ b/ChangeLog.d/fix_hard_link_across_drives.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix a build issue on Windows using CMake where the source and build
+     directories could not be on different drives. Fixes #5751.
diff --git a/ChangeLog.d/fix_tls13_session_resumption_fail_when_hostname_is_not_localhost.txt b/ChangeLog.d/fix_tls13_session_resumption_fail_when_hostname_is_not_localhost.txt
index 5797f48..9f5c649 100644
--- a/ChangeLog.d/fix_tls13_session_resumption_fail_when_hostname_is_not_localhost.txt
+++ b/ChangeLog.d/fix_tls13_session_resumption_fail_when_hostname_is_not_localhost.txt
@@ -1,4 +1,4 @@
 Bugfix
-    * Fix TLS 1.3 session resumption fail. Fixes #6488.
-    * Add configuration check to exclude TLS 1.3 optional authentication of
-      client.
+    * Fix TLS 1.3 session resumption. Fixes #6488.
+    * Add a configuration check to exclude optional client authentication
+      in TLS 1.3 (where it is forbidden).
diff --git a/ChangeLog.d/fix_zeroization.txt b/ChangeLog.d/fix_zeroization.txt
index ad74d9c..8b00dcc 100644
--- a/ChangeLog.d/fix_zeroization.txt
+++ b/ChangeLog.d/fix_zeroization.txt
@@ -1,3 +1,3 @@
 Bugfix
-   * Fix possible crash in TLS PRF code, if a failure to allocate memory occurs.
-     Reported by Michael Madsen in #6516.
+   * Fix a possible null pointer dereference if a memory allocation fails
+     in TLS PRF code. Reported by Michael Madsen in #6516.
diff --git a/ChangeLog.d/mbedtls_asn1_type_free.txt b/ChangeLog.d/mbedtls_asn1_type_free.txt
index 81f3a20..3459bbe 100644
--- a/ChangeLog.d/mbedtls_asn1_type_free.txt
+++ b/ChangeLog.d/mbedtls_asn1_type_free.txt
@@ -1,6 +1,8 @@
 Features
-   * Shared code to free x509 structs like mbedtls_x509_named_data
+   * The new functions mbedtls_asn1_free_named_data_list() and
+     mbedtls_asn1_free_named_data_list_shallow() simplify the management
+     of memory in named data lists in X.509 structures.
 New deprecations
    * Deprecate mbedtls_asn1_free_named_data().
      Use mbedtls_asn1_free_named_data_list()
-     or mbedtls_asn1_free_named_data_list_shallow()
+     or mbedtls_asn1_free_named_data_list_shallow().
diff --git a/ChangeLog.d/pkcs7-parser.txt b/ChangeLog.d/pkcs7-parser.txt
deleted file mode 100644
index 7f85f0c..0000000
--- a/ChangeLog.d/pkcs7-parser.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Features
-   * Added partial support for parsing the PKCS7 cryptographic message syntax,
-     as defined in RFC 2315. Currently, support is limited to the following:
-     - Only the signed data content type, version 1 is supported.
-     - Only DER encoding is supported.
-     - Only a single digest algorithm per message is supported.
-     - Only 0 or 1, certificate is supported per message, which must be in
-       X509 format.
-     - There is no support for certificate-revocation lists.
-     - The authenticated and unauthenticated attribute fields of SignerInfo
-       must be empty.
-     Many thanks to Daniel Axtens, Nayna Jain, and Nick Child from IBM for
-     contributing this feature.
diff --git a/ChangeLog.d/psa_crypto_code_gen_1_1.txt b/ChangeLog.d/psa_crypto_code_gen_1_1.txt
index 2c18e6f..e10a81c 100644
--- a/ChangeLog.d/psa_crypto_code_gen_1_1.txt
+++ b/ChangeLog.d/psa_crypto_code_gen_1_1.txt
@@ -1,6 +1,13 @@
 Features
-    * Brought in PSA code geneneration JSON driver list.
-      Added auto generated templating support for key management.
-      Added Support for transparent and opaque keys (import/export/copy).
-      Included some general JSON validation for the given entry points.
-      Addresses version 1.1 of #5137.
+    * The PSA driver wrapper generator generate_driver_wrappers.py now
+      supports a subset of the driver description language, including
+      the following entry points: import_key, export_key, export_public_key,
+      get_builtin_key, copy_key.
+
+Requirement changes
+   * When building with PSA drivers using generate_driver_wrappers.py, or
+     when building the library from the development branch rather than
+     from a release, the Python module jsonschema is now necessary, in
+     addition to jinja2. The official list of required Python modules is
+     maintained in scripts/basic.requirements.txt and may change again
+     in the future.
diff --git a/ChangeLog.d/psa_driver_wrapper_for_raw_key_agreement.txt b/ChangeLog.d/psa_driver_wrapper_for_raw_key_agreement.txt
new file mode 100644
index 0000000..b9c78a6
--- /dev/null
+++ b/ChangeLog.d/psa_driver_wrapper_for_raw_key_agreement.txt
@@ -0,0 +1,5 @@
+Features
+   * Add a driver dispatch layer for raw key agreement, enabling alternative
+     implementations of raw key agreement through the key_agreement driver
+     entry point. This entry point is specified in the proposed PSA driver
+     interface, but had not yet been implemented.
diff --git a/ChangeLog.d/remove_ssl_session_compression.txt b/ChangeLog.d/remove_ssl_session_compression.txt
deleted file mode 100644
index dc59f1c..0000000
--- a/ChangeLog.d/remove_ssl_session_compression.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Removals
-   * Remove compression property from SSL session struct.
-     MBEDTLS_SSL_COMPRESS_NULL is now the only supported
-     compression option and can be used for compatibility
-     reasons. Changes requested in #4223.
diff --git a/ChangeLog.d/tls13-misc.txt b/ChangeLog.d/tls13-misc.txt
index 497ed38..6733173 100644
--- a/ChangeLog.d/tls13-misc.txt
+++ b/ChangeLog.d/tls13-misc.txt
@@ -1,9 +1,8 @@
 Features
-   * Mbed TLS supports TLS 1.3 key establishment via pre-shared keys,
-     pre-shared keys provisioned externally or via the ticket mechanism
-     (session resumption).
-     The MBEDTLS_SSL_SESSION_TICKETS configuration option controls the support
-     for the ticket mechanism.
-     MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_xxx_ENABLED configuration options
-     have been introduced to control the support for the three possible
-     TLS 1.3 key exchange modes.
+   * Mbed TLS now supports TLS 1.3 key establishment via pre-shared keys.
+     The pre-shared keys can be provisioned externally or via the ticket
+     mechanism (session resumption).
+     The ticket mechanism is supported when the configuration option
+     MBEDTLS_SSL_SESSION_TICKETS is enabled.
+     New options MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_xxx_ENABLED
+     control the support for the three possible TLS 1.3 key exchange modes.
diff --git a/doxygen/input/doc_encdec.h b/doxygen/input/doc_encdec.h
index 96734bd..ec149ae 100644
--- a/doxygen/input/doc_encdec.h
+++ b/doxygen/input/doc_encdec.h
@@ -38,7 +38,7 @@
  * All symmetric encryption algorithms are accessible via the generic cipher layer
  * (see \c mbedtls_cipher_setup()).
  *
- * The asymmetric encryptrion algorithms are accessible via the generic public
+ * The asymmetric encryption algorithms are accessible via the generic public
  * key layer (see \c mbedtls_pk_init()).
  *
  * The following algorithms are provided:
diff --git a/include/mbedtls/asn1write.h b/include/mbedtls/asn1write.h
index 5554720..e6f0479 100644
--- a/include/mbedtls/asn1write.h
+++ b/include/mbedtls/asn1write.h
@@ -352,7 +352,7 @@
  *                  the existing buffer to fit \p val_len.
  *
  * \return          A pointer to the new / existing entry on success.
- * \return          \c NULL if if there was a memory allocation error.
+ * \return          \c NULL if there was a memory allocation error.
  */
 mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list,
                                         const char *oid, size_t oid_len,
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 38a4530..dfb4c5f 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -23,6 +23,7 @@
 #ifndef MBEDTLS_CHECK_CONFIG_H
 #define MBEDTLS_CHECK_CONFIG_H
 
+/* *INDENT-OFF* */
 /*
  * We assume CHAR_BIT is 8 in many places. In practice, this is true on our
  * target platforms, so not an issue, but let's just be extra sure.
@@ -32,6 +33,8 @@
 #error "mbed TLS requires a platform with 8-bit chars"
 #endif
 
+#include <stdint.h>
+
 #if defined(_WIN32)
 #if !defined(MBEDTLS_PLATFORM_C)
 #error "MBEDTLS_PLATFORM_C is required on Windows"
@@ -849,6 +852,13 @@
 #error "MBEDTLS_SSL_EARLY_DATA  defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) && \
+    ( !defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE)     || \
+      ( MBEDTLS_SSL_MAX_EARLY_DATA_SIZE < 0 )       || \
+      ( MBEDTLS_SSL_MAX_EARLY_DATA_SIZE > UINT32_MAX ) )
+#error "MBEDTLS_SSL_MAX_EARLY_DATA_SIZE MUST be defined and in range(0..UINT32_MAX)"
+#endif
+
 #if defined(MBEDTLS_SSL_PROTO_DTLS)     && \
     !defined(MBEDTLS_SSL_PROTO_TLS1_2)
 #error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites"
@@ -903,6 +913,19 @@
 #error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)"
 #endif
 
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT)     &&                 \
+    !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#error "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT) && MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT != 0
+#if defined(MBEDTLS_DEPRECATED_REMOVED)
+#error "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT is deprecated and will be removed in a future version of Mbed TLS"
+#elif defined(MBEDTLS_DEPRECATED_WARNING)
+#warning "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT is deprecated and will be removed in a future version of Mbed TLS"
+#endif
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT && MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT != 0 */
+
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) &&   \
     !defined(MBEDTLS_SSL_PROTO_TLS1_2)
 #error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequisites"
@@ -1077,4 +1100,5 @@
  */
 typedef int mbedtls_iso_c_forbids_empty_translation_units;
 
+/* *INDENT-ON* */
 #endif /* MBEDTLS_CHECK_CONFIG_H */
diff --git a/include/mbedtls/config_psa.h b/include/mbedtls/config_psa.h
index 5b27dda..5727c5e 100644
--- a/include/mbedtls/config_psa.h
+++ b/include/mbedtls/config_psa.h
@@ -7,7 +7,7 @@
  *  those definitions to define symbols used in the library code.
  *
  *  Users and integrators should not edit this file, please edit
- *  include/mbedtls/mbedtls_config.h for MBETLS_XXX settings or
+ *  include/mbedtls/mbedtls_config.h for MBEDTLS_XXX settings or
  *  include/psa/crypto_config.h for PSA_WANT_XXX settings.
  */
 /*
diff --git a/include/mbedtls/lms.h b/include/mbedtls/lms.h
index fe87d40..1179cd1 100644
--- a/include/mbedtls/lms.h
+++ b/include/mbedtls/lms.h
@@ -58,7 +58,7 @@
 #define MBEDTLS_LMS_TYPE_LEN            (4)
 #define MBEDTLS_LMS_H_TREE_HEIGHT(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 10u : 0)
 
-/* The length of a hash output, Currently only imlemented for SHA256.
+/* The length of a hash output, Currently only implemented for SHA256.
  * Max is 32 bytes.
  */
 #define MBEDTLS_LMS_M_NODE_BYTES(type) ((type) == MBEDTLS_LMS_SHA256_M32_H10 ? 32 : 0)
@@ -82,7 +82,7 @@
 
 /** The Identifier of the LMS parameter set, as per
  * https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml
- * We are only implementing a subset of the types, particularly H10, for the sake of simplicty.
+ * We are only implementing a subset of the types, particularly H10, for the sake of simplicity.
  */
 typedef enum {
     MBEDTLS_LMS_SHA256_M32_H10 = 0x6,
@@ -90,7 +90,7 @@
 
 /** The Identifier of the LMOTS parameter set, as per
  *  https://www.iana.org/assignments/leighton-micali-signatures/leighton-micali-signatures.xhtml.
- *  We are only implementing a subset of the types, particularly N32_W8, for the sake of simplicty.
+ *  We are only implementing a subset of the types, particularly N32_W8, for the sake of simplicity.
  */
 typedef enum {
     MBEDTLS_LMOTS_SHA256_N32_W8 = 4
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index a4d0328..78c3635 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -1325,21 +1325,16 @@
 /**
  * \def MBEDTLS_SSL_DTLS_CONNECTION_ID
  *
- * Enable support for the DTLS Connection ID extension
- * (version draft-ietf-tls-dtls-connection-id-05,
- * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05)
+ * Enable support for the DTLS Connection ID (CID) extension,
  * which allows to identify DTLS connections across changes
- * in the underlying transport.
+ * in the underlying transport. The CID functionality is described
+ * in RFC 9146.
  *
  * Setting this option enables the SSL APIs `mbedtls_ssl_set_cid()`,
  * mbedtls_ssl_get_own_cid()`, `mbedtls_ssl_get_peer_cid()` and
  * `mbedtls_ssl_conf_cid()`. See the corresponding documentation for
  * more information.
  *
- * \warning The Connection ID extension is still in draft state.
- *          We make no stability promises for the availability
- *          or the shape of the API controlled by this option.
- *
  * The maximum lengths of outgoing and incoming CIDs can be configured
  * through the options
  * - MBEDTLS_SSL_CID_OUT_LEN_MAX
@@ -1349,7 +1344,30 @@
  *
  * Uncomment to enable the Connection ID extension.
  */
-//#define MBEDTLS_SSL_DTLS_CONNECTION_ID
+#define MBEDTLS_SSL_DTLS_CONNECTION_ID
+
+
+/**
+ * \def MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT
+ *
+ * Defines whether RFC 9146 (default) or the legacy version
+ * (version draft-ietf-tls-dtls-connection-id-05,
+ * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05)
+ * is used.
+ *
+ * Set the value to 0 for the standard version, and
+ * 1 for the legacy draft version.
+ *
+ * \deprecated Support for the legacy version of the DTLS
+ *             Connection ID feature is deprecated. Please
+ *             switch to the standardized version defined
+ *             in RFC 9146 enabled by utilizing
+ *             MBEDTLS_SSL_DTLS_CONNECTION_ID without use
+ *             of MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT.
+ *
+ * Requires: MBEDTLS_SSL_DTLS_CONNECTION_ID
+ */
+#define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT 0
 
 /**
  * \def MBEDTLS_SSL_ASYNC_PRIVATE
@@ -1525,7 +1543,7 @@
  * Requires: MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
  * Requires: MBEDTLS_PSA_CRYPTO_C
  *
- * Note: even though TLS 1.3 depends on PSA Crypto, and uses it unconditonally
+ * Note: even though TLS 1.3 depends on PSA Crypto, and uses it unconditionally
  * for most operations, if you want it to only use PSA for all crypto
  * operations, you need to also enable MBEDTLS_USE_PSA_CRYPTO; otherwise X.509
  * operations, and functions that are common with TLS 1.2 (record protection,
@@ -1656,6 +1674,23 @@
 //#define MBEDTLS_SSL_EARLY_DATA
 
 /**
+ * \def MBEDTLS_SSL_MAX_EARLY_DATA_SIZE
+ *
+ * The default maximum amount of 0-RTT data. See the documentation of
+ * \c mbedtls_ssl_tls13_conf_max_early_data_size() for more information.
+ *
+ * It must be positive and smaller than UINT32_MAX.
+ *
+ * If MBEDTLS_SSL_EARLY_DATA is not defined, this default value does not
+ * have any impact on the build.
+ *
+ * This feature is experimental, not completed and thus not ready for
+ * production.
+ *
+ */
+#define MBEDTLS_SSL_MAX_EARLY_DATA_SIZE        1024
+
+/**
  * \def MBEDTLS_SSL_PROTO_DTLS
  *
  * Enable support for DTLS (all available versions).
@@ -2799,6 +2834,10 @@
 /**
  * \def MBEDTLS_PKCS7_C
  *
+ * This feature is a work in progress and not ready for production. Testing and
+ * validation is incomplete, and handling of malformed inputs may not be robust.
+ * The API may change.
+ *
  * Enable PKCS7 core for using PKCS7 formatted signatures.
  * RFC Link - https://tools.ietf.org/html/rfc2315
  *
@@ -2810,7 +2849,7 @@
  *
  * This module is required for the PKCS7 parsing modules.
  */
-#define MBEDTLS_PKCS7_C
+//#define MBEDTLS_PKCS7_C
 
 /**
  * \def MBEDTLS_PKCS12_C
@@ -3697,17 +3736,6 @@
 //#define MBEDTLS_PSK_MAX_LEN               32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
 //#define MBEDTLS_SSL_COOKIE_TIMEOUT        60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
 
-/** \def MBEDTLS_TLS_EXT_CID
- *
- * At the time of writing, the CID extension has not been assigned its
- * final value. Set this configuration option to make Mbed TLS use a
- * different value.
- *
- * A future minor revision of Mbed TLS may change the default value of
- * this option to match evolving standards and usage.
- */
-//#define MBEDTLS_TLS_EXT_CID                        254
-
 /**
  * Complete list of ciphersuites to use, in order of preference.
  *
diff --git a/include/mbedtls/pkcs12.h b/include/mbedtls/pkcs12.h
index 1b87aea..327996a 100644
--- a/include/mbedtls/pkcs12.h
+++ b/include/mbedtls/pkcs12.h
@@ -94,7 +94,7 @@
  *                   no byte order mark and with a null terminator (i.e. the
  *                   last two bytes should be 0x00 0x00).
  * \param pwdlen     length of the password (may be 0).
- * \param salt       Salt buffer to use This may only be \c NULL when
+ * \param salt       Salt buffer to use. This may only be \c NULL when
  *                   \p saltlen is 0.
  * \param saltlen    length of the salt (may be zero)
  * \param mbedtls_md mbedtls_md type to use during the derivation
diff --git a/include/mbedtls/pkcs7.h b/include/mbedtls/pkcs7.h
index 52895ac..bf61a63 100644
--- a/include/mbedtls/pkcs7.h
+++ b/include/mbedtls/pkcs7.h
@@ -22,6 +22,11 @@
  */
 
 /**
+ * This feature is a work in progress and not ready for production. The API may
+ * change. Furthermore, please note that the implementation has only been
+ * validated with well-formed inputs, not yet with untrusted inputs (which is
+ * almost always the case in practice).
+ *
  * Note: For the time being, this implementation of the PKCS7 cryptographic
  * message syntax is a partial implementation of RFC 2315.
  * Differences include:
@@ -179,7 +184,7 @@
  *
  * \param pkcs7    The pkcs7 structure to be filled by parser for the output.
  * \param buf      The buffer holding the DER encoded pkcs7.
- * \param buflen   The size in Bytes of \p buf.
+ * \param buflen   The size in bytes of \p buf.
  *
  * \note           This function makes an internal copy of the PKCS7 buffer
  *                 \p buf. In particular, \p buf may be destroyed or reused
@@ -192,7 +197,18 @@
                              const size_t buflen );
 
 /**
- * \brief          Verification of PKCS7 signature.
+ * \brief          Verification of PKCS7 signature against a caller-supplied
+ *                 certificate.
+ *
+ *                 For each signer in the PKCS structure, this function computes
+ *                 a signature over the supplied data, using the supplied
+ *                 certificate and the same digest algorithm as specified by the
+ *                 signer. It then compares this signature against the
+ *                 signer's signature; verification succeeds if any comparison
+ *                 matches.
+ *
+ *                 This function does not use the certificates held within the
+ *                 PKCS7 structure itself.
  *
  * \param pkcs7    PKCS7 structure containing signature.
  * \param cert     Certificate containing key to verify signature.
@@ -202,7 +218,7 @@
  * \note           This function internally calculates the hash on the supplied
  *                 plain data for signature verification.
  *
- * \return         A negative error code on failure.
+ * \return         0 if the signature verifies, or a negative error code on failure.
  */
 int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7,
                                       const mbedtls_x509_crt *cert,
@@ -210,7 +226,18 @@
                                       size_t datalen );
 
 /**
- * \brief          Verification of PKCS7 signature.
+ * \brief          Verification of PKCS7 signature against a caller-supplied
+ *                 certificate.
+ *
+ *                 For each signer in the PKCS structure, this function computes
+ *                 a signature over the supplied hash, using the supplied
+ *                 certificate and the same digest algorithm as specified by the
+ *                 signer. It then compares this signature against the
+ *                 signer's signature; verification succeeds if any comparison
+ *                 matches.
+ *
+ *                 This function does not use the certificates held within the
+ *                 PKCS7 structure itself.
  *
  * \param pkcs7    PKCS7 structure containing signature.
  * \param cert     Certificate containing key to verify signature.
@@ -218,9 +245,9 @@
  * \param hashlen  Length of the hash.
  *
  * \note           This function is different from mbedtls_pkcs7_signed_data_verify()
- *                 in a way that it directly recieves the hash of the data.
+ *                 in a way that it directly receives the hash of the data.
  *
- * \return         A negative error code on failure.
+ * \return         0 if the signature verifies, or a negative error code on failure.
  */
 int mbedtls_pkcs7_signed_hash_verify( mbedtls_pkcs7 *pkcs7,
                                       const mbedtls_x509_crt *cert,
diff --git a/include/mbedtls/rsa.h b/include/mbedtls/rsa.h
index 002551f..2bfaf8f 100644
--- a/include/mbedtls/rsa.h
+++ b/include/mbedtls/rsa.h
@@ -239,7 +239,7 @@
  * \param N        The RSA modulus. This may be \c NULL.
  * \param N_len    The Byte length of \p N; it is ignored if \p N == NULL.
  * \param P        The first prime factor of \p N. This may be \c NULL.
- * \param P_len    The Byte length of \p P; it ns ignored if \p P == NULL.
+ * \param P_len    The Byte length of \p P; it is ignored if \p P == NULL.
  * \param Q        The second prime factor of \p N. This may be \c NULL.
  * \param Q_len    The Byte length of \p Q; it is ignored if \p Q == NULL.
  * \param D        The private exponent. This may be \c NULL.
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index ea58661..3f48377 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -409,6 +409,14 @@
 /** \} name SECTION: Module settings */
 
 /*
+ * Default to standard CID mode
+ */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+    !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT)
+#define MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT 0
+#endif
+
+/*
  * Length of the verify data for secure renegotiation
  */
 #define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12
@@ -576,15 +584,10 @@
 #define MBEDTLS_TLS_EXT_SIG_ALG_CERT                50 /* RFC 8446 TLS 1.3 */
 #define MBEDTLS_TLS_EXT_KEY_SHARE                   51 /* RFC 8446 TLS 1.3 */
 
-/* The value of the CID extension is still TBD as of
- * draft-ietf-tls-dtls-connection-id-05
- * (https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05).
- *
- * A future minor revision of Mbed TLS may change the default value of
- * this option to match evolving standards and usage.
- */
-#if !defined(MBEDTLS_TLS_EXT_CID)
-#define MBEDTLS_TLS_EXT_CID                        254 /* TBD */
+#if MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0
+#define MBEDTLS_TLS_EXT_CID                         54 /* RFC 9146 DTLS 1.2 CID */
+#else
+#define MBEDTLS_TLS_EXT_CID                        254 /* Pre-RFC 9146 DTLS 1.2 CID */
 #endif
 
 #define MBEDTLS_TLS_EXT_ECJPAKE_KKPP               256 /* experimental */
@@ -1524,6 +1527,12 @@
     int MBEDTLS_PRIVATE(early_data_enabled);     /*!< Early data enablement:
                                                   *   - MBEDTLS_SSL_EARLY_DATA_DISABLED,
                                                   *   - MBEDTLS_SSL_EARLY_DATA_ENABLED */
+
+#if defined(MBEDTLS_SSL_SRV_C)
+    /* The maximum amount of 0-RTT data. RFC 8446 section 4.6.1 */
+    uint32_t MBEDTLS_PRIVATE(max_early_data_size);
+#endif /* MBEDTLS_SSL_SRV_C */
+
 #endif /* MBEDTLS_SSL_EARLY_DATA */
 
 #if defined(MBEDTLS_SSL_ALPN)
@@ -1961,6 +1970,35 @@
 */
 void mbedtls_ssl_tls13_conf_early_data( mbedtls_ssl_config *conf,
                                         int early_data_enabled );
+
+#if defined(MBEDTLS_SSL_SRV_C)
+/**
+ * \brief Set the maximum amount of 0-RTT data in bytes
+ *        Default:  #MBEDTLS_SSL_MAX_EARLY_DATA_SIZE
+ *
+ *        This function sets the value of the max_early_data_size
+ *        field of the early data indication extension included in
+ *        the NewSessionTicket messages that the server may send.
+ *
+ *        The value defines the maximum amount of 0-RTT data
+ *        in bytes that a client will be allowed to send when using
+ *        one of the tickets defined by the NewSessionTicket messages.
+ *
+ * \note When resuming a session using a ticket, if the server receives more
+ *       early data than allowed for the ticket, it terminates the connection.
+ *       The maximum amount of 0-RTT data should thus be large enough
+ *       to allow a minimum of early data to be exchanged.
+ *
+ * \param[in] conf                  The SSL configuration to use.
+ * \param[in] max_early_data_size   The maximum amount of 0-RTT data.
+ *
+ * \warning This interface is experimental and may change without notice.
+ *
+ */
+void mbedtls_ssl_tls13_conf_max_early_data_size(
+         mbedtls_ssl_config *conf, uint32_t max_early_data_size );
+#endif /* MBEDTLS_SSL_SRV_C */
+
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_EARLY_DATA */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
@@ -2074,8 +2112,9 @@
  * \brief             Configure the use of the Connection ID (CID)
  *                    extension in the next handshake.
  *
- *                    Reference: draft-ietf-tls-dtls-connection-id-05
+ *                    Reference: RFC 9146 (or draft-ietf-tls-dtls-connection-id-05
  *                    https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
+ *                    for legacy version)
  *
  *                    The DTLS CID extension allows the reliable association of
  *                    DTLS records to DTLS connections across changes in the
@@ -2132,7 +2171,7 @@
  *                      the `ServerHello` contains the CID extension, too,
  *                      the CID extension will actually be put to use.
  *                    - On the Server, enabling the use of the CID through
- *                      this call implies that that the server will look for
+ *                      this call implies that the server will look for
  *                      the CID extension in a `ClientHello` from the client,
  *                      and, if present, reply with a CID extension in its
  *                      `ServerHello`.
@@ -2578,7 +2617,7 @@
  * \note The library stores \c p without accessing it. It is the responsibility
  *       of the caller to ensure that the pointer remains valid.
  *
- * \param ssl            The SSL context context to modify.
+ * \param ssl            The SSL context to modify.
  * \param p              The new value of the user data.
  */
 static inline void mbedtls_ssl_set_user_data_p(
@@ -2592,7 +2631,7 @@
  *
  * You can retrieve this value later with mbedtls_ssl_get_user_data_n().
  *
- * \param ssl            The SSL context context to modify.
+ * \param ssl            The SSL context to modify.
  * \param n              The new value of the user data.
  */
 static inline void mbedtls_ssl_set_user_data_n(
@@ -2609,7 +2648,7 @@
  * called. The value is undefined if mbedtls_ssl_set_user_data_n() has
  * been called without a subsequent call to mbedtls_ssl_set_user_data_p().
  *
- * \param ssl            The SSL context context to modify.
+ * \param ssl            The SSL context to modify.
  * \return               The current value of the user data.
  */
 static inline void *mbedtls_ssl_get_user_data_p(
@@ -2625,7 +2664,7 @@
  * called. The value is undefined if mbedtls_ssl_set_user_data_p() has
  * been called without a subsequent call to mbedtls_ssl_set_user_data_n().
  *
- * \param ssl            The SSL context context to modify.
+ * \param ssl            The SSL context to modify.
  * \return               The current value of the user data.
  */
 static inline uintptr_t mbedtls_ssl_get_user_data_n(
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index a71ca3f..03181ed 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -525,7 +525,7 @@
  *
  * This function destroys a key from both volatile
  * memory and, if applicable, non-volatile storage. Implementations shall
- * make a best effort to ensure that that the key material cannot be recovered.
+ * make a best effort to ensure that the key material cannot be recovered.
  *
  * This function also erases any metadata such as policies and frees
  * resources associated with the key.
@@ -3823,7 +3823,7 @@
  * compares those bytes to an expected value, provided as key of type
  * #PSA_KEY_TYPE_PASSWORD_HASH.
  * If you view the key derivation's output as a stream of bytes, this
- * function destructively reads the number of bytes corresponding the the
+ * function destructively reads the number of bytes corresponding to the
  * length of the expected value from the stream before comparing them.
  * The operation's capacity decreases by the number of bytes read.
  *
diff --git a/include/psa/crypto_se_driver.h b/include/psa/crypto_se_driver.h
index f0252c8..225fb17 100644
--- a/include/psa/crypto_se_driver.h
+++ b/include/psa/crypto_se_driver.h
@@ -226,7 +226,7 @@
  * operation by comparing the resulting MAC against a provided value
  *
  * \param[in,out] op_context    A hardware-specific structure for the previously
- *                              started MAC operation to be fiinished
+ *                              started MAC operation to be finished
  * \param[in] p_mac             The MAC value against which the resulting MAC
  *                              will be compared against
  * \param[in] mac_length        The size in bytes of the value stored in `p_mac`
@@ -337,7 +337,7 @@
     /** Function that completes a MAC operation with a verify check
      */
     psa_drv_se_mac_finish_verify_t  MBEDTLS_PRIVATE(p_finish_verify);
-    /** Function that aborts a previoustly started MAC operation
+    /** Function that aborts a previously started MAC operation
      */
     psa_drv_se_mac_abort_t          MBEDTLS_PRIVATE(p_abort);
     /** Function that performs a MAC operation in one call
@@ -746,7 +746,7 @@
                                                   size_t ciphertext_size,
                                                   size_t *p_ciphertext_length);
 
-/** A function that peforms a secure element authenticated decryption operation
+/** A function that performs a secure element authenticated decryption operation
  *
  * \param[in,out] drv_context           The driver context structure.
  * \param[in] key_slot                  Slot containing the key to use
@@ -1157,7 +1157,7 @@
  *
  * Different key derivation algorithms require a different number of inputs.
  * Instead of having an API that takes as input variable length arrays, which
- * can be problemmatic to manage on embedded platforms, the inputs are passed
+ * can be problematic to manage on embedded platforms, the inputs are passed
  * to the driver via a function, `psa_drv_se_key_derivation_collateral`, that
  * is called multiple times with different `collateral_id`s. Thus, for a key
  * derivation algorithm that required 3 parameter inputs, the flow would look
@@ -1271,7 +1271,7 @@
     psa_drv_se_key_derivation_collateral_t MBEDTLS_PRIVATE(p_collateral);
     /** Function that performs a final key derivation step */
     psa_drv_se_key_derivation_derive_t     MBEDTLS_PRIVATE(p_derive);
-    /** Function that perforsm a final key derivation or agreement and
+    /** Function that performs a final key derivation or agreement and
      * exports the key */
     psa_drv_se_key_derivation_export_t     MBEDTLS_PRIVATE(p_export);
 } psa_drv_se_key_derivation_t;
diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h
index 231ea62..b42b2df 100644
--- a/include/psa/crypto_sizes.h
+++ b/include/psa/crypto_sizes.h
@@ -717,7 +717,7 @@
     (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11)
 
 /* Maximum size of the export encoding of an RSA key pair.
- * Assumes thatthe public exponent is less than 2^32 and that the size
+ * Assumes that the public exponent is less than 2^32 and that the size
  * difference between the two primes is at most 1 bit.
  *
  * RSAPrivateKey ::= SEQUENCE {
diff --git a/include/psa/crypto_types.h b/include/psa/crypto_types.h
index 739062d..af61aea 100644
--- a/include/psa/crypto_types.h
+++ b/include/psa/crypto_types.h
@@ -297,7 +297,7 @@
 
 #else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
 /* Implementation-specific: The Mbed Cryptography library can be built as
- * part of a multi-client service that exposes the PSA Cryptograpy API in each
+ * part of a multi-client service that exposes the PSA Cryptography API in each
  * client and encodes the client identity in the key identifier argument of
  * functions such as psa_open_key().
  */
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index b465ddb..c9c1ec0 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -2577,7 +2577,7 @@
  *
  * This flag allows the key to be used for a MAC verification operation
  * or for an asymmetric signature verification operation,
- * if otherwise permitted by by the key's type and policy.
+ * if otherwise permitted by the key's type and policy.
  *
  * For a key pair, this concerns the public key.
  */
@@ -2587,7 +2587,7 @@
  * hash.
  *
  * This flag allows the key to be used for a key derivation operation or for
- * a key agreement operation, if otherwise permitted by by the key's type and
+ * a key agreement operation, if otherwise permitted by the key's type and
  * policy.
  *
  * If this flag is present on all keys used in calls to
@@ -2603,7 +2603,7 @@
  * This flag allows the key to be used:
  *
  * This flag allows the key to be used in a key derivation operation, if
- * otherwise permitted by by the key's type and policy.
+ * otherwise permitted by the key's type and policy.
  *
  * If this flag is present on all keys used in calls to
  * psa_key_derivation_input_key() for a key derivation operation, then it
diff --git a/library/aes.c b/library/aes.c
index 6e1bcd2..56dc5cf 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -1107,7 +1107,7 @@
         {
             /* We are on the last block in a decrypt operation that has
              * leftover bytes, so we need to use the next tweak for this block,
-             * and this tweak for the lefover bytes. Save the current tweak for
+             * and this tweak for the leftover bytes. Save the current tweak for
              * the leftovers and then update the current tweak for use on this,
              * the last full block. */
             memcpy( prev_tweak, tweak, sizeof( tweak ) );
diff --git a/library/bignum_core.c b/library/bignum_core.c
index e3451ae..1ce8457 100644
--- a/library/bignum_core.c
+++ b/library/bignum_core.c
@@ -520,6 +520,7 @@
     return( ret );
 }
 
+MBEDTLS_STATIC_TESTABLE
 void mbedtls_mpi_core_ct_uint_table_lookup( mbedtls_mpi_uint *dest,
                                             const mbedtls_mpi_uint *table,
                                             size_t limbs,
@@ -562,6 +563,161 @@
 
 /* BEGIN MERGE SLOT 1 */
 
+static size_t exp_mod_get_window_size( size_t Ebits )
+{
+    size_t wsize = ( Ebits > 671 ) ? 6 : ( Ebits > 239 ) ? 5 :
+                   ( Ebits >  79 ) ? 4 : 1;
+
+#if( MBEDTLS_MPI_WINDOW_SIZE < 6 )
+    if( wsize > MBEDTLS_MPI_WINDOW_SIZE )
+        wsize = MBEDTLS_MPI_WINDOW_SIZE;
+#endif
+
+    return( wsize );
+}
+
+size_t mbedtls_mpi_core_exp_mod_working_limbs( size_t AN_limbs, size_t E_limbs )
+{
+    const size_t wsize = exp_mod_get_window_size( E_limbs * biL );
+    const size_t welem = ( (size_t) 1 ) << wsize;
+
+    /* How big does each part of the working memory pool need to be? */
+    const size_t table_limbs   = welem * AN_limbs;
+    const size_t select_limbs  = AN_limbs;
+    const size_t temp_limbs    = 2 * AN_limbs + 1;
+
+    return( table_limbs + select_limbs + temp_limbs );
+}
+
+static void exp_mod_precompute_window( const mbedtls_mpi_uint *A,
+                                       const mbedtls_mpi_uint *N,
+                                       size_t AN_limbs,
+                                       mbedtls_mpi_uint mm,
+                                       const mbedtls_mpi_uint *RR,
+                                       size_t welem,
+                                       mbedtls_mpi_uint *Wtable,
+                                       mbedtls_mpi_uint *temp )
+{
+    /* W[0] = 1 (in Montgomery presentation) */
+    memset( Wtable, 0, AN_limbs * ciL );
+    Wtable[0] = 1;
+    mbedtls_mpi_core_montmul( Wtable, Wtable, RR, AN_limbs, N, AN_limbs, mm, temp );
+
+    /* W[1] = A (already in Montgomery presentation) */
+    mbedtls_mpi_uint *W1 = Wtable + AN_limbs;
+    memcpy( W1, A, AN_limbs * ciL );
+
+    /* W[i+1] = W[i] * W[1], i >= 2 */
+    mbedtls_mpi_uint *Wprev = W1;
+    for( size_t i = 2; i < welem; i++ )
+    {
+        mbedtls_mpi_uint *Wcur = Wprev + AN_limbs;
+        mbedtls_mpi_core_montmul( Wcur, Wprev, W1, AN_limbs, N, AN_limbs, mm, temp );
+        Wprev = Wcur;
+    }
+}
+
+/* Exponentiation: X := A^E mod N.
+ *
+ * A must already be in Montgomery form.
+ *
+ * As in other bignum functions, assume that AN_limbs and E_limbs are nonzero.
+ *
+ * RR must contain 2^{2*biL} mod N.
+ *
+ * The algorithm is a variant of Left-to-right k-ary exponentiation: HAC 14.82
+ * (The difference is that the body in our loop processes a single bit instead
+ * of a full window.)
+ */
+void mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X,
+                               const mbedtls_mpi_uint *A,
+                               const mbedtls_mpi_uint *N,
+                               size_t AN_limbs,
+                               const mbedtls_mpi_uint *E,
+                               size_t E_limbs,
+                               const mbedtls_mpi_uint *RR,
+                               mbedtls_mpi_uint *T )
+{
+    const size_t wsize = exp_mod_get_window_size( E_limbs * biL );
+    const size_t welem = ( (size_t) 1 ) << wsize;
+
+    /* This is how we will use the temporary storage T, which must have space
+     * for table_limbs, select_limbs and (2 * AN_limbs + 1) for montmul. */
+    const size_t table_limbs  = welem * AN_limbs;
+    const size_t select_limbs = AN_limbs;
+
+    /* Pointers to specific parts of the temporary working memory pool */
+    mbedtls_mpi_uint *const Wtable  = T;
+    mbedtls_mpi_uint *const Wselect = Wtable  +  table_limbs;
+    mbedtls_mpi_uint *const temp    = Wselect + select_limbs;
+
+    /*
+     * Window precomputation
+     */
+
+    const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init( N );
+
+    /* Set Wtable[i] = A^(2^i) (in Montgomery representation) */
+    exp_mod_precompute_window( A, N, AN_limbs,
+                               mm, RR,
+                               welem, Wtable, temp );
+
+    /*
+     * Fixed window exponentiation
+     */
+
+    /* X = 1 (in Montgomery presentation) initially */
+    memcpy( X, Wtable, AN_limbs * ciL );
+
+    /* We'll process the bits of E from most significant
+     * (limb_index=E_limbs-1, E_bit_index=biL-1) to least significant
+     * (limb_index=0, E_bit_index=0). */
+    size_t E_limb_index = E_limbs;
+    size_t E_bit_index = 0;
+    /* At any given time, window contains window_bits bits from E.
+     * window_bits can go up to wsize. */
+    size_t window_bits = 0;
+    mbedtls_mpi_uint window = 0;
+
+    do
+    {
+        /* Square */
+        mbedtls_mpi_core_montmul( X, X, X, AN_limbs, N, AN_limbs, mm, temp );
+
+        /* Move to the next bit of the exponent */
+        if( E_bit_index == 0 )
+        {
+            --E_limb_index;
+            E_bit_index = biL - 1;
+        }
+        else
+        {
+            --E_bit_index;
+        }
+        /* Insert next exponent bit into window */
+        ++window_bits;
+        window <<= 1;
+        window |= ( E[E_limb_index] >> E_bit_index ) & 1;
+
+        /* Clear window if it's full. Also clear the window at the end,
+         * when we've finished processing the exponent. */
+        if( window_bits == wsize ||
+            ( E_bit_index == 0 && E_limb_index == 0 ) )
+        {
+            /* Select Wtable[window] without leaking window through
+             * memory access patterns. */
+            mbedtls_mpi_core_ct_uint_table_lookup( Wselect, Wtable,
+                                                   AN_limbs, welem, window );
+            /* Multiply X by the selected element. */
+            mbedtls_mpi_core_montmul( X, X, Wselect, AN_limbs, N, AN_limbs, mm,
+                                      temp );
+            window = 0;
+            window_bits = 0;
+        }
+    }
+    while( ! ( E_bit_index == 0 && E_limb_index == 0 ) );
+}
+
 /* END MERGE SLOT 1 */
 
 /* BEGIN MERGE SLOT 2 */
diff --git a/library/bignum_core.h b/library/bignum_core.h
index d48e705..b7af4d0 100644
--- a/library/bignum_core.h
+++ b/library/bignum_core.h
@@ -452,6 +452,7 @@
 int mbedtls_mpi_core_get_mont_r2_unsafe( mbedtls_mpi *X,
                                          const mbedtls_mpi *N );
 
+#if defined(MBEDTLS_TEST_HOOKS)
 /**
  * Copy an MPI from a table without leaking the index.
  *
@@ -469,6 +470,7 @@
                                             size_t limbs,
                                             size_t count,
                                             size_t index );
+#endif /* MBEDTLS_TEST_HOOKS */
 
 /**
  * \brief          Fill an integer with a number of random bytes.
@@ -496,6 +498,55 @@
 
 /* BEGIN MERGE SLOT 1 */
 
+/**
+ * \brief          Returns the number of limbs of working memory required for
+ *                 a call to `mbedtls_mpi_core_exp_mod()`.
+ *
+ * \param AN_limbs The number of limbs in the input `A` and the modulus `N`
+ *                 (they must be the same size) that will be given to
+ *                 `mbedtls_mpi_core_exp_mod()`.
+ * \param E_limbs  The number of limbs in the exponent `E` that will be given
+ *                 to `mbedtls_mpi_core_exp_mod()`.
+ *
+ * \return         The number of limbs of working memory required by
+ *                 `mbedtls_mpi_core_exp_mod()`.
+ */
+size_t mbedtls_mpi_core_exp_mod_working_limbs( size_t AN_limbs, size_t E_limbs );
+
+/**
+ * \brief            Perform a modular exponentiation with secret exponent:
+ *                   X = A^E mod N, where \p A is already in Montgomery form.
+ *
+ * \p X may be aliased to \p A, but not to \p RR or \p E, even if \p E_limbs ==
+ * \p AN_limbs.
+ *
+ * \param[out] X     The destination MPI, as a little endian array of length
+ *                   \p AN_limbs.
+ * \param[in] A      The base MPI, as a little endian array of length \p AN_limbs.
+ *                   Must be in Montgomery form.
+ * \param[in] N      The modulus, as a little endian array of length \p AN_limbs.
+ * \param AN_limbs   The number of limbs in \p X, \p A, \p N, \p RR.
+ * \param[in] E      The exponent, as a little endian array of length \p E_limbs.
+ * \param E_limbs    The number of limbs in \p E.
+ * \param[in] RR     The precomputed residue of 2^{2*biL} modulo N, as a little
+ *                   endian array of length \p AN_limbs.
+ * \param[in,out] T  Temporary storage of at least the number of limbs returned
+ *                   by `mbedtls_mpi_core_exp_mod_working_limbs()`.
+ *                   Its initial content is unused and its final content is
+ *                   indeterminate.
+ *                   It must not alias or otherwise overlap any of the other
+ *                   parameters.
+ *                   It is up to the caller to zeroize \p T when it is no
+ *                   longer needed, and before freeing it if it was dynamically
+ *                   allocated.
+ */
+void mbedtls_mpi_core_exp_mod( mbedtls_mpi_uint *X,
+                               const mbedtls_mpi_uint *A,
+                               const mbedtls_mpi_uint *N, size_t AN_limbs,
+                               const mbedtls_mpi_uint *E, size_t E_limbs,
+                               const mbedtls_mpi_uint *RR,
+                               mbedtls_mpi_uint *T );
+
 /* END MERGE SLOT 1 */
 
 /* BEGIN MERGE SLOT 2 */
diff --git a/library/bignum_mod.c b/library/bignum_mod.c
index 13108c5..7cf2fb2 100644
--- a/library/bignum_mod.c
+++ b/library/bignum_mod.c
@@ -39,7 +39,7 @@
                                    mbedtls_mpi_uint *p,
                                    size_t p_limbs )
 {
-    if( p_limbs < m->limbs || !mbedtls_mpi_core_lt_ct( m->p, p, p_limbs ) )
+    if( p_limbs != m->limbs || !mbedtls_mpi_core_lt_ct( p, m->p, m->limbs ) )
         return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
 
     r->limbs = m->limbs;
@@ -50,7 +50,7 @@
 
 void mbedtls_mpi_mod_residue_release( mbedtls_mpi_mod_residue *r )
 {
-    if ( r == NULL )
+    if( r == NULL )
         return;
 
     r->limbs = 0;
@@ -59,19 +59,18 @@
 
 void mbedtls_mpi_mod_modulus_init( mbedtls_mpi_mod_modulus *m )
 {
-    if ( m == NULL )
+    if( m == NULL )
         return;
 
     m->p = NULL;
     m->limbs = 0;
     m->bits = 0;
-    m->ext_rep = MBEDTLS_MPI_MOD_EXT_REP_INVALID;
     m->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
 }
 
 void mbedtls_mpi_mod_modulus_free( mbedtls_mpi_mod_modulus *m )
 {
-    if ( m == NULL )
+    if( m == NULL )
         return;
 
     switch( m->int_rep )
@@ -96,7 +95,6 @@
     m->p = NULL;
     m->limbs = 0;
     m->bits = 0;
-    m->ext_rep = MBEDTLS_MPI_MOD_EXT_REP_INVALID;
     m->int_rep = MBEDTLS_MPI_MOD_REP_INVALID;
 }
 
@@ -112,17 +110,17 @@
     mbedtls_mpi_init( &N );
     mbedtls_mpi_init( &RR );
 
-    if ( A == NULL || limbs == 0 || limbs >= ( MBEDTLS_MPI_MAX_LIMBS / 2 ) - 2 )
+    if( A == NULL || limbs == 0 || limbs >= ( MBEDTLS_MPI_MAX_LIMBS / 2 ) - 2 )
         goto cleanup;
 
-    if ( mbedtls_mpi_grow( &N, limbs ) )
+    if( mbedtls_mpi_grow( &N, limbs ) )
         goto cleanup;
 
     memcpy( N.p, A, sizeof(mbedtls_mpi_uint) * limbs );
 
     ret = mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N);
 
-    if ( ret == 0 )
+    if( ret == 0 )
     {
         *X = RR.p;
         RR.p = NULL;
@@ -138,7 +136,6 @@
 int mbedtls_mpi_mod_modulus_setup( mbedtls_mpi_mod_modulus *m,
                                    const mbedtls_mpi_uint *p,
                                    size_t p_limbs,
-                                   mbedtls_mpi_mod_ext_rep ext_rep,
                                    mbedtls_mpi_mod_rep_selector int_rep )
 {
     int ret = 0;
@@ -147,17 +144,6 @@
     m->limbs = p_limbs;
     m->bits = mbedtls_mpi_core_bitlen( p, p_limbs );
 
-    switch( ext_rep )
-    {
-        case MBEDTLS_MPI_MOD_EXT_REP_LE:
-        case MBEDTLS_MPI_MOD_EXT_REP_BE:
-            m->ext_rep = ext_rep;
-            break;
-        default:
-            ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
-            goto exit;
-    }
-
     switch( int_rep )
     {
         case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
@@ -193,7 +179,18 @@
 /* END MERGE SLOT 2 */
 
 /* BEGIN MERGE SLOT 3 */
+int mbedtls_mpi_mod_sub( mbedtls_mpi_mod_residue *X,
+                         const mbedtls_mpi_mod_residue *A,
+                         const mbedtls_mpi_mod_residue *B,
+                         const mbedtls_mpi_mod_modulus *N )
+{
+    if( X->limbs != N->limbs || A->limbs != N->limbs || B->limbs != N->limbs )
+        return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA );
 
+    mbedtls_mpi_mod_raw_sub( X->p, A->p, B->p, N );
+
+    return( 0 );
+}
 /* END MERGE SLOT 3 */
 
 /* BEGIN MERGE SLOT 4 */
@@ -209,7 +206,71 @@
 /* END MERGE SLOT 6 */
 
 /* BEGIN MERGE SLOT 7 */
+int mbedtls_mpi_mod_read( mbedtls_mpi_mod_residue *r,
+                          const mbedtls_mpi_mod_modulus *m,
+                          const unsigned char *buf,
+                          size_t buflen,
+                          mbedtls_mpi_mod_ext_rep ext_rep )
+{
+    int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
 
+    /* Do our best to check if r and m have been set up */
+    if( r->limbs == 0 || m->limbs == 0 )
+        goto cleanup;
+    if( r->limbs != m->limbs )
+        goto cleanup;
+
+    ret = mbedtls_mpi_mod_raw_read( r->p, m, buf, buflen, ext_rep );
+    if( ret != 0 )
+        goto cleanup;
+
+    r->limbs = m->limbs;
+
+    if( m->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY )
+       ret = mbedtls_mpi_mod_raw_to_mont_rep( r->p, m );
+
+cleanup:
+    return ( ret );
+}
+
+int mbedtls_mpi_mod_write( const mbedtls_mpi_mod_residue *r,
+                           const mbedtls_mpi_mod_modulus *m,
+                           unsigned char *buf,
+                           size_t buflen,
+                           mbedtls_mpi_mod_ext_rep ext_rep )
+{
+    int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+
+    /* Do our best to check if r and m have been set up */
+    if( r->limbs == 0 || m->limbs == 0 )
+        goto cleanup;
+    if( r->limbs != m->limbs )
+        goto cleanup;
+
+    if( m->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY )
+    {
+        ret = mbedtls_mpi_mod_raw_from_mont_rep( r->p, m );
+        if( ret != 0 )
+            goto cleanup;
+    }
+
+    ret = mbedtls_mpi_mod_raw_write( r->p, m, buf, buflen, ext_rep );
+
+    if( m->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY )
+    {
+        /* If this fails, the value of r is corrupted and we want to return
+         * this error (as opposed to the error code from the write above) to
+         * let the caller know. If it succeeds, we want to return the error
+         * code from write above. */
+        int conv_ret = mbedtls_mpi_mod_raw_to_mont_rep( r->p, m );
+        if( ret == 0 )
+            ret = conv_ret;
+    }
+
+cleanup:
+
+    return ( ret );
+}
 /* END MERGE SLOT 7 */
 
 /* BEGIN MERGE SLOT 8 */
diff --git a/library/bignum_mod.h b/library/bignum_mod.h
index 29c26f2..0a8f4d3 100644
--- a/library/bignum_mod.h
+++ b/library/bignum_mod.h
@@ -64,7 +64,6 @@
     const mbedtls_mpi_uint *p;
     size_t limbs;                            // number of limbs
     size_t bits;                             // bitlen of p
-    mbedtls_mpi_mod_ext_rep ext_rep;         // signals external representation (eg. byte order)
     mbedtls_mpi_mod_rep_selector int_rep;    // selector to signal the active member of the union
     union rep
     {
@@ -75,16 +74,27 @@
 
 /** Setup a residue structure.
  *
- * \param[out] r    The address of residue to setup. The size is determined by
- *                  \p m.
- *                  (In particular, it must have at least as many limbs as the
- *                  modulus \p m.)
+ * The residue will be set up with the buffer \p p and modulus \p m.
+ *
+ * The memory pointed to by \p p will be used by the resulting residue structure.
+ * The value at the pointed-to memory will be the initial value of \p r and must
+ * hold a value that is less than the modulus. This value will be used as-is
+ * and interpreted according to the value of the `m->int_rep` field.
+ *
+ * The modulus \p m will be the modulus associated with \p r. The residue \p r
+ * should only be used in operations where the modulus is \p m.
+ *
+ * \param[out] r    The address of the residue to setup.
  * \param[in] m     The address of the modulus related to \p r.
- * \param[in] p     The address of the limb array storing the value of \p r.
+ * \param[in] p     The address of the limb array containing the value of \p r.
  *                  The memory pointed to by \p p will be used by \p r and must
  *                  not be modified in any way until after
- *                  mbedtls_mpi_mod_residue_release() is called.
- * \param p_limbs   The number of limbs of \p p.
+ *                  mbedtls_mpi_mod_residue_release() is called. The data
+ *                  pointed to by \p p must be less than the modulus (the value
+ *                  pointed to by `m->p`) and already in the representation
+ *                  indicated by `m->int_rep`.
+ * \param p_limbs   The number of limbs of \p p. Must be the same as the number
+ *                  of limbs in the modulus \p m.
  *
  * \return      \c 0 if successful.
  * \return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p p_limbs is less than the
@@ -121,19 +131,15 @@
  *                  not be modified in any way until after
  *                  mbedtls_mpi_mod_modulus_free() is called.
  * \param p_limbs   The number of limbs of \p p.
- * \param ext_rep   The external representation to be used for residues
- *                  associated with \p m (see #mbedtls_mpi_mod_ext_rep).
  * \param int_rep   The internal representation to be used for residues
  *                  associated with \p m (see #mbedtls_mpi_mod_rep_selector).
  *
  * \return      \c 0 if successful.
- * \return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep or \p int_rep is
- *              invalid.
+ * \return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p int_rep is invalid.
  */
 int mbedtls_mpi_mod_modulus_setup( mbedtls_mpi_mod_modulus *m,
                                    const mbedtls_mpi_uint *p,
                                    size_t p_limbs,
-                                   mbedtls_mpi_mod_ext_rep ext_rep,
                                    mbedtls_mpi_mod_rep_selector int_rep );
 
 /** Free elements of a modulus structure.
@@ -157,7 +163,35 @@
 /* END MERGE SLOT 2 */
 
 /* BEGIN MERGE SLOT 3 */
-
+/**
+ * \brief Perform a fixed-size modular subtraction.
+ *
+ * Calculate `A - B modulo N`.
+ *
+ * \p A, \p B and \p X must all have the same number of limbs as \p N.
+ *
+ * \p X may be aliased to \p A or \p B, or even both, but may not overlap
+ * either otherwise.
+ *
+ * \note This function does not check that \p A or \p B are in canonical
+ *       form (that is, are < \p N) - that will have been done by
+ *       mbedtls_mpi_mod_residue_setup().
+ *
+ * \param[out] X    The address of the result MPI. Must be initialized.
+ *                  Must have the same number of limbs as the modulus \p N.
+ * \param[in]  A    The address of the first MPI.
+ * \param[in]  B    The address of the second MPI.
+ * \param[in]  N    The address of the modulus. Used to perform a modulo
+ *                  operation on the result of the subtraction.
+ *
+ * \return          \c 0 if successful.
+ * \return          #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not
+ *                  have the correct number of limbs.
+ */
+int mbedtls_mpi_mod_sub( mbedtls_mpi_mod_residue *X,
+                         const mbedtls_mpi_mod_residue *A,
+                         const mbedtls_mpi_mod_residue *B,
+                         const mbedtls_mpi_mod_modulus *N );
 /* END MERGE SLOT 3 */
 
 /* BEGIN MERGE SLOT 4 */
@@ -173,7 +207,72 @@
 /* END MERGE SLOT 6 */
 
 /* BEGIN MERGE SLOT 7 */
+/** Read a residue from a byte buffer.
+ *
+ * The residue will be automatically converted to the internal representation
+ * based on the value of the `m->int_rep` field.
+ *
+ * The modulus \p m will be the modulus associated with \p r. The residue \p r
+ * should only be used in operations where the modulus is \p m or a modulus
+ * equivalent to \p m (in the sense that all their fields or memory pointed by
+ * their fields hold the same value).
+ *
+ * \param[out] r    The address of the residue. It must have exactly the same
+ *                  number of limbs as the modulus \p m.
+ * \param[in] m     The address of the modulus.
+ * \param[in] buf   The input buffer to import from.
+ * \param buflen    The length in bytes of \p buf.
+ * \param ext_rep   The endianness of the number in the input buffer.
+ *
+ * \return       \c 0 if successful.
+ * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p r isn't
+ *               large enough to hold the value in \p buf.
+ * \return       #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep
+ *               is invalid or the value in the buffer is not less than \p m.
+ */
+int mbedtls_mpi_mod_read( mbedtls_mpi_mod_residue *r,
+                          const mbedtls_mpi_mod_modulus *m,
+                          const unsigned char *buf,
+                          size_t buflen,
+                          mbedtls_mpi_mod_ext_rep ext_rep );
 
+/** Write a residue into a byte buffer.
+ *
+ * The modulus \p m must be the modulus associated with \p r (see
+ * mbedtls_mpi_mod_residue_setup() and mbedtls_mpi_mod_read()).
+ *
+ * The residue will be automatically converted from the internal representation
+ * based on the value of `m->int_rep` field.
+ *
+ * \warning     If the buffer is smaller than `m->bits`, the number of
+ *              leading zeroes is leaked through timing. If \p r is
+ *              secret, the caller must ensure that \p buflen is at least
+ *              (`m->bits`+7)/8.
+ *
+ * \param[in] r     The address of the residue. It must have the same number of
+ *                  limbs as the modulus \p m. (\p r is an input parameter, but
+ *                  its value will be modified during execution and restored
+ *                  before the function returns.)
+ * \param[in] m     The address of the modulus associated with \r.
+ * \param[out] buf  The output buffer to export to.
+ * \param buflen    The length in bytes of \p buf.
+ * \param ext_rep   The endianness in which the number should be written into
+ *                  the output buffer.
+ *
+ * \return       \c 0 if successful.
+ * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't
+ *               large enough to hold the value of \p r (without leading
+ *               zeroes).
+ * \return       #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep is invalid.
+ * \return       #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough
+ *               memory for conversion. Can occur only for moduli with
+ *               MBEDTLS_MPI_MOD_REP_MONTGOMERY.
+ */
+int mbedtls_mpi_mod_write( const mbedtls_mpi_mod_residue *r,
+                           const mbedtls_mpi_mod_modulus *m,
+                           unsigned char *buf,
+                           size_t buflen,
+                           mbedtls_mpi_mod_ext_rep ext_rep );
 /* END MERGE SLOT 7 */
 
 /* BEGIN MERGE SLOT 8 */
diff --git a/library/bignum_mod_raw.c b/library/bignum_mod_raw.c
index 2f49ea2..266d915 100644
--- a/library/bignum_mod_raw.c
+++ b/library/bignum_mod_raw.c
@@ -52,11 +52,12 @@
 int mbedtls_mpi_mod_raw_read( mbedtls_mpi_uint *X,
                               const mbedtls_mpi_mod_modulus *m,
                               const unsigned char *input,
-                              size_t input_length )
+                              size_t input_length,
+                              mbedtls_mpi_mod_ext_rep ext_rep )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    switch( m->ext_rep )
+    switch( ext_rep )
     {
         case MBEDTLS_MPI_MOD_EXT_REP_LE:
             ret = mbedtls_mpi_core_read_le( X, m->limbs,
@@ -87,9 +88,10 @@
 int mbedtls_mpi_mod_raw_write( const mbedtls_mpi_uint *A,
                                const mbedtls_mpi_mod_modulus *m,
                                unsigned char *output,
-                               size_t output_length )
+                               size_t output_length,
+                               mbedtls_mpi_mod_ext_rep ext_rep )
 {
-    switch( m->ext_rep )
+    switch( ext_rep )
     {
         case MBEDTLS_MPI_MOD_EXT_REP_LE:
             return( mbedtls_mpi_core_write_le( A, m->limbs,
@@ -122,6 +124,37 @@
 
 /* BEGIN MERGE SLOT 3 */
 
+size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs( size_t AN_limbs )
+{
+    /* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent,
+     * which will be the same size as the modulus and input (AN_limbs),
+     * and additional space to pass to mbedtls_mpi_core_exp_mod(). */
+    return( AN_limbs +
+            mbedtls_mpi_core_exp_mod_working_limbs( AN_limbs, AN_limbs ) );
+}
+
+void mbedtls_mpi_mod_raw_inv_prime( mbedtls_mpi_uint *X,
+                                    const mbedtls_mpi_uint *A,
+                                    const mbedtls_mpi_uint *N,
+                                    size_t AN_limbs,
+                                    const mbedtls_mpi_uint *RR,
+                                    mbedtls_mpi_uint *T )
+{
+    /* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and
+     *                       |G| = N - 1, so we want
+     *                 g^(|G|-1) = g^(N - 2)
+     */
+
+    /* Use the first AN_limbs of T to hold N - 2 */
+    mbedtls_mpi_uint *Nminus2 = T;
+    (void) mbedtls_mpi_core_sub_int( Nminus2, N, 2, AN_limbs );
+
+    /* Rest of T is given to exp_mod for its working space */
+    mbedtls_mpi_core_exp_mod( X,
+                              A, N, AN_limbs, Nminus2, AN_limbs,
+                              RR, T + AN_limbs );
+}
+
 /* END MERGE SLOT 3 */
 
 /* BEGIN MERGE SLOT 4 */
diff --git a/library/bignum_mod_raw.h b/library/bignum_mod_raw.h
index f6c6ebd..698119e 100644
--- a/library/bignum_mod_raw.h
+++ b/library/bignum_mod_raw.h
@@ -106,6 +106,7 @@
  * \param[in] m         The address of the modulus related to \p X.
  * \param[in] input     The input buffer to import from.
  * \param input_length  The length in bytes of \p input.
+ * \param ext_rep       The endianness of the number in the input buffer.
  *
  * \return       \c 0 if successful.
  * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't
@@ -116,7 +117,8 @@
 int mbedtls_mpi_mod_raw_read( mbedtls_mpi_uint *X,
                               const mbedtls_mpi_mod_modulus *m,
                               const unsigned char *input,
-                              size_t input_length );
+                              size_t input_length,
+                              mbedtls_mpi_mod_ext_rep ext_rep );
 
 /** Export A into unsigned binary data.
  *
@@ -126,6 +128,7 @@
  * \param[in] m         The address of the modulus related to \p A.
  * \param[out] output   The output buffer to export to.
  * \param output_length The length in bytes of \p output.
+ * \param ext_rep       The endianness in which the number should be written into the output buffer.
  *
  * \return       \c 0 if successful.
  * \return       #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't
@@ -136,7 +139,8 @@
 int mbedtls_mpi_mod_raw_write( const mbedtls_mpi_uint *A,
                                const mbedtls_mpi_mod_modulus *m,
                                unsigned char *output,
-                               size_t output_length );
+                               size_t output_length,
+                               mbedtls_mpi_mod_ext_rep ext_rep );
 
 /* BEGIN MERGE SLOT 1 */
 
@@ -170,6 +174,51 @@
 
 /* BEGIN MERGE SLOT 3 */
 
+/**
+ * \brief          Returns the number of limbs of working memory required for
+ *                 a call to `mbedtls_mpi_mod_raw_inv_prime()`.
+ *
+ * \param AN_limbs The number of limbs in the input `A` and the modulus `N`
+ *                 (they must be the same size) that will be given to
+ *                 `mbedtls_mpi_mod_raw_inv_prime()`.
+ *
+ * \return         The number of limbs of working memory required by
+ *                 `mbedtls_mpi_mod_raw_inv_prime()`.
+ */
+size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs( size_t AN_limbs );
+
+/**
+ * \brief Perform fixed-width modular inversion of a Montgomery-form MPI with
+ *        respect to a modulus \p N that must be prime.
+ *
+ * \p X may be aliased to \p A, but not to \p N or \p RR.
+ *
+ * \param[out] X     The modular inverse of \p A with respect to \p N.
+ *                   Will be in Montgomery form.
+ * \param[in] A      The number to calculate the modular inverse of.
+ *                   Must be in Montgomery form. Must not be 0.
+ * \param[in] N      The modulus, as a little-endian array of length \p AN_limbs.
+ *                   Must be prime.
+ * \param AN_limbs   The number of limbs in \p A, \p N and \p RR.
+ * \param[in] RR     The precomputed residue of 2^{2*biL} modulo N, as a little-
+ *                   endian array of length \p AN_limbs.
+ * \param[in,out] T  Temporary storage of at least the number of limbs returned
+ *                   by `mbedtls_mpi_mod_raw_inv_prime_working_limbs()`.
+ *                   Its initial content is unused and its final content is
+ *                   indeterminate.
+ *                   It must not alias or otherwise overlap any of the other
+ *                   parameters.
+ *                   It is up to the caller to zeroize \p T when it is no
+ *                   longer needed, and before freeing it if it was dynamically
+ *                   allocated.
+ */
+void mbedtls_mpi_mod_raw_inv_prime( mbedtls_mpi_uint *X,
+                                    const mbedtls_mpi_uint *A,
+                                    const mbedtls_mpi_uint *N,
+                                    size_t AN_limbs,
+                                    const mbedtls_mpi_uint *RR,
+                                    mbedtls_mpi_uint *T );
+
 /* END MERGE SLOT 3 */
 
 /* BEGIN MERGE SLOT 4 */
diff --git a/library/ccm.c b/library/ccm.c
index 7bf9e9f..065eb60 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -142,7 +142,7 @@
     unsigned char i;
     size_t len_left, olen;
 
-    /* length calulcation can be done only after both
+    /* length calculation can be done only after both
      * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed
      */
     if( !(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGTHS_SET) )
diff --git a/library/debug.c b/library/debug.c
index 6114a46..78ce9ce 100644
--- a/library/debug.c
+++ b/library/debug.c
@@ -107,7 +107,7 @@
     /*
      * With non-blocking I/O and examples that just retry immediately,
      * the logs would be quickly flooded with WANT_READ, so ignore that.
-     * Don't ignore WANT_WRITE however, since is is usually rare.
+     * Don't ignore WANT_WRITE however, since it is usually rare.
      */
     if( ret == MBEDTLS_ERR_SSL_WANT_READ )
         return;
diff --git a/library/lmots.h b/library/lmots.h
index 39e8699..022dcf3 100644
--- a/library/lmots.h
+++ b/library/lmots.h
@@ -139,7 +139,7 @@
  *                           this public key.
  *
  * \param ctx                The initialized LMOTS context that contains the
- *                           publc key.
+ *                           public key.
  * \param key                The buffer into which the key will be output. Must
  *                           be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size.
  *
diff --git a/library/mps_reader.c b/library/mps_reader.c
index 6f823bd..df97b6c 100644
--- a/library/mps_reader.c
+++ b/library/mps_reader.c
@@ -530,7 +530,7 @@
          * of the accumulator. */
         memmove( acc, acc + acc_backup_offset, acc_backup_len );
 
-        /* Copy uncmmitted parts of the current fragment to the
+        /* Copy uncommitted parts of the current fragment to the
          * accumulator. */
         memcpy( acc + acc_backup_len,
                 frag + frag_backup_offset, frag_backup_len );
diff --git a/library/pkcs7.c b/library/pkcs7.c
index ca0170a..5b22afa 100644
--- a/library/pkcs7.c
+++ b/library/pkcs7.c
@@ -103,15 +103,13 @@
                                             | MBEDTLS_ASN1_SEQUENCE );
     if( ret != 0 ) {
         *p = start;
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret );
-        goto out;
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret ) );
     }
 
     ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
     if( ret != 0 ) {
         *p = start;
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret );
-        goto out;
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret ) );
     }
 
     pkcs7->tag = MBEDTLS_ASN1_OID;
@@ -119,7 +117,6 @@
     pkcs7->p = *p;
     *p += len;
 
-out:
     return( ret );
 }
 
@@ -153,8 +150,7 @@
                                             | MBEDTLS_ASN1_SET );
     if( ret != 0 )
     {
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret );
-        goto out;
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret ) );
     }
 
     end = *p + len;
@@ -162,16 +158,14 @@
     ret = mbedtls_asn1_get_alg_null( p, end, alg );
     if( ret != 0 )
     {
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret );
-        goto out;
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret ) );
     }
 
     /** For now, it assumes there is only one digest algorithm specified **/
     if ( *p != end )
-        ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
+        return( MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE );
 
-out:
-    return( ret );
+    return( 0 );
 }
 
 /**
@@ -195,10 +189,9 @@
                     | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
     {
         if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
-            ret = 0;
+            return( 0 );
         else
-            ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
-        goto out;
+            return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret ) );
     }
     start = *p;
     end_set = *p + len1;
@@ -207,8 +200,7 @@
             | MBEDTLS_ASN1_SEQUENCE );
     if( ret != 0 )
     {
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CERT, ret );
-        goto out;
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CERT, ret ) );
     }
 
     end_cert = *p + len2;
@@ -221,15 +213,13 @@
      */
     if ( end_cert != end_set )
     {
-        ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
-        goto out;
+        return( MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE );
     }
 
     *p = start;
     if( ( ret = mbedtls_x509_crt_parse_der( certs, *p, len1 ) ) < 0 )
     {
-        ret = MBEDTLS_ERR_PKCS7_INVALID_CERT;
-        goto out;
+        return( MBEDTLS_ERR_PKCS7_INVALID_CERT );
     }
 
     *p = *p + len1;
@@ -238,10 +228,7 @@
      * Since in this version we strictly support single certificate, and reaching
      * here implies we have parsed successfully, we return 1.
      */
-    ret = 1;
-
-out:
-    return( ret );
+    return( 1 );
 }
 
 /**
@@ -255,7 +242,7 @@
 
     ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OCTET_STRING );
     if( ret != 0 )
-        goto out;
+        return( ret );
 
     signature->tag = MBEDTLS_ASN1_OCTET_STRING;
     signature->len = len;
@@ -263,8 +250,7 @@
 
     *p = *p + len;
 
-out:
-    return( ret );
+    return( 0 );
 }
 
 /**
@@ -328,7 +314,7 @@
     if( ret != 0 )
         goto out;
 
-    /* Asssume authenticatedAttributes is nonexistent */
+    /* Assume authenticatedAttributes is nonexistent */
 
     ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->sig_alg_identifier );
     if( ret != 0 )
@@ -367,6 +353,7 @@
         name_cur = name_cur->next;
         mbedtls_free( name_prv );
     }
+    signer->issuer.next = NULL;
 }
 
 /**
@@ -382,34 +369,32 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int count = 0;
     size_t len = 0;
-    mbedtls_pkcs7_signer_info *signer, *prev;
 
     ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
                                 | MBEDTLS_ASN1_SET );
     if( ret != 0 )
     {
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret );
-        goto out;
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret ) );
     }
 
     /* Detect zero signers */
     if( len == 0 )
     {
-        ret = 0;
-        goto out;
+        return( 0 );
     }
 
     end_set = *p + len;
 
     ret = pkcs7_get_signer_info( p, end_set, signers_set );
     if( ret != 0 )
-        goto out;
+        goto cleanup;
     count++;
 
-    prev = signers_set;
+    mbedtls_pkcs7_signer_info *prev = signers_set;
     while( *p != end_set )
     {
-        signer = mbedtls_calloc( 1, sizeof( mbedtls_pkcs7_signer_info ) );
+        mbedtls_pkcs7_signer_info *signer =
+            mbedtls_calloc( 1, sizeof( mbedtls_pkcs7_signer_info ) );
         if( !signer )
         {
             ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
@@ -426,21 +411,19 @@
         count++;
     }
 
-    ret = count;
-    goto out;
+    return( count );
 
 cleanup:
-    signer = signers_set->next;
     pkcs7_free_signer_info( signers_set );
-    while( signer )
+    mbedtls_pkcs7_signer_info *signer = signers_set->next;
+    while( signer != NULL )
     {
         prev = signer;
         signer = signer->next;
         pkcs7_free_signer_info( prev );
         mbedtls_free( prev );
     }
-
-out:
+    signers_set->next = NULL;
     return( ret );
 }
 
@@ -470,8 +453,7 @@
                                 | MBEDTLS_ASN1_SEQUENCE );
     if( ret != 0 )
     {
-        ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
-        goto out;
+        return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret ) );
     }
 
     end_set = p + len;
@@ -479,37 +461,35 @@
     /* Get version of signed data */
     ret = pkcs7_get_version( &p, end_set, &signed_data->version );
     if( ret != 0 )
-        goto out;
+        return( ret );
 
     /* Get digest algorithm */
     ret = pkcs7_get_digest_algorithm_set( &p, end_set,
             &signed_data->digest_alg_identifiers );
     if( ret != 0 )
-        goto out;
+        return( ret );
 
     ret = mbedtls_oid_get_md_alg( &signed_data->digest_alg_identifiers, &md_alg );
     if( ret != 0 )
     {
-        ret = MBEDTLS_ERR_PKCS7_INVALID_ALG;
-        goto out;
+        return( MBEDTLS_ERR_PKCS7_INVALID_ALG );
     }
 
     /* Do not expect any content */
     ret = pkcs7_get_content_info_type( &p, end_set, &signed_data->content.oid );
     if( ret != 0 )
-        goto out;
+        return( ret );
 
     if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &signed_data->content.oid ) )
     {
-        ret = MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
-        goto out;
+        return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO );
     }
 
     /* Look for certificates, there may or may not be any */
     mbedtls_x509_crt_init( &signed_data->certs );
     ret = pkcs7_get_certificates( &p, end_set, &signed_data->certs );
     if( ret < 0 )
-        goto out;
+        return( ret );
 
     signed_data->no_of_certs = ret;
 
@@ -524,18 +504,15 @@
     /* Get signers info */
     ret = pkcs7_get_signers_info_set( &p, end_set, &signed_data->signers );
     if( ret < 0 )
-        goto out;
+        return( ret );
 
     signed_data->no_of_signers = ret;
 
     /* Don't permit trailing data */
     if ( p != end )
-        ret = MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
-    else
-        ret = 0;
+        return( MBEDTLS_ERR_PKCS7_INVALID_FORMAT );
 
-out:
-    return( ret );
+    return( 0 );
 }
 
 int mbedtls_pkcs7_parse_der( mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
@@ -547,10 +524,9 @@
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int isoidset = 0;
 
-    if( !pkcs7 )
+    if( pkcs7 == NULL )
     {
-        ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
-        goto out;
+        return( MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA );
     }
 
     /* make an internal copy of the buffer for parsing */
@@ -630,15 +606,13 @@
 
     if( pkcs7->signed_data.no_of_signers == 0 )
     {
-        ret = MBEDTLS_ERR_PKCS7_INVALID_CERT;
-        goto out;
+        return( MBEDTLS_ERR_PKCS7_INVALID_CERT );
     }
 
     if( mbedtls_x509_time_is_past( &cert->valid_to ) ||
         mbedtls_x509_time_is_future( &cert->valid_from ))
     {
-        ret = MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID;
-        goto out;
+        return( MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID );
     }
 
     /*
@@ -672,9 +646,9 @@
 
         hash = mbedtls_calloc( mbedtls_md_get_size( md_info ), 1 );
         if( hash == NULL ) {
-            ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
-            goto out;
+            return( MBEDTLS_ERR_PKCS7_ALLOC_FAILED );
         }
+        /* BEGIN must free hash before jumping out */
         if( is_data_hash )
         {
             if( datalen != mbedtls_md_get_size( md_info ))
@@ -697,12 +671,12 @@
                                  mbedtls_md_get_size( md_info ),
                                  signer->sig.p, signer->sig.len );
         mbedtls_free( hash );
+        /* END must free hash before jumping out */
 
         if( ret == 0 )
             break;
     }
 
-out:
     return( ret );
 }
 int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7,
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index e881f2f..cb5791f 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -5723,63 +5723,46 @@
 /* Key agreement */
 /****************************************************************/
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
-static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key,
+psa_status_t psa_key_agreement_raw_builtin( const psa_key_attributes_t *attributes,
+                                            const uint8_t *key_buffer,
+                                            size_t key_buffer_size,
+                                            psa_algorithm_t alg,
+                                            const uint8_t *peer_key,
                                             size_t peer_key_length,
-                                            const mbedtls_ecp_keypair *our_key,
                                             uint8_t *shared_secret,
                                             size_t shared_secret_size,
                                             size_t *shared_secret_length )
 {
-    mbedtls_ecp_keypair *their_key = NULL;
-    mbedtls_ecdh_context ecdh;
-    psa_status_t status;
-    size_t bits = 0;
-    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa( our_key->grp.id, &bits );
-    mbedtls_ecdh_init( &ecdh );
-
-    status = mbedtls_psa_ecp_load_representation(
-                 PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
-                 bits,
-                 peer_key,
-                 peer_key_length,
-                 &their_key );
-    if( status != PSA_SUCCESS )
-        goto exit;
-
-    status = mbedtls_to_psa_error(
-        mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ) );
-    if( status != PSA_SUCCESS )
-        goto exit;
-    status = mbedtls_to_psa_error(
-        mbedtls_ecdh_get_params( &ecdh, our_key, MBEDTLS_ECDH_OURS ) );
-    if( status != PSA_SUCCESS )
-        goto exit;
-
-    status = mbedtls_to_psa_error(
-        mbedtls_ecdh_calc_secret( &ecdh,
-                                  shared_secret_length,
-                                  shared_secret, shared_secret_size,
-                                  mbedtls_psa_get_random,
-                                  MBEDTLS_PSA_RANDOM_STATE ) );
-    if( status != PSA_SUCCESS )
-        goto exit;
-    if( PSA_BITS_TO_BYTES( bits ) != *shared_secret_length )
-        status = PSA_ERROR_CORRUPTION_DETECTED;
-
-exit:
-    if( status != PSA_SUCCESS )
-        mbedtls_platform_zeroize( shared_secret, shared_secret_size );
-    mbedtls_ecdh_free( &ecdh );
-    mbedtls_ecp_keypair_free( their_key );
-    mbedtls_free( their_key );
-
-    return( status );
-}
+    switch( alg )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
+        case PSA_ALG_ECDH:
+            return( mbedtls_psa_key_agreement_ecdh( attributes, key_buffer,
+                                                    key_buffer_size, alg,
+                                                    peer_key, peer_key_length,
+                                                    shared_secret,
+                                                    shared_secret_size,
+                                                    shared_secret_length ) );
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
+        default:
+            (void) attributes;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) peer_key;
+            (void) peer_key_length;
+            (void) shared_secret;
+            (void) shared_secret_size;
+            (void) shared_secret_length;
+            return( PSA_ERROR_NOT_SUPPORTED );
+    }
+}
 
-#define PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE MBEDTLS_ECP_MAX_BYTES
-
+/** Internal function for raw key agreement
+ *  Calls the driver wrapper which will hand off key agreement task
+ *  to the driver's implementation if a driver is present.
+ *  Fallback specified in the driver wrapper is built-in raw key agreement
+ *  (psa_key_agreement_raw_builtin).
+ */
 static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg,
                                                     psa_key_slot_t *private_key,
                                                     const uint8_t *peer_key,
@@ -5788,38 +5771,20 @@
                                                     size_t shared_secret_size,
                                                     size_t *shared_secret_length )
 {
-    switch( alg )
-    {
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
-        case PSA_ALG_ECDH:
-            if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->attr.type ) )
-                return( PSA_ERROR_INVALID_ARGUMENT );
-            mbedtls_ecp_keypair *ecp = NULL;
-            psa_status_t status = mbedtls_psa_ecp_load_representation(
-                                      private_key->attr.type,
-                                      private_key->attr.bits,
-                                      private_key->key.data,
-                                      private_key->key.bytes,
-                                      &ecp );
-            if( status != PSA_SUCCESS )
-                return( status );
-            status = psa_key_agreement_ecdh( peer_key, peer_key_length,
-                                             ecp,
-                                             shared_secret, shared_secret_size,
-                                             shared_secret_length );
-            mbedtls_ecp_keypair_free( ecp );
-            mbedtls_free( ecp );
-            return( status );
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
-        default:
-            (void) private_key;
-            (void) peer_key;
-            (void) peer_key_length;
-            (void) shared_secret;
-            (void) shared_secret_size;
-            (void) shared_secret_length;
-            return( PSA_ERROR_NOT_SUPPORTED );
-    }
+    if( !PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) )
+        return( PSA_ERROR_NOT_SUPPORTED );
+
+    psa_key_attributes_t attributes = {
+      .core = private_key->attr
+    };
+
+    return( psa_driver_wrapper_key_agreement( &attributes,
+                                              private_key->key.data,
+                                              private_key->key.bytes, alg,
+                                              peer_key, peer_key_length,
+                                              shared_secret,
+                                              shared_secret_size,
+                                              shared_secret_length ) );
 }
 
 /* Note that if this function fails, you must call psa_key_derivation_abort()
@@ -5832,7 +5797,7 @@
                                                 size_t peer_key_length )
 {
     psa_status_t status;
-    uint8_t shared_secret[PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE];
+    uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE];
     size_t shared_secret_length = 0;
     psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE( operation->alg );
 
@@ -6033,7 +5998,7 @@
     if( status != PSA_SUCCESS )
         return( status );
     /* Breaking up a request into smaller chunks is currently not supported
-     * for the extrernal RNG interface. */
+     * for the external RNG interface. */
     if( output_length != output_size )
         return( PSA_ERROR_INSUFFICIENT_ENTROPY );
     return( PSA_SUCCESS );
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index 5cefa27..614cad1 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -549,4 +549,62 @@
  */
 psa_status_t psa_validate_unstructured_key_bit_size( psa_key_type_t type,
                                                      size_t bits );
+
+/** Perform a key agreement and return the raw shared secret, using
+    built-in raw key agreement functions.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       key_agreement entry point. This function behaves as a key_agreement
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes           The attributes of the key to use for the
+ *                                  operation.
+ * \param[in]  key_buffer           The buffer containing the private key
+ *                                  context.
+ * \param[in]  key_buffer_size      Size of the \p key_buffer buffer in
+ *                                  bytes.
+ * \param[in]  alg                  A key agreement algorithm that is
+ *                                  compatible with the type of the key.
+ * \param[in]  peer_key             The buffer containing the key context
+ *                                  of the peer's public key.
+ * \param[in]  peer_key_length      Size of the \p peer_key buffer in
+ *                                  bytes.
+ * \param[out] shared_secret        The buffer to which the shared secret
+ *                                  is to be written.
+ * \param[in]  shared_secret_size   Size of the \p shared_secret buffer in
+ *                                  bytes.
+ * \param[out] shared_secret_length On success, the number of bytes that make
+ *                                  up the returned shared secret.
+ * \retval #PSA_SUCCESS
+ *         Success. Shared secret successfully calculated.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p alg is not a key agreement algorithm, or
+ *         \p private_key is not compatible with \p alg,
+ *         or \p peer_key is not valid for \p alg or not compatible with
+ *         \p private_key.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p shared_secret_size is too small
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not a supported key agreement algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE
+ * \retval #PSA_ERROR_HARDWARE_FAILURE
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ * \retval #PSA_ERROR_BAD_STATE
+ */
+psa_status_t psa_key_agreement_raw_builtin(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length );
+
 #endif /* PSA_CRYPTO_CORE_H */
diff --git a/library/psa_crypto_driver_wrappers.h b/library/psa_crypto_driver_wrappers.h
index ee23b6f..a19d7ec 100644
--- a/library/psa_crypto_driver_wrappers.h
+++ b/library/psa_crypto_driver_wrappers.h
@@ -357,6 +357,20 @@
     size_t output_size,
     size_t *output_length );
 
+/*
+ * Raw Key Agreement
+ */
+psa_status_t psa_driver_wrapper_key_agreement(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length );
+
 #endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */
 
 /* End of automatically generated file. */
diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c
index 29f53b9..537a748 100644
--- a/library/psa_crypto_ecp.c
+++ b/library/psa_crypto_ecp.c
@@ -33,6 +33,7 @@
 #include "mbedtls/platform.h"
 
 #include <mbedtls/ecdsa.h>
+#include <mbedtls/ecdh.h>
 #include <mbedtls/ecp.h>
 #include <mbedtls/error.h>
 
@@ -464,4 +465,76 @@
 #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
         * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
 
+/****************************************************************/
+/* ECDH Key Agreement */
+/****************************************************************/
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
+psa_status_t mbedtls_psa_key_agreement_ecdh(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,
+    uint8_t *shared_secret, size_t shared_secret_size,
+    size_t *shared_secret_length )
+{
+    psa_status_t status;
+    if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( attributes->core.type ) ||
+        ! PSA_ALG_IS_ECDH(alg) )
+                return( PSA_ERROR_INVALID_ARGUMENT );
+    mbedtls_ecp_keypair *ecp = NULL;
+    status = mbedtls_psa_ecp_load_representation(
+                attributes->core.type,
+                attributes->core.bits,
+                key_buffer,
+                key_buffer_size,
+                &ecp );
+    if( status != PSA_SUCCESS )
+        return( status );
+    mbedtls_ecp_keypair *their_key = NULL;
+    mbedtls_ecdh_context ecdh;
+    size_t bits = 0;
+    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa( ecp->grp.id, &bits );
+    mbedtls_ecdh_init( &ecdh );
+
+    status = mbedtls_psa_ecp_load_representation(
+                PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
+                bits,
+                peer_key,
+                peer_key_length,
+                &their_key );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    status = mbedtls_to_psa_error(
+        mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ) );
+    if( status != PSA_SUCCESS )
+        goto exit;
+    status = mbedtls_to_psa_error(
+        mbedtls_ecdh_get_params( &ecdh, ecp, MBEDTLS_ECDH_OURS ) );
+    if( status != PSA_SUCCESS )
+        goto exit;
+
+    status = mbedtls_to_psa_error(
+        mbedtls_ecdh_calc_secret( &ecdh,
+                                shared_secret_length,
+                                shared_secret, shared_secret_size,
+                                mbedtls_psa_get_random,
+                                MBEDTLS_PSA_RANDOM_STATE ) );
+    if( status != PSA_SUCCESS )
+        goto exit;
+    if( PSA_BITS_TO_BYTES( bits ) != *shared_secret_length )
+        status = PSA_ERROR_CORRUPTION_DETECTED;
+exit:
+    if( status != PSA_SUCCESS )
+        mbedtls_platform_zeroize( shared_secret, shared_secret_size );
+    mbedtls_ecdh_free( &ecdh );
+    mbedtls_ecp_keypair_free( their_key );
+    mbedtls_free( their_key );
+    mbedtls_ecp_keypair_free( ecp );
+    mbedtls_free( ecp );
+    return( status );
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
+
+
 #endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/library/psa_crypto_ecp.h b/library/psa_crypto_ecp.h
index 429c062..386e87a 100644
--- a/library/psa_crypto_ecp.h
+++ b/library/psa_crypto_ecp.h
@@ -218,4 +218,53 @@
     const uint8_t *key_buffer, size_t key_buffer_size,
     psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
     const uint8_t *signature, size_t signature_length );
+
+
+/** Perform a key agreement and return the raw ECDH shared secret.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       key_agreement entry point. This function behaves as a key_agreement
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes           The attributes of the key to use for the
+ *                                  operation.
+ * \param[in]  key_buffer           The buffer containing the private key
+ *                                  context.
+ * \param[in]  key_buffer_size      Size of the \p key_buffer buffer in
+ *                                  bytes.
+ * \param[in]  alg                  A key agreement algorithm that is
+ *                                  compatible with the type of the key.
+ * \param[in]  peer_key             The buffer containing the key context
+ *                                  of the peer's public key.
+ * \param[in]  peer_key_length      Size of the \p peer_key buffer in
+ *                                  bytes.
+ * \param[out] shared_secret        The buffer to which the shared secret
+ *                                  is to be written.
+ * \param[in]  shared_secret_size   Size of the \p shared_secret buffer in
+ *                                  bytes.
+ * \param[out] shared_secret_length On success, the number of bytes that make
+ *                                  up the returned shared secret.
+ * \retval #PSA_SUCCESS
+ *         Success. Shared secret successfully calculated.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p alg is not a key agreement algorithm, or
+ *         \p private_key is not compatible with \p alg,
+ *         or \p peer_key is not valid for \p alg or not compatible with
+ *         \p private_key.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p shared_secret_size is too small
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not a supported key agreement algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ */
+psa_status_t mbedtls_psa_key_agreement_ecdh(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,
+    uint8_t *shared_secret, size_t shared_secret_size,
+    size_t *shared_secret_length );
 #endif /* PSA_CRYPTO_ECP_H */
diff --git a/library/psa_crypto_pake.c b/library/psa_crypto_pake.c
index 659b712..da66dae 100644
--- a/library/psa_crypto_pake.c
+++ b/library/psa_crypto_pake.c
@@ -197,9 +197,14 @@
 psa_status_t psa_pake_setup( psa_pake_operation_t *operation,
                              const psa_pake_cipher_suite_t *cipher_suite)
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
     /* A context must be freshly initialized before it can be set up. */
     if( operation->alg != PSA_ALG_NONE )
-        return( PSA_ERROR_BAD_STATE );
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto error;
+    }
 
     if( cipher_suite == NULL ||
         PSA_ALG_IS_PAKE(cipher_suite->algorithm ) == 0 ||
@@ -207,7 +212,8 @@
           cipher_suite->type != PSA_PAKE_PRIMITIVE_TYPE_DH ) ||
         PSA_ALG_IS_HASH( cipher_suite->hash ) == 0 )
     {
-        return( PSA_ERROR_INVALID_ARGUMENT );
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto error;
     }
 
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
@@ -218,7 +224,8 @@
             cipher_suite->bits != 256 ||
             cipher_suite->hash != PSA_ALG_SHA_256 )
         {
-            return( PSA_ERROR_NOT_SUPPORTED );
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto error;
         }
 
         operation->alg = cipher_suite->algorithm;
@@ -238,7 +245,11 @@
     }
     else
 #endif
-    return( PSA_ERROR_NOT_SUPPORTED );
+    status = PSA_ERROR_NOT_SUPPORTED;
+
+error:
+    psa_pake_abort( operation );
+    return status;
 }
 
 psa_status_t psa_pake_set_password_key( psa_pake_operation_t *operation,
@@ -253,12 +264,13 @@
     if( operation->alg == PSA_ALG_NONE ||
         operation->state != PSA_PAKE_STATE_SETUP )
     {
-        return( PSA_ERROR_BAD_STATE );
+        status = PSA_ERROR_BAD_STATE;
+        goto error;
     }
 
     status = psa_get_key_attributes( password, &attributes );
     if( status != PSA_SUCCESS )
-        return( status );
+        goto error;
 
     type = psa_get_key_type( &attributes );
     usage = psa_get_key_usage_flags( &attributes );
@@ -268,11 +280,14 @@
     if( type != PSA_KEY_TYPE_PASSWORD &&
         type != PSA_KEY_TYPE_PASSWORD_HASH )
     {
-        return( PSA_ERROR_INVALID_ARGUMENT );
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto error;
     }
 
-    if( ( usage & PSA_KEY_USAGE_DERIVE ) == 0 )
-        return( PSA_ERROR_NOT_PERMITTED );
+    if( ( usage & PSA_KEY_USAGE_DERIVE ) == 0 ) {
+        status = PSA_ERROR_NOT_PERMITTED;
+        goto error;
+    }
 
     if( operation->password != NULL )
         return( PSA_ERROR_BAD_STATE );
@@ -297,47 +312,74 @@
         return( status );
 
     return( PSA_SUCCESS );
+
+error:
+    psa_pake_abort(operation);
+    return( status );
 }
 
 psa_status_t psa_pake_set_user( psa_pake_operation_t *operation,
                                 const uint8_t *user_id,
                                 size_t user_id_len )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
     if( operation->alg == PSA_ALG_NONE ||
         operation->state != PSA_PAKE_STATE_SETUP )
     {
-        return( PSA_ERROR_BAD_STATE );
+        status = PSA_ERROR_BAD_STATE;
+        goto error;
     }
 
     if( user_id_len == 0 || user_id == NULL )
-        return( PSA_ERROR_INVALID_ARGUMENT );
+    {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto error;
+    }
 
-    return( PSA_ERROR_NOT_SUPPORTED );
+    status = PSA_ERROR_NOT_SUPPORTED;
+
+error:
+    psa_pake_abort(operation);
+    return( status );
 }
 
 psa_status_t psa_pake_set_peer( psa_pake_operation_t *operation,
                                 const uint8_t *peer_id,
                                 size_t peer_id_len )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
     if( operation->alg == PSA_ALG_NONE ||
         operation->state != PSA_PAKE_STATE_SETUP )
     {
-        return( PSA_ERROR_BAD_STATE );
+        status = PSA_ERROR_BAD_STATE;
+        goto error;
     }
 
     if( peer_id_len == 0 || peer_id == NULL )
-        return( PSA_ERROR_INVALID_ARGUMENT );
+    {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto error;
+    }
 
-    return( PSA_ERROR_NOT_SUPPORTED );
+    status = PSA_ERROR_NOT_SUPPORTED;
+
+error:
+    psa_pake_abort(operation);
+    return( status );
 }
 
 psa_status_t psa_pake_set_role( psa_pake_operation_t *operation,
                                 psa_pake_role_t role )
 {
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
     if( operation->alg == PSA_ALG_NONE ||
         operation->state != PSA_PAKE_STATE_SETUP )
     {
-        return( PSA_ERROR_BAD_STATE );
+        status = PSA_ERROR_BAD_STATE;
+        goto error;
     }
 
     if( role != PSA_PAKE_ROLE_NONE &&
@@ -346,7 +388,8 @@
         role != PSA_PAKE_ROLE_CLIENT &&
         role != PSA_PAKE_ROLE_SERVER )
     {
-        return( PSA_ERROR_INVALID_ARGUMENT );
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto error;
     }
 
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
@@ -362,7 +405,11 @@
     }
     else
 #endif
-        return( PSA_ERROR_NOT_SUPPORTED );
+        status = PSA_ERROR_NOT_SUPPORTED;
+
+error:
+    psa_pake_abort(operation);
+    return( status );
 }
 
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
@@ -812,7 +859,10 @@
         operation->state != PSA_PAKE_STATE_READY ||
         operation->input_step != PSA_PAKE_STEP_DERIVE ||
         operation->output_step != PSA_PAKE_STEP_DERIVE )
-        return( PSA_ERROR_BAD_STATE );
+    {
+        status = PSA_ERROR_BAD_STATE;
+        goto error;
+    }
 
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
     if( operation->alg == PSA_ALG_JPAKE )
@@ -842,7 +892,13 @@
     }
     else
 #endif
-    return( PSA_ERROR_NOT_SUPPORTED );
+    status = PSA_ERROR_NOT_SUPPORTED;
+
+error:
+    psa_key_derivation_abort( output );
+    psa_pake_abort( operation );
+
+    return( status );
 }
 
 psa_status_t psa_pake_abort(psa_pake_operation_t * operation)
diff --git a/library/psa_crypto_se.h b/library/psa_crypto_se.h
index 549dfb6..693c3ea 100644
--- a/library/psa_crypto_se.h
+++ b/library/psa_crypto_se.h
@@ -139,7 +139,7 @@
     psa_se_drv_table_entry_t *driver,
     psa_key_slot_number_t *slot_number );
 
-/** Destoy a key in a secure element.
+/** Destroy a key in a secure element.
  *
  * This function calls the relevant driver method to destroy a key
  * and updates the driver's persistent data.
diff --git a/library/ssl_client.c b/library/ssl_client.c
index 0f0ea1d..2c4ce43 100644
--- a/library/ssl_client.c
+++ b/library/ssl_client.c
@@ -784,7 +784,7 @@
 
     /*
      * Generate the random bytes, except when responding to a verify request
-     * where we MUST reuse the previoulsy generated random bytes
+     * where we MUST reuse the previously generated random bytes
      * (RFC 6347 4.2.1).
      */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 1902d71..5808cab 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -143,7 +143,7 @@
               MBEDTLS_SSL_EXT_MASK( TRUNCATED_HMAC )                         | \
               MBEDTLS_SSL_EXT_MASK( UNRECOGNIZED ) )
 
-/* RFC 8446 section 4.2. Allowed extensions for ClienHello */
+/* RFC 8446 section 4.2. Allowed extensions for ClientHello */
 #define MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH                                  \
             ( MBEDTLS_SSL_EXT_MASK( SERVERNAME )                             | \
               MBEDTLS_SSL_EXT_MASK( MAX_FRAGMENT_LENGTH )                    | \
@@ -890,13 +890,6 @@
     uint16_t mtu;                       /*!<  Handshake mtu, used to fragment outgoing messages */
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    /*! TLS 1.3 transforms for 0-RTT and encrypted handshake messages.
-     *  Those pointers own the transforms they reference. */
-    mbedtls_ssl_transform *transform_handshake;
-    mbedtls_ssl_transform *transform_earlydata;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
-
     /*
      * Checksum contexts
      */
@@ -981,6 +974,8 @@
     unsigned char *certificate_request_context;
 #endif
 
+    /** TLS 1.3 transform for encrypted handshake messages. */
+    mbedtls_ssl_transform *transform_handshake;
     union
     {
         unsigned char early    [MBEDTLS_TLS1_3_MD_MAX_SIZE];
@@ -989,6 +984,11 @@
     } tls13_master_secrets;
 
     mbedtls_ssl_tls13_handshake_secrets tls13_hs_secrets;
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    mbedtls_ssl_tls13_early_secrets tls13_early_secrets;
+    /** TLS 1.3 transform for early data and handshake messages. */
+    mbedtls_ssl_transform *transform_earlydata;
+#endif
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index 732c346..753998e 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -382,30 +382,80 @@
 }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID || MBEDTLS_SSL_PROTO_TLS1_3 */
 
-/* `add_data` must have size 13 Bytes if the CID extension is disabled,
- * and 13 + 1 + CID-length Bytes if the CID extension is enabled. */
+/* The size of the `add_data` structure depends on various
+ * factors, namely
+ *
+ * 1) CID functionality disabled
+ *
+ * additional_data =
+ *    8:                    seq_num +
+ *    1:                       type +
+ *    2:                    version +
+ *    2:  length of inner plaintext +
+ *
+ * size = 13 bytes
+ *
+ * 2) CID functionality based on RFC 9146 enabled
+ *
+ * size = 8 + 1 + 1 + 1 + 2 + 2 + 6 + 2 + CID-length
+ *      = 23 + CID-length
+ *
+ * 3) CID functionality based on legacy CID version
+    according to draft-ietf-tls-dtls-connection-id-05
+ *  https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
+ *
+ * size = 13 + 1 + CID-length
+ *
+ * More information about the CID usage:
+ *
+ * Per Section 5.3 of draft-ietf-tls-dtls-connection-id-05 the
+ * size of the additional data structure is calculated as:
+ *
+ * additional_data =
+ *    8:                    seq_num +
+ *    1:                  tls12_cid +
+ *    2:     DTLSCipherText.version +
+ *    n:                        cid +
+ *    1:                 cid_length +
+ *    2: length_of_DTLSInnerPlaintext
+ *
+ * Per RFC 9146 the size of the add_data structure is calculated as:
+ *
+ * additional_data =
+ *    8:        seq_num_placeholder +
+ *    1:                  tls12_cid +
+ *    1:                 cid_length +
+ *    1:                  tls12_cid +
+ *    2:     DTLSCiphertext.version +
+ *    2:                      epoch +
+ *    6:            sequence_number +
+ *    n:                        cid +
+ *    2: length_of_DTLSInnerPlaintext
+ *
+ */
 static void ssl_extract_add_data_from_record( unsigned char* add_data,
                                               size_t *add_data_len,
                                               mbedtls_record *rec,
                                               mbedtls_ssl_protocol_version
-                                                tls_version,
+                                              tls_version,
                                               size_t taglen )
 {
-    /* Quoting RFC 5246 (TLS 1.2):
+    /* Several types of ciphers have been defined for use with TLS and DTLS,
+     * and the MAC calculations for those ciphers differ slightly. Further
+     * variants were added when the CID functionality was added with RFC 9146.
+     * This implementations also considers the use of a legacy version of the
+     * CID specification published in draft-ietf-tls-dtls-connection-id-05,
+     * which is used in deployments.
+     *
+     * We will distinguish between the non-CID and the CID cases below.
+     *
+     * --- Non-CID cases ---
+     *
+     * Quoting RFC 5246 (TLS 1.2):
      *
      *    additional_data = seq_num + TLSCompressed.type +
      *                      TLSCompressed.version + TLSCompressed.length;
      *
-     * For the CID extension, this is extended as follows
-     * (quoting draft-ietf-tls-dtls-connection-id-05,
-     *  https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05):
-     *
-     *       additional_data = seq_num + DTLSPlaintext.type +
-     *                         DTLSPlaintext.version +
-     *                         cid +
-     *                         cid_length +
-     *                         length_of_DTLSInnerPlaintext;
-     *
      * For TLS 1.3, the record sequence number is dropped from the AAD
      * and encoded within the nonce of the AEAD operation instead.
      * Moreover, the additional data involves the length of the TLS
@@ -421,11 +471,72 @@
      *
      *     TLSCiphertext.length = TLSInnerPlaintext.length + taglen.
      *
-     */
+     * --- CID cases ---
+     *
+     * RFC 9146 uses a common pattern when constructing the data
+     * passed into a MAC / AEAD cipher.
+     *
+     * Data concatenation for MACs used with block ciphers with
+     * Encrypt-then-MAC Processing (with CID):
+     *
+     *  data = seq_num_placeholder +
+     *         tls12_cid +
+     *         cid_length +
+     *         tls12_cid +
+     *         DTLSCiphertext.version +
+     *         epoch +
+     *         sequence_number +
+     *         cid +
+     *         DTLSCiphertext.length +
+     *         IV +
+     *         ENC(content + padding + padding_length)
+     *
+     * Data concatenation for MACs used with block ciphers (with CID):
+     *
+     *  data =  seq_num_placeholder +
+     *          tls12_cid +
+     *          cid_length +
+     *          tls12_cid +
+     *          DTLSCiphertext.version +
+     *          epoch +
+     *          sequence_number +
+     *          cid +
+     *          length_of_DTLSInnerPlaintext +
+     *          DTLSInnerPlaintext.content +
+     *          DTLSInnerPlaintext.real_type +
+     *          DTLSInnerPlaintext.zeros
+     *
+     * AEAD ciphers use the following additional data calculation (with CIDs):
+     *
+     *     additional_data = seq_num_placeholder +
+     *                tls12_cid +
+     *                cid_length +
+     *                tls12_cid +
+     *                DTLSCiphertext.version +
+     *                epoch +
+     *                sequence_number +
+     *                cid +
+     *                length_of_DTLSInnerPlaintext
+     *
+     * Section 5.3 of draft-ietf-tls-dtls-connection-id-05 (for legacy CID use)
+     * defines the additional data calculation as follows:
+     *
+     *     additional_data = seq_num +
+     *                tls12_cid +
+     *                DTLSCipherText.version +
+     *                cid +
+     *                cid_length +
+     *                length_of_DTLSInnerPlaintext
+    */
 
     unsigned char *cur = add_data;
     size_t ad_len_field = rec->data_len;
 
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+    MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0
+    const unsigned char seq_num_placeholder[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+#endif
+
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     if( tls_version == MBEDTLS_SSL_VERSION_TLS1_3 )
     {
@@ -439,25 +550,72 @@
     {
         ((void) tls_version);
         ((void) taglen);
-        memcpy( cur, rec->ctr, sizeof( rec->ctr ) );
-        cur += sizeof( rec->ctr );
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+    MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0
+        if( rec->cid_len != 0 )
+        {
+            // seq_num_placeholder
+            memcpy( cur, seq_num_placeholder, sizeof(seq_num_placeholder) );
+            cur += sizeof( seq_num_placeholder );
+
+            // tls12_cid type
+            *cur = rec->type;
+            cur++;
+
+            // cid_length
+            *cur = rec->cid_len;
+            cur++;
+        }
+        else
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+        {
+            // epoch + sequence number
+            memcpy( cur, rec->ctr, sizeof( rec->ctr ) );
+            cur += sizeof( rec->ctr );
+        }
     }
 
+    // type
     *cur = rec->type;
     cur++;
 
+    // version
     memcpy( cur, rec->ver, sizeof( rec->ver ) );
     cur += sizeof( rec->ver );
 
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    if( rec->cid_len != 0 )
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+    MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 1
+
+    if (rec->cid_len != 0)
     {
-        memcpy( cur, rec->cid, rec->cid_len );
+        // CID
+        memcpy(cur, rec->cid, rec->cid_len);
         cur += rec->cid_len;
 
+        // cid_length
         *cur = rec->cid_len;
         cur++;
 
+        // length of inner plaintext
+        MBEDTLS_PUT_UINT16_BE(ad_len_field, cur, 0);
+        cur += 2;
+    }
+    else
+#elif defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
+    MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT == 0
+
+    if( rec->cid_len != 0 )
+    {
+        // epoch + sequence number
+        memcpy(cur, rec->ctr, sizeof(rec->ctr));
+        cur += sizeof(rec->ctr);
+
+        // CID
+        memcpy( cur, rec->cid, rec->cid_len );
+        cur += rec->cid_len;
+
+        // length of inner plaintext
         MBEDTLS_PUT_UINT16_BE( ad_len_field, cur, 0 );
         cur += 2;
     }
@@ -529,7 +687,14 @@
     mbedtls_ssl_mode_t ssl_mode;
     int auth_done = 0;
     unsigned char * data;
-    unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX ];
+    /* For an explanation of the additional data length see
+    * the description of ssl_extract_add_data_from_record().
+    */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    unsigned char add_data[23 + MBEDTLS_SSL_CID_OUT_LEN_MAX];
+#else
+    unsigned char add_data[13];
+#endif
     size_t add_data_len;
     size_t post_avail;
 
@@ -1012,13 +1177,7 @@
             size_t sign_mac_length = 0;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-            /*
-             * MAC(MAC_write_key, seq_num +
-             *     TLSCipherText.type +
-             *     TLSCipherText.version +
-             *     length_of( (IV +) ENC(...) ) +
-             *     IV +
-             *     ENC(content + padding + padding_length));
+            /* MAC(MAC_write_key, add_data, IV, ENC(content + padding + padding_length))
              */
 
             if( post_avail < transform->maclen)
@@ -1126,7 +1285,14 @@
     size_t padlen = 0, correct = 1;
 #endif
     unsigned char* data;
-    unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_IN_LEN_MAX ];
+    /* For an explanation of the additional data length see
+    * the description of ssl_extract_add_data_from_record().
+    */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    unsigned char add_data[23 + MBEDTLS_SSL_CID_IN_LEN_MAX];
+#else
+    unsigned char add_data[13];
+#endif
     size_t add_data_len;
 
 #if !defined(MBEDTLS_DEBUG_C)
@@ -3478,7 +3644,7 @@
     {
         /* Shift pointers to account for record header including CID
          * struct {
-         *   ContentType special_type = tls12_cid;
+         *   ContentType outer_type = tls12_cid;
          *   ProtocolVersion version;
          *   uint16 epoch;
          *   uint48 sequence_number;
@@ -3929,7 +4095,7 @@
     if( hs == NULL )
         return( -1 );
 
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_message" ) );
 
     if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC ||
         ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 3d3491b..9bb9dc2 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1447,9 +1447,11 @@
 
     if( ssl->handshake != NULL )
     {
+#if defined(MBEDTLS_SSL_EARLY_DATA)
         mbedtls_ssl_transform_free( ssl->handshake->transform_earlydata );
         mbedtls_free( ssl->handshake->transform_earlydata );
         ssl->handshake->transform_earlydata = NULL;
+#endif
 
         mbedtls_ssl_transform_free( ssl->handshake->transform_handshake );
         mbedtls_free( ssl->handshake->transform_handshake );
@@ -1702,6 +1704,15 @@
 {
     conf->early_data_enabled = early_data_enabled;
 }
+
+#if defined(MBEDTLS_SSL_SRV_C)
+void mbedtls_ssl_tls13_conf_max_early_data_size(
+         mbedtls_ssl_config *conf, uint32_t max_early_data_size )
+{
+    conf->max_early_data_size = max_early_data_size;
+}
+#endif /* MBEDTLS_SSL_SRV_C */
+
 #endif /* MBEDTLS_SSL_EARLY_DATA */
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
@@ -4067,9 +4078,11 @@
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     mbedtls_ssl_transform_free( handshake->transform_handshake );
+    mbedtls_free( handshake->transform_handshake );
+#if defined(MBEDTLS_SSL_EARLY_DATA)
     mbedtls_ssl_transform_free( handshake->transform_earlydata );
     mbedtls_free( handshake->transform_earlydata );
-    mbedtls_free( handshake->transform_handshake );
+#endif
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
 
@@ -4237,7 +4250,7 @@
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending outgoing data" ) );
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
     }
-    /* Protocol must be DLTS, not TLS */
+    /* Protocol must be DTLS, not TLS */
     if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only DTLS is supported" ) );
@@ -5113,6 +5126,15 @@
 #endif
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    mbedtls_ssl_tls13_conf_early_data( conf, MBEDTLS_SSL_EARLY_DATA_DISABLED );
+#if defined(MBEDTLS_SSL_SRV_C)
+    mbedtls_ssl_tls13_conf_max_early_data_size(
+        conf, MBEDTLS_SSL_MAX_EARLY_DATA_SIZE );
+#endif
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)
     mbedtls_ssl_conf_new_session_tickets(
         conf, MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS );
diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c
index 79c884b..7a17452 100644
--- a/library/ssl_tls12_client.c
+++ b/library/ssl_tls12_client.c
@@ -226,9 +226,6 @@
     size_t ext_len;
 
     /*
-     * Quoting draft-ietf-tls-dtls-connection-id-05
-     * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
-     *
      *   struct {
      *      opaque cid<0..2^8-1>;
      *   } ConnectionId;
@@ -1974,8 +1971,8 @@
     }
 
     /*
-     * Note: we currently ignore the PKS identity hint, as we only allow one
-     * PSK to be provisionned on the client. This could be changed later if
+     * Note: we currently ignore the PSK identity hint, as we only allow one
+     * PSK to be provisioned on the client. This could be changed later if
      * someone needs that feature.
      */
     *p += len;
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index 8aa89c6..eeb579a 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -376,9 +376,6 @@
     }
 
     /*
-     * Quoting draft-ietf-tls-dtls-connection-id-05
-     * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
-     *
      *   struct {
      *      opaque cid<0..2^8-1>;
      *   } ConnectionId;
@@ -1775,9 +1772,6 @@
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding CID extension" ) );
 
     /*
-     * Quoting draft-ietf-tls-dtls-connection-id-05
-     * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05
-     *
      *   struct {
      *      opaque cid<0..2^8-1>;
      *   } ConnectionId;
diff --git a/library/ssl_tls13_keys.c b/library/ssl_tls13_keys.c
index ec84a99..cef6144 100644
--- a/library/ssl_tls13_keys.c
+++ b/library/ssl_tls13_keys.c
@@ -215,6 +215,33 @@
     return( psa_ssl_status_to_mbedtls ( status ) );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_make_traffic_key(
+                    psa_algorithm_t hash_alg,
+                    const unsigned char *secret, size_t secret_len,
+                    unsigned char *key, size_t key_len,
+                    unsigned char *iv, size_t iv_len )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    ret = mbedtls_ssl_tls13_hkdf_expand_label(
+                    hash_alg,
+                    secret, secret_len,
+                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ),
+                    NULL, 0,
+                    key, key_len );
+    if( ret != 0 )
+        return( ret );
+
+    ret = mbedtls_ssl_tls13_hkdf_expand_label(
+                    hash_alg,
+                    secret, secret_len,
+                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ),
+                    NULL, 0,
+                    iv, iv_len );
+    return( ret );
+}
+
 /*
  * The traffic keying material is generated from the following inputs:
  *
@@ -240,35 +267,17 @@
 {
     int ret = 0;
 
-    ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg,
-                    client_secret, secret_len,
-                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ),
-                    NULL, 0,
-                    keys->client_write_key, key_len );
+    ret = ssl_tls13_make_traffic_key(
+            hash_alg, client_secret, secret_len,
+            keys->client_write_key, key_len,
+            keys->client_write_iv, iv_len );
     if( ret != 0 )
         return( ret );
 
-    ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg,
-                    server_secret, secret_len,
-                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ),
-                    NULL, 0,
-                    keys->server_write_key, key_len );
-    if( ret != 0 )
-        return( ret );
-
-    ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg,
-                    client_secret, secret_len,
-                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ),
-                    NULL, 0,
-                    keys->client_write_iv, iv_len );
-    if( ret != 0 )
-        return( ret );
-
-    ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg,
-                    server_secret, secret_len,
-                    MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ),
-                    NULL, 0,
-                    keys->server_write_iv, iv_len );
+    ret = ssl_tls13_make_traffic_key(
+            hash_alg, server_secret, secret_len,
+            keys->server_write_key, key_len,
+            keys->server_write_iv, iv_len );
     if( ret != 0 )
         return( ret );
 
@@ -1052,6 +1061,194 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_get_cipher_key_info(
+                    const mbedtls_ssl_ciphersuite_t *ciphersuite_info,
+                    size_t *key_len, size_t *iv_len )
+{
+    psa_key_type_t key_type;
+    psa_algorithm_t alg;
+    size_t taglen;
+    size_t key_bits;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG )
+        taglen = 8;
+    else
+        taglen = 16;
+
+    status = mbedtls_ssl_cipher_to_psa( ciphersuite_info->cipher, taglen,
+                                        &alg, &key_type, &key_bits );
+    if( status != PSA_SUCCESS )
+        return psa_ssl_status_to_mbedtls( status );
+
+    *key_len = PSA_BITS_TO_BYTES( key_bits );
+
+    /* TLS 1.3 only have AEAD ciphers, IV length is unconditionally 12 bytes */
+    *iv_len = 12;
+
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+/*
+ * ssl_tls13_generate_early_key() generates the key necessary for protecting
+ * the early application data and handshake messages as described in section 7
+ * of RFC 8446.
+ *
+ * NOTE: Only one key is generated, the key for the traffic from the client to
+ *       the server. The TLS 1.3 specification does not define a secret and thus
+ *       a key for server early traffic.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_generate_early_key( mbedtls_ssl_context *ssl,
+                                         mbedtls_ssl_key_set *traffic_keys )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_type_t md_type;
+    psa_algorithm_t hash_alg;
+    size_t hash_len;
+    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    size_t transcript_len;
+    size_t key_len;
+    size_t iv_len;
+
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info;
+    mbedtls_ssl_tls13_early_secrets *tls13_early_secrets = &handshake->tls13_early_secrets;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_tls13_generate_early_key" ) );
+
+    ret = ssl_tls13_get_cipher_key_info( ciphersuite_info, &key_len, &iv_len );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_get_cipher_key_info", ret );
+        goto cleanup;
+    }
+
+    md_type = ciphersuite_info->mac;
+
+    hash_alg = mbedtls_hash_info_psa_from_md( ciphersuite_info->mac );
+    hash_len = PSA_HASH_LENGTH( hash_alg );
+
+    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 );
+        goto cleanup;
+    }
+
+    ret = mbedtls_ssl_tls13_derive_early_secrets(
+              hash_alg, handshake->tls13_master_secrets.early,
+              transcript, transcript_len, tls13_early_secrets );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET(
+            1, "mbedtls_ssl_tls13_derive_early_secrets", ret );
+        goto cleanup;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF(
+        4, "Client early traffic secret",
+        tls13_early_secrets->client_early_traffic_secret, hash_len );
+
+    /*
+     * Export client handshake traffic secret
+     */
+    if( ssl->f_export_keys != NULL )
+    {
+        ssl->f_export_keys(
+            ssl->p_export_keys,
+            MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET,
+            tls13_early_secrets->client_early_traffic_secret,
+            hash_len,
+            handshake->randbytes,
+            handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
+            MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */ );
+    }
+
+    ret = ssl_tls13_make_traffic_key(
+              hash_alg,
+              tls13_early_secrets->client_early_traffic_secret,
+              hash_len, traffic_keys->client_write_key, key_len,
+              traffic_keys->client_write_iv, iv_len );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_make_traffic_key", ret );
+        goto cleanup;
+    }
+    traffic_keys->key_len = key_len;
+    traffic_keys->iv_len = iv_len;
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "client early write_key",
+                           traffic_keys->client_write_key,
+                           traffic_keys->key_len);
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "client early write_iv",
+                           traffic_keys->client_write_iv,
+                           traffic_keys->iv_len);
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_tls13_generate_early_key" ) );
+
+cleanup:
+    /* Erase secret and transcript */
+    mbedtls_platform_zeroize(
+        tls13_early_secrets, sizeof( mbedtls_ssl_tls13_early_secrets ) );
+    mbedtls_platform_zeroize( transcript, sizeof( transcript ) );
+    return( ret );
+}
+
+int mbedtls_ssl_tls13_compute_early_transform( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_key_set traffic_keys;
+    mbedtls_ssl_transform *transform_earlydata = NULL;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    /* Next evolution in key schedule: Establish early_data secret and
+     * key material. */
+    ret = ssl_tls13_generate_early_key( ssl, &traffic_keys );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_generate_early_key",
+                               ret );
+        goto cleanup;
+    }
+
+    transform_earlydata = mbedtls_calloc( 1, sizeof( mbedtls_ssl_transform ) );
+    if( transform_earlydata == NULL )
+    {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto cleanup;
+    }
+
+    ret = mbedtls_ssl_tls13_populate_transform(
+                                        transform_earlydata,
+                                        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_earlydata = transform_earlydata;
+
+cleanup:
+    mbedtls_platform_zeroize( &traffic_keys, sizeof( traffic_keys ) );
+    if( ret != 0 )
+        mbedtls_free( transform_earlydata );
+
+    return( ret );
+}
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
 int mbedtls_ssl_tls13_key_schedule_stage_early( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1098,51 +1295,19 @@
     return( 0 );
 }
 
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int mbedtls_ssl_tls13_get_cipher_key_info(
-                    const mbedtls_ssl_ciphersuite_t *ciphersuite_info,
-                    size_t *key_len, size_t *iv_len )
-{
-    psa_key_type_t key_type;
-    psa_algorithm_t alg;
-    size_t taglen;
-    size_t key_bits;
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-
-    if( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG )
-        taglen = 8;
-    else
-        taglen = 16;
-
-    status = mbedtls_ssl_cipher_to_psa( ciphersuite_info->cipher, taglen,
-                                        &alg, &key_type, &key_bits );
-    if( status != PSA_SUCCESS )
-        return psa_ssl_status_to_mbedtls( status );
-
-    *key_len = PSA_BITS_TO_BYTES( key_bits );
-
-    /* TLS 1.3 only have AEAD ciphers, IV length is unconditionally 12 bytes */
-    *iv_len = 12;
-
-    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;
-
     psa_algorithm_t hash_alg;
     size_t hash_len;
-
     unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
     size_t transcript_len;
-
-    size_t key_len, iv_len;
+    size_t key_len;
+    size_t iv_len;
 
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info;
@@ -1150,11 +1315,10 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_tls13_generate_handshake_keys" ) );
 
-    ret = mbedtls_ssl_tls13_get_cipher_key_info( ciphersuite_info,
-                                                 &key_len, &iv_len );
+    ret = ssl_tls13_get_cipher_key_info( ciphersuite_info, &key_len, &iv_len );
     if( ret != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_get_cipher_key_info", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_get_cipher_key_info", ret );
         return ret;
     }
 
@@ -1370,11 +1534,11 @@
 
     /* Extract basic information about hash and ciphersuite */
 
-    ret = mbedtls_ssl_tls13_get_cipher_key_info( handshake->ciphersuite_info,
-                                                 &key_len, &iv_len );
+    ret = ssl_tls13_get_cipher_key_info( handshake->ciphersuite_info,
+                                         &key_len, &iv_len );
     if( ret != 0 )
     {
-        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_get_cipher_key_info", ret );
+        MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_get_cipher_key_info", ret );
         goto cleanup;
     }
 
diff --git a/library/ssl_tls13_keys.h b/library/ssl_tls13_keys.h
index 966b5c5..fc64737 100644
--- a/library/ssl_tls13_keys.h
+++ b/library/ssl_tls13_keys.h
@@ -667,6 +667,27 @@
                                              size_t *actual_len,
                                              int which );
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+/**
+ * \brief Compute TLS 1.3 early transform
+ *
+ * \param ssl  The SSL context to operate on.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ *
+ * \warning    The function does not compute the early master secret. Call
+ *             mbedtls_ssl_tls13_key_schedule_stage_early() before to
+ *             call this function to generate the early master secret.
+ * \note       For a client/server endpoint, the function computes only the
+ *             encryption/decryption part of the transform as the decryption/
+ *             encryption part is not defined by the specification (no early
+ *             traffic from the server to the client).
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_compute_early_transform( mbedtls_ssl_context *ssl );
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
 /**
  * \brief Compute TLS 1.3 handshake transform
  *
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index ce8767c..6caae89 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -634,7 +634,7 @@
 
     if( p_identity_len != identities_end || p_binder_len != binders_end )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 3, ( "pre_shared_key extesion decode error" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "pre_shared_key extension decode error" ) );
         MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
                                       MBEDTLS_ERR_SSL_DECODE_ERROR );
         return( MBEDTLS_ERR_SSL_DECODE_ERROR );
diff --git a/library/x509.c b/library/x509.c
index 362e036..be87973 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -233,7 +233,7 @@
  *
  * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
  * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
- * option. Enfore this at parsing time.
+ * option. Enforce this at parsing time.
  */
 int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params,
                                 mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
diff --git a/library/x509_crl.c b/library/x509_crl.c
index d830fcd..dc2d2e3 100644
--- a/library/x509_crl.c
+++ b/library/x509_crl.c
@@ -1,5 +1,5 @@
 /*
- *  X.509 Certidicate Revocation List (CRL) parsing
+ *  X.509 Certificate Revocation List (CRL) parsing
  *
  *  Copyright The Mbed TLS Contributors
  *  SPDX-License-Identifier: Apache-2.0
diff --git a/programs/pkey/dh_genprime.c b/programs/pkey/dh_genprime.c
index 331838b..3e81d13 100644
--- a/programs/pkey/dh_genprime.c
+++ b/programs/pkey/dh_genprime.c
@@ -42,7 +42,7 @@
 
 #define USAGE \
     "\n usage: dh_genprime param=<>...\n"                                   \
-    "\n acceprable parameters:\n"                                           \
+    "\n acceptable parameters:\n"                                           \
     "    bits=%%d           default: 2048\n"
 
 #define DFL_BITS    2048
diff --git a/programs/psa/aead_demo.c b/programs/psa/aead_demo.c
index c4ed0dd..1efd132 100644
--- a/programs/psa/aead_demo.c
+++ b/programs/psa/aead_demo.c
@@ -104,7 +104,7 @@
 
 /* Run a PSA function and bail out if it fails.
  * The symbolic name of the error code can be recovered using:
- * programs/psa/psa_consant_name status <value> */
+ * programs/psa/psa_constant_name status <value> */
 #define PSA_CHECK( expr )                                       \
     do                                                          \
     {                                                           \
diff --git a/programs/psa/hmac_demo.c b/programs/psa/hmac_demo.c
index 6238892..f949a89 100644
--- a/programs/psa/hmac_demo.c
+++ b/programs/psa/hmac_demo.c
@@ -81,7 +81,7 @@
 
 /* Run a PSA function and bail out if it fails.
  * The symbolic name of the error code can be recovered using:
- * programs/psa/psa_consant_name status <value> */
+ * programs/psa/psa_constant_name status <value> */
 #define PSA_CHECK( expr )                                       \
     do                                                          \
     {                                                           \
diff --git a/programs/psa/key_ladder_demo.c b/programs/psa/key_ladder_demo.c
index 1303719..f40874e 100644
--- a/programs/psa/key_ladder_demo.c
+++ b/programs/psa/key_ladder_demo.c
@@ -713,4 +713,6 @@
     usage( );
     return( EXIT_FAILURE );
 }
-#endif /* MBEDTLS_SHA256_C && MBEDTLS_MD_C && MBEDTLS_AES_C && MBEDTLS_CCM_C && MBEDTLS_PSA_CRYPTO_C && MBEDTLS_FS_IO */
+#endif /* MBEDTLS_SHA256_C && MBEDTLS_MD_C &&
+          MBEDTLS_AES_C && MBEDTLS_CCM_C &&
+          MBEDTLS_PSA_CRYPTO_C && MBEDTLS_FS_IO */
diff --git a/programs/ssl/dtls_client.c b/programs/ssl/dtls_client.c
index 23a34e0..d13ea28 100644
--- a/programs/ssl/dtls_client.c
+++ b/programs/ssl/dtls_client.c
@@ -343,5 +343,5 @@
     mbedtls_exit( ret );
 }
 #endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_NET_C &&
-          MBEDTLD_TIMING_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
+          MBEDTLS_TIMING_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
           MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_RSA_C && MBEDTLS_PEM_PARSE_C */
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 1b4a94a..00624b5 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -129,6 +129,7 @@
 #define DFL_SNI                 NULL
 #define DFL_ALPN_STRING         NULL
 #define DFL_CURVES              NULL
+#define DFL_MAX_EARLY_DATA_SIZE 0
 #define DFL_SIG_ALGS            NULL
 #define DFL_DHM_FILE            NULL
 #define DFL_TRANSPORT           MBEDTLS_SSL_TRANSPORT_STREAM
@@ -424,6 +425,15 @@
 #define USAGE_ECJPAKE ""
 #endif
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+#define USAGE_EARLY_DATA \
+    "    max_early_data_size=%%d default: -1 (disabled)\n"             \
+    "                            options: -1 (disabled), "           \
+    "                                     >= 0 (enabled, max amount of early data )\n"
+#else
+#define USAGE_EARLY_DATA ""
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
 #if defined(MBEDTLS_ECP_C)
 #define USAGE_CURVES \
     "    curves=a,b,c,d      default: \"default\" (library default)\n"  \
@@ -677,6 +687,7 @@
     const char *cid_val_renego; /* the CID to use for incoming messages
                                  * after renegotiation                      */
     int reproducible;           /* make communication reproducible          */
+    uint32_t max_early_data_size; /* max amount of early data               */
     int query_config_mode;      /* whether to read config                   */
     int use_srtp;               /* Support SRTP                             */
     int force_srtp_profile;     /* SRTP protection profile to use or all    */
@@ -1535,6 +1546,9 @@
      };
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    int tls13_early_data_enabled = MBEDTLS_SSL_EARLY_DATA_DISABLED;
+#endif
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
 #if defined(MBEDTLS_MEMORY_DEBUG)
@@ -1691,6 +1705,7 @@
     opt.sni                 = DFL_SNI;
     opt.alpn_string         = DFL_ALPN_STRING;
     opt.curves              = DFL_CURVES;
+    opt.max_early_data_size = DFL_MAX_EARLY_DATA_SIZE;
     opt.sig_algs            = DFL_SIG_ALGS;
     opt.dhm_file            = DFL_DHM_FILE;
     opt.transport           = DFL_TRANSPORT;
@@ -1881,6 +1896,19 @@
         else if( strcmp( p, "sig_algs" ) == 0 )
             opt.sig_algs = q;
 #endif
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+        else if( strcmp( p, "max_early_data_size" ) == 0 )
+        {
+            long long value = atoll( q );
+            tls13_early_data_enabled =
+                value >= 0 ? MBEDTLS_SSL_EARLY_DATA_ENABLED :
+                             MBEDTLS_SSL_EARLY_DATA_DISABLED;
+            if( tls13_early_data_enabled )
+            {
+                opt.max_early_data_size = atoi( q );
+            }
+        }
+#endif /* MBEDTLS_SSL_EARLY_DATA */
         else if( strcmp( p, "renegotiation" ) == 0 )
         {
             opt.renegotiation = (atoi( q )) ?
@@ -1949,7 +1977,7 @@
              * is not recommended in practice.
              * `psk_or_ephemeral` exists in theory, we need this mode to test if
              * this setting work correctly. With this key exchange setting, server
-             * should always perform `ephemeral` handshake. `psk` or `psk_ephermal`
+             * should always perform `ephemeral` handshake. `psk` or `psk_ephemeral`
              * is not expected.
              */
             else if( strcmp( q, "psk_or_ephemeral" ) == 0 )
@@ -2876,6 +2904,15 @@
     if( opt.cert_req_ca_list != DFL_CERT_REQ_CA_LIST )
         mbedtls_ssl_conf_cert_req_ca_list( &conf, opt.cert_req_ca_list );
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    mbedtls_ssl_tls13_conf_early_data( &conf, tls13_early_data_enabled );
+    if( tls13_early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED )
+    {
+        mbedtls_ssl_tls13_conf_max_early_data_size(
+            &conf, opt.max_early_data_size );
+    }
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
 #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
     /* exercise setting DN hints for server certificate request
      * (Intended for use where the client cert expected has been signed by
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index ecb093e..6313c52 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -416,7 +416,7 @@
     Sleep( alarmMs );
     mbedtls_timing_alarmed = 1;
     /* _endthread will be called implicitly on return
-     * That ensures execution of thread funcition's epilogue */
+     * That ensures execution of thread function's epilogue */
 }
 
 static void mbedtls_set_alarm( int seconds )
diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c
index e3386d1..ccd1303 100644
--- a/programs/test/udp_proxy.c
+++ b/programs/test/udp_proxy.c
@@ -377,7 +377,7 @@
 
 #if defined(MBEDTLS_TIMING_C)
 /* Return elapsed time in milliseconds since the first call */
-static unsigned ellapsed_time( void )
+static unsigned elapsed_time( void )
 {
     static int initialized = 0;
     static struct mbedtls_timing_hr_time hires;
@@ -413,9 +413,9 @@
     int ret;
 
     mbedtls_printf( "  %05u flush    %s: %u bytes, %u datagrams, last %u ms\n",
-                    ellapsed_time(), buf->description,
+                    elapsed_time(), buf->description,
                     (unsigned) buf->len, buf->num_datagrams,
-                    ellapsed_time() - buf->packet_lifetime );
+                    elapsed_time() - buf->packet_lifetime );
 
     ret = mbedtls_net_send( buf->ctx, buf->data, buf->len );
 
@@ -427,7 +427,7 @@
 
 static unsigned ctx_buffer_time_remaining( ctx_buffer *buf )
 {
-    unsigned const cur_time = ellapsed_time();
+    unsigned const cur_time = elapsed_time();
 
     if( buf->num_datagrams == 0 )
         return( (unsigned) -1 );
@@ -467,7 +467,7 @@
 
     buf->len += len;
     if( ++buf->num_datagrams == 1 )
-        buf->packet_lifetime = ellapsed_time();
+        buf->packet_lifetime = elapsed_time();
 
     return( (int) len );
 }
@@ -517,10 +517,10 @@
 #if defined(MBEDTLS_TIMING_C)
     if( why == NULL )
         mbedtls_printf( "  %05u dispatch %s %s (%u bytes)\n",
-                ellapsed_time(), p->way, p->type, p->len );
+                elapsed_time(), p->way, p->type, p->len );
     else
         mbedtls_printf( "  %05u dispatch %s %s (%u bytes): %s\n",
-                ellapsed_time(), p->way, p->type, p->len, why );
+                elapsed_time(), p->way, p->type, p->len, why );
 #else
     if( why == NULL )
         mbedtls_printf( "        dispatch %s %s (%u bytes)\n",
diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c
index 30b389a..4879583 100644
--- a/programs/x509/cert_req.c
+++ b/programs/x509/cert_req.c
@@ -355,7 +355,7 @@
     if( ( ret = write_certificate_request( &req, opt.output_file,
                                            mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
     {
-        mbedtls_printf( " failed\n  !  write_certifcate_request %d", ret );
+        mbedtls_printf( " failed\n  !  write_certificate_request %d", ret );
         goto exit;
     }
 
diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c
index f9366fe..a8910d7 100644
--- a/programs/x509/cert_write.c
+++ b/programs/x509/cert_write.c
@@ -752,7 +752,7 @@
         if( ret != 0 )
         {
             mbedtls_strerror( ret, buf, sizeof(buf) );
-            mbedtls_printf( " failed\n  !  x509write_crt_set_basic_contraints "
+            mbedtls_printf( " failed\n  !  x509write_crt_set_basic_constraints "
                             "returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
             goto exit;
         }
diff --git a/scripts/code_style.py b/scripts/code_style.py
new file mode 100755
index 0000000..68cd556
--- /dev/null
+++ b/scripts/code_style.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+"""Check or fix the code style by running Uncrustify.
+
+Note: The code style enforced by this script is not yet introduced to
+Mbed TLS. At present this script will only be used to prepare for a future
+change of code style.
+"""
+# 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.
+import argparse
+import io
+import os
+import subprocess
+import sys
+from typing import List
+
+UNCRUSTIFY_SUPPORTED_VERSION = "0.75.1"
+CONFIG_FILE = ".uncrustify.cfg"
+UNCRUSTIFY_EXE = "uncrustify"
+UNCRUSTIFY_ARGS = ["-c", CONFIG_FILE]
+STDOUT_UTF8 = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
+STDERR_UTF8 = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')
+
+def print_err(*args):
+    print("Error: ", *args, file=STDERR_UTF8)
+
+def get_src_files() -> List[str]:
+    """
+    Use git ls-files to get a list of the source files
+    """
+    git_ls_files_cmd = ["git", "ls-files",
+                        "*.[hc]",
+                        "tests/suites/*.function",
+                        "scripts/data_files/*.fmt"]
+
+    result = subprocess.run(git_ls_files_cmd, stdout=subprocess.PIPE, \
+            stderr=STDERR_UTF8, check=False)
+
+    if result.returncode != 0:
+        print_err("git ls-files returned: " + str(result.returncode))
+        return []
+    else:
+        src_files = str(result.stdout, "utf-8").split()
+        # Don't correct style for files in 3rdparty/
+        src_files = list(filter( \
+                lambda filename: not filename.startswith("3rdparty/"), \
+                src_files))
+        return src_files
+
+def get_uncrustify_version() -> str:
+    """
+    Get the version string from Uncrustify
+    """
+    result = subprocess.run([UNCRUSTIFY_EXE, "--version"], \
+            stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=False)
+    if result.returncode != 0:
+        print_err("Could not get Uncrustify version:", str(result.stderr, "utf-8"))
+        return ""
+    else:
+        return str(result.stdout, "utf-8")
+
+def check_style_is_correct(src_file_list: List[str]) -> bool:
+    """
+    Check the code style and output a diff for each file whose style is
+    incorrect.
+    """
+    style_correct = True
+    for src_file in src_file_list:
+        uncrustify_cmd = [UNCRUSTIFY_EXE] + UNCRUSTIFY_ARGS + [src_file]
+        subprocess.run(uncrustify_cmd, stdout=subprocess.PIPE, \
+                stderr=subprocess.PIPE, check=False)
+
+        # Uncrustify makes changes to the code and places the result in a new
+        # file with the extension ".uncrustify". To get the changes (if any)
+        # simply diff the 2 files.
+        diff_cmd = ["diff", "-u", src_file, src_file + ".uncrustify"]
+        result = subprocess.run(diff_cmd, stdout=subprocess.PIPE, \
+                stderr=STDERR_UTF8, check=False)
+        if len(result.stdout) > 0:
+            print(src_file + " - Incorrect code style.", file=STDOUT_UTF8)
+            print("File changed - diff:", file=STDOUT_UTF8)
+            print(str(result.stdout, "utf-8"), file=STDOUT_UTF8)
+            style_correct = False
+        else:
+            print(src_file + " - OK.", file=STDOUT_UTF8)
+
+        # Tidy up artifact
+        os.remove(src_file + ".uncrustify")
+
+    return style_correct
+
+def fix_style_single_pass(src_file_list: List[str]) -> None:
+    """
+    Run Uncrustify once over the source files.
+    """
+    code_change_args = UNCRUSTIFY_ARGS + ["--no-backup"]
+    for src_file in src_file_list:
+        uncrustify_cmd = [UNCRUSTIFY_EXE] + code_change_args + [src_file]
+        subprocess.run(uncrustify_cmd, check=False, stdout=STDOUT_UTF8, \
+                stderr=STDERR_UTF8)
+
+def fix_style(src_file_list: List[str]) -> int:
+    """
+    Fix the code style. This takes 2 passes of Uncrustify.
+    """
+    fix_style_single_pass(src_file_list)
+    fix_style_single_pass(src_file_list)
+
+    # Guard against future changes that cause the codebase to require
+    # more passes.
+    if not check_style_is_correct(src_file_list):
+        print("Code style still incorrect after second run of Uncrustify.")
+        return 1
+    else:
+        return 0
+
+def main() -> int:
+    """
+    Main with command line arguments.
+    """
+    uncrustify_version = get_uncrustify_version().strip()
+    if UNCRUSTIFY_SUPPORTED_VERSION not in uncrustify_version:
+        print("Warning: Using unsupported Uncrustify version '" \
+                + uncrustify_version + "' (Note: The only supported version" \
+                "is " + UNCRUSTIFY_SUPPORTED_VERSION + ")", file=STDOUT_UTF8)
+
+    src_files = get_src_files()
+
+    parser = argparse.ArgumentParser()
+    parser.add_argument('-f', '--fix', action='store_true', \
+            help='modify source files to fix the code style')
+
+    args = parser.parse_args()
+
+    if args.fix:
+        # Fix mode
+        return fix_style(src_files)
+    else:
+        # Check mode
+        if check_style_is_correct(src_files):
+            return 0
+        else:
+            return 1
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
index a491b07..3ad92aa 100644
--- a/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
+++ b/scripts/data_files/driver_templates/psa_crypto_driver_wrappers.c.jinja
@@ -2476,4 +2476,72 @@
     }
 }
 
+psa_status_t psa_driver_wrapper_key_agreement(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length
+ )
+ {
+    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)
+            status =
+                mbedtls_test_transparent_key_agreement( attributes,
+                        key_buffer, key_buffer_size, alg, peer_key,
+                        peer_key_length, shared_secret, shared_secret_size,
+                        shared_secret_length );
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Software Fallback */
+            status = psa_key_agreement_raw_builtin( attributes,
+                                                    key_buffer,
+                                                    key_buffer_size,
+                                                    alg,
+                                                    peer_key,
+                                                    peer_key_length,
+                                                    shared_secret,
+                                                    shared_secret_size,
+                                                    shared_secret_length );
+            return( status );
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            return( mbedtls_test_opaque_key_agreement( attributes,
+                        key_buffer, key_buffer_size, alg, peer_key,
+                        peer_key_length, shared_secret, shared_secret_size,
+                        shared_secret_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+        default:
+            (void) attributes;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) peer_key;
+            (void) peer_key_length;
+            (void) shared_secret;
+            (void) shared_secret_size;
+            (void) shared_secret_length;
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+    }
+ }
+
 #endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/scripts/mbedtls_dev/bignum_common.py b/scripts/mbedtls_dev/bignum_common.py
index 67ea78d..0339b1a 100644
--- a/scripts/mbedtls_dev/bignum_common.py
+++ b/scripts/mbedtls_dev/bignum_common.py
@@ -99,6 +99,7 @@
     limb_sizes = [32, 64] # type: List[int]
     arities = [1, 2]
     arity = 2
+    suffix = False   # for arity = 1, symbol can be prefix (default) or suffix
 
     def __init__(self, val_a: str, val_b: str = "0", bits_in_limb: int = 32) -> None:
         self.val_a = val_a
@@ -170,7 +171,8 @@
         """
         if not self.case_description:
             if self.arity == 1:
-                self.case_description = "{} {:x}".format(
+                format_string = "{1:x} {0}" if self.suffix else "{0} {1:x}"
+                self.case_description = format_string.format(
                     self.symbol, self.int_a
                 )
             elif self.arity == 2:
@@ -251,6 +253,12 @@
         # provides earlier/more robust input validation.
         self.int_n = hex_to_int(val_n)
 
+    def to_montgomery(self, val: int) -> int:
+        return (val * self.r) % self.int_n
+
+    def from_montgomery(self, val: int) -> int:
+        return (val * self.r_inv) % self.int_n
+
     @property
     def boundary(self) -> int:
         return self.int_n
diff --git a/scripts/mbedtls_dev/bignum_core.py b/scripts/mbedtls_dev/bignum_core.py
index b8e2a31..118a659 100644
--- a/scripts/mbedtls_dev/bignum_core.py
+++ b/scripts/mbedtls_dev/bignum_core.py
@@ -755,6 +755,34 @@
 
 # BEGIN MERGE SLOT 1
 
+class BignumCoreExpMod(BignumCoreTarget, bignum_common.ModOperationCommon):
+    """Test cases for bignum core exponentiation."""
+    symbol = "^"
+    test_function = "mpi_core_exp_mod"
+    test_name = "Core modular exponentiation (Mongtomery form only)"
+    input_style = "fixed"
+
+    def arguments(self) -> List[str]:
+        # Input 'a' has to be given in Montgomery form
+        mont_a = self.to_montgomery(self.int_a)
+        arg_mont_a = self.format_arg('{:x}'.format(mont_a))
+        return [bignum_common.quote_str(n) for n in [self.arg_n,
+                                                     arg_mont_a,
+                                                     self.arg_b]
+               ] + self.result()
+
+    def result(self) -> List[str]:
+        # Result has to be given in Montgomery form too
+        result = pow(self.int_a, self.int_b, self.int_n)
+        mont_result = self.to_montgomery(result)
+        return [self.format_result(mont_result)]
+
+    @property
+    def is_valid(self) -> bool:
+        # The base needs to be canonical, but the exponent can be larger than
+        # the modulus (see for example exponent blinding)
+        return bool(self.int_a < self.int_n)
+
 # END MERGE SLOT 1
 
 # BEGIN MERGE SLOT 2
diff --git a/scripts/mbedtls_dev/bignum_data.py b/scripts/mbedtls_dev/bignum_data.py
index 74d21d0..9658933 100644
--- a/scripts/mbedtls_dev/bignum_data.py
+++ b/scripts/mbedtls_dev/bignum_data.py
@@ -18,7 +18,7 @@
 import random
 
 # Functions calling these were used to produce test data and are here only for
-# reproducability, they are not used by the test generation framework/classes
+# reproducibility, they are not used by the test generation framework/classes
 try:
     from Cryptodome.Util.number import isPrime, getPrime #type: ignore #pylint: disable=import-error
 except ImportError:
@@ -90,8 +90,8 @@
                               "4708d9893a973000b54a23020fc5b043d6e4a51519d9c9cc"
                               "52d32377e78131c1")
 
-# Adding 192 bit and 1024 bit numbers because these are the shortest required
-# for ECC and RSA respectively.
+# Adding 192 bit and 1024 bit numbers because these are the shortest required
+# for ECC and RSA respectively.
 INPUTS_DEFAULT = [
         "0", "1", # corner cases
         "2", "3", # small primes
@@ -110,13 +110,21 @@
 # supported for now.
 MODULI_DEFAULT = [
         "53", # safe prime
-        "45", # non-prime
+        "45", # non-prime
         SAFE_PRIME_192_BIT_SEED_1,  # safe prime
         RANDOM_192_BIT_SEED_2_NO4,  # not a prime
         SAFE_PRIME_1024_BIT_SEED_3, # safe prime
         RANDOM_1024_BIT_SEED_4_NO5, # not a prime
         ]
 
+# Some functions, e.g. mbedtls_mpi_mod_raw_inv_prime(), only support prime moduli.
+ONLY_PRIME_MODULI = [
+        "53", # safe prime
+        "8ac72304057392b5",     # 9999999997777777333 (longer, not safe, prime)
+        SAFE_PRIME_192_BIT_SEED_1,  # safe prime
+        SAFE_PRIME_1024_BIT_SEED_3, # safe prime
+        ]
+
 def __gen_safe_prime(bits, seed):
     '''
     Generate a safe prime.
@@ -128,7 +136,7 @@
     randbytes.
     '''
     rng = random.Random()
-    # We want reproducability across python versions
+    # We want reproducibility across python versions
     rng.seed(seed, version=2)
     while True:
         prime = 2*getPrime(bits-1, rng.randbytes)+1 #pylint: disable=no-member
diff --git a/scripts/mbedtls_dev/bignum_mod.py b/scripts/mbedtls_dev/bignum_mod.py
index a604cc0..aa06fe8 100644
--- a/scripts/mbedtls_dev/bignum_mod.py
+++ b/scripts/mbedtls_dev/bignum_mod.py
@@ -14,7 +14,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from typing import Dict, List # pylint: disable=unused-import
+
 from . import test_data_generation
+from . import bignum_common # pylint: disable=unused-import
 
 class BignumModTarget(test_data_generation.BaseTarget):
     #pylint: disable=abstract-method, too-few-public-methods
@@ -31,6 +34,20 @@
 
 # BEGIN MERGE SLOT 3
 
+class BignumModSub(bignum_common.ModOperationCommon, BignumModTarget):
+    """Test cases for bignum mpi_mod_sub()."""
+    symbol = "-"
+    test_function = "mpi_mod_sub"
+    test_name = "mbedtls_mpi_mod_sub"
+    input_style = "fixed"
+    arity = 2
+
+    def result(self) -> List[str]:
+        result = (self.int_a - self.int_b) % self.int_n
+        # To make negative tests easier, append 0 for success to the
+        # generated cases
+        return [self.format_result(result), "0"]
+
 # END MERGE SLOT 3
 
 # BEGIN MERGE SLOT 4
diff --git a/scripts/mbedtls_dev/bignum_mod_raw.py b/scripts/mbedtls_dev/bignum_mod_raw.py
index 0bbad5d..0486426 100644
--- a/scripts/mbedtls_dev/bignum_mod_raw.py
+++ b/scripts/mbedtls_dev/bignum_mod_raw.py
@@ -18,6 +18,7 @@
 
 from . import test_data_generation
 from . import bignum_common
+from .bignum_data import ONLY_PRIME_MODULI
 
 class BignumModRawTarget(test_data_generation.BaseTarget):
     #pylint: disable=abstract-method, too-few-public-methods
@@ -53,6 +54,34 @@
 
 # BEGIN MERGE SLOT 3
 
+class BignumModRawInvPrime(bignum_common.ModOperationCommon,
+                           BignumModRawTarget):
+    """Test cases for bignum mpi_mod_raw_inv_prime()."""
+    moduli = ONLY_PRIME_MODULI
+    symbol = "^ -1"
+    test_function = "mpi_mod_raw_inv_prime"
+    test_name = "mbedtls_mpi_mod_raw_inv_prime (Montgomery form only)"
+    input_style = "fixed"
+    arity = 1
+    suffix = True
+
+    @property
+    def is_valid(self) -> bool:
+        return self.int_a > 0 and self.int_a < self.int_n
+
+    @property
+    def arg_a(self) -> str:
+        # Input has to be given in Montgomery form
+        mont_a = self.to_montgomery(self.int_a)
+        return self.format_arg('{:x}'.format(mont_a))
+
+    def result(self) -> List[str]:
+        result = bignum_common.invmod(self.int_a, self.int_n)
+        if result < 0:
+            result += self.int_n
+        mont_result = self.to_montgomery(result)
+        return [self.format_result(mont_result)]
+
 # END MERGE SLOT 3
 
 # BEGIN MERGE SLOT 4
@@ -92,10 +121,9 @@
     arity = 1
 
     def result(self) -> List[str]:
-        result = (self.int_a * self.r) % self.int_n
+        result = self.to_montgomery(self.int_a)
         return [self.format_result(result)]
 
-
 class BignumModRawConvertFromMont(bignum_common.ModOperationCommon,
                                   BignumModRawTarget):
     """ Test cases for mpi_mod_raw_from_mont_rep(). """
@@ -106,7 +134,7 @@
     arity = 1
 
     def result(self) -> List[str]:
-        result = (self.int_a * self.r_inv) % self.int_n
+        result = self.from_montgomery(self.int_a)
         return [self.format_result(result)]
 
 
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 0ef6fdb..71dd70b 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -71,6 +71,7 @@
             ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_common.py
             ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_core.py
             ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_mod_raw.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/bignum_mod.py
             ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_case.py
             ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/mbedtls_dev/test_data_generation.py
     )
@@ -107,6 +108,10 @@
 # the risk of a race.
 add_custom_target(test_suite_bignum_generated_data DEPENDS ${bignum_generated_data_files})
 add_custom_target(test_suite_psa_generated_data DEPENDS ${psa_generated_data_files})
+# If SKIP_TEST_SUITES is not defined with -D, get it from the environment.
+if((NOT DEFINED SKIP_TEST_SUITES) AND (DEFINED ENV{SKIP_TEST_SUITES}))
+    set(SKIP_TEST_SUITES $ENV{SKIP_TEST_SUITES})
+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"
 # but not "test_suite_foobar".
diff --git a/tests/Makefile b/tests/Makefile
index 0b31cdd..2d2d70a 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -95,6 +95,7 @@
 generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_common.py
 generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_core.py
 generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_mod_raw.py
+generated_bignum_test_data: ../scripts/mbedtls_dev/bignum_mod.py
 generated_bignum_test_data: ../scripts/mbedtls_dev/test_case.py
 generated_bignum_test_data: ../scripts/mbedtls_dev/test_data_generation.py
 generated_bignum_test_data:
diff --git a/tests/configs/tls13-only.h b/tests/configs/tls13-only.h
index 7483f1c..963086f 100644
--- a/tests/configs/tls13-only.h
+++ b/tests/configs/tls13-only.h
@@ -34,6 +34,8 @@
 #undef MBEDTLS_SSL_DTLS_ANTI_REPLAY
 #undef MBEDTLS_SSL_DTLS_HELLO_VERIFY
 #undef MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
+#undef MBEDTLS_SSL_DTLS_CONNECTION_ID
+#undef MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT
 
 /* Enable some invasive tests */
 #define MBEDTLS_TEST_HOOKS
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index 5591669..388b0ce 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -280,7 +280,7 @@
 	$(OPENSSL) req -x509 -new -subj "/C=UK/O=Mbed TLS/CN=Mbed TLS non-printable othername SAN" -set_serial 77 -config $(test_ca_config_file) -extensions nonprintable_othername_san -days 3650 -sha256 -key $< -out $@
 
 server5-unsupported_othername.crt: server5.key
-	$(OPENSSL) req -x509 -new -subj "/C=UK/O=Mbed TLS/CN=Mbed TLS unsupported othername SAN" -set_serial 77 -config $(test_ca_config_file) -extensions unsupoported_othername_san -days 3650 -sha256 -key $< -out $@
+	$(OPENSSL) req -x509 -new -subj "/C=UK/O=Mbed TLS/CN=Mbed TLS unsupported othername SAN" -set_serial 77 -config $(test_ca_config_file) -extensions unsupported_othername_san -days 3650 -sha256 -key $< -out $@
 
 server5-fan.crt: server5.key
 	$(OPENSSL) req -x509 -new -subj "/C=UK/O=Mbed TLS/CN=Mbed TLS FAN" -set_serial 77 -config $(test_ca_config_file) -extensions fan_cert -days 3650 -sha256 -key server5.key -out $@
diff --git a/tests/data_files/pkcs7_get_signers_info_set-leak-fuzz_pkcs7-4541044530479104.der b/tests/data_files/pkcs7_get_signers_info_set-leak-fuzz_pkcs7-4541044530479104.der
new file mode 100644
index 0000000..51aef0d
--- /dev/null
+++ b/tests/data_files/pkcs7_get_signers_info_set-leak-fuzz_pkcs7-4541044530479104.der
Binary files differ
diff --git a/tests/data_files/pkcs7_get_signers_info_set-missing_free-fuzz_pkcs7-6213931373035520.der b/tests/data_files/pkcs7_get_signers_info_set-missing_free-fuzz_pkcs7-6213931373035520.der
new file mode 100644
index 0000000..ce4fb3b
--- /dev/null
+++ b/tests/data_files/pkcs7_get_signers_info_set-missing_free-fuzz_pkcs7-6213931373035520.der
Binary files differ
diff --git a/tests/data_files/test-ca.opensslconf b/tests/data_files/test-ca.opensslconf
index 3bb2379..b2c2fa1 100644
--- a/tests/data_files/test-ca.opensslconf
+++ b/tests/data_files/test-ca.opensslconf
@@ -18,7 +18,7 @@
 [nonprintable_othername_san]
 subjectAltName=otherName:1.3.6.1.5.5.7.8.4;SEQ:nonprintable_hw_module_name
 
-[unsupoported_othername_san]
+[unsupported_othername_san]
 subjectAltName=otherName:1.2.3.4;UTF8:some other identifier
 
 [dns_alt_names]
diff --git a/tests/include/test/constant_flow.h b/tests/include/test/constant_flow.h
index 9626af9..f3d676e 100644
--- a/tests/include/test/constant_flow.h
+++ b/tests/include/test/constant_flow.h
@@ -46,6 +46,12 @@
  * This file contains two implementations: one based on MemorySanitizer, the
  * other on valgrind's memcheck. If none of them is enabled, dummy macros that
  * do nothing are defined for convenience.
+ *
+ * \note #TEST_CF_SECRET must be called directly from within a .function file,
+ *       not indirectly via a macro defined under tests/include or a function
+ *       under tests/src. This is because we only run Valgrind for constant
+ *       flow on test suites that have greppable annotations inside them (see
+ *       `skip_suites_without_constant_flow` in `tests/scripts/all.sh`).
  */
 
 #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
diff --git a/tests/include/test/drivers/crypto_config_test_driver_extension.h b/tests/include/test/drivers/crypto_config_test_driver_extension.h
index 0bbca4a..fbfe8da 100644
--- a/tests/include/test/drivers/crypto_config_test_driver_extension.h
+++ b/tests/include/test/drivers/crypto_config_test_driver_extension.h
@@ -54,6 +54,14 @@
 #endif
 #endif
 
+#if defined(PSA_WANT_ALG_ECDH)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_ECDH)
+#undef MBEDTLS_PSA_ACCEL_ALG_ECDH
+#else
+#define MBEDTLS_PSA_ACCEL_ALG_ECDH 1
+#endif
+#endif
+
 #if defined(PSA_WANT_ALG_MD5)
 #if defined(MBEDTLS_PSA_ACCEL_ALG_MD5)
 #undef MBEDTLS_PSA_ACCEL_ALG_MD5
@@ -202,7 +210,6 @@
 #define MBEDTLS_PSA_ACCEL_ALG_CCM 1
 #define MBEDTLS_PSA_ACCEL_ALG_CMAC 1
 #define MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING 1
-#define MBEDTLS_PSA_ACCEL_ALG_ECDH 1
 #define MBEDTLS_PSA_ACCEL_ALG_GCM 1
 #define MBEDTLS_PSA_ACCEL_ALG_HKDF 1
 #define MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT 1
@@ -215,6 +222,7 @@
 #define MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS 1
 
 #if defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA)
+#if defined(MBEDTLS_PSA_ACCEL_ALG_ECDH)
 #define MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256 1
 #define MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384 1
 #define MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512 1
@@ -229,6 +237,7 @@
 #define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384 1
 #define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521 1
 #endif
+#endif
 
 #define MBEDTLS_PSA_ACCEL_KEY_TYPE_DERIVE 1
 #define MBEDTLS_PSA_ACCEL_KEY_TYPE_HMAC 1
diff --git a/tests/include/test/drivers/key_agreement.h b/tests/include/test/drivers/key_agreement.h
new file mode 100644
index 0000000..8f28cef
--- /dev/null
+++ b/tests/include/test/drivers/key_agreement.h
@@ -0,0 +1,74 @@
+/*
+ * Test driver for key agreement functions.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#ifndef PSA_CRYPTO_TEST_DRIVERS_KEY_AGREEMENT_H
+#define PSA_CRYPTO_TEST_DRIVERS_KEY_AGREEMENT_H
+
+#include "mbedtls/build_info.h"
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include <psa/crypto_driver_common.h>
+
+typedef struct {
+    /* If non-null, on success, copy this to the output. */
+    void *forced_output;
+    size_t forced_output_length;
+    /* If not PSA_SUCCESS, return this error code instead of processing the
+     * function call. */
+    psa_status_t forced_status;
+    /* Count the amount of times one of the signature driver functions is called. */
+    unsigned long hits;
+} mbedtls_test_driver_key_agreement_hooks_t;
+
+#define MBEDTLS_TEST_DRIVER_KEY_AGREEMENT_INIT { NULL, 0, PSA_SUCCESS, 0 }
+static inline mbedtls_test_driver_key_agreement_hooks_t
+    mbedtls_test_driver_key_agreement_hooks_init( void )
+{
+    const mbedtls_test_driver_key_agreement_hooks_t
+        v = MBEDTLS_TEST_DRIVER_KEY_AGREEMENT_INIT;
+    return( v );
+}
+
+extern mbedtls_test_driver_key_agreement_hooks_t
+    mbedtls_test_driver_key_agreement_hooks;
+
+psa_status_t mbedtls_test_transparent_key_agreement(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length );
+
+psa_status_t mbedtls_test_opaque_key_agreement(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length );
+
+#endif /*PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_TEST_DRIVERS_KEY_AGREEMENT_H */
diff --git a/tests/include/test/drivers/test_driver.h b/tests/include/test/drivers/test_driver.h
index b3c29e4..0a65b40 100644
--- a/tests/include/test/drivers/test_driver.h
+++ b/tests/include/test/drivers/test_driver.h
@@ -37,6 +37,7 @@
 #include "test/drivers/key_management.h"
 #include "test/drivers/signature.h"
 #include "test/drivers/asymmetric_encryption.h"
+#include "test/drivers/key_agreement.h"
 
 #endif /* PSA_CRYPTO_DRIVER_TEST */
 #endif /* PSA_CRYPTO_TEST_DRIVER_H */
diff --git a/tests/include/test/psa_crypto_helpers.h b/tests/include/test/psa_crypto_helpers.h
index bc2b016..3542950 100644
--- a/tests/include/test/psa_crypto_helpers.h
+++ b/tests/include/test/psa_crypto_helpers.h
@@ -189,7 +189,7 @@
  *
  * Do a key policy permission extension on key usage policies always involves
  * permissions of other usage policies
- * (like PSA_KEY_USAGE_SIGN_HASH involves PSA_KEY_USAGE_SIGN_MESSGAE).
+ * (like PSA_KEY_USAGE_SIGN_HASH involves PSA_KEY_USAGE_SIGN_MESSAGE).
  */
 psa_key_usage_t mbedtls_test_update_key_usage_flags( psa_key_usage_t usage_flags );
 
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index b43f999..db46b03 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -185,7 +185,8 @@
     export CTEST_OUTPUT_ON_FAILURE=1
 
     # CFLAGS and LDFLAGS for Asan builds that don't use CMake
-    ASAN_CFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all'
+    # default to -O2, use -Ox _after_ this if you want another level
+    ASAN_CFLAGS='-O2 -Werror -fsanitize=address,undefined -fno-sanitize-recover=all'
 
     # Gather the list of available components. These are the functions
     # defined in this script whose name starts with "component_".
@@ -1246,6 +1247,7 @@
     scripts/config.py unset MBEDTLS_PSA_CRYPTO_STORAGE_C
     scripts/config.py unset MBEDTLS_SSL_DTLS_ANTI_REPLAY
     scripts/config.py unset MBEDTLS_SSL_DTLS_CONNECTION_ID
+    scripts/config.py unset MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT
     scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
     scripts/config.py unset MBEDTLS_SSL_SRV_C
     scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
@@ -1590,6 +1592,17 @@
     env OPENSSL_CMD="$OPENSSL_NEXT" tests/compat.sh -e '^$' -f 'ARIA\|CHACHA'
 }
 
+skip_suites_without_constant_flow () {
+    # Skip the test suites that don't have any constant-flow annotations.
+    # This will need to be adjusted if we ever start declaring things as
+    # secret from macros or functions inside tests/include or tests/src.
+    SKIP_TEST_SUITES=$(
+        git -C tests/suites grep -L TEST_CF_ 'test_suite_*.function' |
+            sed 's/test_suite_//; s/\.function$//' |
+            tr '\n' ,)
+    export SKIP_TEST_SUITES
+}
+
 component_test_memsan_constant_flow () {
     # This tests both (1) accesses to undefined memory, and (2) branches or
     # memory access depending on secret values. To distinguish between those:
@@ -1641,12 +1654,13 @@
     scripts/config.py full
     scripts/config.py set MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND
     scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    skip_suites_without_constant_flow
     cmake -D CMAKE_BUILD_TYPE:String=Release .
     make
 
     # this only shows a summary of the results (how many of each type)
     # details are left in Testing/<date>/DynamicAnalysis.xml
-    msg "test: main suites (full minus MBEDTLS_USE_PSA_CRYPTO, valgrind + constant flow)"
+    msg "test: some suites (full minus MBEDTLS_USE_PSA_CRYPTO, valgrind + constant flow)"
     make memcheck
 }
 
@@ -1663,12 +1677,13 @@
     msg "build: cmake release GCC, full config with constant flow testing"
     scripts/config.py full
     scripts/config.py set MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND
+    skip_suites_without_constant_flow
     cmake -D CMAKE_BUILD_TYPE:String=Release .
     make
 
     # this only shows a summary of the results (how many of each type)
     # details are left in Testing/<date>/DynamicAnalysis.xml
-    msg "test: main suites (valgrind + constant flow)"
+    msg "test: some suites (valgrind + constant flow)"
     make memcheck
 }
 
@@ -1978,6 +1993,38 @@
     make test
 }
 
+component_test_psa_crypto_config_accel_ecdh () {
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated ECDH"
+
+    # Disable ALG_STREAM_CIPHER and ALG_ECB_NO_PADDING to avoid having
+    # partial support for cipher operations in the driver test library.
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_STREAM_CIPHER
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_ECB_NO_PADDING
+
+    loc_accel_list="ALG_ECDH KEY_TYPE_ECC_KEY_PAIR KEY_TYPE_ECC_PUBLIC_KEY"
+    loc_accel_flags=$( echo "$loc_accel_list" | sed 's/[^ ]* */-DLIBTESTDRIVER1_MBEDTLS_PSA_ACCEL_&/g' )
+    make -C tests libtestdriver1.a CFLAGS=" $ASAN_CFLAGS $loc_accel_flags" LDFLAGS="$ASAN_CFLAGS"
+
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_DRIVERS
+    scripts/config.py set MBEDTLS_PSA_CRYPTO_CONFIG
+    scripts/config.py unset MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py unset MBEDTLS_SSL_PROTO_TLS1_3
+    scripts/config.py unset MBEDTLS_ECDH_C
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+    scripts/config.py unset MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+
+    loc_accel_flags="$loc_accel_flags $( echo "$loc_accel_list" | sed 's/[^ ]* */-DMBEDTLS_PSA_ACCEL_&/g' )"
+    make CFLAGS="$ASAN_CFLAGS -O -Werror -I../tests/include -I../tests -I../../tests -DPSA_CRYPTO_DRIVER_TEST -DMBEDTLS_TEST_LIBTESTDRIVER1 $loc_accel_flags" LDFLAGS="-ltestdriver1 $ASAN_CFLAGS"
+
+    not grep mbedtls_ecdh_ library/ecdh.o
+
+    msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated ECDH"
+    make test
+}
+
 component_test_psa_crypto_config_accel_rsa_signature () {
     msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated RSA signature"
 
@@ -2162,11 +2209,16 @@
     msg "test: MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash and USE_PSA"
     make test
 
+    # This is mostly useful so that we can later compare outcome files with
+    # the reference config in analyze_outcomes.py, to check that the
+    # dependency declarations in ssl-opt.sh and in TLS code are correct.
     msg "test: ssl-opt.sh, MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash and USE_PSA"
     tests/ssl-opt.sh
 
-    msg "test: compat.sh, MBEDTLS_PSA_CRYPTO_CONFIG without accelerated hash and USE_PSA"
-    tests/compat.sh
+    # This is to make sure all ciphersuites are exercised, but we don't need
+    # interop testing (besides, we already got some from ssl-opt.sh).
+    msg "test: compat.sh, MBEDTLS_PSA_CRYPTO_CONFIG with accelerated hash and USE_PSA"
+    tests/compat.sh -p mbedTLS -V YES
 }
 
 # This component provides reference configuration for test_psa_crypto_config_accel_hash_use_psa
@@ -2765,21 +2817,20 @@
     tests/compat.sh
 }
 
-component_test_variable_ssl_in_out_buffer_len_CID () {
-    msg "build: MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH and MBEDTLS_SSL_DTLS_CONNECTION_ID enabled (ASan build)"
-    scripts/config.py set MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
-    scripts/config.py set MBEDTLS_SSL_DTLS_CONNECTION_ID
+component_test_dtls_cid_legacy () {
+    msg "build: MBEDTLS_SSL_DTLS_CONNECTION_ID (legacy) enabled (ASan build)"
+    scripts/config.py set MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT 1
 
     CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
     make
 
-    msg "test: MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH and MBEDTLS_SSL_DTLS_CONNECTION_ID"
+    msg "test: MBEDTLS_SSL_DTLS_CONNECTION_ID (legacy)"
     make test
 
-    msg "test: ssl-opt.sh, MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH and MBEDTLS_SSL_DTLS_CONNECTION_ID enabled"
+    msg "test: ssl-opt.sh, MBEDTLS_SSL_DTLS_CONNECTION_ID (legacy) enabled"
     tests/ssl-opt.sh
 
-    msg "test: compat.sh, MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH and MBEDTLS_SSL_DTLS_CONNECTION_ID enabled"
+    msg "test: compat.sh, MBEDTLS_SSL_DTLS_CONNECTION_ID (legacy) enabled"
     tests/compat.sh
 }
 
@@ -3444,30 +3495,43 @@
 
 component_test_valgrind () {
     msg "build: Release (clang)"
+    # default config, in particular without MBEDTLS_USE_PSA_CRYPTO
     CC=clang cmake -D CMAKE_BUILD_TYPE:String=Release .
     make
 
-    msg "test: main suites valgrind (Release)"
+    msg "test: main suites, Valgrind (default config)"
     make memcheck
 
     # Optional parts (slow; currently broken on OS X because programs don't
     # seem to receive signals under valgrind on OS X).
+    # These optional parts don't run on the CI.
     if [ "$MEMORY" -gt 0 ]; then
-        msg "test: ssl-opt.sh --memcheck (Release)"
+        msg "test: ssl-opt.sh --memcheck (default config)"
         tests/ssl-opt.sh --memcheck
     fi
 
     if [ "$MEMORY" -gt 1 ]; then
-        msg "test: compat.sh --memcheck (Release)"
+        msg "test: compat.sh --memcheck (default config)"
         tests/compat.sh --memcheck
     fi
 
     if [ "$MEMORY" -gt 0 ]; then
-        msg "test: context-info.sh --memcheck (Release)"
+        msg "test: context-info.sh --memcheck (default config)"
         tests/context-info.sh --memcheck
     fi
 }
 
+component_test_valgrind_psa () {
+    msg "build: Release, full (clang)"
+    # full config, in particular with MBEDTLS_USE_PSA_CRYPTO
+    scripts/config.py full
+    CC=clang cmake -D CMAKE_BUILD_TYPE:String=Release .
+    make
+
+    msg "test: main suites, Valgrind (full config)"
+    make memcheck
+}
+
 support_test_cmake_out_of_source () {
     distrib_id=""
     distrib_ver=""
@@ -3604,6 +3668,26 @@
     [ "$ver_major" -eq 3 ] && [ "$ver_minor" -ge 10 ]
 }
 
+component_test_corrected_code_style () {
+    ./scripts/code_style.py --fix
+
+    msg "build: make, default config (out-of-box), corrected code style"
+    make
+
+    msg "test: main suites make, default config (out-of-box), corrected code style"
+    make test
+
+    # Clean up code-style corrections
+    git checkout -- .
+}
+
+support_test_corrected_code_style() {
+    case $(uncrustify --version) in
+        *0.75.1*) true;;
+        *) false;;
+    esac
+}
+
 component_check_python_files () {
     msg "Lint: Python scripts"
     tests/scripts/check-python-files.sh
diff --git a/tests/scripts/basic-build-test.sh b/tests/scripts/basic-build-test.sh
index 31beb1c..a96254f 100755
--- a/tests/scripts/basic-build-test.sh
+++ b/tests/scripts/basic-build-test.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-# basic-build-tests.sh
+# basic-build-test.sh
 #
 # Copyright The Mbed TLS Contributors
 # SPDX-License-Identifier: Apache-2.0
@@ -36,7 +36,7 @@
 #
 # This script has been written to be generic and should work on any shell.
 #
-# Usage: basic-build-tests.sh
+# Usage: basic-build-test.sh
 #
 
 # Abort on errors (and uninitiliased variables)
diff --git a/tests/scripts/check_names.py b/tests/scripts/check_names.py
index 396ab74..920537e 100755
--- a/tests/scripts/check_names.py
+++ b/tests/scripts/check_names.py
@@ -629,7 +629,7 @@
         self.log.info("Compiling...")
         symbols = []
 
-        # Back up the config and atomically compile with the full configratuion.
+        # Back up the config and atomically compile with the full configuration.
         shutil.copy(
             "include/mbedtls/mbedtls_config.h",
             "include/mbedtls/mbedtls_config.h.bak"
@@ -892,7 +892,7 @@
     parser.add_argument(
         "-q", "--quiet",
         action="store_true",
-        help="hide unnecessary text, explanations, and highlighs"
+        help="hide unnecessary text, explanations, and highlights"
     )
 
     args = parser.parse_args()
diff --git a/tests/scripts/generate_bignum_tests.py b/tests/scripts/generate_bignum_tests.py
index c3058e9..0b84711 100755
--- a/tests/scripts/generate_bignum_tests.py
+++ b/tests/scripts/generate_bignum_tests.py
@@ -66,7 +66,7 @@
 # Import modules containing additional test classes
 # Test function classes in these modules will be registered by
 # the framework
-from mbedtls_dev import bignum_core, bignum_mod_raw # pylint: disable=unused-import
+from mbedtls_dev import bignum_core, bignum_mod_raw, bignum_mod # pylint: disable=unused-import
 
 class BignumTarget(test_data_generation.BaseTarget):
     #pylint: disable=too-few-public-methods
diff --git a/tests/scripts/generate_psa_tests.py b/tests/scripts/generate_psa_tests.py
index 2f09007..b271048 100755
--- a/tests/scripts/generate_psa_tests.py
+++ b/tests/scripts/generate_psa_tests.py
@@ -80,7 +80,7 @@
 # A temporary hack: at the time of writing, not all dependency symbols
 # are implemented yet. Skip test cases for which the dependency symbols are
 # not available. Once all dependency symbols are available, this hack must
-# be removed so that a bug in the dependency symbols proprely leads to a test
+# be removed so that a bug in the dependency symbols properly leads to a test
 # failure.
 def read_implemented_dependencies(filename: str) -> FrozenSet[str]:
     return frozenset(symbol
@@ -459,7 +459,7 @@
         """Prepare to generate a key.
 
         * `usage`                 : The usage flags used for the key.
-        * `without_implicit_usage`: Flag to defide to apply the usage extension
+        * `without_implicit_usage`: Flag to define to apply the usage extension
         """
         usage_flags = set(usage)
         if not without_implicit_usage:
@@ -483,7 +483,7 @@
     ) -> None:
         """Prepare to generate test data
 
-        * `description`   : used for the the test case names
+        * `description`   : used for the test case names
         * `expected_usage`: the usage flags generated as the expected usage flags
                             in the test cases. CAn differ from the usage flags
                             stored in the keys because of the usage flags extension.
diff --git a/tests/scripts/test_psa_compliance.py b/tests/scripts/test_psa_compliance.py
index 7d06db1..92db417 100755
--- a/tests/scripts/test_psa_compliance.py
+++ b/tests/scripts/test_psa_compliance.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 """Run the PSA Crypto API compliance test suite.
 Clone the repo and check out the commit specified by PSA_ARCH_TEST_REPO and PSA_ARCH_TEST_REF,
-then complie and run the test suite. The clone is stored at <Mbed TLS root>/psa-arch-tests.
+then compile and run the test suite. The clone is stored at <Mbed TLS root>/psa-arch-tests.
 Known defects in either the test suite or mbedtls - identified by their test number - are ignored,
 while unexpected failures AND successes are reported as errors,
 to help keep the list of known defects as up to date as possible.
diff --git a/tests/src/drivers/test_driver_key_agreement.c b/tests/src/drivers/test_driver_key_agreement.c
new file mode 100644
index 0000000..7c37b03
--- /dev/null
+++ b/tests/src/drivers/test_driver_key_agreement.c
@@ -0,0 +1,128 @@
+/*
+ * Test driver for key agreement functions.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+#include <test/helpers.h>
+
+#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) && defined(PSA_CRYPTO_DRIVER_TEST)
+
+#include "psa/crypto.h"
+#include "psa_crypto_core.h"
+#include "psa_crypto_ecp.h"
+
+#include "test/drivers/key_agreement.h"
+#include "test/drivers/test_driver.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_TEST_LIBTESTDRIVER1)
+#include "libtestdriver1/include/psa/crypto.h"
+#include "libtestdriver1/library/psa_crypto_ecp.h"
+#endif
+
+mbedtls_test_driver_key_agreement_hooks_t
+    mbedtls_test_driver_key_agreement_hooks = MBEDTLS_TEST_DRIVER_KEY_AGREEMENT_INIT;
+
+psa_status_t mbedtls_test_transparent_key_agreement(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length )
+{
+    mbedtls_test_driver_key_agreement_hooks.hits++;
+
+    if( mbedtls_test_driver_key_agreement_hooks.forced_status != PSA_SUCCESS )
+        return( mbedtls_test_driver_key_agreement_hooks.forced_status );
+
+    if( mbedtls_test_driver_key_agreement_hooks.forced_output != NULL )
+    {
+        if( mbedtls_test_driver_key_agreement_hooks.forced_output_length > shared_secret_size )
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
+
+        memcpy( shared_secret, mbedtls_test_driver_key_agreement_hooks.forced_output,
+                mbedtls_test_driver_key_agreement_hooks.forced_output_length );
+        *shared_secret_length = mbedtls_test_driver_key_agreement_hooks.forced_output_length;
+
+        return( PSA_SUCCESS );
+    }
+
+    if( PSA_ALG_IS_ECDH(alg) )
+    {
+#if (defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \
+    defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_ALG_ECDH))
+        return( libtestdriver1_mbedtls_psa_key_agreement_ecdh(
+                    (const libtestdriver1_psa_key_attributes_t *) attributes,
+                    key_buffer, key_buffer_size,
+                    alg, peer_key, peer_key_length,
+                    shared_secret, shared_secret_size,
+                    shared_secret_length ) );
+#elif defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
+        return( mbedtls_psa_key_agreement_ecdh(
+                attributes,
+                key_buffer, key_buffer_size,
+                alg, peer_key, peer_key_length,
+                shared_secret, shared_secret_size,
+                shared_secret_length ) );
+#else
+        (void) attributes;
+        (void) key_buffer;
+        (void) key_buffer_size;
+        (void) peer_key;
+        (void) peer_key_length;
+        (void) shared_secret;
+        (void) shared_secret_size;
+        (void) shared_secret_length;
+        return( PSA_ERROR_NOT_SUPPORTED );
+#endif
+    }
+    else
+    {
+        return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+
+}
+
+psa_status_t mbedtls_test_opaque_key_agreement(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length )
+{
+    (void) attributes;
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) alg;
+    (void) peer_key;
+    (void) peer_key_length;
+    (void) shared_secret;
+    (void) shared_secret_size;
+    (void) shared_secret_length;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS && PSA_CRYPTO_DRIVER_TEST */
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index c6f6e29..1fe8bae 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -2614,7 +2614,6 @@
             -c "Deserializing connection..." \
             -S "Deserializing connection..."
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION
 run_test    "Context serialization, server serializes, CCM" \
             "$P_SRV dtls=1 serialize=1 exchanges=2" \
@@ -2688,7 +2687,6 @@
             -c "Deserializing connection..." \
             -s "Deserializing connection..."
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION
 run_test    "Context serialization, re-init, client serializes, CCM" \
             "$P_SRV dtls=1 serialize=0 exchanges=2" \
@@ -2725,7 +2723,6 @@
             -c "Deserializing connection..." \
             -S "Deserializing connection..."
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 requires_config_enabled MBEDTLS_SSL_CONTEXT_SERIALIZATION
 run_test    "Context serialization, re-init, server serializes, CCM" \
             "$P_SRV dtls=1 serialize=2 exchanges=2" \
diff --git a/tests/suites/test_suite_bignum_core.function b/tests/suites/test_suite_bignum_core.function
index d5bb420..7bf03fb 100644
--- a/tests/suites/test_suite_bignum_core.function
+++ b/tests/suites/test_suite_bignum_core.function
@@ -935,7 +935,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
 void mpi_core_ct_uint_table_lookup( int bitlen, int window_size )
 {
     size_t limbs = BITS_TO_LIMBS( bitlen );
@@ -1041,6 +1041,81 @@
 
 /* BEGIN MERGE SLOT 1 */
 
+/* BEGIN_CASE */
+void mpi_core_exp_mod( char * input_N, char * input_A,
+                       char * input_E, char * input_X )
+{
+    mbedtls_mpi_uint *A = NULL;
+    mbedtls_mpi_uint *E = NULL;
+    mbedtls_mpi_uint *N = NULL;
+    mbedtls_mpi_uint *X = NULL;
+    size_t A_limbs, E_limbs, N_limbs, X_limbs;
+    const mbedtls_mpi_uint *R2 = NULL;
+    mbedtls_mpi_uint *Y = NULL;
+    mbedtls_mpi_uint *T = NULL;
+    /* Legacy MPIs for computing R2 */
+    mbedtls_mpi N_mpi;
+    mbedtls_mpi_init( &N_mpi );
+    mbedtls_mpi R2_mpi;
+    mbedtls_mpi_init( &R2_mpi );
+
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &E, &E_limbs, input_E ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &N_limbs, input_N ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &X_limbs, input_X ) );
+    ASSERT_ALLOC( Y, N_limbs );
+
+    TEST_EQUAL( A_limbs, N_limbs );
+    TEST_EQUAL( X_limbs, N_limbs );
+
+    TEST_EQUAL( 0, mbedtls_mpi_grow( &N_mpi, N_limbs ) );
+    memcpy( N_mpi.p, N, N_limbs * sizeof( *N ) );
+    N_mpi.n = N_limbs;
+    TEST_EQUAL( 0,
+                mbedtls_mpi_core_get_mont_r2_unsafe( &R2_mpi, &N_mpi ) );
+    TEST_EQUAL( 0, mbedtls_mpi_grow( &R2_mpi, N_limbs ) );
+    R2 = R2_mpi.p;
+
+    size_t working_limbs = mbedtls_mpi_core_exp_mod_working_limbs( N_limbs,
+                                                                   E_limbs );
+
+    /* No point exactly duplicating the code in mbedtls_mpi_core_exp_mod_working_limbs()
+     * to see if the output is correct, but we can check that it's in a
+     * reasonable range.  The current calculation works out as
+     * `1 + N_limbs * (welem + 3)`, where welem is the number of elements in
+     * the window (1 << 1 up to 1 << 6).
+     */
+    size_t min_expected_working_limbs = 1 + N_limbs * 4;
+    size_t max_expected_working_limbs = 1 + N_limbs * 67;
+
+    TEST_LE_U( min_expected_working_limbs, working_limbs );
+    TEST_LE_U( working_limbs, max_expected_working_limbs );
+
+    ASSERT_ALLOC( T, working_limbs );
+
+    mbedtls_mpi_core_exp_mod( Y, A, N, N_limbs, E, E_limbs, R2, T );
+
+    TEST_EQUAL( 0, memcmp( X, Y, N_limbs * sizeof( mbedtls_mpi_uint ) ) );
+
+    /* Check when output aliased to input */
+
+    mbedtls_mpi_core_exp_mod( A, A, N, N_limbs, E, E_limbs, R2, T );
+
+    TEST_EQUAL( 0, memcmp( X, A, N_limbs * sizeof( mbedtls_mpi_uint ) ) );
+
+exit:
+    mbedtls_free( T );
+    mbedtls_free( A );
+    mbedtls_free( E );
+    mbedtls_free( N );
+    mbedtls_free( X );
+    mbedtls_free( Y );
+    mbedtls_mpi_free( &N_mpi );
+    mbedtls_mpi_free( &R2_mpi );
+    // R2 doesn't need to be freed as it is only aliasing R2_mpi
+}
+/* END_CASE */
+
 /* END MERGE SLOT 1 */
 
 /* BEGIN MERGE SLOT 2 */
diff --git a/tests/suites/test_suite_bignum_mod.data b/tests/suites/test_suite_bignum_mod.data
index 95faa53..501d9d7 100644
--- a/tests/suites/test_suite_bignum_mod.data
+++ b/tests/suites/test_suite_bignum_mod.data
@@ -1,29 +1,11 @@
-Test mbedtls_mpi_mod_setup #1 (Both representations invalid)
-mpi_mod_setup:MBEDTLS_MPI_MOD_EXT_REP_INVALID:MBEDTLS_MPI_MOD_REP_INVALID:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+Test mbedtls_mpi_mod_setup #1 (Internal representation invalid)
+mpi_mod_setup:MBEDTLS_MPI_MOD_REP_INVALID:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
-Test mbedtls_mpi_mod_setup #2 (Internal representation invalid)
-mpi_mod_setup:MBEDTLS_MPI_MOD_EXT_REP_LE:MBEDTLS_MPI_MOD_REP_INVALID:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+Test mbedtls_mpi_mod_setup #6 (Optimised reduction)
+mpi_mod_setup:MBEDTLS_MPI_MOD_REP_OPT_RED:0
 
-Test mbedtls_mpi_mod_setup #3 (Internal representation invalid)
-mpi_mod_setup:MBEDTLS_MPI_MOD_EXT_REP_BE:MBEDTLS_MPI_MOD_REP_INVALID:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
-
-Test mbedtls_mpi_mod_setup #4 (External representation invalid)
-mpi_mod_setup:MBEDTLS_MPI_MOD_EXT_REP_INVALID:MBEDTLS_MPI_MOD_REP_MONTGOMERY:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
-
-Test mbedtls_mpi_mod_setup #5 (External representation invalid)
-mpi_mod_setup:MBEDTLS_MPI_MOD_EXT_REP_INVALID:MBEDTLS_MPI_MOD_REP_OPT_RED:MBEDTLS_ERR_MPI_BAD_INPUT_DATA
-
-Test mbedtls_mpi_mod_setup #6 (Both representations valid)
-mpi_mod_setup:MBEDTLS_MPI_MOD_EXT_REP_BE:MBEDTLS_MPI_MOD_REP_OPT_RED:0
-
-Test mbedtls_mpi_mod_setup #7 (Both representations valid)
-mpi_mod_setup:MBEDTLS_MPI_MOD_EXT_REP_BE:MBEDTLS_MPI_MOD_REP_MONTGOMERY:0
-
-Test mbedtls_mpi_mod_setup #8 (Both representations valid)
-mpi_mod_setup:MBEDTLS_MPI_MOD_EXT_REP_LE:MBEDTLS_MPI_MOD_REP_OPT_RED:0
-
-Test mbedtls_mpi_mod_setup #9 (Both representations valid)
-mpi_mod_setup:MBEDTLS_MPI_MOD_EXT_REP_LE:MBEDTLS_MPI_MOD_REP_MONTGOMERY:0
+Test mbedtls_mpi_mod_setup #7 (Montgomery representation)
+mpi_mod_setup:MBEDTLS_MPI_MOD_REP_MONTGOMERY:0
 
 # BEGIN MERGE SLOT 1
 
@@ -35,6 +17,27 @@
 
 # BEGIN MERGE SLOT 3
 
+mpi_mod_sub base case for negative testing (N, a, b all >= 1 limb)
+mpi_mod_sub:"014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"00033b2e3c9fd0803ce8000f93":"013fe57440828b4a0008aa4159":0
+
+mpi_mod_sub with modulus too long/both inputs too short
+mpi_mod_sub:"0000000014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"00033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_sub with first input too long
+mpi_mod_sub:"014320a022ccb75bdf470ddf25":"0000000000000025a55a46e5da99c71c7":"00033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_sub with second input too long
+mpi_mod_sub:"014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"000000000033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_sub with both inputs too long
+mpi_mod_sub:"014320a022ccb75bdf470ddf25":"0000000000000025a55a46e5da99c71c7":"000000000033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_sub with first input too short
+mpi_mod_sub:"014320a022ccb75bdf470ddf25":"a99c71c7":"00033b2e3c9fd0803ce8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+mpi_mod_sub with second input too short
+mpi_mod_sub:"014320a022ccb75bdf470ddf25":"000000025a55a46e5da99c71c7":"e8000f93":"00":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
 # END MERGE SLOT 3
 
 # BEGIN MERGE SLOT 4
@@ -50,17 +53,269 @@
 # END MERGE SLOT 6
 
 # BEGIN MERGE SLOT 7
+Test mbedtls_mpi_residue_setup #1 m > r
+mpi_residue_setup:"fe":"01":0
 
-# END MERGE SLOT 7
+Test mbedtls_mpi_residue_setup #2 r == m - 1
+mpi_residue_setup:"ff":"fe":0
 
-# BEGIN MERGE SLOT 8
+Test mbedtls_mpi_residue_setup #3 m->limbs = r-> limbs && m > r
+mpi_residue_setup:"7dfe5c6":"fe":0
 
-# END MERGE SLOT 8
+Test mbedtls_mpi_residue_setup #4 m->limbs = r-> limbs && m > r
+mpi_residue_setup:"7ffffffffffffffffffffffffffffffffffffffffffffff1":"0000000000000000000000000000000000000000000000fe":0
 
-# BEGIN MERGE SLOT 9
+Test mbedtls_mpi_residue_setup #5 m->limbs > r-> limbs && m > r
+mpi_residue_setup:"7ffffffff00000000":"fe":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
-# END MERGE SLOT 9
+Test mbedtls_mpi_residue_setup #6 m->limbs < r-> limbs && m > r
+mpi_residue_setup:"ff":"000000000000000000000000000000000000000000000001":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
 
-# BEGIN MERGE SLOT 10
+Test mbedtls_mpi_residue_setup #7 r == m
+mpi_residue_setup:"fe":"fe":-4
 
-# END MERGE SLOT 10
+Test mbedtls_mpi_residue_setup #8 r > m
+mpi_residue_setup:"fe":"ff":-4
+
+Test mbedtls_mpi_mod_io_neg #1 input_r < modulo m
+mpi_mod_io_neg:"fe":"fd":0
+
+Test mbedtls_mpi_mod_io_neg #2  input_r == modulo m
+mpi_mod_io_neg:"fe":"fe":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+Test mbedtls_mpi_mod_io_neg #3  input_r > modulo m
+mpi_mod_io_neg:"fe":"ff":MBEDTLS_ERR_MPI_BAD_INPUT_DATA
+
+Test mbedtls_mpi_mod_io_neg #4  input_r too large to fit
+mpi_mod_io_neg:"fe":"ffffffffffffffffff":MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
+
+Test mbedtls_mpi_mod_io_neg #5  Sucesfull read / output buffer too small
+mpi_mod_io_neg:"7ffffffffffffffffffffffffffffff1":"ffff":0
+
+Test mbedtls_mpi_mod_io #1 N: "11" A: "119".
+mpi_mod_io:"000000000000000b":"0000000000000000":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #2 N: "11" A: "136".
+mpi_mod_io:"000000000000000b":"0000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #3 N: "11" A: "119".
+mpi_mod_io:"000000000000000b":"0000000000000001":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #4 N: "11" A: "136".
+mpi_mod_io:"000000000000000b":"0100000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #5 N: "140737488355333" A: "119".
+mpi_mod_io:"0000800000000005":"0000000000000000":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #6 N: "140737488355333" A: "136".
+mpi_mod_io:"0000800000000005":"0000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #7 N: "140737488355333" A: "119".
+mpi_mod_io:"0000800000000005":"0000000000000001":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #8 N: "140737488355333" A: "136".
+mpi_mod_io:"0000800000000005":"0100000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #9 N: "140737488355333" A: "119".
+mpi_mod_io:"0000800000000005":"00000000000003ca":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #10 N: "140737488355333" A: "136".
+mpi_mod_io:"0000800000000005":"ca03000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #11 N: "140737488355333" A: "119".
+mpi_mod_io:"0000800000000005":"00000000539ed428":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #12 N: "140737488355333" A: "136".
+mpi_mod_io:"0000800000000005":"28d49e5300000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #13 N: "9223372036854775807" A: "119".
+mpi_mod_io:"7fffffffffffffff":"0000000000000000":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #14 N: "9223372036854775807" A: "136".
+mpi_mod_io:"7fffffffffffffff":"0000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #15 N: "9223372036854775807" A: "119".
+mpi_mod_io:"7fffffffffffffff":"0000000000000001":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #16 N: "9223372036854775807" A: "136".
+mpi_mod_io:"7fffffffffffffff":"0100000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #17 N: "9223372036854775807" A: "119".
+mpi_mod_io:"7fffffffffffffff":"00000000000003ca":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #18 N: "9223372036854775807" A: "136".
+mpi_mod_io:"7fffffffffffffff":"ca03000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #19 N: "9223372036854775807" A: "119".
+mpi_mod_io:"7fffffffffffffff":"00000000539ed428":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #20 N: "9223372036854775807" A: "136".
+mpi_mod_io:"7fffffffffffffff":"28d49e5300000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #21 N: "9223372036854775807" A: "119".
+mpi_mod_io:"7fffffffffffffff":"7dfe5c6beb35a2d6":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #22 N: "9223372036854775807" A: "136".
+mpi_mod_io:"7fffffffffffffff":"d6a235eb6b5cfe7d":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #23 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "119".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #24 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "136".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #25 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "119".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #26 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "136".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #27 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "119".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ca":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #28 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "136".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"ca030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #29 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "119".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000539ed428":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #30 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "136".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"28d49e53000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #31 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "119".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007dfe5c6beb35a2d6":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #32 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "136".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"d6a235eb6b5cfe7d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #33 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "119".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dca8de1c2adfc6d7aafb9b48e":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #34 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "136".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"8eb4b9af7a6dfcadc2e18dca0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #35 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "119".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7d17b6c4be72f3d5c16bf9c1af6fc933":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #36 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "136".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"33c96fafc1f96bc1d5f372bec4b6177d0a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #37 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "119".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002fec97beec546f9553142ed52f147845463f579":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #38 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "136".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"79f563548447f152ed423155f946c5ee7bc9fe020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #39 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "119".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"00000000000000000000000000000000000000000000000000000000000000000000000000000000378dc83b8bc5a7b62cba495af4919578dce6d4f175cadc4f":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #40 N: "6610145858169835373800827072568987987787972943497619105736762797475099959212160692262984293277166612477845864397201463825139894315919781838969391314120587" A: "136".
+mpi_mod_io:"7e35b84cb19ea5bc57ec37f5e431462fa962d98c1e63738d4657f18ad6532e6adc3eafe67f1e5fa262af94cee8d3e7268593942a2a98df75154f8c914a282f8b":"4fdcca75f1d4e6dc789591f45a49ba2cb6a7c58b3bc88d3700000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #41 N: "201076468338594879614802819276237850336264827391977454179" A: "119".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #42 N: "201076468338594879614802819276237850336264827391977454179" A: "136".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #43 N: "201076468338594879614802819276237850336264827391977454179" A: "119".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"000000000000000000000000000000000000000000000001":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #44 N: "201076468338594879614802819276237850336264827391977454179" A: "136".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"010000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #45 N: "201076468338594879614802819276237850336264827391977454179" A: "119".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"0000000000000000000000000000000000000000000003ca":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #46 N: "201076468338594879614802819276237850336264827391977454179" A: "136".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"ca0300000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #47 N: "201076468338594879614802819276237850336264827391977454179" A: "119".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"0000000000000000000000000000000000000000539ed428":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #48 N: "201076468338594879614802819276237850336264827391977454179" A: "136".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"28d49e530000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #49 N: "201076468338594879614802819276237850336264827391977454179" A: "119".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"000000000000000000000000000000007dfe5c6beb35a2d6":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #50 N: "201076468338594879614802819276237850336264827391977454179" A: "136".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"d6a235eb6b5cfe7d00000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #51 N: "201076468338594879614802819276237850336264827391977454179" A: "119".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"00000000000000000000000dca8de1c2adfc6d7aafb9b48e":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #52 N: "201076468338594879614802819276237850336264827391977454179" A: "136".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"8eb4b9af7a6dfcadc2e18dca0d0000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #53 N: "201076468338594879614802819276237850336264827391977454179" A: "119".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"000000000000000a7d17b6c4be72f3d5c16bf9c1af6fc933":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #54 N: "201076468338594879614802819276237850336264827391977454179" A: "136".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"33c96fafc1f96bc1d5f372bec4b6177d0a00000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #55 N: "201076468338594879614802819276237850336264827391977454179" A: "119".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"0000000002fec97beec546f9553142ed52f147845463f579":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #56 N: "201076468338594879614802819276237850336264827391977454179" A: "136".
+mpi_mod_io:"08335616aed761f1f7f44e6bd49e807b82e3bf2bf11bfa63":"79f563548447f152ed423155f946c5ee7bc9fe0200000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #57 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "119".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #58 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "136".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #59 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "119".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #60 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "136".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #61 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "119".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ca":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #62 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "136".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"ca030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #63 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "119".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000539ed428":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #64 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "136".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"28d49e53000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #65 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "119".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007dfe5c6beb35a2d6":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #66 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "136".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"d6a235eb6b5cfe7d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #67 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "119".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000dca8de1c2adfc6d7aafb9b48e":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #68 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "136".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"8eb4b9af7a6dfcadc2e18dca0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #69 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "119".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a7d17b6c4be72f3d5c16bf9c1af6fc933":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #70 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "136".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"33c96fafc1f96bc1d5f372bec4b6177d0a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #71 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "119".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002fec97beec546f9553142ed52f147845463f579":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #72 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "136".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"79f563548447f152ed423155f946c5ee7bc9fe020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #73 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "119".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000378dc83b8bc5a7b62cba495af4919578dce6d4f175cadc4f":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #74 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "136".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"4fdcca75f1d4e6dc789591f45a49ba2cb6a7c58b3bc88d3700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_MPI_MOD_EXT_REP_LE
+
+Test mbedtls_mpi_mod_io #75 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "119".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"b6415f2a1a8e48a518345db11f56db3829c8f2c6415ab4a395ab3ac2ea4cbef4af86eb18a84eb6ded4c6ecbfc4b59c2879a675487f687adea9d197a84a5242a5cf6125ce19a6ad2e7341f1c57d43ea4f4c852a51cb63dabcd1c9de2b827a3146a3d175b35bea41ae75d2a286a3e9d43623152ac513dcdea1d72a7da846a8ab358d9be4926c79cfb287cf1cf25b689de3b912176be5dcaf4d4c6e7cb839a4a3243a6c47c1e2c99d65c59d6fa3672575c2f1ca8de6a32e854ec9d8ec635c96af7679fce26d7d159e4a9da3bd74e1272c376cd926d74fe3fb164a5935cff3d5cdb92b35fe2cea32138a7e6bfbc319ebd1725dacb9a359cbf693f2ecb785efb9d627":MBEDTLS_MPI_MOD_EXT_REP_BE
+
+Test mbedtls_mpi_mod_io #76 N: "32292747613635961694771916499883650667878589411552643628627186850993060141490368296439843252993342320145797691611646027435006878234727648863911408777308953382400333083852585109256846643097239747078406546553406955958288616728627292699264194880486908744773379992784153004816057528456043920098334713005039494478693892693017304730883448003944721685094014669042959451482141781404822386404101555113742346277194830729517252154824958327000717338180410404929239489607893939166712107274943411892079802406181464789204374234653633818543559183821503846194953493439237710780169796543565449952151334229364816621060143650318299210551" A: "136".
+mpi_mod_io:"ffcece570f2f991013f26dd5b03c4c5b65f97be5905f36cb4664f2c78ff80aa8135a4aaf57ccb8a0aca2f394909a74cef1ef6758a64d11e2c149c393659d124bfc94196f0ce88f7d7d567efa5a649e2deefaa6e10fdc3deac60d606bf63fc540ac95294347031aefd73d6a9ee10188aaeb7a90d920894553cb196881691cadc51808715a07e8b24fcb1a63df047c7cdf084dd177ba368c806f3d51ddb5d3898c863e687ecaf7d649a57a46264a582f94d3c8f2edaf59f77a7f6bdaf83c991e8f06abe220ec8507386fce8c3da84c6c3903ab8f3ad4630a204196a7dbcbd9bcca4e40ec5cc5c09938d49f5e1e6181db8896f33bb12e6ef73f12ec5c5ea7a8a337":"27d6b9ef85b7ecf293f6cb59a3b9ac5d72d1eb19c3fb6b7e8a1332ea2cfe352bb9cdd5f3cf35594a16fbe34fd726d96c372c27e174bda39d4a9e157d6de2fc7976af965c63ecd8c94e852ea3e68dcaf1c2752567a36f9dc5659dc9e2c1476c3a24a3a439b87c6e4c4dafdce56b1712b9e39d685bf21ccf87b2cf796c92e49b8d35aba846a87d2ad7a1dedc13c52a152336d4e9a386a2d275ae41ea5bb375d1a346317a822bdec9d1bcda63cb512a854c4fea437dc5f141732eada619ce2561cfa542524aa897d1a9de7a687f4875a679289cb5c4bfecc6d4deb64ea818eb86aff4be4ceac23aab95a3b45a41c6f2c82938db561fb15d3418a5488e1a2a5f41b6":MBEDTLS_MPI_MOD_EXT_REP_LE
diff --git a/tests/suites/test_suite_bignum_mod.function b/tests/suites/test_suite_bignum_mod.function
index 1a2d0c1..0d2e232 100644
--- a/tests/suites/test_suite_bignum_mod.function
+++ b/tests/suites/test_suite_bignum_mod.function
@@ -4,6 +4,47 @@
 #include "bignum_mod.h"
 #include "constant_time_internal.h"
 #include "test/constant_flow.h"
+
+#define TEST_COMPARE_MPI_RESIDUES( a, b ) \
+            ASSERT_COMPARE( (a).p, (a).limbs * sizeof(mbedtls_mpi_uint), \
+                            (b).p, (b).limbs * sizeof(mbedtls_mpi_uint) )
+
+static int test_read_modulus( mbedtls_mpi_mod_modulus *m,
+                              mbedtls_mpi_mod_rep_selector int_rep,
+                              char *input )
+{
+    mbedtls_mpi_uint *p = NULL;
+    size_t limbs;
+
+    int ret = mbedtls_test_read_mpi_core( &p, &limbs, input );
+    if( ret != 0 )
+        return( ret );
+
+    return( mbedtls_mpi_mod_modulus_setup( m, p, limbs, int_rep ) );
+}
+
+static int test_read_residue( mbedtls_mpi_mod_residue *r,
+                              const mbedtls_mpi_mod_modulus *m,
+                              char *input,
+                              int skip_limbs_and_value_checks )
+{
+    mbedtls_mpi_uint *p = NULL;
+    size_t limbs;
+
+    int ret = mbedtls_test_read_mpi_core( &p, &limbs, input );
+    if( ret != 0 )
+        return( ret );
+
+    if( skip_limbs_and_value_checks )
+    {
+        r->p = p;
+        r->limbs = limbs;
+        return( 0 );
+    }
+
+    /* mbedtls_mpi_mod_residue_setup() checks limbs, and that value < m */
+    return( mbedtls_mpi_mod_residue_setup( r, m, p, limbs ) );
+}
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -12,7 +53,7 @@
  */
 
 /* BEGIN_CASE */
-void mpi_mod_setup( int ext_rep, int int_rep, int iret )
+void mpi_mod_setup( int int_rep, int iret )
 {
     #define MLIMBS 8
     mbedtls_mpi_uint mp[MLIMBS];
@@ -22,7 +63,7 @@
     memset( mp, 0xFF, sizeof(mp) );
 
     mbedtls_mpi_mod_modulus_init( &m );
-    ret = mbedtls_mpi_mod_modulus_setup( &m, mp, MLIMBS, ext_rep, int_rep );
+    ret = mbedtls_mpi_mod_modulus_setup( &m, mp, MLIMBS, int_rep );
     TEST_EQUAL( ret, iret );
 
     /* Only test if the constants have been set-up  */
@@ -64,7 +105,104 @@
 /* END MERGE SLOT 2 */
 
 /* BEGIN MERGE SLOT 3 */
+/* BEGIN_CASE */
+void mpi_mod_sub( char * input_N,
+                  char * input_A, char * input_B,
+                  char * input_D, int oret )
+{
+    mbedtls_mpi_mod_residue a = { NULL, 0 };
+    mbedtls_mpi_mod_residue b = { NULL, 0 };
+    mbedtls_mpi_mod_residue d = { NULL, 0 };
+    mbedtls_mpi_mod_residue x = { NULL, 0 };
+    mbedtls_mpi_uint *X_raw = NULL;
 
+    mbedtls_mpi_mod_modulus m;
+    mbedtls_mpi_mod_modulus_init( &m );
+
+    TEST_EQUAL( 0,
+        test_read_modulus( &m, MBEDTLS_MPI_MOD_REP_MONTGOMERY, input_N ) );
+
+    /* test_read_residue() normally checks that inputs have the same number of
+     * limbs as the modulus. For negative testing we can ask it to skip this
+     * with a non-zero final parameter. */
+    TEST_EQUAL( 0, test_read_residue( &a, &m, input_A, oret != 0 ) );
+    TEST_EQUAL( 0, test_read_residue( &b, &m, input_B, oret != 0 ) );
+    TEST_EQUAL( 0, test_read_residue( &d, &m, input_D, oret != 0 ) );
+
+    size_t limbs = m.limbs;
+    size_t bytes = limbs * sizeof( *X_raw );
+
+    /* One spare limb for negative testing */
+    ASSERT_ALLOC( X_raw, limbs + 1 );
+
+    if( oret == 0 )
+    {
+        /* Sneak in a couple of negative tests on known-good data */
+
+        /* First, negative test with too many limbs in output */
+        x.p = X_raw;
+        x.limbs = limbs + 1;
+        TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+                    mbedtls_mpi_mod_sub( &x, &a, &b, &m ) );
+
+        /* Then negative test with too few limbs in output */
+        if( limbs > 1 )
+        {
+            x.p = X_raw;
+            x.limbs = limbs - 1;
+            TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+                        mbedtls_mpi_mod_sub( &x, &a, &b, &m ) );
+        }
+
+        /* Negative testing with too many/too few limbs in a and b is covered by
+         * manually-written test cases with oret != 0. */
+
+        /* Back to the normally-scheduled programme */
+    }
+
+    TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &x, &m, X_raw, limbs ) );
+
+    /* a - b => Correct result, or expected error */
+    TEST_EQUAL( oret, mbedtls_mpi_mod_sub( &x, &a, &b, &m ) );
+    if( oret != 0 )
+        goto exit;
+
+    TEST_COMPARE_MPI_RESIDUES( x, d );
+
+    /* a - b: alias x to a => Correct result */
+    memcpy( x.p, a.p, bytes );
+    TEST_EQUAL( 0, mbedtls_mpi_mod_sub( &x, &x, &b, &m ) );
+    TEST_COMPARE_MPI_RESIDUES( x, d );
+
+    /* a - b: alias x to b => Correct result */
+    memcpy( x.p, b.p, bytes );
+    TEST_EQUAL( 0, mbedtls_mpi_mod_sub( &x, &a, &x, &m ) );
+    TEST_COMPARE_MPI_RESIDUES( x, d );
+
+    if ( memcmp( a.p, b.p, bytes ) == 0 )
+    {
+        /* a == b: alias a and b */
+
+        /* a - a => Correct result */
+        TEST_EQUAL( 0, mbedtls_mpi_mod_sub( &x, &a, &a, &m ) );
+        TEST_COMPARE_MPI_RESIDUES( x, d );
+
+        /* a - a: x, a, b all aliased together => Correct result */
+        memcpy( x.p, a.p, bytes );
+        TEST_EQUAL( 0, mbedtls_mpi_mod_sub( &x, &x, &x, &m ) );
+        TEST_COMPARE_MPI_RESIDUES( x, d );
+    }
+
+exit:
+    mbedtls_free( (void *)m.p ); /* mbedtls_mpi_mod_modulus_free() sets m.p = NULL */
+    mbedtls_mpi_mod_modulus_free( &m );
+
+    mbedtls_free( a.p );
+    mbedtls_free( b.p );
+    mbedtls_free( d.p );
+    mbedtls_free( X_raw );
+}
+/* END_CASE */
 /* END MERGE SLOT 3 */
 
 /* BEGIN MERGE SLOT 4 */
@@ -80,7 +218,214 @@
 /* END MERGE SLOT 6 */
 
 /* BEGIN MERGE SLOT 7 */
+/* BEGIN_CASE */
+void mpi_residue_setup( char * input_N, char * input_R, int ret )
+{
+    mbedtls_mpi_uint *N = NULL;
+    mbedtls_mpi_uint *R = NULL;
+    size_t n_limbs, r_limbs;
+    mbedtls_mpi_mod_modulus m;
+    mbedtls_mpi_mod_residue r;
 
+    mbedtls_mpi_mod_modulus_init( &m );
+
+    /* Allocate the memory for intermediate data structures */
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &R, &r_limbs, input_R ) );
+
+    TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
+                MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+
+    TEST_EQUAL( ret, mbedtls_mpi_mod_residue_setup( &r, &m, R , r_limbs ) );
+
+    if ( ret == 0 )
+    {
+        TEST_EQUAL( r.limbs, r_limbs );
+        TEST_ASSERT( r.p == R );
+    }
+
+exit:
+    mbedtls_mpi_mod_modulus_free( &m );
+    mbedtls_free( N );
+    mbedtls_free( R );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_io_neg( char * input_N, data_t * buf, int ret )
+{
+    mbedtls_mpi_uint *N = NULL;
+    mbedtls_mpi_uint *R = NULL;
+
+    mbedtls_mpi_mod_modulus m;
+    mbedtls_mpi_mod_residue r = { NULL, 0 };
+    mbedtls_mpi_mod_ext_rep endian = MBEDTLS_MPI_MOD_EXT_REP_LE;
+
+    mbedtls_mpi_mod_modulus_init( &m );
+
+    size_t n_limbs;
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) );
+    size_t r_limbs = n_limbs;
+    ASSERT_ALLOC( R, r_limbs );
+
+    /* modulus->p == NULL || residue->p == NULL ( m has not been set-up ) */
+    TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+                mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) );
+
+    TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+                mbedtls_mpi_mod_write( &r, &m, buf->x, buf->len, endian ) );
+
+    /* Set up modulus and test with residue->p == NULL */
+    TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
+                MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+
+    TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+                mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) );
+    TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+                mbedtls_mpi_mod_write( &r, &m, buf->x, buf->len, endian ) );
+
+    /* Do the rest of the tests with a residue set up with the input data */
+    TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &r, &m, R , r_limbs ) );
+
+    /* Fail for r_limbs < m->limbs */
+    r.limbs--;
+    TEST_ASSERT( r.limbs < m.limbs );
+    TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+                mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) );
+    TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+                mbedtls_mpi_mod_write( &r, &m, buf->x, buf->len, endian ) );
+    r.limbs++;
+
+    /* Fail for r_limbs > m->limbs */
+    m.limbs--;
+    TEST_ASSERT( r.limbs > m.limbs );
+    TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+                mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) );
+    TEST_EQUAL( MBEDTLS_ERR_MPI_BAD_INPUT_DATA,
+                mbedtls_mpi_mod_write( &r, &m, buf->x, buf->len, endian ) );
+    m.limbs++;
+
+    /* Test the read */
+    TEST_EQUAL( ret, mbedtls_mpi_mod_read( &r, &m, buf->x, buf->len, endian ) );
+
+    /* Test write overflow only when the representation is large and read is successful  */
+    if ( r.limbs > 1 && ret == 0 )
+        TEST_EQUAL( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL,
+                        mbedtls_mpi_mod_write( &r, &m, buf->x, 1, endian ) );
+
+exit:
+    mbedtls_mpi_mod_residue_release( &r );
+    mbedtls_mpi_mod_modulus_free( &m );
+    mbedtls_free( N );
+    mbedtls_free( R );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void mpi_mod_io( char * input_N, data_t * input_A, int endian )
+{
+    mbedtls_mpi_uint *N = NULL;
+    mbedtls_mpi_uint *R = NULL;
+    mbedtls_mpi_uint *R_COPY = NULL;
+    unsigned char *obuf = NULL;
+    unsigned char *ref_buf = NULL;
+    mbedtls_mpi_mod_modulus m;
+    mbedtls_mpi_mod_residue r;
+    mbedtls_mpi_mod_residue r_copy;
+    size_t n_limbs, n_bytes, a_bytes;
+
+    mbedtls_mpi_mod_modulus_init( &m );
+
+    /* Read inputs */
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &n_limbs, input_N ) );
+    n_bytes = n_limbs * sizeof( mbedtls_mpi_uint );
+    a_bytes = input_A->len;
+
+    /* Allocate the memory for intermediate data structures */
+    ASSERT_ALLOC( R, n_bytes );
+    ASSERT_ALLOC( R_COPY, n_bytes );
+
+    /* Test that input's size is not greater to modulo's */
+    TEST_LE_U( a_bytes, n_bytes );
+
+    /* Init Structures */
+    TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
+                MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+
+    /* Enforcing p_limbs >= m->limbs */
+    TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &r, &m, R, n_limbs ) );
+
+    TEST_EQUAL( 0, mbedtls_mpi_mod_read( &r, &m, input_A->x, input_A->len,
+                                         endian ) );
+
+    /* Read a copy for checking that writing didn't change the value of r */
+    TEST_EQUAL( 0, mbedtls_mpi_mod_residue_setup( &r_copy, &m,
+                                                  R_COPY, n_limbs ) );
+    TEST_EQUAL( 0, mbedtls_mpi_mod_read( &r_copy, &m, input_A->x, input_A->len,
+                                         endian ) );
+
+    /* Get number of bytes without leading zeroes */
+    size_t a_bytes_trimmed = a_bytes;
+    while( a_bytes_trimmed > 0 )
+    {
+        unsigned char* r_byte_array = (unsigned char*) r.p;
+        if( r_byte_array[--a_bytes_trimmed] != 0 )
+            break;
+    }
+    a_bytes_trimmed++;
+
+    /* Test write with three output buffer sizes: tight, same as input and
+     * longer than the input */
+    size_t obuf_sizes[3];
+    const size_t obuf_sizes_len = sizeof( obuf_sizes ) / sizeof( obuf_sizes[0] );
+    obuf_sizes[0] = a_bytes_trimmed;
+    obuf_sizes[1] = a_bytes;
+    obuf_sizes[2] = a_bytes + 8;
+
+    for( size_t i = 0; i < obuf_sizes_len; i++ )
+    {
+        ASSERT_ALLOC( obuf, obuf_sizes[i] );
+        TEST_EQUAL( 0, mbedtls_mpi_mod_write( &r, &m, obuf, obuf_sizes[i], endian ) );
+
+        /* Make sure that writing didn't corrupt the value of r */
+        ASSERT_COMPARE( r.p, r.limbs, r_copy.p, r_copy.limbs );
+
+        /* Set up reference output for checking the result */
+        ASSERT_ALLOC( ref_buf, obuf_sizes[i] );
+        switch( endian )
+        {
+            case MBEDTLS_MPI_MOD_EXT_REP_LE:
+                memcpy( ref_buf, input_A->x, a_bytes_trimmed );
+                break;
+            case MBEDTLS_MPI_MOD_EXT_REP_BE:
+                {
+                    size_t a_offset = input_A->len - a_bytes_trimmed;
+                    size_t ref_offset = obuf_sizes[i] - a_bytes_trimmed;
+                    memcpy( ref_buf + ref_offset, input_A->x + a_offset,
+                            a_bytes_trimmed );
+                }
+                break;
+            default:
+                TEST_ASSERT( 0 );
+        }
+
+        /* Check the result */
+        ASSERT_COMPARE( obuf, obuf_sizes[i], ref_buf, obuf_sizes[i] );
+
+        mbedtls_free( ref_buf );
+        ref_buf = NULL;
+        mbedtls_free( obuf );
+        obuf = NULL;
+    }
+
+exit:
+    mbedtls_mpi_mod_modulus_free( &m );
+    mbedtls_free( N );
+    mbedtls_free( R );
+    mbedtls_free( R_COPY );
+    mbedtls_free( obuf );
+}
+/* END_CASE */
 /* END MERGE SLOT 7 */
 
 /* BEGIN MERGE SLOT 8 */
diff --git a/tests/suites/test_suite_bignum_mod_raw.function b/tests/suites/test_suite_bignum_mod_raw.function
index 00ed005..5d23707 100644
--- a/tests/suites/test_suite_bignum_mod_raw.function
+++ b/tests/suites/test_suite_bignum_mod_raw.function
@@ -49,22 +49,22 @@
 
     mbedtls_mpi_uint init[sizeof( X ) / sizeof( X[0] )];
     memset( init, 0xFF, sizeof( init ) );
-    int ret = mbedtls_mpi_mod_modulus_setup( &m, init, nx, endian,
+    int ret = mbedtls_mpi_mod_modulus_setup( &m, init, nx,
                                              MBEDTLS_MPI_MOD_REP_MONTGOMERY );
     TEST_EQUAL( ret, 0 );
 
     if( iendian == MBEDTLS_MPI_MOD_EXT_REP_INVALID && iret != 0 )
-        m.ext_rep = MBEDTLS_MPI_MOD_EXT_REP_INVALID;
+       endian = MBEDTLS_MPI_MOD_EXT_REP_INVALID;
 
-    ret = mbedtls_mpi_mod_raw_read( X, &m, input->x, input->len );
+    ret = mbedtls_mpi_mod_raw_read( X, &m, input->x, input->len, endian );
     TEST_EQUAL( ret, iret );
 
     if( iret == 0 )
     {
         if( iendian == MBEDTLS_MPI_MOD_EXT_REP_INVALID && oret != 0 )
-            m.ext_rep = MBEDTLS_MPI_MOD_EXT_REP_INVALID;
+            endian = MBEDTLS_MPI_MOD_EXT_REP_INVALID;
 
-        ret = mbedtls_mpi_mod_raw_write( X, &m, buf, nb );
+        ret = mbedtls_mpi_mod_raw_write( X, &m, buf, nb, endian );
         TEST_EQUAL( ret, oret );
     }
 
@@ -138,7 +138,6 @@
     memset( buff_m, 0xFF, copy_limbs );
     TEST_EQUAL( mbedtls_mpi_mod_modulus_setup(
                         &m, buff_m, copy_limbs,
-                        MBEDTLS_MPI_MOD_EXT_REP_BE,
                         MBEDTLS_MPI_MOD_REP_MONTGOMERY ), 0 );
 
     /* condition is false */
@@ -211,7 +210,6 @@
     memset( buff_m, 0xFF, copy_limbs );
     TEST_EQUAL( mbedtls_mpi_mod_modulus_setup(
                         &m, buff_m, copy_limbs,
-                        MBEDTLS_MPI_MOD_EXT_REP_BE,
                         MBEDTLS_MPI_MOD_REP_MONTGOMERY ), 0 );
 
     ASSERT_ALLOC( X, limbs );
@@ -310,7 +308,6 @@
 
     TEST_EQUAL( mbedtls_mpi_mod_modulus_setup(
                         &m, N, limbs,
-                        MBEDTLS_MPI_MOD_EXT_REP_BE,
                         MBEDTLS_MPI_MOD_REP_MONTGOMERY ), 0 );
 
     mbedtls_mpi_mod_raw_sub( X, A, B, &m );
@@ -352,6 +349,75 @@
 
 /* BEGIN MERGE SLOT 3 */
 
+/* BEGIN_CASE */
+void mpi_mod_raw_inv_prime( char * input_N, char * input_A, char * input_X )
+{
+    mbedtls_mpi_uint *A = NULL;
+    mbedtls_mpi_uint *N = NULL;
+    mbedtls_mpi_uint *X = NULL;
+    size_t A_limbs, N_limbs, X_limbs;
+    mbedtls_mpi_uint *Y = NULL;
+    mbedtls_mpi_uint *T = NULL;
+    const mbedtls_mpi_uint *R2 = NULL;
+
+    /* Legacy MPIs for computing R2 */
+    mbedtls_mpi N_mpi;  /* gets set up manually, aliasing N, so no need to free */
+    mbedtls_mpi R2_mpi;
+    mbedtls_mpi_init( &R2_mpi );
+
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &A, &A_limbs, input_A ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &N, &N_limbs, input_N ) );
+    TEST_EQUAL( 0, mbedtls_test_read_mpi_core( &X, &X_limbs, input_X ) );
+    ASSERT_ALLOC( Y, N_limbs );
+
+    TEST_EQUAL( A_limbs, N_limbs );
+    TEST_EQUAL( X_limbs, N_limbs );
+
+    N_mpi.s = 1;
+    N_mpi.p = N;
+    N_mpi.n = N_limbs;
+    TEST_EQUAL( 0, mbedtls_mpi_core_get_mont_r2_unsafe( &R2_mpi, &N_mpi ) );
+    TEST_EQUAL( 0, mbedtls_mpi_grow( &R2_mpi, N_limbs ) );
+    R2 = R2_mpi.p;
+
+    size_t working_limbs = mbedtls_mpi_mod_raw_inv_prime_working_limbs( N_limbs );
+
+    /* No point exactly duplicating the code in mbedtls_mpi_mod_raw_inv_prime_working_limbs()
+     * to see if the output is correct, but we can check that it's in a
+     * reasonable range.  The current calculation works out as
+     * `1 + N_limbs * (welem + 4)`, where welem is the number of elements in
+     * the window (1 << 1 up to 1 << 6).
+     */
+    size_t min_expected_working_limbs = 1 + N_limbs * 5;
+    size_t max_expected_working_limbs = 1 + N_limbs * 68;
+
+    TEST_LE_U( min_expected_working_limbs, working_limbs );
+    TEST_LE_U( working_limbs, max_expected_working_limbs );
+
+    ASSERT_ALLOC( T, working_limbs );
+
+    mbedtls_mpi_mod_raw_inv_prime( Y, A, N, N_limbs, R2, T );
+
+    TEST_EQUAL( 0, memcmp( X, Y, N_limbs * sizeof( mbedtls_mpi_uint ) ) );
+
+    /* Check when output aliased to input */
+
+    mbedtls_mpi_mod_raw_inv_prime( A, A, N, N_limbs, R2, T );
+
+    TEST_EQUAL( 0, memcmp( X, A, N_limbs * sizeof( mbedtls_mpi_uint ) ) );
+
+exit:
+    mbedtls_free( T );
+    mbedtls_free( A );
+    mbedtls_free( N );
+    mbedtls_free( X );
+    mbedtls_free( Y );
+    mbedtls_mpi_free( &R2_mpi );
+    // R2 doesn't need to be freed as it is only aliasing R2_mpi
+    // N_mpi doesn't need to be freed as it is only aliasing N
+}
+/* END_CASE */
+
 /* END MERGE SLOT 3 */
 
 /* BEGIN MERGE SLOT 4 */
@@ -392,7 +458,6 @@
 
     TEST_EQUAL( mbedtls_mpi_mod_modulus_setup(
                         &m, N, limbs,
-                        MBEDTLS_MPI_MOD_EXT_REP_BE,
                         MBEDTLS_MPI_MOD_REP_MONTGOMERY
                 ), 0 );
 
@@ -480,7 +545,7 @@
     TEST_LE_U(a_limbs, n_limbs);
 
     TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
-                MBEDTLS_MPI_MOD_EXT_REP_BE, MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+                MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
 
     /* Convert from cannonical into Montgomery representation */
     TEST_EQUAL(0, mbedtls_mpi_mod_raw_to_mont_rep( A, &m ) );
@@ -516,7 +581,7 @@
     TEST_LE_U(a_limbs, n_limbs);
 
     TEST_EQUAL( 0, mbedtls_mpi_mod_modulus_setup( &m, N, n_limbs,
-                MBEDTLS_MPI_MOD_EXT_REP_BE, MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
+                MBEDTLS_MPI_MOD_REP_MONTGOMERY ) );
 
     /* Convert from Montgomery into cannonical representation */
     TEST_EQUAL(0, mbedtls_mpi_mod_raw_from_mont_rep( A, &m ) );
diff --git a/tests/suites/test_suite_constant_time.data b/tests/suites/test_suite_constant_time.data
new file mode 100644
index 0000000..4504aa4
--- /dev/null
+++ b/tests/suites/test_suite_constant_time.data
@@ -0,0 +1,11 @@
+# these are the numbers we'd get with an empty plaintext and truncated HMAC
+Constant-flow memcpy from offset: small
+ssl_cf_memcpy_offset:0:5:10
+
+# we could get this with 255-bytes plaintext and untruncated SHA-256
+Constant-flow memcpy from offset: medium
+ssl_cf_memcpy_offset:0:255:32
+
+# we could get this with 255-bytes plaintext and untruncated SHA-384
+Constant-flow memcpy from offset: large
+ssl_cf_memcpy_offset:100:339:48
diff --git a/tests/suites/test_suite_constant_time.function b/tests/suites/test_suite_constant_time.function
new file mode 100644
index 0000000..a3673b7
--- /dev/null
+++ b/tests/suites/test_suite_constant_time.function
@@ -0,0 +1,49 @@
+/* BEGIN_HEADER */
+/** \file test_suite_constant_time.function
+ *
+ * Functional testing of functions in the constant_time module.
+ *
+ * The tests are instrumented with #TEST_CF_SECRET and #TEST_CF_PUBLIC
+ * (see tests/include/test/constant_flow.h) so that running the tests
+ * under MSan or Valgrind will detect a non-constant-time implementation.
+ */
+
+#include <mbedtls/constant_time.h>
+#include <constant_time_internal.h>
+#include <constant_time_invasive.h>
+
+#include <test/constant_flow.h>
+/* END_HEADER */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC:MBEDTLS_TEST_HOOKS */
+void ssl_cf_memcpy_offset( int offset_min, int offset_max, int len )
+{
+    unsigned char *dst = NULL;
+    unsigned char *src = NULL;
+    size_t src_len = offset_max + len;
+    size_t secret;
+
+    ASSERT_ALLOC( dst, len );
+    ASSERT_ALLOC( src, src_len );
+
+    /* Fill src in a way that we can detect if we copied the right bytes */
+    mbedtls_test_rnd_std_rand( NULL, src, src_len );
+
+    for( secret = offset_min; secret <= (size_t) offset_max; secret++ )
+    {
+        mbedtls_test_set_step( (int) secret );
+
+        TEST_CF_SECRET( &secret, sizeof( secret ) );
+        mbedtls_ct_memcpy_offset( dst, src, secret,
+                                  offset_min, offset_max, len );
+        TEST_CF_PUBLIC( &secret, sizeof( secret ) );
+        TEST_CF_PUBLIC( dst, len );
+
+        ASSERT_COMPARE( dst, len, src + secret, len );
+    }
+
+exit:
+    mbedtls_free( dst );
+    mbedtls_free( src );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_constant_time_hmac.data b/tests/suites/test_suite_constant_time_hmac.data
new file mode 100644
index 0000000..abf90f0
--- /dev/null
+++ b/tests/suites/test_suite_constant_time_hmac.data
@@ -0,0 +1,15 @@
+Constant-flow HMAC: MD5
+depends_on:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+ssl_cf_hmac:MBEDTLS_MD_MD5
+
+Constant-flow HMAC: SHA1
+depends_on:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+ssl_cf_hmac:MBEDTLS_MD_SHA1
+
+Constant-flow HMAC: SHA256
+depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+ssl_cf_hmac:MBEDTLS_MD_SHA256
+
+Constant-flow HMAC: SHA384
+depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA
+ssl_cf_hmac:MBEDTLS_MD_SHA384
diff --git a/tests/suites/test_suite_constant_time_hmac.function b/tests/suites/test_suite_constant_time_hmac.function
new file mode 100644
index 0000000..f8c1bfc
--- /dev/null
+++ b/tests/suites/test_suite_constant_time_hmac.function
@@ -0,0 +1,160 @@
+/* BEGIN_HEADER */
+
+#include <mbedtls/constant_time.h>
+#include <mbedtls/legacy_or_psa.h>
+#include <mbedtls/md.h>
+#include <constant_time_internal.h>
+#include <hash_info.h>
+
+#include <test/constant_flow.h>
+/* END_HEADER */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC:MBEDTLS_TEST_HOOKS */
+void ssl_cf_hmac( int hash )
+{
+    /*
+     * Test the function mbedtls_ct_hmac() against a reference
+     * implementation.
+     */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t alg;
+    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+#else
+    mbedtls_md_context_t ctx, ref_ctx;
+    const mbedtls_md_info_t *md_info;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    size_t out_len, block_size;
+    size_t min_in_len, in_len, max_in_len, i;
+    /* TLS additional data is 13 bytes (hence the "lucky 13" name) */
+    unsigned char add_data[13];
+    unsigned char ref_out[MBEDTLS_HASH_MAX_SIZE];
+    unsigned char *data = NULL;
+    unsigned char *out = NULL;
+    unsigned char rec_num = 0;
+
+    USE_PSA_INIT( );
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    alg = PSA_ALG_HMAC( mbedtls_hash_info_psa_from_md( hash ) );
+
+    out_len = PSA_HASH_LENGTH( alg );
+    block_size = PSA_HASH_BLOCK_LENGTH( alg );
+
+    /* mbedtls_ct_hmac() requires the key to be exportable */
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT |
+                                          PSA_KEY_USAGE_VERIFY_HASH );
+    psa_set_key_algorithm( &attributes, PSA_ALG_HMAC( alg ) );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_HMAC );
+#else
+    mbedtls_md_init( &ctx );
+    mbedtls_md_init( &ref_ctx );
+
+    md_info = mbedtls_md_info_from_type( hash );
+    TEST_ASSERT( md_info != NULL );
+    out_len = mbedtls_md_get_size( md_info );
+    TEST_ASSERT( out_len != 0 );
+    block_size = hash == MBEDTLS_MD_SHA384 ? 128 : 64;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    /* Use allocated out buffer to catch overwrites */
+    ASSERT_ALLOC( out, out_len );
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    /* Set up dummy key */
+    memset( ref_out, 42, sizeof( ref_out ) );
+    TEST_EQUAL( PSA_SUCCESS, psa_import_key( &attributes,
+                                             ref_out, out_len,
+                                             &key ) );
+#else
+    /* Set up contexts with the given hash and a dummy key */
+    TEST_EQUAL( 0, mbedtls_md_setup( &ctx, md_info, 1 ) );
+    TEST_EQUAL( 0, mbedtls_md_setup( &ref_ctx, md_info, 1 ) );
+    memset( ref_out, 42, sizeof( ref_out ) );
+    TEST_EQUAL( 0, mbedtls_md_hmac_starts( &ctx, ref_out, out_len ) );
+    TEST_EQUAL( 0, mbedtls_md_hmac_starts( &ref_ctx, ref_out, out_len ) );
+    memset( ref_out, 0, sizeof( ref_out ) );
+#endif
+
+    /*
+     * Test all possible lengths up to a point. The difference between
+     * max_in_len and min_in_len is at most 255, and make sure they both vary
+     * by at least one block size.
+     */
+    for( max_in_len = 0; max_in_len <= 255 + block_size; max_in_len++ )
+    {
+        mbedtls_test_set_step( max_in_len * 10000 );
+
+        /* Use allocated in buffer to catch overreads */
+        ASSERT_ALLOC( data, max_in_len );
+
+        min_in_len = max_in_len > 255 ? max_in_len - 255 : 0;
+        for( in_len = min_in_len; in_len <= max_in_len; in_len++ )
+        {
+            mbedtls_test_set_step( max_in_len * 10000 + in_len );
+
+            /* Set up dummy data and add_data */
+            rec_num++;
+            memset( add_data, rec_num, sizeof( add_data ) );
+            for( i = 0; i < in_len; i++ )
+                data[i] = ( i & 0xff ) ^ rec_num;
+
+            /* Get the function's result */
+            TEST_CF_SECRET( &in_len, sizeof( in_len ) );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            TEST_EQUAL( 0, mbedtls_ct_hmac( key, PSA_ALG_HMAC( alg ),
+                                            add_data, sizeof( add_data ),
+                                            data, in_len,
+                                            min_in_len, max_in_len,
+                                            out ) );
+#else
+            TEST_EQUAL( 0, mbedtls_ct_hmac( &ctx, add_data, sizeof( add_data ),
+                                            data, in_len,
+                                            min_in_len, max_in_len,
+                                            out ) );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+            TEST_CF_PUBLIC( &in_len, sizeof( in_len ) );
+            TEST_CF_PUBLIC( out, out_len );
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            TEST_EQUAL( PSA_SUCCESS, psa_mac_verify_setup( &operation,
+                                                           key, alg ) );
+            TEST_EQUAL( PSA_SUCCESS, psa_mac_update( &operation, add_data,
+                                                     sizeof( add_data ) ) );
+            TEST_EQUAL( PSA_SUCCESS, psa_mac_update( &operation,
+                                                     data, in_len ) );
+            TEST_EQUAL( PSA_SUCCESS, psa_mac_verify_finish( &operation,
+                                                            out, out_len ) );
+#else
+            /* Compute the reference result */
+            TEST_EQUAL( 0, mbedtls_md_hmac_update( &ref_ctx, add_data,
+                                                   sizeof( add_data ) ) );
+            TEST_EQUAL( 0, mbedtls_md_hmac_update( &ref_ctx, data, in_len ) );
+            TEST_EQUAL( 0, mbedtls_md_hmac_finish( &ref_ctx, ref_out ) );
+            TEST_EQUAL( 0, mbedtls_md_hmac_reset( &ref_ctx ) );
+
+            /* Compare */
+            ASSERT_COMPARE( out, out_len, ref_out, out_len );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+        }
+
+        mbedtls_free( data );
+        data = NULL;
+    }
+
+exit:
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_mac_abort( &operation );
+    psa_destroy_key( key );
+#else
+    mbedtls_md_free( &ref_ctx );
+    mbedtls_md_free( &ctx );
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    mbedtls_free( data );
+    mbedtls_free( out );
+
+    USE_PSA_DONE( );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_mps.function b/tests/suites/test_suite_mps.function
index c40c50e..ec1122a 100644
--- a/tests/suites/test_suite_mps.function
+++ b/tests/suites/test_suite_mps.function
@@ -295,7 +295,7 @@
     /* This test exercises the behaviour of the MPS reader with accumulator
      * in the situation where upon calling mbedtls_mps_reader_reclaim(), the
      * uncommitted data together with the excess data missing in the last
-     * call to medtls_mps_reader_get() exceeds the bounds of the type
+     * call to mbedtls_mps_reader_get() exceeds the bounds of the type
      * holding the buffer length.
      */
 
diff --git a/tests/suites/test_suite_pkcs7.data b/tests/suites/test_suite_pkcs7.data
index 4f81b6f..f3cbb62 100644
--- a/tests/suites/test_suite_pkcs7.data
+++ b/tests/suites/test_suite_pkcs7.data
@@ -62,6 +62,14 @@
 depends_on:MBEDTLS_SHA256_C
 pkcs7_parse:"data_files/pkcs7_signerInfo_serial_invalid_size.der":MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO
 
+pkcs7_get_signers_info_set error handling (6213931373035520)
+depends_on:MBEDTLS_RIPEMD160_C
+pkcs7_parse:"data_files/pkcs7_get_signers_info_set-missing_free-fuzz_pkcs7-6213931373035520.der":MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+
+pkcs7_get_signers_info_set error handling (4541044530479104)
+depends_on:MBEDTLS_RIPEMD160_C
+pkcs7_parse:"data_files/pkcs7_get_signers_info_set-missing_free-fuzz_pkcs7-6213931373035520.der":MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
+
 PKCS7 Only Signed Data Parse Pass #15
 depends_on:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
 pkcs7_parse:"data_files/pkcs7_data_cert_signeddata_sha256.der":MBEDTLS_PKCS7_SIGNED_DATA
diff --git a/tests/suites/test_suite_pkcs7.function b/tests/suites/test_suite_pkcs7.function
index e396140..3d7dec6 100644
--- a/tests/suites/test_suite_pkcs7.function
+++ b/tests/suites/test_suite_pkcs7.function
@@ -26,10 +26,10 @@
     mbedtls_pkcs7_init( &pkcs7 );
 
     res = mbedtls_pk_load_file( pkcs7_file, &pkcs7_buf, &buflen );
-    TEST_ASSERT( res == 0 );
+    TEST_EQUAL( res, 0 );
 
     res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen );
-    TEST_ASSERT( res == res_expect );
+    TEST_EQUAL( res, res_expect );
 
 exit:
     mbedtls_free( pkcs7_buf );
@@ -54,22 +54,22 @@
     mbedtls_pkcs7 pkcs7;
     mbedtls_x509_crt x509;
 
-    USE_PSA_INIT();
-
     mbedtls_pkcs7_init( &pkcs7 );
     mbedtls_x509_crt_init( &x509 );
 
+    USE_PSA_INIT();
+
     res = mbedtls_x509_crt_parse_file( &x509, crt );
-    TEST_ASSERT( res == 0 );
+    TEST_EQUAL( res, 0 );
 
     res = mbedtls_pk_load_file( pkcs7_file, &pkcs7_buf, &buflen );
-    TEST_ASSERT( res == 0 );
+    TEST_EQUAL( res, 0 );
 
     res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen );
-    TEST_ASSERT( res == MBEDTLS_PKCS7_SIGNED_DATA );
+    TEST_EQUAL( res, MBEDTLS_PKCS7_SIGNED_DATA );
 
     res = stat( filetobesigned, &st );
-    TEST_ASSERT( res == 0 );
+    TEST_EQUAL( res, 0 );
 
     file = fopen( filetobesigned, "rb" );
     TEST_ASSERT( file != NULL );
@@ -79,18 +79,18 @@
     TEST_ASSERT( data != NULL );
 
     buflen = fread( (void *)data , sizeof( unsigned char ), datalen, file );
-    TEST_ASSERT( buflen == datalen );
+    TEST_EQUAL( buflen, datalen );
     fclose( file );
 
     if( do_hash_alg )
     {
         res = mbedtls_oid_get_md_alg( &pkcs7.signed_data.digest_alg_identifiers, &md_alg );
-        TEST_ASSERT( res == 0 );
-        TEST_ASSERT( md_alg == (mbedtls_md_type_t) do_hash_alg );
+        TEST_EQUAL( res, 0 );
+        TEST_EQUAL( md_alg, (mbedtls_md_type_t) do_hash_alg );
         md_info = mbedtls_md_info_from_type( md_alg );
 
         res = mbedtls_md( md_info, data, datalen, hash );
-        TEST_ASSERT( res == 0 );
+        TEST_EQUAL( res, 0 );
 
         res = mbedtls_pkcs7_signed_hash_verify( &pkcs7, &x509, hash, sizeof(hash) );
     }
@@ -98,7 +98,7 @@
     {
         res = mbedtls_pkcs7_signed_data_verify( &pkcs7, &x509, data, datalen );
     }
-    TEST_ASSERT( res == res_expect );
+    TEST_EQUAL( res, res_expect );
 
 exit:
     mbedtls_x509_crt_free( &x509 );
@@ -127,28 +127,28 @@
     mbedtls_x509_crt x509_1;
     mbedtls_x509_crt x509_2;
 
-    USE_PSA_INIT();
-
     mbedtls_pkcs7_init( &pkcs7 );
     mbedtls_x509_crt_init( &x509_1 );
     mbedtls_x509_crt_init( &x509_2 );
 
+    USE_PSA_INIT();
+
     res = mbedtls_pk_load_file( pkcs7_file, &pkcs7_buf, &buflen );
-    TEST_ASSERT( res == 0 );
+    TEST_EQUAL( res, 0 );
 
     res = mbedtls_pkcs7_parse_der( &pkcs7, pkcs7_buf, buflen );
-    TEST_ASSERT( res == MBEDTLS_PKCS7_SIGNED_DATA );
+    TEST_EQUAL( res, MBEDTLS_PKCS7_SIGNED_DATA );
 
-    TEST_ASSERT( pkcs7.signed_data.no_of_signers == 2 );
+    TEST_EQUAL( pkcs7.signed_data.no_of_signers, 2 );
 
     res = mbedtls_x509_crt_parse_file( &x509_1, crt1 );
-    TEST_ASSERT( res == 0 );
+    TEST_EQUAL( res, 0 );
 
     res = mbedtls_x509_crt_parse_file( &x509_2, crt2 );
-    TEST_ASSERT( res == 0 );
+    TEST_EQUAL( res, 0 );
 
     res = stat( filetobesigned, &st );
-    TEST_ASSERT( res == 0 );
+    TEST_EQUAL( res, 0 );
 
     file = fopen( filetobesigned, "rb" );
     TEST_ASSERT( file != NULL );
@@ -156,32 +156,32 @@
     datalen = st.st_size;
     ASSERT_ALLOC( data, datalen );
     buflen = fread( ( void * )data , sizeof( unsigned char ), datalen, file );
-    TEST_ASSERT( buflen == datalen );
+    TEST_EQUAL( buflen, datalen );
 
     fclose( file );
 
     if( do_hash_alg )
     {
         res = mbedtls_oid_get_md_alg( &pkcs7.signed_data.digest_alg_identifiers, &md_alg );
-        TEST_ASSERT( res == 0 );
-        TEST_ASSERT( md_alg == MBEDTLS_MD_SHA256 );
+        TEST_EQUAL( res, 0 );
+        TEST_EQUAL( md_alg, MBEDTLS_MD_SHA256 );
 
         md_info = mbedtls_md_info_from_type( md_alg );
 
         res = mbedtls_md( md_info, data, datalen, hash );
-        TEST_ASSERT( res == 0 );
+        TEST_EQUAL( res, 0 );
 
         res = mbedtls_pkcs7_signed_hash_verify( &pkcs7, &x509_1, hash, sizeof(hash) );
-        TEST_ASSERT( res == res_expect );
+        TEST_EQUAL( res, res_expect );
     }
     else
     {
         res = mbedtls_pkcs7_signed_data_verify( &pkcs7, &x509_1, data, datalen );
-        TEST_ASSERT( res == res_expect );
+        TEST_EQUAL( res, res_expect );
     }
 
     res = mbedtls_pkcs7_signed_data_verify( &pkcs7, &x509_2, data, datalen );
-    TEST_ASSERT( res == res_expect );
+    TEST_EQUAL( res, res_expect );
 
 exit:
     mbedtls_x509_crt_free( &x509_1 );
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index 659205d..9ced77c 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -4138,7 +4138,7 @@
 sign_hash_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_256 ):"9ac4335b469bbd791439248504dd0d49c71349a295fee5a1c68507f45a9e1c7b":"6a3399f69421ffe1490377adf2ea1f117d81a63cf5bf22e918d51175eb259151ce95d7c26cc04e25503e2f7a1ec3573e3c2412534bb4a19b3a7811742f49f50f"
 
 PSA sign hash: deterministic ECDSA SECP256R1 SHA-384
-depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDLTS_PSA_BUILTIN_ALG_SHA_384
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PSA_BUILTIN_ALG_SHA_384
 sign_hash_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_DETERMINISTIC_ECDSA( PSA_ALG_SHA_384 ):"59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f":"cd40ba1b555ca5994d30ddffc4ad734b1f5c604675b0f249814aa5de3992ef3ddf4d5dc5d2aab1979ce210b560754df671363d99795475882894c048e3b986ca"
 
 PSA sign hash: deterministic ECDSA SECP384R1 SHA-256
@@ -4406,7 +4406,7 @@
 sign_message_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256):"616263":"36e5b5a7da1c9c265dc447de3a5a704fcb8c03f7a3749dde48d84c9bf736fc1ed48d8b3660e7d3cbc6b1870730b7ce2a043f69e37ccb340b98d1e65184e03548"
 
 PSA sign message: deterministic ECDSA SECP256R1 SHA-384
-depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDLTS_PSA_BUILTIN_ALG_SHA_384
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PSA_BUILTIN_ALG_SHA_384
 sign_message_deterministic:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):"616263":"7ea712a20e3a8cbe0c6e64195362ba7635bbe78af51ddedd7a5fd858395250c592654c35d3b0614ae0e3b329c25cf5b4a5fcb243af3e3ad15c8446fe401be066"
 
 PSA sign message: deterministic ECDSA SECP384R1 SHA-256
@@ -4526,7 +4526,7 @@
 sign_verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_ECDSA(PSA_ALG_SHA_384):"616263"
 
 PSA sign/verify message: deterministic ECDSA SECP256R1 SHA-384
-depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDLTS_PSA_BUILTIN_ALG_SHA_384
+depends_on:PSA_WANT_ALG_DETERMINISTIC_ECDSA:PSA_WANT_ALG_SHA_384:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PSA_BUILTIN_ALG_SHA_384
 sign_verify_message:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"ab45435712649cb30bbddac49197eebf2740ffc7f874d9244c3460f54f322d3a":PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_384):"616263"
 
 PSA sign/verify message: randomized ECDSA SECP384R1 SHA-256
@@ -6490,116 +6490,3 @@
 
 PSA derive persistent key: HKDF SHA-256, exportable
 persistent_key_load_key_from_storage:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_TYPE_RAW_DATA:1024:PSA_KEY_USAGE_EXPORT:0:DERIVE_KEY
-
-PSA PAKE: invalid alg
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_SHA_256:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:"abcd":PSA_ERROR_INVALID_ARGUMENT:0:0:0
-
-PSA PAKE: invalid primitive type
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_DH, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:"abcd":PSA_ERROR_NOT_SUPPORTED:0:0:0
-
-PSA PAKE: invalid primitive family
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_K1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:"abcd":PSA_ERROR_NOT_SUPPORTED:0:0:0
-
-PSA PAKE: invalid primitive bits
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 128):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:"abcd":PSA_ERROR_NOT_SUPPORTED:0:0:0
-
-PSA PAKE: invalid hash
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_1:PSA_PAKE_ROLE_SERVER:0:"abcd":PSA_ERROR_NOT_SUPPORTED:0:0:0
-
-PSA PAKE: ecjpake setup server output step first
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:"abcd":0:0:0:0
-
-PSA PAKE: ecjpake setup server input step first
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:1:"abcd":0:0:0:0
-
-PSA PAKE: ecjpake setup server empty password
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:"":0:0:0:PSA_ERROR_BAD_STATE
-
-PSA PAKE: ecjpake setup client output step first
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_CLIENT:0:"abcd":0:0:0:0
-
-PSA PAKE: ecjpake setup client input step first
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_CLIENT:1:"abcd":0:0:0:0
-
-PSA PAKE: ecjpake setup client empty password
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_CLIENT:0:"":0:0:0:PSA_ERROR_BAD_STATE
-
-PSA PAKE: ecjpake setup client bad password key type
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_DERIVE:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_CLIENT:0:"abcd":0:0:PSA_ERROR_INVALID_ARGUMENT:0
-
-PSA PAKE: ecjpake setup client bad password key usage
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_ENCRYPT:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_CLIENT:0:"abcd":0:0:PSA_ERROR_NOT_PERMITTED:0
-
-PSA PAKE: ecjpake setup invalid role NONE
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_NONE:0:"abcd":0:PSA_ERROR_NOT_SUPPORTED:0:0
-
-PSA PAKE: ecjpake rounds
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
-ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":0:0
-
-PSA PAKE: ecjpake rounds, client input first
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
-ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":1:0
-
-# This test case relies on implementation (it may need to be adjusted in the future)
-PSA PAKE: ecjpake rounds - key is destroyed after being passed to set_password_key
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
-ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":0:1
-
-PSA PAKE: ecjpake no input errors
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:0:"abcdef"
-
-PSA PAKE: ecjpake no input errors, client input first
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:0:"abcdef"
-
-PSA PAKE: ecjpake inject input errors, first round client
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:1:"abcdef"
-
-PSA PAKE: ecjpake inject input errors, first round client, client input first
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:1:1:"abcdef"
-
-PSA PAKE: ecjpake inject input errors, first round server
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:2:"abcdef"
-
-PSA PAKE: ecjpake inject input errors, first round server, client input first
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:1:2:"abcdef"
-
-PSA PAKE: ecjpake inject input errors, second round client
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:3:"abcdef"
-
-PSA PAKE: ecjpake inject input errors, second round client, client input first
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:1:3:"abcdef"
-
-PSA PAKE: ecjpake inject input errors, second round server
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:4:"abcdef"
-
-PSA PAKE: ecjpake inject input errors, second round server, client input first
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
-ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:1:4:"abcdef"
-
-PSA PAKE: ecjpake size macros
-depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
-ecjpake_size_macros:
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index 1f3b3b6..dbbac76 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -622,7 +622,7 @@
  *                                  the data in to be encrypted / decrypted. If
  *                                  -1, no chunking
  * \param expected_output           Expected output
- * \param is_verify                 If non-zero this is an verify operation.
+ * \param is_verify                 If non-zero this is a verify 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.
@@ -1319,6 +1319,24 @@
 }
 #endif /* PSA_WANT_ALG_JPAKE */
 
+typedef enum
+{
+    INJECT_ERR_NONE = 0,
+    INJECT_ERR_UNINITIALIZED_ACCESS,
+    INJECT_ERR_DUPLICATE_SETUP,
+    INJECT_ERR_INVALID_USER,
+    INJECT_ERR_INVALID_PEER,
+    INJECT_ERR_SET_USER,
+    INJECT_ERR_SET_PEER,
+    INJECT_EMPTY_IO_BUFFER,
+    INJECT_UNKNOWN_STEP,
+    INJECT_INVALID_FIRST_STEP,
+    INJECT_WRONG_BUFFER_SIZE,
+    INJECT_VALID_OPERATION_AFTER_FAILURE,
+    INJECT_ANTICIPATE_KEY_DERIVATION_1,
+    INJECT_ANTICIPATE_KEY_DERIVATION_2,
+} ecjpake_injected_failure_t;
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -6113,7 +6131,7 @@
 
     psa_aead_abort( &operation );
 
-    /* Test for calling set lengths with an plaintext length of SIZE_MAX, after setting nonce */
+    /* Test for calling set lengths with a plaintext length of SIZE_MAX, after setting nonce */
     PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
 
     PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
@@ -8754,11 +8772,9 @@
 /* BEGIN_CASE depends_on:PSA_WANT_ALG_JPAKE */
 void ecjpake_setup( int alg_arg, int key_type_pw_arg, int key_usage_pw_arg,
                     int primitive_arg, int hash_arg, int role_arg,
-                    int input_first, data_t *pw_data,
-                    int expected_status_setup_arg,
-                    int expected_status_set_role_arg,
-                    int expected_status_set_password_key_arg,
-                    int expected_status_input_output_arg)
+                    int test_input, data_t *pw_data,
+                    int inj_err_type_arg,
+                    int expected_error_arg)
 {
     psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
     psa_pake_operation_t operation = psa_pake_operation_init();
@@ -8770,12 +8786,9 @@
     psa_pake_role_t role = role_arg;
     mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_status_t expected_status_setup = expected_status_setup_arg;
-    psa_status_t expected_status_set_role = expected_status_set_role_arg;
-    psa_status_t expected_status_set_password_key =
-                        expected_status_set_password_key_arg;
-    psa_status_t expected_status_input_output =
-                        expected_status_input_output_arg;
+    ecjpake_injected_failure_t inj_err_type = inj_err_type_arg;
+    psa_status_t expected_error = expected_error_arg;
+    psa_status_t status;
     unsigned char *output_buffer = NULL;
     size_t output_len = 0;
 
@@ -8800,54 +8813,90 @@
 
     PSA_ASSERT( psa_pake_abort( &operation ) );
 
-    TEST_EQUAL( psa_pake_set_user( &operation, NULL, 0 ),
-                PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( psa_pake_set_peer( &operation, NULL, 0 ),
-                PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( psa_pake_set_password_key( &operation, key ),
-                PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( psa_pake_set_role( &operation, role ),
-                PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_KEY_SHARE,
-                                 NULL, 0, NULL ),
-                PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_KEY_SHARE, NULL, 0),
-                PSA_ERROR_BAD_STATE );
-
-    PSA_ASSERT( psa_pake_abort( &operation ) );
-
-    TEST_EQUAL( psa_pake_setup( &operation, &cipher_suite ),
-                expected_status_setup );
-    if( expected_status_setup != PSA_SUCCESS )
+    if ( inj_err_type == INJECT_ERR_UNINITIALIZED_ACCESS )
+    {
+        TEST_EQUAL( psa_pake_set_user( &operation, NULL, 0 ),
+                    expected_error );
+        PSA_ASSERT( psa_pake_abort( &operation ) );
+        TEST_EQUAL( psa_pake_set_peer( &operation, NULL, 0 ),
+                    expected_error );
+        PSA_ASSERT( psa_pake_abort( &operation ) );
+        TEST_EQUAL( psa_pake_set_password_key( &operation, key ),
+                    expected_error );
+        PSA_ASSERT( psa_pake_abort( &operation ) );
+        TEST_EQUAL( psa_pake_set_role( &operation, role ),
+                    expected_error );
+        PSA_ASSERT( psa_pake_abort( &operation ) );
+        TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_KEY_SHARE,
+                    NULL, 0, NULL ),
+                    expected_error );
+        PSA_ASSERT( psa_pake_abort( &operation ) );
+        TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_KEY_SHARE, NULL, 0),
+                    expected_error );
+        PSA_ASSERT( psa_pake_abort( &operation ) );
         goto exit;
+    }
 
-    TEST_EQUAL( psa_pake_setup( &operation, &cipher_suite ),
-                PSA_ERROR_BAD_STATE );
-
-    TEST_EQUAL( psa_pake_set_role( &operation, role),
-                expected_status_set_role );
-    if( expected_status_set_role != PSA_SUCCESS )
+    status = psa_pake_setup( &operation, &cipher_suite );
+    if (status != PSA_SUCCESS)
+    {
+        TEST_EQUAL( status, expected_error );
         goto exit;
+    }
+
+    if( inj_err_type == INJECT_ERR_DUPLICATE_SETUP )
+    {
+        TEST_EQUAL( psa_pake_setup( &operation, &cipher_suite ),
+                expected_error );
+        goto exit;
+    }
+
+    status = psa_pake_set_role( &operation, role);
+    if ( status != PSA_SUCCESS )
+    {
+        TEST_EQUAL( status, expected_error );
+        goto exit;
+    }
 
     if( pw_data->len > 0 )
     {
-        TEST_EQUAL( psa_pake_set_password_key( &operation, key ),
-                    expected_status_set_password_key );
-        if( expected_status_set_password_key != PSA_SUCCESS )
+        status = psa_pake_set_password_key( &operation, key );
+        if ( status != PSA_SUCCESS )
+        {
+            TEST_EQUAL( status, expected_error );
             goto exit;
+        }
     }
 
-    TEST_EQUAL( psa_pake_set_user( &operation, NULL, 0 ),
-                PSA_ERROR_INVALID_ARGUMENT );
-    TEST_EQUAL( psa_pake_set_peer( &operation, NULL, 0 ),
-                PSA_ERROR_INVALID_ARGUMENT );
+    if ( inj_err_type == INJECT_ERR_INVALID_USER )
+    {
+        TEST_EQUAL( psa_pake_set_user( &operation, NULL, 0 ),
+                    PSA_ERROR_INVALID_ARGUMENT );
+        goto exit;
+    }
 
-    const uint8_t unsupported_id[] = "abcd";
+    if ( inj_err_type == INJECT_ERR_INVALID_PEER )
+    {
+        TEST_EQUAL( psa_pake_set_peer( &operation, NULL, 0 ),
+                    PSA_ERROR_INVALID_ARGUMENT );
+        goto exit;
+    }
 
-    TEST_EQUAL( psa_pake_set_user( &operation, unsupported_id, 4 ),
-                PSA_ERROR_NOT_SUPPORTED );
-    TEST_EQUAL( psa_pake_set_peer( &operation, unsupported_id, 4 ),
-                PSA_ERROR_NOT_SUPPORTED );
+    if ( inj_err_type == INJECT_ERR_SET_USER )
+    {
+        const uint8_t unsupported_id[] = "abcd";
+        TEST_EQUAL( psa_pake_set_user( &operation, unsupported_id, 4 ),
+                    PSA_ERROR_NOT_SUPPORTED );
+        goto exit;
+    }
+
+    if ( inj_err_type == INJECT_ERR_SET_PEER )
+    {
+        const uint8_t unsupported_id[] = "abcd";
+        TEST_EQUAL( psa_pake_set_peer( &operation, unsupported_id, 4 ),
+                    PSA_ERROR_NOT_SUPPORTED );
+        goto exit;
+    }
 
     const size_t size_key_share = PSA_PAKE_INPUT_SIZE( alg, primitive,
                                                 PSA_PAKE_STEP_KEY_SHARE );
@@ -8856,85 +8905,109 @@
     const size_t size_zk_proof = PSA_PAKE_INPUT_SIZE( alg, primitive,
                                                 PSA_PAKE_STEP_ZK_PROOF );
 
-    /* First round */
-    if( input_first )
+    if ( test_input )
     {
-        /* Invalid parameters (input) */
-        TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PROOF,
-                                    NULL, 0 ),
-                    PSA_ERROR_INVALID_ARGUMENT );
-        /* Invalid parameters (step) */
-        TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role,
-                                 key, pw_data->len ) , 0 );
-        TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PROOF + 10,
-                                    output_buffer, size_zk_proof ),
-                    PSA_ERROR_INVALID_ARGUMENT );
-        /* Invalid first step */
-        TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role,
-                                 key, pw_data->len ), 0 );
-        TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PROOF,
-                                    output_buffer, size_zk_proof ),
-                    PSA_ERROR_BAD_STATE );
-
-        /* Possibly valid */
-        TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role,
-                                 key, pw_data->len ), 0 );
-        TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_KEY_SHARE,
-                                    output_buffer, size_key_share ),
-                    expected_status_input_output);
-
-        if( expected_status_input_output == PSA_SUCCESS )
+        if ( inj_err_type == INJECT_EMPTY_IO_BUFFER )
         {
-            /* Buffer too large */
-            TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PUBLIC,
-                                    output_buffer, size_zk_public + 1 ),
-                        PSA_ERROR_INVALID_ARGUMENT );
+            TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PROOF, NULL, 0 ),
+                                        PSA_ERROR_INVALID_ARGUMENT );
+            goto exit;
+        }
 
-            /* The operation's state should be invalidated at this point */
+        if ( inj_err_type == INJECT_UNKNOWN_STEP )
+        {
+            TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PROOF + 10,
+                                        output_buffer, size_zk_proof ),
+                                        PSA_ERROR_INVALID_ARGUMENT );
+            goto exit;
+        }
+
+        if ( inj_err_type == INJECT_INVALID_FIRST_STEP )
+        {
+            TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PROOF,
+                                        output_buffer, size_zk_proof ),
+                                        PSA_ERROR_BAD_STATE );
+            goto exit;
+        }
+
+        status = psa_pake_input( &operation, PSA_PAKE_STEP_KEY_SHARE,
+                                        output_buffer, size_key_share );
+        if ( status != PSA_SUCCESS )
+        {
+            TEST_EQUAL( status, expected_error);
+            goto exit;
+        }
+
+        if ( inj_err_type == INJECT_WRONG_BUFFER_SIZE )
+        {
+            TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PUBLIC,
+                                        output_buffer, size_zk_public + 1 ),
+                                        PSA_ERROR_INVALID_ARGUMENT );
+            goto exit;
+        }
+
+        if ( inj_err_type == INJECT_VALID_OPERATION_AFTER_FAILURE )
+        {
+            // Just trigger any kind of error. We don't care about the result here
+            psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PUBLIC,
+                                        output_buffer, size_zk_public + 1 );
             TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PUBLIC,
                                         output_buffer, size_zk_public ),
-                        PSA_ERROR_BAD_STATE );
+                                        PSA_ERROR_BAD_STATE );
+            goto exit;
         }
-    }
-    else
-    {
-        /* Invalid parameters (output) */
-        TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PROOF,
-                                     NULL, 0, NULL ),
-                    PSA_ERROR_INVALID_ARGUMENT );
-        /* Invalid parameters (step) */
-        TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role,
-                                key, pw_data->len ), 0 );
-        TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PROOF + 10,
-                                     output_buffer, buf_size, &output_len ),
-                    PSA_ERROR_INVALID_ARGUMENT );
-        /* Invalid first step */
-        TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role,
-                                 key, pw_data->len ), 0 );
-        TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PROOF,
-                                     output_buffer, buf_size, &output_len ),
-                    PSA_ERROR_BAD_STATE );
-
-        /* Possibly valid */
-        TEST_EQUAL( ecjpake_operation_setup( &operation, &cipher_suite, role,
-                                 key, pw_data->len ), 0 );
-        TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_KEY_SHARE,
-                                     output_buffer, buf_size, &output_len ),
-                    expected_status_input_output );
-
-        if( expected_status_input_output == PSA_SUCCESS )
+    } else {
+        if ( inj_err_type == INJECT_EMPTY_IO_BUFFER )
         {
-            TEST_ASSERT( output_len > 0 );
+            TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PROOF,
+                                        NULL, 0, NULL ),
+                                        PSA_ERROR_INVALID_ARGUMENT );
+            goto exit;
+        }
 
-            /* Buffer too small */
-            TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PUBLIC,
-                                         output_buffer, size_zk_public - 1, &output_len ),
-                        PSA_ERROR_BUFFER_TOO_SMALL );
+        if ( inj_err_type == INJECT_UNKNOWN_STEP )
+        {
+            TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PROOF + 10,
+                                        output_buffer, buf_size, &output_len ),
+                                        PSA_ERROR_INVALID_ARGUMENT );
+            goto exit;
+        }
 
-            /* The operation's state should be invalidated at this point */
+        if ( inj_err_type == INJECT_INVALID_FIRST_STEP )
+        {
+            TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PROOF,
+                                        output_buffer, buf_size, &output_len ),
+                                        PSA_ERROR_BAD_STATE );
+            goto exit;
+        }
+
+        status = psa_pake_output( &operation, PSA_PAKE_STEP_KEY_SHARE,
+                                    output_buffer, buf_size, &output_len );
+        if ( status != PSA_SUCCESS )
+        {
+            TEST_EQUAL( status, expected_error);
+            goto exit;
+        }
+
+        TEST_ASSERT( output_len > 0 );
+
+        if ( inj_err_type == INJECT_WRONG_BUFFER_SIZE )
+        {
             TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PUBLIC,
-                                         output_buffer, buf_size, &output_len ),
-                        PSA_ERROR_BAD_STATE );
+                                        output_buffer, size_zk_public - 1, &output_len ),
+                                        PSA_ERROR_BUFFER_TOO_SMALL );
+            goto exit;
+        }
+
+        if ( inj_err_type == INJECT_VALID_OPERATION_AFTER_FAILURE )
+        {
+            // Just trigger any kind of error. We don't care about the result here
+            psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PUBLIC,
+                                        output_buffer, size_zk_public - 1, &output_len );
+            TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PUBLIC,
+                                        output_buffer, buf_size, &output_len ),
+                                        PSA_ERROR_BAD_STATE );
+            goto exit;
         }
     }
 
@@ -9001,7 +9074,7 @@
 /* BEGIN_CASE depends_on:PSA_WANT_ALG_JPAKE */
 void ecjpake_rounds( int alg_arg, int primitive_arg, int hash_arg,
                      int derive_alg_arg, data_t *pw_data,
-                     int client_input_first, int destroy_key )
+                     int client_input_first, int inj_err_type_arg )
 {
     psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
     psa_pake_operation_t server = psa_pake_operation_init();
@@ -9015,6 +9088,7 @@
                             PSA_KEY_DERIVATION_OPERATION_INIT;
     psa_key_derivation_operation_t client_derive =
                             PSA_KEY_DERIVATION_OPERATION_INIT;
+    ecjpake_injected_failure_t inj_err_type = inj_err_type_arg;
 
     PSA_INIT( );
 
@@ -9052,22 +9126,27 @@
     PSA_ASSERT( psa_pake_set_password_key( &server, key ) );
     PSA_ASSERT( psa_pake_set_password_key( &client, key ) );
 
-    if( destroy_key == 1 )
-        psa_destroy_key( key );
-
-    TEST_EQUAL( psa_pake_get_implicit_key( &server, &server_derive ),
+    if( inj_err_type == INJECT_ANTICIPATE_KEY_DERIVATION_1 )
+    {
+        TEST_EQUAL( psa_pake_get_implicit_key( &server, &server_derive ),
                 PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( psa_pake_get_implicit_key( &client, &client_derive ),
+        TEST_EQUAL( psa_pake_get_implicit_key( &client, &client_derive ),
                 PSA_ERROR_BAD_STATE );
+        goto exit;
+    }
 
     /* First round */
     ecjpake_do_round( alg, primitive_arg, &server, &client,
                       client_input_first, 1, 0 );
 
-    TEST_EQUAL( psa_pake_get_implicit_key( &server, &server_derive ),
+    if ( inj_err_type == INJECT_ANTICIPATE_KEY_DERIVATION_2 )
+    {
+        TEST_EQUAL( psa_pake_get_implicit_key( &server, &server_derive ),
                 PSA_ERROR_BAD_STATE );
-    TEST_EQUAL( psa_pake_get_implicit_key( &client, &client_derive ),
+        TEST_EQUAL( psa_pake_get_implicit_key( &client, &client_derive ),
                 PSA_ERROR_BAD_STATE );
+        goto exit;
+    }
 
     /* Second round */
     ecjpake_do_round( alg, primitive_arg, &server, &client,
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.data b/tests/suites/test_suite_psa_crypto_driver_wrappers.data
index 0a8d595..6069a69 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.data
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.data
@@ -299,6 +299,22 @@
 depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY:MBEDTLS_PK_PARSE_C:MBEDTLS_PK_WRITE_C:PSA_WANT_ECC_SECP_R1_256
 export_key:PSA_ERROR_GENERIC_ERROR:"":PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1):"":PSA_ERROR_GENERIC_ERROR
 
+raw key agreement through driver: fake
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+key_agreement:PSA_ALG_ECDH:PSA_SUCCESS:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de":"0102030405":PSA_SUCCESS
+
+raw key agreement through driver: in-driver
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+key_agreement:PSA_ALG_ECDH:PSA_SUCCESS:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de":"":PSA_SUCCESS
+
+raw key agreement through driver: fallback
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256:MBEDTLS_PSA_BUILTIN_ALG_ECDH
+key_agreement:PSA_ALG_ECDH:PSA_ERROR_NOT_SUPPORTED:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de":"":PSA_SUCCESS
+
+raw key agreement through driver: error
+depends_on:PSA_WANT_ALG_ECDH:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:MBEDTLS_PK_PARSE_C:PSA_WANT_ECC_SECP_R1_256
+key_agreement:PSA_ALG_ECDH:PSA_ERROR_GENERIC_ERROR:PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1):"c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433":"04d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab":"d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de":"":PSA_ERROR_GENERIC_ERROR
+
 PSA symmetric encrypt validation: AES-CTR, 16 bytes, good
 depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES
 cipher_encrypt_validation:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"6bc1bee22e409f96e93d7e117393172a"
diff --git a/tests/suites/test_suite_psa_crypto_driver_wrappers.function b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
index 128352b..b713cb2 100644
--- a/tests/suites/test_suite_psa_crypto_driver_wrappers.function
+++ b/tests/suites/test_suite_psa_crypto_driver_wrappers.function
@@ -542,6 +542,94 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void key_agreement( int alg_arg,
+                    int force_status_arg,
+                    int our_key_type_arg,
+                    data_t *our_key_data,
+                    data_t *peer_key_data,
+                    data_t *expected_output,
+                    data_t* fake_output,
+                    int expected_status_arg )
+{
+    psa_status_t force_status = force_status_arg;
+    psa_status_t expected_status = expected_status_arg;
+    psa_algorithm_t alg = alg_arg;
+    psa_key_type_t our_key_type = our_key_type_arg;
+    mbedtls_svc_key_id_t our_key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    const uint8_t *expected_output_ptr = NULL;
+    size_t expected_output_length = 0;
+    unsigned char *actual_output = NULL;
+    size_t actual_output_length = ~0;
+    size_t key_bits;
+    psa_status_t actual_status;
+    mbedtls_test_driver_key_agreement_hooks =
+        mbedtls_test_driver_key_agreement_hooks_init();
+
+    PSA_ASSERT( psa_crypto_init( ) );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, our_key_type );
+    PSA_ASSERT( psa_import_key( &attributes,
+                                our_key_data->x, our_key_data->len,
+                                &our_key ) );
+
+    PSA_ASSERT( psa_get_key_attributes( our_key, &attributes ) );
+    key_bits = psa_get_key_bits( &attributes );
+
+    TEST_LE_U( expected_output->len,
+               PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE( our_key_type, key_bits ) );
+    TEST_LE_U( PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE( our_key_type, key_bits ),
+               PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE );
+
+    if( fake_output->len > 0 )
+    {
+        expected_output_ptr =
+            mbedtls_test_driver_key_agreement_hooks.forced_output =
+            fake_output->x;
+
+        expected_output_length =
+            mbedtls_test_driver_key_agreement_hooks.forced_output_length =
+            fake_output->len;
+    }
+    else
+    {
+        expected_output_ptr = expected_output->x;
+        expected_output_length = expected_output->len;
+    }
+
+    mbedtls_test_driver_key_agreement_hooks.hits = 0;
+    mbedtls_test_driver_key_agreement_hooks.forced_status = force_status;
+
+    ASSERT_ALLOC( actual_output, expected_output->len );
+    actual_status = psa_raw_key_agreement( alg, our_key,
+                                       peer_key_data->x, peer_key_data->len,
+                                       actual_output, expected_output->len,
+                                       &actual_output_length ) ;
+    TEST_EQUAL( actual_status, expected_status );
+    TEST_EQUAL( mbedtls_test_driver_key_agreement_hooks.hits, 1 );
+
+    if( actual_status == PSA_SUCCESS )
+    {
+        ASSERT_COMPARE( actual_output, actual_output_length,
+                        expected_output_ptr, expected_output_length);
+    }
+    mbedtls_free( actual_output );
+    actual_output = NULL;
+    actual_output_length = ~0;
+
+exit:
+    psa_reset_key_attributes( &attributes );
+    psa_destroy_key( our_key );
+    PSA_DONE( );
+    mbedtls_test_driver_key_agreement_hooks =
+        mbedtls_test_driver_key_agreement_hooks_init();
+}
+
+/* END_CASE */
+
+/* BEGIN_CASE */
 void cipher_encrypt_validation( int alg_arg,
                                 int key_type_arg,
                                 data_t *key_data,
@@ -660,14 +748,14 @@
     mbedtls_psa_cipher_operation_t mbedtls_operation =
             MBEDTLS_PSA_CIPHER_OPERATION_INIT;
 
-    mbedtls_transparent_test_driver_cipher_operation_t tranparent_operation =
+    mbedtls_transparent_test_driver_cipher_operation_t transparent_operation =
             MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT;
 
     mbedtls_opaque_test_driver_cipher_operation_t opaque_operation =
             MBEDTLS_OPAQUE_TEST_DRIVER_CIPHER_OPERATION_INIT;
 
     operation.ctx.mbedtls_ctx = mbedtls_operation;
-    operation.ctx.transparent_test_driver_ctx = tranparent_operation;
+    operation.ctx.transparent_test_driver_ctx = transparent_operation;
     operation.ctx.opaque_test_driver_ctx = opaque_operation;
 
     PSA_ASSERT( psa_crypto_init( ) );
@@ -792,14 +880,14 @@
     mbedtls_psa_cipher_operation_t mbedtls_operation =
             MBEDTLS_PSA_CIPHER_OPERATION_INIT;
 
-    mbedtls_transparent_test_driver_cipher_operation_t tranparent_operation =
+    mbedtls_transparent_test_driver_cipher_operation_t transparent_operation =
             MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT;
 
     mbedtls_opaque_test_driver_cipher_operation_t opaque_operation =
             MBEDTLS_OPAQUE_TEST_DRIVER_CIPHER_OPERATION_INIT;
 
     operation.ctx.mbedtls_ctx = mbedtls_operation;
-    operation.ctx.transparent_test_driver_ctx = tranparent_operation;
+    operation.ctx.transparent_test_driver_ctx = transparent_operation;
     operation.ctx.opaque_test_driver_ctx = opaque_operation;
 
     PSA_ASSERT( psa_crypto_init( ) );
diff --git a/tests/suites/test_suite_psa_crypto_generate_key.function b/tests/suites/test_suite_psa_crypto_generate_key.function
index dbe9a0e..6dc6043 100644
--- a/tests/suites/test_suite_psa_crypto_generate_key.function
+++ b/tests/suites/test_suite_psa_crypto_generate_key.function
@@ -18,7 +18,7 @@
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = INVALID_KEY_ID;
 
-    // key lifetiem, usage flags, algorithm are irrelevant for this test
+    // key lifetime, usage flags, algorithm are irrelevant for this test
     psa_key_type_t key_type = key_type_arg;
     size_t bits = bits_arg;
     psa_status_t expected_status = expected_status_arg;
diff --git a/tests/suites/test_suite_psa_crypto_pake.data b/tests/suites/test_suite_psa_crypto_pake.data
new file mode 100644
index 0000000..f447ef0
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_pake.data
@@ -0,0 +1,203 @@
+PSA PAKE: uninitialized access to psa_pake_operation_t
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_INJECT_UNINITIALIZED_ACCESS:PSA_ERROR_BAD_STATE
+
+PSA PAKE: invalid alg
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_SHA_256:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_IN_SETUP:PSA_ERROR_INVALID_ARGUMENT
+
+PSA PAKE: invalid primitive type
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_DH, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_IN_SETUP:PSA_ERROR_NOT_SUPPORTED
+
+PSA PAKE: invalid primitive family
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_K1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_IN_SETUP:PSA_ERROR_NOT_SUPPORTED
+
+PSA PAKE: invalid primitive bits
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 128):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_IN_SETUP:PSA_ERROR_NOT_SUPPORTED
+
+PSA PAKE: invalid hash
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_1:PSA_PAKE_ROLE_SERVER:0:ERR_IN_SETUP:PSA_ERROR_NOT_SUPPORTED
+
+PSA PAKE: duplicate a valid setup
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_INJECT_DUPLICATE_SETUP:PSA_ERROR_BAD_STATE
+
+PSA PAKE: ecjpake setup invalid role NONE
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_NONE:0:ERR_IN_SET_ROLE:PSA_ERROR_NOT_SUPPORTED
+
+PSA PAKE: wrong password key type
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_HMAC:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_IN_SET_PASSWORD_KEY:PSA_ERROR_INVALID_ARGUMENT
+
+PSA PAKE: wrong password key usage
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_ENCRYPT:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_IN_SET_PASSWORD_KEY:PSA_ERROR_NOT_PERMITTED
+
+PSA PAKE: set invalid user
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_INJECT_INVALID_USER:PSA_ERROR_INVALID_ARGUMENT
+
+PSA PAKE: set invalid peer
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_INJECT_INVALID_PEER:PSA_ERROR_INVALID_ARGUMENT
+
+PSA PAKE: set user
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_INJECT_SET_USER:PSA_ERROR_NOT_SUPPORTED
+
+PSA PAKE: set peer
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_INJECT_SET_PEER:PSA_ERROR_NOT_SUPPORTED
+
+PSA PAKE: invalid input
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:1:ERR_INJECT_EMPTY_IO_BUFFER:PSA_ERROR_INVALID_ARGUMENT
+
+PSA PAKE: unkown input step
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:1:ERR_INJECT_UNKNOWN_STEP:PSA_ERROR_INVALID_ARGUMENT
+
+PSA PAKE: invalid first input step
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:1:ERR_INJECT_INVALID_FIRST_STEP:PSA_ERROR_BAD_STATE
+
+PSA PAKE: input buffer too large
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:1:ERR_INJECT_WRONG_BUFFER_SIZE:PSA_ERROR_INVALID_ARGUMENT
+
+PSA PAKE: valid input operation after a failure
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:1:ERR_INJECT_VALID_OPERATION_AFTER_FAILURE:PSA_ERROR_BAD_STATE
+
+PSA PAKE: invalid output
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_INJECT_EMPTY_IO_BUFFER:PSA_ERROR_INVALID_ARGUMENT
+
+PSA PAKE: unkown output step
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_INJECT_UNKNOWN_STEP:PSA_ERROR_INVALID_ARGUMENT
+
+PSA PAKE: invalid first output step
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_INJECT_INVALID_FIRST_STEP:PSA_ERROR_BAD_STATE
+
+PSA PAKE: output buffer too small
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_INJECT_WRONG_BUFFER_SIZE:PSA_ERROR_BUFFER_TOO_SMALL
+
+PSA PAKE: valid output operation after a failure
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_setup:PSA_ALG_JPAKE:PSA_KEY_TYPE_PASSWORD:PSA_KEY_USAGE_DERIVE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_PAKE_ROLE_SERVER:0:ERR_INJECT_VALID_OPERATION_AFTER_FAILURE:PSA_ERROR_BAD_STATE
+
+PSA PAKE: check rounds w/o forced errors
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
+ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":0:0:ERR_NONE
+
+PSA PAKE: check rounds w/o forced errors, TLS12_PRF
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
+ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"abcdef":0:0:ERR_NONE
+
+PSA PAKE: check rounds, key is destroyed after being passed to set_password_key
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
+ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":0:1:ERR_NONE
+
+PSA PAKE: check rounds w/o forced errors, client input first
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
+ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":1:0:ERR_NONE
+
+PSA PAKE: force early key derivation 1
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
+ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":0:0:ERR_INJECT_ANTICIPATE_KEY_DERIVATION_1
+
+PSA PAKE: force early key derivation 2
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PSK_TO_MS
+ecjpake_rounds:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256):"abcdef":0:0:ERR_INJECT_ANTICIPATE_KEY_DERIVATION_2
+
+PSA PAKE: no injected errors
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_NONE:PSA_SUCCESS
+
+PSA PAKE: no injected errors, client input first
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:1:"abcdef":ERR_NONE:PSA_SUCCESS
+
+PSA PAKE: inject ERR_INJECT_ROUND1_CLIENT_KEY_SHARE_PART1
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND1_CLIENT_KEY_SHARE_PART1:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND1_CLIENT_ZK_PUBLIC_PART1
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND1_CLIENT_ZK_PUBLIC_PART1:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND1_CLIENT_ZK_PROOF_PART1
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND1_CLIENT_ZK_PROOF_PART1:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND1_CLIENT_KEY_SHARE_PART2
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND1_CLIENT_KEY_SHARE_PART2:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND1_CLIENT_ZK_PUBLIC_PART2
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND1_CLIENT_ZK_PUBLIC_PART2:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND1_CLIENT_ZK_PROOF_PART2
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND1_CLIENT_ZK_PROOF_PART2:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART1
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART1:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND1_SERVER_ZK_PUBLIC_PART1
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND1_SERVER_ZK_PUBLIC_PART1:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART1
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART1:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART2
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART2:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND1_SERVER_ZK_PUBLIC_PART2
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND1_SERVER_ZK_PUBLIC_PART2:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART2
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART2:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND2_CLIENT_KEY_SHARE
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND2_CLIENT_KEY_SHARE:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND2_CLIENT_ZK_PUBLIC
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND2_CLIENT_ZK_PUBLIC:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND2_CLIENT_ZK_PROOF
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND2_CLIENT_ZK_PROOF:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND2_SERVER_KEY_SHARE
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND2_SERVER_KEY_SHARE:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND2_SERVER_ZK_PUBLIC
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND2_SERVER_ZK_PUBLIC:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: inject ERR_INJECT_ROUND2_SERVER_ZK_PROOF
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256
+ecjpake_rounds_inject:PSA_ALG_JPAKE:PSA_PAKE_PRIMITIVE(PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, 256):PSA_ALG_SHA_256:0:"abcdef":ERR_INJECT_ROUND2_SERVER_ZK_PROOF:PSA_ERROR_DATA_INVALID
+
+PSA PAKE: ecjpake size macros
+depends_on:PSA_WANT_KEY_TYPE_ECC_KEY_PAIR:PSA_WANT_ECC_SECP_R1_256
+ecjpake_size_macros:
diff --git a/tests/suites/test_suite_psa_crypto_pake.function b/tests/suites/test_suite_psa_crypto_pake.function
new file mode 100644
index 0000000..4f000c1
--- /dev/null
+++ b/tests/suites/test_suite_psa_crypto_pake.function
@@ -0,0 +1,917 @@
+/* BEGIN_HEADER */
+#include <stdint.h>
+
+#include "psa/crypto.h"
+
+typedef enum
+{
+    ERR_NONE = 0,
+    /* errors forced internally in the code */
+    ERR_INJECT_UNINITIALIZED_ACCESS,
+    ERR_INJECT_DUPLICATE_SETUP,
+    ERR_INJECT_INVALID_USER,
+    ERR_INJECT_INVALID_PEER,
+    ERR_INJECT_SET_USER,
+    ERR_INJECT_SET_PEER,
+    ERR_INJECT_EMPTY_IO_BUFFER,
+    ERR_INJECT_UNKNOWN_STEP,
+    ERR_INJECT_INVALID_FIRST_STEP,
+    ERR_INJECT_WRONG_BUFFER_SIZE,
+    ERR_INJECT_VALID_OPERATION_AFTER_FAILURE,
+    ERR_INJECT_ANTICIPATE_KEY_DERIVATION_1,
+    ERR_INJECT_ANTICIPATE_KEY_DERIVATION_2,
+    ERR_INJECT_ROUND1_CLIENT_KEY_SHARE_PART1,
+    ERR_INJECT_ROUND1_CLIENT_ZK_PUBLIC_PART1,
+    ERR_INJECT_ROUND1_CLIENT_ZK_PROOF_PART1,
+    ERR_INJECT_ROUND1_CLIENT_KEY_SHARE_PART2,
+    ERR_INJECT_ROUND1_CLIENT_ZK_PUBLIC_PART2,
+    ERR_INJECT_ROUND1_CLIENT_ZK_PROOF_PART2,
+    ERR_INJECT_ROUND2_CLIENT_KEY_SHARE,
+    ERR_INJECT_ROUND2_CLIENT_ZK_PUBLIC,
+    ERR_INJECT_ROUND2_CLIENT_ZK_PROOF,
+    ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART1,
+    ERR_INJECT_ROUND1_SERVER_ZK_PUBLIC_PART1,
+    ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART1,
+    ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART2,
+    ERR_INJECT_ROUND1_SERVER_ZK_PUBLIC_PART2,
+    ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART2,
+    ERR_INJECT_ROUND2_SERVER_KEY_SHARE,
+    ERR_INJECT_ROUND2_SERVER_ZK_PUBLIC,
+    ERR_INJECT_ROUND2_SERVER_ZK_PROOF,
+    /* erros issued from the .data file */
+    ERR_IN_SETUP,
+    ERR_IN_SET_ROLE,
+    ERR_IN_SET_PASSWORD_KEY,
+    ERR_IN_INPUT,
+    ERR_IN_OUTPUT,
+} ecjpake_error_stage_t;
+
+typedef enum
+{
+    PAKE_ROUND_ONE,
+    PAKE_ROUND_TWO
+} pake_round_t;
+
+/*
+ * Inject an error on the specified buffer ONLY it this is the correct stage.
+ * Offset 7 is arbitrary, but chosen because it's "in the middle" of the part
+ * we're corrupting.
+ */
+#define DO_ROUND_CONDITIONAL_INJECT( this_stage, buf ) \
+    if ( this_stage == err_stage )                  \
+    {                                               \
+        *( buf + 7) ^= 1;                           \
+    }
+
+#define DO_ROUND_UPDATE_OFFSETS( main_buf_offset, step_offset, step_size ) \
+    {                                       \
+        step_offset = main_buf_offset;      \
+        main_buf_offset += step_size;        \
+    }
+
+#define DO_ROUND_CHECK_FAILURE(  )                                  \
+    if( err_stage != ERR_NONE && status != PSA_SUCCESS )            \
+    {                                                               \
+        TEST_EQUAL( status, expected_error_arg );                   \
+        break;                                                      \
+    }                                                               \
+    else                                                            \
+    {                                                               \
+        TEST_EQUAL( status, PSA_SUCCESS );                          \
+    }
+
+#if defined(PSA_WANT_ALG_JPAKE)
+static void ecjpake_do_round( psa_algorithm_t alg, unsigned int primitive,
+                              psa_pake_operation_t *server,
+                              psa_pake_operation_t *client,
+                              int client_input_first,
+                              pake_round_t round,
+                              ecjpake_error_stage_t err_stage,
+                              int expected_error_arg )
+{
+    unsigned char *buffer0 = NULL, *buffer1 = NULL;
+    size_t buffer_length = (
+        PSA_PAKE_OUTPUT_SIZE(alg, primitive, PSA_PAKE_STEP_KEY_SHARE) +
+        PSA_PAKE_OUTPUT_SIZE(alg, primitive, PSA_PAKE_STEP_ZK_PUBLIC) +
+        PSA_PAKE_OUTPUT_SIZE(alg, primitive, PSA_PAKE_STEP_ZK_PROOF)) * 2;
+    /* The output should be exactly this size according to the spec */
+    const size_t expected_size_key_share =
+        PSA_PAKE_OUTPUT_SIZE(alg, primitive, PSA_PAKE_STEP_KEY_SHARE);
+    /* The output should be exactly this size according to the spec */
+    const size_t expected_size_zk_public =
+        PSA_PAKE_OUTPUT_SIZE(alg, primitive, PSA_PAKE_STEP_ZK_PUBLIC);
+    /* The output can be smaller: the spec allows stripping leading zeroes */
+    const size_t max_expected_size_zk_proof =
+        PSA_PAKE_OUTPUT_SIZE(alg, primitive, PSA_PAKE_STEP_ZK_PROOF);
+    size_t buffer0_off = 0;
+    size_t buffer1_off = 0;
+    size_t s_g1_len, s_g2_len, s_a_len;
+    size_t s_g1_off, s_g2_off, s_a_off;
+    size_t s_x1_pk_len, s_x2_pk_len, s_x2s_pk_len;
+    size_t s_x1_pk_off, s_x2_pk_off, s_x2s_pk_off;
+    size_t s_x1_pr_len, s_x2_pr_len, s_x2s_pr_len;
+    size_t s_x1_pr_off, s_x2_pr_off, s_x2s_pr_off;
+    size_t c_g1_len, c_g2_len, c_a_len;
+    size_t c_g1_off, c_g2_off, c_a_off;
+    size_t c_x1_pk_len, c_x2_pk_len, c_x2s_pk_len;
+    size_t c_x1_pk_off, c_x2_pk_off, c_x2s_pk_off;
+    size_t c_x1_pr_len, c_x2_pr_len, c_x2s_pr_len;
+    size_t c_x1_pr_off, c_x2_pr_off, c_x2s_pr_off;
+    psa_status_t status;
+
+    ASSERT_ALLOC( buffer0, buffer_length );
+    ASSERT_ALLOC( buffer1, buffer_length );
+
+    switch( round )
+    {
+        case PAKE_ROUND_ONE:
+            /* Server first round Output */
+            PSA_ASSERT( psa_pake_output( server, PSA_PAKE_STEP_KEY_SHARE,
+                                         buffer0 + buffer0_off,
+                                         512 - buffer0_off, &s_g1_len ) );
+            TEST_EQUAL( s_g1_len, expected_size_key_share );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART1,
+                                    buffer0 + buffer0_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer0_off, s_g1_off, s_g1_len );
+
+            PSA_ASSERT( psa_pake_output( server, PSA_PAKE_STEP_ZK_PUBLIC,
+                                         buffer0 + buffer0_off,
+                                         512 - buffer0_off, &s_x1_pk_len ) );
+            TEST_EQUAL( s_x1_pk_len, expected_size_zk_public );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND1_SERVER_ZK_PUBLIC_PART1,
+                                    buffer0 + buffer0_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer0_off, s_x1_pk_off, s_x1_pk_len );
+
+            PSA_ASSERT( psa_pake_output( server, PSA_PAKE_STEP_ZK_PROOF,
+                                         buffer0 + buffer0_off,
+                                         512 - buffer0_off, &s_x1_pr_len ) );
+            TEST_LE_U( s_x1_pr_len, max_expected_size_zk_proof );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART1,
+                                    buffer0 + buffer0_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer0_off, s_x1_pr_off, s_x1_pr_len );
+
+            PSA_ASSERT( psa_pake_output( server, PSA_PAKE_STEP_KEY_SHARE,
+                                         buffer0 + buffer0_off,
+                                         512 - buffer0_off, &s_g2_len ) );
+            TEST_EQUAL( s_g2_len, expected_size_key_share );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART2,
+                                    buffer0 + buffer0_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer0_off, s_g2_off, s_g2_len );
+
+            PSA_ASSERT( psa_pake_output( server, PSA_PAKE_STEP_ZK_PUBLIC,
+                                         buffer0 + buffer0_off,
+                                         512 - buffer0_off, &s_x2_pk_len ) );
+            TEST_EQUAL( s_x2_pk_len, expected_size_zk_public );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND1_SERVER_ZK_PUBLIC_PART2,
+                                    buffer0 + buffer0_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer0_off, s_x2_pk_off, s_x2_pk_len );
+
+            PSA_ASSERT( psa_pake_output( server, PSA_PAKE_STEP_ZK_PROOF,
+                                         buffer0 + buffer0_off,
+                                         512 - buffer0_off, &s_x2_pr_len ) );
+            TEST_LE_U( s_x2_pr_len, max_expected_size_zk_proof );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART2,
+                                    buffer0 + buffer0_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer0_off, s_x2_pr_off, s_x2_pr_len );
+
+            /*
+             * When injecting errors in inputs, the implementation is
+             * free to detect it right away of with a delay.
+             * This permits delaying the error until the end of the input
+             * sequence, if no error appears then, this will be treated
+             * as an error.
+             */
+            if( client_input_first == 1 )
+            {
+                /* Client first round Input */
+                status = psa_pake_input( client, PSA_PAKE_STEP_KEY_SHARE,
+                                         buffer0 + s_g1_off, s_g1_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_ZK_PUBLIC,
+                                         buffer0 + s_x1_pk_off,
+                                         s_x1_pk_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_ZK_PROOF,
+                                         buffer0 + s_x1_pr_off,
+                                         s_x1_pr_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_KEY_SHARE,
+                                         buffer0 + s_g2_off,
+                                         s_g2_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_ZK_PUBLIC,
+                                         buffer0 + s_x2_pk_off,
+                                         s_x2_pk_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_ZK_PROOF,
+                                         buffer0 + s_x2_pr_off,
+                                         s_x2_pr_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                /* Error didn't trigger, make test fail */
+                if( ( err_stage >= ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART1 ) &&
+                    ( err_stage <= ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART2 ) )
+                {
+                    TEST_ASSERT( ! "One of the last psa_pake_input() calls should have returned the expected error." );
+                }
+            }
+
+            /* Client first round Output */
+            PSA_ASSERT( psa_pake_output( client, PSA_PAKE_STEP_KEY_SHARE,
+                                         buffer1 + buffer1_off,
+                                         512 - buffer1_off, &c_g1_len ) );
+            TEST_EQUAL( c_g1_len, expected_size_key_share );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND1_CLIENT_KEY_SHARE_PART1,
+                                    buffer1 + buffer1_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer1_off, c_g1_off, c_g1_len );
+
+            PSA_ASSERT( psa_pake_output( client, PSA_PAKE_STEP_ZK_PUBLIC,
+                                         buffer1 + buffer1_off,
+                                         512 - buffer1_off, &c_x1_pk_len ) );
+            TEST_EQUAL( c_x1_pk_len, expected_size_zk_public );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND1_CLIENT_ZK_PUBLIC_PART1,
+                                    buffer1 + buffer1_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer1_off, c_x1_pk_off, c_x1_pk_len );
+
+            PSA_ASSERT( psa_pake_output( client, PSA_PAKE_STEP_ZK_PROOF,
+                                         buffer1 + buffer1_off,
+                                         512 - buffer1_off, &c_x1_pr_len ) );
+            TEST_LE_U( c_x1_pr_len, max_expected_size_zk_proof );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND1_CLIENT_ZK_PROOF_PART1,
+                                    buffer1 + buffer1_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer1_off, c_x1_pr_off, c_x1_pr_len );
+
+            PSA_ASSERT( psa_pake_output( client, PSA_PAKE_STEP_KEY_SHARE,
+                                         buffer1 + buffer1_off,
+                                         512 - buffer1_off, &c_g2_len ) );
+            TEST_EQUAL( c_g2_len, expected_size_key_share );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND1_CLIENT_KEY_SHARE_PART2,
+                                    buffer1 + buffer1_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer1_off, c_g2_off, c_g2_len );
+
+            PSA_ASSERT( psa_pake_output( client, PSA_PAKE_STEP_ZK_PUBLIC,
+                                         buffer1 + buffer1_off,
+                                         512 - buffer1_off, &c_x2_pk_len ) );
+            TEST_EQUAL( c_x2_pk_len, expected_size_zk_public );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND1_CLIENT_ZK_PUBLIC_PART2,
+                                    buffer1 + buffer1_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer1_off, c_x2_pk_off, c_x2_pk_len );
+
+            PSA_ASSERT( psa_pake_output( client, PSA_PAKE_STEP_ZK_PROOF,
+                                         buffer1 + buffer1_off,
+                                         512 - buffer1_off, &c_x2_pr_len ) );
+            TEST_LE_U( c_x2_pr_len, max_expected_size_zk_proof );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND1_CLIENT_ZK_PROOF_PART2,
+                                    buffer1 + buffer1_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer1_off, c_x2_pr_off, buffer1_off );
+
+            if( client_input_first == 0 )
+            {
+                /* Client first round Input */
+                status = psa_pake_input( client, PSA_PAKE_STEP_KEY_SHARE,
+                                         buffer0 + s_g1_off, s_g1_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_ZK_PUBLIC,
+                                         buffer0 + s_x1_pk_off,
+                                         s_x1_pk_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_ZK_PROOF,
+                                         buffer0 + s_x1_pr_off,
+                                         s_x1_pr_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_KEY_SHARE,
+                                         buffer0 + s_g2_off,
+                                         s_g2_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_ZK_PUBLIC,
+                                         buffer0 + s_x2_pk_off,
+                                         s_x2_pk_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_ZK_PROOF,
+                                         buffer0 + s_x2_pr_off,
+                                         s_x2_pr_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                /* Error didn't trigger, make test fail */
+                if( ( err_stage >= ERR_INJECT_ROUND1_SERVER_KEY_SHARE_PART1 ) &&
+                    ( err_stage <= ERR_INJECT_ROUND1_SERVER_ZK_PROOF_PART2 ) )
+                {
+                    TEST_ASSERT( ! "One of the last psa_pake_input() calls should have returned the expected error." );
+                }
+            }
+
+            /* Server first round Input */
+            status = psa_pake_input( server, PSA_PAKE_STEP_KEY_SHARE,
+                                     buffer1 + c_g1_off, c_g1_len );
+            DO_ROUND_CHECK_FAILURE(  );
+
+            status = psa_pake_input( server, PSA_PAKE_STEP_ZK_PUBLIC,
+                                     buffer1 + c_x1_pk_off, c_x1_pk_len );
+            DO_ROUND_CHECK_FAILURE(  );
+
+            status = psa_pake_input( server, PSA_PAKE_STEP_ZK_PROOF,
+                                     buffer1 + c_x1_pr_off, c_x1_pr_len );
+            DO_ROUND_CHECK_FAILURE(  );
+
+            status = psa_pake_input( server, PSA_PAKE_STEP_KEY_SHARE,
+                                     buffer1 + c_g2_off, c_g2_len );
+            DO_ROUND_CHECK_FAILURE(  );
+
+            status = psa_pake_input( server, PSA_PAKE_STEP_ZK_PUBLIC,
+                                     buffer1 + c_x2_pk_off, c_x2_pk_len );
+            DO_ROUND_CHECK_FAILURE(  );
+
+            status = psa_pake_input( server, PSA_PAKE_STEP_ZK_PROOF,
+                                     buffer1 + c_x2_pr_off, c_x2_pr_len );
+            DO_ROUND_CHECK_FAILURE(  );
+
+            /* Error didn't trigger, make test fail */
+            if( ( err_stage >= ERR_INJECT_ROUND1_CLIENT_KEY_SHARE_PART1 ) &&
+                ( err_stage <= ERR_INJECT_ROUND1_CLIENT_ZK_PROOF_PART2 ) )
+            {
+                TEST_ASSERT( ! "One of the last psa_pake_input() calls should have returned the expected error." );
+            }
+
+            break;
+
+        case PAKE_ROUND_TWO:
+            /* Server second round Output */
+            buffer0_off = 0;
+
+            PSA_ASSERT( psa_pake_output( server, PSA_PAKE_STEP_KEY_SHARE,
+                                         buffer0 + buffer0_off,
+                                         512 - buffer0_off, &s_a_len ) );
+            TEST_EQUAL( s_a_len, expected_size_key_share );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND2_SERVER_KEY_SHARE,
+                                    buffer0 + buffer0_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer0_off, s_a_off, s_a_len );
+
+            PSA_ASSERT( psa_pake_output( server, PSA_PAKE_STEP_ZK_PUBLIC,
+                                         buffer0 + buffer0_off,
+                                         512 - buffer0_off, &s_x2s_pk_len ) );
+            TEST_EQUAL( s_x2s_pk_len, expected_size_zk_public );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND2_SERVER_ZK_PUBLIC,
+                                    buffer0 + buffer0_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer0_off, s_x2s_pk_off, s_x2s_pk_len );
+
+            PSA_ASSERT( psa_pake_output( server, PSA_PAKE_STEP_ZK_PROOF,
+                                         buffer0 + buffer0_off,
+                                         512 - buffer0_off, &s_x2s_pr_len ) );
+            TEST_LE_U( s_x2s_pr_len, max_expected_size_zk_proof );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND2_SERVER_ZK_PROOF,
+                                    buffer0 + buffer0_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer0_off, s_x2s_pr_off, s_x2s_pr_len );
+
+            if( client_input_first == 1 )
+            {
+                /* Client second round Input */
+                status = psa_pake_input( client, PSA_PAKE_STEP_KEY_SHARE,
+                                         buffer0 + s_a_off, s_a_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_ZK_PUBLIC,
+                                         buffer0 + s_x2s_pk_off,
+                                         s_x2s_pk_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_ZK_PROOF,
+                                         buffer0 + s_x2s_pr_off,
+                                         s_x2s_pr_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                /* Error didn't trigger, make test fail */
+                if( ( err_stage >= ERR_INJECT_ROUND2_SERVER_KEY_SHARE ) &&
+                    ( err_stage <= ERR_INJECT_ROUND2_SERVER_ZK_PROOF ) )
+                {
+                    TEST_ASSERT( ! "One of the last psa_pake_input() calls should have returned the expected error." );
+                }
+            }
+
+            /* Client second round Output */
+            buffer1_off = 0;
+
+            PSA_ASSERT( psa_pake_output( client, PSA_PAKE_STEP_KEY_SHARE,
+                                         buffer1 + buffer1_off,
+                                         512 - buffer1_off, &c_a_len ) );
+            TEST_EQUAL( c_a_len, expected_size_key_share );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND2_CLIENT_KEY_SHARE,
+                                    buffer1 + buffer1_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer1_off, c_a_off, c_a_len );
+
+            PSA_ASSERT( psa_pake_output( client, PSA_PAKE_STEP_ZK_PUBLIC,
+                                         buffer1 + buffer1_off,
+                                         512 - buffer1_off, &c_x2s_pk_len ) );
+            TEST_EQUAL( c_x2s_pk_len, expected_size_zk_public );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND2_CLIENT_ZK_PUBLIC,
+                                    buffer1 + buffer1_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer1_off, c_x2s_pk_off, c_x2s_pk_len );
+
+            PSA_ASSERT( psa_pake_output( client, PSA_PAKE_STEP_ZK_PROOF,
+                                         buffer1 + buffer1_off,
+                                         512 - buffer1_off, &c_x2s_pr_len ) );
+            TEST_LE_U( c_x2s_pr_len, max_expected_size_zk_proof );
+            DO_ROUND_CONDITIONAL_INJECT(
+                                    ERR_INJECT_ROUND2_CLIENT_ZK_PROOF,
+                                    buffer1 + buffer1_off );
+            DO_ROUND_UPDATE_OFFSETS( buffer1_off, c_x2s_pr_off, c_x2s_pr_len );
+
+            if( client_input_first == 0 )
+            {
+                /* Client second round Input */
+                status = psa_pake_input( client, PSA_PAKE_STEP_KEY_SHARE,
+                                         buffer0 + s_a_off, s_a_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_ZK_PUBLIC,
+                                         buffer0 + s_x2s_pk_off,
+                                         s_x2s_pk_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                status = psa_pake_input( client, PSA_PAKE_STEP_ZK_PROOF,
+                                         buffer0 + s_x2s_pr_off,
+                                         s_x2s_pr_len );
+                DO_ROUND_CHECK_FAILURE(  );
+
+                /* Error didn't trigger, make test fail */
+                if( ( err_stage >= ERR_INJECT_ROUND2_SERVER_KEY_SHARE ) &&
+                    ( err_stage <= ERR_INJECT_ROUND2_SERVER_ZK_PROOF ) )
+                {
+                    TEST_ASSERT( ! "One of the last psa_pake_input() calls should have returned the expected error." );
+                }
+            }
+
+            /* Server second round Input */
+            status = psa_pake_input( server, PSA_PAKE_STEP_KEY_SHARE,
+                                     buffer1 + c_a_off, c_a_len );
+            DO_ROUND_CHECK_FAILURE(  );
+
+            status = psa_pake_input( server, PSA_PAKE_STEP_ZK_PUBLIC,
+                                     buffer1 + c_x2s_pk_off, c_x2s_pk_len );
+            DO_ROUND_CHECK_FAILURE(  );
+
+            status = psa_pake_input( server, PSA_PAKE_STEP_ZK_PROOF,
+                                     buffer1 + c_x2s_pr_off, c_x2s_pr_len );
+            DO_ROUND_CHECK_FAILURE(  );
+
+            /* Error didn't trigger, make test fail */
+            if( ( err_stage >= ERR_INJECT_ROUND2_CLIENT_KEY_SHARE ) &&
+                ( err_stage <= ERR_INJECT_ROUND2_CLIENT_ZK_PROOF ) )
+            {
+                TEST_ASSERT( ! "One of the last psa_pake_input() calls should have returned the expected error." );
+            }
+
+            break;
+
+    }
+
+exit:
+    mbedtls_free( buffer0 );
+    mbedtls_free( buffer1 );
+}
+#endif /* PSA_WANT_ALG_JPAKE */
+
+/*
+ * This check is used for functions that might either succeed or fail depending
+ * on the parameters that are passed in from the *.data file:
+ * - in case of success following functions depend on the current one
+ * - in case of failure the test is always terminated. There are two options
+ *   here
+ *     - terminated successfully if this exact error was expected at this stage
+ *     - terminated with failure otherwise (either no error was expected at this
+ *       stage or a different error code was expected)
+ */
+#define SETUP_ALWAYS_CHECK_STEP( test_function, this_check_err_stage )      \
+    status = test_function;                                                 \
+    if( err_stage != this_check_err_stage )                                 \
+    {                                                                       \
+        PSA_ASSERT( status );                                               \
+    }                                                                       \
+    else                                                                    \
+    {                                                                       \
+        TEST_EQUAL( status, expected_error );                               \
+        goto exit;                                                          \
+    }
+
+/*
+ * This check is used for failures that are injected at code level. There's only
+ * 1 input parameter that is relevant in this case and it's the stage at which
+ * the error should be injected.
+ * The check is conditional in this case because, once the error is triggered,
+ * the pake's context structure is compromised and the setup function cannot
+ * proceed further. As a consequence the test is terminated.
+ * The test succeeds if the returned error is exactly the expected one,
+ * otherwise it fails.
+ */
+#define SETUP_CONDITIONAL_CHECK_STEP( test_function, this_check_err_stage ) \
+    if( err_stage == this_check_err_stage )                                 \
+    {                                                                       \
+        TEST_EQUAL( test_function, expected_error );                        \
+        goto exit;                                                          \
+    }
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_PSA_CRYPTO_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_JPAKE */
+void ecjpake_setup( int alg_arg, int key_type_pw_arg, int key_usage_pw_arg,
+                    int primitive_arg, int hash_arg, int role_arg,
+                    int test_input,
+                    int err_stage_arg,
+                    int expected_error_arg)
+{
+    psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
+    psa_pake_operation_t operation = psa_pake_operation_init();
+    psa_algorithm_t alg = alg_arg;
+    psa_pake_primitive_t primitive = primitive_arg;
+    psa_key_type_t key_type_pw = key_type_pw_arg;
+    psa_key_usage_t key_usage_pw = key_usage_pw_arg;
+    psa_algorithm_t hash_alg = hash_arg;
+    psa_pake_role_t role = role_arg;
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    ecjpake_error_stage_t err_stage = err_stage_arg;
+    psa_status_t expected_error = expected_error_arg;
+    psa_status_t status;
+    unsigned char *output_buffer = NULL;
+    size_t output_len = 0;
+    const uint8_t unsupp_id[] = "abcd";
+    const uint8_t password[] = "abcd";
+    psa_key_derivation_operation_t key_derivation =
+                            PSA_KEY_DERIVATION_OPERATION_INIT;
+
+    PSA_INIT( );
+
+    size_t buf_size = PSA_PAKE_OUTPUT_SIZE( alg, primitive_arg,
+                                       PSA_PAKE_STEP_KEY_SHARE );
+    ASSERT_ALLOC( output_buffer, buf_size );
+
+    psa_set_key_usage_flags( &attributes, key_usage_pw );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, key_type_pw );
+    PSA_ASSERT( psa_import_key( &attributes, password, sizeof( password ),
+                &key ) );
+
+    psa_pake_cs_set_algorithm( &cipher_suite, alg );
+    psa_pake_cs_set_primitive( &cipher_suite, primitive );
+    psa_pake_cs_set_hash( &cipher_suite, hash_alg );
+
+    PSA_ASSERT( psa_pake_abort( &operation ) );
+
+    if ( err_stage == ERR_INJECT_UNINITIALIZED_ACCESS )
+    {
+        TEST_EQUAL( psa_pake_set_user( &operation, NULL, 0 ),
+                    expected_error );
+        TEST_EQUAL( psa_pake_set_peer( &operation, NULL, 0 ),
+                    expected_error );
+        TEST_EQUAL( psa_pake_set_password_key( &operation, key ),
+                    expected_error );
+        TEST_EQUAL( psa_pake_set_role( &operation, role ),
+                    expected_error );
+        TEST_EQUAL( psa_pake_output( &operation, PSA_PAKE_STEP_KEY_SHARE,
+                    NULL, 0, NULL ),
+                    expected_error );
+        TEST_EQUAL( psa_pake_input( &operation, PSA_PAKE_STEP_KEY_SHARE,
+                    NULL, 0 ),
+                    expected_error );
+        TEST_EQUAL( psa_pake_get_implicit_key( &operation, &key_derivation ),
+                    expected_error );
+        goto exit;
+    }
+
+    SETUP_ALWAYS_CHECK_STEP( psa_pake_setup( &operation, &cipher_suite ),
+                            ERR_IN_SETUP );
+
+    SETUP_CONDITIONAL_CHECK_STEP( psa_pake_setup( &operation, &cipher_suite ),
+                                    ERR_INJECT_DUPLICATE_SETUP);
+
+    SETUP_ALWAYS_CHECK_STEP( psa_pake_set_role( &operation, role),
+                                ERR_IN_SET_ROLE );
+
+    SETUP_ALWAYS_CHECK_STEP( psa_pake_set_password_key( &operation, key ),
+                                ERR_IN_SET_PASSWORD_KEY );
+
+    SETUP_CONDITIONAL_CHECK_STEP( psa_pake_set_user( &operation, NULL, 0 ),
+                                    ERR_INJECT_INVALID_USER );
+
+    SETUP_CONDITIONAL_CHECK_STEP( psa_pake_set_peer( &operation, NULL, 0 ),
+                                    ERR_INJECT_INVALID_PEER );
+
+    SETUP_CONDITIONAL_CHECK_STEP( psa_pake_set_user( &operation, unsupp_id, 4 ),
+                                    ERR_INJECT_SET_USER );
+
+    SETUP_CONDITIONAL_CHECK_STEP( psa_pake_set_peer( &operation, unsupp_id, 4 ),
+                                    ERR_INJECT_SET_PEER );
+
+    const size_t size_key_share = PSA_PAKE_INPUT_SIZE( alg, primitive,
+                                                PSA_PAKE_STEP_KEY_SHARE );
+    const size_t size_zk_public = PSA_PAKE_INPUT_SIZE( alg, primitive,
+                                                PSA_PAKE_STEP_ZK_PUBLIC );
+    const size_t size_zk_proof = PSA_PAKE_INPUT_SIZE( alg, primitive,
+                                                PSA_PAKE_STEP_ZK_PROOF );
+
+    if ( test_input )
+    {
+        SETUP_CONDITIONAL_CHECK_STEP( psa_pake_input( &operation,
+                                        PSA_PAKE_STEP_ZK_PROOF,  NULL, 0 ),
+                                        ERR_INJECT_EMPTY_IO_BUFFER );
+
+        SETUP_CONDITIONAL_CHECK_STEP( psa_pake_input( &operation,
+                                        PSA_PAKE_STEP_ZK_PROOF + 10,
+                                        output_buffer, size_zk_proof ),
+                                        ERR_INJECT_UNKNOWN_STEP );
+
+        SETUP_CONDITIONAL_CHECK_STEP( psa_pake_input( &operation,
+                                        PSA_PAKE_STEP_ZK_PROOF,
+                                        output_buffer, size_zk_proof ),
+                                        ERR_INJECT_INVALID_FIRST_STEP )
+
+        SETUP_ALWAYS_CHECK_STEP( psa_pake_input( &operation,
+                                    PSA_PAKE_STEP_KEY_SHARE,
+                                    output_buffer, size_key_share ),
+                                    ERR_IN_INPUT );
+
+        SETUP_CONDITIONAL_CHECK_STEP( psa_pake_input( &operation,
+                                        PSA_PAKE_STEP_ZK_PUBLIC,
+                                        output_buffer, size_zk_public + 1 ),
+                                        ERR_INJECT_WRONG_BUFFER_SIZE );
+
+        SETUP_CONDITIONAL_CHECK_STEP(
+                  ( psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PUBLIC,
+                                        output_buffer, size_zk_public + 1 ),
+                    psa_pake_input( &operation, PSA_PAKE_STEP_ZK_PUBLIC,
+                                        output_buffer, size_zk_public ) ),
+                    ERR_INJECT_VALID_OPERATION_AFTER_FAILURE );
+    } else {
+        SETUP_CONDITIONAL_CHECK_STEP( psa_pake_output( &operation,
+                                        PSA_PAKE_STEP_ZK_PROOF,
+                                        NULL, 0, NULL ),
+                                        ERR_INJECT_EMPTY_IO_BUFFER );
+
+        SETUP_CONDITIONAL_CHECK_STEP( psa_pake_output( &operation,
+                                        PSA_PAKE_STEP_ZK_PROOF + 10,
+                                        output_buffer, buf_size, &output_len ),
+                                        ERR_INJECT_UNKNOWN_STEP );
+
+        SETUP_CONDITIONAL_CHECK_STEP( psa_pake_output( &operation,
+                                        PSA_PAKE_STEP_ZK_PROOF,
+                                        output_buffer, buf_size, &output_len ),
+                                        ERR_INJECT_INVALID_FIRST_STEP );
+
+        SETUP_ALWAYS_CHECK_STEP( psa_pake_output( &operation,
+                                    PSA_PAKE_STEP_KEY_SHARE,
+                                    output_buffer, buf_size, &output_len ),
+                                    ERR_IN_OUTPUT );
+
+        TEST_ASSERT( output_len > 0 );
+
+        SETUP_CONDITIONAL_CHECK_STEP( psa_pake_output( &operation,
+                                        PSA_PAKE_STEP_ZK_PUBLIC,
+                                        output_buffer, size_zk_public - 1,
+                                        &output_len ),
+                                        ERR_INJECT_WRONG_BUFFER_SIZE );
+
+        SETUP_CONDITIONAL_CHECK_STEP(
+              ( psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PUBLIC,
+                        output_buffer, size_zk_public - 1, &output_len ),
+                psa_pake_output( &operation, PSA_PAKE_STEP_ZK_PUBLIC,
+                                        output_buffer, buf_size, &output_len ) ),
+                ERR_INJECT_VALID_OPERATION_AFTER_FAILURE );
+    }
+
+exit:
+    PSA_ASSERT( psa_destroy_key( key ) );
+    PSA_ASSERT( psa_pake_abort( &operation ) );
+    mbedtls_free( output_buffer );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_JPAKE */
+void ecjpake_rounds_inject( int alg_arg, int primitive_arg, int hash_arg,
+                            int client_input_first,
+                            data_t *pw_data,
+                            int err_stage_arg,
+                            int expected_error_arg )
+{
+    psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
+    psa_pake_operation_t server = psa_pake_operation_init();
+    psa_pake_operation_t client = psa_pake_operation_init();
+    psa_algorithm_t alg = alg_arg;
+    psa_algorithm_t hash_alg = hash_arg;
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    ecjpake_error_stage_t err_stage = err_stage_arg;
+
+    PSA_INIT( );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_PASSWORD );
+    PSA_ASSERT( psa_import_key( &attributes, pw_data->x, pw_data->len,
+                &key ) );
+
+    psa_pake_cs_set_algorithm( &cipher_suite, alg );
+    psa_pake_cs_set_primitive( &cipher_suite, primitive_arg );
+    psa_pake_cs_set_hash( &cipher_suite, hash_alg );
+
+    PSA_ASSERT( psa_pake_setup( &server, &cipher_suite ) );
+    PSA_ASSERT( psa_pake_setup( &client, &cipher_suite ) );
+
+    PSA_ASSERT( psa_pake_set_role( &server, PSA_PAKE_ROLE_SERVER ) );
+    PSA_ASSERT( psa_pake_set_role( &client, PSA_PAKE_ROLE_CLIENT ) );
+
+    PSA_ASSERT( psa_pake_set_password_key( &server, key ) );
+    PSA_ASSERT( psa_pake_set_password_key( &client, key ) );
+
+    ecjpake_do_round( alg, primitive_arg, &server, &client,
+                      client_input_first, PAKE_ROUND_ONE,
+                      err_stage, expected_error_arg );
+
+    if( err_stage != ERR_NONE )
+        goto exit;
+
+    ecjpake_do_round( alg, primitive_arg, &server, &client,
+                      client_input_first, PAKE_ROUND_TWO,
+                      err_stage, expected_error_arg );
+
+exit:
+    psa_destroy_key( key );
+    psa_pake_abort( &server );
+    psa_pake_abort( &client );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:PSA_WANT_ALG_JPAKE */
+void ecjpake_rounds( int alg_arg, int primitive_arg, int hash_arg,
+                     int derive_alg_arg, data_t *pw_data,
+                     int client_input_first, int destroy_key,
+                     int err_stage_arg )
+{
+    psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
+    psa_pake_operation_t server = psa_pake_operation_init();
+    psa_pake_operation_t client = psa_pake_operation_init();
+    psa_algorithm_t alg = alg_arg;
+    psa_algorithm_t hash_alg = hash_arg;
+    psa_algorithm_t derive_alg = derive_alg_arg;
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_derivation_operation_t server_derive =
+                            PSA_KEY_DERIVATION_OPERATION_INIT;
+    psa_key_derivation_operation_t client_derive =
+                            PSA_KEY_DERIVATION_OPERATION_INIT;
+    ecjpake_error_stage_t err_stage = err_stage_arg;
+
+    PSA_INIT( );
+
+    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE );
+    psa_set_key_algorithm( &attributes, alg );
+    psa_set_key_type( &attributes, PSA_KEY_TYPE_PASSWORD );
+    PSA_ASSERT( psa_import_key( &attributes, pw_data->x, pw_data->len,
+                &key ) );
+
+    psa_pake_cs_set_algorithm( &cipher_suite, alg );
+    psa_pake_cs_set_primitive( &cipher_suite, primitive_arg );
+    psa_pake_cs_set_hash( &cipher_suite, hash_alg );
+
+    /* Get shared key */
+    PSA_ASSERT( psa_key_derivation_setup( &server_derive, derive_alg ) );
+    PSA_ASSERT( psa_key_derivation_setup( &client_derive, derive_alg ) );
+
+    if( PSA_ALG_IS_TLS12_PRF( derive_alg ) ||
+        PSA_ALG_IS_TLS12_PSK_TO_MS( derive_alg ) )
+    {
+        PSA_ASSERT( psa_key_derivation_input_bytes( &server_derive,
+                                                PSA_KEY_DERIVATION_INPUT_SEED,
+                                                (const uint8_t*) "", 0) );
+        PSA_ASSERT( psa_key_derivation_input_bytes( &client_derive,
+                                                PSA_KEY_DERIVATION_INPUT_SEED,
+                                                (const uint8_t*) "", 0) );
+    }
+
+    PSA_ASSERT( psa_pake_setup( &server, &cipher_suite ) );
+    PSA_ASSERT( psa_pake_setup( &client, &cipher_suite ) );
+
+    PSA_ASSERT( psa_pake_set_role( &server, PSA_PAKE_ROLE_SERVER ) );
+    PSA_ASSERT( psa_pake_set_role( &client, PSA_PAKE_ROLE_CLIENT ) );
+
+    PSA_ASSERT( psa_pake_set_password_key( &server, key ) );
+    PSA_ASSERT( psa_pake_set_password_key( &client, key ) );
+
+    if( destroy_key == 1 )
+        psa_destroy_key( key );
+
+    if( err_stage == ERR_INJECT_ANTICIPATE_KEY_DERIVATION_1 )
+    {
+        TEST_EQUAL( psa_pake_get_implicit_key( &server, &server_derive ),
+                PSA_ERROR_BAD_STATE );
+        TEST_EQUAL( psa_pake_get_implicit_key( &client, &client_derive ),
+                PSA_ERROR_BAD_STATE );
+        goto exit;
+    }
+
+    /* First round */
+    ecjpake_do_round( alg, primitive_arg, &server, &client,
+                      client_input_first, PAKE_ROUND_ONE,
+                      ERR_NONE, PSA_SUCCESS );
+
+    if ( err_stage == ERR_INJECT_ANTICIPATE_KEY_DERIVATION_2 )
+    {
+        TEST_EQUAL( psa_pake_get_implicit_key( &server, &server_derive ),
+                PSA_ERROR_BAD_STATE );
+        TEST_EQUAL( psa_pake_get_implicit_key( &client, &client_derive ),
+                PSA_ERROR_BAD_STATE );
+        goto exit;
+    }
+
+    /* Second round */
+    ecjpake_do_round( alg, primitive_arg, &server, &client,
+                      client_input_first, PAKE_ROUND_TWO,
+                      ERR_NONE, PSA_SUCCESS );
+
+    PSA_ASSERT( psa_pake_get_implicit_key( &server, &server_derive ) );
+    PSA_ASSERT( psa_pake_get_implicit_key( &client, &client_derive ) );
+
+exit:
+    psa_key_derivation_abort( &server_derive );
+    psa_key_derivation_abort( &client_derive );
+    psa_destroy_key( key );
+    psa_pake_abort( &server );
+    psa_pake_abort( &client );
+    PSA_DONE( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void ecjpake_size_macros( )
+{
+    const psa_algorithm_t alg = PSA_ALG_JPAKE;
+    const size_t bits = 256;
+    const psa_pake_primitive_t prim = PSA_PAKE_PRIMITIVE(
+            PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, bits );
+    const psa_key_type_t key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(
+            PSA_ECC_FAMILY_SECP_R1 );
+
+    // https://armmbed.github.io/mbed-crypto/1.1_PAKE_Extension.0-bet.0/html/pake.html#pake-step-types
+    /* The output for KEY_SHARE and ZK_PUBLIC is the same as a public key */
+    TEST_EQUAL( PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_KEY_SHARE),
+                PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( key_type, bits ) );
+    TEST_EQUAL( PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PUBLIC),
+                PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( key_type, bits ) );
+    /* The output for ZK_PROOF is the same bitsize as the curve */
+    TEST_EQUAL( PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PROOF),
+                PSA_BITS_TO_BYTES( bits ) );
+
+    /* Input sizes are the same as output sizes */
+    TEST_EQUAL( PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_KEY_SHARE),
+                PSA_PAKE_INPUT_SIZE(alg, prim, PSA_PAKE_STEP_KEY_SHARE) );
+    TEST_EQUAL( PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PUBLIC),
+                PSA_PAKE_INPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PUBLIC) );
+    TEST_EQUAL( PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PROOF),
+                PSA_PAKE_INPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PROOF) );
+
+    /* These inequalities will always hold even when other PAKEs are added */
+    TEST_LE_U( PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_KEY_SHARE),
+               PSA_PAKE_OUTPUT_MAX_SIZE );
+    TEST_LE_U( PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PUBLIC),
+               PSA_PAKE_OUTPUT_MAX_SIZE );
+    TEST_LE_U( PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PROOF),
+               PSA_PAKE_OUTPUT_MAX_SIZE );
+    TEST_LE_U( PSA_PAKE_INPUT_SIZE(alg, prim, PSA_PAKE_STEP_KEY_SHARE),
+               PSA_PAKE_INPUT_MAX_SIZE );
+    TEST_LE_U( PSA_PAKE_INPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PUBLIC),
+               PSA_PAKE_INPUT_MAX_SIZE );
+    TEST_LE_U( PSA_PAKE_INPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PROOF),
+               PSA_PAKE_INPUT_MAX_SIZE );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_psa_crypto_persistent_key.function b/tests/suites/test_suite_psa_crypto_persistent_key.function
index 08db34a..bb87923 100644
--- a/tests/suites/test_suite_psa_crypto_persistent_key.function
+++ b/tests/suites/test_suite_psa_crypto_persistent_key.function
@@ -2,7 +2,7 @@
 
 /* The tests in this module verify the contents of key store files. They
  * access internal key storage functions directly. Some of the tests depend
- * on the the storage format. On the other hand, these tests treat the storage
+ * on the storage format. On the other hand, these tests treat the storage
  * subsystem as a black box, and in particular have no reliance on the
  * internals of the ITS implementation.
  *
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index a35762d..a7f0501 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -417,59 +417,59 @@
 handshake_ciphersuite_select:"TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384":MBEDTLS_PK_RSA:"":PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH):PSA_ALG_NONE:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:0
 
 Handshake, select ECDHE-ECDSA-WITH-AES-256-CCM, non-opaque
-depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_AES_C:MBEDTLS_CCM_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_AES_C:MBEDTLS_CCM_C:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
 handshake_ciphersuite_select:"TLS-ECDHE-ECDSA-WITH-AES-256-CCM":MBEDTLS_PK_ECDSA:"":PSA_ALG_NONE:PSA_ALG_NONE:0:0:MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM
 
 Handshake, select ECDHE-ECDSA-WITH-AES-256-CCM, opaque, PSA_ALG_ANY_HASH
-depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_AES_C:MBEDTLS_CCM_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_AES_C:MBEDTLS_CCM_C:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
 handshake_ciphersuite_select:"TLS-ECDHE-ECDSA-WITH-AES-256-CCM":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_NONE:PSA_KEY_USAGE_SIGN_HASH:0:MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM
 
 Handshake, select ECDHE-ECDSA-WITH-AES-256-CCM, opaque, PSA_ALG_SHA_256
-depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_AES_C:MBEDTLS_CCM_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_AES_C:MBEDTLS_CCM_C:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
 handshake_ciphersuite_select:"TLS-ECDHE-ECDSA-WITH-AES-256-CCM":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDSA(PSA_ALG_SHA_256):PSA_ALG_NONE:PSA_KEY_USAGE_SIGN_HASH:0:MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM
 
 Handshake, select ECDHE-ECDSA-WITH-AES-256-CCM, opaque, bad alg
-depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_AES_C:MBEDTLS_CCM_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_AES_C:MBEDTLS_CCM_C:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
 handshake_ciphersuite_select:"TLS-ECDHE-ECDSA-WITH-AES-256-CCM":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDH:PSA_ALG_NONE:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:0
 
 Handshake, select ECDHE-ECDSA-WITH-AES-256-CCM, opaque, bad usage
-depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_AES_C:MBEDTLS_CCM_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_AES_C:MBEDTLS_CCM_C:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
 handshake_ciphersuite_select:"TLS-ECDHE-ECDSA-WITH-AES-256-CCM":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_NONE:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:0
 
 Handshake, select ECDH-RSA-WITH-AES-256-CBC-SHA384, non-opaque
-depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_RSA_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_RSA_C:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
 handshake_ciphersuite_select:"TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384":MBEDTLS_PK_ECDSA:"":PSA_ALG_NONE:PSA_ALG_NONE:0:0:MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
 
 Handshake, select ECDH-RSA-WITH-AES-256-CBC-SHA384, opaque
-depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_RSA_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_RSA_C:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
 handshake_ciphersuite_select:"TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDH:PSA_ALG_NONE:PSA_KEY_USAGE_DERIVE:0:MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
 
 Handshake, select ECDH-RSA-WITH-AES-256-CBC-SHA384, opaque, bad alg
-depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_RSA_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_RSA_C:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
 handshake_ciphersuite_select:"TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_NONE:PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:0
 
 Handshake, select ECDH-RSA-WITH-AES-256-CBC-SHA384, opaque, bad usage
-depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_RSA_C:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_AES_C:MBEDTLS_RSA_C:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
 handshake_ciphersuite_select:"TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDH:PSA_ALG_NONE:PSA_KEY_USAGE_DECRYPT:MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:0
 
 Handshake, select ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384, non-opaque
-depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_CAMELLIA_C:MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_CAMELLIA_C:MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
 handshake_ciphersuite_select:"TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384":MBEDTLS_PK_ECDSA:"":PSA_ALG_NONE:PSA_ALG_NONE:0:0:MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
 
 Handshake, select ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384, opaque, PSA_ALG_ANY_HASH
-depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_CAMELLIA_C:MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_CAMELLIA_C:MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
 handshake_ciphersuite_select:"TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_ECDH:PSA_KEY_USAGE_SIGN_HASH|PSA_KEY_USAGE_DERIVE:0:MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
 
 Handshake, select ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384, opaque, PSA_ALG_SHA_384
-depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_CAMELLIA_C:MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_CAMELLIA_C:MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
 handshake_ciphersuite_select:"TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDSA(PSA_ALG_SHA_384):PSA_ALG_ECDH:PSA_KEY_USAGE_SIGN_HASH|PSA_KEY_USAGE_DERIVE:0:MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
 
 Handshake, select ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384, opaque, missing alg
-depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_CAMELLIA_C:MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_CAMELLIA_C:MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
 handshake_ciphersuite_select:"TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_NONE:PSA_KEY_USAGE_SIGN_HASH|PSA_KEY_USAGE_DERIVE:MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:0
 
 Handshake, select ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384, opaque, missing usage
-depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_CAMELLIA_C:MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
+depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_ECDSA_C:MBEDTLS_ECDH_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_CAMELLIA_C:MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
 handshake_ciphersuite_select:"TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_ECDH:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:0
 
 Sending app data via TLS, MFL=512 without fragmentation
@@ -3378,34 +3378,6 @@
 depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_SRV_C
 ssl_serialize_session_load_buf_size:0:"":MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_3
 
-Constant-flow HMAC: MD5
-depends_on:MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-ssl_cf_hmac:MBEDTLS_MD_MD5
-
-Constant-flow HMAC: SHA1
-depends_on:MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-ssl_cf_hmac:MBEDTLS_MD_SHA1
-
-Constant-flow HMAC: SHA256
-depends_on:MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-ssl_cf_hmac:MBEDTLS_MD_SHA256
-
-Constant-flow HMAC: SHA384
-depends_on:MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-ssl_cf_hmac:MBEDTLS_MD_SHA384
-
-# these are the numbers we'd get with an empty plaintext and truncated HMAC
-Constant-flow memcpy from offset: small
-ssl_cf_memcpy_offset:0:5:10
-
-# we could get this with 255-bytes plaintext and untruncated SHA-256
-Constant-flow memcpy from offset: medium
-ssl_cf_memcpy_offset:0:255:32
-
-# we could get this with 255-bytes plaintext and untruncated SHA-384
-Constant-flow memcpy from offset: large
-ssl_cf_memcpy_offset:100:339:48
-
 Test configuration of groups for DHE through mbedtls_ssl_conf_curves()
 conf_curve:
 
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 7447a1d..674e649 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -511,7 +511,7 @@
  * \p peer1 and \p peer2 must have been previously initialized by calling
  * mbedtls_mock_socket_init().
  *
- * The capacites of the internal buffers are set to \p bufsize. Setting this to
+ * The capacities of the internal buffers are set to \p bufsize. Setting this to
  * the correct value allows for simulation of MTU, sanity testing the mock
  * implementation and mocking TCP connections with lower memory cost.
  */
@@ -652,7 +652,7 @@
 }
 
 /*
- * Setup a given mesasge socket context including initialization of
+ * Setup a given message socket context including initialization of
  * input/output queues to a chosen capacity of messages. Also set the
  * corresponding mock socket.
  *
@@ -5438,189 +5438,6 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC:MBEDTLS_TEST_HOOKS */
-void ssl_cf_hmac( int hash )
-{
-    /*
-     * Test the function mbedtls_ct_hmac() against a reference
-     * implementation.
-     */
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_algorithm_t alg;
-    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
-#else
-    mbedtls_md_context_t ctx, ref_ctx;
-    const mbedtls_md_info_t *md_info;
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-    size_t out_len, block_size;
-    size_t min_in_len, in_len, max_in_len, i;
-    /* TLS additional data is 13 bytes (hence the "lucky 13" name) */
-    unsigned char add_data[13];
-    unsigned char ref_out[MBEDTLS_HASH_MAX_SIZE];
-    unsigned char *data = NULL;
-    unsigned char *out = NULL;
-    unsigned char rec_num = 0;
-
-    USE_PSA_INIT( );
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    alg = PSA_ALG_HMAC( mbedtls_hash_info_psa_from_md( hash ) );
-
-    out_len = PSA_HASH_LENGTH( alg );
-    block_size = PSA_HASH_BLOCK_LENGTH( alg );
-
-    /* mbedtls_ct_hmac() requires the key to be exportable */
-    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_EXPORT |
-                                          PSA_KEY_USAGE_VERIFY_HASH );
-    psa_set_key_algorithm( &attributes, PSA_ALG_HMAC( alg ) );
-    psa_set_key_type( &attributes, PSA_KEY_TYPE_HMAC );
-#else
-    mbedtls_md_init( &ctx );
-    mbedtls_md_init( &ref_ctx );
-
-    md_info = mbedtls_md_info_from_type( hash );
-    TEST_ASSERT( md_info != NULL );
-    out_len = mbedtls_md_get_size( md_info );
-    TEST_ASSERT( out_len != 0 );
-    block_size = hash == MBEDTLS_MD_SHA384 ? 128 : 64;
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-    /* Use allocated out buffer to catch overwrites */
-    ASSERT_ALLOC( out, out_len );
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    /* Set up dummy key */
-    memset( ref_out, 42, sizeof( ref_out ) );
-    TEST_EQUAL( PSA_SUCCESS, psa_import_key( &attributes,
-                                             ref_out, out_len,
-                                             &key ) );
-#else
-    /* Set up contexts with the given hash and a dummy key */
-    TEST_EQUAL( 0, mbedtls_md_setup( &ctx, md_info, 1 ) );
-    TEST_EQUAL( 0, mbedtls_md_setup( &ref_ctx, md_info, 1 ) );
-    memset( ref_out, 42, sizeof( ref_out ) );
-    TEST_EQUAL( 0, mbedtls_md_hmac_starts( &ctx, ref_out, out_len ) );
-    TEST_EQUAL( 0, mbedtls_md_hmac_starts( &ref_ctx, ref_out, out_len ) );
-    memset( ref_out, 0, sizeof( ref_out ) );
-#endif
-
-    /*
-     * Test all possible lengths up to a point. The difference between
-     * max_in_len and min_in_len is at most 255, and make sure they both vary
-     * by at least one block size.
-     */
-    for( max_in_len = 0; max_in_len <= 255 + block_size; max_in_len++ )
-    {
-        mbedtls_test_set_step( max_in_len * 10000 );
-
-        /* Use allocated in buffer to catch overreads */
-        ASSERT_ALLOC( data, max_in_len );
-
-        min_in_len = max_in_len > 255 ? max_in_len - 255 : 0;
-        for( in_len = min_in_len; in_len <= max_in_len; in_len++ )
-        {
-            mbedtls_test_set_step( max_in_len * 10000 + in_len );
-
-            /* Set up dummy data and add_data */
-            rec_num++;
-            memset( add_data, rec_num, sizeof( add_data ) );
-            for( i = 0; i < in_len; i++ )
-                data[i] = ( i & 0xff ) ^ rec_num;
-
-            /* Get the function's result */
-            TEST_CF_SECRET( &in_len, sizeof( in_len ) );
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-            TEST_EQUAL( 0, mbedtls_ct_hmac( key, PSA_ALG_HMAC( alg ),
-                                            add_data, sizeof( add_data ),
-                                            data, in_len,
-                                            min_in_len, max_in_len,
-                                            out ) );
-#else
-            TEST_EQUAL( 0, mbedtls_ct_hmac( &ctx, add_data, sizeof( add_data ),
-                                            data, in_len,
-                                            min_in_len, max_in_len,
-                                            out ) );
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-            TEST_CF_PUBLIC( &in_len, sizeof( in_len ) );
-            TEST_CF_PUBLIC( out, out_len );
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-            TEST_EQUAL( PSA_SUCCESS, psa_mac_verify_setup( &operation,
-                                                           key, alg ) );
-            TEST_EQUAL( PSA_SUCCESS, psa_mac_update( &operation, add_data,
-                                                     sizeof( add_data ) ) );
-            TEST_EQUAL( PSA_SUCCESS, psa_mac_update( &operation,
-                                                     data, in_len ) );
-            TEST_EQUAL( PSA_SUCCESS, psa_mac_verify_finish( &operation,
-                                                            out, out_len ) );
-#else
-            /* Compute the reference result */
-            TEST_EQUAL( 0, mbedtls_md_hmac_update( &ref_ctx, add_data,
-                                                   sizeof( add_data ) ) );
-            TEST_EQUAL( 0, mbedtls_md_hmac_update( &ref_ctx, data, in_len ) );
-            TEST_EQUAL( 0, mbedtls_md_hmac_finish( &ref_ctx, ref_out ) );
-            TEST_EQUAL( 0, mbedtls_md_hmac_reset( &ref_ctx ) );
-
-            /* Compare */
-            ASSERT_COMPARE( out, out_len, ref_out, out_len );
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-        }
-
-        mbedtls_free( data );
-        data = NULL;
-    }
-
-exit:
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_mac_abort( &operation );
-    psa_destroy_key( key );
-#else
-    mbedtls_md_free( &ref_ctx );
-    mbedtls_md_free( &ctx );
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-    mbedtls_free( data );
-    mbedtls_free( out );
-
-    USE_PSA_DONE( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE depends_on:MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC:MBEDTLS_TEST_HOOKS */
-void ssl_cf_memcpy_offset( int offset_min, int offset_max, int len )
-{
-    unsigned char *dst = NULL;
-    unsigned char *src = NULL;
-    size_t src_len = offset_max + len;
-    size_t secret;
-
-    ASSERT_ALLOC( dst, len );
-    ASSERT_ALLOC( src, src_len );
-
-    /* Fill src in a way that we can detect if we copied the right bytes */
-    mbedtls_test_rnd_std_rand( NULL, src, src_len );
-
-    for( secret = offset_min; secret <= (size_t) offset_max; secret++ )
-    {
-        mbedtls_test_set_step( (int) secret );
-
-        TEST_CF_SECRET( &secret, sizeof( secret ) );
-        mbedtls_ct_memcpy_offset( dst, src, secret,
-                                  offset_min, offset_max, len );
-        TEST_CF_PUBLIC( &secret, sizeof( secret ) );
-        TEST_CF_PUBLIC( dst, len );
-
-        ASSERT_COMPARE( dst, len, src + secret, len );
-    }
-
-exit:
-    mbedtls_free( dst );
-    mbedtls_free( src );
-}
-/* END_CASE */
-
 /* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
 void test_multiple_psks()
 {