Merge pull request #959 from paul-elliott-arm/merge-into-3.2.0

Merge 3.2.0 into development
diff --git a/BRANCHES.md b/BRANCHES.md
index 3aca159..6240023 100644
--- a/BRANCHES.md
+++ b/BRANCHES.md
@@ -12,11 +12,6 @@
 - One or more long-time support (LTS) branches: these only get bug fixes and
   security fixes. Currently, the only supported LTS branch is:
   [`mbedtls-2.28`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-2.28).
-- For a short time we also have the previous LTS, which has recently ended its
-  support period,
-  [`mbedtls-2.16`](https://github.com/Mbed-TLS/mbedtls/tree/mbedtls-2.16).
-  This branch will move into the `archive` namespace around the time of
-  the next release.
 
 We retain a number of historical branches, whose names are prefixed by `archive/`,
 such as [`archive/mbedtls-2.7`](https://github.com/Mbed-TLS/mbedtls/tree/archive/mbedtls-2.7).
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b97368f..2610359 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -348,7 +348,7 @@
     write_basic_package_version_file(
         "cmake/MbedTLSConfigVersion.cmake"
             COMPATIBILITY SameMajorVersion
-            VERSION 3.1.0)
+            VERSION 3.2.0)
 
     install(
         FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/MbedTLSConfig.cmake"
diff --git a/ChangeLog b/ChangeLog
index 71ba44d..6b1bb21 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,274 @@
-mbed TLS ChangeLog (Sorted per branch, date)
+Mbed TLS ChangeLog (Sorted per branch, date)
+
+= Mbed TLS 3.2.0 branch released 2022-07-11
+
+Default behavior changes
+   * mbedtls_cipher_set_iv will now fail with ChaCha20 and ChaCha20+Poly1305
+     for IV lengths other than 12. The library was silently overwriting this
+     length with 12, but did not inform the caller about it. Fixes #4301.
+
+Requirement changes
+   * The library will no longer compile out of the box on a platform without
+     setbuf(). If your platform does not have setbuf(), you can configure an
+     alternative function by enabling MBEDTLS_PLATFORM_SETBUF_ALT or
+     MBEDTLS_PLATFORM_SETBUF_MACRO.
+
+New deprecations
+   * Deprecate mbedtls_ssl_conf_max_version() and
+     mbedtls_ssl_conf_min_version() in favor of
+     mbedtls_ssl_conf_max_tls_version() and
+     mbedtls_ssl_conf_min_tls_version().
+   * Deprecate mbedtls_cipher_setup_psa(). Use psa_aead_xxx() or
+     psa_cipher_xxx() directly instead.
+   * Secure element drivers enabled by MBEDTLS_PSA_CRYPTO_SE_C are deprecated.
+     This was intended as an experimental feature, but had not been explicitly
+     documented as such. Use opaque drivers with the interface enabled by
+     MBEDTLS_PSA_CRYPTO_DRIVERS instead.
+   * Deprecate mbedtls_ssl_conf_sig_hashes() in favor of the more generic
+     mbedtls_ssl_conf_sig_algs(). Signature algorithms for the TLS 1.2 and
+     TLS 1.3 handshake should now be configured with
+     mbedtls_ssl_conf_sig_algs().
+
+Features
+   * Add accessor to obtain ciphersuite id from ssl context.
+   * Add accessors to get members from ciphersuite info.
+   * Add mbedtls_ssl_ticket_rotate() for external ticket rotation.
+   * Add accessor to get the raw buffer pointer from a PEM context.
+   * The structures mbedtls_ssl_config and mbedtls_ssl_context now store
+     a piece of user data which is reserved for the application. The user
+     data can be either a pointer or an integer.
+   * Add an accessor function to get the configuration associated with
+     an SSL context.
+   * Add a function to access the protocol version from an SSL context in a
+     form that's easy to compare. Fixes #5407.
+   * Add function mbedtls_md_info_from_ctx() to recall the message digest
+     information that was used to set up a message digest context.
+   * Add ALPN support in TLS 1.3 clients.
+   * Add server certificate selection callback near end of Client Hello.
+     Register callback with mbedtls_ssl_conf_cert_cb().
+   * Provide mechanism to reset handshake cert list by calling
+     mbedtls_ssl_set_hs_own_cert() with NULL value for own_cert param.
+   * Add accessor mbedtls_ssl_get_hs_sni() to retrieve SNI from within
+     cert callback (mbedtls_ssl_conf_cert_cb()) during handshake.
+   * The X.509 module now uses PSA hash acceleration if present.
+   * Add support for psa crypto key derivation for elliptic curve
+     keys. Fixes #3260.
+   * Add function mbedtls_timing_get_final_delay() to access the private
+     final delay field in an mbedtls_timing_delay_context, as requested in
+     #5183.
+    * Add mbedtls_pk_sign_ext() which allows generating RSA-PSS signatures when
+      PSA Crypto is enabled.
+   * Add function mbedtls_ecp_export() to export ECP key pair parameters.
+     Fixes #4838.
+   * Add function mbedtls_ssl_is_handshake_over() to enable querying if the SSL
+     Handshake has completed or not, and thus whether to continue calling
+     mbedtls_ssl_handshake_step(), requested in #4383.
+   * Add the function mbedtls_ssl_get_own_cid() to access our own connection id
+     within mbedtls_ssl_context, as requested in #5184.
+   * Introduce mbedtls_ssl_hs_cb_t typedef for use with
+     mbedtls_ssl_conf_cert_cb() and perhaps future callbacks
+     during TLS handshake.
+   * Add functions mbedtls_ssl_conf_max_tls_version() and
+     mbedtls_ssl_conf_min_tls_version() that use a single value to specify
+     the protocol version.
+    * Extend the existing PSA_ALG_TLS12_PSK_TO_MS() algorithm to support
+      mixed-PSK. Add an optional input PSA_KEY_DERIVATION_INPUT_OTHER_SECRET
+      holding the other secret.
+   * When MBEDTLS_PSA_CRYPTO_CONFIG is enabled, you may list the PSA crypto
+     feature requirements in the file named by the new macro
+     MBEDTLS_PSA_CRYPTO_CONFIG_FILE instead of the default psa/crypto_config.h.
+     Furthermore you may name an additional file to include after the main
+     file with the macro MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE.
+   * Add the function mbedtls_x509_crt_has_ext_type() to access the ext types
+     field within mbedtls_x509_crt context, as requested in #5585.
+   * Add HKDF-Expand and HKDF-Extract as separate algorithms in the PSA API.
+   * Add support for the ARMv8 SHA-2 acceleration instructions when building
+     for Aarch64.
+   * Add support for authentication of TLS 1.3 clients by TLS 1.3 servers.
+   * Add support for server HelloRetryRequest message. The TLS 1.3 client is
+     now capable of negotiating another shared secret if the one sent in its
+     first ClientHello was not suitable to the server.
+   * Add support for client-side TLS version negotiation. If both TLS 1.2 and
+     TLS 1.3 protocols are enabled in the build of Mbed TLS, the TLS client now
+     negotiates TLS 1.3 or TLS 1.2 with TLS servers.
+   * Enable building of Mbed TLS with TLS 1.3 protocol support but without TLS
+     1.2 protocol support.
+   * Mbed TLS provides an implementation of a TLS 1.3 server (ephemeral key
+     establishment only). See docs/architecture/tls13-support.md for a
+     description of the support. The MBEDTLS_SSL_PROTO_TLS1_3 and
+     MBEDTLS_SSL_SRV_C configuration options control this.
+   * Add accessors to configure DN hints for certificate request:
+     mbedtls_ssl_conf_dn_hints() and mbedtls_ssl_set_hs_dn_hints()
+   * The configuration option MBEDTLS_USE_PSA_CRYPTO, which previously
+     affected only a limited subset of crypto operations in TLS, X.509 and PK,
+     now causes most of them to be done using PSA Crypto; see
+     docs/use-psa-crypto.md for the list of exceptions.
+   * The function mbedtls_pk_setup_opaque() now supports RSA key pairs as well.
+     Opaque keys can now be used everywhere a private key is expected in the
+     TLS and X.509 modules.
+   * Opaque pre-shared keys for TLS, provisioned with
+     mbedtls_ssl_conf_psk_opaque() or mbedtls_ssl_set_hs_psk_opaque(), which
+     previously only worked for "pure" PSK key exchange, now can also be used
+     for the "mixed" PSK key exchanges as well: ECDHE-PSK, DHE-PSK, RSA-PSK.
+   * cmake now detects if it is being built as a sub-project, and in that case
+     disables the target export/installation and package configuration.
+   * Make USE_PSA_CRYPTO compatible with KEY_ID_ENCODES_OWNER. Fixes #5259.
+   * Add example programs cipher_aead_demo.c, md_hmac_demo.c, aead_demo.c
+     and hmac_demo.c, which use PSA and the md/cipher interfaces side
+     by side in order to illustrate how the operation is performed in PSA.
+     Addresses #5208.
+
+Security
+   * Zeroize dynamically-allocated buffers used by the PSA Crypto key storage
+     module before freeing them. These buffers contain secret key material, and
+     could thus potentially leak the key through freed heap.
+   * Fix potential memory leak inside mbedtls_ssl_cache_set() with
+     an invalid session id length.
+   * Add the platform function mbedtls_setbuf() to allow buffering to be
+     disabled on stdio files, to stop secrets loaded from said files being
+     potentially left in memory after file operations. Reported by
+     Glenn Strauss.
+   * Fix a potential heap buffer overread in TLS 1.2 server-side when
+     MBEDTLS_USE_PSA_CRYPTO is enabled, an opaque key (created with
+     mbedtls_pk_setup_opaque()) is provisioned, and a static ECDH ciphersuite
+     is selected. This may result in an application crash or potentially an
+     information leak.
+   * Fix a buffer overread in DTLS ClientHello parsing in servers with
+     MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE enabled. An unauthenticated client
+     or a man-in-the-middle could cause a DTLS server to read up to 255 bytes
+     after the end of the SSL input buffer. The buffer overread only happens
+     when MBEDTLS_SSL_IN_CONTENT_LEN is less than a threshold that depends on
+     the exact configuration: 258 bytes if using mbedtls_ssl_cookie_check(),
+     and possibly up to 571 bytes with a custom cookie check function.
+     Reported by the Cybeats PSI Team.
+    * Fix a buffer overread in TLS 1.3 Certificate parsing. An unauthenticated
+      client or server could cause an MbedTLS server or client to overread up
+      to 64 kBytes of data and potentially overread the input buffer by that
+      amount minus the size of the input buffer. As overread data undergoes
+      various checks, the likelihood of reaching the boundary of the input
+      buffer is rather small but increases as its size
+      MBEDTLS_SSL_IN_CONTENT_LEN decreases.
+   * Fix check of certificate key usage in TLS 1.3. The usage of the public key
+     provided by a client or server certificate for authentication was not
+     checked properly when validating the certificate. This could cause a
+     client or server to be able to authenticate itself through a certificate
+     to an Mbed TLS TLS 1.3 server or client while it does not own a proper
+     certificate to do so.
+
+Bugfix
+   * Declare or use PSA_WANT_ALG_CCM_STAR_NO_TAG following the general
+     pattern for PSA_WANT_xxx symbols. Previously you had to specify
+     PSA_WANT_ALG_CCM for PSA_ALG_CCM_STAR_NO_TAG.
+   * Fix a memory leak if mbedtls_ssl_config_defaults() is called twice.
+   * Fixed swap of client and server random bytes when exporting them alongside
+     TLS 1.3 handshake and application traffic secret.
+   * Fix several bugs (warnings, compiler and linker errors, test failures)
+     in reduced configurations when MBEDTLS_USE_PSA_CRYPTO is enabled.
+   * Fix a bug in (D)TLS curve negotiation: when MBEDTLS_USE_PSA_CRYPTO was
+     enabled and an ECDHE-ECDSA or ECDHE-RSA key exchange was used, the
+     client would fail to check that the curve selected by the server for
+     ECDHE was indeed one that was offered. As a result, the client would
+     accept any curve that it supported, even if that curve was not allowed
+     according to its configuration. Fixes #5291.
+   * The TLS 1.3 implementation is now compatible with the
+     MBEDTLS_USE_PSA_CRYPTO configuration option.
+   * Fix unit tests that used 0 as the file UID. This failed on some
+     implementations of PSA ITS. Fixes #3838.
+   * Fix mbedtls_ssl_get_version() not reporting TLSv1.3. Fixes #5406.
+   * Fix API violation in mbedtls_md_process() test by adding a call to
+     mbedtls_md_starts(). Fixes #2227.
+   * Fix compile errors when MBEDTLS_HAVE_TIME is not defined. Add tests
+     to catch bad uses of time.h.
+   * Fix a race condition in out-of-source builds with CMake when generated data
+     files are already present. Fixes #5374.
+   * Fix the library search path when building a shared library with CMake
+     on Windows.
+   * Fix bug in the alert sending function mbedtls_ssl_send_alert_message()
+     potentially leading to corrupted alert messages being sent in case
+     the function needs to be re-called after initially returning
+     MBEDTLS_SSL_WANT_WRITE. Fixes #1916.
+   * In configurations with MBEDTLS_SSL_DTLS_CONNECTION_ID enabled but not
+     MBEDTLS_DEBUG_C, DTLS handshakes using CID would crash due to a null
+     pointer dereference. Fix this. Fixes #3998.
+     The fix was released, but not announced, in Mbed TLS 3.1.0.
+   * Fix incorrect documentation of mbedtls_x509_crt_profile. The previous
+     documentation stated that the `allowed_pks` field applies to signatures
+     only, but in fact it does apply to the public key type of the end entity
+     certificate, too. Fixes #1992.
+   * Fix undefined behavior in mbedtls_asn1_find_named_data(), where val is
+     not NULL and val_len is zero.
+   * Fix compilation error with mingw32. Fixed by Cameron Cawley in #4211.
+   * Fix compilation error when using C++ Builder on Windows. Reported by
+     Miroslav Mastny in #4015.
+   * psa_raw_key_agreement() now returns PSA_ERROR_BUFFER_TOO_SMALL when
+     applicable. Fixes #5735.
+   * Fix a bug in the x25519 example program where the removal of
+     MBEDTLS_ECDH_LEGACY_CONTEXT caused the program not to run. Fixes #4901 and
+     #3191.
+   * Fix a TLS 1.3 handshake failure when the peer Finished message has not
+     been received yet when we first try to fetch it.
+   * Encode X.509 dates before 1/1/2000 as UTCTime rather than
+     GeneralizedTime. Fixes #5465.
+   * Add mbedtls_x509_dn_get_next function to return the next relative DN in
+     an X509 name, to allow walking the name list. Fixes #5431.
+    * Fix order value of curve x448.
+   * Fix string representation of DNs when outputting values containing commas
+     and other special characters, conforming to RFC 1779. Fixes #769.
+   * Silence a warning from GCC 12 in the selftest program. Fixes #5974.
+   * Fix check_config.h to check that we have MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
+     when MBEDTLS_SSL_PROTO_TLS1_3 is specified, and make this and other
+     dependencies explicit in the documentation. Fixes #5610.
+   * Fix mbedtls_asn1_write_mpi() writing an incorrect encoding of 0.
+   * Fix a TLS 1.3 handshake failure when the first attempt to send the client
+     Finished message on the network cannot be satisfied. Fixes #5499.
+   * Fix resource leaks in mbedtls_pk_parse_public_key() in low
+     memory conditions.
+   * Fix server connection identifier setting for outgoing encrypted records
+     on DTLS 1.2 session resumption. After DTLS 1.2 session resumption with
+     connection identifier, the Mbed TLS client now properly sends the server
+     connection identifier in encrypted record headers. Fix #5872.
+   * Fix a null pointer dereference when performing some operations on zero
+     represented with 0 limbs (specifically mbedtls_mpi_mod_int() dividing
+     by 2, and mbedtls_mpi_write_string() in base 2).
+   * Fix record sizes larger than 16384 being sometimes accepted despite being
+     non-compliant. This could not lead to a buffer overflow. In particular,
+     application data size was already checked correctly.
+   * Fix MBEDTLS_SVC_KEY_ID_GET_KEY_ID() and MBEDTLS_SVC_KEY_ID_GET_OWNER_ID()
+     which have been broken, resulting in compilation errors, since Mbed TLS
+     3.0.
+   * Ensure that TLS 1.2 ciphersuite/certificate and key selection takes into
+     account not just the type of the key (RSA vs EC) but also what it can
+     actually do. Resolves #5831.
+   * Fix CMake windows host detection, especially when cross compiling.
+   * Fix an error in make where the absence of a generated file caused
+     make to break on a clean checkout. Fixes #5340.
+   * Work around an MSVC ARM64 compiler bug causing incorrect behaviour
+     in mbedtls_mpi_exp_mod(). Reported by Tautvydas Žilys in #5467.
+   * Removed the prompt to exit from all windows build programs that was causing
+     issues in CI/CD environments.
+
+Changes
+   * The file library/psa_crypto_driver_wrappers.c is now generated
+     from a template. In the future, the generation will support
+     driver descriptions. For the time being, to customize this file,
+     see docs/proposed/psa-driver-wrappers-codegen-migration-guide.md
+   * Return PSA_ERROR_INVALID_ARGUMENT if the algorithm passed to one-shot
+     AEAD functions is not an AEAD algorithm. This aligns them with the
+     multipart functions, and the PSA Crypto API 1.1 specification.
+   * In mbedtls_pk_parse_key(), if no password is provided, don't allocate a
+     temporary variable on the heap. Suggested by Sergey Kanatov in #5304.
+   * Assume source files are in UTF-8 when using MSVC with CMake.
+   * Fix runtime library install location when building with CMake and MinGW.
+     DLLs are now installed in the bin directory instead of lib.
+   * cmake: Use GnuInstallDirs to customize install directories
+     Replace custom LIB_INSTALL_DIR variable with standard CMAKE_INSTALL_LIBDIR
+     variable. For backward compatibility, set CMAKE_INSTALL_LIBDIR if
+     LIB_INSTALL_DIR is set.
+   * Add a CMake option that enables static linking of the runtime library
+     in Microsoft Visual C++ compiler. Contributed by Microplankton.
+   * In CMake builds, add aliases for libraries so that the normal MbedTLS::*
+     targets work when MbedTLS is built as a subdirectory. This allows the
+     use of FetchContent, as requested in #5688.
 
 = mbed TLS 3.1.0 branch released 2021-12-17
 
diff --git a/ChangeLog.d/Driver_wrapper_codegen_1.0.txt b/ChangeLog.d/Driver_wrapper_codegen_1.0.txt
deleted file mode 100644
index a4d9c54..0000000
--- a/ChangeLog.d/Driver_wrapper_codegen_1.0.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Changes
-   * The file library/psa_crypto_driver_wrappers.c is now generated
-     from a template. In the future, the generation will support
-     driver descriptions. For the time being, to customize this file,
-     see docs/proposed/psa-driver-wrappers-codegen-migration-guide.md
diff --git a/ChangeLog.d/MD-X.509-hashing.txt b/ChangeLog.d/MD-X.509-hashing.txt
deleted file mode 100644
index 2ca989c..0000000
--- a/ChangeLog.d/MD-X.509-hashing.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Features
-   * The X.509 module now uses PSA hash acceleration if present.
diff --git a/ChangeLog.d/PSA-test-suites-NOT-using-UID-0.txt b/ChangeLog.d/PSA-test-suites-NOT-using-UID-0.txt
deleted file mode 100644
index 9acbb0a..0000000
--- a/ChangeLog.d/PSA-test-suites-NOT-using-UID-0.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix unit tests that used 0 as the file UID. This failed on some
-     implementations of PSA ITS. Fixes #3838.
diff --git a/ChangeLog.d/add-mbedtls_md_starts-to-mbedtls_md_process-test.txt b/ChangeLog.d/add-mbedtls_md_starts-to-mbedtls_md_process-test.txt
deleted file mode 100644
index 57c7561..0000000
--- a/ChangeLog.d/add-mbedtls_md_starts-to-mbedtls_md_process-test.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix API violation in mbedtls_md_process() test by adding a call to
-     mbedtls_md_starts(). Fixes #2227.
diff --git a/ChangeLog.d/add_dn_get_next.txt b/ChangeLog.d/add_dn_get_next.txt
deleted file mode 100644
index 04ee954..0000000
--- a/ChangeLog.d/add_dn_get_next.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Add mbedtls_x509_dn_get_next function to return the next relative DN in
-     an X509 name, to allow walking the name list. Fixes #5431.
diff --git a/ChangeLog.d/add_final_delay_accessor b/ChangeLog.d/add_final_delay_accessor
deleted file mode 100644
index 4b8117f..0000000
--- a/ChangeLog.d/add_final_delay_accessor
+++ /dev/null
@@ -1,4 +0,0 @@
-Features
-   * Add function mbedtls_timing_get_final_delay() to access the private
-     final delay field in an mbedtls_timing_delay_context, as requested in
-     #5183.
diff --git a/ChangeLog.d/add_handshake_completion_accessor b/ChangeLog.d/add_handshake_completion_accessor
deleted file mode 100644
index c06a539..0000000
--- a/ChangeLog.d/add_handshake_completion_accessor
+++ /dev/null
@@ -1,4 +0,0 @@
-Features
-   * Add function mbedtls_ssl_is_handshake_over() to enable querying if the SSL
-     Handshake has completed or not, and thus whether to continue calling
-     mbedtls_ssl_handshake_step(), requested in #4383.
diff --git a/ChangeLog.d/add_own_cid_accessors b/ChangeLog.d/add_own_cid_accessors
deleted file mode 100644
index 553299c..0000000
--- a/ChangeLog.d/add_own_cid_accessors
+++ /dev/null
@@ -1,4 +0,0 @@
-Features
-   * Add the function mbedtls_ssl_get_own_cid() to access our own connection id
-     within mbedtls_ssl_context, as requested in #5184.
-
diff --git a/ChangeLog.d/alert_reentrant.txt b/ChangeLog.d/alert_reentrant.txt
deleted file mode 100644
index 691d64c..0000000
--- a/ChangeLog.d/alert_reentrant.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
-   * Fix bug in the alert sending function mbedtls_ssl_send_alert_message()
-     potentially leading to corrupted alert messages being sent in case
-     the function needs to be re-called after initially returning
-     MBEDTLS_SSL_WANT_WRITE. Fixes #1916.
diff --git a/ChangeLog.d/asn1write-0-fix b/ChangeLog.d/asn1write-0-fix
deleted file mode 100644
index 2e01244..0000000
--- a/ChangeLog.d/asn1write-0-fix
+++ /dev/null
@@ -1,2 +0,0 @@
-Bugfix
-   * Fix mbedtls_asn1_write_mpi() writing an incorrect encoding of 0.
diff --git a/ChangeLog.d/bug_order_x448.txt b/ChangeLog.d/bug_order_x448.txt
deleted file mode 100644
index cebefc4..0000000
--- a/ChangeLog.d/bug_order_x448.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Bugfix
-    * Fix order value of curve x448.
diff --git a/ChangeLog.d/ccm_star_no_tag.txt b/ChangeLog.d/ccm_star_no_tag.txt
deleted file mode 100644
index 21e829c..0000000
--- a/ChangeLog.d/ccm_star_no_tag.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
-   * Declare or use PSA_WANT_ALG_CCM_STAR_NO_TAG following the general
-     pattern for PSA_WANT_xxx symbols. Previously you had to specify
-     PSA_WANT_ALG_CCM for PSA_ALG_CCM_STAR_NO_TAG.
diff --git a/ChangeLog.d/chacha20_invalid_iv_len_fix.txt b/ChangeLog.d/chacha20_invalid_iv_len_fix.txt
deleted file mode 100644
index af35e2a..0000000
--- a/ChangeLog.d/chacha20_invalid_iv_len_fix.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Default behavior changes
-   * mbedtls_cipher_set_iv will now fail with ChaCha20 and ChaCha20+Poly1305
-     for IV lengths other than 12. The library was silently overwriting this
-     length with 12, but did not inform the caller about it. Fixes #4301.
diff --git a/ChangeLog.d/cmake_add_subdirectory_support.txt b/ChangeLog.d/cmake_add_subdirectory_support.txt
deleted file mode 100644
index f14f3f8..0000000
--- a/ChangeLog.d/cmake_add_subdirectory_support.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Changes
-   * In CMake builds, add aliases for libraries so that the normal MbedTLS::*
-     targets work when MbedTLS is built as a subdirectory. This allows the
-     use of FetchContent, as requested in #5688.
diff --git a/ChangeLog.d/cmake_fix_dll_install.txt b/ChangeLog.d/cmake_fix_dll_install.txt
deleted file mode 100644
index 7f407c4..0000000
--- a/ChangeLog.d/cmake_fix_dll_install.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Changes
-   * Fix runtime library install location when building with CMake and MinGW.
-     DLLs are now installed in the bin directory instead of lib.
diff --git a/ChangeLog.d/cmake_msvc_utf8.txt b/ChangeLog.d/cmake_msvc_utf8.txt
deleted file mode 100644
index 552eec7..0000000
--- a/ChangeLog.d/cmake_msvc_utf8.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Changes
-   * Assume source files are in UTF-8 when using MSVC with CMake.
diff --git a/ChangeLog.d/cmake_use_GnuInstallDirs.txt b/ChangeLog.d/cmake_use_GnuInstallDirs.txt
deleted file mode 100644
index d848755..0000000
--- a/ChangeLog.d/cmake_use_GnuInstallDirs.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Changes
-   * cmake: Use GnuInstallDirs to customize install directories
-     Replace custom LIB_INSTALL_DIR variable with standard CMAKE_INSTALL_LIBDIR
-     variable. For backward compatibility, set CMAKE_INSTALL_LIBDIR if
-     LIB_INSTALL_DIR is set.
diff --git a/ChangeLog.d/deprecate_mbedtls_cipher_setup_psa.txt b/ChangeLog.d/deprecate_mbedtls_cipher_setup_psa.txt
deleted file mode 100644
index b145243..0000000
--- a/ChangeLog.d/deprecate_mbedtls_cipher_setup_psa.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-New deprecations
-   * Deprecate mbedtls_cipher_setup_psa(). Use psa_aead_xxx() or
-     psa_cipher_xxx() directly instead.
diff --git a/ChangeLog.d/doc-x509-profile-pk.txt b/ChangeLog.d/doc-x509-profile-pk.txt
deleted file mode 100644
index 35625fe..0000000
--- a/ChangeLog.d/doc-x509-profile-pk.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
-   * Fix incorrect documentation of mbedtls_x509_crt_profile. The previous
-     documentation stated that the `allowed_pks` field applies to signatures
-     only, but in fact it does apply to the public key type of the end entity
-     certificate, too. Fixes #1992.
diff --git a/ChangeLog.d/dtls-cid-null.txt b/ChangeLog.d/dtls-cid-null.txt
deleted file mode 100644
index b020616..0000000
--- a/ChangeLog.d/dtls-cid-null.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
-   * In configurations with MBEDTLS_SSL_DTLS_CONNECTION_ID enabled but not
-     MBEDTLS_DEBUG_C, DTLS handshakes using CID would crash due to a null
-     pointer dereference. Fix this. Fixes #3998.
-     The fix was released, but not announced, in Mbed TLS 3.1.0.
diff --git a/ChangeLog.d/fix-csr_subject_commas.txt b/ChangeLog.d/fix-csr_subject_commas.txt
deleted file mode 100644
index e01c9a8..0000000
--- a/ChangeLog.d/fix-csr_subject_commas.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix string representation of DNs when outputting values containing commas
-     and other special characters, conforming to RFC 1779. Fixes #769.
diff --git a/ChangeLog.d/fix-parllel-cmake-build-fail.txt b/ChangeLog.d/fix-parllel-cmake-build-fail.txt
deleted file mode 100644
index 112fa85..0000000
--- a/ChangeLog.d/fix-parllel-cmake-build-fail.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix a race condition in out-of-source builds with CMake when generated data
-     files are already present. Fixes #5374.
diff --git a/ChangeLog.d/fix-time-format-pre-2000.txt b/ChangeLog.d/fix-time-format-pre-2000.txt
deleted file mode 100644
index 414201e..0000000
--- a/ChangeLog.d/fix-time-format-pre-2000.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Encode X.509 dates before 1/1/2000 as UTCTime rather than
-     GeneralizedTime. Fixes #5465.
diff --git a/ChangeLog.d/fix-undefined-memcpy-mbedtls_asn1_named_data.txt b/ChangeLog.d/fix-undefined-memcpy-mbedtls_asn1_named_data.txt
deleted file mode 100644
index b30f7fa..0000000
--- a/ChangeLog.d/fix-undefined-memcpy-mbedtls_asn1_named_data.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix undefined behavior in mbedtls_asn1_find_named_data(), where val is
-     not NULL and val_len is zero.
diff --git a/ChangeLog.d/fix-windows-cmake-build-with-shared-libraries.txt b/ChangeLog.d/fix-windows-cmake-build-with-shared-libraries.txt
deleted file mode 100644
index a6540a1..0000000
--- a/ChangeLog.d/fix-windows-cmake-build-with-shared-libraries.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix the library search path when building a shared library with CMake
-     on Windows.
diff --git a/ChangeLog.d/fix-x25519-program.txt b/ChangeLog.d/fix-x25519-program.txt
deleted file mode 100644
index bf5d6ac..0000000
--- a/ChangeLog.d/fix-x25519-program.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
-   * Fix a bug in the x25519 example program where the removal of
-     MBEDTLS_ECDH_LEGACY_CONTEXT caused the program not to run. Fixes #4901 and
-     #3191.
diff --git a/ChangeLog.d/fix_some_resource_leaks.txt b/ChangeLog.d/fix_some_resource_leaks.txt
deleted file mode 100644
index 9761537..0000000
--- a/ChangeLog.d/fix_some_resource_leaks.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Bugfix
-   * Fix resource leaks in mbedtls_pk_parse_public_key() in low
-     memory conditions.
-Security
-   * Fix potential memory leak inside mbedtls_ssl_cache_set() with
-     an invalid session id length.
diff --git a/ChangeLog.d/hkdf_extract_expand.txt b/ChangeLog.d/hkdf_extract_expand.txt
deleted file mode 100644
index c394bbd..0000000
--- a/ChangeLog.d/hkdf_extract_expand.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Features
-   * Add HKDF-Expand and HKDF-Extract as separate algorithms in the PSA API.
diff --git a/ChangeLog.d/mbedtls_ecp_export.txt b/ChangeLog.d/mbedtls_ecp_export.txt
deleted file mode 100644
index 5dce5b4..0000000
--- a/ChangeLog.d/mbedtls_ecp_export.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add function mbedtls_ecp_export() to export ECP key pair parameters.
-     Fixes #4838.
diff --git a/ChangeLog.d/mbedtls_pem_get_der.txt b/ChangeLog.d/mbedtls_pem_get_der.txt
deleted file mode 100644
index b03b058..0000000
--- a/ChangeLog.d/mbedtls_pem_get_der.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Features
-   * Add accessor to get the raw buffer pointer from a PEM context.
diff --git a/ChangeLog.d/mbedtls_pk_sign_ext.txt b/ChangeLog.d/mbedtls_pk_sign_ext.txt
deleted file mode 100644
index 8dfa2e5..0000000
--- a/ChangeLog.d/mbedtls_pk_sign_ext.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-    * Add mbedtls_pk_sign_ext() which allows generating RSA-PSS signatures when
-      PSA Crypto is enabled.
diff --git a/ChangeLog.d/mbedtls_sha2_a64_crypto_acceleration.txt b/ChangeLog.d/mbedtls_sha2_a64_crypto_acceleration.txt
deleted file mode 100644
index a6e7f6d..0000000
--- a/ChangeLog.d/mbedtls_sha2_a64_crypto_acceleration.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add support for the ARMv8 SHA-2 acceleration instructions when building
-     for Aarch64.
diff --git a/ChangeLog.d/mbedtls_ssl_cert_cb.txt b/ChangeLog.d/mbedtls_ssl_cert_cb.txt
deleted file mode 100644
index fcdc23c..0000000
--- a/ChangeLog.d/mbedtls_ssl_cert_cb.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Features
-   * Add server certificate selection callback near end of Client Hello.
-     Register callback with mbedtls_ssl_conf_cert_cb().
-   * Provide mechanism to reset handshake cert list by calling
-     mbedtls_ssl_set_hs_own_cert() with NULL value for own_cert param.
-   * Add accessor mbedtls_ssl_get_hs_sni() to retrieve SNI from within
-     cert callback (mbedtls_ssl_conf_cert_cb()) during handshake.
diff --git a/ChangeLog.d/mbedtls_ssl_comfig_defaults-memleak.txt b/ChangeLog.d/mbedtls_ssl_comfig_defaults-memleak.txt
deleted file mode 100644
index 043b273..0000000
--- a/ChangeLog.d/mbedtls_ssl_comfig_defaults-memleak.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Bugfix
-   * Fix a memory leak if mbedtls_ssl_config_defaults() is called twice.
diff --git a/ChangeLog.d/mbedtls_ssl_dn_hint.txt b/ChangeLog.d/mbedtls_ssl_dn_hint.txt
deleted file mode 100644
index f569a36..0000000
--- a/ChangeLog.d/mbedtls_ssl_dn_hint.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add accessors to configure DN hints for certificate request:
-     mbedtls_ssl_conf_dn_hints() and mbedtls_ssl_set_hs_dn_hints()
diff --git a/ChangeLog.d/mbedtls_ssl_get_ciphersuite_id.txt b/ChangeLog.d/mbedtls_ssl_get_ciphersuite_id.txt
deleted file mode 100644
index c4235b7..0000000
--- a/ChangeLog.d/mbedtls_ssl_get_ciphersuite_id.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add accessor to obtain ciphersuite id from ssl context.
-   * Add accessors to get members from ciphersuite info.
diff --git a/ChangeLog.d/mbedtls_ssl_hs_cb_t.txt b/ChangeLog.d/mbedtls_ssl_hs_cb_t.txt
deleted file mode 100644
index 28c3371..0000000
--- a/ChangeLog.d/mbedtls_ssl_hs_cb_t.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Features
-   * Introduce mbedtls_ssl_hs_cb_t typedef for use with
-     mbedtls_ssl_conf_cert_cb() and perhaps future callbacks
-     during TLS handshake.
diff --git a/ChangeLog.d/mbedtls_ssl_ticket_rotate.txt b/ChangeLog.d/mbedtls_ssl_ticket_rotate.txt
deleted file mode 100644
index b843bfd..0000000
--- a/ChangeLog.d/mbedtls_ssl_ticket_rotate.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Features
-   * Add mbedtls_ssl_ticket_rotate() for external ticket rotation.
diff --git a/ChangeLog.d/mbedtls_ssl_tls13_client.txt b/ChangeLog.d/mbedtls_ssl_tls13_client.txt
deleted file mode 100644
index 57a26e1..0000000
--- a/ChangeLog.d/mbedtls_ssl_tls13_client.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Features
-   * Add ALPN support in TLS 1.3 clients.
diff --git a/ChangeLog.d/mbedtls_tlsver_enum.txt b/ChangeLog.d/mbedtls_tlsver_enum.txt
deleted file mode 100644
index c027ab7..0000000
--- a/ChangeLog.d/mbedtls_tlsver_enum.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-New deprecations
-   * Deprecate mbedtls_ssl_conf_max_version() and
-     mbedtls_ssl_conf_min_version() in favor of
-     mbedtls_ssl_conf_max_tls_version() and
-     mbedtls_ssl_conf_min_tls_version().
-
-Features
-   * Add functions mbedtls_ssl_conf_max_tls_version() and
-     mbedtls_ssl_conf_min_tls_version() that use a single value to specify
-     the protocol version.
diff --git a/ChangeLog.d/md_info_from_ctx.txt b/ChangeLog.d/md_info_from_ctx.txt
deleted file mode 100644
index aa61e1a..0000000
--- a/ChangeLog.d/md_info_from_ctx.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add function mbedtls_md_info_from_ctx() to recall the message digest
-     information that was used to set up a message digest context.
diff --git a/ChangeLog.d/mingw.txt b/ChangeLog.d/mingw.txt
deleted file mode 100644
index ac4e741..0000000
--- a/ChangeLog.d/mingw.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
-   * Fix compilation error with mingw32. Fixed by Cameron Cawley in #4211.
-   * Fix compilation error when using C++ Builder on Windows. Reported by
-     Miroslav Mastny in #4015.
diff --git a/ChangeLog.d/pkparse-pkcs8-unencrypted-no-alloc.txt b/ChangeLog.d/pkparse-pkcs8-unencrypted-no-alloc.txt
deleted file mode 100644
index 9d7a32e..0000000
--- a/ChangeLog.d/pkparse-pkcs8-unencrypted-no-alloc.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Changes
-   * In mbedtls_pk_parse_key(), if no password is provided, don't allocate a
-     temporary variable on the heap. Suggested by Sergey Kanatov in #5304.
diff --git a/ChangeLog.d/psa_aead_singleshot_error.txt b/ChangeLog.d/psa_aead_singleshot_error.txt
deleted file mode 100644
index ccf1d4c..0000000
--- a/ChangeLog.d/psa_aead_singleshot_error.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Changes
-   * Return PSA_ERROR_INVALID_ARGUMENT if the algorithm passed to one-shot
-     AEAD functions is not an AEAD algorithm. This aligns them with the
-     multipart functions, and the PSA Crypto API 1.1 specification.
diff --git a/ChangeLog.d/psa_crypto_config_file.txt b/ChangeLog.d/psa_crypto_config_file.txt
deleted file mode 100644
index d42651d..0000000
--- a/ChangeLog.d/psa_crypto_config_file.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Features
-   * When MBEDTLS_PSA_CRYPTO_CONFIG is enabled, you may list the PSA crypto
-     feature requirements in the file named by the new macro
-     MBEDTLS_PSA_CRYPTO_CONFIG_FILE instead of the default psa/crypto_config.h.
-     Furthermore you may name an additional file to include after the main
-     file with the macro MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE.
diff --git a/ChangeLog.d/psa_crypto_key_derivation_for_ECC_keys.txt b/ChangeLog.d/psa_crypto_key_derivation_for_ECC_keys.txt
deleted file mode 100644
index 393fa8d..0000000
--- a/ChangeLog.d/psa_crypto_key_derivation_for_ECC_keys.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add support for psa crypto key derivation for elliptic curve
-     keys. Fixes #3260.
diff --git a/ChangeLog.d/psa_crypto_reduced_configs_bugs.txt b/ChangeLog.d/psa_crypto_reduced_configs_bugs.txt
deleted file mode 100644
index 0d61cb7..0000000
--- a/ChangeLog.d/psa_crypto_reduced_configs_bugs.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix several bugs (warnings, compiler and linker errors, test failures)
-     in reduced configurations when MBEDTLS_USE_PSA_CRYPTO is enabled.
diff --git a/ChangeLog.d/psa_crypto_se.txt b/ChangeLog.d/psa_crypto_se.txt
deleted file mode 100644
index f8136b1..0000000
--- a/ChangeLog.d/psa_crypto_se.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-New deprecations
-   * Secure element drivers enabled by MBEDTLS_PSA_CRYPTO_SE_C are deprecated.
-     This was intended as an experimental feature, but had not been explicitly
-     documented as such. Use opaque drivers with the interface enabled by
-     MBEDTLS_PSA_CRYPTO_DRIVERS instead.
diff --git a/ChangeLog.d/psa_raw_key_agreement-buffer_too_small.txt b/ChangeLog.d/psa_raw_key_agreement-buffer_too_small.txt
deleted file mode 100644
index 415c849..0000000
--- a/ChangeLog.d/psa_raw_key_agreement-buffer_too_small.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * psa_raw_key_agreement() now returns PSA_ERROR_BUFFER_TOO_SMALL when
-     applicable. Fixes #5735.
diff --git a/ChangeLog.d/psk_to_ms_mixed_psk.txt b/ChangeLog.d/psk_to_ms_mixed_psk.txt
deleted file mode 100644
index 998cc11..0000000
--- a/ChangeLog.d/psk_to_ms_mixed_psk.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Features
-    * Extend the existing PSA_ALG_TLS12_PSK_TO_MS() algorithm to support
-      mixed-PSK. Add an optional input PSA_KEY_DERIVATION_INPUT_OTHER_SECRET
-      holding the other secret.
diff --git a/ChangeLog.d/resumption_cid.txt b/ChangeLog.d/resumption_cid.txt
deleted file mode 100644
index 5c237aa..0000000
--- a/ChangeLog.d/resumption_cid.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Bugfix
-   * Fix server connection identifier setting for outgoing encrypted records
-     on DTLS 1.2 session resumption. After DTLS 1.2 session resumption with
-     connection identifier, the Mbed TLS client now properly sends the server
-     connection identifier in encrypted record headers. Fix #5872.
diff --git a/ChangeLog.d/selftest-gcc12.txt b/ChangeLog.d/selftest-gcc12.txt
deleted file mode 100644
index aafa256..0000000
--- a/ChangeLog.d/selftest-gcc12.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Bugfix
-   * Silence a warning from GCC 12 in the selftest program. Fixes #5974.
diff --git a/ChangeLog.d/ssl_context-user_data.txt b/ChangeLog.d/ssl_context-user_data.txt
deleted file mode 100644
index 630d8f0..0000000
--- a/ChangeLog.d/ssl_context-user_data.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Features
-   * The structures mbedtls_ssl_config and mbedtls_ssl_context now store
-     a piece of user data which is reserved for the application. The user
-     data can be either a pointer or an integer.
-   * Add an accessor function to get the configuration associated with
-     an SSL context.
diff --git a/ChangeLog.d/ssl_context-version_number.txt b/ChangeLog.d/ssl_context-version_number.txt
deleted file mode 100644
index b5951d0..0000000
--- a/ChangeLog.d/ssl_context-version_number.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add a function to access the protocol version from an SSL context in a
-     form that's easy to compare. Fixes #5407.
diff --git a/ChangeLog.d/ssl_get_version_1_3.txt b/ChangeLog.d/ssl_get_version_1_3.txt
deleted file mode 100644
index 4436522..0000000
--- a/ChangeLog.d/ssl_get_version_1_3.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Bugfix
-   * Fix mbedtls_ssl_get_version() not reporting TLSv1.3. Fixes #5406.
diff --git a/ChangeLog.d/static_link_common_runtime_msvc.txt b/ChangeLog.d/static_link_common_runtime_msvc.txt
deleted file mode 100644
index 6104943..0000000
--- a/ChangeLog.d/static_link_common_runtime_msvc.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Changes
-   * Add a CMake option that enables static linking of the runtime library
-     in Microsoft Visual C++ compiler. Contributed by Microplankton.
diff --git a/ChangeLog.d/timeless.txt b/ChangeLog.d/timeless.txt
deleted file mode 100644
index 84f07d6..0000000
--- a/ChangeLog.d/timeless.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix compile errors when MBEDTLS_HAVE_TIME is not defined. Add tests
-     to catch bad uses of time.h.
diff --git a/ChangeLog.d/tls13-fix-finished-fetch.txt b/ChangeLog.d/tls13-fix-finished-fetch.txt
deleted file mode 100644
index 9a8acb3..0000000
--- a/ChangeLog.d/tls13-fix-finished-fetch.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fix a TLS 1.3 handshake failure when the peer Finished message has not
-     been received yet when we first try to fetch it.
diff --git a/ChangeLog.d/tls13-misc-changelogs.txt b/ChangeLog.d/tls13-misc-changelogs.txt
deleted file mode 100644
index a575b33..0000000
--- a/ChangeLog.d/tls13-misc-changelogs.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-Bugfix
-   * Fix a TLS 1.3 handshake failure when the first attempt to send the client
-     Finished message on the network cannot be satisfied. Fixes #5499.
-
-Features
-   * Add support for authentication of TLS 1.3 clients by TLS 1.3 servers.
-   * Add support for server HelloRetryRequest message. The TLS 1.3 client is
-     now capable of negotiating another shared secret if the one sent in its
-     first ClientHello was not suitable to the server.
-   * Add support for client-side TLS version negotiation. If both TLS 1.2 and
-     TLS 1.3 protocols are enabled in the build of Mbed TLS, the TLS client now
-     negotiates TLS 1.3 or TLS 1.2 with TLS servers.
-   * Enable building of Mbed TLS with TLS 1.3 protocol support but without TLS
-     1.2 protocol support.
-   * Mbed TLS provides an implementation of a TLS 1.3 server (ephemeral key
-     establishment only). See docs/architecture/tls13-support.md for a
-     description of the support. The MBEDTLS_SSL_PROTO_TLS1_3 and
-     MBEDTLS_SSL_SRV_C configuration options control this.
diff --git a/ChangeLog.d/tls13_and_keep_certificates.txt b/ChangeLog.d/tls13_and_keep_certificates.txt
deleted file mode 100644
index 8c2421f..0000000
--- a/ChangeLog.d/tls13_and_keep_certificates.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Bugfix
-   * Fix check_config.h to check that we have MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
-     when MBEDTLS_SSL_PROTO_TLS1_3 is specified, and make this and other
-     dependencies explicit in the documentation. Fixes #5610.
diff --git a/ChangeLog.d/tls13_and_use_psa_crypto.txt b/ChangeLog.d/tls13_and_use_psa_crypto.txt
deleted file mode 100644
index 6198804..0000000
--- a/ChangeLog.d/tls13_and_use_psa_crypto.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * The TLS 1.3 implementation is now compatible with the
-     MBEDTLS_USE_PSA_CRYPTO configuration option.
diff --git a/ChangeLog.d/tls13_f_export_keys.txt b/ChangeLog.d/tls13_f_export_keys.txt
deleted file mode 100644
index 31debc2..0000000
--- a/ChangeLog.d/tls13_f_export_keys.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Fixed swap of client and server random bytes when exporting them alongside
-     TLS 1.3 handshake and application traffic secret.
diff --git a/ChangeLog.d/use-psa-ecdhe-curve.txt b/ChangeLog.d/use-psa-ecdhe-curve.txt
deleted file mode 100644
index 658f88f..0000000
--- a/ChangeLog.d/use-psa-ecdhe-curve.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Bugfix
-   * Fix a bug in (D)TLS curve negotiation: when MBEDTLS_USE_PSA_CRYPTO was
-     enabled and an ECDHE-ECDSA or ECDHE-RSA key exchange was used, the
-     client would fail to check that the curve selected by the server for
-     ECDHE was indeed one that was offered. As a result, the client would
-     accept any curve that it supported, even if that curve was not allowed
-     according to its configuration. Fixes #5291.
diff --git a/ChangeLog.d/use-psa-improvements.txt b/ChangeLog.d/use-psa-improvements.txt
deleted file mode 100644
index 1bd97a4..0000000
--- a/ChangeLog.d/use-psa-improvements.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-Features
-   * The configuration option MBEDTLS_USE_PSA_CRYPTO, which previously
-     affected only a limited subset of crypto operations in TLS, X.509 and PK,
-     now causes most of them to be done using PSA Crypto; see
-     docs/use-psa-crypto.md for the list of exceptions.
-   * The function mbedtls_pk_setup_opaque() now supports RSA key pairs as well.
-     Opaque keys can now be used everywhere a private key is expected in the
-     TLS and X.509 modules.
-   * Opaque pre-shared keys for TLS, provisioned with
-     mbedtls_ssl_conf_psk_opaque() or mbedtls_ssl_set_hs_psk_opaque(), which
-     previously only worked for "pure" PSK key exchange, now can also be used
-     for the "mixed" PSK key exchanges as well: ECDHE-PSK, DHE-PSK, RSA-PSK.
diff --git a/ChangeLog.d/x509_ext_types_accessor.txt b/ChangeLog.d/x509_ext_types_accessor.txt
deleted file mode 100644
index 13a3152..0000000
--- a/ChangeLog.d/x509_ext_types_accessor.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Features
-   * Add the function mbedtls_x509_crt_has_ext_type() to access the ext types
-     field within mbedtls_x509_crt context, as requested in #5585.
diff --git a/ChangeLog.d/zeroize_key_buffers_before_free.txt b/ChangeLog.d/zeroize_key_buffers_before_free.txt
deleted file mode 100644
index ba5bae1..0000000
--- a/ChangeLog.d/zeroize_key_buffers_before_free.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Security
-   * Zeroize dynamically-allocated buffers used by the PSA Crypto key storage
-     module before freeing them. These buffers contain secret key material, and
-     could thus potentially leak the key through freed heap.
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index 1c2be1a..282e9bf 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -22,7 +22,7 @@
  */
 
 /**
- * @mainpage mbed TLS v3.1.0 source code documentation
+ * @mainpage mbed TLS v3.2.0 source code documentation
  *
  * This documentation describes the internal structure of mbed TLS.  It was
  * automatically generated from specially formatted comment blocks in
diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile
index 6d104c8..653babc 100644
--- a/doxygen/mbedtls.doxyfile
+++ b/doxygen/mbedtls.doxyfile
@@ -1,4 +1,4 @@
-PROJECT_NAME           = "mbed TLS v3.1.0"
+PROJECT_NAME           = "mbed TLS v3.2.0"
 OUTPUT_DIRECTORY       = ../apidoc/
 FULL_PATH_NAMES        = NO
 OPTIMIZE_OUTPUT_FOR_C  = YES
diff --git a/include/mbedtls/build_info.h b/include/mbedtls/build_info.h
index 3dd944c..75545f2 100644
--- a/include/mbedtls/build_info.h
+++ b/include/mbedtls/build_info.h
@@ -37,7 +37,7 @@
  * Major, Minor, Patchlevel
  */
 #define MBEDTLS_VERSION_MAJOR  3
-#define MBEDTLS_VERSION_MINOR  1
+#define MBEDTLS_VERSION_MINOR  2
 #define MBEDTLS_VERSION_PATCH  0
 
 /**
@@ -45,9 +45,9 @@
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x03010000
-#define MBEDTLS_VERSION_STRING         "3.1.0"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 3.1.0"
+#define MBEDTLS_VERSION_NUMBER         0x03020000
+#define MBEDTLS_VERSION_STRING         "3.2.0"
+#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 3.2.0"
 
 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
 #define _CRT_SECURE_NO_DEPRECATE 1
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index c08d3f7..5fe9849 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -385,6 +385,20 @@
 #error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously"
 #endif
 
+#if defined(MBEDTLS_PLATFORM_SETBUF_ALT) && !defined(MBEDTLS_PLATFORM_C)
+#error "MBEDTLS_PLATFORM_SETBUF_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) && !defined(MBEDTLS_PLATFORM_C)
+#error "MBEDTLS_PLATFORM_SETBUF_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_SETBUF_MACRO) &&\
+    ( defined(MBEDTLS_PLATFORM_STD_SETBUF) ||\
+        defined(MBEDTLS_PLATFORM_SETBUF_ALT) )
+#error "MBEDTLS_PLATFORM_SETBUF_MACRO and MBEDTLS_PLATFORM_STD_SETBUF/MBEDTLS_PLATFORM_SETBUF_ALT cannot be defined simultaneously"
+#endif
+
 #if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\
     ( !defined(MBEDTLS_PLATFORM_C) ||\
         !defined(MBEDTLS_HAVE_TIME) )
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index 8629721..1c60ec8 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -225,6 +225,7 @@
  * Uncomment a macro to enable alternate implementation of specific base
  * platform function
  */
+//#define MBEDTLS_PLATFORM_SETBUF_ALT
 //#define MBEDTLS_PLATFORM_EXIT_ALT
 //#define MBEDTLS_PLATFORM_TIME_ALT
 //#define MBEDTLS_PLATFORM_FPRINTF_ALT
@@ -3328,6 +3329,7 @@
 //#define MBEDTLS_PLATFORM_STD_MEM_HDR   <stdlib.h> /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
 //#define MBEDTLS_PLATFORM_STD_CALLOC        calloc /**< Default allocator to use, can be undefined */
 //#define MBEDTLS_PLATFORM_STD_FREE            free /**< Default free to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_SETBUF      setbuf /**< Default setbuf to use, can be undefined */
 //#define MBEDTLS_PLATFORM_STD_EXIT            exit /**< Default exit to use, can be undefined */
 //#define MBEDTLS_PLATFORM_STD_TIME            time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
 //#define MBEDTLS_PLATFORM_STD_FPRINTF      fprintf /**< Default fprintf to use, can be undefined */
@@ -3345,6 +3347,7 @@
 //#define MBEDTLS_PLATFORM_CALLOC_MACRO        calloc /**< Default allocator macro to use, can be undefined */
 //#define MBEDTLS_PLATFORM_FREE_MACRO            free /**< Default free macro to use, can be undefined */
 //#define MBEDTLS_PLATFORM_EXIT_MACRO            exit /**< Default exit macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_SETBUF_MACRO      setbuf /**< Default setbuf macro to use, can be undefined */
 //#define MBEDTLS_PLATFORM_TIME_MACRO            time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
 //#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO       time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
 //#define MBEDTLS_PLATFORM_FPRINTF_MACRO      fprintf /**< Default fprintf macro to use, can be undefined */
diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h
index 207aed0..867961d 100644
--- a/include/mbedtls/pk.h
+++ b/include/mbedtls/pk.h
@@ -216,32 +216,6 @@
 typedef void mbedtls_pk_restart_ctx;
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
-#if defined(MBEDTLS_RSA_C)
-/**
- * Quick access to an RSA context inside a PK context.
- *
- * \warning You must make sure the PK context actually holds an RSA context
- * before using this function!
- */
-static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk )
-{
-    return( (mbedtls_rsa_context *) (pk).MBEDTLS_PRIVATE(pk_ctx) );
-}
-#endif /* MBEDTLS_RSA_C */
-
-#if defined(MBEDTLS_ECP_C)
-/**
- * Quick access to an EC context inside a PK context.
- *
- * \warning You must make sure the PK context actually holds an EC context
- * before using this function!
- */
-static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk )
-{
-    return( (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx) );
-}
-#endif /* MBEDTLS_ECP_C */
-
 #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
 /**
  * \brief           Types for RSA-alt abstraction
@@ -735,6 +709,55 @@
  */
 mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx );
 
