Merge pull request #5010 from gilles-peskine-arm/psa-rsa-pss_any_salt

PSA: fix salt length for PSS verification
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 210aba4..cd990ab 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,6 +46,11 @@
 
 option(UNSAFE_BUILD "Allow unsafe builds. These builds ARE NOT SECURE." OFF)
 option(MBEDTLS_FATAL_WARNINGS "Compiler warnings treated as errors" ON)
+if(WIN32)
+    option(GEN_FILES "Generate the auto-generated files as needed" OFF)
+else()
+    option(GEN_FILES "Generate the auto-generated files as needed" ON)
+endif()
 
 string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}")
 string(REGEX MATCH "GNU" CMAKE_COMPILER_IS_GNU "${CMAKE_C_COMPILER_ID}")
@@ -135,6 +140,22 @@
     endif()
 endfunction(link_to_source)
 
+# Get the filename without the final extension (i.e. convert "a.b.c" to "a.b")
+function(get_name_without_last_ext dest_var full_name)
+    # Split into a list on '.' (but a cmake list is just a ';'-separated string)
+    string(REPLACE "." ";" ext_parts "${full_name}")
+    # Remove the last item if there are more than one
+    list(LENGTH ext_parts ext_parts_len)
+    if (${ext_parts_len} GREATER "1")
+        math(EXPR ext_parts_last_item "${ext_parts_len} - 1")
+        list(REMOVE_AT ext_parts ${ext_parts_last_item})
+    endif()
+    # Convert back to a string by replacing separators with '.'
+    string(REPLACE ";" "." no_ext_name "${ext_parts}")
+    # Copy into the desired variable
+    set(${dest_var} ${no_ext_name} PARENT_SCOPE)
+endfunction(get_name_without_last_ext)
+
 string(REGEX MATCH "Clang" CMAKE_COMPILER_IS_CLANG "${CMAKE_C_COMPILER_ID}")
 
 include(CheckCCompilerFlag)
diff --git a/ChangeLog.d/base64-ranges.txt b/ChangeLog.d/base64-ranges.txt
new file mode 100644
index 0000000..e3f3862
--- /dev/null
+++ b/ChangeLog.d/base64-ranges.txt
@@ -0,0 +1,4 @@
+Changes
+   * Improve the performance of base64 constant-flow code. The result is still
+     slower than the original non-constant-flow implementation, but much faster
+     than the previous constant-flow implementation. Fixes #4814.
diff --git a/ChangeLog.d/check-return.txt b/ChangeLog.d/check-return.txt
new file mode 100644
index 0000000..045b180
--- /dev/null
+++ b/ChangeLog.d/check-return.txt
@@ -0,0 +1,17 @@
+Bugfix
+   * Failures of alternative implementations of AES or DES single-block
+     functions enabled with MBEDTLS_AES_ENCRYPT_ALT, MBEDTLS_AES_DECRYPT_ALT,
+     MBEDTLS_DES_CRYPT_ECB_ALT or MBEDTLS_DES3_CRYPT_ECB_ALT were ignored.
+     This does not concern the implementation provided with Mbed TLS,
+     where this function cannot fail, or full-module replacements with
+     MBEDTLS_AES_ALT or MBEDTLS_DES_ALT. Reported by Armelle Duboc in #1092.
+
+Features
+   * Warn if errors from certain functions are ignored. This is currently
+     supported on GCC-like compilers and on MSVC and can be configured through
+     the macro MBEDTLS_CHECK_RETURN. The warnings are always enabled
+     (where supported) for critical functions where ignoring the return
+     value is almost always a bug. Enable the new configuration option
+     MBEDTLS_CHECK_RETURN_WARNING to get warnings for other functions. This
+     is currently implemented in the AES and DES modules, and will be extended
+     to other modules in the future.
diff --git a/ChangeLog.d/fix-psa_gen_key-status.txt b/ChangeLog.d/fix-psa_gen_key-status.txt
new file mode 100644
index 0000000..7860988
--- /dev/null
+++ b/ChangeLog.d/fix-psa_gen_key-status.txt
@@ -0,0 +1,2 @@
+Bugfix
+   * Fix the error returned by psa_generate_key() for a public key. Fixes #4551.
diff --git a/ChangeLog.d/issue5065.txt b/ChangeLog.d/issue5065.txt
new file mode 100644
index 0000000..943ee47
--- /dev/null
+++ b/ChangeLog.d/issue5065.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix compile-time or run-time errors in PSA
+     AEAD functions when ChachaPoly is disabled. Fixes #5065.
diff --git a/ChangeLog.d/no-strerror.txt b/ChangeLog.d/no-strerror.txt
new file mode 100644
index 0000000..69743a8
--- /dev/null
+++ b/ChangeLog.d/no-strerror.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix the build of sample programs when neither MBEDTLS_ERROR_C nor
+     MBEDTLS_ERROR_STRERROR_DUMMY is enabled.
diff --git a/ChangeLog.d/psa_gcm_buffer_limitation.txt b/ChangeLog.d/psa_gcm_buffer_limitation.txt
new file mode 100644
index 0000000..0c07e24
--- /dev/null
+++ b/ChangeLog.d/psa_gcm_buffer_limitation.txt
@@ -0,0 +1,16 @@
+Bugfix
+   * Remove PSA'a AEAD finish/verify output buffer limitation for GCM.
+     The requirement of minimum 15 bytes for output buffer in
+     psa_aead_finish() and psa_aead_verify() does not apply to the built-in
+     implementation of GCM.
+   * Move GCM's update output buffer length verification from PSA AEAD to
+     the built-in implementation of the GCM.
+     The requirement for output buffer size to be equal or greater then
+     input buffer size is valid only for the built-in implementation of GCM.
+     Alternative GCM implementations can process whole blocks only.
+
+API changes
+   * New error code for GCM: MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL.
+     Alternative GCM implementations are expected to verify
+     the length of the provided output buffers and to return the
+     MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL in case the buffer length is too small.
diff --git a/ChangeLog.d/remove-greentea-support.txt b/ChangeLog.d/remove-greentea-support.txt
new file mode 100644
index 0000000..af4df4b
--- /dev/null
+++ b/ChangeLog.d/remove-greentea-support.txt
@@ -0,0 +1,3 @@
+Removals
+   * Remove the partial support for running unit tests via Greentea on Mbed OS,
+     which had been unmaintained since 2018.
diff --git a/ChangeLog.d/remove-ssl-export-keys.txt b/ChangeLog.d/remove-ssl-export-keys.txt
new file mode 100644
index 0000000..1a4b31d
--- /dev/null
+++ b/ChangeLog.d/remove-ssl-export-keys.txt
@@ -0,0 +1,5 @@
+Changes
+   * Remove MBEDTLS_SSL_EXPORT_KEYS, making it always on and increasing the
+     code size by about 80B on an M0 build. This option only gated an ability
+     to set a callback, but was deemed unnecessary as it was yet another define
+     to remember when writing tests, or test configurations. Fixes #4653.
diff --git a/README.md b/README.md
index b80ee11..e6924cb 100644
--- a/README.md
+++ b/README.md
@@ -67,6 +67,7 @@
 Any of the following methods are available to generate the configuration-independent files:
 
 * If not cross-compiling, running `make` with any target, or just `make`, will automatically generate required files.
+* On non-Windows systems, when not cross-compiling, CMake will generate the required files automatically.
 * Run `make generated_files` to generate all the configuration-independent files.
 * On Unix/POSIX systems, run `tests/scripts/check-generated-files.sh -u` to generate all the configuration-independent files.
 * On Windows, run `scripts\make_generated_files.bat` to generate all the configuration-independent files.
@@ -298,3 +299,10 @@
 ------------
 
 We gratefully accept bug reports and contributions from the community. Please see the [contributing guidelines](CONTRIBUTING.md) for details on how to do this.