+#if defined(MBEDTLS_RSA_C)
+/**
+ * Quick access to an RSA context inside a PK context.
+ *
+ * \warning This function can only be used when the type of the context, as
+ * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_RSA.
+ * Ensuring that is the caller's responsibility.
+ * Alternatively, you can check whether this function returns NULL.
+ *
+ * \return The internal RSA context held by the PK context, or NULL.
+ */
+static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk )
+{
+    switch( mbedtls_pk_get_type( &pk ) )
+    {
+        case MBEDTLS_PK_RSA:
+            return( (mbedtls_rsa_context *) (pk).MBEDTLS_PRIVATE(pk_ctx) );
+        default:
+            return( NULL );
+    }
+}
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_ECP_C)
+/**
+ * Quick access to an EC context inside a PK context.
+ *
+ * \warning This function can only be used when the type of the context, as
+ * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_ECKEY,
+ * #MBEDTLS_PK_ECKEY_DH, or #MBEDTLS_PK_ECDSA.
+ * Ensuring that is the caller's responsibility.
+ * Alternatively, you can check whether this function returns NULL.
+ *
+ * \return The internal EC context held by the PK context, or NULL.
+ */
+static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk )
+{
+    switch( mbedtls_pk_get_type( &pk ) )
+    {
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+            return( (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx) );
+        default:
+            return( NULL );
+    }
+}
+#endif /* MBEDTLS_ECP_C */
+
 #if defined(MBEDTLS_PK_PARSE_C)
 /** \ingroup pk_module */
 /**
diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h
index a598434..a5a43ac 100644
--- a/include/mbedtls/platform.h
+++ b/include/mbedtls/platform.h
@@ -91,6 +91,9 @@
 #if !defined(MBEDTLS_PLATFORM_STD_FREE)
 #define MBEDTLS_PLATFORM_STD_FREE       free /**< The default \c free function to use. */
 #endif
+#if !defined(MBEDTLS_PLATFORM_STD_SETBUF)
+#define MBEDTLS_PLATFORM_STD_SETBUF   setbuf /**< The default \c setbuf function to use. */
+#endif
 #if !defined(MBEDTLS_PLATFORM_STD_EXIT)
 #define MBEDTLS_PLATFORM_STD_EXIT      exit /**< The default \c exit function to use. */
 #endif
@@ -277,6 +280,56 @@
 #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
 
 /*
+ * The function pointers for setbuf
+ */
+#if defined(MBEDTLS_PLATFORM_SETBUF_ALT)
+#include <stdio.h>
+/**
+ * \brief                  Function pointer to call for `setbuf()` functionality
+ *                         (changing the internal buffering on stdio calls).
+ *
+ * \note                   The library calls this function to disable
+ *                         buffering when reading or writing sensitive data,
+ *                         to avoid having extra copies of sensitive data
+ *                         remaining in stdio buffers after the file is
+ *                         closed. If this is not a concern, for example if
+ *                         your platform's stdio doesn't have any buffering,
+ *                         you can set mbedtls_setbuf to a function that
+ *                         does nothing.
+ *
+ *                         The library always calls this function with
+ *                         `buf` equal to `NULL`.
+ */
+extern void (*mbedtls_setbuf)( FILE *stream, char *buf );
+
+/**
+ * \brief                  Dynamically configure the function that is called
+ *                         when the mbedtls_setbuf() function is called by the
+ *                         library.
+ *
+ * \param   setbuf_func   The \c setbuf function implementation
+ *
+ * \return                 \c 0
+ */
+int mbedtls_platform_set_setbuf( void (*setbuf_func)(
+                                     FILE *stream, char *buf ) );
+#elif defined(MBEDTLS_PLATFORM_SETBUF_MACRO)
+/**
+ * \brief                  Macro defining the function for the library to
+ *                         call for `setbuf` functionality (changing the
+ *                         internal buffering on stdio calls).
+ *
+ * \note                   See extra comments on the mbedtls_setbuf() function
+ *                         pointer above.
+ *
+ * \return                 \c 0 on success, negative on error.
+ */
+#define mbedtls_setbuf    MBEDTLS_PLATFORM_SETBUF_MACRO
+#else
+#define mbedtls_setbuf    setbuf
+#endif /* MBEDTLS_PLATFORM_SETBUF_ALT / MBEDTLS_PLATFORM_SETBUF_MACRO */
+
+/*
  * The function pointers for exit
  */
 #if defined(MBEDTLS_PLATFORM_EXIT_ALT)
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index d08de59..d652157 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -274,7 +274,7 @@
 if(USE_SHARED_MBEDTLS_LIBRARY)
     set(CMAKE_LIBRARY_PATH ${CMAKE_CURRENT_BINARY_DIR})
     add_library(${mbedcrypto_target} SHARED ${src_crypto})
-    set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 3.1.0 SOVERSION 11)
+    set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 3.2.0 SOVERSION 12)
     target_link_libraries(${mbedcrypto_target} PUBLIC ${libs})
 
     if(TARGET everest)
@@ -282,11 +282,11 @@
     endif()
 
     add_library(${mbedx509_target} SHARED ${src_x509})
-    set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.1.0 SOVERSION 4)
+    set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.2.0 SOVERSION 4)
     target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target})
 
     add_library(${mbedtls_target} SHARED ${src_tls})
-    set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.1.0 SOVERSION 17)
+    set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.2.0 SOVERSION 18)
     target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target})
 endif(USE_SHARED_MBEDTLS_LIBRARY)
 
diff --git a/library/Makefile b/library/Makefile
index d267e05..f5ff474 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -47,9 +47,9 @@
 endif
 endif
 
-SOEXT_TLS=so.17
+SOEXT_TLS=so.18
 SOEXT_X509=so.4
-SOEXT_CRYPTO=so.11
+SOEXT_CRYPTO=so.12
 
 # Set AR_DASH= (empty string) to use an ar implementation that does not accept
 # the - prefix for command line options (e.g. llvm-ar)
diff --git a/library/bignum.c b/library/bignum.c
index 11acc01..8717c8a 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -1785,7 +1785,7 @@
     /*
      * handle trivial cases
      */