+
+Contact
+-------
+
+* To report a security vulnerability in Mbed TLS, please email <mbed-tls-security@lists.trustedfirmware.org>. For more information, see [`SECURITY.md`](SECURITY.md).
+* To report a bug or request a feature in Mbed TLS, please [file an issue on GitHub](https://github.com/ARMmbed/mbedtls/issues/new/choose).
+* Please see [`SUPPORT.md`](SUPPORT.md) for other channels for discussion and support about Mbed TLS.
diff --git a/configs/config-thread.h b/configs/config-thread.h
index be889a1..36d8245 100644
--- a/configs/config-thread.h
+++ b/configs/config-thread.h
@@ -45,7 +45,6 @@
 #define MBEDTLS_SSL_PROTO_DTLS
 #define MBEDTLS_SSL_DTLS_ANTI_REPLAY
 #define MBEDTLS_SSL_DTLS_HELLO_VERIFY
-#define MBEDTLS_SSL_EXPORT_KEYS
 
 /* mbed TLS modules */
 #define MBEDTLS_AES_C
diff --git a/docs/.gitignore b/docs/.gitignore
index 33ae5ac..23f832b 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -1,3 +1,2 @@
 *.html
 *.pdf
-!PSACryptoDriverModelSpec.pdf
diff --git a/docs/PSACryptoDriverModelSpec.pdf b/docs/PSACryptoDriverModelSpec.pdf
deleted file mode 100644
index cf11380..0000000
--- a/docs/PSACryptoDriverModelSpec.pdf
+++ /dev/null
Binary files differ
diff --git a/docs/architecture/tls13-experimental.md b/docs/architecture/tls13-experimental.md
index 5d7c14f..88d0b73 100644
--- a/docs/architecture/tls13-experimental.md
+++ b/docs/architecture/tls13-experimental.md
@@ -255,7 +255,7 @@
     Example 1: #define CLIENT_HELLO_RANDOM_LEN 32, macro for the length of the
         `random` field of the ClientHello message.
 
-    Example 2 (consistent abbreviation): `mbedtls_ssl_tls1_3_write_sig_alg_ext()`
+    Example 2 (consistent abbreviation): `mbedtls_ssl_tls13_write_sig_alg_ext()`
         and `MBEDTLS_TLS_EXT_SIG_ALG`, `sig_alg` standing for
         `signature_algorithms`.
 
@@ -279,7 +279,7 @@
     of another one which could potentially lead to some nasty issues.
 
     Example: `cipher_suites` vector of ClientHello in
-             `ssl_tls1_3_write_client_hello_cipher_suites()`
+             `ssl_tls13_write_client_hello_cipher_suites()`
     ```
     size_t cipher_suites_len;
     unsigned char *p_cipher_suites_len;
diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h
index 879c3f2..becbfae 100644
--- a/include/mbedtls/aes.h
+++ b/include/mbedtls/aes.h
@@ -42,6 +42,7 @@
 #include "mbedtls/private_access.h"
 
 #include "mbedtls/build_info.h"
+#include "mbedtls/platform_util.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -163,6 +164,7 @@
  * \return         \c 0 on success.
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
                     unsigned int keybits );
 
@@ -181,6 +183,7 @@
  * \return         \c 0 on success.
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
                     unsigned int keybits );
 
@@ -201,6 +204,7 @@
  * \return         \c 0 on success.
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
                                 const unsigned char *key,
                                 unsigned int keybits );
@@ -221,6 +225,7 @@
  * \return         \c 0 on success.
  * \return         #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
                                 const unsigned char *key,
                                 unsigned int keybits );
@@ -249,6 +254,7 @@
 
  * \return         \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
                     int mode,
                     const unsigned char input[16],
@@ -296,6 +302,7 @@
  * \return         #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
  *                 on failure.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
                     int mode,
                     size_t length,
@@ -340,6 +347,7 @@
  *                     smaller than an AES block in size (16 Bytes) or if \p
  *                     length is larger than 2^20 blocks (16 MiB).
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
                            int mode,
                            size_t length,
@@ -388,6 +396,7 @@
  *
  * \return         \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
                        int mode,
                        size_t length,
@@ -432,6 +441,7 @@
  *
  * \return         \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
                     int mode,
                     size_t length,
@@ -486,6 +496,7 @@
  *
  * \return         \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
                        size_t length,
                        size_t *iv_off,
@@ -572,6 +583,7 @@
  *
  * \return                 \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
                        size_t length,
                        size_t *nc_off,
@@ -592,6 +604,7 @@
  *
  * \return          \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
                                   const unsigned char input[16],
                                   unsigned char output[16] );
@@ -607,6 +620,7 @@
  *
  * \return          \c 0 on success.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
                                   const unsigned char input[16],
                                   unsigned char output[16] );
@@ -618,6 +632,7 @@
  * \return         \c 0 on success.
  * \return         \c 1 on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_aes_self_test( int verbose );
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/include/mbedtls/config_psa.h b/include/mbedtls/config_psa.h
index 60191f1..5615a68 100644
--- a/include/mbedtls/config_psa.h
+++ b/include/mbedtls/config_psa.h
@@ -273,6 +273,18 @@
 #endif /* PSA_HAVE_SOFT_KEY_TYPE_AES || PSA_HAVE_SOFT_BLOCK_MODE */
 #endif /* PSA_WANT_KEY_TYPE_AES */
 
+#if defined(PSA_WANT_KEY_TYPE_ARIA)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA)
+#define PSA_HAVE_SOFT_KEY_TYPE_ARIA 1
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA */
+#if defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
+    defined(PSA_HAVE_SOFT_BLOCK_MODE) || \
+    defined(PSA_HAVE_SOFT_BLOCK_AEAD)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1
+#define MBEDTLS_ARIA_C
+#endif /* PSA_HAVE_SOFT_KEY_TYPE_ARIA || PSA_HAVE_SOFT_BLOCK_MODE */
+#endif /* PSA_WANT_KEY_TYPE_ARIA */
+
 #if defined(PSA_WANT_KEY_TYPE_CAMELLIA)
 #if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA)
 #define PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA 1
@@ -307,6 +319,7 @@
  * PSA_HAVE_SOFT_BLOCK_CIPHER, which can be used in any of these
  * situations. */
 #if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
     defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \
     defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)
 #define PSA_HAVE_SOFT_BLOCK_CIPHER 1
@@ -387,6 +400,7 @@
 #if defined(PSA_WANT_ALG_CCM)
 #if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM) || \
     defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
     defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)
 #define MBEDTLS_PSA_BUILTIN_ALG_CCM 1
 #define MBEDTLS_CCM_C
@@ -396,6 +410,7 @@
 #if defined(PSA_WANT_ALG_GCM)
 #if !defined(MBEDTLS_PSA_ACCEL_ALG_GCM) || \
     defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
     defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)
 #define MBEDTLS_PSA_BUILTIN_ALG_GCM 1
 #define MBEDTLS_GCM_C
@@ -635,6 +650,11 @@
 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1
 #endif
 
+#if defined(MBEDTLS_ARIA_C)
+#define PSA_WANT_KEY_TYPE_ARIA 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1
+#endif
+
 #if defined(MBEDTLS_CAMELLIA_C)
 #define PSA_WANT_KEY_TYPE_CAMELLIA 1
 #define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1
@@ -666,7 +686,7 @@
 #endif
 
 #if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) || \
-    defined(MBEDTLS_CAMELLIA_C)
+    defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)
 #define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1
 #define PSA_WANT_ALG_ECB_NO_PADDING 1
 #endif
diff --git a/include/mbedtls/des.h b/include/mbedtls/des.h
index 63a8e00..be74cb1 100644
--- a/include/mbedtls/des.h
+++ b/include/mbedtls/des.h
@@ -29,6 +29,7 @@
 #include "mbedtls/private_access.h"
 
 #include "mbedtls/build_info.h"
+#include "mbedtls/platform_util.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -139,6 +140,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
 
 /**
@@ -152,6 +154,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
 
 /**
@@ -166,6 +169,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
 
 /**
@@ -180,6 +184,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
 
 /**
@@ -190,6 +195,7 @@
  *
  * \return         0
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
                       const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
 
@@ -201,6 +207,7 @@
  *
  * \return         0
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
                       const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
 
@@ -212,6 +219,7 @@
  *
  * \return         0
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
                       const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
 
@@ -223,6 +231,7 @@
  *
  * \return         0
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
                       const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
 
@@ -239,6 +248,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
                     const unsigned char input[8],
                     unsigned char output[8] );
@@ -266,6 +276,7 @@
  *                 security risk. We recommend considering stronger ciphers
  *                 instead.
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
                     int mode,
                     size_t length,
@@ -283,6 +294,7 @@
  *
  * \return         0 if successful
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
                      const unsigned char input[8],
                      unsigned char output[8] );
@@ -308,6 +320,7 @@
  *
  * \return         0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
  */
+MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
                      int mode,
                      size_t length,
@@ -338,6 +351,7 @@
  *
  * \return         0 if successful, or 1 if the test failed
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_des_self_test( int verbose );
 
 #endif /* MBEDTLS_SELF_TEST */
diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h
index 27420ce..8b2b9ea 100644
--- a/include/mbedtls/error.h
+++ b/include/mbedtls/error.h
@@ -56,7 +56,7 @@
  * Module   Nr  Codes assigned
  * ERROR     2  0x006E          0x0001
  * MPI       7  0x0002-0x0010
- * GCM       3  0x0012-0x0014   0x0013-0x0013
+ * GCM       3  0x0012-0x0016   0x0013-0x0013
  * THREADING 3  0x001A-0x001E
  * AES       5  0x0020-0x0022   0x0021-0x0025
  * CAMELLIA  3  0x0024-0x0026   0x0027-0x0027
diff --git a/include/mbedtls/gcm.h b/include/mbedtls/gcm.h
index 9d9155f..7dc9dfb 100644
--- a/include/mbedtls/gcm.h
+++ b/include/mbedtls/gcm.h
@@ -45,6 +45,8 @@
 #define MBEDTLS_ERR_GCM_AUTH_FAILED                       -0x0012
 /** Bad input parameters to function. */
 #define MBEDTLS_ERR_GCM_BAD_INPUT                         -0x0014
+/** An output buffer is too small. */
+#define MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL                  -0x0016
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index adc317d..c2f4587 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -521,6 +521,29 @@
 //#define MBEDTLS_CAMELLIA_SMALL_MEMORY
 
 /**
+ * \def MBEDTLS_CHECK_RETURN_WARNING
+ *
+ * If this macro is defined, emit a compile-time warning if application code
+ * calls a function without checking its return value, but the return value
+ * should generally be checked in portable applications.
+ *
+ * This is only supported on platforms where #MBEDTLS_CHECK_RETURN is
+ * implemented. Otherwise this option has no effect.
+ *
+ * Uncomment to get warnings on using fallible functions without checking
+ * their return value.
+ *
+ * \note  This feature is a work in progress.
+ *        Warnings will be added to more functions in the future.
+ *
+ * \note  A few functions are considered critical, and ignoring the return
+ *        value of these functions will trigger a warning even if this
+ *        macro is not defined. To completely disable return value check
+ *        warnings, define #MBEDTLS_CHECK_RETURN with an empty expansion.
+ */
+//#define MBEDTLS_CHECK_RETURN_WARNING
+
+/**
  * \def MBEDTLS_CIPHER_MODE_CBC
  *
  * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
@@ -1599,16 +1622,6 @@
 #define MBEDTLS_SSL_SESSION_TICKETS
 
 /**
- * \def MBEDTLS_SSL_EXPORT_KEYS
- *
- * Enable support for exporting key block and master secret.
- * This is required for certain users of TLS, e.g. EAP-TLS.
- *
- * Comment this macro to disable support for key export
- */
-#define MBEDTLS_SSL_EXPORT_KEYS
-
-/**
  * \def MBEDTLS_SSL_SERVER_NAME_INDICATION
  *
  * Enable support for RFC 6066 server name indication (SNI) in SSL.
@@ -3067,6 +3080,29 @@
 //#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO   mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
 //#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO  mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
 
+/** \def MBEDTLS_CHECK_RETURN
+ *
+ * This macro is used at the beginning of the declaration of a function
+ * to indicate that its return value should be checked. It should
+ * instruct the compiler to emit a warning or an error if the function
+ * is called without checking its return value.
+ *
+ * There is a default implementation for popular compilers in platform_util.h.
+ * You can override the default implementation by defining your own here.
+ *
+ * If the implementation here is empty, this will effectively disable the
+ * checking of functions' return values.
+ */
+//#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__))
+
+/** \def MBEDTLS_IGNORE_RETURN
+ *
+ * This macro requires one argument, which should be a C function call.
+ * If that function call would cause a #MBEDTLS_CHECK_RETURN warning, this
+ * warning is suppressed.
+ */
+//#define MBEDTLS_IGNORE_RETURN( result ) ((void) !(result))
+
 /* PSA options */
 /**
  * Use HMAC_DRBG with the specified hash algorithm for HMAC_DRBG for the
diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h
index 1a0a135..36e3718 100644
--- a/include/mbedtls/platform_util.h
+++ b/include/mbedtls/platform_util.h
@@ -60,6 +60,95 @@
 #endif /* MBEDTLS_DEPRECATED_WARNING */
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
 
+/* Implementation of the check-return facility.
+ * See the user documentation in mbedtls_config.h.
+ *
+ * Do not use this macro directly to annotate function: instead,
+ * use one of MBEDTLS_CHECK_RETURN_CRITICAL or MBEDTLS_CHECK_RETURN_TYPICAL
+ * depending on how important it is to check the return value.
+ */
+#if !defined(MBEDTLS_CHECK_RETURN)
+#if defined(__GNUC__)
+#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__))
+#elif defined(_MSC_VER) && _MSC_VER >= 1700
+#include <sal.h>
+#define MBEDTLS_CHECK_RETURN _Check_return_
+#else
+#define MBEDTLS_CHECK_RETURN
+#endif
+#endif
+
+/** Critical-failure function
+ *
+ * This macro appearing at the beginning of the declaration of a function
+ * indicates that its return value should be checked in all applications.
+ * Omitting the check is very likely to indicate a bug in the application
+ * and will result in a compile-time warning if #MBEDTLS_CHECK_RETURN
+ * is implemented for the compiler in use.
+ *
+ * \note  The use of this macro is a work in progress.
+ *        This macro may be added to more functions in the future.
+ *        Such an extension is not considered an API break, provided that
+ *        there are near-unavoidable circumstances under which the function
+ *        can fail. For example, signature/MAC/AEAD verification functions,
+ *        and functions that require a random generator, are considered
+ *        return-check-critical.
+ */
+#define MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_CHECK_RETURN
+
+/** Ordinary-failure function
+ *
+ * This macro appearing at the beginning of the declaration of a function
+ * indicates that its return value should be generally be checked in portable
+ * applications. Omitting the check will result in a compile-time warning if
+ * #MBEDTLS_CHECK_RETURN is implemented for the compiler in use and
+ * #MBEDTLS_CHECK_RETURN_WARNING is enabled in the compile-time configuration.
+ *
+ * You can use #MBEDTLS_IGNORE_RETURN to explicitly ignore the return value
+ * of a function that is annotated with #MBEDTLS_CHECK_RETURN.
+ *
+ * \note  The use of this macro is a work in progress.
+ *        This macro will be added to more functions in the future.
+ *        Eventually this should appear before most functions returning
+ *        an error code (as \c int in the \c mbedtls_xxx API or
+ *        as ::psa_status_t in the \c psa_xxx API).
+ */
+#if defined(MBEDTLS_CHECK_RETURN_WARNING)
+#define MBEDTLS_CHECK_RETURN_TYPICAL MBEDTLS_CHECK_RETURN
+#else
+#define MBEDTLS_CHECK_RETURN_TYPICAL
+#endif
+
+/** Benign-failure function
+ *
+ * This macro appearing at the beginning of the declaration of a function
+ * indicates that it is rarely useful to check its return value.
+ *
+ * This macro has an empty expansion. It exists for documentation purposes:
+ * a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function
+ * has been analyzed for return-check usefuless, whereas the lack of
+ * an annotation indicates that the function has not been analyzed and its
+ * return-check usefulness is unknown.
+ */
+#define MBEDTLS_CHECK_RETURN_OPTIONAL
+
+/** \def MBEDTLS_IGNORE_RETURN
+ *
+ * Call this macro with one argument, a function call, to suppress a warning
+ * from #MBEDTLS_CHECK_RETURN due to that function call.
+ */
+#if !defined(MBEDTLS_IGNORE_RETURN)
+/* GCC doesn't silence the warning with just (void)(result).
+ * (void)!(result) is known to work up at least up to GCC 10, as well
+ * as with Clang and MSVC.
+ *
+ * https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Non_002dbugs.html
+ * https://stackoverflow.com/questions/40576003/ignoring-warning-wunused-result
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425#c34
+ */
+#define MBEDTLS_IGNORE_RETURN(result) ( (void) !( result ) )
+#endif
+
 /**
  * \brief       Securely zeroize a buffer
  *
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 2349245..288d9b3 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -486,6 +486,7 @@
 #define MBEDTLS_SSL_HS_SERVER_HELLO             2
 #define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST     3
 #define MBEDTLS_SSL_HS_NEW_SESSION_TICKET       4
+#define MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS     8 // NEW IN TLS 1.3
 #define MBEDTLS_SSL_HS_CERTIFICATE             11
 #define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE     12
 #define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST     13
@@ -593,6 +594,9 @@
 
 #define MBEDTLS_PREMASTER_SIZE     sizeof( union mbedtls_ssl_premaster_secret )
 
+/* Length in number of bytes of the TLS sequence number */
+#define MBEDTLS_SSL_SEQUENCE_NUMBER_LEN 8
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -1140,7 +1144,6 @@
 }
 mbedtls_tls_prf_types;
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 typedef enum
 {
     MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET = 0,
@@ -1176,7 +1179,6 @@
                                         const unsigned char client_random[32],
                                         const unsigned char server_random[32],
                                         mbedtls_tls_prf_types tls_prf_type );
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 /**
  * SSL/TLS configuration to be shared between mbedtls_ssl_context structures.
@@ -1566,7 +1568,7 @@
     size_t MBEDTLS_PRIVATE(out_buf_len);         /*!< length of output buffer          */
 #endif
 
-    unsigned char MBEDTLS_PRIVATE(cur_out_ctr)[8]; /*!<  Outgoing record sequence  number. */
+    unsigned char MBEDTLS_PRIVATE(cur_out_ctr)[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!<  Outgoing record sequence  number. */
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     uint16_t MBEDTLS_PRIVATE(mtu);               /*!< path mtu, used to fragment outgoing messages */
@@ -1631,11 +1633,9 @@
                             *   and #MBEDTLS_SSL_CID_DISABLED. */
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     /** Callback to export key block and master secret                      */
     mbedtls_ssl_export_keys_t *MBEDTLS_PRIVATE(f_export_keys);
     void *MBEDTLS_PRIVATE(p_export_keys);            /*!< context for key export callback    */
-#endif
 };
 
 /**
@@ -2208,7 +2208,6 @@
         void *p_ticket );
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 /**
  * \brief   Configure a key export callback.
  *          (Default: none.)
@@ -2230,7 +2229,6 @@
 void mbedtls_ssl_set_export_keys_cb( mbedtls_ssl_context *ssl,
                                      mbedtls_ssl_export_keys_t *f_export_keys,
                                      void *p_export_keys );
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
 /**
diff --git a/include/psa/crypto.h b/include/psa/crypto.h
index b3ef363..5d9854a 100644
--- a/include/psa/crypto.h
+++ b/include/psa/crypto.h
@@ -3682,6 +3682,7 @@
  *   The following key types defined in this specification follow this scheme:
  *
  *     - #PSA_KEY_TYPE_AES;
+ *     - #PSA_KEY_TYPE_ARIA;
  *     - #PSA_KEY_TYPE_CAMELLIA;
  *     - #PSA_KEY_TYPE_DERIVE;
  *     - #PSA_KEY_TYPE_HMAC;
diff --git a/include/psa/crypto_config.h b/include/psa/crypto_config.h
index 64d8c58..6476e3c 100644
--- a/include/psa/crypto_config.h
+++ b/include/psa/crypto_config.h
@@ -111,6 +111,7 @@
 #define PSA_WANT_KEY_TYPE_DERIVE                1
 #define PSA_WANT_KEY_TYPE_HMAC                  1
 #define PSA_WANT_KEY_TYPE_AES                   1
+#define PSA_WANT_KEY_TYPE_ARIA                  1
 #define PSA_WANT_KEY_TYPE_CAMELLIA              1
 #define PSA_WANT_KEY_TYPE_CHACHA20              1
 #define PSA_WANT_KEY_TYPE_DES                   1
diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h
index 86a03d1..621b872 100644
--- a/include/psa/crypto_values.h
+++ b/include/psa/crypto_values.h
@@ -466,6 +466,10 @@
  */
 #define PSA_KEY_TYPE_AES                            ((psa_key_type_t)0x2400)
 
+/** Key for a cipher, AEAD or MAC algorithm based on the
+ * ARIA block cipher. */
+#define PSA_KEY_TYPE_ARIA                           ((psa_key_type_t)0x2406)
+
 /** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES).
  *
  * The size of the key can be 64 bits (single DES), 128 bits (2-key 3DES) or
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index a5d692c..18aff5a 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -109,6 +109,44 @@
     ssl_tls13_generic.c
 )
 
+if(GEN_FILES)
+    find_package(Perl REQUIRED)
+
+    file(GLOB error_headers ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls/*.h)
+    add_custom_command(
+        OUTPUT
+            ${CMAKE_CURRENT_BINARY_DIR}/error.c
+        COMMAND
+            ${PERL_EXECUTABLE}
+                ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_errors.pl
+                ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls
+                ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files
+                ${CMAKE_CURRENT_BINARY_DIR}/error.c
+        DEPENDS
+            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_errors.pl
+            ${error_headers}
+            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/error.fmt
+    )
+
+    add_custom_command(
+        OUTPUT
+            ${CMAKE_CURRENT_BINARY_DIR}/version_features.c
+        COMMAND
+            ${PERL_EXECUTABLE}
+                ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_features.pl
+                ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls
+                ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files
+                ${CMAKE_CURRENT_BINARY_DIR}/version_features.c
+        DEPENDS
+            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_features.pl
+            ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls/mbedtls_config.h
+            ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/version_features.fmt
+    )
+else()
+    link_to_source(error.c)
+    link_to_source(version_features.c)
+endif()
+
 if(CMAKE_COMPILER_IS_GNUCC)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes")
 endif(CMAKE_COMPILER_IS_GNUCC)
diff --git a/library/aes.c b/library/aes.c
index 8e3358c..4afc3c4 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -1011,6 +1011,7 @@
                     unsigned char *output )
 {
     int i;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[16];
 
     AES_VALIDATE_RET( ctx != NULL );
@@ -1040,7 +1041,9 @@
         while( length > 0 )
         {
             memcpy( temp, input, 16 );
-            mbedtls_aes_crypt_ecb( ctx, mode, input, output );
+            ret = mbedtls_aes_crypt_ecb( ctx, mode, input, output );
+            if( ret != 0 )
+                goto exit;
 
             for( i = 0; i < 16; i++ )
                 output[i] = (unsigned char)( output[i] ^ iv[i] );
@@ -1059,7 +1062,9 @@
             for( i = 0; i < 16; i++ )
                 output[i] = (unsigned char)( input[i] ^ iv[i] );
 
-            mbedtls_aes_crypt_ecb( ctx, mode, output, output );
+            ret = mbedtls_aes_crypt_ecb( ctx, mode, output, output );
+            if( ret != 0 )
+                goto exit;
             memcpy( iv, output, 16 );
 
             input  += 16;
@@ -1067,8 +1072,10 @@
             length -= 16;
         }
     }
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -1222,6 +1229,7 @@
                        unsigned char *output )
 {
     int c;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
 
     AES_VALIDATE_RET( ctx != NULL );
@@ -1242,7 +1250,11 @@
         while( length-- )
         {
             if( n == 0 )
-                mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+            {
+                ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+                if( ret != 0 )
+                    goto exit;
+            }
 
             c = *input++;
             *output++ = (unsigned char)( c ^ iv[n] );
@@ -1256,7 +1268,11 @@
         while( length-- )
         {
             if( n == 0 )
-                mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+            {
+                ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+                if( ret != 0 )
+                    goto exit;
+            }
 
             iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
 
@@ -1265,8 +1281,10 @@
     }
 
     *iv_off = n;
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 
 /*
@@ -1279,6 +1297,7 @@
                             const unsigned char *input,
                             unsigned char *output )
 {
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char c;
     unsigned char ov[17];
 
@@ -1291,7 +1310,9 @@
     while( length-- )
     {
         memcpy( ov, iv, 16 );
-        mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+        ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+        if( ret != 0 )
+            goto exit;
 
         if( mode == MBEDTLS_AES_DECRYPT )
             ov[16] = *input;
@@ -1303,8 +1324,10 @@
 
         memcpy( iv, ov + 1, 16 );
     }
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
@@ -1366,6 +1389,7 @@
                        unsigned char *output )
 {
     int c, i;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
 
     AES_VALIDATE_RET( ctx != NULL );
@@ -1383,7 +1407,9 @@
     while( length-- )
     {
         if( n == 0 ) {
-            mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
+            ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
+            if( ret != 0 )
+                goto exit;
 
             for( i = 16; i > 0; i-- )
                 if( ++nonce_counter[i - 1] != 0 )
@@ -1396,8 +1422,10 @@
     }
 
     *nc_off = n;
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
diff --git a/library/base64.c b/library/base64.c
index 9cf5dd4..a516c1d 100644
--- a/library/base64.c
+++ b/library/base64.c
@@ -22,6 +22,7 @@
 #if defined(MBEDTLS_BASE64_C)
 
 #include "mbedtls/base64.h"
+#include "base64_invasive.h"
 
 #include <stdint.h>
 
@@ -35,127 +36,41 @@
 #endif /* MBEDTLS_PLATFORM_C */
 #endif /* MBEDTLS_SELF_TEST */
 
-static const unsigned char base64_enc_map[64] =
-{
-    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
-    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
-    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
-    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
-    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
-    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
-    '8', '9', '+', '/'
-};
-
-static const unsigned char base64_dec_map[128] =
-{
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-    127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
-     54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
-    127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
-      5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
-     15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
-     25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
-     29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
-     39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
-     49,  50,  51, 127, 127, 127, 127, 127
-};
-
 #define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
 
-/*
- * Constant flow conditional assignment to unsigned char
+/* Return 0xff if low <= c <= high, 0 otherwise.
+ *
+ * Constant flow with respect to c.
  */
-static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src,
-                                       unsigned char condition )
+MBEDTLS_STATIC_TESTABLE
+unsigned char mbedtls_base64_mask_of_range( unsigned char low,
+                                            unsigned char high,
+                                            unsigned char c )
 {
-    /* MSVC has a warning about unary minus on unsigned integer types,
-     * but this is well-defined and precisely what we want to do here. */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-
-    /* Generate bitmask from condition, mask will either be 0xFF or 0 */
-    unsigned char mask = ( condition | -condition );
-    mask >>= 7;
-    mask = -mask;
-
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
-    *dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask );
+    /* low_mask is: 0 if low <= c, 0x...ff if low > c */
+    unsigned low_mask = ( (unsigned) c - low ) >> 8;
+    /* high_mask is: 0 if c <= high, 0x...ff if c > high */
+    unsigned high_mask = ( (unsigned) high - c ) >> 8;
+    return( ~( low_mask | high_mask ) & 0xff );
 }
 
-/*
- * Constant flow conditional assignment to uint_32
+/* Given a value in the range 0..63, return the corresponding Base64 digit.
+ * The implementation assumes that letters are consecutive (e.g. ASCII
+ * but not EBCDIC).
  */
-static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src,
-                                       uint32_t condition )
+MBEDTLS_STATIC_TESTABLE
+unsigned char mbedtls_base64_enc_char( unsigned char val )
 {
-    /* MSVC has a warning about unary minus on unsigned integer types,
-     * but this is well-defined and precisely what we want to do here. */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-
-    /* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */
-    uint32_t mask = ( condition | -condition );
-    mask >>= 31;
-    mask = -mask;
-
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
-    *dest = ( src & mask ) | ( ( *dest ) & ~mask );
-}
-
-/*
- * Constant flow check for equality
- */
-static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b )
-{
-    size_t difference = in_a ^ in_b;
-
-    /* MSVC has a warning about unary minus on unsigned integer types,
-     * but this is well-defined and precisely what we want to do here. */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-
-    difference |= -difference;
-
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
-    /* cope with the varying size of size_t per platform */
-    difference >>= ( sizeof( difference ) * 8 - 1 );
-
-    return (unsigned char) ( 1 ^ difference );
-}
-
-/*
- * Constant flow lookup into table.
- */
-static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table,
-                                                 const size_t table_size, const size_t table_index )
-{
-    size_t i;
-    unsigned char result = 0;
-
-    for( i = 0; i < table_size; ++i )
-    {
-        mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) );
-    }
-
-    return result;
+    unsigned char digit = 0;
+    /* For each range of values, if val is in that range, mask digit with
+     * the corresponding value. Since val can only be in a single range,
+     * only at most one masking will change digit. */
+    digit |= mbedtls_base64_mask_of_range(  0, 25, val ) & ( 'A' + val );
+    digit |= mbedtls_base64_mask_of_range( 26, 51, val ) & ( 'a' + val - 26 );
+    digit |= mbedtls_base64_mask_of_range( 52, 61, val ) & ( '0' + val - 52 );
+    digit |= mbedtls_base64_mask_of_range( 62, 62, val ) & '+';
+    digit |= mbedtls_base64_mask_of_range( 63, 63, val ) & '/';
+    return( digit );
 }
 
 /*
@@ -198,17 +113,12 @@
         C2 = *src++;
         C3 = *src++;
 
-        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                            ( ( C1 >> 2 ) & 0x3F ) );
-
-        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                            ( ( ( ( C1 &  3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
-
-        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                            ( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) );
-
-        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                            ( C3 & 0x3F ) );
+        *p++ = mbedtls_base64_enc_char( ( C1 >> 2 ) & 0x3F );
+        *p++ = mbedtls_base64_enc_char( ( ( ( C1 &  3 ) << 4 ) + ( C2 >> 4 ) )
+                                        & 0x3F );
+        *p++ = mbedtls_base64_enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) )
+                                        & 0x3F );
+        *p++ = mbedtls_base64_enc_char( C3 & 0x3F );
     }
 
     if( i < slen )
@@ -216,15 +126,12 @@
         C1 = *src++;
         C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
 
-        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                            ( ( C1 >> 2 ) & 0x3F ) );
-
-        *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                            ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
+        *p++ = mbedtls_base64_enc_char( ( C1 >> 2 ) & 0x3F );
+        *p++ = mbedtls_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) )
+                                        & 0x3F );
 
         if( ( i + 1 ) < slen )
-             *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
-                                                 ( ( ( C2 & 15 ) << 2 ) & 0x3F ) );
+             *p++ = mbedtls_base64_enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F );
         else *p++ = '=';
 
         *p++ = '=';
@@ -236,26 +143,58 @@
     return( 0 );
 }
 
+/* Given a Base64 digit, return its value.
+ * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
+ * return -1.
+ *
+ * The implementation assumes that letters are consecutive (e.g. ASCII
+ * but not EBCDIC).
+ *
+ * The implementation is constant-flow (no branch or memory access depending
+ * on the value of c) unless the compiler inlines and optimizes a specific
+ * access.
+ */
+MBEDTLS_STATIC_TESTABLE
+signed char mbedtls_base64_dec_value( unsigned char c )
+{
+    unsigned char val = 0;
+    /* For each range of digits, if c is in that range, mask val with
+     * the corresponding value. Since c can only be in a single range,
+     * only at most one masking will change val. Set val to one plus
+     * the desired value so that it stays 0 if c is in none of the ranges. */
+    val |= mbedtls_base64_mask_of_range( 'A', 'Z', c ) & ( c - 'A' +  0 + 1 );
+    val |= mbedtls_base64_mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 );
+    val |= mbedtls_base64_mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 );
+    val |= mbedtls_base64_mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 );
+    val |= mbedtls_base64_mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 );
+    /* At this point, val is 0 if c is an invalid digit and v+1 if c is
+     * a digit with the value v. */
+    return( val - 1 );
+}
+
 /*
  * Decode a base64-formatted buffer
  */
 int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
                    const unsigned char *src, size_t slen )
 {
-    size_t i, n;
-    uint32_t j, x;
+    size_t i; /* index in source */
+    size_t n; /* number of digits or trailing = in source */
+    uint32_t x; /* value accumulator */
+    unsigned accumulated_digits = 0;
+    unsigned equals = 0;
+    int spaces_present = 0;
     unsigned char *p;
-    unsigned char dec_map_lookup;
 
     /* First pass: check for validity and get output length */
-    for( i = n = j = 0; i < slen; i++ )
+    for( i = n = 0; i < slen; i++ )
     {
         /* Skip spaces before checking for EOL */
-        x = 0;
+        spaces_present = 0;
         while( i < slen && src[i] == ' ' )
         {
             ++i;
-            ++x;
+            spaces_present = 1;
         }
 
         /* Spaces at end of buffer are OK */
@@ -270,20 +209,24 @@
             continue;
 
         /* Space inside a line is an error */
-        if( x != 0 )
+        if( spaces_present )
             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
 
-        if( src[i] == '=' && ++j > 2 )
+        if( src[i] > 127 )
             return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
 
-        dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] );
-
-        if( src[i] > 127 || dec_map_lookup == 127 )
-            return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-
-        if( dec_map_lookup < 64 && j != 0 )
-            return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
-
+        if( src[i] == '=' )
+        {
+            if( ++equals > 2 )
+                return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+        }
+        else
+        {
+            if( equals != 0 )
+                return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+            if( mbedtls_base64_dec_value( src[i] ) < 0 )
+                return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
+        }
         n++;
     }
 
@@ -298,7 +241,7 @@
      *     n = ( ( n * 6 ) + 7 ) >> 3;
      */
     n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
-    n -= j;
+    n -= equals;
 
     if( dst == NULL || dlen < n )
     {
@@ -306,22 +249,24 @@
         return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
     }
 
-   for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
-   {
+    equals = 0;
+    for( x = 0, p = dst; i > 0; i--, src++ )
+    {
         if( *src == '\r' || *src == '\n' || *src == ' ' )
             continue;
 
-        dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src );
+        x = x << 6;
+        if( *src == '=' )
+            ++equals;
+        else
+            x |= mbedtls_base64_dec_value( *src );
 
-        mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) );
-        x  = ( x << 6 ) | ( dec_map_lookup & 0x3F );
-
-        if( ++n == 4 )
+        if( ++accumulated_digits == 4 )
         {
-            n = 0;
-            if( j > 0 ) *p++ = MBEDTLS_BYTE_2( x );
-            if( j > 1 ) *p++ = MBEDTLS_BYTE_1( x );
-            if( j > 2 ) *p++ = MBEDTLS_BYTE_0( x );
+            accumulated_digits = 0;
+            *p++ = MBEDTLS_BYTE_2( x );
+            if( equals <= 1 ) *p++ = MBEDTLS_BYTE_1( x );
+            if( equals <= 0 ) *p++ = MBEDTLS_BYTE_0( x );
         }
     }
 
diff --git a/library/base64_invasive.h b/library/base64_invasive.h
new file mode 100644
index 0000000..9e26471
--- /dev/null
+++ b/library/base64_invasive.h
@@ -0,0 +1,55 @@
+/**
+ * \file base_invasive.h
+ *
+ * \brief Base64 module: interfaces for invasive testing only.
+ *
+ * The interfaces in this file are intended for testing purposes only.
+ * They SHOULD NOT be made available in library integrations except when
+ * building the library for testing.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef MBEDTLS_BASE64_INVASIVE_H
+#define MBEDTLS_BASE64_INVASIVE_H
+
+#include "common.h"
+
+#if defined(MBEDTLS_TEST_HOOKS)
+/* Return 0xff if low <= c <= high, 0 otherwise.
+ *
+ * Constant flow with respect to c.
+ */
+unsigned char mbedtls_base64_mask_of_range( unsigned char low,
+                                            unsigned char high,
+                                            unsigned char c );
+
+/* Given a value in the range 0..63, return the corresponding Base64 digit.
+ *
+ * Operates in constant time (no branches or memory access depending on val).
+ */
+unsigned char mbedtls_base64_enc_char( unsigned char val );
+
+/* Given a Base64 digit, return its value.
+ * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
+ * return -1.
+ *
+ * Operates in constant time (no branches or memory access depending on c).
+ */
+signed char mbedtls_base64_dec_value( unsigned char c );
+#endif /* MBEDTLS_TEST_HOOKS */
+
+#endif /* MBEDTLS_SSL_INVASIVE_H */
diff --git a/library/common.h b/library/common.h
index 9b10ec8..a630fcc 100644
--- a/library/common.h
+++ b/library/common.h
@@ -87,7 +87,7 @@
  * big-endian order (MSB first).
  *
  * \param   data    Base address of the memory to get the four bytes from.
- * \param   offset  Offset from \p base of the first and most significant
+ * \param   offset  Offset from \p data of the first and most significant
  *                  byte of the four bytes to build the 32 bits unsigned
  *                  integer from.
  */
@@ -107,7 +107,7 @@
  * \param   n       32 bits unsigned integer to put in memory.
  * \param   data    Base address of the memory where to put the 32
  *                  bits unsigned integer in.
- * \param   offset  Offset from \p base where to put the most significant
+ * \param   offset  Offset from \p data where to put the most significant
  *                  byte of the 32 bits unsigned integer \p n.
  */
 #ifndef MBEDTLS_PUT_UINT32_BE
@@ -125,7 +125,7 @@
  * little-endian order (LSB first).
  *
  * \param   data    Base address of the memory to get the four bytes from.
- * \param   offset  Offset from \p base of the first and least significant
+ * \param   offset  Offset from \p data of the first and least significant
  *                  byte of the four bytes to build the 32 bits unsigned
  *                  integer from.
  */
@@ -145,7 +145,7 @@
  * \param   n       32 bits unsigned integer to put in memory.
  * \param   data    Base address of the memory where to put the 32
  *                  bits unsigned integer in.
- * \param   offset  Offset from \p base where to put the least significant
+ * \param   offset  Offset from \p data where to put the least significant
  *                  byte of the 32 bits unsigned integer \p n.
  */
 #ifndef MBEDTLS_PUT_UINT32_LE
@@ -163,7 +163,7 @@
  * little-endian order (LSB first).
  *
  * \param   data    Base address of the memory to get the two bytes from.
- * \param   offset  Offset from \p base of the first and least significant
+ * \param   offset  Offset from \p data of the first and least significant
  *                  byte of the two bytes to build the 16 bits unsigned
  *                  integer from.
  */
@@ -181,7 +181,7 @@
  * \param   n       16 bits unsigned integer to put in memory.
  * \param   data    Base address of the memory where to put the 16
  *                  bits unsigned integer in.
- * \param   offset  Offset from \p base where to put the least significant
+ * \param   offset  Offset from \p data where to put the least significant
  *                  byte of the 16 bits unsigned integer \p n.
  */
 #ifndef MBEDTLS_PUT_UINT16_LE
@@ -197,7 +197,7 @@
  * big-endian order (MSB first).
  *
  * \param   data    Base address of the memory to get the two bytes from.
- * \param   offset  Offset from \p base of the first and most significant
+ * \param   offset  Offset from \p data of the first and most significant
  *                  byte of the two bytes to build the 16 bits unsigned
  *                  integer from.
  */
@@ -215,7 +215,7 @@
  * \param   n       16 bits unsigned integer to put in memory.
  * \param   data    Base address of the memory where to put the 16
  *                  bits unsigned integer in.
- * \param   offset  Offset from \p base where to put the most significant
+ * \param   offset  Offset from \p data where to put the most significant
  *                  byte of the 16 bits unsigned integer \p n.
  */
 #ifndef MBEDTLS_PUT_UINT16_BE
@@ -227,11 +227,83 @@
 #endif
 
 /**
+ * Get the unsigned 24 bits integer corresponding to three bytes in
+ * big-endian order (MSB first).
+ *
+ * \param   data    Base address of the memory to get the three bytes from.
+ * \param   offset  Offset from \p data of the first and most significant
+ *                  byte of the three bytes to build the 24 bits unsigned
+ *                  integer from.
+ */
+#ifndef MBEDTLS_GET_UINT24_BE
+#define MBEDTLS_GET_UINT24_BE( data , offset )                  \
+    (                                                           \
+          ( (uint32_t) ( data )[( offset )    ] << 16 )         \
+        | ( (uint32_t) ( data )[( offset ) + 1] << 8  )         \
+        | ( (uint32_t) ( data )[( offset ) + 2]       )         \
+    )
+#endif
+
+/**
+ * Put in memory a 24 bits unsigned integer in big-endian order.
+ *
+ * \param   n       24 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 24
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p data where to put the most significant
+ *                  byte of the 24 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT24_BE
+#define MBEDTLS_PUT_UINT24_BE( n, data, offset )                \
+{                                                               \
+    ( data )[( offset )    ] = MBEDTLS_BYTE_2( n );             \
+    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
+    ( data )[( offset ) + 2] = MBEDTLS_BYTE_0( n );             \
+}
+#endif
+
+/**
+ * Get the unsigned 24 bits integer corresponding to three bytes in
+ * little-endian order (LSB first).
+ *
+ * \param   data    Base address of the memory to get the three bytes from.
+ * \param   offset  Offset from \p data of the first and least significant
+ *                  byte of the three bytes to build the 24 bits unsigned
+ *                  integer from.
+ */
+#ifndef MBEDTLS_GET_UINT24_LE
+#define MBEDTLS_GET_UINT24_LE( data, offset )                   \
+    (                                                           \
+          ( (uint32_t) ( data )[( offset )    ]       )         \
+        | ( (uint32_t) ( data )[( offset ) + 1] <<  8 )         \
+        | ( (uint32_t) ( data )[( offset ) + 2] << 16 )         \
+    )
+#endif
+
+/**
+ * Put in memory a 24 bits unsigned integer in little-endian order.
+ *
+ * \param   n       24 bits unsigned integer to put in memory.
+ * \param   data    Base address of the memory where to put the 24
+ *                  bits unsigned integer in.
+ * \param   offset  Offset from \p data where to put the least significant
+ *                  byte of the 24 bits unsigned integer \p n.
+ */
+#ifndef MBEDTLS_PUT_UINT24_LE
+#define MBEDTLS_PUT_UINT24_LE( n, data, offset )                \
+{                                                               \
+    ( data )[( offset )    ] = MBEDTLS_BYTE_0( n );             \
+    ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n );             \
+    ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n );             \
+}
+#endif
+
+/**
  * Get the unsigned 64 bits integer corresponding to eight bytes in
  * big-endian order (MSB first).
  *
  * \param   data    Base address of the memory to get the eight bytes from.
- * \param   offset  Offset from \p base of the first and most significant
+ * \param   offset  Offset from \p data of the first and most significant
  *                  byte of the eight bytes to build the 64 bits unsigned
  *                  integer from.
  */
@@ -255,7 +327,7 @@
  * \param   n       64 bits unsigned integer to put in memory.
  * \param   data    Base address of the memory where to put the 64
  *                  bits unsigned integer in.
- * \param   offset  Offset from \p base where to put the most significant
+ * \param   offset  Offset from \p data where to put the most significant
  *                  byte of the 64 bits unsigned integer \p n.
  */
 #ifndef MBEDTLS_PUT_UINT64_BE
@@ -277,7 +349,7 @@
  * little-endian order (LSB first).
  *
  * \param   data    Base address of the memory to get the eight bytes from.
- * \param   offset  Offset from \p base of the first and least significant
+ * \param   offset  Offset from \p data of the first and least significant
  *                  byte of the eight bytes to build the 64 bits unsigned
  *                  integer from.
  */
@@ -301,7 +373,7 @@
  * \param   n       64 bits unsigned integer to put in memory.
  * \param   data    Base address of the memory where to put the 64
  *                  bits unsigned integer in.
- * \param   offset  Offset from \p base where to put the least significant
+ * \param   offset  Offset from \p data where to put the least significant
  *                  byte of the 64 bits unsigned integer \p n.
  */
 #ifndef MBEDTLS_PUT_UINT64_LE
diff --git a/library/des.c b/library/des.c
index 7f90faa..91d22b5 100644
--- a/library/des.c
+++ b/library/des.c
@@ -28,6 +28,7 @@
 #if defined(MBEDTLS_DES_C)
 
 #include "mbedtls/des.h"
+#include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 
 #include <string.h>
@@ -642,6 +643,7 @@
                     unsigned char *output )
 {
     int i;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[8];
 
     if( length % 8 )
@@ -654,7 +656,9 @@
             for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( input[i] ^ iv[i] );
 
-            mbedtls_des_crypt_ecb( ctx, output, output );
+            ret = mbedtls_des_crypt_ecb( ctx, output, output );
+            if( ret != 0 )
+                goto exit;
             memcpy( iv, output, 8 );
 
             input  += 8;
@@ -667,7 +671,9 @@
         while( length > 0 )
         {
             memcpy( temp, input, 8 );
-            mbedtls_des_crypt_ecb( ctx, input, output );
+            ret = mbedtls_des_crypt_ecb( ctx, input, output );
+            if( ret != 0 )
+                goto exit;
 
             for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( output[i] ^ iv[i] );
@@ -679,8 +685,10 @@
             length -= 8;
         }
     }
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -741,6 +749,7 @@
                      unsigned char *output )
 {
     int i;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char temp[8];
 
     if( length % 8 )
@@ -753,7 +762,9 @@
             for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( input[i] ^ iv[i] );
 
-            mbedtls_des3_crypt_ecb( ctx, output, output );
+            ret = mbedtls_des3_crypt_ecb( ctx, output, output );
+            if( ret != 0 )
+                goto exit;
             memcpy( iv, output, 8 );
 
             input  += 8;
@@ -766,7 +777,9 @@
         while( length > 0 )
         {
             memcpy( temp, input, 8 );
-            mbedtls_des3_crypt_ecb( ctx, input, output );
+            ret = mbedtls_des3_crypt_ecb( ctx, input, output );
+            if( ret != 0 )
+                goto exit;
 
             for( i = 0; i < 8; i++ )
                 output[i] = (unsigned char)( output[i] ^ iv[i] );
@@ -778,8 +791,10 @@
             length -= 8;
         }
     }
+    ret = 0;
 
-    return( 0 );
+exit:
+    return( ret );
 }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -872,39 +887,43 @@
         switch( i )
         {
         case 0:
-            mbedtls_des_setkey_dec( &ctx, des3_test_keys );
+            ret = mbedtls_des_setkey_dec( &ctx, des3_test_keys );
             break;
 
         case 1:
-            mbedtls_des_setkey_enc( &ctx, des3_test_keys );
+            ret = mbedtls_des_setkey_enc( &ctx, des3_test_keys );
             break;
 
         case 2:
-            mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
             break;
 
         case 3:
-            mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
             break;
 
         case 4:
-            mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
             break;
 
         case 5:
-            mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
             break;
 
         default:
             return( 1 );
         }
+        if( ret != 0 )
+            goto exit;
 
         for( j = 0; j < 100; j++ )
         {
             if( u == 0 )
-                mbedtls_des_crypt_ecb( &ctx, buf, buf );
+                ret = mbedtls_des_crypt_ecb( &ctx, buf, buf );
             else
-                mbedtls_des3_crypt_ecb( &ctx3, buf, buf );
+                ret = mbedtls_des3_crypt_ecb( &ctx3, buf, buf );
+            if( ret != 0 )
+                goto exit;
         }
 
         if( ( v == MBEDTLS_DES_DECRYPT &&
@@ -947,41 +966,45 @@
         switch( i )
         {
         case 0:
-            mbedtls_des_setkey_dec( &ctx, des3_test_keys );
+            ret = mbedtls_des_setkey_dec( &ctx, des3_test_keys );
             break;
 
         case 1:
-            mbedtls_des_setkey_enc( &ctx, des3_test_keys );
+            ret = mbedtls_des_setkey_enc( &ctx, des3_test_keys );
             break;
 
         case 2:
-            mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set2key_dec( &ctx3, des3_test_keys );
             break;
 
         case 3:
-            mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set2key_enc( &ctx3, des3_test_keys );
             break;
 
         case 4:
-            mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set3key_dec( &ctx3, des3_test_keys );
             break;
 
         case 5:
-            mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
+            ret = mbedtls_des3_set3key_enc( &ctx3, des3_test_keys );
             break;
 
         default:
             return( 1 );
         }
+        if( ret != 0 )
+            goto exit;
 
         if( v == MBEDTLS_DES_DECRYPT )
         {
             for( j = 0; j < 100; j++ )
             {
                 if( u == 0 )
-                    mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                    ret = mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
                 else
-                    mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+                    ret = mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+                if( ret != 0 )
+                    goto exit;
             }
         }
         else
@@ -991,9 +1014,11 @@
                 unsigned char tmp[8];
 
                 if( u == 0 )
-                    mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
+                    ret = mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf );
                 else
-                    mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+                    ret = mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf );
+                if( ret != 0 )
+                    goto exit;
 
                 memcpy( tmp, prv, 8 );
                 memcpy( prv, buf, 8 );
@@ -1027,6 +1052,8 @@
     mbedtls_des_free( &ctx );
     mbedtls_des3_free( &ctx3 );
 
+    if( ret != 0 )
+        ret = 1;
     return( ret );
 }
 
diff --git a/library/ecdh.c b/library/ecdh.c
index b72bd1f..ddd4ef5 100644
--- a/library/ecdh.c
+++ b/library/ecdh.c
@@ -806,6 +806,60 @@
 #endif
 }
 
+static int ecdh_tls13_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
+                                            const unsigned char *buf,
+                                            size_t buf_len )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *p = buf;
+    size_t data_len;
+
+    if( buf_len < 3 )
+        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+
+    data_len = MBEDTLS_GET_UINT16_BE( p, 0 );
+    p += 2;
+
+    if( data_len < 1 || data_len != ( buf_len - 2 ) )
+        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+
+    if( ( ret = mbedtls_ecp_point_read_binary( &ctx->grp,
+                                               &ctx->Qp, p, data_len ) ) != 0)
+    {
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+/*
+ * Parse and import the client's TLS 1.3 public value
+ */
+int mbedtls_ecdh_tls13_read_public( mbedtls_ecdh_context *ctx,
+                                    const unsigned char *buf,
+                                    size_t buf_len )
+{
+    ECDH_VALIDATE_RET( ctx != NULL );
+    ECDH_VALIDATE_RET( buf != NULL );
+
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+    return( ecdh_tls13_read_public_internal( ctx, buf, buf_len ) );
+#else
+    switch( ctx->var )
+    {
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+        case MBEDTLS_ECDH_VARIANT_EVEREST:
+            return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#endif
+        case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
+            return( ecdh_tls13_read_public_internal( &ctx->ctx.mbed_ecdh,
+                                                     buf, buf_len ) );
+        default:
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+#endif
+}
+
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
 
 #endif /* MBEDTLS_ECDH_C */
diff --git a/library/ecdh_misc.h b/library/ecdh_misc.h
index d1342f8..d0f338a 100644
--- a/library/ecdh_misc.h
+++ b/library/ecdh_misc.h
@@ -36,13 +36,19 @@
                                    mbedtls_ecp_group_id grp_id );
 
 /*
- * TLS 1.3 version of mbedtls_ecdh_make_params in ecdh.h
+ * TLS 1.3 version of mbedtls_ecdh_make_params
  */
 int mbedtls_ecdh_tls13_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
-                                    unsigned char *buf, size_t blen,
+                                    unsigned char *buf, size_t buf_len,
                                     int ( *f_rng )( void *, unsigned char *, size_t ),
                                     void *p_rng );
 
+/*
+ * TLS 1.3 version of mbedtls_ecdh_read_public
+ */
+int mbedtls_ecdh_tls13_read_public( mbedtls_ecdh_context *ctx,
+                                    const unsigned char *buf,
+                                    size_t buf_len );
 
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
 
diff --git a/library/gcm.c b/library/gcm.c
index 910646b..6d62564 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -431,7 +431,7 @@
     unsigned char ectr[16];
 
     if( output_size < input_length )
-        return( MBEDTLS_ERR_GCM_BAD_INPUT );
+        return( MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL );
     GCM_VALIDATE_RET( output_length != NULL );
     *output_length = input_length;
 
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index ece64b1..3670071 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -201,6 +201,8 @@
 
         case MBEDTLS_ERR_GCM_AUTH_FAILED:
             return( PSA_ERROR_INVALID_SIGNATURE );
+        case MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL:
+            return( PSA_ERROR_BUFFER_TOO_SMALL );
         case MBEDTLS_ERR_GCM_BAD_INPUT:
             return( PSA_ERROR_INVALID_ARGUMENT );
 
@@ -446,6 +448,12 @@
                 return( PSA_ERROR_INVALID_ARGUMENT );
             break;
 #endif
+#if defined(PSA_WANT_KEY_TYPE_ARIA)
+        case PSA_KEY_TYPE_ARIA:
+            if( bits != 128 && bits != 192 && bits != 256 )
+                return( PSA_ERROR_INVALID_ARGUMENT );
+            break;
+#endif
 #if defined(PSA_WANT_KEY_TYPE_CAMELLIA)
         case PSA_KEY_TYPE_CAMELLIA:
             if( bits != 128 && bits != 192 && bits != 256 )
@@ -3621,34 +3629,35 @@
 {
     psa_algorithm_t base_alg = psa_aead_get_base_algorithm( alg );
 
-#if defined(PSA_WANT_ALG_GCM)
-    if( base_alg == PSA_ALG_GCM )
+    switch(base_alg)
     {
-        /* Not checking max nonce size here as GCM spec allows almost
-         * arbitrarily large nonces. Please note that we do not generally
-         * recommend the usage of nonces of greater length than
-         * PSA_AEAD_NONCE_MAX_SIZE, as large nonces are hashed to a shorter
-         * size, which can then lead to collisions if you encrypt a very
-         * large number of messages.*/
-        if( nonce_length != 0 )
-            return( PSA_SUCCESS );
-    }
+#if defined(PSA_WANT_ALG_GCM)
+        case PSA_ALG_GCM:
+            /* Not checking max nonce size here as GCM spec allows almost
+            * arbitrarily large nonces. Please note that we do not generally
+            * recommend the usage of nonces of greater length than
+            * PSA_AEAD_NONCE_MAX_SIZE, as large nonces are hashed to a shorter
+            * size, which can then lead to collisions if you encrypt a very
+            * large number of messages.*/
+            if( nonce_length != 0 )
+                return( PSA_SUCCESS );
+            break;
 #endif /* PSA_WANT_ALG_GCM */
 #if defined(PSA_WANT_ALG_CCM)
-    if( base_alg == PSA_ALG_CCM )
-    {
-        if( nonce_length >= 7 && nonce_length <= 13 )
-            return( PSA_SUCCESS );
-    }
-    else
+        case PSA_ALG_CCM:
+            if( nonce_length >= 7 && nonce_length <= 13 )
+                return( PSA_SUCCESS );
+            break;
 #endif /* PSA_WANT_ALG_CCM */
 #if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
-    if( base_alg == PSA_ALG_CHACHA20_POLY1305 )
-    {
-        if( nonce_length == 12 )
-            return( PSA_SUCCESS );
-    }
+        case PSA_ALG_CHACHA20_POLY1305:
+            if( nonce_length == 12 )
+                return( PSA_SUCCESS );
+            break;
 #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
+        default:
+            break;
+    }
 
     return( PSA_ERROR_NOT_SUPPORTED );
 }
@@ -3950,40 +3959,40 @@
         goto exit;
     }
 
-#if defined(PSA_WANT_ALG_GCM)
-    if( operation->alg == PSA_ALG_GCM )
+    switch(operation->alg)
     {
-        /* Lengths can only be too large for GCM if size_t is bigger than 32
-         * bits. Without the guard this code will generate warnings on 32bit
-         * builds. */
+#if defined(PSA_WANT_ALG_GCM)
+        case PSA_ALG_GCM:
+            /* Lengths can only be too large for GCM if size_t is bigger than 32
+            * bits. Without the guard this code will generate warnings on 32bit
+            * builds. */
 #if SIZE_MAX > UINT32_MAX
-        if( (( uint64_t ) ad_length ) >> 61 != 0 ||
-            (( uint64_t ) plaintext_length ) > 0xFFFFFFFE0ull )
-        {
-            status = PSA_ERROR_INVALID_ARGUMENT;
-            goto exit;
-        }
+            if( (( uint64_t ) ad_length ) >> 61 != 0 ||
+                (( uint64_t ) plaintext_length ) > 0xFFFFFFFE0ull )
+            {
+                status = PSA_ERROR_INVALID_ARGUMENT;
+                goto exit;
+            }
 #endif
-    }
-    else
+            break;
 #endif /* PSA_WANT_ALG_GCM */
 #if defined(PSA_WANT_ALG_CCM)
-    if( operation->alg == PSA_ALG_CCM )
-    {
-        if( ad_length > 0xFF00 )
-        {
-            status = PSA_ERROR_INVALID_ARGUMENT;
-            goto exit;
-        }
-    }
-    else
+        case PSA_ALG_CCM:
+            if( ad_length > 0xFF00 )
+            {
+                status = PSA_ERROR_INVALID_ARGUMENT;
+                goto exit;
+            }
+            break;
 #endif /* PSA_WANT_ALG_CCM */
 #if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
-    if( operation->alg == PSA_ALG_CHACHA20_POLY1305 )
-    {
-        /* No length restrictions for ChaChaPoly. */
-    }
+        case PSA_ALG_CHACHA20_POLY1305:
+            /* No length restrictions for ChaChaPoly. */
+            break;
 #endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
+        default:
+            break;
+    }
 
     status = psa_driver_wrapper_aead_set_lengths( operation, ad_length,
                                                   plaintext_length );
@@ -5703,6 +5712,10 @@
     if( psa_get_key_bits( attributes ) == 0 )
         return( PSA_ERROR_INVALID_ARGUMENT );
 
+    /* Reject any attempt to create a public key. */
+    if( PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->core.type) )
+        return( PSA_ERROR_INVALID_ARGUMENT );
+
     status = psa_start_key_creation( PSA_KEY_CREATION_GENERATE, attributes,
                                      &slot, &driver );
     if( status != PSA_SUCCESS )
diff --git a/library/psa_crypto_aead.c b/library/psa_crypto_aead.c
index a72865c..c7f7352 100644
--- a/library/psa_crypto_aead.c
+++ b/library/psa_crypto_aead.c
@@ -510,9 +510,6 @@
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
     if( operation->alg == PSA_ALG_GCM )
     {
-        if( output_size < input_length )
-            return( PSA_ERROR_BUFFER_TOO_SMALL );
-
         status =  mbedtls_to_psa_error(
             mbedtls_gcm_update( &operation->ctx.gcm,
                                 input, input_length,
@@ -567,9 +564,6 @@
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
     if( operation->alg == PSA_ALG_GCM )
     {
-        if( ciphertext_size < 15 )
-            return( PSA_ERROR_BUFFER_TOO_SMALL );
-
         status =  mbedtls_to_psa_error(
             mbedtls_gcm_finish( &operation->ctx.gcm,
                                 ciphertext, ciphertext_size, ciphertext_length,
diff --git a/library/psa_crypto_cipher.c b/library/psa_crypto_cipher.c
index 2268fc5..ce8ab5c 100644
--- a/library/psa_crypto_cipher.c
+++ b/library/psa_crypto_cipher.c
@@ -115,6 +115,9 @@
         case PSA_KEY_TYPE_AES:
             cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
             break;
+        case PSA_KEY_TYPE_ARIA:
+            cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
+            break;
         case PSA_KEY_TYPE_DES:
             /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
              * and 192 for three-key Triple-DES. */
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 3f3f505..dbef6aa 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -307,6 +307,11 @@
       + ( MBEDTLS_SSL_CID_OUT_LEN_MAX ) )
 #endif
 
+#define MBEDTLS_TLS1_3_MD_MAX_SIZE         MBEDTLS_MD_MAX_SIZE
+
+#define MBEDTLS_CLIENT_HELLO_RANDOM_LEN 32
+#define MBEDTLS_SERVER_HELLO_RANDOM_LEN 32
+
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
 /**
  * \brief          Return the maximum fragment length (payload, in bytes) for
@@ -409,6 +414,32 @@
         }                                                                \
     } while( 0 )
 
+/**
+ * \brief        This macro checks if the remaining length in an input buffer is
+ *               greater or equal than a needed length. If it is not the case, it
+ *               returns #MBEDTLS_ERR_SSL_DECODE_ERROR error and pends a
+ *               #MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR alert message.
+ *
+ *               This is a function-like macro. It is guaranteed to evaluate each
+ *               argument exactly once.
+ *
+ * \param cur    Pointer to the current position in the buffer.
+ * \param end    Pointer to one past the end of the buffer.
+ * \param need   Needed length in bytes.
+ *
+ */
+#define MBEDTLS_SSL_CHK_BUF_READ_PTR( cur, end, need )                          \
+    do {                                                                        \
+        if( mbedtls_ssl_chk_buf_ptr( ( cur ), ( end ), ( need ) ) != 0 )        \
+        {                                                                       \
+            MBEDTLS_SSL_DEBUG_MSG( 1,                                           \
+                                   ( "missing input data in %s", __func__ ) );  \
+            MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,   \
+                                          MBEDTLS_ERR_SSL_DECODE_ERROR );       \
+            return( MBEDTLS_ERR_SSL_DECODE_ERROR );                             \
+        }                                                                       \
+    } while( 0 )
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -478,6 +509,27 @@
 };
 typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set;
 
+typedef struct
+{
+    unsigned char binder_key                  [ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+    unsigned char client_early_traffic_secret [ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+    unsigned char early_exporter_master_secret[ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+} mbedtls_ssl_tls1_3_early_secrets;
+
+typedef struct
+{
+    unsigned char client_handshake_traffic_secret[ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+    unsigned char server_handshake_traffic_secret[ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+} mbedtls_ssl_tls1_3_handshake_secrets;
+
+typedef struct
+{
+    unsigned char client_application_traffic_secret_N[ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+    unsigned char server_application_traffic_secret_N[ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+    unsigned char exporter_master_secret             [ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+    unsigned char resumption_master_secret           [ MBEDTLS_TLS1_3_MD_MAX_SIZE ];
+} mbedtls_ssl_tls1_3_application_secrets;
+
 /*
  * This structure contains the parameters only needed during handshake.
  */
@@ -486,6 +538,9 @@
     /*
      * Handshake specific crypto variables
      */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
+    int tls1_3_kex_modes; /*!< key exchange modes for TLS 1.3 */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
     defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
@@ -573,8 +628,8 @@
                                               flight being received          */
     mbedtls_ssl_transform *alt_transform_out;   /*!<  Alternative transform for
                                               resending messages             */
-    unsigned char alt_out_ctr[8];       /*!<  Alternative record epoch/counter
-                                              for resending messages         */
+    unsigned char alt_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!<  Alternative record epoch/counter
+                                                                      for resending messages         */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     /* The state of CID configuration in this handshake. */
@@ -663,7 +718,9 @@
 
     size_t pmslen;                      /*!<  premaster length        */
 
-    unsigned char randbytes[64];        /*!<  random bytes            */
+    unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN +
+                            MBEDTLS_SERVER_HELLO_RANDOM_LEN];
+                                        /*!<  random bytes            */
     unsigned char premaster[MBEDTLS_PREMASTER_SIZE];
                                         /*!<  premaster secret        */
 
@@ -675,6 +732,15 @@
     int extensions_present;             /*!< extension presence; Each bitfield
                                              represents an extension and defined
                                              as \c MBEDTLS_SSL_EXT_XXX */
+
+    union
+    {
+        unsigned char early    [MBEDTLS_TLS1_3_MD_MAX_SIZE];
+        unsigned char handshake[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+        unsigned char app      [MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    } tls1_3_master_secrets;
+
+    mbedtls_ssl_tls1_3_handshake_secrets tls13_hs_secrets;
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
@@ -819,7 +885,9 @@
     /* We need the Hello random bytes in order to re-derive keys from the
      * Master Secret and other session info,
      * see ssl_tls12_populate_transform() */
-    unsigned char randbytes[64]; /*!< ServerHello.random+ClientHello.random */
+    unsigned char randbytes[MBEDTLS_SERVER_HELLO_RANDOM_LEN +
+                            MBEDTLS_CLIENT_HELLO_RANDOM_LEN];
+                            /*!< ServerHello.random+ClientHello.random */
 #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
 };
 
@@ -866,14 +934,14 @@
 
 typedef struct
 {
-    uint8_t ctr[8];         /* In TLS:  The implicit record sequence number.
-                             * In DTLS: The 2-byte epoch followed by
-                             *          the 6-byte sequence number.
-                             * This is stored as a raw big endian byte array
-                             * as opposed to a uint64_t because we rarely
-                             * need to perform arithmetic on this, but do
-                             * need it as a Byte array for the purpose of
-                             * MAC computations.                             */
+    uint8_t ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN];  /* In TLS:  The implicit record sequence number.
+                                                    * In DTLS: The 2-byte epoch followed by
+                                                    *          the 6-byte sequence number.
+                                                    * This is stored as a raw big endian byte array
+                                                    * as opposed to a uint64_t because we rarely
+                                                    * need to perform arithmetic on this, but do
+                                                    * need it as a Byte array for the purpose of
+                                                    * MAC computations.                             */
     uint8_t type;           /* The record content type.                      */
     uint8_t ver[2];         /* SSL/TLS version as present on the wire.
                              * Convert to internal presentation of versions
@@ -956,6 +1024,14 @@
  */
 void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl );
 
+/* set inbound transform of ssl context */
+void mbedtls_ssl_set_inbound_transform( mbedtls_ssl_context *ssl,
+                                        mbedtls_ssl_transform *transform );
+
+/* set outbound transform of ssl context */
+void mbedtls_ssl_set_outbound_transform( mbedtls_ssl_context *ssl,
+                                         mbedtls_ssl_transform *transform );
+
 int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl );
 int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl );
 void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl );
@@ -1415,6 +1491,53 @@
                    MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK_ALL ) );
 }
 
+/**
+ * Given a list of key exchange modes, check if at least one of them is
+ * supported.
+ *
+ * \param[in] ssl  SSL context
+ * \param kex_modes_mask  Mask of the key exchange modes to check
+ *
+ * \return 0 if at least one of the key exchange modes is supported,
+ *         !=0 otherwise.
+ */
+static inline unsigned mbedtls_ssl_tls1_3_check_kex_modes( mbedtls_ssl_context *ssl,
+                                                           int kex_modes_mask )
+{
+    return( ( ssl->handshake->tls1_3_kex_modes & kex_modes_mask ) == 0 );
+}
+
+static inline int mbedtls_ssl_tls1_3_psk_enabled( mbedtls_ssl_context *ssl )
+{
+    return( ! mbedtls_ssl_tls1_3_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK ) );
+}
+
+static inline int mbedtls_ssl_tls1_3_psk_ephemeral_enabled(
+                                                    mbedtls_ssl_context *ssl )
+{
+    return( ! mbedtls_ssl_tls1_3_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK_EPHEMERAL ) );
+}
+
+static inline int mbedtls_ssl_tls1_3_ephemeral_enabled( mbedtls_ssl_context *ssl )
+{
+    return( ! mbedtls_ssl_tls1_3_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_EPHEMERAL ) );
+}
+
+static inline int mbedtls_ssl_tls1_3_some_ephemeral_enabled( mbedtls_ssl_context *ssl )
+{
+    return( ! mbedtls_ssl_tls1_3_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_EPHEMERAL_ALL ) );
+}
+
+static inline int mbedtls_ssl_tls1_3_some_psk_enabled( mbedtls_ssl_context *ssl )
+{
+    return( ! mbedtls_ssl_tls1_3_check_kex_modes( ssl,
+                   MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK_ALL ) );
+}
+
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
 
 /**
@@ -1504,19 +1627,31 @@
                                            unsigned hs_type,
                                            unsigned char **buf,
                                            size_t *buflen );
+
+/*
+ * Handler of TLS 1.3 server certificate message
+ */
+int mbedtls_ssl_tls13_process_certificate( mbedtls_ssl_context *ssl );
+
 /*
  * Write TLS 1.3 handshake message tail
  */
 int mbedtls_ssl_tls13_finish_handshake_msg( mbedtls_ssl_context *ssl,
                                             size_t buf_len,
                                             size_t msg_len );
-/*
- * Update checksum with handshake header
- */
+
 void mbedtls_ssl_tls13_add_hs_hdr_to_checksum( mbedtls_ssl_context *ssl,
                                                unsigned hs_type,
                                                size_t total_hs_len );
 
+/*
+ * Update checksum of handshake messages.
+ */
+void mbedtls_ssl_tls1_3_add_hs_msg_to_checksum( mbedtls_ssl_context *ssl,
+                                                unsigned hs_type,
+                                                unsigned char const *msg,
+                                                size_t msg_len );
+
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
 /*
  * Write TLS 1.3 Signature Algorithm extension
@@ -1530,4 +1665,11 @@
 
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
 
+/* Get handshake transcript */
+int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl,
+                                          const mbedtls_md_type_t md,
+                                          unsigned char *dst,
+                                          size_t dst_len,
+                                          size_t *olen );
+
 #endif /* ssl_misc.h */
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index 3bf4a60..3795c65 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -2101,7 +2101,7 @@
 static int ssl_swap_epochs( mbedtls_ssl_context *ssl )
 {
     mbedtls_ssl_transform *tmp_transform;
-    unsigned char tmp_out_ctr[8];
+    unsigned char tmp_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN];
 
     if( ssl->transform_out == ssl->handshake->alt_transform_out )
     {
@@ -2117,9 +2117,11 @@
     ssl->handshake->alt_transform_out = tmp_transform;
 
     /* Swap epoch + sequence_number */
-    memcpy( tmp_out_ctr,                 ssl->cur_out_ctr,            8 );
-    memcpy( ssl->cur_out_ctr,            ssl->handshake->alt_out_ctr, 8 );
-    memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr,                 8 );
+    memcpy( tmp_out_ctr, ssl->cur_out_ctr, sizeof( tmp_out_ctr ) );
+    memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr,
+            sizeof( ssl->cur_out_ctr ) );
+    memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr,
+            sizeof( ssl->handshake->alt_out_ctr ) );
 
     /* Adjust to the newly activated transform */
     mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out );
@@ -2562,7 +2564,7 @@
         mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
                            ssl->conf->transport, ssl->out_hdr + 1 );
 
-        memcpy( ssl->out_ctr, ssl->cur_out_ctr, 8 );
+        memcpy( ssl->out_ctr, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN );
         MBEDTLS_PUT_UINT16_BE( len, ssl->out_len, 0);
 
         if( ssl->transform_out != NULL )
@@ -2574,7 +2576,7 @@
             rec.data_len    = ssl->out_msglen;
             rec.data_offset = ssl->out_msg - rec.buf;
 
-            memcpy( &rec.ctr[0], ssl->out_ctr, 8 );
+            memcpy( &rec.ctr[0], ssl->out_ctr, sizeof( rec.ctr ) );
             mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver,
                                        ssl->conf->transport, rec.ver );
             rec.type = ssl->out_msgtype;
@@ -3649,9 +3651,12 @@
 #endif
         {
             unsigned i;
-            for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- )
+            for( i = MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
+                 i > mbedtls_ssl_ep_len( ssl ); i-- )
+            {
                 if( ++ssl->in_ctr[i - 1] != 0 )
                     break;
+            }
 
             /* The loop goes to its end iff the counter is wrapping */
             if( i == mbedtls_ssl_ep_len( ssl ) )
@@ -4791,7 +4796,7 @@
     }
     else
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
-    memset( ssl->in_ctr, 0, 8 );
+    memset( ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN );
 
     mbedtls_ssl_update_in_pointers( ssl );
 
@@ -4827,12 +4832,12 @@
     {
         ssl->out_ctr = ssl->out_hdr +  3;
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-        ssl->out_cid = ssl->out_ctr +  8;
+        ssl->out_cid = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
         ssl->out_len = ssl->out_cid;
         if( transform != NULL )
             ssl->out_len += transform->out_cid_len;
 #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-        ssl->out_len = ssl->out_ctr + 8;
+        ssl->out_len = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
         ssl->out_iv  = ssl->out_len + 2;
     }
@@ -4881,17 +4886,17 @@
          * ssl_parse_record_header(). */
         ssl->in_ctr = ssl->in_hdr +  3;
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-        ssl->in_cid = ssl->in_ctr +  8;
+        ssl->in_cid = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
         ssl->in_len = ssl->in_cid; /* Default: no CID */
 #else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-        ssl->in_len = ssl->in_ctr + 8;
+        ssl->in_len = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
         ssl->in_iv  = ssl->in_len + 2;
     }
     else
 #endif
     {
-        ssl->in_ctr = ssl->in_hdr - 8;
+        ssl->in_ctr = ssl->in_hdr - MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
         ssl->in_len = ssl->in_hdr + 3;
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
         ssl->in_cid = ssl->in_len;
@@ -5065,9 +5070,11 @@
     }
 
     in_ctr_cmp = memcmp( ssl->in_ctr + ep_len,
-                        ssl->conf->renego_period + ep_len, 8 - ep_len );
-    out_ctr_cmp = memcmp( ssl->cur_out_ctr + ep_len,
-                          ssl->conf->renego_period + ep_len, 8 - ep_len );
+                         &ssl->conf->renego_period[ep_len],
+                         MBEDTLS_SSL_SEQUENCE_NUMBER_LEN - ep_len );
+    out_ctr_cmp = memcmp( &ssl->cur_out_ctr[ep_len],
+                          &ssl->conf->renego_period[ep_len],
+                          sizeof( ssl->cur_out_ctr ) - ep_len );
 
     if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 )
     {
@@ -5551,6 +5558,20 @@
     mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) );
 }
 
+void mbedtls_ssl_set_inbound_transform( mbedtls_ssl_context *ssl,
+                                        mbedtls_ssl_transform *transform )
+{
+    ssl->transform_in = transform;
+    memset( ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN );
+}
+
+void mbedtls_ssl_set_outbound_transform( mbedtls_ssl_context *ssl,
+                                         mbedtls_ssl_transform *transform )
+{
+    ssl->transform_out = transform;
+    memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) );
+}
+
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 
 void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl )
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index b8c4314..e27fdff 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -1220,7 +1220,8 @@
             return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
         }
 
-        memcpy( ssl->cur_out_ctr + 2, ssl->in_ctr + 2, 6 );
+        memcpy( &ssl->cur_out_ctr[2], ssl->in_ctr + 2,
+                sizeof( ssl->cur_out_ctr ) - 2 );
 
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
         if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index f33f106..c507950 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -587,7 +587,6 @@
 #endif /* MBEDTLS_USE_PSA_CRYPTO &&
           MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 static mbedtls_tls_prf_types tls_prf_get_type( mbedtls_ssl_tls_prf_cb *tls_prf )
 {
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
@@ -608,7 +607,6 @@
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
     return( MBEDTLS_SSL_TLS_PRF_NONE );
 }
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 int  mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf,
                           const unsigned char *secret, size_t slen,
@@ -660,8 +658,9 @@
  * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random
  * - [in] minor_ver: SSL/TLS minor version
  * - [in] endpoint: client or server
- * - [in] ssl: optionally used for:
- *        - MBEDTLS_SSL_EXPORT_KEYS: ssl->conf->{f,p}_export_keys
+ * - [in] ssl: used for:
+ *        - ssl->conf->{f,p}_export_keys
+ *      [in] optionally used for:
  *        - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg
  */
 static int ssl_tls12_populate_transform( mbedtls_ssl_transform *transform,
@@ -694,10 +693,13 @@
     const mbedtls_cipher_info_t *cipher_info;
     const mbedtls_md_info_t *md_info;
 
-#if !defined(MBEDTLS_SSL_EXPORT_KEYS) && \
-    !defined(MBEDTLS_DEBUG_C)
-    ssl = NULL; /* make sure we don't use it except for those cases */
-    (void) ssl;
+#if !defined(MBEDTLS_DEBUG_C) && \
+    !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    if( ssl->f_export_keys == NULL )
+    {
+        ssl = NULL; /* make sure we don't use it except for these cases */
+        (void) ssl;
+    }
 #endif
 
     /*
@@ -960,8 +962,7 @@
     ((void) mac_dec);
     ((void) mac_enc);
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
-    if( ssl->f_export_keys != NULL )
+    if( ssl != NULL && ssl->f_export_keys != NULL )
     {
         ssl->f_export_keys( ssl->p_export_keys,
                             MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET,
@@ -970,42 +971,26 @@
                             randbytes,
                             tls_prf_get_type( tls_prf ) );
     }
-#endif
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-
-    /* Only use PSA-based ciphers for TLS-1.2.
-     * That's relevant at least for TLS-1.0, where
-     * we assume that mbedtls_cipher_crypt() updates
-     * the structure field for the IV, which the PSA-based
-     * implementation currently doesn't. */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+    ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc,
+                                    cipher_info, transform->taglen );
+    if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
     {
-        ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc,
-                                        cipher_info, transform->taglen );
-        if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
-            goto end;
-        }
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
+        goto end;
+    }
 
-        if( ret == 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based encryption cipher context" ) );
-            psa_fallthrough = 0;
-        }
-        else
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record encryption - fall through to default setup." ) );
-            psa_fallthrough = 1;
-        }
+    if( ret == 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based encryption cipher context" ) );
+        psa_fallthrough = 0;
     }
     else
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record encryption - fall through to default setup." ) );
         psa_fallthrough = 1;
-#else
-    psa_fallthrough = 1;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    }
 
     if( psa_fallthrough == 1 )
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
@@ -1017,38 +1002,24 @@
     }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    /* Only use PSA-based ciphers for TLS-1.2.
-     * That's relevant at least for TLS-1.0, where
-     * we assume that mbedtls_cipher_crypt() updates
-     * the structure field for the IV, which the PSA-based
-     * implementation currently doesn't. */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+    ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec,
+                                    cipher_info, transform->taglen );
+    if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
     {
-        ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec,
-                                        cipher_info, transform->taglen );
-        if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE )
-        {
-            MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
-            goto end;
-        }
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret );
+        goto end;
+    }
 
-        if( ret == 0 )
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based decryption cipher context" ) );
-            psa_fallthrough = 0;
-        }
-        else
-        {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record decryption - fall through to default setup." ) );
-            psa_fallthrough = 1;
-        }
+    if( ret == 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based decryption cipher context" ) );
+        psa_fallthrough = 0;
     }
     else
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record decryption - fall through to default setup." ) );
         psa_fallthrough = 1;
-#else
-    psa_fallthrough = 1;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    }
 
     if( psa_fallthrough == 1 )
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
@@ -2820,10 +2791,12 @@
 
         /* Remember current epoch settings for resending */
         ssl->handshake->alt_transform_out = ssl->transform_out;
-        memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, 8 );
+        memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr,
+                sizeof( ssl->handshake->alt_out_ctr ) );
 
         /* Set sequence_number to zero */
-        memset( ssl->cur_out_ctr + 2, 0, 6 );
+        memset( &ssl->cur_out_ctr[2], 0, sizeof( ssl->cur_out_ctr ) - 2 );
+
 
         /* Increment epoch */
         for( i = 2; i > 0; i-- )
@@ -2839,7 +2812,7 @@
     }
     else
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
-    memset( ssl->cur_out_ctr, 0, 8 );
+    memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) );
 
     ssl->transform_out = ssl->transform_negotiate;
     ssl->session_out = ssl->session_negotiate;
@@ -4229,7 +4202,6 @@
 #endif
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 void mbedtls_ssl_set_export_keys_cb( mbedtls_ssl_context *ssl,
                                      mbedtls_ssl_export_keys_t *f_export_keys,
                                      void *p_export_keys )
@@ -4237,7 +4209,6 @@
     ssl->f_export_keys = f_export_keys;
     ssl->p_export_keys = p_export_keys;
 }
-#endif
 
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
 void mbedtls_ssl_conf_async_private_cb(
@@ -5792,11 +5763,11 @@
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    used += 8;
+    used += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
     if( used <= buf_len )
     {
-        memcpy( p, ssl->cur_out_ctr, 8 );
-        p += 8;
+        memcpy( p, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN );
+        p += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
     }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -6052,11 +6023,10 @@
     ssl->disable_datagram_packing = *p++;
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    if( (size_t)( end - p ) < 8 )
+    if( (size_t)( end - p ) < sizeof( ssl->cur_out_ctr ) )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
-    memcpy( ssl->cur_out_ctr, p, 8 );
-    p += 8;
+    memcpy( ssl->cur_out_ctr, p, sizeof( ssl->cur_out_ctr ) );
+    p += sizeof( ssl->cur_out_ctr );
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if( (size_t)( end - p ) < 2 )
@@ -6995,4 +6965,106 @@
 
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl,
+                                          const mbedtls_md_type_t md,
+                                          unsigned char *dst,
+                                          size_t dst_len,
+                                          size_t *olen )
+{
+    ((void) ssl);
+    ((void) md);
+    ((void) dst);
+    ((void) dst_len);
+    *olen = 0;
+    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE);
+}
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_SHA384_C)
+static int ssl_get_handshake_transcript_sha384( mbedtls_ssl_context *ssl,
+                                                unsigned char *dst,
+                                                size_t dst_len,
+                                                size_t *olen )
+{
+    int ret;
+    mbedtls_sha512_context sha512;
+
+    if( dst_len < 48 )
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+
+    mbedtls_sha512_init( &sha512 );
+    mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 );
+
+    if( ( ret = mbedtls_sha512_finish( &sha512, dst ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha512_finish", ret );
+        goto exit;
+    }
+
+    *olen = 48;
+
+exit:
+
+    mbedtls_sha512_free( &sha512 );
+    return( ret );
+}
+#endif /* MBEDTLS_SHA384_C */
+
+#if defined(MBEDTLS_SHA256_C)
+static int ssl_get_handshake_transcript_sha256( mbedtls_ssl_context *ssl,
+                                                unsigned char *dst,
+                                                size_t dst_len,
+                                                size_t *olen )
+{
+    int ret;
+    mbedtls_sha256_context sha256;
+
+    if( dst_len < 32 )
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+
+    mbedtls_sha256_init( &sha256 );
+    mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 );
+
+    if( ( ret = mbedtls_sha256_finish( &sha256, dst ) ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha256_finish", ret );
+        goto exit;
+    }
+
+    *olen = 32;
+
+exit:
+
+    mbedtls_sha256_free( &sha256 );
+    return( ret );
+}
+#endif /* MBEDTLS_SHA256_C */
+
+int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl,
+                                          const mbedtls_md_type_t md,
+                                          unsigned char *dst,
+                                          size_t dst_len,
+                                          size_t *olen )
+{
+    switch( md )
+    {
+
+#if defined(MBEDTLS_SHA384_C)
+    case MBEDTLS_MD_SHA384:
+        return( ssl_get_handshake_transcript_sha384( ssl, dst, dst_len, olen ) );
+#endif /* MBEDTLS_SHA384_C */
+
+#if defined(MBEDTLS_SHA256_C)
+    case MBEDTLS_MD_SHA256:
+        return( ssl_get_handshake_transcript_sha256( ssl, dst, dst_len, olen ) );
+#endif /* MBEDTLS_SHA256_C */
+
+    default:
+        break;
+    }
+    return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+}
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+
 #endif /* MBEDTLS_SSL_TLS_C */
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 633bb8d..0fb09c4 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -29,11 +29,11 @@
 
 #include "mbedtls/debug.h"
 #include "mbedtls/error.h"
+#include "mbedtls/platform.h"
 
 #include "ssl_misc.h"
 #include "ecdh_misc.h"
-
-#define CLIENT_HELLO_RANDOM_LEN 32
+#include "ssl_tls13_keys.h"
 
 /* Write extensions */
 
@@ -92,6 +92,26 @@
     return( 0 );
 }
 
+static int ssl_tls13_parse_supported_versions_ext( mbedtls_ssl_context *ssl,
+                                                   const unsigned char *buf,
+                                                   const unsigned char *end )
+{
+    ((void) ssl);
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, 2);
+    if( buf[0] != MBEDTLS_SSL_MAJOR_VERSION_3 ||
+        buf[1] != MBEDTLS_SSL_MINOR_VERSION_4 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "unexpected version" ) );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+
+    return( 0 );
+}
+
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
 
 /*
@@ -452,6 +472,127 @@
     return( ret );
 }
 
+#if defined(MBEDTLS_ECDH_C)
+
+static int ssl_tls13_check_ecdh_params( const mbedtls_ssl_context *ssl )
+{
+    const mbedtls_ecp_curve_info *curve_info;
+    mbedtls_ecp_group_id grp_id;
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+    grp_id = ssl->handshake->ecdh_ctx.grp.id;
+#else
+    grp_id = ssl->handshake->ecdh_ctx.grp_id;
+#endif
+
+    curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id );
+    if( curve_info == NULL )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) );
+
+    if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 )
+        return( -1 );
+
+    MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
+                            MBEDTLS_DEBUG_ECDH_QP );
+
+    return( 0 );
+}
+
+static int ssl_tls13_read_public_ecdhe_share( mbedtls_ssl_context *ssl,
+                                              const unsigned char *buf,
+                                              size_t buf_len )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    ret = mbedtls_ecdh_tls13_read_public( &ssl->handshake->ecdh_ctx,
+                                          buf, buf_len );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_tls13_read_public" ), ret );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+
+    if( ssl_tls13_check_ecdh_params( ssl ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "ssl_tls13_check_ecdh_params() failed!" ) );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_ECDH_C */
+
+/*
+ * ssl_tls13_parse_key_share_ext()
+ *      Parse key_share extension in Server Hello
+ *
+ * struct {
+ *        KeyShareEntry server_share;
+ * } KeyShareServerHello;
+ * struct {
+ *        NamedGroup group;
+ *        opaque key_exchange<1..2^16-1>;
+ * } KeyShareEntry;
+ */
+static int ssl_tls13_parse_key_share_ext( mbedtls_ssl_context *ssl,
+                                          const unsigned char *buf,
+                                          const unsigned char *end )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *p = buf;
+    uint16_t group, offered_group;
+
+    /* ...
+     * NamedGroup group; (2 bytes)
+     * ...
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
+    group = MBEDTLS_GET_UINT16_BE( p, 0 );
+    p += 2;
+
+    /* Check that the chosen group matches the one we offered. */
+    offered_group = ssl->handshake->offered_group_id;
+    if( offered_group != group )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1,
+            ( "Invalid server key share, our group %u, their group %u",
+              (unsigned) offered_group, (unsigned) group ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+                                      MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+        return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+    }
+
+#if defined(MBEDTLS_ECDH_C)
+    if( mbedtls_ssl_tls13_named_group_is_ecdhe( group ) )
+    {
+        /* Complete ECDHE key agreement */
+        ret = ssl_tls13_read_public_ecdhe_share( ssl, p, end - p );
+        if( ret != 0 )
+            return( ret );
+    }
+    else
+#endif /* MBEDTLS_ECDH_C */
+    if( 0 /* other KEMs? */ )
+    {
+        /* Do something */
+    }
+    else
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+
+    ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_KEY_SHARE;
+    return( ret );
+}
+
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
 /* Write cipher_suites
@@ -565,11 +706,11 @@
     p += 2;
 
     /* Write the random bytes ( random ).*/
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, CLIENT_HELLO_RANDOM_LEN );
-    memcpy( p, ssl->handshake->randbytes, CLIENT_HELLO_RANDOM_LEN );
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, MBEDTLS_CLIENT_HELLO_RANDOM_LEN );
+    memcpy( p, ssl->handshake->randbytes, MBEDTLS_CLIENT_HELLO_RANDOM_LEN );
     MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes",
-                           p, CLIENT_HELLO_RANDOM_LEN );
-    p += CLIENT_HELLO_RANDOM_LEN;
+                           p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN );
+    p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN;
 
     /*
      * Write legacy_session_id
@@ -690,7 +831,7 @@
 
     if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng,
                                   ssl->handshake->randbytes,
-                                  CLIENT_HELLO_RANDOM_LEN ) ) != 0 )
+                                  MBEDTLS_CLIENT_HELLO_RANDOM_LEN ) ) != 0 )
     {
         MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret );
         return( ret );
@@ -738,32 +879,688 @@
 }
 
 /*
+ * Functions for parsing and processing Server Hello
+ */
+/* Returns a negative value on failure, and otherwise
+ * - SSL_SERVER_HELLO_COORDINATE_HELLO or
+ * - SSL_SERVER_HELLO_COORDINATE_HRR
+ * to indicate which message is expected and to be parsed next. */
+#define SSL_SERVER_HELLO_COORDINATE_HELLO 0
+#define SSL_SERVER_HELLO_COORDINATE_HRR 1
+static int ssl_server_hello_is_hrr( mbedtls_ssl_context *ssl,
+                                    const unsigned char *buf,
+                                    const unsigned char *end )
+{
+    static const unsigned char magic_hrr_string[MBEDTLS_SERVER_HELLO_RANDOM_LEN] =
+        { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
+          0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
+          0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
+          0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33 ,0x9C };
+
+    /* Check whether this message is a HelloRetryRequest ( HRR ) message.
+     *
+     * Server Hello and HRR are only distinguished by Random set to the
+     * special value of the SHA-256 of "HelloRetryRequest".
+     *
+     * struct {
+     *    ProtocolVersion legacy_version = 0x0303;
+     *    Random random;
+     *    opaque legacy_session_id_echo<0..32>;
+     *    CipherSuite cipher_suite;
+     *    uint8 legacy_compression_method = 0;
+     *    Extension extensions<6..2^16-1>;
+     * } ServerHello;
+     *
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, 2 + sizeof( magic_hrr_string ) );
+
+    if( memcmp( buf + 2, magic_hrr_string, sizeof( magic_hrr_string ) ) == 0 )
+    {
+        return( SSL_SERVER_HELLO_COORDINATE_HRR );
+    }
+
+    return( SSL_SERVER_HELLO_COORDINATE_HELLO );
+}
+
+/* Fetch and preprocess
+ * Returns a negative value on failure, and otherwise
+ * - SSL_SERVER_HELLO_COORDINATE_HELLO or
+ * - SSL_SERVER_HELLO_COORDINATE_HRR
+ */
+static int ssl_tls13_server_hello_coordinate( mbedtls_ssl_context *ssl,
+                                              unsigned char **buf,
+                                              size_t *buf_len )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_read_record( ssl, 0 ) );
+
+    if( ( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) ||
+        ( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "unexpected message" ) );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
+                                      MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+        return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+    }
+
+    *buf = ssl->in_msg + 4;
+    *buf_len = ssl->in_hslen - 4;
+
+    ret = ssl_server_hello_is_hrr( ssl, *buf, *buf + *buf_len );
+    switch( ret )
+    {
+        case SSL_SERVER_HELLO_COORDINATE_HELLO:
+            MBEDTLS_SSL_DEBUG_MSG( 2, ( "received ServerHello message" ) );
+            break;
+        case SSL_SERVER_HELLO_COORDINATE_HRR:
+            MBEDTLS_SSL_DEBUG_MSG( 2, ( "received HelloRetryRequest message" ) );
+            break;
+    }
+
+cleanup:
+
+    return( ret );
+}
+
+static int ssl_tls13_check_server_hello_session_id_echo( mbedtls_ssl_context *ssl,
+                                                         const unsigned char **buf,
+                                                         const unsigned char *end )
+{
+    const unsigned char *p = *buf;
+    size_t legacy_session_id_echo_len;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 1 );
+    legacy_session_id_echo_len = *p++ ;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, legacy_session_id_echo_len );
+
+    /* legacy_session_id_echo */
+    if( ssl->session_negotiate->id_len != legacy_session_id_echo_len ||
+        memcmp( ssl->session_negotiate->id, p , legacy_session_id_echo_len ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_BUF( 3, "Expected Session ID",
+                               ssl->session_negotiate->id,
+                               ssl->session_negotiate->id_len );
+        MBEDTLS_SSL_DEBUG_BUF( 3, "Received Session ID", p,
+                               legacy_session_id_echo_len );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+
+    p += legacy_session_id_echo_len;
+    *buf = p;
+
+    MBEDTLS_SSL_DEBUG_BUF( 3, "Session ID", ssl->session_negotiate->id,
+                            ssl->session_negotiate->id_len );
+    return( 0 );
+}
+
+static int ssl_tls13_cipher_suite_is_offered( mbedtls_ssl_context *ssl,
+                                              int cipher_suite )
+{
+    const int *ciphersuite_list = ssl->conf->ciphersuite_list;
+
+    /* Check whether we have offered this ciphersuite */
+    for ( size_t i = 0; ciphersuite_list[i] != 0; i++ )
+    {
+        if( ciphersuite_list[i] == cipher_suite )
+        {
+            return( 1 );
+        }
+    }
+    return( 0 );
+}
+
+/* Parse ServerHello message and configure context
+ *
+ * struct {
+ *    ProtocolVersion legacy_version = 0x0303; // TLS 1.2
+ *    Random random;
+ *    opaque legacy_session_id_echo<0..32>;
+ *    CipherSuite cipher_suite;
+ *    uint8 legacy_compression_method = 0;
+ *    Extension extensions<6..2^16-1>;
+ * } ServerHello;
+ */
+static int ssl_tls13_parse_server_hello( mbedtls_ssl_context *ssl,
+                                         const unsigned char *buf,
+                                         const unsigned char *end )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const unsigned char *p = buf;
+    size_t extensions_len;
+    const unsigned char *extensions_end;
+    uint16_t cipher_suite;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+
+    /*
+     * Check there is space for minimal fields
+     *
+     * - legacy_version             ( 2 bytes)
+     * - random                     (MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes)
+     * - legacy_session_id_echo     ( 1 byte ), minimum size
+     * - cipher_suite               ( 2 bytes)
+     * - legacy_compression_method  ( 1 byte )
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 6 );
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "server hello", p, end - p );
+    MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", p, 2 );
+
+    /* ...
+     * ProtocolVersion legacy_version = 0x0303; // TLS 1.2
+     * ...
+     * with ProtocolVersion defined as:
+     * uint16 ProtocolVersion;
+     */
+    if( !( p[0] == MBEDTLS_SSL_MAJOR_VERSION_3 &&
+           p[1] == MBEDTLS_SSL_MINOR_VERSION_3 ) )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Unsupported version of TLS." ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION,
+                                      MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION );
+        return( MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION );
+    }
+    p += 2;
+
+    /* ...
+     * Random random;
+     * ...
+     * with Random defined as:
+     * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN];
+     */
+    memcpy( &ssl->handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], p,
+            MBEDTLS_SERVER_HELLO_RANDOM_LEN );
+    MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes",
+                           p, MBEDTLS_SERVER_HELLO_RANDOM_LEN );
+    p += MBEDTLS_SERVER_HELLO_RANDOM_LEN;
+
+    /* ...
+     * opaque legacy_session_id_echo<0..32>;
+     * ...
+     */
+    if( ssl_tls13_check_server_hello_session_id_echo( ssl, &p, end ) != 0 )
+    {
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+
+    /* ...
+     * CipherSuite cipher_suite;
+     * ...
+     * with CipherSuite defined as:
+     * uint8 CipherSuite[2];
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
+    cipher_suite = MBEDTLS_GET_UINT16_BE( p, 0 );
+    p += 2;
+
+
+    /*
+     * Check whether this ciphersuite is supported and offered.
+     * Via the force_ciphersuite version we may have instructed the client
+     * to use a different ciphersuite.
+     */
+    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( cipher_suite );
+    if( ciphersuite_info == NULL ||
+        ssl_tls13_cipher_suite_is_offered( ssl, cipher_suite ) == 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite(%04x) not found or not offered",
+                                    cipher_suite ) );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+
+
+    /* Configure ciphersuites */
+    mbedtls_ssl_optimize_checksum( ssl, ciphersuite_info );
+
+    ssl->handshake->ciphersuite_info = ciphersuite_info;
+    ssl->session_negotiate->ciphersuite = cipher_suite;
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: ( %04x ) - %s",
+                                 cipher_suite, ciphersuite_info->name ) );
+
+#if defined(MBEDTLS_HAVE_TIME)
+    ssl->session_negotiate->start = time( NULL );
+#endif /* MBEDTLS_HAVE_TIME */
+
+    /* ...
+     * uint8 legacy_compression_method = 0;
+     * ...
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 1 );
+    if( p[0] != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad legacy compression method" ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                                      MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+        return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+    }
+    p++;
+
+    /* ...
+     * Extension extensions<6..2^16-1>;
+     * ...
+     * struct {
+     *      ExtensionType extension_type; (2 bytes)
+     *      opaque extension_data<0..2^16-1>;
+     * } Extension;
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
+    extensions_len = MBEDTLS_GET_UINT16_BE( p, 0 );
+    p += 2;
+
+    /* Check extensions do not go beyond the buffer of data. */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, extensions_len );
+    extensions_end = p + extensions_len;
+
+    MBEDTLS_SSL_DEBUG_BUF( 3, "server hello extensions", p, extensions_len );
+
+    while( p < extensions_end )
+    {
+        unsigned int extension_type;
+        size_t extension_data_len;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, 4 );
+        extension_type = MBEDTLS_GET_UINT16_BE( p, 0 );
+        extension_data_len = MBEDTLS_GET_UINT16_BE( p, 2 );
+        p += 4;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, extension_data_len );
+
+        switch( extension_type )
+        {
+            case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS:
+                MBEDTLS_SSL_DEBUG_MSG( 3,
+                            ( "found supported_versions extension" ) );
+
+                ret = ssl_tls13_parse_supported_versions_ext( ssl,
+                                                              p,
+                                                              p + extension_data_len );
+                if( ret != 0 )
+                    return( ret );
+                break;
+
+            case MBEDTLS_TLS_EXT_PRE_SHARED_KEY:
+                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found pre_shared_key extension." ) );
+                MBEDTLS_SSL_DEBUG_MSG( 3, ( "pre_shared_key:Not supported yet" ) );
+
+                MBEDTLS_SSL_PEND_FATAL_ALERT(
+                    MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT,
+                    MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION );
+                return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION );
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+            case MBEDTLS_TLS_EXT_KEY_SHARE:
+                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found key_shares extension" ) );
+                if( ( ret = ssl_tls13_parse_key_share_ext( ssl,
+                                            p, p + extension_data_len ) ) != 0 )
+                {
+                    MBEDTLS_SSL_DEBUG_RET( 1,
+                                           "ssl_tls13_parse_key_share_ext",
+                                           ret );
+                    return( ret );
+                }
+                break;
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
+            default:
+                MBEDTLS_SSL_DEBUG_MSG(
+                    3,
+                    ( "unknown extension found: %u ( ignoring )",
+                      extension_type ) );
+
+                MBEDTLS_SSL_PEND_FATAL_ALERT(
+                    MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT,
+                    MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION );
+                return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION );
+        }
+
+        p += extension_data_len;
+    }
+
+    return( 0 );
+}
+
+static int ssl_tls13_finalize_server_hello( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_key_set traffic_keys;
+    mbedtls_ssl_transform *transform_handshake = NULL;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    /* Determine the key exchange mode:
+     * 1) If both the pre_shared_key and key_share extensions were received
+     *    then the key exchange mode is PSK with EPHEMERAL.
+     * 2) If only the pre_shared_key extension was received then the key
+     *    exchange mode is PSK-only.
+     * 3) If only the key_share extension was received then the key
+     *    exchange mode is EPHEMERAL-only.
+     */
+    switch( handshake->extensions_present &
+            ( MBEDTLS_SSL_EXT_PRE_SHARED_KEY | MBEDTLS_SSL_EXT_KEY_SHARE ) )
+    {
+        /* Only the pre_shared_key extension was received */
+        case MBEDTLS_SSL_EXT_PRE_SHARED_KEY:
+            handshake->tls1_3_kex_modes = MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK;
+            break;
+
+        /* Only the key_share extension was received */
+        case MBEDTLS_SSL_EXT_KEY_SHARE:
+            handshake->tls1_3_kex_modes = MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_EPHEMERAL;
+            break;
+
+        /* Both the pre_shared_key and key_share extensions were received */
+        case ( MBEDTLS_SSL_EXT_PRE_SHARED_KEY | MBEDTLS_SSL_EXT_KEY_SHARE ):
+            handshake->tls1_3_kex_modes = MBEDTLS_SSL_TLS13_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
+            break;
+
+        /* Neither pre_shared_key nor key_share extension was received */
+        default:
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Unknown key exchange." ) );
+            ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+            goto cleanup;
+    }
+
+    /* Start the TLS 1.3 key schedule: Set the PSK and derive early secret.
+     *
+     * TODO: We don't have to do this in case we offered 0-RTT and the
+     *       server accepted it. In this case, we could skip generating
+     *       the early secret. */
+    ret = mbedtls_ssl_tls1_3_key_schedule_stage_early( ssl );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_key_schedule_stage_early_data",
+                               ret );
+        goto cleanup;
+    }
+
+    /* Compute handshake secret */
+    ret = mbedtls_ssl_tls13_key_schedule_stage_handshake( ssl );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_derive_master_secret", ret );
+        goto cleanup;
+    }
+
+    /* Next evolution in key schedule: Establish handshake secret and
+     * key material. */
+    ret = mbedtls_ssl_tls13_generate_handshake_keys( ssl, &traffic_keys );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_generate_handshake_keys",
+                               ret );
+        goto cleanup;
+    }
+
+    transform_handshake = mbedtls_calloc( 1, sizeof( mbedtls_ssl_transform ) );
+    if( transform_handshake == NULL )
+    {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto cleanup;
+    }
+
+    ret = mbedtls_ssl_tls13_populate_transform( transform_handshake,
+                              ssl->conf->endpoint,
+                              ssl->session_negotiate->ciphersuite,
+                              &traffic_keys,
+                              ssl );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_populate_transform", ret );
+        goto cleanup;
+    }
+
+    handshake->transform_handshake = transform_handshake;
+    mbedtls_ssl_set_inbound_transform( ssl, transform_handshake );
+
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to handshake keys for inbound traffic" ) );
+    ssl->session_in = ssl->session_negotiate;
+
+    /*
+     * State machine update
+     */
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS );
+
+cleanup:
+
+    mbedtls_platform_zeroize( &traffic_keys, sizeof( traffic_keys ) );
+    if( ret != 0 )
+    {
+        mbedtls_free( transform_handshake );
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+            MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+    }
+    return( ret );
+}
+
+/*
+ * Wait and parse ServerHello handshake message.
  * Handler for MBEDTLS_SSL_SERVER_HELLO
  */
 static int ssl_tls1_3_process_server_hello( mbedtls_ssl_context *ssl )
 {
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
-    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS );
-    return( 0 );
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *buf;
+    size_t buf_len;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> %s", __func__ ) );
+
+    /* Coordination step
+     * - Fetch record
+     * - Make sure it's either a ServerHello or a HRR.
+     * - Switch processing routine in case of HRR
+     */
+    ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3;
+    ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE;
+
+    ret = ssl_tls13_server_hello_coordinate( ssl, &buf, &buf_len );
+    /* Parsing step
+     * We know what message to expect by now and call
+     * the respective parsing function.
+     */
+    if( ret == SSL_SERVER_HELLO_COORDINATE_HELLO )
+    {
+        MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_server_hello( ssl, buf,
+                                                            buf + buf_len ) );
+
+        mbedtls_ssl_tls1_3_add_hs_msg_to_checksum( ssl,
+                                                   MBEDTLS_SSL_HS_SERVER_HELLO,
+                                                   buf, buf_len );
+
+        MBEDTLS_SSL_PROC_CHK( ssl_tls13_finalize_server_hello( ssl ) );
+    }
+    else if( ret == SSL_SERVER_HELLO_COORDINATE_HRR )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "HRR not supported" ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ,
+                                      MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+        ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+
+cleanup:
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= %s", __func__ ) );
+    return( ret );
 }
 
 /*
- * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS
+ *
+ * EncryptedExtensions message
+ *
+ * The EncryptedExtensions message contains any extensions which
+ * should be protected, i.e., any which are not needed to establish
+ * the cryptographic context.
  */
-static int ssl_tls1_3_process_encrypted_extensions( mbedtls_ssl_context *ssl )
+
+/*
+ * Overview
+ */
+
+/* Main entry point; orchestrates the other functions */
+static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl );
+
+static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl,
+                                                 const unsigned char *buf,
+                                                 const unsigned char *end );
+static int ssl_tls13_postprocess_encrypted_extensions( mbedtls_ssl_context *ssl );
+
+/*
+ * Handler for  MBEDTLS_SSL_ENCRYPTED_EXTENSIONS
+ */
+static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl )
 {
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
-    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST );
+    int ret;
+    unsigned char *buf;
+    size_t buf_len;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse encrypted extensions" ) );
+
+    MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls1_3_fetch_handshake_msg( ssl,
+                                             MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                                             &buf, &buf_len ) );
+
+    /* Process the message contents */
+    MBEDTLS_SSL_PROC_CHK(
+        ssl_tls13_parse_encrypted_extensions( ssl, buf, buf + buf_len ) );
+
+    mbedtls_ssl_tls1_3_add_hs_msg_to_checksum(
+        ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, buf_len );
+
+    MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_encrypted_extensions( ssl ) );
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse encrypted extensions" ) );
+    return( ret );
+
+}
+
+/* Parse EncryptedExtensions message
+ * struct {
+ *     Extension extensions<0..2^16-1>;
+ * } EncryptedExtensions;
+ */
+static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl,
+                                                 const unsigned char *buf,
+                                                 const unsigned char *end )
+{
+    int ret = 0;
+    size_t extensions_len;
+    const unsigned char *p = buf;
+    const unsigned char *extensions_end;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
+    extensions_len = MBEDTLS_GET_UINT16_BE( p, 0 );
+    p += 2;
+
+    MBEDTLS_SSL_DEBUG_BUF( 3, "encrypted extensions", p, extensions_len );
+    extensions_end = p + extensions_len;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, extensions_len );
+
+    while( p < extensions_end )
+    {
+        unsigned int extension_type;
+        size_t extension_data_len;
+
+        /*
+         * struct {
+         *     ExtensionType extension_type; (2 bytes)
+         *     opaque extension_data<0..2^16-1>;
+         * } Extension;
+         */
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, 4 );
+        extension_type = MBEDTLS_GET_UINT16_BE( p, 0 );
+        extension_data_len = MBEDTLS_GET_UINT16_BE( p, 2 );
+        p += 4;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, extension_data_len );
+
+        /* The client MUST check EncryptedExtensions for the
+         * presence of any forbidden extensions and if any are found MUST abort
+         * the handshake with an "unsupported_extension" alert.
+         */
+        switch( extension_type )
+        {
+
+            case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS:
+                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extensions supported groups" ) );
+                break;
+
+            default:
+                MBEDTLS_SSL_DEBUG_MSG(
+                    3, ( "unsupported extension found: %u ", extension_type) );
+                MBEDTLS_SSL_PEND_FATAL_ALERT(
+                    MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT,
+                    MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION );
+                return ( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION );
+        }
+
+        p += extension_data_len;
+    }
+
+    /* Check that we consumed all the message. */
+    if( p != end )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "EncryptedExtension lengths misaligned" ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                      MBEDTLS_ERR_SSL_DECODE_ERROR );
+        return( MBEDTLS_ERR_SSL_DECODE_ERROR );
+    }
+
+    return( ret );
+}
+
+static int ssl_tls13_postprocess_encrypted_extensions( mbedtls_ssl_context *ssl )
+{
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+    if( mbedtls_ssl_tls1_3_some_psk_enabled( ssl ) )
+        mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED );
+    else
+        mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST );
+#else
+    ((void) ssl);
+    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED );
+#endif
     return( 0 );
 }
 
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
 /*
  * Handler for  MBEDTLS_SSL_CERTIFICATE_REQUEST
  */
-static int ssl_tls1_3_process_certificate_request( mbedtls_ssl_context *ssl )
+static int ssl_tls13_process_certificate_request( mbedtls_ssl_context *ssl )
 {
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
+    int ret = mbedtls_ssl_read_record( ssl, 0 );
+
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
+        return( ret );
+    }
+
+    if( ( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) &&
+        ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ) )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "CertificateRequest not supported" ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+                                      MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+        return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE );
+    }
+
+    ssl->keep_current_message = 1;
     mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_CERTIFICATE );
+
     return( 0 );
 }
 
@@ -772,7 +1569,12 @@
  */
 static int ssl_tls1_3_process_server_certificate( mbedtls_ssl_context *ssl )
 {
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "%s hasn't been implemented", __func__ ) );
+    int ret;
+
+    ret = mbedtls_ssl_tls13_process_certificate( ssl );
+    if( ret != 0 )
+        return( ret );
+
     mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY );
     return( 0 );
 }
@@ -786,7 +1588,7 @@
     mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED );
     return( 0 );
 }
-
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 /*
  * Handler for MBEDTLS_SSL_SERVER_FINISHED
  */
@@ -869,11 +1671,12 @@
             break;
 
         case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS:
-            ret = ssl_tls1_3_process_encrypted_extensions( ssl );
+            ret = ssl_tls13_process_encrypted_extensions( ssl );
             break;
 
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
         case MBEDTLS_SSL_CERTIFICATE_REQUEST:
-            ret = ssl_tls1_3_process_certificate_request( ssl );
+            ret = ssl_tls13_process_certificate_request( ssl );
             break;
 
         case MBEDTLS_SSL_SERVER_CERTIFICATE:
@@ -883,6 +1686,7 @@
         case MBEDTLS_SSL_CERTIFICATE_VERIFY:
             ret = ssl_tls1_3_process_certificate_verify( ssl );
             break;
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
         case MBEDTLS_SSL_SERVER_FINISHED:
             ret = ssl_tls1_3_process_server_finished( ssl );
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index 99ab269..c8601ce 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -27,6 +27,10 @@
 #include "mbedtls/debug.h"
 
 #include "ssl_misc.h"
+#include <mbedtls/debug.h>
+#include <mbedtls/oid.h>
+#include <mbedtls/platform.h>
+
 
 int mbedtls_ssl_tls1_3_fetch_handshake_msg( mbedtls_ssl_context *ssl,
                                             unsigned hs_type,
@@ -104,6 +108,15 @@
     return( ret );
 }
 
+void mbedtls_ssl_tls1_3_add_hs_msg_to_checksum( mbedtls_ssl_context *ssl,
+                                                unsigned hs_type,
+                                                unsigned char const *msg,
+                                                size_t msg_len )
+{
+    mbedtls_ssl_tls13_add_hs_hdr_to_checksum( ssl, hs_type, msg_len );
+    ssl->handshake->update_checksum( ssl, msg, msg_len );
+}
+
 void mbedtls_ssl_tls13_add_hs_hdr_to_checksum( mbedtls_ssl_context *ssl,
                                                unsigned hs_type,
                                                size_t total_hs_len )
@@ -206,6 +219,339 @@
 
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
+/*
+ *
+ * STATE HANDLING: Incoming Certificate, client-side only currently.
+ *
+ */
+
+/*
+ * Implementation
+ */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+/*
+ * Structure of Certificate message:
+ *
+ * enum {
+ *     X509(0),
+ *     RawPublicKey(2),
+ *     (255)
+ * } CertificateType;
+ *
+ * struct {
+ *     select (certificate_type) {
+ *         case RawPublicKey:
+ *           * From RFC 7250 ASN.1_subjectPublicKeyInfo *
+ *           opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;
+ *         case X509:
+ *           opaque cert_data<1..2^24-1>;
+ *     };
+ *     Extension extensions<0..2^16-1>;
+ * } CertificateEntry;
+ *
+ * struct {
+ *     opaque certificate_request_context<0..2^8-1>;
+ *     CertificateEntry certificate_list<0..2^24-1>;
+ * } Certificate;
+ *
+ */
+
+/* Parse certificate chain send by the server. */
+static int ssl_tls13_parse_certificate( mbedtls_ssl_context *ssl,
+                                        const unsigned char *buf,
+                                        const unsigned char *end )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t certificate_request_context_len = 0;
+    size_t certificate_list_len = 0;
+    const unsigned char *p = buf;
+    const unsigned char *certificate_list_end;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 4 );
+    certificate_request_context_len = p[0];
+    certificate_list_len = MBEDTLS_GET_UINT24_BE( p, 1 );
+    p += 4;
+
+    /* In theory, the certificate list can be up to 2^24 Bytes, but we don't
+     * support anything beyond 2^16 = 64K.
+     */
+    if( ( certificate_request_context_len != 0 ) ||
+        ( certificate_list_len >= 0x10000 ) )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                      MBEDTLS_ERR_SSL_DECODE_ERROR );
+        return( MBEDTLS_ERR_SSL_DECODE_ERROR );
+    }
+
+    /* In case we tried to reuse a session but it failed */
+    if( ssl->session_negotiate->peer_cert != NULL )
+    {
+        mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert );
+        mbedtls_free( ssl->session_negotiate->peer_cert );
+    }
+
+    if( ( ssl->session_negotiate->peer_cert =
+          mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ) ) == NULL )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc( %" MBEDTLS_PRINTF_SIZET " bytes ) failed",
+                                    sizeof( mbedtls_x509_crt ) ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR,
+                                      MBEDTLS_ERR_SSL_ALLOC_FAILED );
+        return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
+    }
+
+    mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert );
+
+    certificate_list_end = p + certificate_list_len;
+    while( p < certificate_list_end )
+    {
+        size_t cert_data_len, extensions_len;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, certificate_list_end, 3 );
+        cert_data_len = MBEDTLS_GET_UINT24_BE( p, 0 );
+        p += 3;
+
+        /* In theory, the CRT can be up to 2^24 Bytes, but we don't support
+         * anything beyond 2^16 = 64K. Otherwise as in the TLS 1.2 code,
+         * check that we have a minimum of 128 bytes of data, this is not
+         * clear why we need that though.
+         */
+        if( ( cert_data_len < 128 ) || ( cert_data_len >= 0x10000 ) )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad Certificate message" ) );
+            MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                          MBEDTLS_ERR_SSL_DECODE_ERROR );
+            return( MBEDTLS_ERR_SSL_DECODE_ERROR );
+        }
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, certificate_list_end, cert_data_len );
+        ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert,
+                                          p, cert_data_len );
+
+        switch( ret )
+        {
+            case 0: /*ok*/
+                break;
+            case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND:
+                /* Ignore certificate with an unknown algorithm: maybe a
+                   prior certificate was already trusted. */
+                break;
+
+            case MBEDTLS_ERR_X509_ALLOC_FAILED:
+                MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR,
+                                              MBEDTLS_ERR_X509_ALLOC_FAILED );
+                MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret );
+                return( ret );
+
+            case MBEDTLS_ERR_X509_UNKNOWN_VERSION:
+                MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT,
+                                              MBEDTLS_ERR_X509_UNKNOWN_VERSION );
+                MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret );
+                return( ret );
+
+            default:
+                MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_BAD_CERT,
+                                              ret );
+                MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret );
+                return( ret );
+        }
+
+        p += cert_data_len;
+
+        /* Certificate extensions length */
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, certificate_list_end, 2 );
+        extensions_len = MBEDTLS_GET_UINT16_BE( p, 0 );
+        p += 2;
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, certificate_list_end, extensions_len );
+        p += extensions_len;
+    }
+
+    /* Check that all the message is consumed. */
+    if( p != end )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad Certificate message" ) );
+        MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, \
+                                      MBEDTLS_ERR_SSL_DECODE_ERROR );
+        return( MBEDTLS_ERR_SSL_DECODE_ERROR );
+    }
+
+    MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert );
+
+    return( ret );
+}
+#else
+static int ssl_tls13_parse_certificate( mbedtls_ssl_context *ssl,
+                                        const unsigned char *buf,
+                                        const unsigned char *end )
+{
+    ((void) ssl);
+    ((void) buf);
+    ((void) end);
+    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+}
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+/* Validate certificate chain sent by the server. */
+static int ssl_tls13_validate_certificate( mbedtls_ssl_context *ssl )
+{
+    int ret = 0;
+    mbedtls_x509_crt *ca_chain;
+    mbedtls_x509_crl *ca_crl;
+    uint32_t verify_result = 0;
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    if( ssl->handshake->sni_ca_chain != NULL )
+    {
+        ca_chain = ssl->handshake->sni_ca_chain;
+        ca_crl = ssl->handshake->sni_ca_crl;
+    }
+    else
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+    {
+        ca_chain = ssl->conf->ca_chain;
+        ca_crl = ssl->conf->ca_crl;
+    }
+
+    /*
+     * Main check: verify certificate
+     */
+    ret = mbedtls_x509_crt_verify_with_profile(
+        ssl->session_negotiate->peer_cert,
+        ca_chain, ca_crl,
+        ssl->conf->cert_profile,
+        ssl->hostname,
+        &verify_result,
+        ssl->conf->f_vrfy, ssl->conf->p_vrfy );
+
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret );
+    }
+
+    /*
+     * Secondary checks: always done, but change 'ret' only if it was 0
+     */
+
+#if defined(MBEDTLS_ECP_C)
+    {
+        const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk;
+
+        /* If certificate uses an EC key, make sure the curve is OK */
+        if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
+            mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 )
+        {
+            verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY;
+
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate ( EC key curve )" ) );
+            if( ret == 0 )
+                ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+        }
+    }
+#endif /* MBEDTLS_ECP_C */
+
+    if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert,
+                                      ssl->handshake->ciphersuite_info,
+                                      !ssl->conf->endpoint,
+                                      &verify_result ) != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate ( usage extensions )" ) );
+        if( ret == 0 )
+            ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+    }
+
+
+    if( ca_chain == NULL )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
+        ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
+    }
+
+    if( ret != 0 )
+    {
+        /* The certificate may have been rejected for several reasons.
+           Pick one and send the corresponding alert. Which alert to send
+           may be a subject of debate in some cases. */
+        if( verify_result & MBEDTLS_X509_BADCERT_OTHER )
+            MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED, ret );
+        else if( verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH )
+            MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_BAD_CERT, ret );
+        else if( verify_result & ( MBEDTLS_X509_BADCERT_KEY_USAGE |
+                                   MBEDTLS_X509_BADCERT_EXT_KEY_USAGE |
+                                   MBEDTLS_X509_BADCERT_NS_CERT_TYPE |
+                                   MBEDTLS_X509_BADCERT_BAD_PK |
+                                   MBEDTLS_X509_BADCERT_BAD_KEY ) )
+            MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, ret );
+        else if( verify_result & MBEDTLS_X509_BADCERT_EXPIRED )
+            MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED, ret );
+        else if( verify_result & MBEDTLS_X509_BADCERT_REVOKED )
+            MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED, ret );
+        else if( verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED )
+            MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA, ret );
+        else
+            MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN, ret );
+    }
+
+#if defined(MBEDTLS_DEBUG_C)
+    if( verify_result != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %08x",
+                                    (unsigned int) verify_result ) );
+    }
+    else
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) );
+    }
+#endif /* MBEDTLS_DEBUG_C */
+
+    ssl->session_negotiate->verify_result = verify_result;
+    return( ret );
+}
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+static int ssl_tls13_validate_certificate( mbedtls_ssl_context *ssl )
+{
+    ((void) ssl);
+    return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+}
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+
+int mbedtls_ssl_tls13_process_certificate( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
+
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    unsigned char *buf;
+    size_t buf_len;
+
+    MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls1_3_fetch_handshake_msg(
+                          ssl, MBEDTLS_SSL_HS_CERTIFICATE,
+                          &buf, &buf_len ) );
+
+    /* Parse the certificate chain sent by the peer. */
+    MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_certificate( ssl, buf, buf + buf_len ) );
+    /* Validate the certificate chain and set the verification results. */
+    MBEDTLS_SSL_PROC_CHK( ssl_tls13_validate_certificate( ssl ) );
+
+    mbedtls_ssl_tls1_3_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE,
+                                               buf, buf_len );
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
+#else
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+    ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+    return( ret );
+}
+
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
 
 #endif /* MBEDTLS_SSL_TLS_C */
diff --git a/library/ssl_tls13_keys.c b/library/ssl_tls13_keys.c
index 7aec21d..96f5310 100644
--- a/library/ssl_tls13_keys.c
+++ b/library/ssl_tls13_keys.c
@@ -21,14 +21,16 @@
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
 
-#include "mbedtls/hkdf.h"
-#include "ssl_misc.h"
-#include "ssl_tls13_keys.h"
-#include "mbedtls/debug.h"
-
 #include <stdint.h>
 #include <string.h>
 
+#include "mbedtls/hkdf.h"
+#include "mbedtls/debug.h"
+#include "mbedtls/error.h"
+
+#include "ssl_misc.h"
+#include "ssl_tls13_keys.h"
+
 #define MBEDTLS_SSL_TLS1_3_LABEL( name, string )       \
     .name = string,
 
@@ -820,4 +822,210 @@
     return( 0 );
 }
 
+int mbedtls_ssl_tls1_3_key_schedule_stage_early( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_type_t md_type;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+
+    if( handshake->ciphersuite_info == NULL )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher suite info not found" ) );
+        return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+    }
+
+    md_type = handshake->ciphersuite_info->mac;
+
+    ret = mbedtls_ssl_tls1_3_evolve_secret( md_type, NULL, NULL, 0,
+                                            handshake->tls1_3_master_secrets.early );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_evolve_secret", ret );
+        return( ret );
+    }
+
+    return( 0 );
+}
+
+/* mbedtls_ssl_tls13_generate_handshake_keys() generates keys necessary for
+ * protecting the handshake messages, as described in Section 7 of TLS 1.3. */
+int mbedtls_ssl_tls13_generate_handshake_keys( mbedtls_ssl_context *ssl,
+                                               mbedtls_ssl_key_set *traffic_keys )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    mbedtls_md_type_t md_type;
+    mbedtls_md_info_t const *md_info;
+    size_t md_size;
+
+    unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
+    size_t transcript_len;
+
+    mbedtls_cipher_info_t const *cipher_info;
+    size_t keylen, ivlen;
+
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info;
+    mbedtls_ssl_tls1_3_handshake_secrets *tls13_hs_secrets = &handshake->tls13_hs_secrets;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_tls13_generate_handshake_keys" ) );
+
+    cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher );
+    keylen = cipher_info->key_bitlen >> 3;
+    ivlen = cipher_info->iv_size;
+
+    md_type = ciphersuite_info->mac;
+    md_info = mbedtls_md_info_from_type( md_type );
+    md_size = mbedtls_md_get_size( md_info );
+
+    ret = mbedtls_ssl_get_handshake_transcript( ssl, md_type,
+                                                transcript,
+                                                sizeof( transcript ),
+                                                &transcript_len );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1,
+                               "mbedtls_ssl_get_handshake_transcript",
+                               ret );
+        return( ret );
+    }
+
+    ret = mbedtls_ssl_tls1_3_derive_handshake_secrets( md_type,
+                                    handshake->tls1_3_master_secrets.handshake,
+                                    transcript, transcript_len, tls13_hs_secrets );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_derive_handshake_secrets",
+                               ret );
+        return( ret );
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "Client handshake traffic secret",
+                    tls13_hs_secrets->client_handshake_traffic_secret,
+                    md_size );
+    MBEDTLS_SSL_DEBUG_BUF( 4, "Server handshake traffic secret",
+                    tls13_hs_secrets->server_handshake_traffic_secret,
+                    md_size );
+
+    /*
+     * Export client handshake traffic secret
+     */
+    if( ssl->f_export_keys != NULL )
+    {
+        ssl->f_export_keys( ssl->p_export_keys,
+                MBEDTLS_SSL_KEY_EXPORT_TLS13_CLIENT_HANDSHAKE_TRAFFIC_SECRET,
+                tls13_hs_secrets->client_handshake_traffic_secret,
+                md_size,
+                handshake->randbytes + 32,
+                handshake->randbytes,
+                MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */ );
+
+        ssl->f_export_keys( ssl->p_export_keys,
+                MBEDTLS_SSL_KEY_EXPORT_TLS13_SERVER_HANDSHAKE_TRAFFIC_SECRET,
+                tls13_hs_secrets->server_handshake_traffic_secret,
+                md_size,
+                handshake->randbytes + 32,
+                handshake->randbytes,
+                MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */ );
+    }
+
+    ret = mbedtls_ssl_tls1_3_make_traffic_keys( md_type,
+                            tls13_hs_secrets->client_handshake_traffic_secret,
+                            tls13_hs_secrets->server_handshake_traffic_secret,
+                            md_size, keylen, ivlen, traffic_keys );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_make_traffic_keys", ret );
+        goto exit;
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "client_handshake write_key",
+                           traffic_keys->client_write_key,
+                           traffic_keys->key_len);
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "server_handshake write_key",
+                           traffic_keys->server_write_key,
+                           traffic_keys->key_len);
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "client_handshake write_iv",
+                           traffic_keys->client_write_iv,
+                           traffic_keys->iv_len);
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "server_handshake write_iv",
+                           traffic_keys->server_write_iv,
+                           traffic_keys->iv_len);
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_tls13_generate_handshake_keys" ) );
+
+exit:
+
+    return( ret );
+}
+
+int mbedtls_ssl_tls13_key_schedule_stage_handshake( mbedtls_ssl_context *ssl )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    mbedtls_md_type_t const md_type = handshake->ciphersuite_info->mac;
+    size_t ephemeral_len = 0;
+    unsigned char ecdhe[MBEDTLS_ECP_MAX_BYTES];
+#if defined(MBEDTLS_DEBUG_C)
+    mbedtls_md_info_t const * const md_info = mbedtls_md_info_from_type( md_type );
+    size_t const md_size = mbedtls_md_get_size( md_info );
+#endif /* MBEDTLS_DEBUG_C */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
+    /*
+     * Compute ECDHE secret used to compute the handshake secret from which
+     * client_handshake_traffic_secret and server_handshake_traffic_secret
+     * are derived in the handshake secret derivation stage.
+     */
+    if( mbedtls_ssl_tls1_3_ephemeral_enabled( ssl ) )
+    {
+        if( mbedtls_ssl_tls13_named_group_is_ecdhe( handshake->offered_group_id ) )
+        {
+#if defined(MBEDTLS_ECDH_C)
+            ret = mbedtls_ecdh_calc_secret( &handshake->ecdh_ctx,
+                                            &ephemeral_len, ecdhe, sizeof( ecdhe ),
+                                            ssl->conf->f_rng,
+                                            ssl->conf->p_rng );
+            if( ret != 0 )
+            {
+                MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret );
+                return( ret );
+            }
+#endif /* MBEDTLS_ECDH_C */
+        }
+        else if( mbedtls_ssl_tls13_named_group_is_dhe( handshake->offered_group_id ) )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHE not supported." ) );
+            return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+        }
+    }
+#else
+    return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */
+
+    /*
+     * Compute the Handshake Secret
+     */
+    ret = mbedtls_ssl_tls1_3_evolve_secret( md_type,
+                                            handshake->tls1_3_master_secrets.early,
+                                            ecdhe, ephemeral_len,
+                                            handshake->tls1_3_master_secrets.handshake );
+    if( ret != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_evolve_secret", ret );
+        return( ret );
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "Handshake secret",
+                           handshake->tls1_3_master_secrets.handshake, md_size );
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
+    mbedtls_platform_zeroize( ecdhe, sizeof( ecdhe ) );
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */
+    return( 0 );
+}
+
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
diff --git a/library/ssl_tls13_keys.h b/library/ssl_tls13_keys.h
index ca892b1..384f433 100644
--- a/library/ssl_tls13_keys.h
+++ b/library/ssl_tls13_keys.h
@@ -70,27 +70,6 @@
 #define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN  \
     MBEDTLS_MD_MAX_SIZE
 
-typedef struct
-{
-    unsigned char binder_key                  [ MBEDTLS_MD_MAX_SIZE ];
-    unsigned char client_early_traffic_secret [ MBEDTLS_MD_MAX_SIZE ];
-    unsigned char early_exporter_master_secret[ MBEDTLS_MD_MAX_SIZE ];
-} mbedtls_ssl_tls1_3_early_secrets;
-
-typedef struct
-{
-    unsigned char client_handshake_traffic_secret[ MBEDTLS_MD_MAX_SIZE ];
-    unsigned char server_handshake_traffic_secret[ MBEDTLS_MD_MAX_SIZE ];
-} mbedtls_ssl_tls1_3_handshake_secrets;
-
-typedef struct
-{
-    unsigned char client_application_traffic_secret_N[ MBEDTLS_MD_MAX_SIZE ];
-    unsigned char server_application_traffic_secret_N[ MBEDTLS_MD_MAX_SIZE ];
-    unsigned char exporter_master_secret             [ MBEDTLS_MD_MAX_SIZE ];
-    unsigned char resumption_master_secret           [ MBEDTLS_MD_MAX_SIZE ];
-} mbedtls_ssl_tls1_3_application_secrets;
-
 /* Maximum desired length for expanded key material generated
  * by HKDF-Expand-Label.
  *
@@ -531,4 +510,59 @@
                                           mbedtls_ssl_key_set const *traffic_keys,
                                           mbedtls_ssl_context *ssl );
 
+/*
+ * TLS 1.3 key schedule evolutions
+ *
+ *   Early -> Handshake -> Application
+ *
+ * Small wrappers around mbedtls_ssl_tls1_3_evolve_secret().
+ */
+
+/**
+ * \brief Begin TLS 1.3 key schedule by calculating early secret.
+ *
+ *        The TLS 1.3 key schedule can be viewed as a simple state machine
+ *        with states Initial -> Early -> Handshake -> Application, and
+ *        this function represents the Initial -> Early transition.
+ *
+ * \param ssl  The SSL context to operate on.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+int mbedtls_ssl_tls1_3_key_schedule_stage_early( mbedtls_ssl_context *ssl );
+
+/**
+ * \brief Transition into handshake stage of TLS 1.3 key schedule.
+ *
+ *        The TLS 1.3 key schedule can be viewed as a simple state machine
+ *        with states Initial -> Early -> Handshake -> Application, and
+ *        this function represents the Early -> Handshake transition.
+ *
+ *        In the handshake stage, mbedtls_ssl_tls13_generate_handshake_keys()
+ *        can be used to derive the handshake traffic keys.
+ *
+ * \param ssl  The SSL context to operate on. This must be in key schedule
+ *             stage \c Early.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+int mbedtls_ssl_tls13_key_schedule_stage_handshake( mbedtls_ssl_context *ssl );
+
+/**
+ * \brief Compute TLS 1.3 handshake traffic keys.
+ *
+ * \param ssl  The SSL context to operate on. This must be in
+ *             key schedule stage \c Handshake, see
+ *             mbedtls_ssl_tls13_key_schedule_stage_handshake().
+ * \param traffic_keys The address at which to store the handshake traffic key
+ *                     keys. This must be writable but may be uninitialized.
+ *
+ * \returns    \c 0 on success.
+ * \returns    A negative error code on failure.
+ */
+int mbedtls_ssl_tls13_generate_handshake_keys( mbedtls_ssl_context *ssl,
+                                               mbedtls_ssl_key_set *traffic_keys );
+
 #endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */
diff --git a/programs/.gitignore b/programs/.gitignore
index d8eb6ba..deb104a 100644
--- a/programs/.gitignore
+++ b/programs/.gitignore
@@ -69,6 +69,7 @@
 x509/cert_req
 x509/cert_write
 x509/crl_app
+x509/load_roots
 x509/req_app
 
 # Generated data files
diff --git a/programs/Makefile b/programs/Makefile
index 02eb5a1..7f9d11e 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -110,6 +110,7 @@
 	x509/cert_req \
 	x509/cert_write \
 	x509/crl_app \
+	x509/load_roots \
 	x509/req_app \
 # End of APPS
 
@@ -387,6 +388,10 @@
 	echo "  CC    x509/cert_req.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/cert_req.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
+x509/load_roots$(EXEXT): x509/load_roots.c $(DEP)
+	echo "  CC    x509/load_roots.c"
+	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/load_roots.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
+
 x509/req_app$(EXEXT): x509/req_app.c $(DEP)
 	echo "  CC    x509/req_app.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/req_app.c    $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c
index eccb42a..d633e4d 100644
--- a/programs/pkey/dh_client.c
+++ b/programs/pkey/dh_client.c
@@ -270,7 +270,9 @@
     mbedtls_printf( "...\n  . Receiving and decrypting the ciphertext" );
     fflush( stdout );
 
-    mbedtls_aes_setkey_dec( &aes, buf, 256 );
+    ret = mbedtls_aes_setkey_dec( &aes, buf, 256 );
+    if( ret != 0 )
+        goto exit;
 
     memset( buf, 0, sizeof( buf ) );
 
@@ -280,7 +282,9 @@
         goto exit;
     }
 
-    mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, buf, buf );
+    ret = mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, buf, buf );
+    if( ret != 0 )
+        goto exit;
     buf[16] = '\0';
     mbedtls_printf( "\n  . Plaintext is \"%s\"\n\n", (char *) buf );
 
diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c
index 0ddb85c..75713ff 100644
--- a/programs/pkey/dh_server.c
+++ b/programs/pkey/dh_server.c
@@ -290,9 +290,13 @@
     mbedtls_printf( "...\n  . Encrypting and sending the ciphertext" );
     fflush( stdout );
 
-    mbedtls_aes_setkey_enc( &aes, buf, 256 );
+    ret = mbedtls_aes_setkey_enc( &aes, buf, 256 );
+    if( ret != 0 )
+        goto exit;
     memcpy( buf, PLAINTEXT, 16 );
-    mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_ENCRYPT, buf, buf );
+    ret = mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_ENCRYPT, buf, buf );
+    if( ret != 0 )
+        goto exit;
 
     if( ( ret = mbedtls_net_send( &client_fd, buf, 16 ) ) != 16 )
     {
diff --git a/programs/pkey/key_app_writer.c b/programs/pkey/key_app_writer.c
index 8a09af5..ed6addf 100644
--- a/programs/pkey/key_app_writer.c
+++ b/programs/pkey/key_app_writer.c
@@ -202,7 +202,9 @@
 {
     int ret = 1;
     int exit_code = MBEDTLS_EXIT_FAILURE;
-    char buf[1024];
+#if defined(MBEDTLS_ERROR_C)
+    char buf[200];
+#endif
     int i;
     char *p, *q;
 
@@ -220,7 +222,9 @@
     mbedtls_ctr_drbg_init( &ctr_drbg );
 
     mbedtls_pk_init( &key );
+#if defined(MBEDTLS_ERROR_C)
     memset( buf, 0, sizeof( buf ) );
+#endif
 
     mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q );
     mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &DP );
@@ -316,8 +320,7 @@
                                         mbedtls_ctr_drbg_random, &ctr_drbg );
         if( ret != 0 )
         {
-            mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
-            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
+            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned -0x%04x", (unsigned int) -ret );
             goto exit;
         }
 
@@ -377,8 +380,7 @@
 
         if( ret != 0 )
         {
-            mbedtls_strerror( ret, (char *) buf, sizeof(buf) );
-            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_public_key returned -0x%04x - %s\n\n", (unsigned int) -ret, buf );
+            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_public_key returned -0x%04x", (unsigned int) -ret );
             goto exit;
         }
 
diff --git a/programs/psa/CMakeLists.txt b/programs/psa/CMakeLists.txt
index 23e85fe..26ca73c 100644
--- a/programs/psa/CMakeLists.txt
+++ b/programs/psa/CMakeLists.txt
@@ -4,6 +4,25 @@
     psa_constant_names
 )
 
+if(GEN_FILES)
+    add_custom_command(
+        OUTPUT
+            ${CMAKE_CURRENT_BINARY_DIR}/psa_constant_names_generated.c
+        COMMAND
+            ${MBEDTLS_PYTHON_EXECUTABLE}
+                ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/generate_psa_constants.py
+                ${CMAKE_CURRENT_BINARY_DIR}
+        WORKING_DIRECTORY
+            ${CMAKE_CURRENT_SOURCE_DIR}/../..
+        DEPENDS
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/generate_psa_constants.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../include/psa/crypto_values.h
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../include/psa/crypto_extra.h
+    )
+else()
+    link_to_source(psa_constant_names_generated.c)
+endif()
+
 foreach(exe IN LISTS executables)
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>)
     target_link_libraries(${exe} ${mbedcrypto_target})
@@ -11,6 +30,11 @@
 endforeach()
 
 target_include_directories(psa_constant_names PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
+if(GEN_FILES)
+    add_custom_target(generate_psa_constant_names_generated_c
+        DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/psa_constant_names_generated.c)
+    add_dependencies(psa_constant_names generate_psa_constant_names_generated_c)
+endif()
 
 install(TARGETS ${executables}
         DESTINATION "bin"
diff --git a/programs/ssl/CMakeLists.txt b/programs/ssl/CMakeLists.txt
index def9c7c..280bbcf 100644
--- a/programs/ssl/CMakeLists.txt
+++ b/programs/ssl/CMakeLists.txt
@@ -18,23 +18,38 @@
     ssl_server2
 )
 
+if(GEN_FILES)
+    # Inform CMake that the following file will be generated as part of the build
+    # process, so it doesn't complain that it doesn't exist yet. Starting from
+    # CMake 3.20, this will no longer be necessary as CMake will automatically
+    # propagate this information across the tree, for now it's only visible
+    # inside the same directory, so we need to propagate manually.
+    set_source_files_properties(
+        ${CMAKE_CURRENT_BINARY_DIR}/../test/query_config.c
+        PROPERTIES GENERATED TRUE)
+endif()
+
 foreach(exe IN LISTS executables)
     set(extra_sources "")
     if(exe STREQUAL "ssl_client2" OR exe STREQUAL "ssl_server2")
         list(APPEND extra_sources
-            ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
+            ssl_test_lib.c
+            ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.h
+            ${CMAKE_CURRENT_BINARY_DIR}/../test/query_config.c)
     endif()
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>
         ${extra_sources})
     target_link_libraries(${exe} ${libs})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
+    if(exe STREQUAL "ssl_client2" OR exe STREQUAL "ssl_server2")
+        if(GEN_FILES)
+            add_dependencies(${exe} generate_query_config_c)
+        endif()
+        target_include_directories(${exe}
+            PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../test)
+    endif()
 endforeach()
 
-set_property(TARGET ssl_client2 APPEND PROPERTY SOURCES
-    ssl_test_lib.c ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
-set_property(TARGET ssl_server2 APPEND PROPERTY SOURCES
-    ssl_test_lib.c ${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.c)
-
 if(THREADS_FOUND)
     add_executable(ssl_pthread_server ssl_pthread_server.c $<TARGET_OBJECTS:mbedtls_test>)
     target_include_directories(ssl_pthread_server PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index a970503..f872e60 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -207,7 +207,6 @@
 #define USAGE_TICKETS ""
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 #define USAGE_EAP_TLS                                       \
     "    eap_tls=%%d          default: 0 (disabled)\n"
 #define USAGE_NSS_KEYLOG                                    \
@@ -230,12 +229,6 @@
 #else /* MBEDTLS_SSL_DTLS_SRTP */
 #define USAGE_SRTP ""
 #endif
-#else /* MBEDTLS_SSL_EXPORT_KEYS */
-#define USAGE_EAP_TLS ""
-#define USAGE_NSS_KEYLOG ""
-#define USAGE_NSS_KEYLOG_FILE ""
-#define USAGE_SRTP ""
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
 #define USAGE_MAX_FRAG_LEN                                      \
@@ -729,7 +722,6 @@
     unsigned char *context_buf = NULL;
     size_t context_buf_len;
 #endif
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     unsigned char eap_tls_keymaterial[16];
     unsigned char eap_tls_iv[8];
     const char* eap_tls_label = "client EAP encryption";
@@ -747,7 +739,6 @@
         MBEDTLS_TLS_SRTP_UNSET
     };
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
@@ -1692,7 +1683,7 @@
     if( opt.key_opaque != 0 )
     {
         if( ( ret = mbedtls_pk_wrap_as_opaque( &pkey, &key_slot,
-                                               PSA_ALG_SHA_256 ) ) != 0 )
+                                               PSA_ALG_ANY_HASH ) ) != 0 )
         {
             mbedtls_printf( " failed\n  !  "
                             "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", (unsigned int)  -ret );
@@ -1962,7 +1953,6 @@
         goto exit;
     }
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     if( opt.eap_tls != 0 )
     {
         mbedtls_ssl_set_export_keys_cb( &ssl, eap_tls_key_derivation,
@@ -1981,7 +1971,6 @@
                                         &dtls_srtp_keying );
     }
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
     if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 )
@@ -2169,7 +2158,6 @@
     }
 #endif
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     if( opt.eap_tls != 0  )
     {
         size_t j = 0;
@@ -2286,7 +2274,6 @@
         }
     }
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
     if( opt.reconnect != 0 )
     {
         mbedtls_printf("  . Saving session for reuse..." );
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index e8e4ed8..c0f3196 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -80,6 +80,7 @@
 #define DFL_CA_PATH             ""
 #define DFL_CRT_FILE            ""
 #define DFL_KEY_FILE            ""
+#define DFL_KEY_OPAQUE          0
 #define DFL_KEY_PWD             ""
 #define DFL_CRT_FILE2           ""
 #define DFL_KEY_FILE2           ""
@@ -200,6 +201,13 @@
 #else
 #define USAGE_IO ""
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_X509_CRT_PARSE_C)
+#define USAGE_KEY_OPAQUE \
+    "    key_opaque=%%d       Handle your private keys as if they were opaque\n" \
+    "                        default: 0 (disabled)\n"
+#else
+#define USAGE_KEY_OPAQUE ""
+#endif
 
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
 #define USAGE_SSL_ASYNC \
@@ -278,7 +286,6 @@
 #define USAGE_TICKETS ""
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 #define USAGE_EAP_TLS                                       \
     "    eap_tls=%%d          default: 0 (disabled)\n"
 #define USAGE_NSS_KEYLOG                                    \
@@ -299,12 +306,6 @@
 #else /* MBEDTLS_SSL_DTLS_SRTP */
 #define USAGE_SRTP ""
 #endif
-#else /* MBEDTLS_SSL_EXPORT_KEYS */
-#define USAGE_EAP_TLS ""
-#define USAGE_NSS_KEYLOG ""
-#define USAGE_NSS_KEYLOG_FILE ""
-#define USAGE_SRTP ""
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_CACHE_C)
 #define USAGE_CACHE                                             \
@@ -483,6 +484,7 @@
     "    cert_req_ca_list=%%d default: 1 (send ca list)\n"  \
     "                        options: 1 (send ca list), 0 (don't send)\n" \
     USAGE_IO                                                \
+    USAGE_KEY_OPAQUE                                        \
     "\n"                                                    \
     USAGE_PSK                                               \
     USAGE_CA_CALLBACK                                       \
@@ -567,6 +569,7 @@
     const char *ca_path;        /* the path with the CA certificate(s) reside */
     const char *crt_file;       /* the file with the server certificate     */
     const char *key_file;       /* the file with the server key             */
+    int key_opaque;             /* handle private key as if it were opaque  */
     const char *key_pwd;        /* the password for the server key          */
     const char *crt_file2;      /* the file with the 2nd server certificate */
     const char *key_file2;      /* the file with the 2nd server key         */
@@ -1315,6 +1318,10 @@
     mbedtls_pk_context pkey;
     mbedtls_x509_crt srvcert2;
     mbedtls_pk_context pkey2;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_key_id_t key_slot = 0; /* invalid key slot */
+    psa_key_id_t key_slot2 = 0; /* invalid key slot */
+#endif
     int key_cert_init = 0, key_cert_init2 = 0;
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
     ssl_async_key_context_t ssl_async_keys;
@@ -1365,7 +1372,6 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_status_t status;
 #endif
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     unsigned char eap_tls_keymaterial[16];
     unsigned char eap_tls_iv[8];
     const char* eap_tls_label = "client EAP encryption";
@@ -1383,7 +1389,6 @@
          MBEDTLS_TLS_SRTP_UNSET
      };
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
@@ -1491,6 +1496,7 @@
     opt.ca_path             = DFL_CA_PATH;
     opt.crt_file            = DFL_CRT_FILE;
     opt.key_file            = DFL_KEY_FILE;
+    opt.key_opaque          = DFL_KEY_OPAQUE;
     opt.key_pwd             = DFL_KEY_PWD;
     opt.crt_file2           = DFL_CRT_FILE2;
     opt.key_file2           = DFL_KEY_FILE2;
@@ -1622,6 +1628,10 @@
             opt.key_file = q;
         else if( strcmp( p, "key_pwd" ) == 0 )
             opt.key_pwd = q;
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_X509_CRT_PARSE_C)
+        else if( strcmp( p, "key_opaque" ) == 0 )
+            opt.key_opaque = atoi( q );
+#endif
         else if( strcmp( p, "crt_file2" ) == 0 )
             opt.crt_file2 = q;
         else if( strcmp( p, "key_file2" ) == 0 )
@@ -2477,7 +2487,34 @@
 #endif /* MBEDTLS_ECDSA_C */
     }
 
-    mbedtls_printf( " ok\n" );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if( opt.key_opaque != 0 )
+    {
+        if ( mbedtls_pk_get_type( &pkey ) == MBEDTLS_PK_ECKEY )
+        {
+            if( ( ret = mbedtls_pk_wrap_as_opaque( &pkey, &key_slot,
+                                                PSA_ALG_ANY_HASH ) ) != 0 )
+            {
+                mbedtls_printf( " failed\n  !  "
+                                "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", (unsigned int)  -ret );
+                goto exit;
+            }
+        }
+
+        if ( mbedtls_pk_get_type( &pkey2 ) == MBEDTLS_PK_ECKEY )
+        {
+            if( ( ret = mbedtls_pk_wrap_as_opaque( &pkey2, &key_slot2,
+                                                PSA_ALG_ANY_HASH ) ) != 0 )
+            {
+                mbedtls_printf( " failed\n  !  "
+                                "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", (unsigned int)  -ret );
+                goto exit;
+            }
+        }
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+    mbedtls_printf( " ok (key types: %s - %s)\n", mbedtls_pk_get_name( &pkey ), mbedtls_pk_get_name( &pkey2 ) );
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
 #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO)
@@ -2966,7 +3003,6 @@
         goto exit;
     }
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     if( opt.eap_tls != 0 )
     {
         mbedtls_ssl_set_export_keys_cb( &ssl, eap_tls_key_derivation,
@@ -2985,7 +3021,6 @@
                                         &dtls_srtp_keying );
     }
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
     io_ctx.ssl = &ssl;
     io_ctx.net = &client_fd;
@@ -3251,7 +3286,6 @@
 #endif /* MBEDTLS_X509_REMOVE_INFO */
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
     if( opt.eap_tls != 0 )
     {
         size_t j = 0;
@@ -3369,7 +3403,6 @@
         }
     }
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
     ret = report_cid_usage( &ssl, "initial handshake" );
@@ -3923,6 +3956,10 @@
     mbedtls_pk_free( &pkey );
     mbedtls_x509_crt_free( &srvcert2 );
     mbedtls_pk_free( &pkey2 );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_destroy_key( key_slot );
+    psa_destroy_key( key_slot2 );
+#endif
 #endif
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
     for( i = 0; (size_t) i < ssl_async_keys.slots_used; i++ )
diff --git a/programs/ssl/ssl_test_common_source.c b/programs/ssl/ssl_test_common_source.c
index 6ec4171..62cd35d 100644
--- a/programs/ssl/ssl_test_common_source.c
+++ b/programs/ssl/ssl_test_common_source.c
@@ -24,7 +24,6 @@
  *  limitations under the License.
  */
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
 void eap_tls_key_derivation( void *p_expkey,
                              mbedtls_ssl_key_export_type secret_type,
                              const unsigned char *secret,
@@ -140,8 +139,6 @@
 }
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
 
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
-
 int ssl_check_record( mbedtls_ssl_context const *ssl,
                       unsigned char const *buf, size_t len )
 {
diff --git a/programs/ssl/ssl_test_lib.h b/programs/ssl/ssl_test_lib.h
index f9e031b..6b9e7b8 100644
--- a/programs/ssl/ssl_test_lib.h
+++ b/programs/ssl/ssl_test_lib.h
@@ -95,8 +95,6 @@
 
 #include "../test/query_config.h"
 
-#if defined(MBEDTLS_SSL_EXPORT_KEYS)
-
 typedef struct eap_tls_keys
 {
     unsigned char master_secret[48];
@@ -122,8 +120,6 @@
 
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
 
-#endif /* MBEDTLS_SSL_EXPORT_KEYS */
-
 typedef struct
 {
     mbedtls_ssl_context *ssl;
diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt
index a0a1b76..142a831 100644
--- a/programs/test/CMakeLists.txt
+++ b/programs/test/CMakeLists.txt
@@ -27,15 +27,44 @@
     target_link_libraries(cpp_dummy_build ${mbedcrypto_target})
 endif()
 
+if(GEN_FILES)
+    find_package(Perl REQUIRED)
+
+    add_custom_command(
+        OUTPUT
+            ${CMAKE_CURRENT_BINARY_DIR}/query_config.c
+        COMMAND
+            ${PERL}
+                ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/generate_query_config.pl
+                ${CMAKE_CURRENT_SOURCE_DIR}/../../include/mbedtls/mbedtls_config.h
+                ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/data_files/query_config.fmt
+                ${CMAKE_CURRENT_BINARY_DIR}/query_config.c
+        DEPENDS
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/generate_query_config.pl
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../include/mbedtls/mbedtls_config.h
+            ${CMAKE_CURRENT_SOURCE_DIR}/../../scripts/data_files/query_config.fmt
+    )
+    # this file will also be used in another directory, so create a target, see
+    # https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#how-can-i-add-a-dependency-to-a-source-file-which-is-generated-in-a-subdirectory
+    add_custom_target(generate_query_config_c
+        DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/query_config.c)
+else()
+    link_to_source(query_config.c)
+endif()
+
 foreach(exe IN LISTS executables_libs executables_mbedcrypto)
     set(extra_sources "")
     if(exe STREQUAL "query_compile_time_config")
         list(APPEND extra_sources
-            ${CMAKE_CURRENT_SOURCE_DIR}/query_config.c)
+            ${CMAKE_CURRENT_SOURCE_DIR}/query_config.h
+            ${CMAKE_CURRENT_BINARY_DIR}/query_config.c)
     endif()
     add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>
         ${extra_sources})
     target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
+    if(exe STREQUAL "query_compile_time_config")
+        target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
+    endif()
 
     # This emulates "if ( ... IN_LIST ... )" which becomes available in CMake 3.3
     list(FIND executables_libs ${exe} exe_index)
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 5985caf..d3faad9 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -674,7 +674,8 @@
     {
         mbedtls_des3_context des3;
         mbedtls_des3_init( &des3 );
-        mbedtls_des3_set3key_enc( &des3, tmp );
+        if( mbedtls_des3_set3key_enc( &des3, tmp ) != 0 )
+            mbedtls_exit( 1 );
         TIME_AND_TSC( "3DES",
                 mbedtls_des3_crypt_cbc( &des3, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
         mbedtls_des3_free( &des3 );
@@ -684,7 +685,8 @@
     {
         mbedtls_des_context des;
         mbedtls_des_init( &des );
-        mbedtls_des_setkey_enc( &des, tmp );
+        if( mbedtls_des_setkey_enc( &des, tmp ) != 0 )
+            mbedtls_exit( 1 );
         TIME_AND_TSC( "DES",
                 mbedtls_des_crypt_cbc( &des, MBEDTLS_DES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
         mbedtls_des_free( &des );
@@ -722,7 +724,7 @@
 
             memset( buf, 0, sizeof( buf ) );
             memset( tmp, 0, sizeof( tmp ) );
-            mbedtls_aes_setkey_enc( &aes, tmp, keysize );
+            CHECK_AND_CONTINUE( mbedtls_aes_setkey_enc( &aes, tmp, keysize ) );
 
             TIME_AND_TSC( title,
                 mbedtls_aes_crypt_cbc( &aes, MBEDTLS_AES_ENCRYPT, BUFSIZE, tmp, buf, buf ) );
@@ -743,7 +745,7 @@
 
             memset( buf, 0, sizeof( buf ) );
             memset( tmp, 0, sizeof( tmp ) );
-            mbedtls_aes_xts_setkey_enc( &ctx, tmp, keysize * 2 );
+            CHECK_AND_CONTINUE( mbedtls_aes_xts_setkey_enc( &ctx, tmp, keysize * 2 ) );
 
             TIME_AND_TSC( title,
                     mbedtls_aes_crypt_xts( &ctx, MBEDTLS_AES_ENCRYPT, BUFSIZE,
diff --git a/programs/x509/CMakeLists.txt b/programs/x509/CMakeLists.txt
index a04fa8b..5876b8d 100644
--- a/programs/x509/CMakeLists.txt
+++ b/programs/x509/CMakeLists.txt
@@ -7,6 +7,7 @@
     cert_req
     cert_write
     crl_app
+    load_roots
     req_app
 )
 
diff --git a/programs/x509/load_roots.c b/programs/x509/load_roots.c
new file mode 100644
index 0000000..e07bed7
--- /dev/null
+++ b/programs/x509/load_roots.c
@@ -0,0 +1,213 @@
+/*
+ *  Root CA reading application
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ *
+ *  This file is provided under the Apache License 2.0, or the
+ *  GNU General Public License v2.0 or later.
+ *
+ *  **********
+ *  Apache License 2.0:
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  **********
+ *
+ *  **********
+ *  GNU General Public License v2.0 or later:
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ *  **********
+ */
+
+#include "mbedtls/build_info.h"
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#define mbedtls_time            time
+#define mbedtls_time_t          time_t
+#define mbedtls_fprintf         fprintf
+#define mbedtls_printf          printf
+#define mbedtls_exit            exit
+#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
+#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
+#endif /* MBEDTLS_PLATFORM_C */
+
+#if !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) ||  \
+    !defined(MBEDTLS_TIMING_C)
+int main( void )
+{
+    mbedtls_printf("MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_FS_IO and/or "
+           "MBEDTLS_TIMING_C not defined.\n");
+    mbedtls_exit( 0 );
+}
+#else
+
+#include "mbedtls/error.h"
+#include "mbedtls/timing.h"
+#include "mbedtls/x509_crt.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DFL_ITERATIONS          1
+#define DFL_PRIME_CACHE         1
+
+#define USAGE \
+    "\n usage: load_roots param=<>... [--] FILE...\n"   \
+    "\n acceptable parameters:\n"                       \
+    "    iterations=%%d        Iteration count (not including cache priming); default: 1\n"  \
+    "    prime=%%d             Prime the disk read cache? Default: 1 (yes)\n"  \
+    "\n"
+
+
+/*
+ * global options
+ */
+struct options
+{
+    const char **filenames;     /* NULL-terminated list of file names */
+    unsigned iterations;        /* Number of iterations to time */
+    int prime_cache;            /* Prime the disk read cache? */
+} opt;
+
+
+int read_certificates( const char *const *filenames )
+{
+    mbedtls_x509_crt cas;
+    int ret = 0;
+    const char *const *cur;
+
+    mbedtls_x509_crt_init( &cas );
+
+    for( cur = filenames; *cur != NULL; cur++ )
+    {
+        ret = mbedtls_x509_crt_parse_file( &cas, *cur );
+        if( ret != 0 )
+        {
+#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
+            char error_message[200];
+            mbedtls_strerror( ret, error_message, sizeof( error_message ) );
+            printf( "\n%s: -0x%04x (%s)\n",
+                    *cur, (unsigned) -ret, error_message );
+#else
+            printf( "\n%s: -0x%04x\n",
+                    *cur, (unsigned) -ret );
+#endif
+            goto exit;
+        }
+    }
+
+exit:
+    mbedtls_x509_crt_free( &cas );
+    return( ret == 0 );
+}
+
+int main( int argc, char *argv[] )
+{
+    int exit_code = MBEDTLS_EXIT_FAILURE;
+    unsigned i, j;
+    struct mbedtls_timing_hr_time timer;
+    unsigned long ms;
+
+    if( argc <= 1 )
+    {
+        mbedtls_printf( USAGE );
+        goto exit;
+    }
+
+    opt.filenames = NULL;
+    opt.iterations = DFL_ITERATIONS;
+    opt.prime_cache = DFL_PRIME_CACHE;
+
+    for( i = 1; i < (unsigned) argc; i++ )
+    {
+        char *p = argv[i];
+        char *q = NULL;
+
+        if( strcmp( p, "--" ) == 0 )
+            break;
+        if( ( q = strchr( p, '=' ) ) == NULL )
+            break;
+        *q++ = '\0';
+
+        for( j = 0; p + j < q; j++ )
+        {
+            if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' )
+                argv[i][j] |= 0x20;
+        }
+
+        if( strcmp( p, "iterations" ) == 0 )
+        {
+            opt.iterations = atoi( q );
+        }
+        else if( strcmp( p, "prime" ) == 0 )
+        {
+            opt.iterations = atoi( q ) != 0;
+        }
+        else
+        {
+            mbedtls_printf( "Unknown option: %s\n", p );
+            mbedtls_printf( USAGE );
+            goto exit;
+        }
+    }
+
+    opt.filenames = (const char**) argv + i;
+    if( *opt.filenames == 0 )
+    {
+        mbedtls_printf( "Missing list of certificate files to parse\n" );
+        goto exit;
+    }
+
+    mbedtls_printf( "Parsing %u certificates", argc - i );
+    if( opt.prime_cache )
+    {
+        if( ! read_certificates( opt.filenames ) )
+            goto exit;
+        mbedtls_printf( " " );
+    }
+
+    (void) mbedtls_timing_get_timer( &timer, 1 );
+    for( i = 1; i <= opt.iterations; i++ )
+    {
+        if( ! read_certificates( opt.filenames ) )
+            goto exit;
+        mbedtls_printf( "." );
+    }
+    ms = mbedtls_timing_get_timer( &timer, 0 );
+    mbedtls_printf( "\n%u iterations -> %lu ms\n", opt.iterations, ms );
+    exit_code = MBEDTLS_EXIT_SUCCESS;
+
+exit:
+    mbedtls_exit( exit_code );
+}
+#endif /* necessary configuration */
diff --git a/scripts/generate_query_config.pl b/scripts/generate_query_config.pl
index e3bbaa0..7855c7c 100755
--- a/scripts/generate_query_config.pl
+++ b/scripts/generate_query_config.pl
@@ -14,7 +14,8 @@
 # information is used to automatically generate the body of the query_config()
 # function by using the template in scripts/data_files/query_config.fmt.
 #
-# Usage: ./scripts/generate_query_config.pl without arguments
+# Usage: scripts/generate_query_config.pl without arguments, or
+# generate_query_config.pl config_file template_file output_file
 #
 # Copyright The Mbed TLS Contributors
 # SPDX-License-Identifier: Apache-2.0
@@ -33,15 +34,24 @@
 
 use strict;
 
-my $config_file = "./include/mbedtls/mbedtls_config.h";
+my ($config_file, $query_config_format_file, $query_config_file);
 
-my $query_config_format_file = "./scripts/data_files/query_config.fmt";
-my $query_config_file = "./programs/test/query_config.c";
+if( @ARGV ) {
+    die "Invalid number of arguments - usage: $0 [CONFIG_FILE TEMPLATE_FILE OUTPUT_FILE]" if scalar @ARGV != 3;
+    ($config_file, $query_config_format_file, $query_config_file) = @ARGV;
 
-unless( -f $config_file && -f $query_config_format_file ) {
-    chdir '..' or die;
-    -f $config_file && -f $query_config_format_file
-      or die "Without arguments, must be run from root or a subdirectory\n";
+    -f $config_file or die "No such file: $config_file";
+    -f $query_config_format_file or die "No such file: $query_config_format_file";
+} else {
+    $config_file = "./include/mbedtls/mbedtls_config.h";
+    $query_config_format_file = "./scripts/data_files/query_config.fmt";
+    $query_config_file = "./programs/test/query_config.c";
+
+    unless( -f $config_file && -f $query_config_format_file ) {
+        chdir '..' or die;
+        -f $config_file && -f $query_config_format_file
+          or die "No arguments supplied, must be run from project root or a first-level subdirectory\n";
+    }
 }
 
 # Excluded macros from the generated query_config.c. For example, macros that
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index fbd746e..41dceed 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -13,10 +13,48 @@
     message(FATAL_ERROR "Cannot build test suites without Python 3")
 endif()
 
-# Enable definition of various functions used throughout the testsuite
-# (gethostname, strdup, fileno...) even when compiling with -std=c99. Harmless
-# on non-POSIX platforms.
-add_definitions("-D_POSIX_C_SOURCE=200809L")
+# generated .data files will go there
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/suites)
+
+# Get base names for generated files (starting at "suites/")
+execute_process(
+    COMMAND
+        ${MBEDTLS_PYTHON_EXECUTABLE}
+        ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_psa_tests.py
+        --list-for-cmake
+        --directory suites
+    WORKING_DIRECTORY
+        ${CMAKE_CURRENT_SOURCE_DIR}/..
+    OUTPUT_VARIABLE
+        base_generated_data_files)
+
+# Derive generated file paths in the build directory
+set(generated_data_files "")
+foreach(file ${base_generated_data_files})
+    list(APPEND generated_data_files ${CMAKE_CURRENT_BINARY_DIR}/${file})
+endforeach()
+
+if(GEN_FILES)
+    add_custom_command(
+        OUTPUT
+            ${generated_data_files}
+        WORKING_DIRECTORY
+            ${CMAKE_CURRENT_SOURCE_DIR}/..
+        COMMAND
+            ${MBEDTLS_PYTHON_EXECUTABLE}
+            ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_psa_tests.py
+            --directory ${CMAKE_CURRENT_BINARY_DIR}/suites
+        DEPENDS
+            ${CMAKE_CURRENT_SOURCE_DIR}/../tests/scripts/generate_psa_tests.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/../include/psa/crypto_config.h
+            ${CMAKE_CURRENT_SOURCE_DIR}/../include/psa/crypto_values.h
+            ${CMAKE_CURRENT_SOURCE_DIR}/../include/psa/crypto_extra.h
+    )
+else()
+    foreach(file ${base_generated_data_files})
+        link_to_source(${file})
+    endforeach()
+endif()
 
 # Test suites caught by SKIP_TEST_SUITES are built but not executed.
 # "foo" as a skip pattern skips "test_suite_foo" and "test_suite_foo.bar"
@@ -32,10 +70,52 @@
         set(data_name ${suite_name})
     endif()
 
+    # Get the test names of the tests with generated .data files
+    # from the generated_data_files list in parent scope.
+    set(generated_data_names "")
+    foreach(generated_data_file ${generated_data_files})
+        # Get the plain filename
+        get_filename_component(generated_data_name ${generated_data_file} NAME)
+        # Remove the ".data" extension
+        get_name_without_last_ext(generated_data_name ${generated_data_name})
+        # Remove leading "test_suite_"
+        string(SUBSTRING ${generated_data_name} 11 -1 generated_data_name)
+        list(APPEND generated_data_names ${generated_data_name})
+    endforeach()
+
+    if(";${generated_data_names};" MATCHES ";${data_name};")
+        set(data_file
+            ${CMAKE_CURRENT_BINARY_DIR}/suites/test_suite_${data_name}.data)
+    else()
+        set(data_file
+            ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${data_name}.data)
+    endif()
+
     add_custom_command(
-        OUTPUT test_suite_${data_name}.c
-        COMMAND ${MBEDTLS_PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py -f ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function -d ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${data_name}.data -t ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function -p ${CMAKE_CURRENT_SOURCE_DIR}/suites/host_test.function -s ${CMAKE_CURRENT_SOURCE_DIR}/suites --helpers-file ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function -o .
-        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py ${mbedtls_target} ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/host_test.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${data_name}.data
+        OUTPUT
+            # The output filename of generate_test_code.py is derived from the -d
+            # input argument.
+            test_suite_${data_name}.c
+        COMMAND
+            ${MBEDTLS_PYTHON_EXECUTABLE}
+            ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py
+            -f ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function
+            -d ${data_file}
+            -t ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function
+            -p ${CMAKE_CURRENT_SOURCE_DIR}/suites/host_test.function
+            -s ${CMAKE_CURRENT_SOURCE_DIR}/suites
+            --helpers-file ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function
+            -o .
+        DEPENDS
+            ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_test_code.py
+            ${CMAKE_CURRENT_SOURCE_DIR}/suites/test_suite_${suite_name}.function
+            ${data_file}
+            ${CMAKE_CURRENT_SOURCE_DIR}/suites/main_test.function
+            ${CMAKE_CURRENT_SOURCE_DIR}/suites/host_test.function
+            ${CMAKE_CURRENT_SOURCE_DIR}/suites/helpers.function
+            ${mbedtls_target}
+        BYPRODUCTS
+            test_suite_${data_name}.datax
     )
 
     add_executable(test_suite_${data_name} test_suite_${data_name}.c $<TARGET_OBJECTS:mbedtls_test>)
@@ -55,6 +135,11 @@
     endif()
 endfunction(add_test_suite)
 
+# Enable definition of various functions used throughout the testsuite
+# (gethostname, strdup, fileno...) even when compiling with -std=c99. Harmless
+# on non-POSIX platforms.
+add_definitions("-D_POSIX_C_SOURCE=200809L")
+
 if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
     set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function")
 endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)
@@ -170,5 +255,4 @@
     link_to_source(data_files)
     link_to_source(scripts)
     link_to_source(ssl-opt.sh)
-    link_to_source(suites)
 endif()
diff --git a/tests/Makefile b/tests/Makefile
index db642c7..77a3172 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -173,7 +173,7 @@
 
 clean:
 ifndef WINDOWS
-	rm -rf $(BINARIES) *.c *.datax TESTS
+	rm -rf $(BINARIES) *.c *.datax
 	rm -f src/*.o src/drivers/*.o src/libmbed*
 	rm -f include/test/instrument_record_status.h
 else
@@ -184,9 +184,6 @@
 	if exist src/drivers/*.o del /Q /F src/drivers/*.o
 	if exist src/libmbed* del /Q /F src/libmed*
 	if exist include/test/instrument_record_status.h del /Q /F include/test/instrument_record_status.h
-ifneq ($(wildcard TESTS/.*),)
-	rmdir /Q /S TESTS
-endif
 endif
 
 neat: clean
@@ -202,40 +199,6 @@
 
 test: check
 
-# Create separate targets for generating embedded tests.
-EMBEDDED_TESTS := $(addprefix embedded_,$(APPS))
-
-# Generate test code for target.
-
-.SECONDEXPANSION:
-$(EMBEDDED_TESTS): embedded_%: suites/$$(firstword $$(subst ., ,$$*)).function suites/%.data scripts/generate_test_code.py suites/helpers.function suites/main_test.function suites/target_test.function
-	echo "  Gen  ./TESTS/mbedtls/$*/$*.c"
-	$(PYTHON) scripts/generate_test_code.py -f suites/$(firstword $(subst ., ,$*)).function \
-		-d suites/$*.data \
-		-t suites/main_test.function \
-		-p suites/target_test.function \
-		-s suites  \
-		--helpers-file suites/helpers.function \
-		-o ./TESTS/mbedtls/$*
-
-generate-target-tests: $(EMBEDDED_TESTS)
-
-define copy_header_to_target
-TESTS/mbedtls/$(1)/$(2): include/test/$(2)
-	echo "  Copy ./$$@"
-ifndef WINDOWS
-	mkdir -p $$(@D)
-	cp $$< $$@
-else
-	mkdir $$(@D)
-	copy $$< $$@
-endif
-
-endef
-$(foreach app, $(APPS), $(foreach file, $(notdir $(wildcard include/test/*.h)), \
-	$(eval $(call copy_header_to_target,$(app),$(file)))))
-$(addprefix embedded_,$(filter test_suite_psa_%, $(APPS))): embedded_%: $(patsubst TESTS/mbedtls/%, include/test/%, $(wildcard include/test/*. include/test/*/*.h))
-
 ifdef RECORD_PSA_STATUS_COVERAGE_LOG
 include/test/instrument_record_status.h: ../include/psa/crypto.h Makefile
 	echo "  Gen  $@"
diff --git a/tests/include/test/helpers.h b/tests/include/test/helpers.h
index 27e5599..ef32cdf 100644
--- a/tests/include/test/helpers.h
+++ b/tests/include/test/helpers.h
@@ -73,6 +73,8 @@
     const char *filename;
     int line_no;
     unsigned long step;
+    char line1[76];
+    char line2[76];
 #if defined(MBEDTLS_TEST_MUTEX_USAGE)
     const char *mutex_usage_error;
 #endif
@@ -132,6 +134,27 @@
 void mbedtls_test_info_reset( void );
 
 /**
+ * \brief           Record the current test case as a failure if two integers
+ *                  have a different value.
+ *
+ *                  This function is usually called via the macro
+ *                  #TEST_EQUAL.
+ *
+ * \param test      Description of the failure or assertion that failed. This
+ *                  MUST be a string literal. This normally has the form
+ *                  "EXPR1 == EXPR2" where EXPR1 has the value \p value1
+ *                  and EXPR2 has the value \p value2.
+ * \param line_no   Line number where the failure originated.
+ * \param filename  Filename where the failure originated.
+ * \param value1    The first value to compare.
+ * \param value2    The second value to compare.
+ *
+ * \return          \c 1 if the values are equal, otherwise \c 0.
+ */
+int mbedtls_test_equal( const char *test, int line_no, const char* filename,
+                        unsigned long long value1, unsigned long long value2 );
+
+/**
  * \brief          This function decodes the hexadecimal representation of
  *                 data.
  *
diff --git a/tests/include/test/macros.h b/tests/include/test/macros.h
index 9b3fc9c..a88b2e8 100644
--- a/tests/include/test/macros.h
+++ b/tests/include/test/macros.h
@@ -73,15 +73,21 @@
        }                                                    \
     } while( 0 )
 
-/** Evaluate two expressions and fail the test case if they have different
- * values.
+/** Evaluate two integer expressions and fail the test case if they have
+ * different values.
  *
- * \param expr1     An expression to evaluate.
- * \param expr2     The expected value of \p expr1. This can be any
- *                  expression, but it is typically a constant.
+ * The two expressions should have the same signedness, otherwise the
+ * comparison is not meaningful if the signed value is negative.
+ *
+ * \param expr1     An integral-typed expression to evaluate.
+ * \param expr2     Another integral-typed expression to evaluate.
  */
-#define TEST_EQUAL( expr1, expr2 )              \
-    TEST_ASSERT( ( expr1 ) == ( expr2 ) )
+#define TEST_EQUAL( expr1, expr2 )                                      \
+    do {                                                                \
+        if( ! mbedtls_test_equal( #expr1 " == " #expr2, __LINE__, __FILE__, \
+                                  expr1, expr2 ) )                      \
+            goto exit;                                                  \
+    } while( 0 )
 
 /** Allocate memory dynamically and fail the test case if this fails.
  * The allocated memory will be filled with zeros.
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 812b6b1..c148cf1 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -175,7 +175,7 @@
 
     # if MAKEFLAGS is not set add the -j option to speed up invocations of make
     if [ -z "${MAKEFLAGS+set}" ]; then
-        export MAKEFLAGS="-j"
+        export MAKEFLAGS="-j$(all_sh_nproc)"
     fi
 
     # Include more verbose output for failing tests run by CMake or make
@@ -292,7 +292,8 @@
            -iname CMakeFiles -exec rm -rf {} \+ -o \
            \( -iname cmake_install.cmake -o \
               -iname CTestTestfile.cmake -o \
-              -iname CMakeCache.txt \) -exec rm -f {} \+
+              -iname CMakeCache.txt -o \
+              -path './cmake/*.cmake' \) -exec rm -f {} \+
     # Recover files overwritten by in-tree CMake builds
     rm -f include/Makefile include/mbedtls/Makefile programs/*/Makefile
 
@@ -343,6 +344,18 @@
 trap 'fatal_signal INT' INT
 trap 'fatal_signal TERM' TERM
 
+# Number of processors on this machine. Used as the default setting
+# for parallel make.
+all_sh_nproc ()
+{
+    {
+        nproc || # Linux
+        sysctl -n hw.ncpuonline || # NetBSD, OpenBSD
+        sysctl -n hw.ncpu || # FreeBSD
+        echo 1
+    } 2>/dev/null
+}
+
 msg()
 {
     if [ -n "${current_component:-}" ]; then
@@ -986,7 +999,16 @@
 
 component_test_ref_configs () {
     msg "test/build: ref-configs (ASan build)" # ~ 6 min 20s
-    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
+    # test-ref-configs works by overwriting mbedtls_config.h; this makes cmake
+    # want to re-generate generated files that depend on it, quite correctly.
+    # However this doesn't work as the generation script expects a specific
+    # format for mbedtls_config.h, which the other files don't follow. Also,
+    # cmake can't know this, but re-generation is actually not necessary as
+    # the generated files only depend on the list of available options, not
+    # whether they're on or off. So, disable cmake's (over-sensitive here)
+    # dependency resolution for generated files and just rely on them being
+    # present (thanks to pre_generate_files) by turning GEN_FILES off.
+    CC=gcc cmake -D GEN_FILES=Off -D CMAKE_BUILD_TYPE:String=Asan .
     tests/scripts/test-ref-configs.pl
 }
 
@@ -1283,7 +1305,7 @@
 component_test_full_cmake_clang () {
     msg "build: cmake, full config, clang" # ~ 50s
     scripts/config.py full
-    CC=clang cmake -D CMAKE_BUILD_TYPE:String=Check -D ENABLE_TESTING=On .
+    CC=clang cmake -D CMAKE_BUILD_TYPE:String=Release -D ENABLE_TESTING=On .
     make
 
     msg "test: main suites (full config, clang)" # ~ 5s
@@ -1584,6 +1606,19 @@
     make test
 }
 
+component_test_psa_crypto_config_chachapoly_disabled() {
+    # full minus MBEDTLS_CHACHAPOLY_C without PSA_WANT_ALG_GCM and PSA_WANT_ALG_CHACHA20_POLY1305
+    msg "build: full minus MBEDTLS_CHACHAPOLY_C without PSA_WANT_ALG_GCM and PSA_WANT_ALG_CHACHA20_POLY1305"
+    scripts/config.py full
+    scripts/config.py unset MBEDTLS_CHACHAPOLY_C
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_GCM
+    scripts/config.py -f include/psa/crypto_config.h unset PSA_WANT_ALG_CHACHA20_POLY1305
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -O2" LDFLAGS="$ASAN_CFLAGS"
+
+    msg "test: full minus MBEDTLS_CHACHAPOLY_C without PSA_WANT_ALG_GCM and PSA_WANT_ALG_CHACHA20_POLY1305"
+    make test
+}
+
 # This should be renamed to test and updated once the accelerator ECDSA code is in place and ready to test.
 component_build_psa_accel_alg_ecdsa() {
     # full plus MBEDTLS_PSA_CRYPTO_CONFIG with PSA_WANT_ALG_ECDSA
@@ -1926,7 +1961,8 @@
     scripts/config.py set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
     scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
     scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -Os'
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Check .
+    make
 }
 
 component_build_no_ssl_srv () {
@@ -1959,7 +1995,7 @@
     scripts/config.py set MBEDTLS_PLATFORM_MEMORY
     scripts/config.py set MBEDTLS_MEMORY_BACKTRACE
     scripts/config.py set MBEDTLS_MEMORY_DEBUG
-    CC=gcc cmake .
+    CC=gcc cmake -DCMAKE_BUILD_TYPE:String=Release .
     make
 
     msg "test: MBEDTLS_MEMORY_BUFFER_ALLOC_C and MBEDTLS_MEMORY_BACKTRACE"
@@ -1970,7 +2006,7 @@
     msg "build: default config with memory buffer allocator"
     scripts/config.py set MBEDTLS_MEMORY_BUFFER_ALLOC_C
     scripts/config.py set MBEDTLS_PLATFORM_MEMORY
-    CC=gcc cmake .
+    CC=gcc cmake -DCMAKE_BUILD_TYPE:String=Release .
     make
 
     msg "test: MBEDTLS_MEMORY_BUFFER_ALLOC_C"
@@ -2060,6 +2096,18 @@
     tests/compat.sh
 }
 
+component_test_CID_no_debug() {
+    msg "build: Connection ID enabled, debug disabled"
+    scripts/config.py unset MBEDTLS_DEBUG_C
+    scripts/config.py set MBEDTLS_SSL_DTLS_CONNECTION_ID
+
+    CC=gcc cmake .
+    make
+
+    msg "test: Connection ID enabled, debug disabled"
+    make test
+}
+
 component_test_ssl_alloc_buffer_and_mfl () {
     msg "build: default config with memory buffer allocator and MFL extension"
     scripts/config.py set MBEDTLS_MEMORY_BUFFER_ALLOC_C
@@ -2067,7 +2115,7 @@
     scripts/config.py set MBEDTLS_MEMORY_DEBUG
     scripts/config.py set MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
     scripts/config.py set MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
-    CC=gcc cmake .
+    CC=gcc cmake -DCMAKE_BUILD_TYPE:String=Release .
     make
 
     msg "test: MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH, MBEDTLS_MEMORY_BUFFER_ALLOC_C, MBEDTLS_MEMORY_DEBUG and MBEDTLS_SSL_MAX_FRAGMENT_LENGTH"
@@ -2094,7 +2142,7 @@
 component_test_no_date_time () {
     msg "build: default config without MBEDTLS_HAVE_TIME_DATE"
     scripts/config.py unset MBEDTLS_HAVE_TIME_DATE
-    CC=gcc cmake
+    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Check .
     make
 
     msg "test: !MBEDTLS_HAVE_TIME_DATE - main suites"
@@ -2275,7 +2323,8 @@
 }
 
 component_test_m32_o0 () {
-    # Build once with -O0, to compile out the i386 specific inline assembly
+    # Build without optimization, so as to use portable C code (in a 32-bit
+    # build) and not the i386-specific inline assembly.
     msg "build: i386, make, gcc -O0 (ASan build)" # ~ 30s
     scripts/config.py full
     make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O0" LDFLAGS="-m32 $ASAN_CFLAGS"
@@ -2290,19 +2339,20 @@
     esac
 }
 
-component_test_m32_o1 () {
-    # Build again with -O1, to compile in the i386 specific inline assembly
-    msg "build: i386, make, gcc -O1 (ASan build)" # ~ 30s
+component_test_m32_o2 () {
+    # Build with optimization, to use the i386 specific inline assembly
+    # and go faster for tests.
+    msg "build: i386, make, gcc -O2 (ASan build)" # ~ 30s
     scripts/config.py full
-    make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O1" LDFLAGS="-m32 $ASAN_CFLAGS"
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O2" LDFLAGS="-m32 $ASAN_CFLAGS"
 
-    msg "test: i386, make, gcc -O1 (ASan build)"
+    msg "test: i386, make, gcc -O2 (ASan build)"
     make test
 
-    msg "test ssl-opt.sh, i386, make, gcc-O1"
+    msg "test ssl-opt.sh, i386, make, gcc-O2"
     tests/ssl-opt.sh
 }
-support_test_m32_o1 () {
+support_test_m32_o2 () {
     support_test_m32_o0 "$@"
 }
 
@@ -2411,7 +2461,7 @@
     scripts/config.pl full
     scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
     scripts/config.pl set MBEDTLS_X509_REMOVE_INFO
-    make CFLAGS='-Werror -O1'
+    make CFLAGS='-Werror -O2'
 
     msg "test: full + MBEDTLS_X509_REMOVE_INFO" # ~ 10s
     make test
@@ -2631,7 +2681,7 @@
     MBEDTLS_ROOT_DIR="$PWD"
     mkdir "$OUT_OF_SOURCE_DIR"
     cd "$OUT_OF_SOURCE_DIR"
-    cmake "$MBEDTLS_ROOT_DIR"
+    cmake -D CMAKE_BUILD_TYPE:String=Check "$MBEDTLS_ROOT_DIR"
     make
 
     msg "test: cmake 'out-of-source' build"
diff --git a/tests/scripts/check_names.py b/tests/scripts/check_names.py
index a9aa118..ac2490f 100755
--- a/tests/scripts/check_names.py
+++ b/tests/scripts/check_names.py
@@ -44,6 +44,7 @@
 
 import abc
 import argparse
+import fnmatch
 import glob
 import textwrap
 import os
@@ -222,8 +223,9 @@
         # Memo for storing "glob expression": set(filepaths)
         self.files = {}
 
-        # Globally excluded filenames
-        self.excluded_files = ["**/bn_mul", "**/compat-2.x.h"]
+        # Globally excluded filenames.
+        # Note that "*" can match directory separators in exclude lists.
+        self.excluded_files = ["*/bn_mul", "*/compat-2.x.h"]
 
     @staticmethod
     def check_repo_path():
@@ -302,6 +304,15 @@
             "mbed_words": mbed_words
         }
 
+    def is_file_excluded(self, path, exclude_wildcards):
+        """Whether the given file path is excluded."""
+        # exclude_wildcards may be None. Also, consider the global exclusions.
+        exclude_wildcards = (exclude_wildcards or []) + self.excluded_files
+        for pattern in exclude_wildcards:
+            if fnmatch.fnmatch(path, pattern):
+                return True
+        return False
+
     def get_files(self, include_wildcards, exclude_wildcards):
         """
         Get all files that match any of the UNIX-style wildcards. While the
@@ -317,25 +328,11 @@
         """
         accumulator = set()
 
-        # exclude_wildcards may be None. Also, consider the global exclusions.
-        exclude_wildcards = (exclude_wildcards or []) + self.excluded_files
-
-        # Internal function to hit the memoisation cache or add to it the result
-        # of a glob operation. Used both for inclusion and exclusion since the
-        # only difference between them is whether they perform set union or
-        # difference on the return value of this function.
-        def hit_cache(wildcard):
-            if wildcard not in self.files:
-                self.files[wildcard] = set(glob.glob(wildcard, recursive=True))
-            return self.files[wildcard]
-
         for include_wildcard in include_wildcards:
-            accumulator = accumulator.union(hit_cache(include_wildcard))
+            accumulator = accumulator.union(glob.iglob(include_wildcard))
 
-        for exclude_wildcard in exclude_wildcards:
-            accumulator = accumulator.difference(hit_cache(exclude_wildcard))
-
-        return list(accumulator)
+        return list(path for path in accumulator
+                    if not self.is_file_excluded(path, exclude_wildcards))
 
     def parse_macros(self, include, exclude=None):
         """
diff --git a/tests/scripts/generate_psa_tests.py b/tests/scripts/generate_psa_tests.py
index c788ce6..39fb210 100755
--- a/tests/scripts/generate_psa_tests.py
+++ b/tests/scripts/generate_psa_tests.py
@@ -155,8 +155,30 @@
     tc.set_arguments([key_type] + list(args))
     return tc
 
+def test_case_for_key_type_invalid_argument(
+        verb: str, key_type: str, bits: int,
+        dependencies: List[str],
+        *args: str,
+        param_descr: str = ''
+) -> test_case.TestCase:
+    """Return one test case exercising a key creation method
+    for an invalid argument when key is public.
+    """
+    hack_dependencies_not_implemented(dependencies)
+    tc = test_case.TestCase()
+    short_key_type = re.sub(r'PSA_(KEY_TYPE|ECC_FAMILY)_', r'', key_type)
+    adverb = 'not' if dependencies else 'never'
+    if param_descr:
+        adverb = param_descr + ' ' + adverb
+    tc.set_description('PSA {} {} {}-bit invalid argument'
+                       .format(verb, short_key_type, bits))
+    tc.set_function(verb + '_invalid_argument')
+    tc.set_dependencies(dependencies)
+    tc.set_arguments([key_type] + list(args))
+    return tc
+
 class NotSupported:
-    """Generate test cases for when something is not supported."""
+    """Generate test cases for when something is not supported or argument is inavlid."""
 
     def __init__(self, info: Information) -> None:
         self.constructors = info.constructors
@@ -171,11 +193,13 @@
             param: Optional[int] = None,
             param_descr: str = '',
     ) -> Iterator[test_case.TestCase]:
-        """Return test cases exercising key creation when the given type is unsupported.
+        """Return test cases exercising key creation when the given type is unsupported
+        or argument is invalid.
 
         If param is present and not None, emit test cases conditioned on this
         parameter not being supported. If it is absent or None, emit test cases
-        conditioned on the base type not being supported.
+        conditioned on the base type not being supported. If key is public emit test
+        case for invalid argument.
         """
         if kt.name in self.ALWAYS_SUPPORTED:
             # Don't generate test cases for key types that are always supported.
@@ -203,12 +227,20 @@
                 # supported or not depending on implementation capabilities,
                 # only generate the test case once.
                 continue
-            yield test_case_for_key_type_not_supported(
-                'generate', kt.expression, bits,
-                finish_family_dependencies(generate_dependencies, bits),
-                str(bits),
-                param_descr=param_descr,
-            )
+            if kt.name.endswith('_PUBLIC_KEY'):
+                yield test_case_for_key_type_invalid_argument(
+                    'generate', kt.expression, bits,
+                    finish_family_dependencies(generate_dependencies, bits),
+                    str(bits),
+                    param_descr=param_descr,
+                )
+            else:
+                yield test_case_for_key_type_not_supported(
+                    'generate', kt.expression, bits,
+                    finish_family_dependencies(generate_dependencies, bits),
+                    str(bits),
+                    param_descr=param_descr,
+                )
             # To be added: derive
 
     ECC_KEY_TYPES = ('PSA_KEY_TYPE_ECC_KEY_PAIR',
@@ -229,7 +261,6 @@
                 yield from self.test_cases_for_key_type_not_supported(
                     kt, 0, param_descr='curve')
 
-
 class StorageKey(psa_storage.Key):
     """Representation of a key for storage format testing."""
 
@@ -668,6 +699,10 @@
     parser = argparse.ArgumentParser(description=__doc__)
     parser.add_argument('--list', action='store_true',
                         help='List available targets and exit')
+    parser.add_argument('--list-for-cmake', action='store_true',
+                        help='Print \';\'-separated list of available targets and exit')
+    parser.add_argument('--directory', metavar='DIR',
+                        help='Output directory (default: tests/suites)')
     parser.add_argument('targets', nargs='*', metavar='TARGET',
                         help='Target file to generate (default: all; "-": none)')
     options = parser.parse_args(args)
@@ -677,6 +712,11 @@
         for name in sorted(generator.TARGETS):
             print(generator.filename_for(name))
         return
+    # List in a cmake list format (i.e. ';'-separated)
+    if options.list_for_cmake:
+        print(';'.join(generator.filename_for(name)
+                       for name in sorted(generator.TARGETS)), end='')
+        return
     if options.targets:
         # Allow "-" as a special case so you can run
         # ``generate_psa_tests.py - $targets`` and it works uniformly whether
diff --git a/tests/scripts/generate_test_code.py b/tests/scripts/generate_test_code.py
index 7382fb6..f5750aa 100755
--- a/tests/scripts/generate_test_code.py
+++ b/tests/scripts/generate_test_code.py
@@ -106,10 +106,6 @@
 Platform file contains platform specific setup code and test case
 dispatch code. For example, host_test.function reads test data
 file from host's file system and dispatches tests.
-In case of on-target target_test.function tests are not dispatched
-on target. Target code is kept minimum and only test functions are
-dispatched. Test case dispatch is done on the host using tools like
-Greentea.
 
 Template file:
 ---------
diff --git a/tests/scripts/mbedtls_test.py b/tests/scripts/mbedtls_test.py
deleted file mode 100755
index 64f12bb..0000000
--- a/tests/scripts/mbedtls_test.py
+++ /dev/null
@@ -1,382 +0,0 @@
-#!/usr/bin/env python3
-
-# Greentea host test script for Mbed TLS on-target test suite testing.
-#
-# Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-
-"""
-Mbed TLS on-target test suite tests are implemented as Greentea
-tests. Greentea tests are implemented in two parts: target test and
-host test. Target test is a C application that is built for the
-target platform and executes on the target. Host test is a Python
-class derived from mbed_host_tests.BaseHostTest. Target communicates
-with the host over serial for the test data and sends back the result.
-
-Python tool mbedgt (Greentea) is responsible for flashing the test
-binary on to the target and dynamically loading this host test module.
-
-Greentea documentation can be found here:
-https://github.com/ARMmbed/greentea
-"""
-
-
-import re
-import os
-import binascii
-
-from mbed_host_tests import BaseHostTest, event_callback # type: ignore # pylint: disable=import-error
-
-
-class TestDataParserError(Exception):
-    """Indicates error in test data, read from .data file."""
-    pass
-
-
-class TestDataParser:
-    """
-    Parses test name, dependencies, test function name and test parameters
-    from the data file.
-    """
-
-    def __init__(self):
-        """
-        Constructor
-        """
-        self.tests = []
-
-    def parse(self, data_file):
-        """
-        Data file parser.
-
-        :param data_file: Data file path
-        """
-        with open(data_file, 'r') as data_f:
-            self.__parse(data_f)
-
-    @staticmethod
-    def __escaped_split(inp_str, split_char):
-        """
-        Splits inp_str on split_char except when escaped.
-
-        :param inp_str: String to split
-        :param split_char: Split character
-        :return: List of splits
-        """
-        split_colon_fn = lambda x: re.sub(r'\\' + split_char, split_char, x)
-        if len(split_char) > 1:
-            raise ValueError('Expected split character. Found string!')
-        out = list(map(split_colon_fn, re.split(r'(?<!\\)' + split_char, inp_str)))
-        out = [x for x in out if x]
-        return out
-
-    def __parse(self, data_f):
-        """
-        Parses data file using supplied file object.
-
-        :param data_f: Data file object
-        :return:
-        """
-        for line in data_f:
-            line = line.strip()
-            if not line:
-                continue
-            # Read test name
-            name = line
-
-            # Check dependencies
-            dependencies = []
-            line = next(data_f).strip()
-            match = re.search('depends_on:(.*)', line)
-            if match:
-                dependencies = [int(x) for x in match.group(1).split(':')]
-                line = next(data_f).strip()
-
-            # Read test vectors
-            line = line.replace('\\n', '\n')
-            parts = self.__escaped_split(line, ':')
-            function_name = int(parts[0])
-            args = parts[1:]
-            args_count = len(args)
-            if args_count % 2 != 0:
-                err_str_fmt = "Number of test arguments({}) should be even: {}"
-                raise TestDataParserError(err_str_fmt.format(args_count, line))
-            grouped_args = [(args[i * 2], args[(i * 2) + 1])
-                            for i in range(int(len(args)/2))]
-            self.tests.append((name, function_name, dependencies,
-                               grouped_args))
-
-    def get_test_data(self):
-        """
-        Returns test data.
-        """
-        return self.tests
-
-
-class MbedTlsTest(BaseHostTest):
-    """
-    Host test for Mbed TLS unit tests. This script is loaded at
-    run time by Greentea for executing Mbed TLS test suites. Each
-    communication from the target is received in this object as
-    an event, which is then handled by the event handler method
-    decorated by the associated event. Ex: @event_callback('GO').
-
-    Target test sends requests for dispatching next test. It reads
-    tests from the intermediate data file and sends test function
-    identifier, dependency identifiers, expression identifiers and
-    the test data in binary form. Target test checks dependencies
-    , evaluate integer constant expressions and dispatches the test
-    function with received test parameters. After test function is
-    finished, target sends the result. This class handles the result
-    event and prints verdict in the form that Greentea understands.
-
-    """
-    # status/error codes from suites/helpers.function
-    DEPENDENCY_SUPPORTED = 0
-    KEY_VALUE_MAPPING_FOUND = DEPENDENCY_SUPPORTED
-    DISPATCH_TEST_SUCCESS = DEPENDENCY_SUPPORTED
-
-    KEY_VALUE_MAPPING_NOT_FOUND = -1    # Expression Id not found.
-    DEPENDENCY_NOT_SUPPORTED = -2       # Dependency not supported.
-    DISPATCH_TEST_FN_NOT_FOUND = -3     # Test function not found.
-    DISPATCH_INVALID_TEST_DATA = -4     # Invalid parameter type.
-    DISPATCH_UNSUPPORTED_SUITE = -5     # Test suite not supported/enabled.
-
-    def __init__(self):
-        """
-        Constructor initialises test index to 0.
-        """
-        super(MbedTlsTest, self).__init__()
-        self.tests = []
-        self.test_index = -1
-        self.dep_index = 0
-        self.suite_passed = True
-        self.error_str = dict()
-        self.error_str[self.DEPENDENCY_SUPPORTED] = \
-            'DEPENDENCY_SUPPORTED'
-        self.error_str[self.KEY_VALUE_MAPPING_NOT_FOUND] = \
-            'KEY_VALUE_MAPPING_NOT_FOUND'
-        self.error_str[self.DEPENDENCY_NOT_SUPPORTED] = \
-            'DEPENDENCY_NOT_SUPPORTED'
-        self.error_str[self.DISPATCH_TEST_FN_NOT_FOUND] = \
-            'DISPATCH_TEST_FN_NOT_FOUND'
-        self.error_str[self.DISPATCH_INVALID_TEST_DATA] = \
-            'DISPATCH_INVALID_TEST_DATA'
-        self.error_str[self.DISPATCH_UNSUPPORTED_SUITE] = \
-            'DISPATCH_UNSUPPORTED_SUITE'
-
-    def setup(self):
-        """
-        Setup hook implementation. Reads test suite data file and parses out
-        tests.
-        """
-        binary_path = self.get_config_item('image_path')
-        script_dir = os.path.split(os.path.abspath(__file__))[0]
-        suite_name = os.path.splitext(os.path.basename(binary_path))[0]
-        data_file = ".".join((suite_name, 'datax'))
-        data_file = os.path.join(script_dir, '..', 'mbedtls',
-                                 suite_name, data_file)
-        if os.path.exists(data_file):
-            self.log("Running tests from %s" % data_file)
-            parser = TestDataParser()
-            parser.parse(data_file)
-            self.tests = parser.get_test_data()
-            self.print_test_info()
-        else:
-            self.log("Data file not found: %s" % data_file)
-            self.notify_complete(False)
-
-    def print_test_info(self):
-        """
-        Prints test summary read by Greentea to detect test cases.
-        """
-        self.log('{{__testcase_count;%d}}' % len(self.tests))
-        for name, _, _, _ in self.tests:
-            self.log('{{__testcase_name;%s}}' % name)
-
-    @staticmethod
-    def align_32bit(data_bytes):
-        """
-        4 byte aligns input byte array.
-
-        :return:
-        """
-        data_bytes += bytearray((4 - (len(data_bytes))) % 4)
-
-    @staticmethod
-    def hex_str_bytes(hex_str):
-        """
-        Converts Hex string representation to byte array
-
-        :param hex_str: Hex in string format.
-        :return: Output Byte array
-        """
-        if hex_str[0] != '"' or hex_str[len(hex_str) - 1] != '"':
-            raise TestDataParserError("HEX test parameter missing '\"':"
-                                      " %s" % hex_str)
-        hex_str = hex_str.strip('"')
-        if len(hex_str) % 2 != 0:
-            raise TestDataParserError("HEX parameter len should be mod of "
-                                      "2: %s" % hex_str)
-
-        data_bytes = binascii.unhexlify(hex_str)
-        return data_bytes
-
-    @staticmethod
-    def int32_to_big_endian_bytes(i):
-        """
-        Coverts i to byte array in big endian format.
-
-        :param i: Input integer
-        :return: Output bytes array in big endian or network order
-        """
-        data_bytes = bytearray([((i >> x) & 0xff) for x in [24, 16, 8, 0]])
-        return data_bytes
-
-    def test_vector_to_bytes(self, function_id, dependencies, parameters):
-        """
-        Converts test vector into a byte array that can be sent to the target.
-
-        :param function_id: Test Function Identifier
-        :param dependencies: Dependency list
-        :param parameters: Test function input parameters
-        :return: Byte array and its length
-        """
-        data_bytes = bytearray([len(dependencies)])
-        if dependencies:
-            data_bytes += bytearray(dependencies)
-        data_bytes += bytearray([function_id, len(parameters)])
-        for typ, param in parameters:
-            if typ in ('int', 'exp'):
-                i = int(param, 0)
-                data_bytes += b'I' if typ == 'int' else b'E'
-                self.align_32bit(data_bytes)
-                data_bytes += self.int32_to_big_endian_bytes(i)
-            elif typ == 'char*':
-                param = param.strip('"')
-                i = len(param) + 1  # + 1 for null termination
-                data_bytes += b'S'
-                self.align_32bit(data_bytes)
-                data_bytes += self.int32_to_big_endian_bytes(i)
-                data_bytes += bytearray(param, encoding='ascii')
-                data_bytes += b'\0'   # Null terminate
-            elif typ == 'hex':
-                binary_data = self.hex_str_bytes(param)
-                data_bytes += b'H'
-                self.align_32bit(data_bytes)
-                i = len(binary_data)
-                data_bytes += self.int32_to_big_endian_bytes(i)
-                data_bytes += binary_data
-        length = self.int32_to_big_endian_bytes(len(data_bytes))
-        return data_bytes, length
-
-    def run_next_test(self):
-        """
-        Fetch next test information and execute the test.
-
-        """
-        self.test_index += 1
-        self.dep_index = 0
-        if self.test_index < len(self.tests):
-            name, function_id, dependencies, args = self.tests[self.test_index]
-            self.run_test(name, function_id, dependencies, args)
-        else:
-            self.notify_complete(self.suite_passed)
-
-    def run_test(self, name, function_id, dependencies, args):
-        """
-        Execute the test on target by sending next test information.
-
-        :param name: Test name
-        :param function_id: function identifier
-        :param dependencies: Dependencies list
-        :param args: test parameters
-        :return:
-        """
-        self.log("Running: %s" % name)
-
-        param_bytes, length = self.test_vector_to_bytes(function_id,
-                                                        dependencies, args)
-        self.send_kv(
-            ''.join('{:02x}'.format(x) for x in length),
-            ''.join('{:02x}'.format(x) for x in param_bytes)
-        )
-
-    @staticmethod
-    def get_result(value):
-        """
-        Converts result from string type to integer
-        :param value: Result code in string
-        :return: Integer result code. Value is from the test status
-                 constants defined under the MbedTlsTest class.
-        """
-        try:
-            return int(value)
-        except ValueError:
-            ValueError("Result should return error number. "
-                       "Instead received %s" % value)
-
-    @event_callback('GO')
-    def on_go(self, _key, _value, _timestamp):
-        """
-        Sent by the target to start first test.
-
-        :param _key: Event key
-        :param _value: Value. ignored
-        :param _timestamp: Timestamp ignored.
-        :return:
-        """
-        self.run_next_test()
-
-    @event_callback("R")
-    def on_result(self, _key, value, _timestamp):
-        """
-        Handle result. Prints test start, finish required by Greentea
-        to detect test execution.
-
-        :param _key: Event key
-        :param value: Value. ignored
-        :param _timestamp: Timestamp ignored.
-        :return:
-        """
-        int_val = self.get_result(value)
-        name, _, _, _ = self.tests[self.test_index]
-        self.log('{{__testcase_start;%s}}' % name)
-        self.log('{{__testcase_finish;%s;%d;%d}}' % (name, int_val == 0,
-                                                     int_val != 0))
-        if int_val != 0:
-            self.suite_passed = False
-        self.run_next_test()
-
-    @event_callback("F")
-    def on_failure(self, _key, value, _timestamp):
-        """
-        Handles test execution failure. That means dependency not supported or
-        Test function not supported. Hence marking test as skipped.
-
-        :param _key: Event key
-        :param value: Value. ignored
-        :param _timestamp: Timestamp ignored.
-        :return:
-        """
-        int_val = self.get_result(value)
-        if int_val in self.error_str:
-            err = self.error_str[int_val]
-        else:
-            err = 'Unknown error'
-        # For skip status, do not write {{__testcase_finish;...}}
-        self.log("Error: %s" % err)
-        self.run_next_test()
diff --git a/tests/src/helpers.c b/tests/src/helpers.c
index 4d3d53d..ec4d84e 100644
--- a/tests/src/helpers.c
+++ b/tests/src/helpers.c
@@ -95,6 +95,31 @@
     mbedtls_test_info.test = 0;
     mbedtls_test_info.line_no = 0;
     mbedtls_test_info.filename = 0;
+    memset( mbedtls_test_info.line1, 0, sizeof( mbedtls_test_info.line1 ) );
+    memset( mbedtls_test_info.line2, 0, sizeof( mbedtls_test_info.line2 ) );
+}
+
+int mbedtls_test_equal( const char *test, int line_no, const char* filename,
+                        unsigned long long value1, unsigned long long value2 )
+{
+    if( value1 == value2 )
+        return( 1 );
+    if( mbedtls_test_info.result == MBEDTLS_TEST_RESULT_FAILED )
+    {
+        /* We've already recorded the test as having failed. Don't
+         * overwrite any previous information about the failure. */
+        return( 0 );
+    }
+    mbedtls_test_fail( test, line_no, filename );
+    (void) mbedtls_snprintf( mbedtls_test_info.line1,
+                             sizeof( mbedtls_test_info.line1 ),
+                             "lhs = 0x%016llx = %lld",
+                             value1, (long long) value1 );
+    (void) mbedtls_snprintf( mbedtls_test_info.line2,
+                             sizeof( mbedtls_test_info.line2 ),
+                             "rhs = 0x%016llx = %lld",
+                             value2, (long long) value2 );
+    return( 0 );
 }
 
 int mbedtls_test_unhexify( unsigned char *obuf,
diff --git a/tests/src/psa_exercise_key.c b/tests/src/psa_exercise_key.c
index e4e55c9..923d2c1 100644
--- a/tests/src/psa_exercise_key.c
+++ b/tests/src/psa_exercise_key.c
@@ -663,7 +663,7 @@
         TEST_EQUAL( mbedtls_asn1_get_tag( &p, end, &len,
                                           MBEDTLS_ASN1_SEQUENCE |
                                           MBEDTLS_ASN1_CONSTRUCTED ), 0 );
-        TEST_EQUAL( p + len, end );
+        TEST_EQUAL( len, end - p );
         if( ! mbedtls_test_asn1_skip_integer( &p, end, 0, 0, 0 ) )
             goto exit;
         if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
@@ -684,7 +684,7 @@
             goto exit;
         if( ! mbedtls_test_asn1_skip_integer( &p, end, 1, bits / 2 + 1, 0 ) )
             goto exit;
-        TEST_EQUAL( p, end );
+        TEST_EQUAL( p - end, 0 );
 
         TEST_ASSERT( exported_length <= PSA_EXPORT_KEY_PAIR_MAX_SIZE );
     }
@@ -716,12 +716,12 @@
                                           MBEDTLS_ASN1_SEQUENCE |
                                           MBEDTLS_ASN1_CONSTRUCTED ),
                     0 );
-        TEST_EQUAL( p + len, end );
+        TEST_EQUAL( len, end - p );
         if( ! mbedtls_test_asn1_skip_integer( &p, end, bits, bits, 1 ) )
             goto exit;
         if( ! mbedtls_test_asn1_skip_integer( &p, end, 2, bits, 1 ) )
             goto exit;
-        TEST_EQUAL( p, end );
+        TEST_EQUAL( p - end, 0 );
 
 
         TEST_ASSERT( exported_length <=
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 66c6485..9930210 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -552,6 +552,32 @@
     fi
 }
 
+# True if the presence of the given pattern in a log definitely indicates
+# that the test has failed. False if the presence is inconclusive.
+#
+# Inputs:
+# * $1: pattern found in the logs
+# * $TIMES_LEFT: >0 if retrying is an option
+#
+# Outputs:
+# * $outcome: set to a retry reason if the pattern is inconclusive,
+#             unchanged otherwise.
+# * Return value: 1 if the pattern is inconclusive,
+#                 0 if the failure is definitive.
+log_pattern_presence_is_conclusive() {
+    # If we've run out of attempts, then don't retry no matter what.
+    if [ $TIMES_LEFT -eq 0 ]; then
+        return 0
+    fi
+    case $1 in
+        "resend")
+            # An undesired resend may have been caused by the OS dropping or
+            # delaying a packet at an inopportune time.
+            outcome="RETRY(resend)"
+            return 1;;
+    esac
+}
+
 # fail <message>
 fail() {
     record_outcome "FAIL" "$1"
@@ -626,6 +652,8 @@
 # Wait for process $2 named $3 to be listening on port $1. Print error to $4.
 if type lsof >/dev/null 2>/dev/null; then
     wait_app_start() {
+        newline='
+'
         START_TIME=$(date +%s)
         if [ "$DTLS" -eq 1 ]; then
             proto=UDP
@@ -633,7 +661,15 @@
             proto=TCP
         fi
         # Make a tight loop, server normally takes less than 1s to start.
-        while ! lsof -a -n -b -i "$proto:$1" -p "$2" >/dev/null 2>/dev/null; do
+        while true; do
+              SERVER_PIDS=$(lsof -a -n -b -i "$proto:$1" -F p)
+              # When we use a proxy, it will be listening on the same port we
+              # are checking for as well as the server and lsof will list both.
+              # If multiple PIDs are returned, each one will be on a separate
+              # line, each prepended with 'p'.
+             case ${newline}${SERVER_PIDS}${newline} in
+                  *${newline}p${2}${newline}*) break;;
+              esac
               if [ $(( $(date +%s) - $START_TIME )) -gt $DOG_DELAY ]; then
                   echo "$3 START TIMEOUT"
                   echo "$3 START TIMEOUT" >> $4
@@ -753,7 +789,7 @@
 # check if the given command uses dtls and sets global variable DTLS
 detect_dtls() {
     case "$1" in
-        *dtls=1*|-dtls|-u) DTLS=1;;
+        *dtls=1*|*-dtls*|*-u*) DTLS=1;;
         *) DTLS=0;;
     esac
 }
@@ -795,6 +831,271 @@
     SKIP_HANDSHAKE_CHECK="YES"
 }
 
+# Analyze the commands that will be used in a test.
+#
+# Analyze and possibly instrument $PXY_CMD, $CLI_CMD, $SRV_CMD to pass
+# extra arguments or go through wrappers.
+# Set $DTLS (0=TLS, 1=DTLS).
+analyze_test_commands() {
+    # update DTLS variable
+    detect_dtls "$SRV_CMD"
+
+    # if the test uses DTLS but no custom proxy, add a simple proxy
+    # as it provides timing info that's useful to debug failures
+    if [ -z "$PXY_CMD" ] && [ "$DTLS" -eq 1 ]; then
+        PXY_CMD="$P_PXY"
+        case " $SRV_CMD " in
+            *' server_addr=::1 '*)
+                PXY_CMD="$PXY_CMD server_addr=::1 listen_addr=::1";;
+        esac
+    fi
+
+    # update CMD_IS_GNUTLS variable
+    is_gnutls "$SRV_CMD"
+
+    # if the server uses gnutls but doesn't set priority, explicitly
+    # set the default priority
+    if [ "$CMD_IS_GNUTLS" -eq 1 ]; then
+        case "$SRV_CMD" in
+              *--priority*) :;;
+              *) SRV_CMD="$SRV_CMD --priority=NORMAL";;
+        esac
+    fi
+
+    # update CMD_IS_GNUTLS variable
+    is_gnutls "$CLI_CMD"
+
+    # if the client uses gnutls but doesn't set priority, explicitly
+    # set the default priority
+    if [ "$CMD_IS_GNUTLS" -eq 1 ]; then
+        case "$CLI_CMD" in
+              *--priority*) :;;
+              *) CLI_CMD="$CLI_CMD --priority=NORMAL";;
+        esac
+    fi
+
+    # fix client port
+    if [ -n "$PXY_CMD" ]; then
+        CLI_CMD=$( echo "$CLI_CMD" | sed s/+SRV_PORT/$PXY_PORT/g )
+    else
+        CLI_CMD=$( echo "$CLI_CMD" | sed s/+SRV_PORT/$SRV_PORT/g )
+    fi
+
+    # prepend valgrind to our commands if active
+    if [ "$MEMCHECK" -gt 0 ]; then
+        if is_polar "$SRV_CMD"; then
+            SRV_CMD="valgrind --leak-check=full $SRV_CMD"
+        fi
+        if is_polar "$CLI_CMD"; then
+            CLI_CMD="valgrind --leak-check=full $CLI_CMD"
+        fi
+    fi
+}
+
+# Check for failure conditions after a test case.
+#
+# Inputs from run_test:
+# * positional parameters: test options (see run_test documentation)
+# * $CLI_EXIT: client return code
+# * $CLI_EXPECT: expected client return code
+# * $SRV_RET: server return code
+# * $CLI_OUT, $SRV_OUT, $PXY_OUT: files containing client/server/proxy logs
+# * $TIMES_LEFT: if nonzero, a RETRY outcome is allowed
+#
+# Outputs:
+# * $outcome: one of PASS/RETRY*/FAIL
+check_test_failure() {
+    outcome=FAIL
+
+    if [ $TIMES_LEFT -gt 0 ] &&
+       grep '===CLIENT_TIMEOUT===' $CLI_OUT >/dev/null
+    then
+        outcome="RETRY(client-timeout)"
+        return
+    fi
+
+    # check if the client and server went at least to the handshake stage
+    # (useful to avoid tests with only negative assertions and non-zero
+    # expected client exit to incorrectly succeed in case of catastrophic
+    # failure)
+    if [ "X$SKIP_HANDSHAKE_CHECK" != "XYES" ]
+    then
+        if is_polar "$SRV_CMD"; then
+            if grep "Performing the SSL/TLS handshake" $SRV_OUT >/dev/null; then :;
+            else
+                fail "server or client failed to reach handshake stage"
+                return
+            fi
+        fi
+        if is_polar "$CLI_CMD"; then
+            if grep "Performing the SSL/TLS handshake" $CLI_OUT >/dev/null; then :;
+            else
+                fail "server or client failed to reach handshake stage"
+                return
+            fi
+        fi
+    fi
+
+    SKIP_HANDSHAKE_CHECK="NO"
+    # Check server exit code (only for Mbed TLS: GnuTLS and OpenSSL don't
+    # exit with status 0 when interrupted by a signal, and we don't really
+    # care anyway), in case e.g. the server reports a memory leak.
+    if [ $SRV_RET != 0 ] && is_polar "$SRV_CMD"; then
+        fail "Server exited with status $SRV_RET"
+        return
+    fi
+
+    # check client exit code
+    if [ \( "$CLI_EXPECT" = 0 -a "$CLI_EXIT" != 0 \) -o \
+         \( "$CLI_EXPECT" != 0 -a "$CLI_EXIT" = 0 \) ]
+    then
+        fail "bad client exit code (expected $CLI_EXPECT, got $CLI_EXIT)"
+        return
+    fi
+
+    # check other assertions
+    # lines beginning with == are added by valgrind, ignore them
+    # lines with 'Serious error when reading debug info', are valgrind issues as well
+    while [ $# -gt 0 ]
+    do
+        case $1 in
+            "-s")
+                if grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then :; else
+                    fail "pattern '$2' MUST be present in the Server output"
+                    return
+                fi
+                ;;
+
+            "-c")
+                if grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then :; else
+                    fail "pattern '$2' MUST be present in the Client output"
+                    return
+                fi
+                ;;
+
+            "-S")
+                if grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then
+                    if log_pattern_presence_is_conclusive "$2"; then
+                        fail "pattern '$2' MUST NOT be present in the Server output"
+                    fi
+                    return
+                fi
+                ;;
+
+            "-C")
+                if grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then
+                    if log_pattern_presence_is_conclusive "$2"; then
+                        fail "pattern '$2' MUST NOT be present in the Client output"
+                    fi
+                    return
+                fi
+                ;;
+
+                # The filtering in the following two options (-u and -U) do the following
+                #   - ignore valgrind output
+                #   - filter out everything but lines right after the pattern occurrences
+                #   - keep one of each non-unique line
+                #   - count how many lines remain
+                # A line with '--' will remain in the result from previous outputs, so the number of lines in the result will be 1
+                # if there were no duplicates.
+            "-U")
+                if [ $(grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep -A1 "$2" | grep -v "$2" | sort | uniq -d | wc -l) -gt 1 ]; then
+                    fail "lines following pattern '$2' must be unique in Server output"
+                    return
+                fi
+                ;;
+
+            "-u")
+                if [ $(grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep -A1 "$2" | grep -v "$2" | sort | uniq -d | wc -l) -gt 1 ]; then
+                    fail "lines following pattern '$2' must be unique in Client output"
+                    return
+                fi
+                ;;
+            "-F")
+                if ! $2 "$SRV_OUT"; then
+                    fail "function call to '$2' failed on Server output"
+                    return
+                fi
+                ;;
+            "-f")
+                if ! $2 "$CLI_OUT"; then
+                    fail "function call to '$2' failed on Client output"
+                    return
+                fi
+                ;;
+            "-g")
+                if ! eval "$2 '$SRV_OUT' '$CLI_OUT'"; then
+                    fail "function call to '$2' failed on Server and Client output"
+                    return
+                fi
+                ;;
+
+            *)
+                echo "Unknown test: $1" >&2
+                exit 1
+        esac
+        shift 2
+    done
+
+    # check valgrind's results
+    if [ "$MEMCHECK" -gt 0 ]; then
+        if is_polar "$SRV_CMD" && has_mem_err $SRV_OUT; then
+            fail "Server has memory errors"
+            return
+        fi
+        if is_polar "$CLI_CMD" && has_mem_err $CLI_OUT; then
+            fail "Client has memory errors"
+            return
+        fi
+    fi
+
+    # if we're here, everything is ok
+    outcome=PASS
+}
+
+# Run the current test case: start the server and if applicable the proxy, run
+# the client, wait for all processes to finish or time out.
+#
+# Inputs:
+# * $NAME: test case name
+# * $CLI_CMD, $SRV_CMD, $PXY_CMD: commands to run
+# * $CLI_OUT, $SRV_OUT, $PXY_OUT: files to contain client/server/proxy logs
+#
+# Outputs:
+# * $CLI_EXIT: client return code
+# * $SRV_RET: server return code
+do_run_test_once() {
+    # run the commands
+    if [ -n "$PXY_CMD" ]; then
+        printf "# %s\n%s\n" "$NAME" "$PXY_CMD" > $PXY_OUT
+        $PXY_CMD >> $PXY_OUT 2>&1 &
+        PXY_PID=$!
+        wait_proxy_start "$PXY_PORT" "$PXY_PID"
+    fi
+
+    check_osrv_dtls
+    printf '# %s\n%s\n' "$NAME" "$SRV_CMD" > $SRV_OUT
+    provide_input | $SRV_CMD >> $SRV_OUT 2>&1 &
+    SRV_PID=$!
+    wait_server_start "$SRV_PORT" "$SRV_PID"
+
+    printf '# %s\n%s\n' "$NAME" "$CLI_CMD" > $CLI_OUT
+    eval "$CLI_CMD" >> $CLI_OUT 2>&1 &
+    wait_client_done
+
+    sleep 0.05
+
+    # terminate the server (and the proxy)
+    kill $SRV_PID
+    wait $SRV_PID
+    SRV_RET=$?
+
+    if [ -n "$PXY_CMD" ]; then
+        kill $PXY_PID >/dev/null 2>&1
+        wait $PXY_PID
+    fi
+}
+
 # Usage: run_test name [-p proxy_cmd] srv_cmd cli_cmd cli_exit [option [...]]
 # Options:  -s pattern  pattern that must be present in server output
 #           -c pattern  pattern that must be present in client output
@@ -857,234 +1158,23 @@
         return
     fi
 
-    # update DTLS variable
-    detect_dtls "$SRV_CMD"
-
-    # if the test uses DTLS but no custom proxy, add a simple proxy
-    # as it provides timing info that's useful to debug failures
-    if [ -z "$PXY_CMD" ] && [ "$DTLS" -eq 1 ]; then
-        PXY_CMD="$P_PXY"
-        case " $SRV_CMD " in
-            *' server_addr=::1 '*)
-                PXY_CMD="$PXY_CMD server_addr=::1 listen_addr=::1";;
-        esac
-    fi
-
-    # update CMD_IS_GNUTLS variable
-    is_gnutls "$SRV_CMD"
-
-    # if the server uses gnutls but doesn't set priority, explicitly
-    # set the default priority
-    if [ "$CMD_IS_GNUTLS" -eq 1 ]; then
-        case "$SRV_CMD" in
-              *--priority*) :;;
-              *) SRV_CMD="$SRV_CMD --priority=NORMAL";;
-        esac
-    fi
-
-    # update CMD_IS_GNUTLS variable
-    is_gnutls "$CLI_CMD"
-
-    # if the client uses gnutls but doesn't set priority, explicitly
-    # set the default priority
-    if [ "$CMD_IS_GNUTLS" -eq 1 ]; then
-        case "$CLI_CMD" in
-              *--priority*) :;;
-              *) CLI_CMD="$CLI_CMD --priority=NORMAL";;
-        esac
-    fi
-
-    # fix client port
-    if [ -n "$PXY_CMD" ]; then
-        CLI_CMD=$( echo "$CLI_CMD" | sed s/+SRV_PORT/$PXY_PORT/g )
-    else
-        CLI_CMD=$( echo "$CLI_CMD" | sed s/+SRV_PORT/$SRV_PORT/g )
-    fi
-
-    # prepend valgrind to our commands if active
-    if [ "$MEMCHECK" -gt 0 ]; then
-        if is_polar "$SRV_CMD"; then
-            SRV_CMD="valgrind --leak-check=full $SRV_CMD"
-        fi
-        if is_polar "$CLI_CMD"; then
-            CLI_CMD="valgrind --leak-check=full $CLI_CMD"
-        fi
-    fi
+    analyze_test_commands "$@"
 
     TIMES_LEFT=2
     while [ $TIMES_LEFT -gt 0 ]; do
         TIMES_LEFT=$(( $TIMES_LEFT - 1 ))
 
-        # run the commands
-        if [ -n "$PXY_CMD" ]; then
-            printf "# %s\n%s\n" "$NAME" "$PXY_CMD" > $PXY_OUT
-            $PXY_CMD >> $PXY_OUT 2>&1 &
-            PXY_PID=$!
-            wait_proxy_start "$PXY_PORT" "$PXY_PID"
-        fi
+        do_run_test_once
 
-        check_osrv_dtls
-        printf '# %s\n%s\n' "$NAME" "$SRV_CMD" > $SRV_OUT
-        provide_input | $SRV_CMD >> $SRV_OUT 2>&1 &
-        SRV_PID=$!
-        wait_server_start "$SRV_PORT" "$SRV_PID"
-
-        printf '# %s\n%s\n' "$NAME" "$CLI_CMD" > $CLI_OUT
-        eval "$CLI_CMD" >> $CLI_OUT 2>&1 &
-        wait_client_done
-
-        sleep 0.05
-
-        # terminate the server (and the proxy)
-        kill $SRV_PID
-        wait $SRV_PID
-        SRV_RET=$?
-
-        if [ -n "$PXY_CMD" ]; then
-            kill $PXY_PID >/dev/null 2>&1
-            wait $PXY_PID
-        fi
-
-        # retry only on timeouts
-        if grep '===CLIENT_TIMEOUT===' $CLI_OUT >/dev/null; then
-            printf "RETRY "
-        else
-            TIMES_LEFT=0
-        fi
-    done
-
-    # check if the client and server went at least to the handshake stage
-    # (useful to avoid tests with only negative assertions and non-zero
-    # expected client exit to incorrectly succeed in case of catastrophic
-    # failure)
-    if [ "X$SKIP_HANDSHAKE_CHECK" != "XYES" ]
-    then
-        if is_polar "$SRV_CMD"; then
-            if grep "Performing the SSL/TLS handshake" $SRV_OUT >/dev/null; then :;
-            else
-                fail "server or client failed to reach handshake stage"
-                return
-            fi
-        fi
-        if is_polar "$CLI_CMD"; then
-            if grep "Performing the SSL/TLS handshake" $CLI_OUT >/dev/null; then :;
-            else
-                fail "server or client failed to reach handshake stage"
-                return
-            fi
-        fi
-    fi
-
-    SKIP_HANDSHAKE_CHECK="NO"
-    # Check server exit code (only for Mbed TLS: GnuTLS and OpenSSL don't
-    # exit with status 0 when interrupted by a signal, and we don't really
-    # care anyway), in case e.g. the server reports a memory leak.
-    if [ $SRV_RET != 0 ] && is_polar "$SRV_CMD"; then
-        fail "Server exited with status $SRV_RET"
-        return
-    fi
-
-    # check client exit code
-    if [ \( "$CLI_EXPECT" = 0 -a "$CLI_EXIT" != 0 \) -o \
-         \( "$CLI_EXPECT" != 0 -a "$CLI_EXIT" = 0 \) ]
-    then
-        fail "bad client exit code (expected $CLI_EXPECT, got $CLI_EXIT)"
-        return
-    fi
-
-    # check other assertions
-    # lines beginning with == are added by valgrind, ignore them
-    # lines with 'Serious error when reading debug info', are valgrind issues as well
-    while [ $# -gt 0 ]
-    do
-        case $1 in
-            "-s")
-                if grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then :; else
-                    fail "pattern '$2' MUST be present in the Server output"
-                    return
-                fi
-                ;;
-
-            "-c")
-                if grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then :; else
-                    fail "pattern '$2' MUST be present in the Client output"
-                    return
-                fi
-                ;;
-
-            "-S")
-                if grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then
-                    fail "pattern '$2' MUST NOT be present in the Server output"
-                    return
-                fi
-                ;;
-
-            "-C")
-                if grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep "$2" >/dev/null; then
-                    fail "pattern '$2' MUST NOT be present in the Client output"
-                    return
-                fi
-                ;;
-
-                # The filtering in the following two options (-u and -U) do the following
-                #   - ignore valgrind output
-                #   - filter out everything but lines right after the pattern occurrences
-                #   - keep one of each non-unique line
-                #   - count how many lines remain
-                # A line with '--' will remain in the result from previous outputs, so the number of lines in the result will be 1
-                # if there were no duplicates.
-            "-U")
-                if [ $(grep -v '^==' $SRV_OUT | grep -v 'Serious error when reading debug info' | grep -A1 "$2" | grep -v "$2" | sort | uniq -d | wc -l) -gt 1 ]; then
-                    fail "lines following pattern '$2' must be unique in Server output"
-                    return
-                fi
-                ;;
-
-            "-u")
-                if [ $(grep -v '^==' $CLI_OUT | grep -v 'Serious error when reading debug info' | grep -A1 "$2" | grep -v "$2" | sort | uniq -d | wc -l) -gt 1 ]; then
-                    fail "lines following pattern '$2' must be unique in Client output"
-                    return
-                fi
-                ;;
-            "-F")
-                if ! $2 "$SRV_OUT"; then
-                    fail "function call to '$2' failed on Server output"
-                    return
-                fi
-                ;;
-            "-f")
-                if ! $2 "$CLI_OUT"; then
-                    fail "function call to '$2' failed on Client output"
-                    return
-                fi
-                ;;
-            "-g")
-                if ! eval "$2 '$SRV_OUT' '$CLI_OUT'"; then
-                    fail "function call to '$2' failed on Server and Client output"
-                    return
-                fi
-                ;;
-
-            *)
-                echo "Unknown test: $1" >&2
-                exit 1
+        check_test_failure "$@"
+        case $outcome in
+            PASS) break;;
+            RETRY*) printf "$outcome ";;
+            FAIL) return;;
         esac
-        shift 2
     done
 
-    # check valgrind's results
-    if [ "$MEMCHECK" -gt 0 ]; then
-        if is_polar "$SRV_CMD" && has_mem_err $SRV_OUT; then
-            fail "Server has memory errors"
-            return
-        fi
-        if is_polar "$CLI_CMD" && has_mem_err $CLI_OUT; then
-            fail "Client has memory errors"
-            return
-        fi
-    fi
-
-    # if we're here, everything is ok
+    # If we get this far, the test case passed.
     record_outcome "PASS"
     if [ "$PRESERVE_LOGS" -gt 0 ]; then
         mv $SRV_OUT o-srv-${TESTS}.log
@@ -1309,22 +1399,24 @@
 
 # fix commands to use this port, force IPv4 while at it
 # +SRV_PORT will be replaced by either $SRV_PORT or $PXY_PORT later
+# Note: Using 'localhost' rather than 127.0.0.1 here is unwise, as on many
+# machines that will resolve to ::1, and we don't want ipv6 here.
 P_SRV="$P_SRV server_addr=127.0.0.1 server_port=$SRV_PORT"
 P_CLI="$P_CLI server_addr=127.0.0.1 server_port=+SRV_PORT"
 P_PXY="$P_PXY server_addr=127.0.0.1 server_port=$SRV_PORT listen_addr=127.0.0.1 listen_port=$PXY_PORT ${SEED:+"seed=$SEED"}"
 O_SRV="$O_SRV -accept $SRV_PORT"
-O_CLI="$O_CLI -connect localhost:+SRV_PORT"
+O_CLI="$O_CLI -connect 127.0.0.1:+SRV_PORT"
 G_SRV="$G_SRV -p $SRV_PORT"
 G_CLI="$G_CLI -p +SRV_PORT"
 
 if [ -n "${OPENSSL_LEGACY:-}" ]; then
     O_LEGACY_SRV="$O_LEGACY_SRV -accept $SRV_PORT -dhparam data_files/dhparams.pem"
-    O_LEGACY_CLI="$O_LEGACY_CLI -connect localhost:+SRV_PORT"
+    O_LEGACY_CLI="$O_LEGACY_CLI -connect 127.0.0.1:+SRV_PORT"
 fi
 
 if [ -n "${OPENSSL_NEXT:-}" ]; then
     O_NEXT_SRV="$O_NEXT_SRV -accept $SRV_PORT"
-    O_NEXT_CLI="$O_NEXT_CLI -connect localhost:+SRV_PORT"
+    O_NEXT_CLI="$O_NEXT_CLI -connect 127.0.0.1:+SRV_PORT"
 fi
 
 if [ -n "${GNUTLS_NEXT_SERV:-}" ]; then
@@ -1435,12 +1527,53 @@
 requires_config_enabled MBEDTLS_ECDSA_C
 requires_config_enabled MBEDTLS_SHA256_C
 run_test    "Opaque key for client authentication" \
-            "$P_SRV auth_mode=required" \
+            "$P_SRV auth_mode=required crt_file=data_files/server5.crt \
+             key_file=data_files/server5.key" \
             "$P_CLI key_opaque=1 crt_file=data_files/server5.crt \
              key_file=data_files/server5.key" \
             0 \
             -c "key type: Opaque" \
+            -c "Ciphersuite is TLS-ECDHE-ECDSA" \
             -s "Verifying peer X.509 certificate... ok" \
+            -s "Ciphersuite is TLS-ECDHE-ECDSA" \
+            -S "error" \
+            -C "error"
+
+# Test using an opaque private key for server authentication
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+requires_config_enabled MBEDTLS_X509_CRT_PARSE_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SHA256_C
+run_test    "Opaque key for server authentication" \
+            "$P_SRV auth_mode=required key_opaque=1 crt_file=data_files/server5.crt \
+             key_file=data_files/server5.key" \
+            "$P_CLI crt_file=data_files/server5.crt \
+             key_file=data_files/server5.key" \
+            0 \
+            -c "Verifying peer X.509 certificate... ok" \
+            -c "Ciphersuite is TLS-ECDHE-ECDSA" \
+            -s "key types: Opaque - invalid PK" \
+            -s "Ciphersuite is TLS-ECDHE-ECDSA" \
+            -S "error" \
+            -C "error"
+
+# Test using an opaque private key for client/server authentication
+requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
+requires_config_enabled MBEDTLS_X509_CRT_PARSE_C
+requires_config_enabled MBEDTLS_ECDSA_C
+requires_config_enabled MBEDTLS_SHA256_C
+run_test    "Opaque key for client/server authentication" \
+            "$P_SRV auth_mode=required key_opaque=1 crt_file=data_files/server5.crt \
+             key_file=data_files/server5.key" \
+            "$P_CLI key_opaque=1 crt_file=data_files/server5.crt \
+             key_file=data_files/server5.key" \
+            0 \
+            -c "key type: Opaque" \
+            -c "Verifying peer X.509 certificate... ok" \
+            -c "Ciphersuite is TLS-ECDHE-ECDSA" \
+            -s "key types: Opaque - invalid PK" \
+            -s "Verifying peer X.509 certificate... ok" \
+            -s "Ciphersuite is TLS-ECDHE-ECDSA" \
             -S "error" \
             -C "error"
 
@@ -2694,10 +2827,13 @@
             -c "parse new session ticket" \
             -c "a session has been resumed"
 
+# For reasons that aren't fully understood, this test randomly fails with high
+# probability with OpenSSL 1.0.2g on the CI, see #5012.
+requires_openssl_next
 run_test    "Session resume using tickets, DTLS: openssl client" \
             "$P_SRV dtls=1 debug_level=3 tickets=1" \
-            "( $O_CLI -dtls -sess_out $SESSION; \
-               $O_CLI -dtls -sess_in $SESSION; \
+            "( $O_NEXT_CLI -dtls -sess_out $SESSION; \
+               $O_NEXT_CLI -dtls -sess_in $SESSION; \
                rm -f $SESSION )" \
             0 \
             -s "found session ticket extension" \
@@ -2894,10 +3030,13 @@
             -s "a session has been resumed" \
             -c "a session has been resumed"
 
+# For reasons that aren't fully understood, this test randomly fails with high
+# probability with OpenSSL 1.0.2g on the CI, see #5012.
+requires_openssl_next
 run_test    "Session resume using cache, DTLS: openssl client" \
             "$P_SRV dtls=1 debug_level=3 tickets=0" \
-            "( $O_CLI -dtls -sess_out $SESSION; \
-               $O_CLI -dtls -sess_in $SESSION; \
+            "( $O_NEXT_CLI -dtls -sess_out $SESSION; \
+               $O_NEXT_CLI -dtls -sess_in $SESSION; \
                rm -f $SESSION )" \
             0 \
             -s "found session ticket extension" \
@@ -8613,7 +8752,6 @@
             -s "Extra-header:" \
             -c "Extra-header:"
 
-requires_config_enabled MBEDTLS_SSL_EXPORT_KEYS
 run_test    "export keys functionality" \
             "$P_SRV eap_tls=1 debug_level=3" \
             "$P_CLI eap_tls=1 debug_level=3" \
@@ -8625,6 +8763,7 @@
 
 # openssl feature tests: check if tls1.3 exists.
 requires_openssl_tls1_3
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
 run_test    "TLS1.3: Test openssl tls1_3 feature" \
             "$O_NEXT_SRV -tls1_3 -msg" \
             "$O_NEXT_CLI -tls1_3 -msg" \
@@ -8636,8 +8775,9 @@
 requires_gnutls_tls1_3
 requires_gnutls_next_no_ticket
 requires_gnutls_next_disable_tls13_compat
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
 run_test    "TLS1.3: Test gnutls tls1_3 feature" \
-            "$G_NEXT_SRV --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:%NO_TICKETS:%DISABLE_TLS13_COMPAT_MODE" \
+            "$G_NEXT_SRV --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:%NO_TICKETS:%DISABLE_TLS13_COMPAT_MODE --disable-client-cert " \
             "$G_NEXT_CLI localhost --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:%NO_TICKETS:%DISABLE_TLS13_COMPAT_MODE -V" \
             0 \
             -s "Version: TLS1.3" \
@@ -8668,9 +8808,10 @@
 
 requires_openssl_tls1_3
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
+requires_config_disabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "TLS1.3: Test client hello msg work - openssl" \
-            "$O_NEXT_SRV -tls1_3 -msg" \
-            "$P_CLI debug_level=2 min_version=tls1_3 max_version=tls1_3" \
+            "$O_NEXT_SRV -tls1_3 -msg -no_middlebox" \
+            "$P_CLI debug_level=3 min_version=tls1_3 max_version=tls1_3" \
             1 \
             -c "SSL - The requested feature is not available" \
             -s "ServerHello"                \
@@ -8685,13 +8826,22 @@
             -c "tls1_3 client state: 20"    \
             -c "tls1_3 client state: 11"    \
             -c "tls1_3 client state: 14"    \
-            -c "tls1_3 client state: 15"
+            -c "tls1_3 client state: 15"    \
+            -c "<= ssl_tls1_3_process_server_hello" \
+            -c "server hello, chosen ciphersuite: ( 1301 ) - TLS1-3-AES-128-GCM-SHA256" \
+            -c "ECDH curve: x25519"         \
+            -c "=> ssl_tls1_3_process_server_hello" \
+            -c "Certificate verification flags clear" \
+            -c "<= parse encrypted extensions"
 
 requires_gnutls_tls1_3
+requires_gnutls_next_no_ticket
+requires_gnutls_next_disable_tls13_compat
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL
+requires_config_disabled MBEDTLS_USE_PSA_CRYPTO
 run_test    "TLS1.3: Test client hello msg work - gnutls" \
-            "$G_NEXT_SRV --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3 --debug=4" \
-            "$P_CLI debug_level=2 min_version=tls1_3 max_version=tls1_3" \
+            "$G_NEXT_SRV --debug=4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:+CIPHER-ALL:%NO_TICKETS:%DISABLE_TLS13_COMPAT_MODE --disable-client-cert" \
+            "$P_CLI debug_level=3 min_version=tls1_3 max_version=tls1_3" \
             1 \
             -c "SSL - The requested feature is not available" \
             -s "SERVER HELLO was queued"    \
@@ -8706,7 +8856,13 @@
             -c "tls1_3 client state: 20"    \
             -c "tls1_3 client state: 11"    \
             -c "tls1_3 client state: 14"    \
-            -c "tls1_3 client state: 15"
+            -c "tls1_3 client state: 15"    \
+            -c "<= ssl_tls1_3_process_server_hello" \
+            -c "server hello, chosen ciphersuite: ( 1301 ) - TLS1-3-AES-128-GCM-SHA256" \
+            -c "ECDH curve: x25519"         \
+            -c "=> ssl_tls1_3_process_server_hello" \
+            -c "Certificate verification flags clear" \
+            -c "<= parse encrypted extensions"
 
 # Test heap memory usage after handshake
 requires_config_enabled MBEDTLS_MEMORY_DEBUG
diff --git a/tests/suites/host_test.function b/tests/suites/host_test.function
index a5fd717..17926eb 100644
--- a/tests/suites/host_test.function
+++ b/tests/suites/host_test.function
@@ -778,6 +778,12 @@
                     mbedtls_fprintf( stdout, "line %d, %s",
                                      mbedtls_test_info.line_no,
                                      mbedtls_test_info.filename );
+                    if( mbedtls_test_info.line1[0] != 0 )
+                        mbedtls_fprintf( stdout, "\n  %s",
+                                         mbedtls_test_info.line1 );
+                    if( mbedtls_test_info.line2[0] != 0 )
+                        mbedtls_fprintf( stdout, "\n  %s",
+                                         mbedtls_test_info.line2 );
                 }
                 fflush( stdout );
             }
diff --git a/tests/suites/target_test.function b/tests/suites/target_test.function
deleted file mode 100644
index 637a79d..0000000
--- a/tests/suites/target_test.function
+++ /dev/null
@@ -1,449 +0,0 @@
-#line 2 "suites/target_test.function"
-
-#include "greentea-client/test_env.h"
-
-/**
- * \brief       Increments pointer and asserts that it does not overflow.
- *
- * \param p     Pointer to byte array
- * \param start Pointer to start of byte array
- * \param len   Length of byte array
- * \param step  Increment size
- *
- */
-#define INCR_ASSERT(p, start, len, step) do                     \
-{                                                               \
-    TEST_HELPER_ASSERT( ( p ) >= ( start ) );                               \
-    TEST_HELPER_ASSERT( sizeof( *( p ) ) == sizeof( *( start ) ) );         \
-    /* <= is checked to support use inside a loop where         \
-       pointer is incremented after reading data.       */      \
-    TEST_HELPER_ASSERT( (uint32_t)( ( ( p ) - ( start ) ) + ( step ) ) <= ( len ) );\
-    ( p ) += ( step );                                          \
-}                                                               \
-while( 0 )
-
-
-/**
- * \brief       4 byte align unsigned char pointer
- *
- * \param p     Pointer to byte array
- * \param start Pointer to start of byte array
- * \param len   Length of byte array
- *
- */
-#define ALIGN_32BIT(p, start, len) do               \
-{                                                   \
-    uint32_t align = ( - (uintptr_t)( p ) ) % 4;    \
-    INCR_ASSERT( ( p ), ( start ), ( len ), align );\
-}                                                   \
-while( 0 )
-
-
-/**
- * \brief       Verify dependencies. Dependency identifiers are
- *              encoded in the buffer as 8 bit unsigned integers.
- *
- * \param count     Number of dependencies.
- * \param dep_p     Pointer to buffer.
- *
- * \return          DEPENDENCY_SUPPORTED if success else DEPENDENCY_NOT_SUPPORTED.
- */
-int verify_dependencies( uint8_t count, uint8_t * dep_p )
-{
-    uint8_t i;
-    for ( i = 0; i < count; i++ )
-    {
-        if ( dep_check( (int)(dep_p[i]) ) != DEPENDENCY_SUPPORTED )
-            return( DEPENDENCY_NOT_SUPPORTED );
-    }
-    return( DEPENDENCY_SUPPORTED );
-}
-
-/**
- * \brief       Receives hex string on serial interface, and converts to a byte.
- *
- * \param none
- *
- * \return      unsigned int8
- */
-uint8_t receive_byte()
-{
-    uint8_t byte;
-    uint8_t c[3];
-    size_t len;
-
-    c[0] = greentea_getc();
-    c[1] = greentea_getc();
-    c[2] = '\0';
-
-    TEST_HELPER_ASSERT( mbedtls_test_unhexify( &byte, sizeof( byte ),
-                                               c, &len ) == 0 );
-    TEST_HELPER_ASSERT( len != 2 );
-
-    return( byte );
-}
-
-/**
- * \brief       Receives unsigned integer on serial interface.
- *              Integers are encoded in network order, and sent as hex ascii string.
- *
- * \param none
- *
- * \return      unsigned int
- */
-uint32_t receive_uint32()
-{
-    uint32_t value;
-    size_t len;
-    const uint8_t c_be[8] = { greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc(),
-                              greentea_getc()
-                             };
-    const uint8_t c[9] = { c_be[6], c_be[7], c_be[4], c_be[5], c_be[2],
-                           c_be[3], c_be[0], c_be[1], '\0' };
-
-    TEST_HELPER_ASSERT( mbedtls_test_unhexify( (uint8_t*)&value, sizeof( value ),
-                                               c, &len ) == 0 );
-    TEST_HELPER_ASSERT( len != 8 );
-
-    return( value );
-}
-
-/**
- * \brief       Parses out an unsigned 32 int value from the byte array.
- *              Integers are encoded in network order.
- *
- * \param p     Pointer to byte array
- *
- * \return      unsigned int
- */
-uint32_t parse_uint32( uint8_t * p )
-{
-    uint32_t value;
-    value =  *p++ << 24;
-    value |= *p++ << 16;
-    value |= *p++ << 8;
-    value |= *p;
-    return( value );
-}
-
-
-/**
- * \brief       Receives test data on serial as greentea key,value pair:
- *              {{<length>;<byte array>}}
- *
- * \param data_len  Out pointer to hold received data length.
- *
- * \return      Byte array.
- */
-uint8_t * receive_data( uint32_t * data_len )
-{
-    uint32_t i = 0, errors = 0;
-    char c;
-    uint8_t * data = NULL;
-
-    /* Read opening braces */
-    i = 0;
-    while ( i < 2 )
-    {
-        c = greentea_getc();
-        /* Ignore any prevous CR LF characters */
-        if ( c == '\n' || c == '\r' )
-            continue;
-        i++;
-        if ( c != '{' )
-            return( NULL );
-    }
-
-    /* Read data length */
-    *data_len = receive_uint32();
-    data = (uint8_t *)malloc( *data_len );
-    TEST_HELPER_ASSERT( data != NULL );
-
-    greentea_getc(); // read ';' received after key i.e. *data_len
-
-    for( i = 0; i < *data_len; i++ )
-        data[i] = receive_byte();
-
-    /* Read closing braces */
-    for( i = 0; i < 2; i++ )
-    {
-        c = greentea_getc();
-        if ( c != '}' )
-        {
-            errors++;
-            break;
-        }
-    }
-
-    if ( errors )
-    {
-        free( data );
-        data = NULL;
-        *data_len = 0;
-    }
-
-    return( data );
-}
-
-/**
- * \brief       Parse the received byte array and count the number of arguments
- *              to the test function passed as type hex.
- *
- * \param count     Parameter count
- * \param data      Received Byte array
- * \param data_len  Byte array length
- *
- * \return      count of hex params
- */
-uint32_t find_hex_count( uint8_t count, uint8_t * data, uint32_t data_len )
-{
-    uint32_t i = 0, sz = 0;
-    char c;
-    uint8_t * p = NULL;
-    uint32_t hex_count = 0;
-
-    p = data;
-
-    for( i = 0; i < count; i++ )
-    {
-        c = (char)*p;
-        INCR_ASSERT( p, data, data_len, 1 );
-
-        /* Align p to 4 bytes for int, expression, string len or hex length */
-        ALIGN_32BIT( p, data, data_len );
-
-        /* Network to host conversion */
-        sz = (int32_t)parse_uint32( p );
-
-        INCR_ASSERT( p, data, data_len, sizeof( int32_t ) );
-
-        if ( c == 'H' || c == 'S' )
-        {
-            INCR_ASSERT( p, data, data_len, sz );
-            hex_count += ( c == 'H' )?1:0;
-        }
-    }
-
-    return( hex_count );
-}
-
-/**
- * \brief       Parses received byte array for test parameters.
- *
- * \param count     Parameter count
- * \param data      Received Byte array
- * \param data_len  Byte array length
- * \param error     Parsing error out variable.
- *
- * \return      Array of parsed parameters allocated on heap.
- *              Note: Caller has the responsibility to delete
- *                    the memory after use.
- */
-void ** parse_parameters( uint8_t count, uint8_t * data, uint32_t data_len,
-                          int * error )
-{
-    uint32_t i = 0, hex_count = 0;
-    char c;
-    void ** params = NULL;
-    void ** cur = NULL;
-    uint8_t * p = NULL;
-
-    hex_count = find_hex_count(count, data, data_len);
-
-    params = (void **)malloc( sizeof( void *) * ( count + hex_count ) );
-    TEST_HELPER_ASSERT( params != NULL );
-    cur = params;
-
-    p = data;
-
-    /* Parameters */
-    for( i = 0; i < count; i++ )
-    {
-        c = (char)*p;
-        INCR_ASSERT( p, data, data_len, 1 );
-
-        /* Align p to 4 bytes for int, expression, string len or hex length */
-        ALIGN_32BIT( p, data, data_len );
-
-        /* Network to host conversion */
-        *( (int32_t *)p ) = (int32_t)parse_uint32( p );
-
-        switch( c )
-        {
-            case 'E':
-                {
-                    if ( get_expression( *( (int32_t *)p ), (int32_t *)p ) )
-                    {
-                        *error = KEY_VALUE_MAPPING_NOT_FOUND;
-                        goto exit;
-                    }
-                } /* Intentional fall through */
-            case 'I':
-                {
-                    *cur++ = (void *)p;
-                    INCR_ASSERT( p, data, data_len, sizeof( int32_t ) );
-                }
-                break;
-            case 'H': /* Intentional fall through */
-            case 'S':
-                {
-                    uint32_t * sz = (uint32_t *)p;
-                    INCR_ASSERT( p, data, data_len, sizeof( int32_t ) );
-                    *cur++ = (void *)p;
-                    if ( c == 'H' )
-                        *cur++ = (void *)sz;
-                    INCR_ASSERT( p, data, data_len, ( *sz ) );
-                }
-                break;
-            default:
-                    {
-                        *error = DISPATCH_INVALID_TEST_DATA;
-                        goto exit;
-                    }
-                break;
-        }
-    }
-
-exit:
-    if ( *error )
-    {
-        free( params );
-        params = NULL;
-    }
-
-    return( params );
-}
-
-/**
- * \brief       Sends greentea key and int value pair to host.
- *
- * \param key   key string
- * \param value integer value
- *
- * \return      void
- */
-void send_key_integer( char * key, int value )
-{
-    char str[50];
-    snprintf( str, sizeof( str ), "%d", value );
-    greentea_send_kv( key, str );
-}
-
-/**
- * \brief       Sends test setup failure to the host.
- *
- * \param failure   Test set failure
- *
- * \return      void
- */
-void send_failure( int failure )
-{
-    send_key_integer( "F", failure );
-}
-
-/**
- * \brief       Sends test status to the host.
- *
- * \param status    Test status (PASS=0/FAIL=!0)
- *
- * \return      void
- */
-void send_status( int status )
-{
-    send_key_integer( "R", status );
-}
-
-
-/**
- * \brief       Embedded implementation of execute_tests().
- *              Ignores command line and received test data
- *              on serial.
- *
- * \param argc  not used
- * \param argv  not used
- *
- * \return      Program exit status.
- */
-int execute_tests( int args, const char ** argv )
-{
-    int ret = 0;
-    uint32_t data_len = 0;
-    uint8_t count = 0, function_id;
-    void ** params = NULL;
-    uint8_t * data = NULL, * p = NULL;
-
-    GREENTEA_SETUP( 800, "mbedtls_test" );
-    greentea_send_kv( "GO", " " );
-
-    while ( 1 )
-    {
-        ret = 0;
-        mbedtls_test_info_reset( );
-        data_len = 0;
-
-        data = receive_data( &data_len );
-        if ( data == NULL )
-            continue;
-        p = data;
-
-        do
-        {
-            /* Read dependency count */
-            count = *p;
-            TEST_HELPER_ASSERT( count < data_len );
-            INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
-            ret = verify_dependencies( count, p );
-            if ( ret != DEPENDENCY_SUPPORTED )
-                break;
-
-            if ( count )
-                INCR_ASSERT( p, data, data_len, count );
-
-            /* Read function id */
-            function_id = *p;
-            INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
-            if ( ( ret = check_test( function_id ) ) != DISPATCH_TEST_SUCCESS )
-                break;
-
-            /* Read number of parameters */
-            count = *p;
-            INCR_ASSERT( p, data, data_len, sizeof( uint8_t ) );
-
-            /* Parse parameters if present */
-            if ( count )
-            {
-                params = parse_parameters( count, p, data_len - ( p - data ), &ret );
-                if ( ret )
-                    break;
-            }
-
-            ret = dispatch_test( function_id, params );
-        }
-        while ( 0 );
-
-        if ( data )
-        {
-            free( data );
-            data = NULL;
-        }
-
-        if ( params )
-        {
-            free( params );
-            params = NULL;
-        }
-
-        if ( ret )
-            send_failure( ret );
-        else
-            send_status( mbedtls_test_info.result );
-    }
-    return( 0 );
-}
-
diff --git a/tests/suites/test_suite_aes.function b/tests/suites/test_suite_aes.function
index 1892c25..52af8e0 100644
--- a/tests/suites/test_suite_aes.function
+++ b/tests/suites/test_suite_aes.function
@@ -67,7 +67,7 @@
 
     mbedtls_aes_init( &ctx );
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cbc( &ctx, MBEDTLS_AES_ENCRYPT, src_str->len, iv_str->x, src_str->x, output ) == cbc_result );
     if( cbc_result == 0 )
     {
@@ -92,7 +92,7 @@
     memset(output, 0x00, 100);
     mbedtls_aes_init( &ctx );
 
-    mbedtls_aes_setkey_dec( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_dec( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cbc( &ctx, MBEDTLS_AES_DECRYPT, src_str->len, iv_str->x, src_str->x, output ) == cbc_result );
     if( cbc_result == 0)
     {
@@ -241,7 +241,7 @@
     mbedtls_aes_init( &ctx );
 
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cfb128( &ctx, MBEDTLS_AES_ENCRYPT, 16, &iv_offset, iv_str->x, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x, 16, dst->len ) == 0 );
@@ -263,7 +263,7 @@
     mbedtls_aes_init( &ctx );
 
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cfb128( &ctx, MBEDTLS_AES_DECRYPT, 16, &iv_offset, iv_str->x, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x, 16, dst->len ) == 0 );
@@ -284,7 +284,7 @@
     mbedtls_aes_init( &ctx );
 
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cfb8( &ctx, MBEDTLS_AES_ENCRYPT, src_str->len, iv_str->x, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x,
@@ -306,7 +306,7 @@
     mbedtls_aes_init( &ctx );
 
 
-    mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 );
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
     TEST_ASSERT( mbedtls_aes_crypt_cfb8( &ctx, MBEDTLS_AES_DECRYPT, src_str->len, iv_str->x, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x,
diff --git a/tests/suites/test_suite_base64.data b/tests/suites/test_suite_base64.data
index 3a892f4..5556668 100644
--- a/tests/suites/test_suite_base64.data
+++ b/tests/suites/test_suite_base64.data
@@ -1,3 +1,33 @@
+mask_of_range empty (1..0)
+mask_of_range:1:0
+
+mask_of_range empty (255..0)
+mask_of_range:255:0
+
+mask_of_range empty (42..7)
+mask_of_range:42:7
+
+mask_of_range 0..0
+mask_of_range:0:0
+
+mask_of_range 42..42
+mask_of_range:42:42
+
+mask_of_range 255..255
+mask_of_range:255:255
+
+mask_of_range 0..255
+mask_of_range:0:255
+
+mask_of_range 'A'..'Z'
+mask_of_range:65:90
+
+enc_char (all digits)
+enc_chars:
+
+dec_value (all characters)
+dec_chars:
+
 Test case mbedtls_base64_encode #1 buffer just right
 mbedtls_base64_encode:"":"":0:0
 
diff --git a/tests/suites/test_suite_base64.function b/tests/suites/test_suite_base64.function
index be9b6e8..67fbb67 100644
--- a/tests/suites/test_suite_base64.function
+++ b/tests/suites/test_suite_base64.function
@@ -1,6 +1,13 @@
 /* BEGIN_HEADER */
 #include "mbedtls/base64.h"
+#include "base64_invasive.h"
 #include <test/constant_flow.h>
+
+#if defined(MBEDTLS_TEST_HOOKS)
+static const char base64_digits[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#endif /* MBEDTLS_TEST_HOOKS */
+
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -8,6 +15,65 @@
  * END_DEPENDENCIES
  */
 
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
+void mask_of_range( int low_arg, int high_arg )
+{
+    unsigned char low = low_arg, high = high_arg;
+    unsigned c;
+    for( c = 0; c <= 0xff; c++ )
+    {
+        mbedtls_test_set_step( c );
+        TEST_CF_SECRET( &c, sizeof( c ) );
+        unsigned char m = mbedtls_base64_mask_of_range( low, high, c );
+        TEST_CF_PUBLIC( &c, sizeof( c ) );
+        TEST_CF_PUBLIC( &m, sizeof( m ) );
+        if( low <= c && c <= high )
+            TEST_EQUAL( m, 0xff );
+        else
+            TEST_EQUAL( m, 0 );
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
+void enc_chars( )
+{
+    for( unsigned value = 0; value < 64; value++ )
+    {
+        mbedtls_test_set_step( value );
+        TEST_CF_SECRET( &value, sizeof( value ) );
+        unsigned char digit = mbedtls_base64_enc_char( value );
+        TEST_CF_PUBLIC( &value, sizeof( value ) );
+        TEST_CF_PUBLIC( &digit, sizeof( digit ) );
+        TEST_EQUAL( digit, base64_digits[value] );
+    }
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */
+void dec_chars( )
+{
+    char *p;
+    signed char expected;
+
+    for( unsigned c = 0; c <= 0xff; c++ )
+    {
+        mbedtls_test_set_step( c );
+        /* base64_digits is 0-terminated. sizeof()-1 excludes the trailing 0. */
+        p = memchr( base64_digits, c, sizeof( base64_digits ) - 1 );
+        if( p == NULL )
+            expected = -1;
+        else
+            expected = p - base64_digits;
+        TEST_CF_SECRET( &c, sizeof( c ) );
+        signed char actual = mbedtls_base64_dec_value( c );
+        TEST_CF_PUBLIC( &c, sizeof( c ) );
+        TEST_CF_PUBLIC( &actual, sizeof( actual ) );
+        TEST_EQUAL( actual, expected );
+    }
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void mbedtls_base64_encode( char * src_string, char * dst_string,
                             int dst_buf_size, int result )
diff --git a/tests/suites/test_suite_des.function b/tests/suites/test_suite_des.function
index 5b24935..7256fb5 100644
--- a/tests/suites/test_suite_des.function
+++ b/tests/suites/test_suite_des.function
@@ -24,7 +24,7 @@
     mbedtls_des_init( &ctx );
 
 
-    mbedtls_des_setkey_enc( &ctx, key_str->x );
+    TEST_ASSERT( mbedtls_des_setkey_enc( &ctx, key_str->x ) == 0 );
     TEST_ASSERT( mbedtls_des_crypt_ecb( &ctx, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x, 8, dst->len ) == 0 );
@@ -44,7 +44,7 @@
     mbedtls_des_init( &ctx );
 
 
-    mbedtls_des_setkey_dec( &ctx, key_str->x );
+    TEST_ASSERT( mbedtls_des_setkey_dec( &ctx, key_str->x ) == 0 );
     TEST_ASSERT( mbedtls_des_crypt_ecb( &ctx, src_str->x, output ) == 0 );
 
     TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x, 8, dst->len ) == 0 );
@@ -65,7 +65,7 @@
     mbedtls_des_init( &ctx );
 
 
-    mbedtls_des_setkey_enc( &ctx, key_str->x );
+    TEST_ASSERT( mbedtls_des_setkey_enc( &ctx, key_str->x ) == 0 );
     TEST_ASSERT( mbedtls_des_crypt_cbc( &ctx, MBEDTLS_DES_ENCRYPT, src_str->len, iv_str->x, src_str->x, output ) == cbc_result );
     if( cbc_result == 0 )
     {
@@ -91,7 +91,7 @@
     mbedtls_des_init( &ctx );
 
 
-    mbedtls_des_setkey_dec( &ctx, key_str->x );
+    TEST_ASSERT( mbedtls_des_setkey_dec( &ctx, key_str->x ) == 0 );
     TEST_ASSERT( mbedtls_des_crypt_cbc( &ctx, MBEDTLS_DES_DECRYPT, src_str->len, iv_str->x, src_str->x, output ) == cbc_result );
     if( cbc_result == 0 )
     {
@@ -117,9 +117,9 @@
 
 
     if( key_count == 2 )
-        mbedtls_des3_set2key_enc( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set2key_enc( &ctx, key_str->x ) == 0 );
     else if( key_count == 3 )
-        mbedtls_des3_set3key_enc( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set3key_enc( &ctx, key_str->x ) == 0 );
     else
         TEST_ASSERT( 0 );
 
@@ -144,9 +144,9 @@
 
 
     if( key_count == 2 )
-        mbedtls_des3_set2key_dec( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set2key_dec( &ctx, key_str->x ) == 0 );
     else if( key_count == 3 )
-        mbedtls_des3_set3key_dec( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set3key_dec( &ctx, key_str->x ) == 0 );
     else
         TEST_ASSERT( 0 );
 
@@ -172,9 +172,9 @@
 
 
     if( key_count == 2 )
-        mbedtls_des3_set2key_enc( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set2key_enc( &ctx, key_str->x ) == 0 );
     else if( key_count == 3 )
-        mbedtls_des3_set3key_enc( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set3key_enc( &ctx, key_str->x ) == 0 );
     else
         TEST_ASSERT( 0 );
 
@@ -205,9 +205,9 @@
 
 
     if( key_count == 2 )
-        mbedtls_des3_set2key_dec( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set2key_dec( &ctx, key_str->x ) == 0 );
     else if( key_count == 3 )
-        mbedtls_des3_set3key_dec( &ctx, key_str->x );
+        TEST_ASSERT( mbedtls_des3_set3key_dec( &ctx, key_str->x ) == 0 );
     else
         TEST_ASSERT( 0 );
 
diff --git a/tests/suites/test_suite_gcm.aes128_de.data b/tests/suites/test_suite_gcm.aes128_de.data
index 3df31e5..ede6f24 100644
--- a/tests/suites/test_suite_gcm.aes128_de.data
+++ b/tests/suites/test_suite_gcm.aes128_de.data
@@ -726,6 +726,10 @@
 depends_on:MBEDTLS_AES_C
 gcm_bad_parameters:MBEDTLS_CIPHER_ID_AES:MBEDTLS_GCM_DECRYPT:"d0194b6ee68f0ed8adc4b22ed15dbf14":"":"":"":32:MBEDTLS_ERR_GCM_BAD_INPUT
 
+AES-GCM, output buffer too small, NIST Validation (AES-128,128,1024,0,128) #0
+depends_on:MBEDTLS_AES_C
+gcm_update_output_buffer_too_small:MBEDTLS_CIPHER_ID_AES:MBEDTLS_GCM_DECRYPT:"0dd358bc3f992f26e81e3a2f3aa2d517":"87cc4fd75788c9d5cc83bae5d764dd249d178ab23224049795d4288b5ed9ea3f317068a39a7574b300c8544226e87b08e008fbe241d094545c211d56ac44437d41491a438272738968c8d371aa7787b5f606c8549a9d868d8a71380e9657d3c0337979feb01de5991fc1470dfc59eb02511efbbff3fcb479a862ba3844a25aaa":"d8c750bb443ee1a169dfe97cfe4d855b"
+
 AES-GCM Selftest
 depends_on:MBEDTLS_AES_C
 gcm_selftest:
diff --git a/tests/suites/test_suite_gcm.aes128_en.data b/tests/suites/test_suite_gcm.aes128_en.data
index d60c458..273642c 100644
--- a/tests/suites/test_suite_gcm.aes128_en.data
+++ b/tests/suites/test_suite_gcm.aes128_en.data
@@ -726,6 +726,9 @@
 depends_on:MBEDTLS_AES_C
 gcm_bad_parameters:MBEDTLS_CIPHER_ID_AES:MBEDTLS_GCM_ENCRYPT:"d0194b6ee68f0ed8adc4b22ed15dbf14":"":"":"":32:MBEDTLS_ERR_GCM_BAD_INPUT
 
+AES-GCM, output buffer too small, NIST Validation (AES-128,128,1024,0,128) #0
+gcm_update_output_buffer_too_small:MBEDTLS_CIPHER_ID_AES:MBEDTLS_GCM_ENCRYPT:"ce0f8cfe9d64c4f4c045d11b97c2d918":"dfff250d380f363880963b42d6913c1ba11e8edf7c4ab8b76d79ccbaac628f548ee542f48728a9a2620a0d69339c8291e8d398440d740e310908cdee7c273cc91275ce7271ba12f69237998b07b789b3993aaac8dc4ec1914432a30f5172f79ea0539bd1f70b36d437e5170bc63039a5280816c05e1e41760b58e35696cebd55":"ad4c3627a494fc628316dc03faf81db8"
+
 AES-GCM Selftest
 depends_on:MBEDTLS_AES_C
 gcm_selftest:
diff --git a/tests/suites/test_suite_gcm.function b/tests/suites/test_suite_gcm.function
index c530e6b..5696679 100644
--- a/tests/suites/test_suite_gcm.function
+++ b/tests/suites/test_suite_gcm.function
@@ -431,6 +431,29 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE */
+void gcm_update_output_buffer_too_small( int cipher_id, int mode,
+                                         data_t * key_str, const data_t *input,
+                                         const data_t *iv )
+{
+    mbedtls_gcm_context ctx;
+    uint8_t *output = NULL;
+    size_t olen = 0;
+    size_t output_len = input->len - 1;
+
+    mbedtls_gcm_init( &ctx );
+    TEST_EQUAL( mbedtls_gcm_setkey( &ctx, cipher_id, key_str->x, key_str->len * 8 ), 0 );
+    TEST_EQUAL( 0, mbedtls_gcm_starts( &ctx, mode, iv->x, iv->len ) );
+
+    ASSERT_ALLOC( output, output_len );
+    TEST_EQUAL( MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL, mbedtls_gcm_update( &ctx, input->x, input->len, output, output_len, &olen ) );
+
+exit:
+    mbedtls_free( output );
+    mbedtls_gcm_free( &ctx );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
 void gcm_selftest(  )
 {
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index e189d0f..9c20495 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -3364,7 +3364,7 @@
 
 PSA AEAD finish buffer test: AES - GCM, BUF = 8, TAG = 16
 depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
-aead_multipart_finish_buffer_test:PSA_KEY_TYPE_AES:"fbc0b4c56a714c83217b2d1bcadd2ed2e9efb0dcac6cc19f":PSA_ALG_GCM:8:16:"5f4b43e811da9c470d6a9b01":"":"d2ae38c4375954835d75b8e4c2f9bbb4":PSA_ERROR_BUFFER_TOO_SMALL
+aead_multipart_finish_buffer_test:PSA_KEY_TYPE_AES:"fbc0b4c56a714c83217b2d1bcadd2ed2e9efb0dcac6cc19f":PSA_ALG_GCM:8:16:"5f4b43e811da9c470d6a9b01":"":"d2ae38c4375954835d75b8e4c2f9bbb4":PSA_SUCCESS
 
 PSA AEAD finish buffer test: AES - GCM, BUF = 15, TAG = 20
 depends_on:PSA_WANT_ALG_GCM:PSA_WANT_KEY_TYPE_AES
@@ -4558,19 +4558,19 @@
 
 PSA key derivation: HKDF SHA-256, request maximum capacity
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
-derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":255 * 32:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865":""
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:"000102030405060708090a0b0c":PSA_KEY_DERIVATION_INPUT_SECRET:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_KEY_DERIVATION_INPUT_INFO:"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256):"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865":""
 
 PSA key derivation: HKDF SHA-1, request maximum capacity
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1
-derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):PSA_KEY_DERIVATION_INPUT_SALT:"":PSA_KEY_DERIVATION_INPUT_SECRET:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":PSA_KEY_DERIVATION_INPUT_INFO:"":255 * 20:"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48":""
+derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_1):PSA_KEY_DERIVATION_INPUT_SALT:"":PSA_KEY_DERIVATION_INPUT_SECRET:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":PSA_KEY_DERIVATION_INPUT_INFO:"":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_1):"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48":""
 
 PSA key derivation: HKDF SHA-256, request too much capacity
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
-derive_set_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_256):255 * 32 + 1:PSA_ERROR_INVALID_ARGUMENT
+derive_set_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_256):255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256) + 1:PSA_ERROR_INVALID_ARGUMENT
 
 PSA key derivation: HKDF SHA-1, request too much capacity
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_1
-derive_set_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_1):255 * 20 + 1:PSA_ERROR_INVALID_ARGUMENT
+derive_set_capacity:PSA_ALG_HKDF(PSA_ALG_SHA_1):255 * PSA_HASH_LENGTH(PSA_ALG_SHA_1) + 1:PSA_ERROR_INVALID_ARGUMENT
 
 PSA key derivation: over capacity 42: output 42+1
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
@@ -4590,19 +4590,19 @@
 
 PSA key derivation: HKDF SHA-256, read maximum capacity minus 1
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
-derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32 - 1
+derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256) - 1
 
 PSA key derivation: HKDF SHA-256, read maximum capacity
 depends_on:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256
-derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32
+derive_full:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256)
 
 PSA key derivation: TLS 1.2 PRF SHA-256, read maximum capacity minus 1
 depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
-derive_full:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32 - 1
+derive_full:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256) - 1
 
 PSA key derivation: TLS 1.2 PRF SHA-256, read maximum capacity
 depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_PRF
-derive_full:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * 32
+derive_full:PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":255 * PSA_HASH_LENGTH(PSA_ALG_SHA_256)
 
 PSA key derivation: HKDF SHA-256, exercise AES128-CTR
 depends_on:PSA_WANT_ALG_CTR:PSA_WANT_ALG_HKDF:PSA_WANT_ALG_SHA_256:PSA_WANT_KEY_TYPE_AES
@@ -4841,7 +4841,7 @@
 
 PSA generate key: bad type (RSA public key)
 depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY
-generate_key:PSA_KEY_TYPE_RSA_PUBLIC_KEY:512:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_NOT_SUPPORTED:0
+generate_key:PSA_KEY_TYPE_RSA_PUBLIC_KEY:512:PSA_KEY_USAGE_EXPORT:0:PSA_ERROR_INVALID_ARGUMENT:0
 
 PSA generate key: raw data, 0 bits: invalid argument
 # The spec allows either INVALID_ARGUMENT or NOT_SUPPORTED
diff --git a/tests/suites/test_suite_psa_crypto_metadata.data b/tests/suites/test_suite_psa_crypto_metadata.data
index 7eb1dc9..ad806c7 100644
--- a/tests/suites/test_suite_psa_crypto_metadata.data
+++ b/tests/suites/test_suite_psa_crypto_metadata.data
@@ -130,6 +130,18 @@
 depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_CCM
 aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_AES:256
 
+AEAD: CCM-ARIA-128
+depends_on:PSA_WANT_KEY_TYPE_ARIA:PSA_WANT_ALG_CCM
+aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_ARIA:128
+
+AEAD: CCM-ARIA-192
+depends_on:PSA_WANT_KEY_TYPE_ARIA:PSA_WANT_ALG_CCM
+aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_ARIA:192
+
+AEAD: CCM-ARIA-256
+depends_on:PSA_WANT_KEY_TYPE_ARIA:PSA_WANT_ALG_CCM
+aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_ARIA:256
+
 AEAD: CCM-CAMELLIA-128
 depends_on:PSA_WANT_KEY_TYPE_CAMELLIA:PSA_WANT_ALG_CCM
 aead_algorithm:PSA_ALG_CCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_CAMELLIA:128
@@ -154,6 +166,18 @@
 depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_GCM
 aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_AES:256
 
+AEAD: GCM-ARIA-128
+depends_on:PSA_WANT_KEY_TYPE_ARIA:PSA_WANT_ALG_GCM
+aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_ARIA:128
+
+AEAD: GCM-ARIA-192
+depends_on:PSA_WANT_KEY_TYPE_ARIA:PSA_WANT_ALG_GCM
+aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_ARIA:192
+
+AEAD: GCM-ARIA-256
+depends_on:PSA_WANT_KEY_TYPE_ARIA:PSA_WANT_ALG_GCM
+aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_ARIA:256
+
 AEAD: GCM-CAMELLIA-128
 depends_on:PSA_WANT_KEY_TYPE_CAMELLIA:PSA_WANT_ALG_GCM
 aead_algorithm:PSA_ALG_GCM:ALG_IS_AEAD_ON_BLOCK_CIPHER:16:PSA_KEY_TYPE_CAMELLIA:128
@@ -303,6 +327,10 @@
 depends_on:PSA_WANT_KEY_TYPE_AES
 block_cipher_key_type:PSA_KEY_TYPE_AES:16
 
+Block cipher key type: ARIA
+depends_on:PSA_WANT_KEY_TYPE_ARIA
+block_cipher_key_type:PSA_KEY_TYPE_ARIA:16
+
 Block cipher key type: DES
 depends_on:PSA_WANT_KEY_TYPE_DES
 block_cipher_key_type:PSA_KEY_TYPE_DES:8
diff --git a/tests/suites/test_suite_psa_crypto_not_supported.function b/tests/suites/test_suite_psa_crypto_not_supported.function
index e3253d8..0665230 100644
--- a/tests/suites/test_suite_psa_crypto_not_supported.function
+++ b/tests/suites/test_suite_psa_crypto_not_supported.function
@@ -50,3 +50,22 @@
     PSA_DONE( );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void generate_invalid_argument( int key_type, int bits )
+{
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = INVALID_KEY_ID;
+
+    PSA_ASSERT( psa_crypto_init( ) );
+    psa_set_key_type( &attributes, key_type );
+    psa_set_key_bits( &attributes, bits );
+    TEST_EQUAL( psa_generate_key( &attributes, &key_id ),
+                PSA_ERROR_INVALID_ARGUMENT );
+    TEST_ASSERT( mbedtls_svc_key_id_equal( key_id, MBEDTLS_SVC_KEY_ID_INIT ) );
+
+exit:
+    psa_destroy_key( key_id );
+    PSA_DONE( );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_psa_crypto_se_driver_hal.data b/tests/suites/test_suite_psa_crypto_se_driver_hal.data
index a57e9b3..2bcf4e4 100644
--- a/tests/suites/test_suite_psa_crypto_se_driver_hal.data
+++ b/tests/suites/test_suite_psa_crypto_se_driver_hal.data
@@ -78,6 +78,21 @@
 Key import smoke test: AES-GCM
 import_key_smoke:PSA_KEY_TYPE_AES:PSA_ALG_GCM:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
 
+Key import smoke test: ARIA-CTR
+import_key_smoke:PSA_KEY_TYPE_ARIA:PSA_ALG_CTR:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+Key import smoke test: ARIA-CBC
+import_key_smoke:PSA_KEY_TYPE_ARIA:PSA_ALG_CBC_NO_PADDING:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+Key import smoke test: ARIA-CMAC
+import_key_smoke:PSA_KEY_TYPE_ARIA:PSA_ALG_CMAC:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+Key import smoke test: ARIA-CCM
+import_key_smoke:PSA_KEY_TYPE_ARIA:PSA_ALG_CCM:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+Key import smoke test: ARIA-GCM
+import_key_smoke:PSA_KEY_TYPE_ARIA:PSA_ALG_GCM:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
 Key import smoke test: CAMELLIA-CTR
 import_key_smoke:PSA_KEY_TYPE_CAMELLIA:PSA_ALG_CTR:"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"