-    if( b == 1 )
+    if( b == 1 || A->n == 0 )
     {
         *r = 0;
         return( 0 );
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index 23ea07b..43f490e 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -607,6 +607,9 @@
     if( ( f = fopen( path, "wb" ) ) == NULL )
         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( f, NULL );
+
     if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
                                          MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
         goto exit;
@@ -640,6 +643,9 @@
     if( ( f = fopen( path, "rb" ) ) == NULL )
         return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( f, NULL );
+
     n = fread( buf, 1, sizeof( buf ), f );
     if( fread( &c, 1, 1, f ) != 0 )
     {
diff --git a/library/dhm.c b/library/dhm.c
index 2ce0ed4..1e95bda 100644
--- a/library/dhm.c
+++ b/library/dhm.c
@@ -620,6 +620,7 @@
 
     if( ( f = fopen( path, "rb" ) ) == NULL )
         return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
+    /* The data loaded here is public, so don't bother disabling buffering. */
 
     fseek( f, 0, SEEK_END );
     if( ( size = ftell( f ) ) == -1 )
diff --git a/library/entropy.c b/library/entropy.c
index 9e31f84..08c5bd7 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -457,6 +457,9 @@
         goto exit;
     }
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( f, NULL );
+
     if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE )
     {
         ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
@@ -484,6 +487,9 @@
     if( ( f = fopen( path, "rb" ) ) == NULL )
         return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( f, NULL );
+
     fseek( f, 0, SEEK_END );
     n = (size_t) ftell( f );
     fseek( f, 0, SEEK_SET );
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index 058c307..2ae57fd 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -35,7 +35,7 @@
 #if defined(MBEDTLS_TIMING_C)
 #include "mbedtls/timing.h"
 #endif
-#if defined(MBEDTLS_ENTROPY_NV_SEED)
+#if defined(MBEDTLS_ENTROPY_NV_SEED) || !defined(HAVE_SYSCTL_ARND)
 #include "mbedtls/platform.h"
 #endif
 
@@ -195,6 +195,9 @@
     if( file == NULL )
         return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( file, NULL );
+
     read_len = fread( output, 1, len, file );
     if( read_len != len )
     {
diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c
index ab353bf..8b13a86 100644
--- a/library/hmac_drbg.c
+++ b/library/hmac_drbg.c
@@ -436,6 +436,9 @@
     if( ( f = fopen( path, "wb" ) ) == NULL )
         return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( f, NULL );
+
     if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
         goto exit;
 
@@ -465,6 +468,9 @@
     if( ( f = fopen( path, "rb" ) ) == NULL )
         return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( f, NULL );
+
     n = fread( buf, 1, sizeof( buf ), f );
     if( fread( &c, 1, 1, f ) != 0 )
     {
diff --git a/library/md.c b/library/md.c
index f2c1a90..a387da5 100644
--- a/library/md.c
+++ b/library/md.c
@@ -605,6 +605,9 @@
     if( ( f = fopen( path, "rb" ) ) == NULL )
         return( MBEDTLS_ERR_MD_FILE_IO_ERROR );
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( f, NULL );
+
     mbedtls_md_init( &ctx );
 
     if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 )
diff --git a/library/pkparse.c b/library/pkparse.c
index 6f40968..73d59a6 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -82,6 +82,9 @@
     if( ( f = fopen( path, "rb" ) ) == NULL )
         return( MBEDTLS_ERR_PK_FILE_IO_ERROR );
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( f, NULL );
+
     fseek( f, 0, SEEK_END );
     if( ( size = ftell( f ) ) == -1 )
     {
diff --git a/library/platform.c b/library/platform.c
index e742fde..6151e6c 100644
--- a/library/platform.c
+++ b/library/platform.c
@@ -226,6 +226,28 @@
 }
 #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */
 
+#if defined(MBEDTLS_PLATFORM_SETBUF_ALT)
+#if !defined(MBEDTLS_PLATFORM_STD_SETBUF)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static void platform_setbuf_uninit( FILE *stream, char *buf )
+{
+   ((void) stream);
+   ((void) buf);
+}
+
+#define MBEDTLS_PLATFORM_STD_SETBUF   platform_setbuf_uninit
+#endif /* !MBEDTLS_PLATFORM_STD_SETBUF */
+void (*mbedtls_setbuf)( FILE *stream, char *buf ) = MBEDTLS_PLATFORM_STD_SETBUF;
+
+int mbedtls_platform_set_setbuf( void (*setbuf_func)( FILE *stream, char *buf ) )
+{
+   mbedtls_setbuf = setbuf_func;
+   return( 0 );
+}
+#endif /* MBEDTLS_PLATFORM_SETBUF_ALT */
+
 #if defined(MBEDTLS_PLATFORM_EXIT_ALT)
 #if !defined(MBEDTLS_PLATFORM_STD_EXIT)
 /*
@@ -288,6 +310,9 @@
     if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL )
         return( -1 );
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( file, NULL );
+
     if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len )
     {
         fclose( file );
@@ -307,6 +332,9 @@
     if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL )
         return -1;
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( file, NULL );
+
     if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len )
     {
         fclose( file );
diff --git a/library/psa_its_file.c b/library/psa_its_file.c
index f058720..b7c2e6b 100644
--- a/library/psa_its_file.c
+++ b/library/psa_its_file.c
@@ -102,6 +102,9 @@
     if( *p_stream == NULL )
         return( PSA_ERROR_DOES_NOT_EXIST );
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( *p_stream, NULL );
+
     n = fread( &header, 1, sizeof( header ), *p_stream );
     if( n != sizeof( header ) )
         return( PSA_ERROR_DATA_CORRUPT );
@@ -201,9 +204,13 @@
 
     psa_its_fill_filename( uid, filename );
     stream = fopen( PSA_ITS_STORAGE_TEMP, "wb" );
+
     if( stream == NULL )
         goto exit;
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( stream, NULL );
+
     status = PSA_ERROR_INSUFFICIENT_STORAGE;
     n = fwrite( &header, 1, sizeof( header ), stream );
     if( n != sizeof( header ) )
diff --git a/library/ssl_cache.c b/library/ssl_cache.c
index d198474..6505e11 100644
--- a/library/ssl_cache.c
+++ b/library/ssl_cache.c
@@ -50,6 +50,7 @@
 #endif
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_cache_find_entry( mbedtls_ssl_cache_context *cache,
                                  unsigned char const *session_id,
                                  size_t session_id_len,
@@ -124,6 +125,7 @@
     return( ret );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_cache_pick_writing_slot( mbedtls_ssl_cache_context *cache,
                                         unsigned char const *session_id,
                                         size_t session_id_len,
diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c
index 62988f2..835159e 100644
--- a/library/ssl_ciphersuites.c
+++ b/library/ssl_ciphersuites.c
@@ -1778,6 +1778,7 @@
 static int supported_ciphersuites[MAX_CIPHERSUITES];
 static int supported_init = 0;
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info )
 {
     (void)cs_info;
diff --git a/library/ssl_client.c b/library/ssl_client.c
index 22ca57c..20f1aff 100644
--- a/library/ssl_client.c
+++ b/library/ssl_client.c
@@ -46,6 +46,7 @@
 #include "ssl_debug_helpers.h"
 
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
                                    unsigned char *buf,
                                    const unsigned char *end,
@@ -129,6 +130,7 @@
  * } ProtocolNameList;
  *
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
                                unsigned char *buf,
                                const unsigned char *end,
@@ -226,6 +228,7 @@
  *
  * DHE groups are not supported yet.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_supported_groups_ext( mbedtls_ssl_context *ssl,
                                            unsigned char *buf,
                                            const unsigned char *end,
@@ -308,6 +311,7 @@
 #endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
           MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_client_hello_cipher_suites(
             mbedtls_ssl_context *ssl,
             unsigned char *buf,
@@ -424,6 +428,7 @@
  *     };
  * } ClientHello;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_client_hello_body( mbedtls_ssl_context *ssl,
                                         unsigned char *buf,
                                         unsigned char *end,
@@ -654,6 +659,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_generate_random( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -691,6 +697,7 @@
     return( ret );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_prepare_client_hello( mbedtls_ssl_context *ssl )
 {
     int ret;
diff --git a/library/ssl_client.h b/library/ssl_client.h
index 8e0c216..be4d067 100644
--- a/library/ssl_client.h
+++ b/library/ssl_client.h
@@ -28,6 +28,7 @@
 
 #include <stddef.h>
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_write_client_hello( mbedtls_ssl_context *ssl );
 
 #endif /* MBEDTLS_SSL_CLIENT_H */
diff --git a/library/ssl_cookie.c b/library/ssl_cookie.c
index 0f2bc60..4b2d2d2 100644
--- a/library/ssl_cookie.c
+++ b/library/ssl_cookie.c
@@ -160,6 +160,7 @@
 /*
  * Generate the HMAC part of a cookie
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx,
                             const unsigned char time[4],
                             unsigned char **p, unsigned char *end,
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index bd8c14d..39a47ca 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -381,11 +381,38 @@
  * \return       Zero if the needed space is available in the buffer, non-zero
  *               otherwise.
  */
+#if ! defined(MBEDTLS_TEST_HOOKS)
 static inline int mbedtls_ssl_chk_buf_ptr( const uint8_t *cur,
                                            const uint8_t *end, size_t need )
 {
     return( ( cur > end ) || ( need > (size_t)( end - cur ) ) );
 }
+#else
+typedef struct
+{
+    const uint8_t *cur;
+    const uint8_t *end;
+    size_t need;
+} mbedtls_ssl_chk_buf_ptr_args;
+
+void mbedtls_ssl_set_chk_buf_ptr_fail_args(
+    const uint8_t *cur, const uint8_t *end, size_t need );
+void mbedtls_ssl_reset_chk_buf_ptr_fail_args( void );
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_cmp_chk_buf_ptr_fail_args( mbedtls_ssl_chk_buf_ptr_args *args );
+
+static inline int mbedtls_ssl_chk_buf_ptr( const uint8_t *cur,
+                                           const uint8_t *end, size_t need )
+{
+    if( ( cur > end ) || ( need > (size_t)( end - cur ) ) )
+    {
+        mbedtls_ssl_set_chk_buf_ptr_fail_args( cur, end, need );
+        return( 1 );
+    }
+    return( 0 );
+}
+#endif /* MBEDTLS_TEST_HOOKS */
 
 /**
  * \brief        This macro checks if the remaining size in a buffer is
@@ -1102,6 +1129,7 @@
  *                      (<> 0) or not ( 0 ).
  * \param[out]  out_len Length of the data written into the buffer \p buf
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls12_write_client_hello_exts( mbedtls_ssl_context *ssl,
                                                unsigned char *buf,
                                                const unsigned char *end,
@@ -1153,7 +1181,9 @@
 void mbedtls_ssl_set_outbound_transform( mbedtls_ssl_context *ssl,
                                          mbedtls_ssl_transform *transform );
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl );
 void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl );
 static inline void mbedtls_ssl_handshake_set_state( mbedtls_ssl_context *ssl,
@@ -1162,15 +1192,19 @@
     ssl->state = ( int ) state;
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl );
 
 void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl );
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl );
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2  */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl );
 void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl );
 
@@ -1250,16 +1284,20 @@
  *              following the above definition.
  *
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
                              unsigned update_hs_digest );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want );
 
 /*
  * Write handshake message header
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_start_handshake_msg( mbedtls_ssl_context *ssl, unsigned hs_type,
                                      unsigned char **buf, size_t *buf_len );
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_write_handshake_msg_ext( mbedtls_ssl_context *ssl,
                                          int update_checksum,
                                          int force_flush );
@@ -1271,19 +1309,28 @@
 /*
  * Write handshake message tail
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_finish_handshake_msg( mbedtls_ssl_context *ssl,
                                       size_t buf_len, size_t msg_len );
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, int force_flush );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl );
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl );
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl );
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl );
 
 void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl,
@@ -1299,10 +1346,12 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl,
                                       mbedtls_key_exchange_type_t key_ex );
 #endif /* !MBEDTLS_USE_PSA_CRYPTO */
 #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_2)
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_conf_has_static_psk( mbedtls_ssl_config const *conf );
 #endif
 
@@ -1370,11 +1419,14 @@
 unsigned char mbedtls_ssl_hash_from_md_alg( int md );
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md );
 #endif
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_check_curve_tls_id( const mbedtls_ssl_context *ssl, uint16_t tls_id );
 #if defined(MBEDTLS_ECP_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id );
 #endif
 
@@ -1429,6 +1481,7 @@
  *
  * Return 0 if everything is OK, -1 if not.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert,
                           const mbedtls_ssl_ciphersuite_t *ciphersuite,
                           int cert_endpoint,
@@ -1477,21 +1530,26 @@
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl );
 void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_resend( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl );
 #endif
 
 /* Visible for testing purposes only */
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl );
 void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl );
 #endif
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
                               const mbedtls_ssl_session *src );
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
 /* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
                                             unsigned char *hash, size_t *hashlen,
                                             unsigned char *data, size_t data_len,
@@ -1503,11 +1561,13 @@
 #endif
 
 void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
                              mbedtls_ssl_transform *transform,
                              mbedtls_record *rec,
                              int (*f_rng)(void *, unsigned char *, size_t),
                              void *p_rng );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
                              mbedtls_ssl_transform *transform,
                              mbedtls_record *rec );
@@ -1525,10 +1585,12 @@
 }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl );
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
 void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl );
 
 void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl );
@@ -1536,6 +1598,7 @@
                               mbedtls_ssl_transform *transform );
 void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl );
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial );
 void mbedtls_ssl_session_reset_msg_layer( mbedtls_ssl_context *ssl,
                                           int partial );
@@ -1543,6 +1606,7 @@
 /*
  * Send pending alert
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_handle_pending_alert( mbedtls_ssl_context *ssl );
 
 /*
@@ -1563,6 +1627,7 @@
 void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl );
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl );
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
@@ -1627,7 +1692,9 @@
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
 extern const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[
                         MBEDTLS_SERVER_HELLO_RANDOM_LEN ];
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_process_finished_message( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_write_finished_message( mbedtls_ssl_context *ssl );
 void mbedtls_ssl_tls13_handshake_wrapup( mbedtls_ssl_context *ssl );
 
@@ -1640,6 +1707,7 @@
  * \param[in]   end     End address of the buffer where to write the extensions
  * \param[out]  out_len Length of the data written into the buffer \p buf
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_write_client_hello_exts( mbedtls_ssl_context *ssl,
                                                unsigned char *buf,
                                                unsigned char *end,
@@ -1650,6 +1718,7 @@
  *
  * \param ssl       SSL context
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_handshake_client_step( mbedtls_ssl_context *ssl );
 
 /**
@@ -1657,6 +1726,7 @@
  *
  * \param ssl       SSL context
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl );
 
 
@@ -1749,6 +1819,7 @@
 /*
  * Fetch TLS 1.3 handshake message header
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_fetch_handshake_msg( mbedtls_ssl_context *ssl,
                                            unsigned hs_type,
                                            unsigned char **buf,
@@ -1757,17 +1828,20 @@
 /*
  * Handler of TLS 1.3 server certificate message
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_process_certificate( mbedtls_ssl_context *ssl );
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
 /*
  * Handler of TLS 1.3 write Certificate message
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_write_certificate( mbedtls_ssl_context *ssl );
 
 /*
  * Handler of TLS 1.3 write Certificate Verify message
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_write_certificate_verify( mbedtls_ssl_context *ssl );
 
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
@@ -1775,16 +1849,20 @@
 /*
  * Generic handler of Certificate Verify
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_process_certificate_verify( mbedtls_ssl_context *ssl );
 
 /*
  * Write of dummy-CCS's for middlebox compatibility
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_write_change_cipher_spec( mbedtls_ssl_context *ssl );
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_reset_transcript_for_hrr( mbedtls_ssl_context *ssl );
 
 #if defined(MBEDTLS_ECDH_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
                 mbedtls_ssl_context *ssl,
                 uint16_t named_group,
@@ -1800,12 +1878,14 @@
 /*
  * Parse TLS Signature Algorithm extension
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_parse_sig_alg_ext( mbedtls_ssl_context *ssl,
                                    const unsigned char *buf,
                                    const unsigned char *end );
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
 /* Get handshake transcript */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl,
                                           const mbedtls_md_type_t md,
                                           unsigned char *dst,
@@ -2172,6 +2252,7 @@
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_check_sig_alg_cert_key_match( uint16_t sig_alg,
                                                     mbedtls_pk_context *key );
 
@@ -2265,6 +2346,7 @@
 
 #if defined(MBEDTLS_ECDH_C)
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_read_public_ecdhe_share( mbedtls_ssl_context *ssl,
                                                const unsigned char *buf,
                                                size_t buf_len );
@@ -2297,31 +2379,44 @@
  *
  * \return 0 if valid, negative value otherwise.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_validate_ciphersuite(
     const mbedtls_ssl_context *ssl,
     const mbedtls_ssl_ciphersuite_t *suite_info,
     mbedtls_ssl_protocol_version min_tls_version,
     mbedtls_ssl_protocol_version max_tls_version );
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_write_sig_alg_ext( mbedtls_ssl_context *ssl, unsigned char *buf,
                                    const unsigned char *end, size_t *out_len );
 
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_parse_server_name_ext( mbedtls_ssl_context *ssl,
                                        const unsigned char *buf,
                                        const unsigned char *end );
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
 #if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
                                 const unsigned char *buf,
                                 const unsigned char *end );
 
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
                                 unsigned char *buf,
                                 unsigned char *end,
                                 size_t *out_len );
 #endif /* MBEDTLS_SSL_ALPN */
 
+#if defined(MBEDTLS_TEST_HOOKS)
+int mbedtls_ssl_check_dtls_clihlo_cookie(
+                           mbedtls_ssl_context *ssl,
+                           const unsigned char *cli_id, size_t cli_id_len,
+                           const unsigned char *in, size_t in_len,
+                           unsigned char *obuf, size_t buf_len, size_t *olen );
+#endif
+
 #endif /* ssl_misc.h */
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index d0b8a64..fb0b709 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -86,6 +86,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
                                     unsigned char *buf,
                                     size_t len,
@@ -157,11 +158,16 @@
 static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
                                      uint8_t slot );
 static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_buffer_message( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
                                      mbedtls_record const *rec );
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
 
 static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
@@ -179,6 +185,7 @@
     return( out_buf_len );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
 {
     size_t const bytes_written = ssl->out_left;
@@ -195,6 +202,7 @@
     return( (int) ( mtu - bytes_written ) );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -246,6 +254,7 @@
  * Double the retransmit timeout value, within the allowed range,
  * returning -1 if the maximum value has already been reached.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
 {
     uint32_t new_timeout;
@@ -329,6 +338,7 @@
  *  - A negative error code if `max_len` didn't offer enough space
  *    for the expansion.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_build_inner_plaintext( unsigned char *content,
                                       size_t *content_size,
                                       size_t remaining,
@@ -356,6 +366,7 @@
 
 /* This function parses a (D)TLSInnerPlaintext structure.
  * See ssl_build_inner_plaintext() for details. */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_inner_plaintext( unsigned char const *content,
                                           size_t *content_size,
                                           uint8_t *rec_type )
@@ -469,6 +480,7 @@
 #if defined(MBEDTLS_GCM_C) || \
     defined(MBEDTLS_CCM_C) || \
     defined(MBEDTLS_CHACHAPOLY_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_transform_aead_dynamic_iv_is_explicit(
                                 mbedtls_ssl_transform const *transform )
 {
@@ -2066,6 +2078,7 @@
 /*
  * Append current handshake message to current outgoing flight
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_flight_append( mbedtls_ssl_context *ssl )
 {
     mbedtls_ssl_flight_item *msg;
@@ -2132,6 +2145,7 @@
 /*
  * Swap transform_out and out_ctr with the alternative ones
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_swap_epochs( mbedtls_ssl_context *ssl )
 {
     mbedtls_ssl_transform *tmp_transform;
@@ -2767,6 +2781,7 @@
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl )
 {
     if( ssl->in_msglen < ssl->in_hslen ||
@@ -2792,6 +2807,7 @@
               ssl->in_msg[8] );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_hs_header( mbedtls_ssl_context const *ssl )
 {
     uint32_t msg_len, frag_off, frag_len;
@@ -2858,6 +2874,7 @@
 /*
  * Check that bitmask is full
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_bitmask_check( unsigned char *mask, size_t len )
 {
     size_t i;
@@ -3057,6 +3074,7 @@
             ( (uint64_t) buf[5]       ) );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3139,8 +3157,8 @@
 
 #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
 /*
- * Without any SSL context, check if a datagram looks like a ClientHello with
- * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message.
+ * Check if a datagram looks like a ClientHello with a valid cookie,
+ * and if it doesn't, generate a HelloVerifyRequest message.
  * Both input and output include full DTLS headers.
  *
  * - if cookie is valid, return 0
@@ -3149,15 +3167,15 @@
  *   return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
  * - otherwise return a specific error code
  */
-static int ssl_check_dtls_clihlo_cookie(
-                           mbedtls_ssl_cookie_write_t *f_cookie_write,
-                           mbedtls_ssl_cookie_check_t *f_cookie_check,
-                           void *p_cookie,
+MBEDTLS_CHECK_RETURN_CRITICAL
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ssl_check_dtls_clihlo_cookie(
+                           mbedtls_ssl_context *ssl,
                            const unsigned char *cli_id, size_t cli_id_len,
                            const unsigned char *in, size_t in_len,
                            unsigned char *obuf, size_t buf_len, size_t *olen )
 {
-    size_t sid_len, cookie_len;
+    size_t sid_len, cookie_len, epoch, fragment_offset;
     unsigned char *p;
 
     /*
@@ -3186,26 +3204,55 @@
      *
      * Minimum length is 61 bytes.
      */
-    if( in_len < 61 ||
-        in[0] != MBEDTLS_SSL_MSG_HANDSHAKE ||
-        in[3] != 0 || in[4] != 0 ||
-        in[19] != 0 || in[20] != 0 || in[21] != 0 )
+    MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: in_len=%u",
+                                (unsigned) in_len ) );
+    MBEDTLS_SSL_DEBUG_BUF( 4, "cli_id", cli_id, cli_id_len );
+    if( in_len < 61 )
     {
+        MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: record too short" ) );
+        return( MBEDTLS_ERR_SSL_DECODE_ERROR );
+    }
+
+    epoch = MBEDTLS_GET_UINT16_BE( in, 3 );
+    fragment_offset = MBEDTLS_GET_UINT24_BE( in, 19 );
+
+    if( in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || epoch != 0 ||
+        fragment_offset != 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: not a good ClientHello" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 4, ( "    type=%u epoch=%u fragment_offset=%u",
+                                    in[0], (unsigned) epoch,
+                                    (unsigned) fragment_offset ) );
         return( MBEDTLS_ERR_SSL_DECODE_ERROR );
     }
 
     sid_len = in[59];
-    if( sid_len > in_len - 61 )
+    if( 59 + 1 + sid_len + 1 > in_len )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: sid_len=%u > %u",
+                                    (unsigned) sid_len,
+                                    (unsigned) in_len - 61 ) );
         return( MBEDTLS_ERR_SSL_DECODE_ERROR );
+    }
+    MBEDTLS_SSL_DEBUG_BUF( 4, "sid received from network",
+                           in + 60, sid_len );
 
     cookie_len = in[60 + sid_len];
-    if( cookie_len > in_len - 60 )
-        return( MBEDTLS_ERR_SSL_DECODE_ERROR );
-
-    if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len,
-                        cli_id, cli_id_len ) == 0 )
+    if( 59 + 1 + sid_len + 1 + cookie_len > in_len )
     {
-        /* Valid cookie */
+        MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: cookie_len=%u > %u",
+                                    (unsigned) cookie_len,
+                                    (unsigned) ( in_len - sid_len - 61 ) ) );
+        return( MBEDTLS_ERR_SSL_DECODE_ERROR );
+    }
+
+    MBEDTLS_SSL_DEBUG_BUF( 4, "cookie received from network",
+                           in + sid_len + 61, cookie_len );
+    if( ssl->conf->f_cookie_check( ssl->conf->p_cookie,
+                                   in + sid_len + 61, cookie_len,
+                                   cli_id, cli_id_len ) == 0 )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: valid" ) );
         return( 0 );
     }
 
@@ -3240,8 +3287,9 @@
 
     /* Generate and write actual cookie */
     p = obuf + 28;
-    if( f_cookie_write( p_cookie,
-                        &p, obuf + buf_len, cli_id, cli_id_len ) != 0 )
+    if( ssl->conf->f_cookie_write( ssl->conf->p_cookie,
+                                   &p, obuf + buf_len,
+                                   cli_id, cli_id_len ) != 0 )
     {
         return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
     }
@@ -3280,6 +3328,7 @@
  * includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected
  * errors, and is the right thing to do in both cases).
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3295,15 +3344,13 @@
         return( 0 );
     }
 
-    ret = ssl_check_dtls_clihlo_cookie(
-            ssl->conf->f_cookie_write,
-            ssl->conf->f_cookie_check,
-            ssl->conf->p_cookie,
+    ret = mbedtls_ssl_check_dtls_clihlo_cookie(
+            ssl,
             ssl->cli_id, ssl->cli_id_len,
             ssl->in_buf, ssl->in_left,
             ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len );
 
-    MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret );
+    MBEDTLS_SSL_DEBUG_RET( 2, "mbedtls_ssl_check_dtls_clihlo_cookie", ret );
 
     if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
     {
@@ -3337,6 +3384,7 @@
 }
 #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_record_type( uint8_t record_type )
 {
     if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE &&
@@ -3369,6 +3417,7 @@
  * Point 2 is needed when the peer is resending, and we have already received
  * the first record from a datagram but are still waiting for the others.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
                                     unsigned char *buf,
                                     size_t len,
@@ -3481,7 +3530,6 @@
     /*
      * Parse and validate record version
      */
-
     rec->ver[0] = buf[ rec_hdr_version_offset + 0 ];
     rec->ver[1] = buf[ rec_hdr_version_offset + 1 ];
     tls_version = mbedtls_ssl_read_version( buf + rec_hdr_version_offset,
@@ -3489,10 +3537,12 @@
 
     if( tls_version > ssl->conf->max_tls_version )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS version mismatch" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS version mismatch: got %u, expected max %u",
+                                    (unsigned) tls_version,
+                                    (unsigned) ssl->conf->max_tls_version) );
+
         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
     }
-
     /*
      * Parse/Copy record sequence number.
      */
@@ -3594,6 +3644,7 @@
 
 
 #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl )
 {
     unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
@@ -3623,6 +3674,7 @@
 /*
  * If applicable, decrypt record content
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
                                        mbedtls_record *rec )
 {
@@ -3757,7 +3809,7 @@
 
     /* Check actual (decrypted) record content length against
      * configured maximum. */
-    if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
+    if( rec->data_len > MBEDTLS_SSL_IN_CONTENT_LEN )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
         return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -3775,8 +3827,11 @@
  */
 
 /* Helper functions for mbedtls_ssl_read_record(). */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_consume_current_message( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_get_next_record( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl );
 
 int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
@@ -3864,6 +3919,7 @@
 }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
 {
     if( ssl->in_left > ssl->next_record_offset )
@@ -3872,6 +3928,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
 {
     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
@@ -3969,6 +4026,7 @@
     return( ret );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
                                   size_t desired )
 {
@@ -4011,6 +4069,7 @@
     return( -1 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_buffer_message( mbedtls_ssl_context *ssl )
 {
     int ret = 0;
@@ -4215,6 +4274,7 @@
 }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
 {
     /*
@@ -4302,6 +4362,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl )
 {
     if( ssl->in_msglen > 0 )
@@ -4328,6 +4389,7 @@
     }
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_load_buffered_record( mbedtls_ssl_context *ssl )
 {
     mbedtls_ssl_handshake_params * const hs = ssl->handshake;
@@ -4385,6 +4447,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
                                      mbedtls_record const *rec )
 {
@@ -4443,6 +4506,7 @@
 
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_get_next_record( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -5193,6 +5257,7 @@
 /*
  * Check record counters and renegotiate if they're above the limit.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
 {
     size_t ep_len = mbedtls_ssl_ep_len( ssl );
@@ -5232,6 +5297,7 @@
  * and having a helper function allows to distinguish between TLS <= 1.2 and
  * TLS 1.3 in the future without bloating the logic of mbedtls_ssl_read().
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_handle_hs_message_post_handshake( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -5549,6 +5615,7 @@
  * Therefore, it is possible that the input message length is 0 and the
  * corresponding return code is 0 on success.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_real( mbedtls_ssl_context *ssl,
                            const unsigned char *buf, size_t len )
 {
diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c
index a924a2a..28c4d3e 100644
--- a/library/ssl_ticket.c
+++ b/library/ssl_ticket.c
@@ -66,6 +66,7 @@
 /*
  * Generate/update a key
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
                                unsigned char index )
 {
@@ -113,6 +114,7 @@
 /*
  * Rotate/generate keys if necessary
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
 {
 #if !defined(MBEDTLS_HAVE_TIME)
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index d3bb291..e60b82f 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -58,6 +58,30 @@
 #include "mbedtls/oid.h"
 #endif
 
+#if defined(MBEDTLS_TEST_HOOKS)
+static mbedtls_ssl_chk_buf_ptr_args chk_buf_ptr_fail_args;
+
+void mbedtls_ssl_set_chk_buf_ptr_fail_args(
+    const uint8_t *cur, const uint8_t *end, size_t need )
+{
+    chk_buf_ptr_fail_args.cur = cur;
+    chk_buf_ptr_fail_args.end = end;
+    chk_buf_ptr_fail_args.need = need;
+}
+
+void mbedtls_ssl_reset_chk_buf_ptr_fail_args( void )
+{
+    memset( &chk_buf_ptr_fail_args, 0, sizeof( chk_buf_ptr_fail_args ) );
+}
+
+int mbedtls_ssl_cmp_chk_buf_ptr_fail_args( mbedtls_ssl_chk_buf_ptr_args *args )
+{
+    return( ( chk_buf_ptr_fail_args.cur  != args->cur  ) ||
+            ( chk_buf_ptr_fail_args.end  != args->end  ) ||
+            ( chk_buf_ptr_fail_args.need != args->need ) );
+}
+#endif /* MBEDTLS_TEST_HOOKS */
+
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
@@ -275,6 +299,7 @@
 }
 
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int resize_buffer( unsigned char **buffer, size_t len_new, size_t *len_old )
 {
     unsigned char* resized_buffer = mbedtls_calloc( 1, len_new );
@@ -380,6 +405,7 @@
                           const unsigned char *, size_t,
                           unsigned char *, size_t);
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls12_populate_transform( mbedtls_ssl_transform *transform,
                                    int ciphersuite,
                                    const unsigned char master[48],
@@ -393,6 +419,7 @@
                                    const mbedtls_ssl_context *ssl );
 
 #if defined(MBEDTLS_SHA256_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int tls_prf_sha256( const unsigned char *secret, size_t slen,
                            const char *label,
                            const unsigned char *random, size_t rlen,
@@ -403,6 +430,7 @@
 #endif /* MBEDTLS_SHA256_C */
 
 #if defined(MBEDTLS_SHA384_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int tls_prf_sha384( const unsigned char *secret, size_t slen,
                            const char *label,
                            const unsigned char *random, size_t rlen,
@@ -415,6 +443,7 @@
 static size_t ssl_session_save_tls12( const mbedtls_ssl_session *session,
                                       unsigned char *buf,
                                       size_t buf_len );
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_session_load_tls12( mbedtls_ssl_session *session,
                                    const unsigned char *buf,
                                    size_t len );
@@ -672,6 +701,7 @@
     memset( session, 0, sizeof(mbedtls_ssl_session) );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_handshake_init( mbedtls_ssl_context *ssl )
 {
     /* Clear old handshake information if present */
@@ -862,6 +892,7 @@
 
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
 /* Dummy cookie callbacks for defaults */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_cookie_write_dummy( void *ctx,
                       unsigned char **p, unsigned char *end,
                       const unsigned char *cli_id, size_t cli_id_len )
@@ -875,6 +906,7 @@
     return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_cookie_check_dummy( void *ctx,
                       const unsigned char *cookie, size_t cookie_len,
                       const unsigned char *cli_id, size_t cli_id_len )
@@ -897,6 +929,7 @@
     memset( ssl, 0, sizeof( mbedtls_ssl_context ) );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_conf_version_check( const mbedtls_ssl_context *ssl )
 {
     const mbedtls_ssl_config *conf = ssl->conf;
@@ -948,6 +981,7 @@
     return( MBEDTLS_ERR_SSL_BAD_CONFIG );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_conf_check(const mbedtls_ssl_context *ssl)
 {
     int ret;
@@ -1092,6 +1126,8 @@
         memset( ssl->in_buf, 0, in_buf_len );
     }
 
+    ssl->send_alert = 0;
+
     /* Reset outgoing message writing */
     ssl->out_msgtype = 0;
     ssl->out_msglen  = 0;
@@ -1371,6 +1407,7 @@
 }
 
 /* Append a new keycert entry to a (possibly empty) list */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_append_key_cert( mbedtls_ssl_key_cert **head,
                                 mbedtls_x509_crt *cert,
                                 mbedtls_pk_context *key )
@@ -1524,6 +1561,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_conf_psk_is_configured( mbedtls_ssl_config const *conf )
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
@@ -1569,6 +1607,7 @@
  * It checks that the provided identity is well-formed and attempts
  * to make a copy of it in the SSL config.
  * On failure, the PSK identity in the config remains unset. */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf,
                                       unsigned char const *psk_identity,
                                       size_t psk_identity_len )
@@ -2763,6 +2802,7 @@
  *
  */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_session_save( const mbedtls_ssl_session *session,
                              unsigned char omit_header,
                              unsigned char *buf,
@@ -2837,6 +2877,7 @@
  * This internal version is wrapped by a public function that cleans up in
  * case of error, and has an extra option omit_header.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_session_load( mbedtls_ssl_session *session,
                              unsigned char omit_header,
                              const unsigned char *buf,
@@ -2903,6 +2944,7 @@
 /*
  * Perform a single step of the SSL handshake
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_prepare_handshake_step( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3061,6 +3103,7 @@
 /*
  * Write HelloRequest to request renegotiation on server
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_hello_request( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3659,6 +3702,7 @@
  * This internal version is wrapped by a public function that cleans up in
  * case of error.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_context_load( mbedtls_ssl_context *ssl,
                              const unsigned char *buf,
                              size_t len )
@@ -4224,6 +4268,7 @@
 #if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
 /* Function for checking `ssl_preset_*_sig_algs` and `ssl_tls12_preset_*_sig_algs`
  * to make sure there are no duplicated signature algorithm entries. */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_no_sig_alg_duplication( uint16_t * sig_algs )
 {
     size_t i, j;
@@ -4769,6 +4814,7 @@
 #else /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_SHA384_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_get_handshake_transcript_sha384( mbedtls_ssl_context *ssl,
                                                 unsigned char *dst,
                                                 size_t dst_len,
@@ -4799,6 +4845,7 @@
 #endif /* MBEDTLS_SHA384_C */
 
 #if defined(MBEDTLS_SHA256_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_get_handshake_transcript_sha256( mbedtls_ssl_context *ssl,
                                                 unsigned char *dst,
                                                 size_t dst_len,
@@ -5034,6 +5081,7 @@
     return( PSA_SUCCESS );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int tls_prf_generic( mbedtls_md_type_t md_type,
                             const unsigned char *secret, size_t slen,
                             const char *label,
@@ -5110,6 +5158,7 @@
 
 #else /* MBEDTLS_USE_PSA_CRYPTO */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int tls_prf_generic( mbedtls_md_type_t md_type,
                             const unsigned char *secret, size_t slen,
                             const char *label,
@@ -5202,6 +5251,7 @@
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_SHA256_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int tls_prf_sha256( const unsigned char *secret, size_t slen,
                            const char *label,
                            const unsigned char *random, size_t rlen,
@@ -5213,6 +5263,7 @@
 #endif /* MBEDTLS_SHA256_C */
 
 #if defined(MBEDTLS_SHA384_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int tls_prf_sha384( const unsigned char *secret, size_t slen,
                            const char *label,
                            const unsigned char *random, size_t rlen,
@@ -5232,6 +5283,7 @@
  * Outputs:
  * - the tls_prf, calc_verify and calc_finished members of handshake structure
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake,
                                    mbedtls_md_type_t hash )
 {
@@ -5276,6 +5328,7 @@
  *      EMS: passed to calc_verify (debug + session_negotiate)
  *      PSA-PSA: conf
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake,
                                unsigned char *master,
                                const mbedtls_ssl_context *ssl )
@@ -5744,6 +5797,7 @@
 #endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
 
 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_hello_request( mbedtls_ssl_context *ssl );
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -5915,6 +5969,7 @@
 #if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
 
 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
                                          unsigned char *crt_buf,
                                          size_t crt_buf_len )
@@ -5930,6 +5985,7 @@
     return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) );
 }
 #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
                                          unsigned char *crt_buf,
                                          size_t crt_buf_len )
@@ -5964,6 +6020,7 @@
  * Once the certificate message is read, parse it into a cert chain and
  * perform basic checks, but leave actual verification to the caller
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
                                         mbedtls_x509_crt *chain )
 {
@@ -6119,6 +6176,7 @@
 }
 
 #if defined(MBEDTLS_SSL_SRV_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl )
 {
     if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
@@ -6144,6 +6202,7 @@
  */
 #define SSL_CERTIFICATE_EXPECTED 0
 #define SSL_CERTIFICATE_SKIP     1
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl,
                                              int authmode )
 {
@@ -6173,6 +6232,7 @@
     return( SSL_CERTIFICATE_EXPECTED );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
                                          int authmode,
                                          mbedtls_x509_crt *chain,
@@ -6270,7 +6330,9 @@
     {
         const mbedtls_pk_context *pk = &chain->pk;
 
-        /* If certificate uses an EC key, make sure the curve is OK */
+        /* If certificate uses an EC key, make sure the curve is OK.
+         * This is a public key, so it can't be opaque, so can_do() is a good
+         * enough check to ensure pk_ec() is safe to use here. */
         if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
             mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 )
         {
@@ -6361,6 +6423,7 @@
 }
 
 #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl,
                                          unsigned char *start, size_t len )
 {
@@ -6392,6 +6455,7 @@
     return( ret );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl,
                                      unsigned char *start, size_t len )
 {
@@ -7060,6 +7124,7 @@
  *      [in] optionally used for:
  *        - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls12_populate_transform( mbedtls_ssl_transform *transform,
                                    int ciphersuite,
                                    const unsigned char master[48],
@@ -7889,6 +7954,7 @@
     return( used );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_session_load_tls12( mbedtls_ssl_session *session,
                                    const unsigned char *buf,
                                    size_t len )
@@ -8254,6 +8320,7 @@
  *          ServerName server_name_list<1..2^16-1>
  *     } ServerNameList;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_parse_server_name_ext( mbedtls_ssl_context *ssl,
                                        const unsigned char *buf,
                                        const unsigned char *end )
@@ -8309,6 +8376,7 @@
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
 #if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
                                 const unsigned char *buf,
                                 const unsigned char *end )
diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c
index 050aaa1..7fa6443 100644
--- a/library/ssl_tls12_client.c
+++ b/library/ssl_tls12_client.c
@@ -75,6 +75,7 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
                                         unsigned char *buf,
                                         const unsigned char *end,
@@ -116,6 +117,7 @@
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
                                                   unsigned char *buf,
                                                   const unsigned char *end,
@@ -147,6 +149,7 @@
           MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
                                        unsigned char *buf,
                                        const unsigned char *end,
@@ -220,6 +223,7 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_cid_ext( mbedtls_ssl_context *ssl,
                               unsigned char *buf,
                               const unsigned char *end,
@@ -266,6 +270,7 @@
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
                                               unsigned char *buf,
                                               const unsigned char *end,
@@ -298,6 +303,7 @@
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
                                            unsigned char *buf,
                                            const unsigned char *end,
@@ -328,6 +334,7 @@
 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
 
 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
                                       unsigned char *buf,
                                       const unsigned char *end,
@@ -358,6 +365,7 @@
 #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
                                          unsigned char *buf,
                                          const unsigned char *end,
@@ -400,6 +408,7 @@
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
 #if defined(MBEDTLS_SSL_DTLS_SRTP)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
                                    unsigned char *buf,
                                    const unsigned char *end,
@@ -629,6 +638,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
                                          const unsigned char *buf,
                                          size_t len )
@@ -673,6 +683,7 @@
 }
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
                                               const unsigned char *buf,
                                               size_t len )
@@ -699,6 +710,7 @@
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
                               const unsigned char *buf,
                               size_t len )
@@ -755,6 +767,7 @@
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
                                          const unsigned char *buf,
                                          size_t len )
@@ -780,6 +793,7 @@
 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
 
 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
                                          const unsigned char *buf,
                                          size_t len )
@@ -805,6 +819,7 @@
 #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
                                          const unsigned char *buf,
                                          size_t len )
@@ -831,6 +846,7 @@
 
 #if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
                                                   const unsigned char *buf,
                                                   size_t len )
@@ -879,6 +895,7 @@
           MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
                                    const unsigned char *buf,
                                    size_t len )
@@ -913,6 +930,7 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
                                const unsigned char *buf, size_t len )
 {
@@ -983,6 +1001,7 @@
 #endif /* MBEDTLS_SSL_ALPN */
 
 #if defined(MBEDTLS_SSL_DTLS_SRTP)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
                                    const unsigned char *buf,
                                    size_t len )
@@ -1103,6 +1122,7 @@
  * Parse HelloVerifyRequest.  Only called after verifying the HS type.
  */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
 {
     const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
@@ -1184,6 +1204,7 @@
 }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
 {
     int ret, i;
@@ -1716,6 +1737,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
     defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl,
                                        unsigned char **p,
                                        unsigned char *end )
@@ -1761,6 +1783,7 @@
     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ||     \
     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
                                              unsigned char **p,
                                              unsigned char *end )
@@ -1825,6 +1848,7 @@
     return( 0 );
 }
 #else
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
 {
     const mbedtls_ecp_curve_info *curve_info;
@@ -1853,6 +1877,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
                                          unsigned char **p,
                                          unsigned char *end )
@@ -1893,6 +1918,7 @@
           MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
                                       unsigned char **p,
                                       unsigned char *end )
@@ -1939,6 +1965,7 @@
 /*
  * Generate a pre-master secret and encrypt it with the server's RSA key
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
                                     size_t offset, size_t *olen,
                                     size_t pms_offset )
@@ -2021,6 +2048,7 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) ||                     \
     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl,
                                           unsigned char **p,
                                           unsigned char *end,
@@ -2079,6 +2107,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2097,6 +2126,8 @@
     peer_pk = &ssl->session_negotiate->peer_cert->pk;
 #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
+    /* This is a public key, so it can't be opaque, so can_do() is a good
+     * enough check to ensure pk_ec() is safe to use below. */
     if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECKEY ) )
     {
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
@@ -2166,6 +2197,7 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
           MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2513,6 +2545,7 @@
 }
 
 #if ! defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
 {
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -2531,6 +2564,7 @@
     return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
 }
 #else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2734,6 +2768,7 @@
 }
 #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2773,6 +2808,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3295,6 +3331,7 @@
 }
 
 #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
 {
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -3320,6 +3357,7 @@
     return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
 }
 #else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -3459,6 +3497,7 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index 4ab3db5..4e18e62 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -78,6 +78,7 @@
 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf )
 {
     if( conf->f_psk != NULL )
@@ -99,6 +100,7 @@
 }
 #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
                                          const unsigned char *buf,
                                          size_t len )
@@ -176,6 +178,7 @@
  *
  * DHE groups are not supported yet.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_supported_groups_ext( mbedtls_ssl_context *ssl,
                                            const unsigned char *buf,
                                            size_t len )
@@ -242,6 +245,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
                                               const unsigned char *buf,
                                               size_t len )
@@ -287,6 +291,7 @@
           MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
                                    const unsigned char *buf,
                                    size_t len )
@@ -316,6 +321,7 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
                                               const unsigned char *buf,
                                               size_t len )
@@ -335,6 +341,7 @@
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
                               const unsigned char *buf,
                               size_t len )
@@ -407,6 +414,7 @@
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
                                       const unsigned char *buf,
                                       size_t len )
@@ -431,6 +439,7 @@
 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
 
 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
                                       const unsigned char *buf,
                                       size_t len )
@@ -455,6 +464,7 @@
 #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
                                          unsigned char *buf,
                                          size_t len )
@@ -529,6 +539,7 @@
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
 #if defined(MBEDTLS_SSL_DTLS_SRTP)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
                                    const unsigned char *buf,
                                    size_t len )
@@ -657,6 +668,7 @@
  * Return 0 if the given key uses one of the acceptable curves, -1 otherwise
  */
 #if defined(MBEDTLS_ECDSA_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_key_curve( mbedtls_pk_context *pk,
                                 const mbedtls_ecp_curve_info **curves )
 {
@@ -678,6 +690,7 @@
  * Try picking a certificate for this ciphersuite,
  * return 0 on success and -1 on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_pick_cert( mbedtls_ssl_context *ssl,
                           const mbedtls_ssl_ciphersuite_t * ciphersuite_info )
 {
@@ -784,6 +797,7 @@
  * Check if a given ciphersuite is suitable for use with our config/keys/etc
  * Sets ciphersuite_info only if the suite matches.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id,
                                   const mbedtls_ssl_ciphersuite_t **ciphersuite_info )
 {
@@ -881,6 +895,7 @@
 /* This function doesn't alert on errors that happen early during
    ClientHello parsing because they might indicate that the client is
    not talking SSL/TLS at all and would not understand our alert. */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_client_hello( mbedtls_ssl_context *ssl )
 {
     int ret, got_common_suite;
@@ -1049,16 +1064,29 @@
         MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
         return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
     }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d",
-                   ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) );
-
-    /* We don't support fragmentation of ClientHello (yet?) */
-    if( buf[1] != 0 ||
-        msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
-        return( MBEDTLS_ERR_SSL_DECODE_ERROR );
+        size_t handshake_len = MBEDTLS_GET_UINT24_BE( buf, 1 );
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %u",
+                       ( unsigned ) handshake_len ) );
+
+        /* The record layer has a record size limit of 2^14 - 1 and
+         * fragmentation is not supported, so buf[1] should be zero. */
+        if( buf[1] != 0 )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message: %u != 0",
+                                        (unsigned) buf[1] ) );
+            return( MBEDTLS_ERR_SSL_DECODE_ERROR );
+        }
+
+        /* We don't support fragmentation of ClientHello (yet?) */
+        if( msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + handshake_len )
+        {
+            MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message: %u != %u + %u",
+                                    (unsigned) msg_len,
+                                    (unsigned) mbedtls_ssl_hs_hdr_len( ssl ),
+                                    (unsigned) handshake_len ) );
+            return( MBEDTLS_ERR_SSL_DECODE_ERROR );
+        }
     }
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -1093,16 +1121,24 @@
             ssl->handshake->out_msg_seq = cli_msg_seq;
             ssl->handshake->in_msg_seq  = cli_msg_seq + 1;
         }
-
-        /*
-         * For now we don't support fragmentation, so make sure
-         * fragment_offset == 0 and fragment_length == length
-         */
-        if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 ||
-            memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) );
-            return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+            /*
+             * For now we don't support fragmentation, so make sure
+             * fragment_offset == 0 and fragment_length == length
+             */
+            size_t fragment_offset, fragment_length, length;
+            fragment_offset = MBEDTLS_GET_UINT24_BE( ssl->in_msg, 6 );
+            fragment_length = MBEDTLS_GET_UINT24_BE( ssl->in_msg, 9 );
+            length = MBEDTLS_GET_UINT24_BE( ssl->in_msg, 1 );
+            MBEDTLS_SSL_DEBUG_MSG(
+                4, ( "fragment_offset=%u fragment_length=%u length=%u",
+                     (unsigned) fragment_offset, (unsigned) fragment_length,
+                     (unsigned) length ) );
+            if( fragment_offset != 0 || length != fragment_length )
+            {
+                MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) );
+                return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+            }
         }
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
@@ -2045,6 +2081,7 @@
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
 
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2163,6 +2200,7 @@
     mbedtls_ssl_session_free( &session_tmp );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
 {
 #if defined(MBEDTLS_HAVE_TIME)
@@ -2349,7 +2387,10 @@
 
 #if defined(MBEDTLS_SSL_ALPN)
     unsigned char *end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN - 4;
-    mbedtls_ssl_write_alpn_ext( ssl, p + 2 + ext_len, end, &olen );
+    if( ( ret = mbedtls_ssl_write_alpn_ext( ssl, p + 2 + ext_len, end, &olen ) )
+        != 0 )
+        return ret;
+
     ext_len += olen;
 #endif
 
@@ -2379,6 +2420,7 @@
 }
 
 #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
 {
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -2397,6 +2439,7 @@
     return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
 }
 #else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -2568,6 +2611,7 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO) &&                      \
         ( defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
           defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) )
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2662,6 +2706,7 @@
 }
 #elif defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2694,6 +2739,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \
     defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl,
                                            size_t *signature_len )
 {
@@ -2721,6 +2767,7 @@
 /* Prepare the ServerKeyExchange message, up to and including
  * calculating the signature if any, but excluding formatting the
  * signature and sending the message. */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
                                             size_t *signature_len )
 {
@@ -3148,6 +3195,7 @@
  * that do not include a ServerKeyExchange message, do nothing. Either
  * way, if successful, move on to the next step in the SSL state
  * machine. */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3169,7 +3217,12 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED)
         if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
         {
-            ssl_get_ecdh_params_from_cert( ssl );
+            ret = ssl_get_ecdh_params_from_cert( ssl );
+            if( ret != 0 )
+            {
+                MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret );
+                return( ret );
+            }
         }
 #endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */
 
@@ -3245,6 +3298,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3284,6 +3338,7 @@
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) ||                       \
     defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p,
                                        const unsigned char *end )
 {
@@ -3327,6 +3382,7 @@
     defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
 
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl,
                                    unsigned char *peer_pms,
                                    size_t *peer_pmslen,
@@ -3344,6 +3400,7 @@
 }
 #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
                                       const unsigned char *p,
                                       const unsigned char *end,
@@ -3429,6 +3486,7 @@
     return( ret );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
                                     const unsigned char *p,
                                     const unsigned char *end,
@@ -3517,6 +3575,7 @@
           MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p,
                                           const unsigned char *end )
 {
@@ -3577,6 +3636,7 @@
 }
 #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -4014,6 +4074,7 @@
 }
 
 #if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
 {
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -4032,6 +4093,7 @@
     return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
 }
 #else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -4195,6 +4257,7 @@
 #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index 416316b..2b68306 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -42,6 +42,7 @@
  *      ProtocolVersion versions<2..254>;
  * } SupportedVersions;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_supported_versions_ext( mbedtls_ssl_context *ssl,
                                                    unsigned char *buf,
                                                    unsigned char *end,
@@ -91,6 +92,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_supported_versions_ext( mbedtls_ssl_context *ssl,
                                                    const unsigned char *buf,
                                                    const unsigned char *end )
@@ -120,6 +122,7 @@
 }
 
 #if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_alpn_ext( mbedtls_ssl_context *ssl,
                                      const unsigned char *buf, size_t len )
 {
@@ -168,6 +171,7 @@
 }
 #endif /* MBEDTLS_SSL_ALPN */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_reset_key_share( mbedtls_ssl_context *ssl )
 {
     uint16_t group_id = ssl->handshake->offered_group_id;
@@ -206,6 +210,7 @@
 /*
  * Functions for writing key_share extension.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_get_default_group_id( mbedtls_ssl_context *ssl,
                                            uint16_t *group_id )
 {
@@ -255,6 +260,7 @@
  *          KeyShareEntry client_shares<0..2^16-1>;
  *      } KeyShareClientHello;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_key_share_ext( mbedtls_ssl_context *ssl,
                                           unsigned char *buf,
                                           unsigned char *end,
@@ -368,6 +374,7 @@
  *        NamedGroup selected_group;
  * } KeyShareHelloRetryRequest;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_hrr_key_share_ext( mbedtls_ssl_context *ssl,
                                               const unsigned char *buf,
                                               const unsigned char *end )
@@ -442,6 +449,7 @@
  *        opaque key_exchange<1..2^16-1>;
  * } KeyShareEntry;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_key_share_ext( mbedtls_ssl_context *ssl,
                                           const unsigned char *buf,
                                           const unsigned char *end )
@@ -516,6 +524,7 @@
  * a "cookie" extension in the new ClientHello.  Clients MUST NOT use
  * cookies in their initial ClientHello in subsequent connections.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_cookie_ext( mbedtls_ssl_context *ssl,
                                        const unsigned char *buf,
                                        const unsigned char *end )
@@ -549,6 +558,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_cookie_ext( mbedtls_ssl_context *ssl,
                                        unsigned char *buf,
                                        unsigned char *end,
@@ -642,6 +652,7 @@
  * \return 1 if the ServerHello contains a supported_versions extension
  * \return A negative value if an error occurred while parsing the ServerHello.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_is_supported_versions_ext_present(
     mbedtls_ssl_context *ssl,
     const unsigned char *buf,
@@ -717,6 +728,7 @@
  *     the server is TLS 1.3 capable but negotiating TLS 1.2 or below.
  * - 0 otherwise
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_is_downgrade_negotiation( mbedtls_ssl_context *ssl,
                                                const unsigned char *buf,
                                                const unsigned char *end )
@@ -749,6 +761,7 @@
  */
 #define SSL_SERVER_HELLO 0
 #define SSL_SERVER_HELLO_HRR 1
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_server_hello_is_hrr( mbedtls_ssl_context *ssl,
                                     const unsigned char *buf,
                                     const unsigned char *end )
@@ -788,6 +801,7 @@
  * - SSL_SERVER_HELLO_TLS1_2
  */
 #define SSL_SERVER_HELLO_TLS1_2 2
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_preprocess_server_hello( mbedtls_ssl_context *ssl,
                                               const unsigned char *buf,
                                               const unsigned char *end )
@@ -878,6 +892,7 @@
     return( ret );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_check_server_hello_session_id_echo( mbedtls_ssl_context *ssl,
                                                          const unsigned char **buf,
                                                          const unsigned char *end )
@@ -925,6 +940,7 @@
  *    Extension extensions<6..2^16-1>;
  * } ServerHello;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_server_hello( mbedtls_ssl_context *ssl,
                                          const unsigned char *buf,
                                          const unsigned char *end,
@@ -1183,6 +1199,7 @@
     return( ret );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_postprocess_server_hello( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1258,6 +1275,7 @@
     return( ret );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_postprocess_hrr( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1281,6 +1299,7 @@
  * Wait and parse ServerHello handshake message.
  * Handler for MBEDTLS_SSL_SERVER_HELLO
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_process_server_hello( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1355,6 +1374,7 @@
  *     Extension extensions<0..2^16-1>;
  * } EncryptedExtensions;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl,
                                                  const unsigned char *buf,
                                                  const unsigned char *end )
@@ -1436,6 +1456,7 @@
     return( ret );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl )
 {
     int ret;
@@ -1486,6 +1507,7 @@
  * - SSL_CERTIFICATE_REQUEST_SKIP
  * indicating if a Certificate Request is expected or not.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_certificate_request_coordinate( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1523,6 +1545,7 @@
  *   Extension extensions<2..2^16-1>;
  * } CertificateRequest;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_certificate_request( mbedtls_ssl_context *ssl,
                                                 const unsigned char *buf,
                                                 const unsigned char *end )
@@ -1639,6 +1662,7 @@
 /*
  * Handler for  MBEDTLS_SSL_CERTIFICATE_REQUEST
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_process_certificate_request( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1684,6 +1708,7 @@
 /*
  * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_process_server_certificate( mbedtls_ssl_context *ssl )
 {
     int ret;
@@ -1699,6 +1724,7 @@
 /*
  * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_process_certificate_verify( mbedtls_ssl_context *ssl )
 {
     int ret;
@@ -1715,6 +1741,7 @@
 /*
  * Handler for MBEDTLS_SSL_SERVER_FINISHED
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_process_server_finished( mbedtls_ssl_context *ssl )
 {
     int ret;
@@ -1746,6 +1773,7 @@
 /*
  * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_client_certificate( mbedtls_ssl_context *ssl )
 {
     int non_empty_certificate_msg = 0;
@@ -1788,6 +1816,7 @@
 /*
  * Handler for MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_client_certificate_verify( mbedtls_ssl_context *ssl )
 {
     int ret = mbedtls_ssl_tls13_write_certificate_verify( ssl );
@@ -1802,6 +1831,7 @@
 /*
  * Handler for MBEDTLS_SSL_CLIENT_FINISHED
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_client_finished( mbedtls_ssl_context *ssl )
 {
     int ret;
@@ -1825,6 +1855,7 @@
 /*
  * Handler for MBEDTLS_SSL_FLUSH_BUFFERS
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_flush_buffers( mbedtls_ssl_context *ssl )
 {
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
@@ -1835,6 +1866,7 @@
 /*
  * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_handshake_wrapup( mbedtls_ssl_context *ssl )
 {
 
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index 8ec9f90..265d6d3 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -31,6 +31,7 @@
 #include <string.h>
 
 #include "ssl_misc.h"
+#include "ssl_tls13_invasive.h"
 #include "ssl_tls13_keys.h"
 #include "ssl_debug_helpers.h"
 
@@ -156,6 +157,7 @@
     *verify_buffer_len = idx;
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_certificate_verify( mbedtls_ssl_context *ssl,
                                                const unsigned char *buf,
                                                const unsigned char *end,
@@ -385,9 +387,11 @@
  */
 
 /* 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 )
+MBEDTLS_CHECK_RETURN_CRITICAL
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_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;
@@ -438,6 +442,7 @@
 
     mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert );
 
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, certificate_list_len );
     certificate_list_end = p + certificate_list_len;
     while( p < certificate_list_end )
     {
@@ -517,9 +522,11 @@
     return( ret );
 }
 #else
-static int ssl_tls13_parse_certificate( mbedtls_ssl_context *ssl,
-                                        const unsigned char *buf,
-                                        const unsigned char *end )
+MBEDTLS_CHECK_RETURN_CRITICAL
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ssl_tls13_parse_certificate( mbedtls_ssl_context *ssl,
+                                         const unsigned char *buf,
+                                         const unsigned char *end )
 {
     ((void) ssl);
     ((void) buf);
@@ -532,12 +539,15 @@
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
 /* Validate certificate chain sent by the server. */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_validate_certificate( mbedtls_ssl_context *ssl )
 {
     int ret = 0;
     int authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
     mbedtls_x509_crt *ca_chain;
     mbedtls_x509_crl *ca_crl;
+    const char *ext_oid;
+    size_t ext_len;
     uint32_t verify_result = 0;
 
     /* If SNI was used, overwrite authentication mode
@@ -626,12 +636,25 @@
     /*
      * Secondary checks: always done, but change 'ret' only if it was 0
      */
-    if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert,
-                                      ssl->handshake->ciphersuite_info,
-                                      !ssl->conf->endpoint,
-                                      &verify_result ) != 0 )
+    if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate ( usage extensions )" ) );
+        ext_oid = MBEDTLS_OID_SERVER_AUTH;
+        ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH );
+    }
+    else
+    {
+        ext_oid = MBEDTLS_OID_CLIENT_AUTH;
+        ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH );
+    }
+
+    if( ( mbedtls_x509_crt_check_key_usage(
+              ssl->session_negotiate->peer_cert,
+              MBEDTLS_X509_KU_DIGITAL_SIGNATURE ) != 0 ) ||
+        ( mbedtls_x509_crt_check_extended_key_usage(
+              ssl->session_negotiate->peer_cert,
+              ext_oid, ext_len ) != 0 ) )
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) );
         if( ret == 0 )
             ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
     }
@@ -641,7 +664,8 @@
      * with details encoded in the verification flags. All other kinds
      * of error codes, including those from the user provided f_vrfy
      * functions, are treated as fatal and lead to a failure of
-     * ssl_tls13_parse_certificate even if verification was optional. */
+     * mbedtls_ssl_tls13_parse_certificate even if verification was optional.
+     */
     if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
         ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
           ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE ) )
@@ -696,6 +720,7 @@
     return( ret );
 }
 #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_validate_certificate( mbedtls_ssl_context *ssl )
 {
     ((void) ssl);
@@ -718,8 +743,8 @@
                           &buf, &buf_len ) );
 
     /* Parse the certificate chain sent by the peer. */
-    MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_certificate( ssl, buf,
-                                                       buf + buf_len ) );
+    MBEDTLS_SSL_PROC_CHK( mbedtls_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 ) );
 
@@ -757,6 +782,7 @@
  *        CertificateEntry certificate_list<0..2^24-1>;
  *    } Certificate;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_certificate_body( mbedtls_ssl_context *ssl,
                                              unsigned char *buf,
                                              unsigned char *end,
@@ -850,7 +876,6 @@
 /*
  * STATE HANDLING: Output Certificate Verify
  */
-
 int mbedtls_ssl_tls13_check_sig_alg_cert_key_match( uint16_t sig_alg,
                                                     mbedtls_pk_context *key )
 {
@@ -902,6 +927,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_select_sig_alg_for_certificate_verify(
                                           mbedtls_ssl_context *ssl,
                                           mbedtls_pk_context *own_key,
@@ -931,6 +957,7 @@
     return( -1 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_certificate_verify_body( mbedtls_ssl_context *ssl,
                                                     unsigned char *buf,
                                                     unsigned char *end,
@@ -1080,6 +1107,7 @@
  * Implementation
  */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_preprocess_finished_message( mbedtls_ssl_context *ssl )
 {
     int ret;
@@ -1099,6 +1127,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_finished_message( mbedtls_ssl_context *ssl,
                                              const unsigned char *buf,
                                              const unsigned char *end )
@@ -1177,6 +1206,7 @@
  * Implement
  */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_prepare_finished_message( mbedtls_ssl_context *ssl )
 {
     int ret;
@@ -1197,6 +1227,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_finished_message_body( mbedtls_ssl_context *ssl,
                                                   unsigned char *buf,
                                                   unsigned char *end,
@@ -1276,6 +1307,7 @@
  *
  */
 #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_change_cipher_spec_body( mbedtls_ssl_context *ssl,
                                                     unsigned char *buf,
                                                     unsigned char *end,
diff --git a/library/ssl_tls13_invasive.h b/library/ssl_tls13_invasive.h
index f874a88..5470200 100644
--- a/library/ssl_tls13_invasive.h
+++ b/library/ssl_tls13_invasive.h
@@ -25,7 +25,9 @@
 #include "psa/crypto.h"
 
 #if defined(MBEDTLS_TEST_HOOKS)
-
+int mbedtls_ssl_tls13_parse_certificate( mbedtls_ssl_context *ssl,
+                                         const unsigned char *buf,
+                                         const unsigned char *end );
 #endif /* MBEDTLS_TEST_HOOKS */
 
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
diff --git a/library/ssl_tls13_keys.c b/library/ssl_tls13_keys.c
index d4a8e46..51743bb 100644
--- a/library/ssl_tls13_keys.c
+++ b/library/ssl_tls13_keys.c
@@ -644,6 +644,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_calc_finished_core( psa_algorithm_t hash_alg,
                                          unsigned char const *base_key,
                                          unsigned char const *transcript,
@@ -1071,6 +1072,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int mbedtls_ssl_tls13_get_cipher_key_info(
                     const mbedtls_ssl_ciphersuite_t *ciphersuite_info,
                     size_t *key_len, size_t *iv_len )
diff --git a/library/ssl_tls13_keys.h b/library/ssl_tls13_keys.h
index 693b6c4..76c1e93 100644
--- a/library/ssl_tls13_keys.h
+++ b/library/ssl_tls13_keys.h
@@ -121,6 +121,7 @@
  * \return           A negative error code on failure.
  */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_hkdf_expand_label(
                      psa_algorithm_t hash_alg,
                      const unsigned char *secret, size_t secret_len,
@@ -159,6 +160,7 @@
  * \returns             A negative error code on failure.
  */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_make_traffic_keys(
                      psa_algorithm_t hash_alg,
                      const unsigned char *client_secret,
@@ -205,6 +207,7 @@
  * \returns        \c 0 on success.
  * \returns        A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_derive_secret(
                    psa_algorithm_t hash_alg,
                    const unsigned char *secret, size_t secret_len,
@@ -255,6 +258,7 @@
  * \returns        \c 0 on success.
  * \returns        A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_derive_early_secrets(
           psa_algorithm_t hash_alg,
           unsigned char const *early_secret,
@@ -300,6 +304,7 @@
  * \returns        \c 0 on success.
  * \returns        A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_derive_handshake_secrets(
           psa_algorithm_t hash_alg,
           unsigned char const *handshake_secret,
@@ -350,6 +355,7 @@
  * \returns        \c 0 on success.
  * \returns        A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_derive_application_secrets(
           psa_algorithm_t hash_alg,
           unsigned char const *master_secret,
@@ -380,6 +386,7 @@
  * \returns        \c 0 on success.
  * \returns        A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_derive_resumption_master_secret(
           psa_algorithm_t hash_alg,
           unsigned char const *application_secret,
@@ -453,6 +460,7 @@
  * \returns           A negative error code on failure.
  */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_evolve_secret(
                    psa_algorithm_t hash_alg,
                    const unsigned char *secret_old,
@@ -482,6 +490,7 @@
  * \returns           \c 0 on success.
  * \returns           A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_create_psk_binder( mbedtls_ssl_context *ssl,
                                const psa_algorithm_t hash_alg,
                                unsigned char const *psk, size_t psk_len,
@@ -516,6 +525,7 @@
  *                     mbedtls_ssl_transform_encrypt().
  * \return             A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_populate_transform( mbedtls_ssl_transform *transform,
                                           int endpoint,
                                           int ciphersuite,
@@ -542,6 +552,7 @@
  * \returns    \c 0 on success.
  * \returns    A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_key_schedule_stage_early( mbedtls_ssl_context *ssl );
 
 /**
@@ -560,6 +571,7 @@
  * \returns    \c 0 on success.
  * \returns    A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_key_schedule_stage_handshake( mbedtls_ssl_context *ssl );
 
 /**
@@ -574,6 +586,7 @@
  * \returns    \c 0 on success.
  * \returns    A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_generate_handshake_keys( mbedtls_ssl_context *ssl,
                                                mbedtls_ssl_key_set *traffic_keys );
 
@@ -593,6 +606,7 @@
  * \returns    \c 0 on success.
  * \returns    A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_key_schedule_stage_application( mbedtls_ssl_context *ssl );
 
 /**
@@ -607,6 +621,7 @@
  * \returns    \c 0 on success.
  * \returns    A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_generate_application_keys(
     mbedtls_ssl_context* ssl, mbedtls_ssl_key_set *traffic_keys );
 
@@ -620,6 +635,7 @@
  * \returns    \c 0 on success.
  * \returns    A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_generate_resumption_master_secret(
     mbedtls_ssl_context *ssl );
 
@@ -645,6 +661,7 @@
  * \returns    \c 0 on success.
  * \returns    A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_calculate_verify_data( mbedtls_ssl_context *ssl,
                                              unsigned char *dst,
                                              size_t dst_len,
@@ -660,6 +677,7 @@
  * \returns    \c 0 on success.
  * \returns    A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_compute_handshake_transform( mbedtls_ssl_context *ssl );
 
 /**
@@ -671,6 +689,7 @@
  * \returns    \c 0 on success.
  * \returns    A negative error code on failure.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_compute_application_transform( mbedtls_ssl_context *ssl );
 
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 144c70d..7d99433 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -50,6 +50,7 @@
  *          ProtocolVersion versions<2..254>;
  *   } SupportedVersions;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_supported_versions_ext( mbedtls_ssl_context *ssl,
                                                    const unsigned char *buf,
                                                    const unsigned char *end )
@@ -106,6 +107,7 @@
  *       NamedGroup named_group_list<2..2^16-1>;
  *   } NamedGroupList;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_supported_groups_ext( mbedtls_ssl_context *ssl,
                                                  const unsigned char *buf,
                                                  const unsigned char *end )
@@ -168,6 +170,7 @@
  *    be needed.
  *  - A negative value for fatal errors.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_key_shares_ext( mbedtls_ssl_context *ssl,
                                            const unsigned char *buf,
                                            const unsigned char *end )
@@ -313,6 +316,7 @@
 }
 #endif /* MBEDTLS_DEBUG_C */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_client_hello_has_exts( mbedtls_ssl_context *ssl,
                                             int exts_mask )
 {
@@ -320,6 +324,7 @@
     return( masked == exts_mask );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange(
         mbedtls_ssl_context *ssl )
 {
@@ -329,6 +334,7 @@
                           MBEDTLS_SSL_EXT_SIG_ALG ) );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_check_ephemeral_key_exchange( mbedtls_ssl_context *ssl )
 {
     if( !mbedtls_ssl_conf_tls13_ephemeral_enabled( ssl ) )
@@ -348,6 +354,7 @@
  * Pick best ( private key, certificate chain ) pair based on the signature
  * algorithms supported by the client.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_pick_key_cert( mbedtls_ssl_context *ssl )
 {
     mbedtls_ssl_key_cert *key_cert, *key_cert_list;
@@ -463,6 +470,7 @@
 #define SSL_CLIENT_HELLO_OK           0
 #define SSL_CLIENT_HELLO_HRR_REQUIRED 1
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_client_hello( mbedtls_ssl_context *ssl,
                                          const unsigned char *buf,
                                          const unsigned char *end )
@@ -804,6 +812,7 @@
 
 /* Update the handshake state machine */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_postprocess_client_hello( mbedtls_ssl_context* ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -850,6 +859,7 @@
  * Main entry point from the state machine; orchestrates the otherfunctions.
  */
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_process_client_hello( mbedtls_ssl_context *ssl )
 {
 
@@ -888,6 +898,7 @@
 /*
  * Handler for MBEDTLS_SSL_SERVER_HELLO
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_prepare_server_hello( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -923,6 +934,7 @@
  *      ProtocolVersion selected_version;
  * } SupportedVersions;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_server_hello_supported_versions_ext(
                                                 mbedtls_ssl_context *ssl,
                                                 unsigned char *buf,
@@ -960,6 +972,7 @@
 
 /* Generate and export a single key share. For hybrid KEMs, this can
  * be called multiple times with the different components of the hybrid. */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_generate_and_write_key_share( mbedtls_ssl_context *ssl,
                                                    uint16_t named_group,
                                                    unsigned char *buf,
@@ -1013,6 +1026,7 @@
  *     KeyShareEntry server_share;
  * } KeyShareServerHello;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_key_share_ext( mbedtls_ssl_context *ssl,
                                           unsigned char *buf,
                                           unsigned char *end,
@@ -1056,6 +1070,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_hrr_key_share_ext( mbedtls_ssl_context *ssl,
                                               unsigned char *buf,
                                               unsigned char *end,
@@ -1131,6 +1146,7 @@
  *        Extension extensions<6..2^16-1>;
  *    } ServerHello;
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_server_hello_body( mbedtls_ssl_context *ssl,
                                               unsigned char *buf,
                                               unsigned char *end,
@@ -1257,6 +1273,7 @@
     return( ret );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_finalize_write_server_hello( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1272,6 +1289,7 @@
     return( ret );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_server_hello( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1319,6 +1337,7 @@
 /*
  * Handler for MBEDTLS_SSL_HELLO_RETRY_REQUEST
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_prepare_hello_retry_request( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1345,6 +1364,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_hello_retry_request( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1398,6 +1418,7 @@
  * } EncryptedExtensions;
  *
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_encrypted_extensions_body( mbedtls_ssl_context *ssl,
                                                       unsigned char *buf,
                                                       unsigned char *end,
@@ -1436,6 +1457,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_encrypted_extensions( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1487,6 +1509,7 @@
  * indicating if the writing of the CertificateRequest
  * should be skipped or not.
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_certificate_request_coordinate( mbedtls_ssl_context *ssl )
 {
     int authmode;
@@ -1513,6 +1536,7 @@
  * } CertificateRequest;
  *
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_certificate_request_body( mbedtls_ssl_context *ssl,
                                                      unsigned char *buf,
                                                      const unsigned char *end,
@@ -1559,6 +1583,7 @@
     return( 0 );
 }
 
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_certificate_request( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1606,6 +1631,7 @@
 /*
  * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_server_certificate( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1631,6 +1657,7 @@
 /*
  * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_certificate_verify( mbedtls_ssl_context *ssl )
 {
     int ret = mbedtls_ssl_tls13_write_certificate_verify( ssl );
@@ -1644,6 +1671,7 @@
 /*
  * Handler for MBEDTLS_SSL_SERVER_FINISHED
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_server_finished( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1679,6 +1707,7 @@
 /*
  * Handler for MBEDTLS_SSL_CLIENT_FINISHED
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_process_client_finished( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1701,6 +1730,7 @@
 /*
  * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP
  */
+MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_handshake_wrapup( mbedtls_ssl_context *ssl )
 {
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) );
diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c
index 7288548..136e25b 100644
--- a/programs/aes/crypt_and_hash.c
+++ b/programs/aes/crypt_and_hash.c
@@ -166,6 +166,10 @@
         goto exit;
     }
 
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( fin, NULL );
+    mbedtls_setbuf( fout, NULL );
+
     /*
      * Read the Cipher and MD from the command line
      */
diff --git a/programs/psa/key_ladder_demo.c b/programs/psa/key_ladder_demo.c
index cad875e..1303719 100644
--- a/programs/psa/key_ladder_demo.c
+++ b/programs/psa/key_ladder_demo.c
@@ -56,6 +56,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "mbedtls/platform.h" // for mbedtls_setbuf
 #include "mbedtls/platform_util.h" // for mbedtls_platform_zeroize
 
 #include <psa/crypto.h>
@@ -177,6 +178,8 @@
                                key_data, sizeof( key_data ),
                                &key_size ) );
     SYS_CHECK( ( key_file = fopen( output_file_name, "wb" ) ) != NULL );
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( key_file, NULL );
     SYS_CHECK( fwrite( key_data, 1, key_size, key_file ) == key_size );
     SYS_CHECK( fclose( key_file ) == 0 );
     key_file = NULL;
@@ -231,6 +234,8 @@
     unsigned char extra_byte;
 
     SYS_CHECK( ( key_file = fopen( key_file_name, "rb" ) ) != NULL );
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( key_file, NULL );
     SYS_CHECK( ( key_size = fread( key_data, 1, sizeof( key_data ),
                                    key_file ) ) != 0 );
     if( fread( &extra_byte, 1, 1, key_file ) != 0 )
@@ -372,6 +377,8 @@
 
     /* Find the size of the data to wrap. */
     SYS_CHECK( ( input_file = fopen( input_file_name, "rb" ) ) != NULL );
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( input_file, NULL );
     SYS_CHECK( fseek( input_file, 0, SEEK_END ) == 0 );
     SYS_CHECK( ( input_position = ftell( input_file ) ) != -1 );
 #if LONG_MAX > SIZE_MAX
@@ -418,6 +425,8 @@
 
     /* Write the output. */
     SYS_CHECK( ( output_file = fopen( output_file_name, "wb" ) ) != NULL );
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( output_file, NULL );
     SYS_CHECK( fwrite( &header, 1, sizeof( header ),
                        output_file ) == sizeof( header ) );
     SYS_CHECK( fwrite( buffer, 1, ciphertext_size,
@@ -453,6 +462,8 @@
 
     /* Load and validate the header. */
     SYS_CHECK( ( input_file = fopen( input_file_name, "rb" ) ) != NULL );
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( input_file, NULL );
     SYS_CHECK( fread( &header, 1, sizeof( header ),
                       input_file ) == sizeof( header ) );
     if( memcmp( &header.magic, WRAPPED_DATA_MAGIC,
@@ -509,6 +520,8 @@
 
     /* Write the output. */
     SYS_CHECK( ( output_file = fopen( output_file_name, "wb" ) ) != NULL );
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf( output_file, NULL );
     SYS_CHECK( fwrite( buffer, 1, plaintext_size,
                        output_file ) == plaintext_size );
     SYS_CHECK( fclose( output_file ) == 0 );
diff --git a/programs/ssl/ssl_test_common_source.c b/programs/ssl/ssl_test_common_source.c
index ad9dcdd..8c35fab 100644
--- a/programs/ssl/ssl_test_common_source.c
+++ b/programs/ssl/ssl_test_common_source.c
@@ -101,6 +101,10 @@
             goto exit;
         }
 
+        /* Ensure no stdio buffering of secrets, as such buffers cannot be
+         * wiped. */
+        mbedtls_setbuf( f, NULL );
+
         if( fwrite( nss_keylog_line, 1, len, f ) != len )
         {
             fclose( f );
@@ -305,6 +309,9 @@
 #if defined(MBEDTLS_SHA224_C)
     MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA224 )
 #endif
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
+#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA256_C */
 #if defined(MBEDTLS_SHA1_C)
     /* Allow SHA-1 as we use it extensively in tests. */
     MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA1 )
diff --git a/programs/ssl/ssl_test_lib.h b/programs/ssl/ssl_test_lib.h
index 03349ba..c368f57 100644
--- a/programs/ssl/ssl_test_lib.h
+++ b/programs/ssl/ssl_test_lib.h
@@ -34,6 +34,7 @@
 #define mbedtls_printf     printf
 #define mbedtls_fprintf    fprintf
 #define mbedtls_snprintf   snprintf
+#define mbedtls_setbuf     setbuf
 #define mbedtls_exit            exit
 #define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
 #define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 6144c2f..458fe8f 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -2253,6 +2253,7 @@
     scripts/config.py unset MBEDTLS_PLATFORM_SNPRINTF_ALT
     scripts/config.py unset MBEDTLS_PLATFORM_TIME_ALT
     scripts/config.py unset MBEDTLS_PLATFORM_EXIT_ALT
+    scripts/config.py unset MBEDTLS_PLATFORM_SETBUF_ALT
     scripts/config.py unset MBEDTLS_PLATFORM_NV_SEED_ALT
     scripts/config.py unset MBEDTLS_ENTROPY_NV_SEED
     scripts/config.py unset MBEDTLS_FS_IO
@@ -2904,6 +2905,18 @@
     if_build_succeeded tests/ssl-opt.sh
 }
 
+component_test_tls13_only_with_hooks () {
+    msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3 and MBEDTLS_TEST_HOOKS, without MBEDTLS_SSL_PROTO_TLS1_2"
+    scripts/config.py set MBEDTLS_TEST_HOOKS
+    make CFLAGS="'-DMBEDTLS_USER_CONFIG_FILE=\"../tests/configs/tls13-only.h\"'"
+
+    msg "test: default config with MBEDTLS_SSL_PROTO_TLS1_3 enabled, without MBEDTLS_SSL_PROTO_TLS1_2"
+    if_build_succeeded make test
+
+    msg "ssl-opt.sh (TLS 1.3)"
+    if_build_succeeded tests/ssl-opt.sh
+}
+
 component_test_tls13 () {
     msg "build: default config with MBEDTLS_SSL_PROTO_TLS1_3 enabled, without padding"
     scripts/config.py set MBEDTLS_SSL_PROTO_TLS1_3
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 6df879c..80b7806 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -6211,7 +6211,6 @@
             0 \
             -c "Ciphersuite is TLS-[EC]*DHE-RSA-WITH-"
 
-
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "keyUsage srv: RSA, keyEncipherment -> RSA" \
             "$P_SRV key_file=data_files/server2.key \
@@ -6346,6 +6345,78 @@
             -c "Ciphersuite is TLS-" \
             -c "! Usage does not match the keyUsage extension"
 
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "keyUsage cli 1.3: DigitalSignature+KeyEncipherment, RSA: OK" \
+            "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server2.key \
+             -cert data_files/server2.ku-ds_ke.crt" \
+            "$P_CLI debug_level=3" \
+            0 \
+            -C "bad certificate (usage extensions)" \
+            -C "Processing of the Certificate handshake message failed" \
+            -c "Ciphersuite is"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "keyUsage cli 1.3: KeyEncipherment, RSA: fail" \
+            "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server2.key \
+             -cert data_files/server2.ku-ke.crt" \
+            "$P_CLI debug_level=1" \
+            1 \
+            -c "bad certificate (usage extensions)" \
+            -c "Processing of the Certificate handshake message failed" \
+            -C "Ciphersuite is"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "keyUsage cli 1.3: KeyAgreement, RSA: fail" \
+            "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server2.key \
+             -cert data_files/server2.ku-ka.crt" \
+            "$P_CLI debug_level=1" \
+            1 \
+            -c "bad certificate (usage extensions)" \
+            -c "Processing of the Certificate handshake message failed" \
+            -C "Ciphersuite is"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "keyUsage cli 1.3: DigitalSignature, ECDSA: OK" \
+            "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \
+             -cert data_files/server5.ku-ds.crt" \
+            "$P_CLI debug_level=3" \
+            0 \
+            -C "bad certificate (usage extensions)" \
+            -C "Processing of the Certificate handshake message failed" \
+            -c "Ciphersuite is"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "keyUsage cli 1.3: KeyEncipherment, ECDSA: fail" \
+            "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \
+             -cert data_files/server5.ku-ke.crt" \
+            "$P_CLI debug_level=1" \
+            1 \
+            -c "bad certificate (usage extensions)" \
+            -c "Processing of the Certificate handshake message failed" \
+            -C "Ciphersuite is"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "keyUsage cli 1.3: KeyAgreement, ECDSA: fail" \
+            "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \
+             -cert data_files/server5.ku-ka.crt" \
+            "$P_CLI debug_level=1" \
+            1 \
+            -c "bad certificate (usage extensions)" \
+            -c "Processing of the Certificate handshake message failed" \
+            -C "Ciphersuite is"
+
 # Tests for keyUsage in leaf certificates, part 3:
 # server-side checking of client cert
 
@@ -6355,6 +6426,7 @@
             "$O_CLI -key data_files/server2.key \
              -cert data_files/server2.ku-ds.crt" \
             0 \
+            -s "Verifying peer X.509 certificate... ok" \
             -S "bad certificate (usage extensions)" \
             -S "Processing of the Certificate handshake message failed"
 
@@ -6382,6 +6454,7 @@
             "$O_CLI -key data_files/server5.key \
              -cert data_files/server5.ku-ds.crt" \
             0 \
+            -s "Verifying peer X.509 certificate... ok" \
             -S "bad certificate (usage extensions)" \
             -S "Processing of the Certificate handshake message failed"
 
@@ -6394,6 +6467,52 @@
             -s "bad certificate (usage extensions)" \
             -S "Processing of the Certificate handshake message failed"
 
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "keyUsage cli-auth 1.3: RSA, DigitalSignature: OK" \
+            "$P_SRV debug_level=1 auth_mode=optional" \
+            "$O_NEXT_CLI_NO_CERT -key data_files/server2.key \
+             -cert data_files/server2.ku-ds.crt" \
+            0 \
+            -s "Verifying peer X.509 certificate... ok" \
+            -S "bad certificate (usage extensions)" \
+            -S "Processing of the Certificate handshake message failed"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "keyUsage cli-auth 1.3: RSA, KeyEncipherment: fail (soft)" \
+            "$P_SRV debug_level=1 auth_mode=optional" \
+            "$O_NEXT_CLI_NO_CERT -key data_files/server2.key \
+             -cert data_files/server2.ku-ke.crt" \
+            0 \
+            -s "bad certificate (usage extensions)" \
+            -S "Processing of the Certificate handshake message failed"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "keyUsage cli-auth 1.3: ECDSA, DigitalSignature: OK" \
+            "$P_SRV debug_level=1 auth_mode=optional" \
+            "$O_NEXT_CLI_NO_CERT -key data_files/server5.key \
+             -cert data_files/server5.ku-ds.crt" \
+            0 \
+            -s "Verifying peer X.509 certificate... ok" \
+            -S "bad certificate (usage extensions)" \
+            -S "Processing of the Certificate handshake message failed"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "keyUsage cli-auth 1.3: ECDSA, KeyAgreement: fail (soft)" \
+            "$P_SRV debug_level=1 auth_mode=optional" \
+            "$O_NEXT_CLI_NO_CERT -key data_files/server5.key \
+             -cert data_files/server5.ku-ka.crt" \
+            0 \
+            -s "bad certificate (usage extensions)" \
+            -S "Processing of the Certificate handshake message failed"
+
 # Tests for extendedKeyUsage, part 1: server-side certificate/suite selection
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
@@ -6466,6 +6585,54 @@
             -c "Processing of the Certificate handshake message failed" \
             -C "Ciphersuite is TLS-"
 
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "extKeyUsage cli 1.3: serverAuth -> OK" \
+            "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \
+             -cert data_files/server5.eku-srv.crt" \
+            "$P_CLI debug_level=1" \
+            0 \
+            -C "bad certificate (usage extensions)" \
+            -C "Processing of the Certificate handshake message failed" \
+            -c "Ciphersuite is"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "extKeyUsage cli 1.3: serverAuth,clientAuth -> OK" \
+            "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \
+             -cert data_files/server5.eku-srv_cli.crt" \
+            "$P_CLI debug_level=1" \
+            0 \
+            -C "bad certificate (usage extensions)" \
+            -C "Processing of the Certificate handshake message failed" \
+            -c "Ciphersuite is"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "extKeyUsage cli 1.3: codeSign,anyEKU -> OK" \
+            "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \
+             -cert data_files/server5.eku-cs_any.crt" \
+            "$P_CLI debug_level=1" \
+            0 \
+            -C "bad certificate (usage extensions)" \
+            -C "Processing of the Certificate handshake message failed" \
+            -c "Ciphersuite is"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "extKeyUsage cli 1.3: codeSign -> fail" \
+            "$O_NEXT_SRV_NO_CERT -tls1_3 -num_tickets=0 -key data_files/server5.key \
+             -cert data_files/server5.eku-cs.crt" \
+            "$P_CLI debug_level=1" \
+            1 \
+            -c "bad certificate (usage extensions)" \
+            -c "Processing of the Certificate handshake message failed" \
+            -C "Ciphersuite is"
+
 # Tests for extendedKeyUsage, part 3: server-side checking of client cert
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
@@ -6513,6 +6680,50 @@
             -s "bad certificate (usage extensions)" \
             -s "Processing of the Certificate handshake message failed"
 
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "extKeyUsage cli-auth 1.3: clientAuth -> OK" \
+            "$P_SRV debug_level=1 auth_mode=optional" \
+            "$O_NEXT_CLI_NO_CERT -key data_files/server5.key \
+             -cert data_files/server5.eku-cli.crt" \
+            0 \
+            -S "bad certificate (usage extensions)" \
+            -S "Processing of the Certificate handshake message failed"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "extKeyUsage cli-auth 1.3: serverAuth,clientAuth -> OK" \
+            "$P_SRV debug_level=1 auth_mode=optional" \
+            "$O_NEXT_CLI_NO_CERT -key data_files/server5.key \
+             -cert data_files/server5.eku-srv_cli.crt" \
+            0 \
+            -S "bad certificate (usage extensions)" \
+            -S "Processing of the Certificate handshake message failed"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "extKeyUsage cli-auth 1.3: codeSign,anyEKU -> OK" \
+            "$P_SRV debug_level=1 auth_mode=optional" \
+            "$O_NEXT_CLI_NO_CERT -key data_files/server5.key \
+             -cert data_files/server5.eku-cs_any.crt" \
+            0 \
+            -S "bad certificate (usage extensions)" \
+            -S "Processing of the Certificate handshake message failed"
+
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_openssl_tls1_3
+requires_config_disabled MBEDTLS_SSL_PROTO_TLS1_2
+run_test    "extKeyUsage cli-auth 1.3: codeSign -> fail (soft)" \
+            "$P_SRV debug_level=1 auth_mode=optional" \
+            "$O_NEXT_CLI_NO_CERT -key data_files/server5.key \
+             -cert data_files/server5.eku-cs.crt" \
+            0 \
+            -s "bad certificate (usage extensions)" \
+            -S "Processing of the Certificate handshake message failed"
+
 # Tests for DHM parameters loading
 
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data
index 02a11c8..056310a 100644
--- a/tests/suites/test_suite_mpi.data
+++ b/tests/suites/test_suite_mpi.data
@@ -67,12 +67,18 @@
 Test mpi_read_write_string #9 (Empty MPI hex -> dec)
 mpi_read_write_string:16:"":10:"0":4:0:0
 
+Test mpi_read_write_string #9 (Empty MPI hex -> base 2)
+mpi_read_write_string:16:"":2:"0":4:0:0
+
 Test mpi_read_write_string #8 (Empty MPI dec -> hex)
 mpi_read_write_string:10:"":16:"":4:0:0
 
 Test mpi_read_write_string #9 (Empty MPI dec -> dec)
 mpi_read_write_string:10:"":10:"0":4:0:0
 
+Test mpi_read_write_string #9 (Empty MPI dec -> base 2)
+mpi_read_write_string:16:"":2:"0":4:0:0
+
 Test mpi_write_string #10 (Negative hex with odd number of digits)
 mpi_read_write_string:16:"-1":16:"":3:0:MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL
 
@@ -1216,9 +1222,15 @@
 Test mbedtls_mpi_mod_int: 0 (null) % 1
 mbedtls_mpi_mod_int:16:"":1:0:0
 
+Test mbedtls_mpi_mod_int: 0 (null) % 2
+mbedtls_mpi_mod_int:16:"":2:0:0
+
 Test mbedtls_mpi_mod_int: 0 (null) % -1
 mbedtls_mpi_mod_int:16:"":-1:0:MBEDTLS_ERR_MPI_NEGATIVE_VALUE
 
+Test mbedtls_mpi_mod_int: 0 (null) % -2
+mbedtls_mpi_mod_int:16:"":-2:0:MBEDTLS_ERR_MPI_NEGATIVE_VALUE
+
 Base test mbedtls_mpi_exp_mod #1
 mbedtls_mpi_exp_mod:10:"23":10:"13":10:"29":10:"24":0
 
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index a851d5c..19a1ae6 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -3429,3 +3429,24 @@
 
 Force a bad session id length
 force_bad_session_id_len
+
+Cookie parsing: nominal run
+cookie_parsing:"16fefd0000000000000000002F010000de000000000000011efefd7b7272727272727272727272727272727272727272727272727272727272727d00200000000000000000000000000000000000000000000000000000000000000000":MBEDTLS_ERR_SSL_INTERNAL_ERROR
+
+Cookie parsing: cookie_len overflow
+cookie_parsing:"16fefd000000000000000000ea010000de000000000000011efefd7b7272727272727272727272727272727272727272727272727272727272727db97b7373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737373737db963":MBEDTLS_ERR_SSL_DECODE_ERROR
+
+Cookie parsing: non-zero fragment offset
+cookie_parsing:"16fefd00000000000000000032010000de000072000000011efefd7b7272727272727272727272727272727272727272727272727272727272727d01730143":MBEDTLS_ERR_SSL_DECODE_ERROR
+
+Cookie parsing: sid_len overflow
+cookie_parsing:"16fefd00000000000000000032010000de000000000000011efefd7b7272727272727272727272727272727272727272727272727272727272727dFF730143":MBEDTLS_ERR_SSL_DECODE_ERROR
+
+Cookie parsing: record too short
+cookie_parsing:"16fefd0000000000000000002f010000de000000000000011efefd7b7272727272727272727272727272727272727272727272727272727272727dFF":MBEDTLS_ERR_SSL_DECODE_ERROR
+
+Cookie parsing: one byte overread
+cookie_parsing:"16fefd0000000000000000002F010000de000000000000011efefd7b7272727272727272727272727272727272727272727272727272727272727d0001":MBEDTLS_ERR_SSL_DECODE_ERROR
+
+TLS 1.3 srv Certificate msg - wrong vector lengths
+tls13_server_certificate_msg_invalid_vector_len
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index c65b565..9a031b6 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -139,6 +139,23 @@
     (void) opts;
 #endif
 }
+
+#if defined(MBEDTLS_TEST_HOOKS)
+static void set_chk_buf_ptr_args(
+    mbedtls_ssl_chk_buf_ptr_args *args,
+    unsigned char *cur, unsigned char *end, size_t need )
+{
+    args->cur = cur;
+    args->end = end;
+    args->need = need;
+}
+
+static void reset_chk_buf_ptr_args( mbedtls_ssl_chk_buf_ptr_args *args )
+{
+    memset( args, 0, sizeof( *args ) );
+}
+#endif /* MBEDTLS_TEST_HOOKS */
+
 /*
  * Buffer structure for custom I/O callbacks.
  */
@@ -2383,6 +2400,119 @@
 }
 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
 
+#if defined(MBEDTLS_TEST_HOOKS)
+/*
+ * Tweak vector lengths in a TLS 1.3 Certificate message
+ *
+ * \param[in]       buf    Buffer containing the Certificate message to tweak
+ * \param[in]]out]  end    End of the buffer to parse
+ * \param           tweak  Tweak identifier (from 1 to the number of tweaks).
+ * \param[out]  expected_result  Error code expected from the parsing function
+ * \param[out]  args  Arguments of the MBEDTLS_SSL_CHK_BUF_READ_PTR call that
+ *                    is expected to fail. All zeroes if no
+ *                    MBEDTLS_SSL_CHK_BUF_READ_PTR failure is expected.
+ */
+int tweak_tls13_certificate_msg_vector_len(
+    unsigned char *buf, unsigned char **end, int tweak,
+    int *expected_result, mbedtls_ssl_chk_buf_ptr_args *args )
+{
+/*
+ * The definition of the tweaks assume that the certificate list contains only
+ * one certificate.
+ */
+
+/*
+ * struct {
+ *     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;
+ */
+    unsigned char *p_certificate_request_context_len = buf;
+    size_t certificate_request_context_len = buf[0];
+
+    unsigned char *p_certificate_list_len = buf + 1 + certificate_request_context_len;
+    unsigned char *certificate_list = p_certificate_list_len + 3;
+    size_t certificate_list_len = MBEDTLS_GET_UINT24_BE( p_certificate_list_len, 0 );
+
+    unsigned char *p_cert_data_len = certificate_list;
+    unsigned char *cert_data = p_cert_data_len + 3;
+    size_t cert_data_len = MBEDTLS_GET_UINT24_BE( p_cert_data_len, 0 );
+
+    unsigned char *p_extensions_len = cert_data + cert_data_len;
+    unsigned char *extensions = p_extensions_len + 2;
+    size_t extensions_len = MBEDTLS_GET_UINT16_BE( p_extensions_len, 0 );
+
+    *expected_result = MBEDTLS_ERR_SSL_DECODE_ERROR;
+
+    switch( tweak )
+    {
+        case 1:
+        /* Failure when checking if the certificate request context length and
+         * certificate list length can be read
+         */
+        *end = buf + 3;
+        set_chk_buf_ptr_args( args, buf, *end, 4 );
+        break;
+
+        case 2:
+        /* Invalid certificate request context length.
+         */
+        *p_certificate_request_context_len =
+            certificate_request_context_len + 1;
+        reset_chk_buf_ptr_args( args );
+        break;
+
+        case 3:
+        /* Failure when checking if certificate_list data can be read. */
+        MBEDTLS_PUT_UINT24_BE( certificate_list_len + 1,
+                               p_certificate_list_len, 0 );
+        set_chk_buf_ptr_args( args, certificate_list, *end,
+                              certificate_list_len + 1 );
+        break;
+
+        case 4:
+        /* Failure when checking if the cert_data length can be read. */
+        MBEDTLS_PUT_UINT24_BE( 2, p_certificate_list_len, 0 );
+        set_chk_buf_ptr_args( args, p_cert_data_len, certificate_list + 2, 3 );
+        break;
+
+        case 5:
+        /* Failure when checking if cert_data data can be read. */
+        MBEDTLS_PUT_UINT24_BE( certificate_list_len - 3 + 1,
+                               p_cert_data_len, 0 );
+        set_chk_buf_ptr_args( args, cert_data,
+                              certificate_list + certificate_list_len,
+                              certificate_list_len - 3 + 1 );
+        break;
+
+        case 6:
+        /* Failure when checking if the extensions length can be read. */
+        MBEDTLS_PUT_UINT24_BE( certificate_list_len - extensions_len - 1,
+                               p_certificate_list_len, 0 );
+        set_chk_buf_ptr_args( args, p_extensions_len,
+            certificate_list + certificate_list_len - extensions_len - 1, 2 );
+        break;
+
+        case 7:
+        /* Failure when checking if extensions data can be read. */
+        MBEDTLS_PUT_UINT16_BE( extensions_len + 1, p_extensions_len, 0 );
+
+        set_chk_buf_ptr_args( args, extensions,
+            certificate_list + certificate_list_len, extensions_len + 1 );
+        break;
+
+        default:
+        return( -1 );
+    }
+
+    return( 0 );
+}
+#endif /* MBEDTLS_TEST_HOOKS */
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -5574,6 +5704,34 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE:MBEDTLS_TEST_HOOKS */
+void cookie_parsing( data_t *cookie, int exp_ret )
+{
+    mbedtls_ssl_context ssl;
+    mbedtls_ssl_config conf;
+    size_t len;
+
+    mbedtls_ssl_init( &ssl );
+    mbedtls_ssl_config_init( &conf );
+    TEST_EQUAL( mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_SERVER,
+                                             MBEDTLS_SSL_TRANSPORT_DATAGRAM,
+                                             MBEDTLS_SSL_PRESET_DEFAULT ),
+                0 );
+
+    TEST_EQUAL( mbedtls_ssl_setup( &ssl, &conf ), 0 );
+    TEST_EQUAL( mbedtls_ssl_check_dtls_clihlo_cookie( &ssl, ssl.cli_id,
+                                                  ssl.cli_id_len,
+                                                  cookie->x, cookie->len,
+                                                  ssl.out_buf,
+                                                  MBEDTLS_SSL_OUT_CONTENT_LEN,
+                                                  &len ),
+                exp_ret );
+
+    mbedtls_ssl_free( &ssl );
+    mbedtls_ssl_config_free( &conf );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_TIMING_C:MBEDTLS_HAVE_TIME */
 void timing_final_delay_accessor( )
 {
@@ -5735,3 +5893,95 @@
     USE_PSA_DONE( );
 }
 /* END_CASE */
+/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS:MBEDTLS_SSL_PROTO_TLS1_3:!MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_SRV_C:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+void tls13_server_certificate_msg_invalid_vector_len( )
+{
+    int ret = -1;
+    mbedtls_endpoint client_ep, server_ep;
+    unsigned char *buf, *end;
+    size_t buf_len;
+    int step = 0;
+    int expected_result;
+    mbedtls_ssl_chk_buf_ptr_args expected_chk_buf_ptr_args;
+    handshake_test_options client_options;
+    handshake_test_options server_options;
+
+    /*
+     * Test set-up
+     */
+    USE_PSA_INIT( );
+
+    init_handshake_options( &client_options );
+    client_options.pk_alg = MBEDTLS_PK_ECDSA;
+    ret = mbedtls_endpoint_init( &client_ep, MBEDTLS_SSL_IS_CLIENT,
+                                 &client_options, NULL, NULL, NULL, NULL );
+    TEST_EQUAL( ret, 0 );
+
+    init_handshake_options( &server_options );
+    server_options.pk_alg = MBEDTLS_PK_ECDSA;
+    ret = mbedtls_endpoint_init( &server_ep, MBEDTLS_SSL_IS_SERVER,
+                                 &server_options, NULL, NULL, NULL, NULL );
+    TEST_EQUAL( ret, 0 );
+
+    ret = mbedtls_mock_socket_connect( &(client_ep.socket),
+                                       &(server_ep.socket), 1024 );
+    TEST_EQUAL( ret, 0 );
+
+    while( 1 )
+    {
+        mbedtls_test_set_step( ++step );
+
+        ret = mbedtls_move_handshake_to_state( &(server_ep.ssl),
+                                               &(client_ep.ssl),
+                                               MBEDTLS_SSL_CERTIFICATE_VERIFY );
+        TEST_EQUAL( ret, 0 );
+
+        ret = mbedtls_ssl_flush_output( &(server_ep.ssl) );
+        TEST_EQUAL( ret, 0 );
+
+        ret = mbedtls_move_handshake_to_state( &(client_ep.ssl),
+                                               &(server_ep.ssl),
+                                               MBEDTLS_SSL_SERVER_CERTIFICATE );
+        TEST_EQUAL( ret, 0 );
+
+        ret = mbedtls_ssl_tls13_fetch_handshake_msg( &(client_ep.ssl),
+                                                     MBEDTLS_SSL_HS_CERTIFICATE,
+                                                     &buf, &buf_len );
+        TEST_EQUAL( ret, 0 );
+
+        end = buf + buf_len;
+
+        /*
+         * Tweak server Certificate message and parse it.
+         */
+
+        ret = tweak_tls13_certificate_msg_vector_len(
+            buf, &end, step, &expected_result, &expected_chk_buf_ptr_args );
+
+        if( ret != 0 )
+            break;
+
+        ret = mbedtls_ssl_tls13_parse_certificate( &(client_ep.ssl), buf, end );
+        TEST_EQUAL( ret, expected_result );
+
+        TEST_ASSERT( mbedtls_ssl_cmp_chk_buf_ptr_fail_args(
+                         &expected_chk_buf_ptr_args ) == 0 );
+
+        mbedtls_ssl_reset_chk_buf_ptr_fail_args( );
+
+        ret = mbedtls_ssl_session_reset( &(client_ep.ssl) );
+        TEST_EQUAL( ret, 0 );
+
+        ret = mbedtls_ssl_session_reset( &(server_ep.ssl) );
+        TEST_EQUAL( ret, 0 );
+    }
+
+exit:
+    mbedtls_ssl_reset_chk_buf_ptr_fail_args( );
+    mbedtls_endpoint_free( &client_ep, NULL );
+    mbedtls_endpoint_free( &server_ep, NULL );
+    free_handshake_options( &client_options );
+    free_handshake_options( &server_options );
+    USE_PSA_DONE( );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data
index da12382..e4ffded 100644
--- a/tests/suites/test_suite_version.data
+++ b/tests/suites/test_suite_version.data
@@ -1,8 +1,8 @@
 Check compile time library version
-check_compiletime_version:"3.1.0"
+check_compiletime_version:"3.2.0"
 
 Check runtime library version
-check_runtime_version:"3.1.0"
+check_runtime_version:"3.2.0"
 
 Check for MBEDTLS_VERSION_C
 check_feature:"MBEDTLS_VERSION_C":0