Merge pull request #5970 from gabor-mezei-arm/5229_Send_dummy_change_cipher_spec_records_from_server

TLS 1.3 server: Send dummy change_cipher_spec records

The internal CI PR-merge job ran successfully thus good to go.
diff --git a/ChangeLog.d/add_dn_get_next.txt b/ChangeLog.d/add_dn_get_next.txt
new file mode 100644
index 0000000..04ee954
--- /dev/null
+++ b/ChangeLog.d/add_dn_get_next.txt
@@ -0,0 +1,3 @@
+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
index 8d341df..4b8117f 100644
--- a/ChangeLog.d/add_final_delay_accessor
+++ b/ChangeLog.d/add_final_delay_accessor
@@ -1,4 +1,4 @@
 Features
-   * Add the function mbedtls_timing_get_final_delay() to access the private
+   * Add function mbedtls_timing_get_final_delay() to access the private
      final delay field in an mbedtls_timing_delay_context, as requested in
-     #5183
+     #5183.
diff --git a/ChangeLog.d/add_handshake_completion_accessor b/ChangeLog.d/add_handshake_completion_accessor
index e2b28cf..c06a539 100644
--- a/ChangeLog.d/add_handshake_completion_accessor
+++ b/ChangeLog.d/add_handshake_completion_accessor
@@ -1,4 +1,4 @@
 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
+     mbedtls_ssl_handshake_step(), requested in #4383.
diff --git a/ChangeLog.d/add_own_cid_accessors b/ChangeLog.d/add_own_cid_accessors
index fb02868..553299c 100644
--- a/ChangeLog.d/add_own_cid_accessors
+++ b/ChangeLog.d/add_own_cid_accessors
@@ -1,4 +1,4 @@
 Features
    * Add the function mbedtls_ssl_get_own_cid() to access our own connection id
-     within mbedtls_ssl_context, as requested in #5184
+     within mbedtls_ssl_context, as requested in #5184.
 
diff --git a/ChangeLog.d/bug_order_x448.txt b/ChangeLog.d/bug_order_x448.txt
new file mode 100644
index 0000000..cebefc4
--- /dev/null
+++ b/ChangeLog.d/bug_order_x448.txt
@@ -0,0 +1,2 @@
+Bugfix
+    * Fix order value of curve x448.
diff --git a/ChangeLog.d/cmake_add_subdirectory_support.txt b/ChangeLog.d/cmake_add_subdirectory_support.txt
index afcc4b6..f14f3f8 100644
--- a/ChangeLog.d/cmake_add_subdirectory_support.txt
+++ b/ChangeLog.d/cmake_add_subdirectory_support.txt
@@ -1,4 +1,4 @@
 Changes
-   * Add aliases for libraries so that the normal MbedTLS::* targets
-     work when MbedTLS is built as a subdirectory.  Allows use of
-     CMake's FetchContent, as requested in #5688.
+   * 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
index df51c65..7f407c4 100644
--- a/ChangeLog.d/cmake_fix_dll_install.txt
+++ b/ChangeLog.d/cmake_fix_dll_install.txt
@@ -1,3 +1,3 @@
 Changes
-   * cmake: Fix runtime library install location in mingw
-     This install DLLs in bin directory instead of lib.
+   * 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/deprecate_mbedtls_cipher_setup_psa.txt b/ChangeLog.d/deprecate_mbedtls_cipher_setup_psa.txt
index 782b751..b145243 100644
--- a/ChangeLog.d/deprecate_mbedtls_cipher_setup_psa.txt
+++ b/ChangeLog.d/deprecate_mbedtls_cipher_setup_psa.txt
@@ -1,3 +1,3 @@
 New deprecations
-   * Deprecate mbedtls_cipher_setup_psa() function.
-     Use psa_aead_xxx() / psa_cipher_xxx() directly instead.
+   * Deprecate mbedtls_cipher_setup_psa(). Use psa_aead_xxx() or
+     psa_cipher_xxx() directly instead.
diff --git a/ChangeLog.d/fix-csr_subject_commas.txt b/ChangeLog.d/fix-csr_subject_commas.txt
new file mode 100644
index 0000000..e01c9a8
--- /dev/null
+++ b/ChangeLog.d/fix-csr_subject_commas.txt
@@ -0,0 +1,3 @@
+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
index 4746c7b..112fa85 100644
--- a/ChangeLog.d/fix-parllel-cmake-build-fail.txt
+++ b/ChangeLog.d/fix-parllel-cmake-build-fail.txt
@@ -1,3 +1,3 @@
 Bugfix
    * Fix a race condition in out-of-source builds with CMake when generated data
-     files are already present. Fixes #5374
+     files are already present. Fixes #5374.
diff --git a/ChangeLog.d/fix-windows-cmake-build-with-shared-libraries.txt b/ChangeLog.d/fix-windows-cmake-build-with-shared-libraries.txt
index 6878645..a6540a1 100644
--- a/ChangeLog.d/fix-windows-cmake-build-with-shared-libraries.txt
+++ b/ChangeLog.d/fix-windows-cmake-build-with-shared-libraries.txt
@@ -1,3 +1,3 @@
 Bugfix
-   * Fix compilation on Windows when building shared library, by setting
-     library search path to CMAKE_CURRENT_BINARY_DIR.
+   * 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
index af60465..bf5d6ac 100644
--- a/ChangeLog.d/fix-x25519-program.txt
+++ b/ChangeLog.d/fix-x25519-program.txt
@@ -1,4 +1,4 @@
 Bugfix
-   * Fix a bug in x25519 example program where the removal of
+   * 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/mbedtls_ecp_export.txt b/ChangeLog.d/mbedtls_ecp_export.txt
index 4b5d7d4..5dce5b4 100644
--- a/ChangeLog.d/mbedtls_ecp_export.txt
+++ b/ChangeLog.d/mbedtls_ecp_export.txt
@@ -1,3 +1,3 @@
 Features
-   * Add mbedtls_ecp_export() function to export ECP
-     keypair parameters. Fixes #4838.
+   * Add function mbedtls_ecp_export() to export ECP key pair parameters.
+     Fixes #4838.
diff --git a/ChangeLog.d/mbedtls_sha256_a64_crypto_acceleration.txt b/ChangeLog.d/mbedtls_sha256_a64_crypto_acceleration.txt
deleted file mode 100644
index 865b337..0000000
--- a/ChangeLog.d/mbedtls_sha256_a64_crypto_acceleration.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Features
-   * A64 SHA-2 crypto extension support for SHA-256
diff --git a/ChangeLog.d/mbedtls_sha2_a64_crypto_acceleration.txt b/ChangeLog.d/mbedtls_sha2_a64_crypto_acceleration.txt
new file mode 100644
index 0000000..a6e7f6d
--- /dev/null
+++ b/ChangeLog.d/mbedtls_sha2_a64_crypto_acceleration.txt
@@ -0,0 +1,3 @@
+Features
+   * Add support for the ARMv8 SHA-2 acceleration instructions when building
+     for Aarch64.
diff --git a/ChangeLog.d/mbedtls_sha512_a64_crypto_acceleration.txt b/ChangeLog.d/mbedtls_sha512_a64_crypto_acceleration.txt
deleted file mode 100644
index 01be0b3..0000000
--- a/ChangeLog.d/mbedtls_sha512_a64_crypto_acceleration.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Features
-   * A64 crypto extension support for SHA-512
diff --git a/ChangeLog.d/mbedtls_ssl_comfig_defaults-memleak.txt b/ChangeLog.d/mbedtls_ssl_comfig_defaults-memleak.txt
index d55c016..043b273 100644
--- a/ChangeLog.d/mbedtls_ssl_comfig_defaults-memleak.txt
+++ b/ChangeLog.d/mbedtls_ssl_comfig_defaults-memleak.txt
@@ -1,2 +1,2 @@
 Bugfix
-   * Fix memory leak if mbedtls_ssl_config_defaults() call is repeated
+   * Fix a memory leak if mbedtls_ssl_config_defaults() is called twice.
diff --git a/ChangeLog.d/mbedtls_ssl_tls13_client.txt b/ChangeLog.d/mbedtls_ssl_tls13_client.txt
index 855945b..57a26e1 100644
--- a/ChangeLog.d/mbedtls_ssl_tls13_client.txt
+++ b/ChangeLog.d/mbedtls_ssl_tls13_client.txt
@@ -1,4 +1,2 @@
 Features
-   * Add ALPN support in tls13 client. Client is able to write ALPN extension
-     in client hello, and able to parse the response from server encrypted
-     extension.
+   * Add ALPN support in TLS 1.3 clients.
diff --git a/ChangeLog.d/mbedtls_tlsver_enum.txt b/ChangeLog.d/mbedtls_tlsver_enum.txt
index 16435c6..c027ab7 100644
--- a/ChangeLog.d/mbedtls_tlsver_enum.txt
+++ b/ChangeLog.d/mbedtls_tlsver_enum.txt
@@ -1,6 +1,10 @@
+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
-   * Unify internal/external TLS protocol version enums
-   * Deprecate mbedtls_ssl_conf_max_version()
-     Replaced with mbedtls_ssl_conf_max_tls_version()
-   * Deprecate mbedtls_ssl_conf_min_version()
-     Replaced with mbedtls_ssl_conf_min_tls_version()
+   * 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
index f8ec1a0..aa61e1a 100644
--- a/ChangeLog.d/md_info_from_ctx.txt
+++ b/ChangeLog.d/md_info_from_ctx.txt
@@ -1,3 +1,3 @@
 Features
-   * Add a function to extract message digest information from a message
-     digest context.
+   * 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/psa_aead_singleshot_error.txt b/ChangeLog.d/psa_aead_singleshot_error.txt
index 7243874..ccf1d4c 100644
--- a/ChangeLog.d/psa_aead_singleshot_error.txt
+++ b/ChangeLog.d/psa_aead_singleshot_error.txt
@@ -1,4 +1,4 @@
 Changes
-   * Return PSA_ERROR_INVALID_ARGUMENT if the algorithm passed to singleshot
+   * 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 spec.
+     multipart functions, and the PSA Crypto API 1.1 specification.
diff --git a/ChangeLog.d/psa_crypto_reduced_configs.txt b/ChangeLog.d/psa_crypto_reduced_configs.txt
deleted file mode 100644
index 5bc9bc1..0000000
--- a/ChangeLog.d/psa_crypto_reduced_configs.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Changes
-   * Automatically enable MBEDTLS_PK_WRITE_C if MBEDTLS_PK_C and
-     MBEDTLS_USE_PSA_CRYPTO are enabled. This is due to ecdsa_verify_wrap
-     requirements, but will also probably be needed by RSA soon, hence the
-     broader PK_C requirement.
diff --git a/ChangeLog.d/psk_to_ms_mixed_psk.txt b/ChangeLog.d/psk_to_ms_mixed_psk.txt
index b189661..998cc11 100644
--- a/ChangeLog.d/psk_to_ms_mixed_psk.txt
+++ b/ChangeLog.d/psk_to_ms_mixed_psk.txt
@@ -1,4 +1,4 @@
 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
+      mixed-PSK. Add an optional input PSA_KEY_DERIVATION_INPUT_OTHER_SECRET
       holding the other secret.
diff --git a/ChangeLog.d/raw-agreement-destroy-missing.txt b/ChangeLog.d/raw-agreement-destroy-missing.txt
deleted file mode 100644
index 7342b8c..0000000
--- a/ChangeLog.d/raw-agreement-destroy-missing.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-Bugfix
-   * Add missing key slot destruction calls when a raw key agreement or
-     a public key export fails in ssl_write_client_key_exchange.
diff --git a/ChangeLog.d/tls13-fix-finished-fetch.txt b/ChangeLog.d/tls13-fix-finished-fetch.txt
index 28c30f9..9a8acb3 100644
--- a/ChangeLog.d/tls13-fix-finished-fetch.txt
+++ b/ChangeLog.d/tls13-fix-finished-fetch.txt
@@ -1,5 +1,3 @@
 Bugfix
-   * Fix handshake failure when the peer Finished message has not been received
-     yet when we first try to fetch it. The fetching is moved before the
-     preprocessing computations to avoid doing them multiple times, which was
-     causing the handshake to fail.
+   * 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/use-psa-ecdhe-curve.txt b/ChangeLog.d/use-psa-ecdhe-curve.txt
index cc432bd..658f88f 100644
--- a/ChangeLog.d/use-psa-ecdhe-curve.txt
+++ b/ChangeLog.d/use-psa-ecdhe-curve.txt
@@ -4,4 +4,4 @@
      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.
+     according to its configuration. Fixes #5291.
diff --git a/docs/architecture/tls13-support.md b/docs/architecture/tls13-support.md
index 2cf2a48..6c39bc5 100644
--- a/docs/architecture/tls13-support.md
+++ b/docs/architecture/tls13-support.md
@@ -409,3 +409,101 @@
                                      buf_len );
     ```
     even if it fits.
+
+
+Overview of handshake code organization
+---------------------------------------
+
+The TLS 1.3 handshake protocol is implemented as a state machine. The
+functions `mbedtls_ssl_tls13_handshake_{client,server}_step` are the top level
+functions of that implementation. They are implemented as a switch over all the
+possible states of the state machine.
+
+Most of the states are either dedicated to the processing or writing of an
+handshake message.
+
+The implementation does not go systematically through all states as this would
+result in too many checks of whether something needs to be done or not in a
+given state to be duplicated across several state handlers. For example, on
+client side, the states related to certificate parsing and validation are
+bypassed if the handshake is based on a pre-shared key and thus does not
+involve certificates.
+
+On the contrary, the implementation goes systematically though some states
+even if they could be bypassed if it helps in minimizing when and where inbound
+and outbound keys are updated. The `MBEDTLS_SSL_CLIENT_CERTIFICATE` state on
+client side is a example of that.
+
+The names of the handlers processing/writing an handshake message are
+prefixed with `(mbedtls_)ssl_tls13_{process,write}`. To ease the maintenance and
+reduce the risk of bugs, the code of the message processing and writing
+handlers is split into a sequence of stages.
+
+The sending of data to the peer only occurs in `mbedtls_ssl_handshake_step`
+between the calls to the handlers and as a consequence handlers do not have to
+care about the MBEDTLS_ERR_SSL_WANT_WRITE error code. Furthermore, all pending
+data are flushed before to call the next handler. That way, handlers do not
+have to worry about pending data when changing outbound keys.
+
+### Message processing handlers
+For message processing handlers, the stages are:
+
+* coordination stage: check if the state should be bypassed. This stage is
+optional. The check is either purely based on the reading of the value of some
+fields of the SSL context or based on the reading of the type of the next
+message. The latter occurs when it is not known what the next handshake message
+will be, an example of that on client side being if we are going to receive a
+CertificateRequest message or not. The intent is, apart from the next record
+reading to not modify the SSL context as this stage may be repeated if the
+next handshake message has not been received yet.
+
+* fetching stage: at this stage we are sure of the type of the handshake
+message we must receive next and we try to fetch it. If we did not go through
+a coordination stage involving the next record type reading, the next
+handshake message may not have been received yet, the handler returns with
+`MBEDTLS_ERR_SSL_WANT_READ` without changing the current state and it will be
+called again later.
+
+* pre-processing stage: prepare the SSL context for the message parsing. This
+stage is optional. Any processing that must be done before the parsing of the
+message or that can be done to simplify the parsing code. Some simple and
+partial parsing of the handshake message may append at that stage like in the
+ServerHello message pre-processing.
+
+* parsing stage: parse the message and restrict as much as possible any
+update of the SSL context. The idea of the pre-processing/parsing/post-processing
+organization is to concentrate solely on the parsing in the parsing function to
+reduce the size of its code and to simplify it.
+
+* post-processing stage: following the parsing, further update of the SSL
+context to prepare for the next incoming and outgoing messages. This stage is
+optional. For example, secret and key computations occur at this stage, as well
+as handshake messages checksum update.
+
+* state change: the state change is done in the main state handler to ease the
+navigation of the state machine transitions.
+
+
+### Message writing handlers
+For message writing handlers, the stages are:
+
+* coordination stage: check if the state should be bypassed. This stage is
+optional. The check is based on the value of some fields of the SSL context.
+
+* preparation stage: prepare for the message writing. This stage is optional.
+Any processing that must be done before the writing of the message or that can
+be done to simplify the writing code.
+
+* writing stage: write the message and restrict as much as possible any update
+of the SSL context. The idea of the preparation/writing/finalization
+organization is to concentrate solely on the writing in the writing function to
+reduce the size of its code and simplify it.
+
+* finalization stage: following the writing, further update of the SSL
+context to prepare for the next incoming and outgoing messages. This stage is
+optional. For example, handshake secret and key computation occur at that
+stage (ServerHello writing finalization), switching to handshake keys for
+outbound message on server side as well.
+
+* state change: the state change is done in the main state handler to ease
+the navigation of the state machine transitions.
diff --git a/include/mbedtls/config_psa.h b/include/mbedtls/config_psa.h
index ac7b7e8..b469d3c 100644
--- a/include/mbedtls/config_psa.h
+++ b/include/mbedtls/config_psa.h
@@ -611,6 +611,10 @@
 #define PSA_WANT_ALG_HMAC 1
 #define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1
 #define PSA_WANT_ALG_HKDF 1
+#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1
+#define PSA_WANT_ALG_HKDF_EXTRACT 1
+#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1
+#define PSA_WANT_ALG_HKDF_EXPAND 1
 #endif /* MBEDTLS_HKDF_C */
 
 #if defined(MBEDTLS_MD_C)
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index 9c8ec11..e3e168b 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -2813,9 +2813,9 @@
 /**
  * \def MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
  *
- * Enable acceleration of the SHA-256 cryptographic hash algorithm with the
- * Arm A64 cryptographic extensions if they are available at runtime. If not,
- * it will fall back to the C implementation.
+ * Enable acceleration of the SHA-256 and SHA-224 cryptographic hash algorithms
+ * with the ARMv8 cryptographic extensions if they are available at runtime.
+ * If not, the library will fall back to the C implementation.
  *
  * \note If MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT is defined when building
  * for a non-Aarch64 build it will be silently ignored.
@@ -2838,9 +2838,9 @@
 /**
  * \def MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY
  *
- * Enable acceleration of the SHA-256 cryptographic hash algorithm with the
- * Arm A64 cryptographic extensions, which must be available at runtime (or
- * an illegal instruction fault will occur).
+ * Enable acceleration of the SHA-256 and SHA-224 cryptographic hash algorithms
+ * with the ARMv8 cryptographic extensions, which must be available at runtime
+ * or else an illegal instruction fault will occur.
  *
  * \note This allows builds with a smaller code size than with
  * MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
@@ -2896,9 +2896,9 @@
 /**
  * \def MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
  *
- * Enable acceleration of the SHA-512 cryptographic hash algorithm with the
- * Arm A64 cryptographic extensions if they are available at runtime. If not,
- * it will fall back to the C implementation.
+ * Enable acceleration of the SHA-512 and SHA-384 cryptographic hash algorithms
+ * with the ARMv8 cryptographic extensions if they are available at runtime.
+ * If not, the library will fall back to the C implementation.
  *
  * \note If MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT is defined when building
  * for a non-Aarch64 build it will be silently ignored.
@@ -2923,9 +2923,9 @@
 /**
  * \def MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY
  *
- * Enable acceleration of the SHA-512 cryptographic hash algorithm with the
- * Arm A64 cryptographic extensions, which must be available at runtime (or
- * an illegal instruction fault will occur).
+ * Enable acceleration of the SHA-512 and SHA-384 cryptographic hash algorithms
+ * with the ARMv8 cryptographic extensions, which must be available at runtime
+ * or else an illegal instruction fault will occur.
  *
  * \note This allows builds with a smaller code size than with
  * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
diff --git a/include/mbedtls/x509.h b/include/mbedtls/x509.h
index 3c76fec..213efa0 100644
--- a/include/mbedtls/x509.h
+++ b/include/mbedtls/x509.h
@@ -267,6 +267,25 @@
 int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn );
 
 /**
+ * \brief          Return the next relative DN in an X509 name.
+ *
+ * \note           Intended use is to compare function result to dn->next
+ *                 in order to detect boundaries of multi-valued RDNs.
+ *
+ * \param dn       Current node in the X509 name
+ *
+ * \return         Pointer to the first attribute-value pair of the
+ *                 next RDN in sequence, or NULL if end is reached.
+ */
+static inline mbedtls_x509_name * mbedtls_x509_dn_get_next(
+    mbedtls_x509_name * dn )
+{
+    while( dn->MBEDTLS_PRIVATE(next_merged) && dn->next != NULL )
+        dn = dn->next;
+    return( dn->next );
+}
+
+/**
  * \brief          Store the certificate serial in printable form into buf;
  *                 no more than size characters will be written.
  *
diff --git a/library/ecp_curves.c b/library/ecp_curves.c
index 6b8ff5c..51956cd 100644
--- a/library/ecp_curves.c
+++ b/library/ecp_curves.c
@@ -4737,6 +4737,8 @@
     ECP_VALIDATE_RET( grp != NULL );
     mbedtls_ecp_group_free( grp );
 
+    mbedtls_ecp_group_init( grp );
+
     grp->id = id;
 
     switch( id )
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index b1f0c90..119826f 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -2280,4 +2280,16 @@
                                            mbedtls_pk_context *own_key,
                                            uint16_t *algorithm );
 
+#if defined(MBEDTLS_SSL_ALPN)
+int mbedtls_ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
+                                const unsigned char *buf,
+                                const unsigned char *end );
+
+
+int mbedtls_ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
+                                unsigned char *buf,
+                                unsigned char *end,
+                                size_t *out_len );
+#endif /* MBEDTLS_SSL_ALPN */
+
 #endif /* ssl_misc.h */
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 8332461..5fa02d2 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -6139,7 +6139,7 @@
         ssl->in_msg[0]  == MBEDTLS_SSL_HS_CERTIFICATE   &&
         memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer has no certificate" ) );
         return( 0 );
     }
     return( -1 );
@@ -8285,4 +8285,125 @@
 }
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
+#if defined(MBEDTLS_SSL_ALPN)
+int mbedtls_ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
+                                const unsigned char *buf,
+                                const unsigned char *end )
+{
+    const unsigned char *p = buf;
+    size_t protocol_name_list_len;
+    const unsigned char *protocol_name_list;
+    const unsigned char *protocol_name_list_end;
+    size_t protocol_name_len;
+
+    /* If ALPN not configured, just ignore the extension */
+    if( ssl->conf->alpn_list == NULL )
+        return( 0 );
+
+    /*
+     * RFC7301, section 3.1
+     *      opaque ProtocolName<1..2^8-1>;
+     *
+     *      struct {
+     *          ProtocolName protocol_name_list<2..2^16-1>
+     *      } ProtocolNameList;
+     */
+
+    /*
+     * protocol_name_list_len    2 bytes
+     * protocol_name_len         1 bytes
+     * protocol_name             >=1 byte
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 4 );
+
+    protocol_name_list_len = MBEDTLS_GET_UINT16_BE( p, 0 );
+    p += 2;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, protocol_name_list_len );
+    protocol_name_list = p;
+    protocol_name_list_end = p + protocol_name_list_len;
+
+    /* Validate peer's list (lengths) */
+    while( p < protocol_name_list_end )
+    {
+        protocol_name_len = *p++;
+        MBEDTLS_SSL_CHK_BUF_READ_PTR( p, protocol_name_list_end,
+                                      protocol_name_len );
+        if( protocol_name_len == 0 )
+        {
+            MBEDTLS_SSL_PEND_FATAL_ALERT(
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+            return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
+        }
+
+        p += protocol_name_len;
+    }
+
+    /* Use our order of preference */
+    for( const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++ )
+    {
+        size_t const alpn_len = strlen( *alpn );
+        p = protocol_name_list;
+        while( p < protocol_name_list_end )
+        {
+            protocol_name_len = *p++;
+            if( protocol_name_len == alpn_len &&
+                memcmp( p, *alpn, alpn_len ) == 0 )
+            {
+                ssl->alpn_chosen = *alpn;
+                return( 0 );
+            }
+
+            p += protocol_name_len;
+        }
+    }
+
+    /* If we get here, no match was found */
+    MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL,
+            MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL );
+    return( MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL );
+}
+
+int mbedtls_ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
+                                unsigned char *buf,
+                                unsigned char *end,
+                                size_t *out_len )
+{
+    unsigned char *p = buf;
+    size_t protocol_name_len;
+    *out_len = 0;
+
+    if( ssl->alpn_chosen == NULL )
+    {
+        return( 0 );
+    }
+
+    protocol_name_len = strlen( ssl->alpn_chosen );
+    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 7 + protocol_name_len );
+
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server side, adding alpn extension" ) );
+    /*
+     * 0 . 1    ext identifier
+     * 2 . 3    ext length
+     * 4 . 5    protocol list length
+     * 6 . 6    protocol name length
+     * 7 . 7+n  protocol name
+     */
+    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ALPN, p, 0 );
+
+    *out_len = 7 + protocol_name_len;
+
+    MBEDTLS_PUT_UINT16_BE( protocol_name_len + 3, p, 2 );
+    MBEDTLS_PUT_UINT16_BE( protocol_name_len + 1, p, 4 );
+    /* Note: the length of the chosen protocol has been checked to be less
+     * than 255 bytes in `mbedtls_ssl_conf_alpn_protocols`.
+     */
+    p[6] = MBEDTLS_BYTE_0( protocol_name_len );
+
+    memcpy( p + 7, ssl->alpn_chosen, protocol_name_len );
+    return ( 0 );
+}
+#endif /* MBEDTLS_SSL_ALPN */
+
 #endif /* MBEDTLS_SSL_TLS_C */
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index e92014c..21e5cda 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -528,94 +528,6 @@
 }
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-#if defined(MBEDTLS_SSL_ALPN)
-static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
-                               const unsigned char *buf, size_t len )
-{
-    size_t list_len, cur_len, ours_len;
-    const unsigned char *theirs, *start, *end;
-    const char **ours;
-
-    /* If ALPN not configured, just ignore the extension */
-    if( ssl->conf->alpn_list == NULL )
-        return( 0 );
-
-    /*
-     * opaque ProtocolName<1..2^8-1>;
-     *
-     * struct {
-     *     ProtocolName protocol_name_list<2..2^16-1>
-     * } ProtocolNameList;
-     */
-
-    /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */
-    if( len < 4 )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_DECODE_ERROR );
-    }
-
-    list_len = ( buf[0] << 8 ) | buf[1];
-    if( list_len != len - 2 )
-    {
-        mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-        return( MBEDTLS_ERR_SSL_DECODE_ERROR );
-    }
-
-    /*
-     * Validate peer's list (lengths)
-     */
-    start = buf + 2;
-    end = buf + len;
-    for( theirs = start; theirs != end; theirs += cur_len )
-    {
-        cur_len = *theirs++;
-
-        /* Current identifier must fit in list */
-        if( cur_len > (size_t)( end - theirs ) )
-        {
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
-            return( MBEDTLS_ERR_SSL_DECODE_ERROR );
-        }
-
-        /* Empty strings MUST NOT be included */
-        if( cur_len == 0 )
-        {
-            mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
-            return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
-        }
-    }
-
-    /*
-     * Use our order of preference
-     */
-    for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ )
-    {
-        ours_len = strlen( *ours );
-        for( theirs = start; theirs != end; theirs += cur_len )
-        {
-            cur_len = *theirs++;
-
-            if( cur_len == ours_len &&
-                memcmp( theirs, *ours, cur_len ) == 0 )
-            {
-                ssl->alpn_chosen = *ours;
-                return( 0 );
-            }
-        }
-    }
-
-    /* If we get there, no match was found */
-    mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                            MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL );
-    return( MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL );
-}
-#endif /* MBEDTLS_SSL_ALPN */
-
 #if defined(MBEDTLS_SSL_DTLS_SRTP)
 static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
                                    const unsigned char *buf,
@@ -1524,7 +1436,8 @@
             case MBEDTLS_TLS_EXT_ALPN:
                 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
 
-                ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size );
+                ret = mbedtls_ssl_parse_alpn_ext( ssl, ext + 4,
+                                                  ext + 4 + ext_size );
                 if( ret != 0 )
                     return( ret );
                 break;
@@ -2040,39 +1953,6 @@
 }
 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
-#if defined(MBEDTLS_SSL_ALPN )
-static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
-                                unsigned char *buf, size_t *olen )
-{
-    if( ssl->alpn_chosen == NULL )
-    {
-        *olen = 0;
-        return;
-    }
-
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) );
-
-    /*
-     * 0 . 1    ext identifier
-     * 2 . 3    ext length
-     * 4 . 5    protocol list length
-     * 6 . 6    protocol name length
-     * 7 . 7+n  protocol name
-     */
-    MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ALPN, buf, 0);
-
-    *olen = 7 + strlen( ssl->alpn_chosen );
-
-    MBEDTLS_PUT_UINT16_BE( *olen - 4, buf, 2 );
-
-    MBEDTLS_PUT_UINT16_BE( *olen - 6, buf, 4 );
-
-    buf[6] = MBEDTLS_BYTE_0( *olen - 7 );
-
-    memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 );
-}
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
-
 #if defined(MBEDTLS_SSL_DTLS_SRTP ) && defined(MBEDTLS_SSL_PROTO_DTLS)
 static void ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
                                     unsigned char *buf,
@@ -2446,7 +2326,8 @@
 #endif
 
 #if defined(MBEDTLS_SSL_ALPN)
-    ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen );
+    unsigned char *end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN - 4;
+    mbedtls_ssl_write_alpn_ext( ssl, p + 2 + ext_len, end, &olen );
     ext_len += olen;
 #endif
 
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index b498fd4..416316b 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -121,11 +121,12 @@
 
 #if defined(MBEDTLS_SSL_ALPN)
 static int ssl_tls13_parse_alpn_ext( mbedtls_ssl_context *ssl,
-                               const unsigned char *buf, size_t len )
+                                     const unsigned char *buf, size_t len )
 {
-    size_t list_len, name_len;
     const unsigned char *p = buf;
     const unsigned char *end = buf + len;
+    size_t protocol_name_list_len, protocol_name_len;
+    const unsigned char *protocol_name_list_end;
 
     /* If we didn't send it, the server shouldn't send it */
     if( ssl->conf->alpn_list == NULL )
@@ -141,21 +142,22 @@
      * the "ProtocolNameList" MUST contain exactly one "ProtocolName"
      */
 
-    /* Min length is 2 ( list_len ) + 1 ( name_len ) + 1 ( name ) */
-    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 4 );
-
-    list_len = MBEDTLS_GET_UINT16_BE( p, 0 );
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
+    protocol_name_list_len = MBEDTLS_GET_UINT16_BE( p, 0 );
     p += 2;
-    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, list_len );
 
-    name_len = *p++;
-    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, list_len - 1 );
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, protocol_name_list_len );
+    protocol_name_list_end = p + protocol_name_list_len;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, protocol_name_list_end, 1 );
+    protocol_name_len = *p++;
 
     /* Check that the server chosen protocol was in our list and save it */
-    for ( const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++ )
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, protocol_name_list_end, protocol_name_len );
+    for( const char **alpn = ssl->conf->alpn_list; *alpn != NULL; alpn++ )
     {
-        if( name_len == strlen( *alpn ) &&
-            memcmp( buf + 3, *alpn, name_len ) == 0 )
+        if( protocol_name_len == strlen( *alpn ) &&
+            memcmp( p, *alpn, protocol_name_len ) == 0 )
         {
             ssl->alpn_chosen = *alpn;
             return( 0 );
@@ -667,6 +669,7 @@
      * - cipher_suite               2 bytes
      * - legacy_compression_method  1 byte
      */
+     MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, legacy_session_id_echo_len + 4 );
      p += legacy_session_id_echo_len + 4;
 
     /* Case of no extension */
@@ -740,12 +743,12 @@
 }
 
 /* Returns a negative value on failure, and otherwise
- * - SSL_SERVER_HELLO_COORDINATE_HELLO or
- * - SSL_SERVER_HELLO_COORDINATE_HRR
+ * - SSL_SERVER_HELLO or
+ * - SSL_SERVER_HELLO_HRR
  * to indicate which message is expected and to be parsed next.
  */
-#define SSL_SERVER_HELLO_COORDINATE_HELLO 0
-#define SSL_SERVER_HELLO_COORDINATE_HRR 1
+#define SSL_SERVER_HELLO 0
+#define SSL_SERVER_HELLO_HRR 1
 static int ssl_server_hello_is_hrr( mbedtls_ssl_context *ssl,
                                     const unsigned char *buf,
                                     const unsigned char *end )
@@ -772,37 +775,32 @@
     if( memcmp( buf + 2, mbedtls_ssl_tls13_hello_retry_request_magic,
                 sizeof( mbedtls_ssl_tls13_hello_retry_request_magic ) ) == 0 )
     {
-        return( SSL_SERVER_HELLO_COORDINATE_HRR );
+        return( SSL_SERVER_HELLO_HRR );
     }
 
-    return( SSL_SERVER_HELLO_COORDINATE_HELLO );
+    return( SSL_SERVER_HELLO );
 }
 
-/* Fetch and preprocess
+/*
  * Returns a negative value on failure, and otherwise
- * - SSL_SERVER_HELLO_COORDINATE_HELLO or
- * - SSL_SERVER_HELLO_COORDINATE_HRR or
- * - SSL_SERVER_HELLO_COORDINATE_TLS1_2
+ * - SSL_SERVER_HELLO or
+ * - SSL_SERVER_HELLO_HRR or
+ * - SSL_SERVER_HELLO_TLS1_2
  */
-#define SSL_SERVER_HELLO_COORDINATE_TLS1_2 2
-static int ssl_tls13_server_hello_coordinate( mbedtls_ssl_context *ssl,
-                                              unsigned char **buf,
-                                              size_t *buf_len )
+#define SSL_SERVER_HELLO_TLS1_2 2
+static int ssl_tls13_preprocess_server_hello( mbedtls_ssl_context *ssl,
+                                              const unsigned char *buf,
+                                              const unsigned char *end )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    const unsigned char *end;
-
-    MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl,
-                                             MBEDTLS_SSL_HS_SERVER_HELLO,
-                                             buf, buf_len ) );
-    end = *buf + *buf_len;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
 
     MBEDTLS_SSL_PROC_CHK_NEG( ssl_tls13_is_supported_versions_ext_present(
-                                  ssl, *buf, end ) );
+                                  ssl, buf, end ) );
     if( ret == 0 )
     {
         MBEDTLS_SSL_PROC_CHK_NEG(
-            ssl_tls13_is_downgrade_negotiation( ssl, *buf, end ) );
+            ssl_tls13_is_downgrade_negotiation( ssl, buf, end ) );
 
         /* If the server is negotiating TLS 1.2 or below and:
          * . we did not propose TLS 1.2 or
@@ -810,7 +808,7 @@
          *   version of the protocol and thus we are under downgrade attack
          * abort the handshake with an "illegal parameter" alert.
          */
-        if( ssl->handshake->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 || ret )
+        if( handshake->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 || ret )
         {
             MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
                                           MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
@@ -820,7 +818,7 @@
         ssl->keep_current_message = 1;
         ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
         mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_SERVER_HELLO,
-                                            *buf, *buf_len );
+                                            buf, (size_t)(end - buf) );
 
         if( mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) )
         {
@@ -829,23 +827,25 @@
                 return( ret );
         }
 
-        return( SSL_SERVER_HELLO_COORDINATE_TLS1_2 );
+        return( SSL_SERVER_HELLO_TLS1_2 );
     }
 
-    ret = ssl_server_hello_is_hrr( ssl, *buf, end );
+    handshake->extensions_present = MBEDTLS_SSL_EXT_NONE;
+
+    ret = ssl_server_hello_is_hrr( ssl, buf, end );
     switch( ret )
     {
-        case SSL_SERVER_HELLO_COORDINATE_HELLO:
+        case SSL_SERVER_HELLO:
             MBEDTLS_SSL_DEBUG_MSG( 2, ( "received ServerHello message" ) );
             break;
-        case SSL_SERVER_HELLO_COORDINATE_HRR:
+        case SSL_SERVER_HELLO_HRR:
             MBEDTLS_SSL_DEBUG_MSG( 2, ( "received HelloRetryRequest message" ) );
              /* If a client receives a second
               * HelloRetryRequest in the same connection (i.e., where the ClientHello
               * was itself in response to a HelloRetryRequest), it MUST abort the
               * handshake with an "unexpected_message" alert.
               */
-            if( ssl->handshake->hello_retry_request_count > 0 )
+            if( handshake->hello_retry_request_count > 0 )
             {
                 MBEDTLS_SSL_DEBUG_MSG( 1, ( "Multiple HRRs received" ) );
                 MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
@@ -868,7 +868,7 @@
                 return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER );
             }
 
-            ssl->handshake->hello_retry_request_count++;
+            handshake->hello_retry_request_count++;
 
             break;
     }
@@ -1247,11 +1247,6 @@
     MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to handshake keys for inbound traffic" ) );
     ssl->session_in = ssl->session_negotiate;
 
-    /*
-     * State machine update
-     */
-    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS );
-
 cleanup:
     if( ret != 0 )
     {
@@ -1267,17 +1262,6 @@
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
-    /* If not offering early data, the client sends a dummy CCS record
-     * immediately before its second flight. This may either be before
-     * its second ClientHello or before its encrypted handshake flight.
-     */
-    mbedtls_ssl_handshake_set_state( ssl,
-            MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO );
-#else
-    mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_HELLO );
-#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
-
     mbedtls_ssl_session_reset_msg_layer( ssl, 0 );
 
     /*
@@ -1306,20 +1290,17 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> %s", __func__ ) );
 
-    /* Coordination step
-     * - Fetch record
-     * - Make sure it's either a ServerHello or a HRR.
-     * - Switch processing routine in case of HRR
-     */
-    ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE;
+    MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl,
+                                             MBEDTLS_SSL_HS_SERVER_HELLO,
+                                             &buf, &buf_len ) );
 
-    ret = ssl_tls13_server_hello_coordinate( ssl, &buf, &buf_len );
+    ret = ssl_tls13_preprocess_server_hello( ssl, buf, buf + buf_len );
     if( ret < 0 )
         goto cleanup;
     else
-        is_hrr = ( ret == SSL_SERVER_HELLO_COORDINATE_HRR );
+        is_hrr = ( ret == SSL_SERVER_HELLO_HRR );
 
-    if( ret == SSL_SERVER_HELLO_COORDINATE_TLS1_2 )
+    if( ret == SSL_SERVER_HELLO_TLS1_2 )
     {
         ret = 0;
         goto cleanup;
@@ -1335,9 +1316,24 @@
                                         buf, buf_len );
 
     if( is_hrr )
+    {
         MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_hrr( ssl ) );
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+    /* If not offering early data, the client sends a dummy CCS record
+     * immediately before its second flight. This may either be before
+     * its second ClientHello or before its encrypted handshake flight.
+     */
+        mbedtls_ssl_handshake_set_state( ssl,
+            MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO );
+#else
+        mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_HELLO );
+#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
+    }
     else
+    {
         MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_server_hello( ssl ) );
+        mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS );
+    }
 
 cleanup:
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= %s ( %s )", __func__,
@@ -1347,56 +1343,13 @@
 
 /*
  *
- * EncryptedExtensions message
+ * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS
  *
  * The EncryptedExtensions message contains any extensions which
  * should be protected, i.e., any which are not needed to establish
  * the cryptographic context.
  */
 
-/*
- * Overview
- */
-
-/* Main entry point; orchestrates the other functions */
-static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl );
-
-static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl,
-                                                 const unsigned char *buf,
-                                                 const unsigned char *end );
-static int ssl_tls13_postprocess_encrypted_extensions( mbedtls_ssl_context *ssl );
-
-/*
- * Handler for  MBEDTLS_SSL_ENCRYPTED_EXTENSIONS
- */
-static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl )
-{
-    int ret;
-    unsigned char *buf;
-    size_t buf_len;
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse encrypted extensions" ) );
-
-    MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl,
-                                             MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
-                                             &buf, &buf_len ) );
-
-    /* Process the message contents */
-    MBEDTLS_SSL_PROC_CHK(
-        ssl_tls13_parse_encrypted_extensions( ssl, buf, buf + buf_len ) );
-
-    mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
-                                        buf, buf_len );
-
-    MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_encrypted_extensions( ssl ) );
-
-cleanup:
-
-    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse encrypted extensions" ) );
-    return( ret );
-
-}
-
 /* Parse EncryptedExtensions message
  * struct {
  *     Extension extensions<0..2^16-1>;
@@ -1416,8 +1369,8 @@
     p += 2;
 
     MBEDTLS_SSL_DEBUG_BUF( 3, "encrypted extensions", p, extensions_len );
-    extensions_end = p + extensions_len;
     MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, extensions_len );
+    extensions_end = p + extensions_len;
 
     while( p < extensions_end )
     {
@@ -1483,8 +1436,25 @@
     return( ret );
 }
 
-static int ssl_tls13_postprocess_encrypted_extensions( mbedtls_ssl_context *ssl )
+static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl )
 {
+    int ret;
+    unsigned char *buf;
+    size_t buf_len;
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse encrypted extensions" ) );
+
+    MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl,
+                                             MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                                             &buf, &buf_len ) );
+
+    /* Process the message contents */
+    MBEDTLS_SSL_PROC_CHK(
+        ssl_tls13_parse_encrypted_extensions( ssl, buf, buf + buf_len ) );
+
+    mbedtls_ssl_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                                        buf, buf_len );
+
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
     if( mbedtls_ssl_tls13_some_psk_enabled( ssl ) )
         mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED );
@@ -1494,12 +1464,16 @@
     ((void) ssl);
     mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED );
 #endif
-    return( 0 );
+
+cleanup:
+
+    MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse encrypted extensions" ) );
+    return( ret );
+
 }
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
 /*
- *
  * STATE HANDLING: CertificateRequest
  *
  */
@@ -1532,9 +1506,12 @@
     if( ( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) &&
         ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ) )
     {
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "got a certificate request" ) );
         return( SSL_CERTIFICATE_REQUEST_EXPECT_REQUEST );
     }
 
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "got no certificate request" ) );
+
     return( SSL_CERTIFICATE_REQUEST_SKIP );
 }
 
@@ -1687,7 +1664,6 @@
     }
     else if( ret == SSL_CERTIFICATE_REQUEST_SKIP )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip tls13 parse certificate request" ) );
         ret = 0;
     }
     else
@@ -1697,9 +1673,6 @@
         goto cleanup;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request",
-                                ssl->handshake->client_auth ? "a" : "no" ) );
-
     mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_CERTIFICATE );
 
 cleanup:
@@ -1803,7 +1776,10 @@
                                          MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY );
    }
    else
+   {
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "skip write certificate verify" ) );
         mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED );
+   }
 
     return( 0 );
 }
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index f508bca..893de43 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -567,7 +567,7 @@
      */
     if( ssl->session_negotiate->peer_cert == NULL )
     {
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer has not sent a certificate" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer has no certificate" ) );
 
 #if defined(MBEDTLS_SSL_SRV_C)
         if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
@@ -812,7 +812,7 @@
         /* Currently, we don't have any certificate extensions defined.
          * Hence, we are sending an empty extension with length zero.
          */
-        MBEDTLS_PUT_UINT24_BE( 0, p, 0 );
+        MBEDTLS_PUT_UINT16_BE( 0, p, 0 );
         p += 2;
     }
 
@@ -1437,12 +1437,12 @@
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
 
     /* Get size of the TLS opaque key_exchange field of the KeyShareEntry struct. */
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 );
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 );
     uint16_t peerkey_len = MBEDTLS_GET_UINT16_BE( p, 0 );
     p += 2;
 
     /* Check if key size is consistent with given buffer length. */
-    MBEDTLS_SSL_CHK_BUF_PTR( p, end, peerkey_len );
+    MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, peerkey_len );
 
     /* Store peer's ECDH public key. */
     memcpy( handshake->ecdh_psa_peerkey, p, peerkey_len );
diff --git a/library/ssl_tls13_invasive.h b/library/ssl_tls13_invasive.h
index 4e39f90..f874a88 100644
--- a/library/ssl_tls13_invasive.h
+++ b/library/ssl_tls13_invasive.h
@@ -26,60 +26,6 @@
 
 #if defined(MBEDTLS_TEST_HOOKS)
 
-/**
- *  \brief  Take the input keying material \p ikm and extract from it a
- *          fixed-length pseudorandom key \p prk.
- *
- *  \param       hash_alg  Hash algorithm to use.
- *  \param       salt      An optional salt value (a non-secret random value);
- *                         if the salt is not provided, a string of all zeros
- *                         of the length of the hash provided by \p alg is used
- *                         as the salt.
- *  \param       salt_len  The length in bytes of the optional \p salt.
- *  \param       ikm       The input keying material.
- *  \param       ikm_len   The length in bytes of \p ikm.
- *  \param[out]  prk       A pseudorandom key of \p prk_len bytes.
- *  \param       prk_size  Size of the \p prk buffer in bytes.
- *  \param[out]  prk_len   On success, the length in bytes of the
- *                         pseudorandom key in \p prk.
- *
- *  \return 0 on success.
- *  \return #PSA_ERROR_INVALID_ARGUMENT when the parameters are invalid.
- *  \return An PSA_ERROR_* error for errors returned from the underlying
- *          PSA layer.
- */
-psa_status_t mbedtls_psa_hkdf_extract( psa_algorithm_t hash_alg,
-                                       const unsigned char *salt, size_t salt_len,
-                                       const unsigned char *ikm, size_t ikm_len,
-                                       unsigned char *prk, size_t prk_size,
-                                       size_t *prk_len );
-
-/**
- *  \brief  Expand the supplied \p prk into several additional pseudorandom
- *          keys, which is the output of the HKDF.
- *
- *  \param  hash_alg  Hash algorithm to use.
- *  \param  prk       A pseudorandom key of \p prk_len bytes. \p prk is
- *                    usually the output from the HKDF extract step.
- *  \param  prk_len   The length in bytes of \p prk.
- *  \param  info      An optional context and application specific information
- *                    string. This can be a zero-length string.
- *  \param  info_len  The length of \p info in bytes.
- *  \param  okm       The output keying material of \p okm_len bytes.
- *  \param  okm_len   The length of the output keying material in bytes. This
- *                    must be less than or equal to
- *                    255 * #PSA_HASH_LENGTH( \p alg ) bytes.
- *
- *  \return 0 on success.
- *  \return #PSA_ERROR_INVALID_ARGUMENT when the parameters are invalid.
- *  \return An PSA_ERROR_* error for errors returned from the underlying
- *          PSA layer.
- */
-psa_status_t mbedtls_psa_hkdf_expand( psa_algorithm_t hash_alg,
-                                      const unsigned char *prk, size_t prk_len,
-                                      const unsigned char *info, size_t info_len,
-                                      unsigned char *okm, size_t okm_len );
-
 #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 91cc4d9..d4a8e46 100644
--- a/library/ssl_tls13_keys.c
+++ b/library/ssl_tls13_keys.c
@@ -137,182 +137,6 @@
     *dst_len = total_hkdf_lbl_len;
 }
 
-MBEDTLS_STATIC_TESTABLE
-psa_status_t mbedtls_psa_hkdf_extract( psa_algorithm_t hash_alg,
-                                       const unsigned char *salt, size_t salt_len,
-                                       const unsigned char *ikm, size_t ikm_len,
-                                       unsigned char *prk, size_t prk_size,
-                                       size_t *prk_len )
-{
-    unsigned char null_salt[PSA_MAC_MAX_SIZE] = { '\0' };
-    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_status_t destroy_status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_algorithm_t alg = PSA_ALG_HMAC( hash_alg );
-
-    if( salt == NULL || salt_len == 0 )
-    {
-        size_t hash_len;
-
-        if( salt_len != 0 )
-        {
-            return( PSA_ERROR_INVALID_ARGUMENT );
-        }
-
-        hash_len = PSA_HASH_LENGTH( alg );
-
-        if( hash_len == 0 )
-        {
-            return( PSA_ERROR_INVALID_ARGUMENT );
-        }
-
-        /* salt_len <= sizeof( salt ) because
-           PSA_HASH_LENGTH( alg ) <= PSA_MAC_MAX_SIZE. */
-        salt = null_salt;
-        salt_len = hash_len;
-    }
-
-    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_MESSAGE );
-    psa_set_key_algorithm( &attributes, alg );
-    psa_set_key_type( &attributes, PSA_KEY_TYPE_HMAC );
-
-    status = psa_import_key( &attributes, salt, salt_len, &key );
-    if( status != PSA_SUCCESS )
-    {
-        goto cleanup;
-    }
-
-    status = psa_mac_compute( key, alg, ikm, ikm_len, prk, prk_size, prk_len );
-
-cleanup:
-    destroy_status = psa_destroy_key( key );
-
-    return( ( status == PSA_SUCCESS ) ? destroy_status : status );
-}
-
-MBEDTLS_STATIC_TESTABLE
-psa_status_t mbedtls_psa_hkdf_expand( psa_algorithm_t hash_alg,
-                                      const unsigned char *prk, size_t prk_len,
-                                      const unsigned char *info, size_t info_len,
-                                      unsigned char *okm, size_t okm_len )
-{
-    size_t hash_len;
-    size_t where = 0;
-    size_t n;
-    size_t t_len = 0;
-    size_t i;
-    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_status_t destroy_status = PSA_ERROR_CORRUPTION_DETECTED;
-    unsigned char t[PSA_MAC_MAX_SIZE];
-    psa_algorithm_t alg = PSA_ALG_HMAC( hash_alg );
-
-    if( okm == NULL )
-    {
-        return( PSA_ERROR_INVALID_ARGUMENT );
-    }
-
-    hash_len = PSA_HASH_LENGTH( alg );
-
-    if( prk_len < hash_len || hash_len == 0 )
-    {
-        return( PSA_ERROR_INVALID_ARGUMENT );
-    }
-
-    if( info == NULL )
-    {
-        info = (const unsigned char *) "";
-        info_len = 0;
-    }
-
-    n = okm_len / hash_len;
-
-    if( okm_len % hash_len != 0 )
-    {
-        n++;
-    }
-
-    /*
-     * Per RFC 5869 Section 2.3, okm_len must not exceed
-     * 255 times the hash length
-     */
-    if( n > 255 )
-    {
-        return( PSA_ERROR_INVALID_ARGUMENT );
-    }
-
-    psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_MESSAGE );
-    psa_set_key_algorithm( &attributes, alg );
-    psa_set_key_type( &attributes, PSA_KEY_TYPE_HMAC );
-
-    status = psa_import_key( &attributes, prk, prk_len, &key );
-    if( status != PSA_SUCCESS )
-    {
-        goto cleanup;
-    }
-
-    memset( t, 0, hash_len );
-
-    /*
-     * Compute T = T(1) | T(2) | T(3) | ... | T(N)
-     * Where T(N) is defined in RFC 5869 Section 2.3
-     */
-    for( i = 1; i <= n; i++ )
-    {
-        size_t num_to_copy;
-        unsigned char c = i & 0xff;
-        size_t len;
-
-        status = psa_mac_sign_setup( &operation, key, alg );
-        if( status != PSA_SUCCESS )
-        {
-            goto cleanup;
-        }
-
-        status = psa_mac_update( &operation, t, t_len );
-        if( status != PSA_SUCCESS )
-        {
-            goto cleanup;
-        }
-
-        status = psa_mac_update( &operation, info, info_len );
-        if( status != PSA_SUCCESS )
-        {
-            goto cleanup;
-        }
-
-        /* The constant concatenated to the end of each T(n) is a single octet. */
-        status = psa_mac_update( &operation, &c, 1 );
-        if( status != PSA_SUCCESS )
-        {
-            goto cleanup;
-        }
-
-        status = psa_mac_sign_finish( &operation, t, PSA_MAC_MAX_SIZE, &len );
-        if( status != PSA_SUCCESS )
-        {
-            goto cleanup;
-        }
-
-        num_to_copy = i != n ? hash_len : okm_len - where;
-        memcpy( okm + where, t, num_to_copy );
-        where += hash_len;
-        t_len = hash_len;
-    }
-
-cleanup:
-    if( status != PSA_SUCCESS )
-        psa_mac_abort( &operation );
-    destroy_status = psa_destroy_key( key );
-
-    mbedtls_platform_zeroize( t, sizeof( t ) );
-
-    return( ( status == PSA_SUCCESS ) ? destroy_status : status );
-}
-
 int mbedtls_ssl_tls13_hkdf_expand_label(
                      psa_algorithm_t hash_alg,
                      const unsigned char *secret, size_t secret_len,
@@ -321,7 +145,11 @@
                      unsigned char *buf, size_t buf_len )
 {
     unsigned char hkdf_label[ SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN ];
-    size_t hkdf_label_len;
+    size_t hkdf_label_len = 0;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_derivation_operation_t operation =
+        PSA_KEY_DERIVATION_OPERATION_INIT;
 
     if( label_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN )
     {
@@ -352,11 +180,39 @@
                                  hkdf_label,
                                  &hkdf_label_len );
 
-    return( psa_ssl_status_to_mbedtls(
-                mbedtls_psa_hkdf_expand( hash_alg,
-                                         secret, secret_len,
-                                         hkdf_label, hkdf_label_len,
-                                         buf, buf_len ) ) );
+    status = psa_key_derivation_setup( &operation, PSA_ALG_HKDF_EXPAND( hash_alg ) );
+
+    if( status != PSA_SUCCESS )
+         goto cleanup;
+
+    status = psa_key_derivation_input_bytes( &operation,
+                                             PSA_KEY_DERIVATION_INPUT_SECRET,
+                                             secret,
+                                             secret_len );
+
+    if( status != PSA_SUCCESS )
+         goto cleanup;
+
+    status = psa_key_derivation_input_bytes( &operation,
+                                             PSA_KEY_DERIVATION_INPUT_INFO,
+                                             hkdf_label,
+                                             hkdf_label_len );
+
+    if( status != PSA_SUCCESS )
+         goto cleanup;
+
+    status = psa_key_derivation_output_bytes( &operation,
+                                              buf,
+                                              buf_len );
+
+    if( status != PSA_SUCCESS )
+         goto cleanup;
+
+cleanup:
+    abort_status = psa_key_derivation_abort( &operation );
+    status = ( status == PSA_SUCCESS ? abort_status : status );
+    mbedtls_platform_zeroize( hkdf_label, hkdf_label_len );
+    return( psa_ssl_status_to_mbedtls ( status ) );
 }
 
 /*
@@ -473,10 +329,13 @@
                    unsigned char *secret_new )
 {
     int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
     size_t hlen, ilen;
     unsigned char tmp_secret[ PSA_MAC_MAX_SIZE ] = { 0 };
     unsigned char tmp_input [ MBEDTLS_ECP_MAX_BYTES ] = { 0 };
-    size_t secret_len;
+    psa_key_derivation_operation_t operation =
+        PSA_KEY_DERIVATION_OPERATION_INIT;
 
     if( ! PSA_ALG_IS_HASH( hash_alg ) )
         return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
@@ -498,6 +357,8 @@
             goto cleanup;
     }
 
+    ret = 0;
+
     if( input != NULL )
     {
         memcpy( tmp_input, input, input_len );
@@ -508,17 +369,39 @@
         ilen = hlen;
     }
 
-    /* HKDF-Extract takes a salt and input key material.
-     * The salt is the old secret, and the input key material
-     * is the input secret (PSK / ECDHE). */
-    ret = psa_ssl_status_to_mbedtls(
-            mbedtls_psa_hkdf_extract( hash_alg,
-                                      tmp_secret, hlen,
-                                      tmp_input, ilen,
-                                      secret_new, hlen, &secret_len ) );
+    status = psa_key_derivation_setup( &operation,
+                                       PSA_ALG_HKDF_EXTRACT( hash_alg ) );
+
+    if( status != PSA_SUCCESS )
+         goto cleanup;
+
+    status = psa_key_derivation_input_bytes( &operation,
+                                             PSA_KEY_DERIVATION_INPUT_SALT,
+                                             tmp_secret,
+                                             hlen );
+
+    if( status != PSA_SUCCESS )
+         goto cleanup;
+
+    status = psa_key_derivation_input_bytes( &operation,
+                                             PSA_KEY_DERIVATION_INPUT_SECRET,
+                                             tmp_input,
+                                             ilen );
+
+    if( status != PSA_SUCCESS )
+         goto cleanup;
+
+    status = psa_key_derivation_output_bytes( &operation,
+                                              secret_new,
+                                              PSA_HASH_LENGTH( hash_alg ) );
+
+    if( status != PSA_SUCCESS )
+         goto cleanup;
 
  cleanup:
-
+    abort_status = psa_key_derivation_abort( &operation );
+    status = ( status == PSA_SUCCESS ? abort_status : status );
+    ret = ( ret == 0 ? psa_ssl_status_to_mbedtls ( status ) : ret );
     mbedtls_platform_zeroize( tmp_secret, sizeof(tmp_secret) );
     mbedtls_platform_zeroize( tmp_input,  sizeof(tmp_input)  );
     return( ret );
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 7afaa8c..ffbbbcf 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -303,6 +303,13 @@
                 & MBEDTLS_SSL_EXT_SERVERNAME ) > 0 ) ?
                 "TRUE" : "FALSE" ) );
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+#if defined ( MBEDTLS_SSL_ALPN )
+    MBEDTLS_SSL_DEBUG_MSG( 3,
+            ( "- ALPN_EXTENSION   ( %s )",
+            ( ( ssl->handshake->extensions_present
+                & MBEDTLS_SSL_EXT_ALPN ) > 0 ) ?
+                "TRUE" : "FALSE" ) );
+#endif /* MBEDTLS_SSL_ALPN */
 }
 #endif /* MBEDTLS_DEBUG_C */
 
@@ -731,6 +738,21 @@
                 ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SUPPORTED_VERSIONS;
                 break;
 
+#if defined(MBEDTLS_SSL_ALPN)
+            case MBEDTLS_TLS_EXT_ALPN:
+                MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) );
+
+                ret = mbedtls_ssl_parse_alpn_ext( ssl, p, extension_data_end );
+                if( ret != 0 )
+                {
+                    MBEDTLS_SSL_DEBUG_RET(
+                            1, ( "mbedtls_ssl_parse_alpn_ext" ), ret );
+                    return( ret );
+                }
+                ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_ALPN;
+                break;
+#endif /* MBEDTLS_SSL_ALPN */
+
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
             case MBEDTLS_TLS_EXT_SIG_ALG:
                 MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) );
@@ -1073,7 +1095,7 @@
      * - extension_data_length  (2 bytes)
      * - selected_group         (2 bytes)
      */
-    MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, 6 );
+    MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 6 );
 
     MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0 );
     MBEDTLS_PUT_UINT16_BE( 2, buf, 2 );
@@ -1289,8 +1311,7 @@
 /*
  * Handler for MBEDTLS_SSL_HELLO_RETRY_REQUEST
  */
-static int ssl_tls13_write_hello_retry_request_coordinate(
-                                                    mbedtls_ssl_context *ssl )
+static int ssl_tls13_prepare_hello_retry_request( mbedtls_ssl_context *ssl )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     if( ssl->handshake->hello_retry_request_count > 0 )
@@ -1324,7 +1345,7 @@
 
     MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello retry request" ) );
 
-    MBEDTLS_SSL_PROC_CHK( ssl_tls13_write_hello_retry_request_coordinate( ssl ) );
+    MBEDTLS_SSL_PROC_CHK( ssl_tls13_prepare_hello_retry_request( ssl ) );
 
     MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_start_handshake_msg(
                               ssl, MBEDTLS_SSL_HS_SERVER_HELLO,
@@ -1374,9 +1395,11 @@
                                                       unsigned char *end,
                                                       size_t *out_len )
 {
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p = buf;
     size_t extensions_len = 0;
     unsigned char *p_extensions_len;
+    size_t output_len;
 
     *out_len = 0;
 
@@ -1385,6 +1408,15 @@
     p += 2;
 
     ((void) ssl);
+    ((void) ret);
+    ((void) output_len);
+
+#if defined(MBEDTLS_SSL_ALPN)
+    ret = mbedtls_ssl_write_alpn_ext( ssl, p, end, &output_len );
+    if( ret != 0 )
+        return( ret );
+    p += output_len;
+#endif /* MBEDTLS_SSL_ALPN */
 
     extensions_len = ( p - p_extensions_len ) - 2;
     MBEDTLS_PUT_UINT16_BE( extensions_len, p_extensions_len, 0 );
@@ -1621,15 +1653,18 @@
         return( ret );
     }
 
-    if( ssl->handshake->certificate_request_sent )
-    {
-        mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE );
+    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to handshake keys for inbound traffic" ) );
+    mbedtls_ssl_set_inbound_transform( ssl, ssl->handshake->transform_handshake );
 
-        MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to handshake keys for inbound traffic" ) );
-        mbedtls_ssl_set_inbound_transform( ssl, ssl->handshake->transform_handshake );
-    }
+    if( ssl->handshake->certificate_request_sent )
+        mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE );
     else
+    {
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "skip parse certificate" ) );
+        MBEDTLS_SSL_DEBUG_MSG( 2, ( "skip parse certificate verify" ) );
         mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED );
+    }
+
     return( 0 );
 }
 
@@ -1640,12 +1675,6 @@
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if( ! ssl->handshake->certificate_request_sent )
-    {
-        MBEDTLS_SSL_DEBUG_MSG( 1,
-            ( "Switch to handshake traffic keys for inbound traffic" ) );
-        mbedtls_ssl_set_inbound_transform( ssl, ssl->handshake->transform_handshake );
-    }
     ret = mbedtls_ssl_tls13_process_finished_message( ssl );
     if( ret != 0 )
         return( ret );
@@ -1776,8 +1805,11 @@
                         ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY );
                 }
                 else
+                {
+                    MBEDTLS_SSL_DEBUG_MSG( 2, ( "skip parse certificate verify" ) );
                     mbedtls_ssl_handshake_set_state(
                         ssl, MBEDTLS_SSL_CLIENT_FINISHED );
+                }
             }
             break;
 
diff --git a/library/x509.c b/library/x509.c
index 2e11c7f..7f3917f 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -741,7 +741,7 @@
 int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i, n;
+    size_t i, j, n;
     unsigned char c, merge = 0;
     const mbedtls_x509_name *name;
     const char *short_name = NULL;
@@ -775,17 +775,24 @@
             ret = mbedtls_snprintf( p, n, "\?\?=" );
         MBEDTLS_X509_SAFE_SNPRINTF;
 
-        for( i = 0; i < name->val.len; i++ )
+        for( i = 0, j = 0; i < name->val.len; i++, j++ )
         {
-            if( i >= sizeof( s ) - 1 )
-                break;
+            if( j >= sizeof( s ) - 1 )
+                return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
 
             c = name->val.p[i];
+            // Special characters requiring escaping, RFC 1779
+            if( c && strchr( ",=+<>#;\"\\", c ) )
+            {
+                if( j + 1 >= sizeof( s ) - 1 )
+                    return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+                s[j++] = '\\';
+            }
             if( c < 32 || c >= 127 )
-                 s[i] = '?';
-            else s[i] = c;
+                 s[j] = '?';
+            else s[j] = c;
         }
-        s[i] = '\0';
+        s[j] = '\0';
         ret = mbedtls_snprintf( p, n, "%s", s );
         MBEDTLS_X509_SAFE_SNPRINTF;
 
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index c0ad9b0..6187d17 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -909,6 +909,10 @@
 	$(MBEDTLS_CERT_REQ) output_file=$@ filename=$< subject_name="C=NL,O=PolarSSL,CN=PolarSSL Server 1" md=SHA1 force_ns_cert_type=1
 all_final += server1.req.cert_type_empty
 
+server1.req.commas.sha256: server1.key
+	$(MBEDTLS_CERT_REQ) output_file=$@ filename=$< subject_name="C=NL,O=PolarSSL\, Commas,CN=PolarSSL Server 1" md=SHA256
+all_final += server1.req.commas.sha256
+
 # server2*
 
 server2_pwd_ec = PolarSSLTest
@@ -966,7 +970,9 @@
 	$(MBEDTLS_CERT_WRITE) request_file=server1.req.sha256 issuer_crt=$(test_ca_crt) issuer_key=$(test_ca_key_file_rsa) issuer_pwd=$(test_ca_pwd_rsa) not_before=20190210144406 not_after=20290210144406 md=SHA1 authority_identifier=0 version=3 output_file=$@
 server1.der: server1.crt
 	$(OPENSSL) x509 -inform PEM -in $< -outform DER -out $@
-all_final += server1.crt server1.noauthid.crt server1.crt.der
+server1.commas.crt: server1.key server1.req.commas.sha256 $(test_ca_crt) $(test_ca_key_file_rsa)
+	$(MBEDTLS_CERT_WRITE) request_file=server1.req.commas.sha256 issuer_crt=$(test_ca_crt) issuer_key=$(test_ca_key_file_rsa) issuer_pwd=$(test_ca_pwd_rsa) version=1 not_before=20190210144406 not_after=20290210144406 md=SHA1 version=3 output_file=$@
+all_final += server1.crt server1.noauthid.crt server1.crt.der server1.commas.crt
 
 server1.key_usage.crt: server1.key server1.req.sha256 $(test_ca_crt) $(test_ca_key_file_rsa)
 	$(MBEDTLS_CERT_WRITE) request_file=server1.req.sha256 issuer_crt=$(test_ca_crt) issuer_key=$(test_ca_key_file_rsa) issuer_pwd=$(test_ca_pwd_rsa) version=1 not_before=20190210144406 not_after=20290210144406 md=SHA1 key_usage=digital_signature,non_repudiation,key_encipherment version=3 output_file=$@
diff --git a/tests/data_files/server1.commas.crt b/tests/data_files/server1.commas.crt
new file mode 100644
index 0000000..5acd255
--- /dev/null
+++ b/tests/data_files/server1.commas.crt
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDRzCCAi+gAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER
+MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN
+MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjBEMQswCQYDVQQGEwJOTDEZMBcG
+A1UECgwQUG9sYXJTU0wsIENvbW1hczEaMBgGA1UEAwwRUG9sYXJTU0wgU2VydmVy
+IDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpAh89QGrVVVOL/Tbu
+gmUuFWFeib+46EWQ2+6IFlLT8UNQR5YSWWSHa/0r4Eb5c77dz5LhkVvtZqBviSl5
+RYDQg2rVQUN3Xzl8CQRHgrBXOXDto+wVGR6oMwhHwQVCqf1Mw7Tf3QYfTRBRQGdz
+Ew9A+G2BJV8KsVPGMH4VOaz5Wu5/kp6mBVvnE5eFtSOS2dQkBtUJJYl1B92mGo8/
+CRm+rWUsZOuVm9z+QV4XptpsW2nMAroULBYknErczdD3Umdz8S2gI/1+9DHKLXDK
+iQsE2y6mT3Buns69WIniU1meblqSZeKIPwyUGaPd5eidlRPtKdurcBLcWsprF6tS
+glSxAgMBAAGjTTBLMAkGA1UdEwQCMAAwHQYDVR0OBBYEFB901j8pwXR0RTsFEiw9
+qL1DWQKmMB8GA1UdIwQYMBaAFLRa5KWz3tJS9rnVppUP6z68x/3/MA0GCSqGSIb3
+DQEBBQUAA4IBAQA1Ecg+VVJRmgFF9cnlztnXj4y9QKj8MCf2uZA3nTNe1Deh9l17
+ZNNWdPkXzVzf0IeR3LQRKT+daTzxuOOCSV9OxOcN0dIODBwa97BtNQfuWw2eWC9I
+3UOVXbx8Ga+bXnD8ouatpyEG0FfhLO5YgEP0K9TyyN/nFa9kkB2Kvpy8yWm3w9WG
+WgsOr2fpIExfC2ZFaiu3NVGTpT9fLv8RTatSC1XLA5Sr8NNHia3zCvEJEAlTuFHs
+wm8apIAHlb44bbgW+7UwBIH9r2A21gQFy3v4cTLtlbnaUBbHUJvarK4ru70J+gew
+OO3NZ1ocvnV+qGIcc7LgyNA8pZW5Jbewb/gN
+-----END CERTIFICATE-----
diff --git a/tests/data_files/server1.req.commas.sha256 b/tests/data_files/server1.req.commas.sha256
new file mode 100644
index 0000000..0287a31
--- /dev/null
+++ b/tests/data_files/server1.req.commas.sha256
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIICiTCCAXECAQAwRDELMAkGA1UEBhMCTkwxGTAXBgNVBAoMEFBvbGFyU1NMLCBD
+b21tYXMxGjAYBgNVBAMMEVBvbGFyU1NMIFNlcnZlciAxMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/uOhFkNvuiBZS
+0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFDd185fAkER4Kw
+Vzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVfCrFTxjB+FTms
++Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTrlZvc/kFeF6ba
+bFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9wbp7OvViJ4lNZ
+nm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQABoAAwDQYJKoZI
+hvcNAQELBQADggEBAI7ZtRJYX6cMuwVhwXOizPV+WD17wby+273V4R8e9/6QA4nY
+RrSciAse+nWZz9Y6toBzLWr0K/9SCzwBX4OzMvLqu4A1G/wApODCDnbGaUPNUxRt
+6qbg8y7faBWvDGjk4+OpQ0suR/pdbM/L7pImqWRNwYdSPbJumNqIdB/Ewtso0TlA
+QVZ992RPe1LovXpDCfPP2p123L7/UHezNCtu5QmzLsDfQmN/rLhCJ2NZzTsnIdnP
+jp6XYU4kRV2BPDL65k38k8CSVWb6fw9XwPNUiyO3q1Zs6jpGJRYMLj9qTEoRN1np
+RME09CN2siMcgkv8UqDeDJ4Oa9qyXS6VXsDmSNI=
+-----END CERTIFICATE REQUEST-----
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index ba49177..afabb64 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -4747,7 +4747,6 @@
 # Tests for auth_mode, there are duplicated tests using ca callback for authentication
 # When updating these tests, modify the matching authentication tests accordingly
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: server badcert, client required" \
             "$P_SRV crt_file=data_files/server5-badsign.crt \
              key_file=data_files/server5.key" \
@@ -4781,7 +4780,6 @@
             -C "X509 - Certificate verification failed" \
             -C "SSL - No CA Chain is set, but required to operate"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: server goodcert, client required, no trusted CA" \
             "$P_SRV" \
             "$P_CLI debug_level=3 auth_mode=required ca_file=none ca_path=none" \
@@ -4852,7 +4850,6 @@
             -c "Supported Signature Algorithm found: 4," \
             -c "Supported Signature Algorithm found: 5,"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: client has no cert, server required (TLS)" \
             "$P_SRV debug_level=3 auth_mode=required" \
             "$P_CLI debug_level=3 crt_file=none \
@@ -4864,12 +4861,10 @@
             -c "= write certificate$" \
             -C "skip write certificate$" \
             -S "x509_verify_cert() returned" \
-            -s "client has no certificate" \
+            -s "peer has no certificate" \
             -s "! mbedtls_ssl_handshake returned" \
-            -c "! mbedtls_ssl_handshake returned" \
             -s "No client certification received from the client, but required by the authentication mode"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: client badcert, server required" \
             "$P_SRV debug_level=3 auth_mode=required" \
             "$P_CLI debug_level=3 crt_file=data_files/server5-badsign.crt \
@@ -4885,13 +4880,11 @@
             -s "! The certificate is not correctly signed by the trusted CA" \
             -s "! mbedtls_ssl_handshake returned" \
             -s "send alert level=2 message=48" \
-            -c "! mbedtls_ssl_handshake returned" \
             -s "X509 - Certificate verification failed"
 # We don't check that the client receives the alert because it might
 # detect that its write end of the connection is closed and abort
 # before reading the alert message.
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: client cert self-signed and trusted, server required" \
             "$P_SRV debug_level=3 auth_mode=required ca_file=data_files/server5-selfsigned.crt" \
             "$P_CLI debug_level=3 crt_file=data_files/server5-selfsigned.crt \
@@ -4907,7 +4900,6 @@
             -S "! The certificate is not correctly signed" \
             -S "X509 - Certificate verification failed"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: client cert not trusted, server required" \
             "$P_SRV debug_level=3 auth_mode=required" \
             "$P_CLI debug_level=3 crt_file=data_files/server5-selfsigned.crt \
@@ -4922,10 +4914,8 @@
             -s "x509_verify_cert() returned" \
             -s "! The certificate is not correctly signed by the trusted CA" \
             -s "! mbedtls_ssl_handshake returned" \
-            -c "! mbedtls_ssl_handshake returned" \
             -s "X509 - Certificate verification failed"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: client badcert, server optional" \
             "$P_SRV debug_level=3 auth_mode=optional" \
             "$P_CLI debug_level=3 crt_file=data_files/server5-badsign.crt \
@@ -4943,7 +4933,6 @@
             -C "! mbedtls_ssl_handshake returned" \
             -S "X509 - Certificate verification failed"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: client badcert, server none" \
             "$P_SRV debug_level=3 auth_mode=none" \
             "$P_CLI debug_level=3 crt_file=data_files/server5-badsign.crt \
@@ -4961,7 +4950,6 @@
             -C "! mbedtls_ssl_handshake returned" \
             -S "X509 - Certificate verification failed"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: client no cert, server optional" \
             "$P_SRV debug_level=3 auth_mode=optional" \
             "$P_CLI debug_level=3 crt_file=none key_file=none" \
@@ -5023,7 +5011,6 @@
 # are in place so that the semantics are consistent with the test description.
 requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: server max_int chain, client default" \
             "$P_SRV crt_file=data_files/dir-maxpath/c09.pem \
                     key_file=data_files/dir-maxpath/09.key" \
@@ -5033,7 +5020,6 @@
 
 requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: server max_int+1 chain, client default" \
             "$P_SRV crt_file=data_files/dir-maxpath/c10.pem \
                     key_file=data_files/dir-maxpath/10.key" \
@@ -5065,7 +5051,6 @@
 
 requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: client max_int+1 chain, server default" \
             "$P_SRV ca_file=data_files/dir-maxpath/00.crt" \
             "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \
@@ -5075,7 +5060,6 @@
 
 requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: client max_int+1 chain, server optional" \
             "$P_SRV ca_file=data_files/dir-maxpath/00.crt auth_mode=optional" \
             "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \
@@ -5085,7 +5069,6 @@
 
 requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: client max_int+1 chain, server required" \
             "$P_SRV ca_file=data_files/dir-maxpath/00.crt auth_mode=required" \
             "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \
@@ -5095,7 +5078,6 @@
 
 requires_config_value_equals "MBEDTLS_X509_MAX_INTERMEDIATE_CA" $MAX_IM_CA
 requires_full_size_output_buffer
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Authentication: client max_int chain, server required" \
             "$P_SRV ca_file=data_files/dir-maxpath/00.crt auth_mode=required" \
             "$P_CLI crt_file=data_files/dir-maxpath/c09.pem \
@@ -5657,7 +5639,6 @@
 
 # Tests for non-blocking I/O: exercise a variety of handshake flows
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Non-blocking I/O: basic handshake" \
             "$P_SRV nbio=2 tickets=0 auth_mode=none" \
             "$P_CLI nbio=2 tickets=0" \
@@ -5666,7 +5647,6 @@
             -C "mbedtls_ssl_handshake returned" \
             -c "Read from server: .* bytes read"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Non-blocking I/O: client auth" \
             "$P_SRV nbio=2 tickets=0 auth_mode=required" \
             "$P_CLI nbio=2 tickets=0" \
@@ -5722,7 +5702,6 @@
 
 # Tests for event-driven I/O: exercise a variety of handshake flows
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Event-driven I/O: basic handshake" \
             "$P_SRV event=1 tickets=0 auth_mode=none" \
             "$P_CLI event=1 tickets=0" \
@@ -5731,7 +5710,6 @@
             -C "mbedtls_ssl_handshake returned" \
             -c "Read from server: .* bytes read"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "Event-driven I/O: client auth" \
             "$P_SRV event=1 tickets=0 auth_mode=required" \
             "$P_CLI event=1 tickets=0" \
@@ -5901,7 +5879,6 @@
 
 # Tests for ALPN extension
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "ALPN: none" \
             "$P_SRV debug_level=3" \
             "$P_CLI debug_level=3" \
@@ -5909,12 +5886,11 @@
             -C "client hello, adding alpn extension" \
             -S "found alpn extension" \
             -C "got an alert message, type: \\[2:120]" \
-            -S "server hello, adding alpn extension" \
+            -S "server side, adding alpn extension" \
             -C "found alpn extension " \
             -C "Application Layer Protocol is" \
             -S "Application Layer Protocol is"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "ALPN: client only" \
             "$P_SRV debug_level=3" \
             "$P_CLI debug_level=3 alpn=abc,1234" \
@@ -5922,12 +5898,11 @@
             -c "client hello, adding alpn extension" \
             -s "found alpn extension" \
             -C "got an alert message, type: \\[2:120]" \
-            -S "server hello, adding alpn extension" \
+            -S "server side, adding alpn extension" \
             -C "found alpn extension " \
             -c "Application Layer Protocol is (none)" \
             -S "Application Layer Protocol is"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "ALPN: server only" \
             "$P_SRV debug_level=3 alpn=abc,1234" \
             "$P_CLI debug_level=3" \
@@ -5935,12 +5910,11 @@
             -C "client hello, adding alpn extension" \
             -S "found alpn extension" \
             -C "got an alert message, type: \\[2:120]" \
-            -S "server hello, adding alpn extension" \
+            -S "server side, adding alpn extension" \
             -C "found alpn extension " \
             -C "Application Layer Protocol is" \
             -s "Application Layer Protocol is (none)"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "ALPN: both, common cli1-srv1" \
             "$P_SRV debug_level=3 alpn=abc,1234" \
             "$P_CLI debug_level=3 alpn=abc,1234" \
@@ -5948,12 +5922,11 @@
             -c "client hello, adding alpn extension" \
             -s "found alpn extension" \
             -C "got an alert message, type: \\[2:120]" \
-            -s "server hello, adding alpn extension" \
+            -s "server side, adding alpn extension" \
             -c "found alpn extension" \
             -c "Application Layer Protocol is abc" \
             -s "Application Layer Protocol is abc"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "ALPN: both, common cli2-srv1" \
             "$P_SRV debug_level=3 alpn=abc,1234" \
             "$P_CLI debug_level=3 alpn=1234,abc" \
@@ -5961,12 +5934,11 @@
             -c "client hello, adding alpn extension" \
             -s "found alpn extension" \
             -C "got an alert message, type: \\[2:120]" \
-            -s "server hello, adding alpn extension" \
+            -s "server side, adding alpn extension" \
             -c "found alpn extension" \
             -c "Application Layer Protocol is abc" \
             -s "Application Layer Protocol is abc"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "ALPN: both, common cli1-srv2" \
             "$P_SRV debug_level=3 alpn=abc,1234" \
             "$P_CLI debug_level=3 alpn=1234,abcde" \
@@ -5974,12 +5946,11 @@
             -c "client hello, adding alpn extension" \
             -s "found alpn extension" \
             -C "got an alert message, type: \\[2:120]" \
-            -s "server hello, adding alpn extension" \
+            -s "server side, adding alpn extension" \
             -c "found alpn extension" \
             -c "Application Layer Protocol is 1234" \
             -s "Application Layer Protocol is 1234"
 
-requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
 run_test    "ALPN: both, no common" \
             "$P_SRV debug_level=3 alpn=abc,123" \
             "$P_CLI debug_level=3 alpn=1234,abcde" \
@@ -5987,7 +5958,7 @@
             -c "client hello, adding alpn extension" \
             -s "found alpn extension" \
             -c "got an alert message, type: \\[2:120]" \
-            -S "server hello, adding alpn extension" \
+            -S "server side, adding alpn extension" \
             -C "found alpn extension" \
             -C "Application Layer Protocol is 1234" \
             -S "Application Layer Protocol is 1234"
@@ -7362,6 +7333,20 @@
             0 \
             -s "Read from client: 1 bytes read"
 
+run_test    "Small client packet TLS 1.3 AEAD" \
+            "$P_SRV force_version=tls13" \
+            "$P_CLI request_size=1 \
+             force_ciphersuite=TLS1-3-AES-128-CCM-SHA256" \
+            0 \
+            -s "Read from client: 1 bytes read"
+
+run_test    "Small client packet TLS 1.3 AEAD shorter tag" \
+            "$P_SRV force_version=tls13" \
+            "$P_CLI request_size=1 \
+             force_ciphersuite=TLS1-3-AES-128-CCM-8-SHA256" \
+            0 \
+            -s "Read from client: 1 bytes read"
+
 # Tests for small client packets in DTLS
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
@@ -7412,6 +7397,18 @@
             0 \
             -c "Read from server: 1 bytes read"
 
+run_test    "Small server packet TLS 1.3 AEAD" \
+            "$P_SRV response_size=1 force_version=tls13" \
+            "$P_CLI force_ciphersuite=TLS1-3-AES-128-CCM-SHA256" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
+run_test    "Small server packet TLS 1.3 AEAD shorter tag" \
+            "$P_SRV response_size=1 force_version=tls13" \
+            "$P_CLI force_ciphersuite=TLS1-3-AES-128-CCM-8-SHA256" \
+            0 \
+            -c "Read from server: 1 bytes read"
+
 # Tests for small server packets in DTLS
 
 requires_config_enabled MBEDTLS_SSL_PROTO_DTLS
@@ -7476,6 +7473,22 @@
             -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
             -s "Read from client: $MAX_CONTENT_LEN bytes read"
 
+run_test    "Large client packet TLS 1.3 AEAD" \
+            "$P_SRV force_version=tls13" \
+            "$P_CLI request_size=16384 \
+             force_ciphersuite=TLS1-3-AES-128-CCM-SHA256" \
+            0 \
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
+
+run_test    "Large client packet TLS 1.3 AEAD shorter tag" \
+            "$P_SRV force_version=tls13" \
+            "$P_CLI request_size=16384 \
+             force_ciphersuite=TLS1-3-AES-128-CCM-8-SHA256" \
+            0 \
+            -c "16384 bytes written in $(fragments_for_write 16384) fragments" \
+            -s "Read from client: $MAX_CONTENT_LEN bytes read"
+
 # The tests below fail when the server's OUT_CONTENT_LEN is less than 16384.
 run_test    "Large server packet TLS 1.2 BlockCipher" \
             "$P_SRV response_size=16384 force_version=tls12" \
@@ -7515,6 +7528,18 @@
             0 \
             -c "Read from server: 16384 bytes read"
 
+run_test    "Large server packet TLS 1.3 AEAD" \
+            "$P_SRV response_size=16384 force_version=tls13" \
+            "$P_CLI force_ciphersuite=TLS1-3-AES-128-CCM-SHA256" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
+run_test    "Large server packet TLS 1.3 AEAD shorter tag" \
+            "$P_SRV response_size=16384 force_version=tls13" \
+            "$P_CLI force_ciphersuite=TLS1-3-AES-128-CCM-8-SHA256" \
+            0 \
+            -c "Read from server: 16384 bytes read"
+
 # Tests for restartable ECC
 
 # Force the use of a curve that supports restartable ECC (secp256r1).
@@ -10517,6 +10542,36 @@
             -c "HTTP/1.0 200 OK" \
             -c "Application Layer Protocol is h2"
 
+requires_openssl_tls1_3
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_DEBUG_C
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_enabled MBEDTLS_SSL_ALPN
+run_test    "TLS 1.3: server alpn - openssl" \
+            "$P_SRV debug_level=3 tickets=0 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 alpn=h2" \
+            "$O_NEXT_CLI -msg -tls1_3 -no_middlebox -alpn h2" \
+            0 \
+            -s "found alpn extension" \
+            -s "server side, adding alpn extension" \
+            -s "Protocol is TLSv1.3" \
+            -s "HTTP/1.0 200 OK" \
+            -s "Application Layer Protocol is h2"
+
+requires_gnutls_tls1_3
+requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
+requires_config_enabled MBEDTLS_DEBUG_C
+requires_config_enabled MBEDTLS_SSL_SRV_C
+requires_config_enabled MBEDTLS_SSL_ALPN
+run_test    "TLS 1.3: server alpn - gnutls" \
+            "$P_SRV debug_level=3 tickets=0 crt_file=data_files/server5.crt key_file=data_files/server5.key force_version=tls13 alpn=h2" \
+            "$G_NEXT_CLI localhost -d 4 --priority=NORMAL:-VERS-ALL:+VERS-TLS1.3:%NO_TICKETS:%DISABLE_TLS13_COMPAT_MODE -V --alpn h2" \
+            0 \
+            -s "found alpn extension" \
+            -s "server side, adding alpn extension" \
+            -s "Protocol is TLSv1.3" \
+            -s "HTTP/1.0 200 OK" \
+            -s "Application Layer Protocol is h2"
+
 requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_3
 requires_config_enabled MBEDTLS_DEBUG_C
 requires_config_enabled MBEDTLS_SSL_CLI_C
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index 2eb8c2d..4ea4d3b 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -890,3 +890,56 @@
 ECP export key parameters #2 (invalid group)
 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
 ecp_export:MBEDTLS_ECP_DP_SECP256R1:"37cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f76822596292":"4ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edff":"00f12a1320760270a83cbffd53f6031ef76a5d86c8a204f2c30ca9ebf51f0f0ea7":MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE:1
+
+ECP check order for SECP192R1
+depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_SECP192R1:"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"
+
+ECP check order for SECP224R1
+depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_SECP224R1:"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"
+
+ECP check order for SECP256R1
+depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_SECP256R1:"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"
+
+ECP check order for SECP384R1
+depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_SECP384R1:"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"
+
+ECP check order for SECP521R1
+depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_SECP521R1:"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"
+
+ECP check order for BP256R1
+depends_on:MBEDTLS_ECP_DP_BP256R1_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_BP256R1:"A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7"
+
+ECP check order for BP384R1
+depends_on:MBEDTLS_ECP_DP_BP384R1_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_BP384R1:"8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565"
+
+ECP check order for BP512R1
+depends_on:MBEDTLS_ECP_DP_BP512R1_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_BP512R1:"AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069"
+
+ECP check order for CURVE25519
+depends_on:MBEDTLS_ECP_DP_CURVE25519_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_CURVE25519:"1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed"
+
+ECP check order for SECP192K1
+depends_on:MBEDTLS_ECP_DP_SECP192K1_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_SECP192K1:"fffffffffffffffffffffffe26f2fc170f69466a74defd8d"
+
+ECP check order for SECP224K1
+depends_on:MBEDTLS_ECP_DP_SECP224K1_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_SECP224K1:"10000000000000000000000000001dce8d2ec6184caf0a971769fb1f7"
+
+ECP check order for SECP256K1
+depends_on:MBEDTLS_ECP_DP_SECP256K1_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_SECP256K1:"fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"
+
+ECP check order for CURVE448
+depends_on:MBEDTLS_ECP_DP_CURVE448_ENABLED
+ecp_check_order:MBEDTLS_ECP_DP_CURVE448:"3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3"
+
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index c3e6b05..1b77f1d 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -1063,3 +1063,27 @@
     mbedtls_ecp_point_free( &export_Q );
 }
 /* END_CASE */
+
+/* BEGIN_CASE */
+void ecp_check_order( int id, char * expected_order_hex )
+{
+    mbedtls_ecp_group grp;
+    mbedtls_mpi expected_n;
+
+    mbedtls_ecp_group_init( &grp );
+    mbedtls_mpi_init( &expected_n );
+
+    TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
+    TEST_ASSERT( mbedtls_test_read_mpi( &expected_n, 16, expected_order_hex ) == 0);
+
+    // check sign bits are well-formed (i.e. 1 or -1) - see #5810
+    TEST_ASSERT( grp.N.s == -1 || grp.N.s == 1);
+    TEST_ASSERT( expected_n.s == -1 || expected_n.s == 1);
+
+    TEST_ASSERT( mbedtls_mpi_cmp_mpi( &grp.N, &expected_n ) == 0 );
+
+exit:
+    mbedtls_ecp_group_free( &grp );
+    mbedtls_mpi_free( &expected_n );
+}
+/* END_CASE */
diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data
index 5192342..f643335 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -2792,83 +2792,6 @@
 depends_on:PSA_WANT_ALG_SHA_256
 ssl_tls13_key_evolution:PSA_ALG_SHA_256:"fb9fc80689b3a5d02c33243bf69a1b1b20705588a794304a6e7120155edf149a":"":"7f2882bb9b9a46265941653e9c2f19067118151e21d12e57a7b6aca1f8150c8d"
 
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #1 Extract
-depends_on:PSA_WANT_ALG_SHA_256
-psa_hkdf_extract:PSA_ALG_SHA_256:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #2 Extract
-depends_on:PSA_WANT_ALG_SHA_256
-psa_hkdf_extract:PSA_ALG_SHA_256:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f":"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf":"06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244"
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #3 Extract
-depends_on:PSA_WANT_ALG_SHA_256
-psa_hkdf_extract:PSA_ALG_SHA_256:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"":"19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04"
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #4 Extract
-depends_on:PSA_WANT_ALG_SHA_1
-psa_hkdf_extract:PSA_ALG_SHA_1:"0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243"
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #5 Extract
-depends_on:PSA_WANT_ALG_SHA_1
-psa_hkdf_extract:PSA_ALG_SHA_1:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f":"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf":"8adae09a2a307059478d309b26c4115a224cfaf6"
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #6 Extract
-depends_on:PSA_WANT_ALG_SHA_1
-psa_hkdf_extract:PSA_ALG_SHA_1:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"":"da8c8a73c7fa77288ec6f5e7c297786aa0d32d01"
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #7 Extract
-depends_on:PSA_WANT_ALG_SHA_1
-psa_hkdf_extract:PSA_ALG_SHA_1:"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c":"":"2adccada18779e7c2077ad2eb19d3f3e731385dd"
-
-SSL TLS 1.3 Key schedule: HKDF extract fails with wrong hash alg
-psa_hkdf_extract_ret:0:PSA_ERROR_INVALID_ARGUMENT
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #1 Expand
-depends_on:PSA_WANT_ALG_SHA_256
-psa_hkdf_expand:PSA_ALG_SHA_256:"f0f1f2f3f4f5f6f7f8f9":"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5":"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #2 Expand
-depends_on:PSA_WANT_ALG_SHA_256
-psa_hkdf_expand:PSA_ALG_SHA_256:"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244":"b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #3 Expand
-depends_on:PSA_WANT_ALG_SHA_256
-psa_hkdf_expand:PSA_ALG_SHA_256:"":"19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04":"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8"
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #4 Expand
-depends_on:PSA_WANT_ALG_SHA_1
-psa_hkdf_expand:PSA_ALG_SHA_1:"f0f1f2f3f4f5f6f7f8f9":"9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243":"085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896"
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #5 Expand
-depends_on:PSA_WANT_ALG_SHA_1
-psa_hkdf_expand:PSA_ALG_SHA_1:"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff":"8adae09a2a307059478d309b26c4115a224cfaf6":"0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4"
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #6 Expand
-depends_on:PSA_WANT_ALG_SHA_1
-psa_hkdf_expand:PSA_ALG_SHA_1:"":"da8c8a73c7fa77288ec6f5e7c297786aa0d32d01":"0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918"
-
-SSL TLS 1.3 Key schedule: HKDF RFC5869 Test Vector #7 Expand
-depends_on:PSA_WANT_ALG_SHA_1
-psa_hkdf_expand:PSA_ALG_SHA_1:"":"2adccada18779e7c2077ad2eb19d3f3e731385dd":"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48"
-
-SSL TLS 1.3 Key schedule: HKDF expand fails with NULL okm
-depends_on:PSA_WANT_ALG_SHA_256
-psa_hkdf_expand_ret:PSA_ALG_SHA_256:32:0:PSA_ERROR_INVALID_ARGUMENT
-
-SSL TLS 1.3 Key schedule: HKDF expand fails with invalid alg
-psa_hkdf_expand_ret:0:32:32:PSA_ERROR_INVALID_ARGUMENT
-
-SSL TLS 1.3 Key schedule: HKDF expand fails with prk_len < hash_len
-depends_on:PSA_WANT_ALG_SHA_256
-psa_hkdf_expand_ret:PSA_ALG_SHA_256:16:32:PSA_ERROR_INVALID_ARGUMENT
-
-SSL TLS 1.3 Key schedule: HKDF expand fails with okm_len / hash_len > 255
-psa_hkdf_expand_ret:PSA_ALG_SHA_256:32:8192:PSA_ERROR_INVALID_ARGUMENT
-
-SSL TLS 1.3 Key schedule: HKDF expand fails with key import
-depends_on:PSA_WANT_ALG_SHA_256
-psa_hkdf_expand_ret:PSA_ALG_SHA_256:32:32:PSA_ERROR_INSUFFICIENT_MEMORY
-
 SSL TLS 1.3 Key schedule: HKDF Expand Label #1
 # Vector from TLS 1.3 Byte by Byte (https://tls13.ulfheim.net/)
 # Server handshake traffic secret -> Server traffic key
diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function
index 8d683ad..b8caca3 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -2101,14 +2101,9 @@
     TEST_ASSERT( mbedtls_ssl_is_handshake_over( &client.ssl ) == 1 );
 
     /* Make sure server state is moved to HANDSHAKE_OVER also. */
-    TEST_ASSERT( mbedtls_move_handshake_to_state( &(server.ssl),
-                                                  &(client.ssl),
-                                                  MBEDTLS_SSL_HANDSHAKE_OVER )
-                 ==  expected_handshake_result );
-    if( expected_handshake_result != 0 )
-    {
-        goto exit;
-    }
+    TEST_EQUAL( mbedtls_move_handshake_to_state( &(server.ssl),
+                                                 &(client.ssl),
+                                                 MBEDTLS_SSL_HANDSHAKE_OVER ), 0 );
 
     TEST_ASSERT( mbedtls_ssl_is_handshake_over( &server.ssl ) == 1 );
 
@@ -3964,157 +3959,6 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS:MBEDTLS_SSL_PROTO_TLS1_3 */
-void psa_hkdf_extract( int alg,
-                       data_t *ikm,
-                       data_t *salt,
-                       data_t *prk )
-{
-    unsigned char *output_prk = NULL;
-    size_t output_prk_size, output_prk_len;
-
-    PSA_INIT( );
-
-    output_prk_size = PSA_HASH_LENGTH( alg );
-    ASSERT_ALLOC( output_prk, output_prk_size );
-
-    PSA_ASSERT( mbedtls_psa_hkdf_extract( alg, salt->x, salt->len,
-                                          ikm->x, ikm->len,
-                                          output_prk, output_prk_size,
-                                          &output_prk_len ) );
-
-    ASSERT_COMPARE( output_prk, output_prk_len, prk->x, prk->len );
-
-exit:
-    mbedtls_free( output_prk );
-
-    PSA_DONE( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS:MBEDTLS_SSL_PROTO_TLS1_3 */
-void psa_hkdf_extract_ret( int alg, int ret )
-{
-    int output_ret;
-    unsigned char *salt = NULL;
-    unsigned char *ikm = NULL;
-    unsigned char *prk = NULL;
-    size_t salt_len, ikm_len, prk_len;
-
-    PSA_INIT( );
-
-    ASSERT_ALLOC( prk, PSA_MAC_MAX_SIZE);
-    salt_len = 0;
-    ikm_len = 0;
-    prk_len = 0;
-
-    output_ret = mbedtls_psa_hkdf_extract( alg, salt, salt_len,
-                                           ikm, ikm_len,
-                                           prk, PSA_MAC_MAX_SIZE, &prk_len );
-    TEST_ASSERT( output_ret == ret );
-    TEST_ASSERT( prk_len == 0 );
-
-exit:
-    mbedtls_free( prk );
-
-    PSA_DONE( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS:MBEDTLS_SSL_PROTO_TLS1_3 */
-void psa_hkdf_expand( int alg,
-                      data_t *info,
-                      data_t *prk,
-                      data_t *okm )
-{
-    enum { OKM_LEN  = 1024 };
-    unsigned char *output_okm = NULL;
-
-    PSA_INIT( );
-
-    ASSERT_ALLOC( output_okm, OKM_LEN );
-    TEST_ASSERT( prk->len == PSA_HASH_LENGTH( alg ) );
-    TEST_ASSERT( okm->len < OKM_LEN );
-
-    PSA_ASSERT( mbedtls_psa_hkdf_expand( alg, prk->x, prk->len,
-                                         info->x, info->len,
-                                         output_okm, OKM_LEN ) );
-
-    ASSERT_COMPARE( output_okm, okm->len, okm->x, okm->len );
-
-exit:
-    mbedtls_free( output_okm );
-
-    PSA_DONE( );
-}
-/* END_CASE */
-
-/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS:MBEDTLS_SSL_PROTO_TLS1_3 */
-void psa_hkdf_expand_ret( int alg, int prk_len, int okm_len, int ret )
-{
-    int output_ret;
-    unsigned char *info = NULL;
-    unsigned char *prk = NULL;
-    unsigned char *okm = NULL;
-    size_t info_len;
-    size_t i;
-    mbedtls_svc_key_id_t *keys = NULL;
-
-    PSA_INIT( );
-
-    info_len = 0;
-
-    if( prk_len > 0 )
-        ASSERT_ALLOC( prk, prk_len );
-
-    if( okm_len > 0 )
-        ASSERT_ALLOC( okm, okm_len );
-
-    if( ret == PSA_ERROR_INSUFFICIENT_MEMORY )
-    {
-        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-
-        /* Reserve all key slot to make the key import fail. */
-        psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_MESSAGE );
-        psa_set_key_algorithm( &attributes, alg );
-        psa_set_key_type( &attributes, PSA_KEY_TYPE_HMAC );
-
-        ASSERT_ALLOC( keys, MBEDTLS_PSA_KEY_SLOT_COUNT );
-
-        for( i = 0; i < MBEDTLS_PSA_KEY_SLOT_COUNT; i++ )
-        {
-            /* Do not use the 0 value because it will be passed to
-               mbedtls_psa_hkdf_expand */
-            prk[0] = i + 1;
-            keys[i] = MBEDTLS_SVC_KEY_ID_INIT;
-            psa_import_key( &attributes, prk, prk_len, &keys[i] );
-        }
-
-        /* reset prk buffer */
-        prk[0] = 0;
-    }
-
-    output_ret = mbedtls_psa_hkdf_expand( alg, prk, prk_len,
-                                          info, info_len,
-                                          okm, okm_len );
-    TEST_ASSERT( output_ret == ret );
-
-exit:
-    mbedtls_free( prk );
-    mbedtls_free( okm );
-
-   if( ret == PSA_ERROR_INSUFFICIENT_MEMORY )
-   {
-        for( i = 0; i < MBEDTLS_PSA_KEY_SLOT_COUNT; i++ )
-            psa_destroy_key( keys[i] );
-
-        mbedtls_free( keys );
-   }
-
-    PSA_DONE( );
-}
-/* END_CASE */
-
 /* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3 */
 void ssl_tls13_hkdf_expand_label( int hash_alg,
                                   data_t *secret,
@@ -4980,7 +4824,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ENTROPY_C:MBEDTLS_CTR_DRBG_C */
+/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ENTROPY_C:MBEDTLS_CTR_DRBG_C */
 void app_data( int mfl, int cli_msg_len, int srv_msg_len,
                int expected_cli_fragments,
                int expected_srv_fragments, int dtls )
@@ -4994,6 +4838,9 @@
     options.expected_cli_fragments = expected_cli_fragments;
     options.expected_srv_fragments = expected_srv_fragments;
     options.dtls = dtls;
+#if ! defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    options.expected_negotiated_version = MBEDTLS_SSL_VERSION_TLS1_3;
+#endif
 
     perform_handshake( &options );
     /* The goto below is used to avoid an "unused label" warning.*/
@@ -5001,7 +4848,7 @@
 }
 /* END_CASE */
 
-/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:!MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ENTROPY_C:MBEDTLS_CTR_DRBG_C */
+/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_ENTROPY_C:MBEDTLS_CTR_DRBG_C */
 void app_data_tls( int mfl, int cli_msg_len, int srv_msg_len,
                    int expected_cli_fragments,
                    int expected_srv_fragments )
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index d04b7d8..eb9e9aa 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -294,6 +294,10 @@
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA512_C:MBEDTLS_RSA_C:!MBEDTLS_X509_REMOVE_INFO
 mbedtls_x509_csr_info:"data_files/server1.req.sha512":"CSR version   \: 1\nsubject name  \: C=NL, O=PolarSSL, CN=PolarSSL Server 1\nsigned using  \: RSA with SHA-512\nRSA key size  \: 2048 bits\n"
 
+X509 CSR Information RSA with SHA-256, containing commas
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA256_C:MBEDTLS_RSA_C:MBEDTS_X509_INFO
+mbedtls_x509_csr_info:"data_files/server1.req.commas.sha256":"CSR version   \: 1\nsubject name  \: C=NL, O=PolarSSL\, Commas, CN=PolarSSL Server 1\nsigned using  \: RSA with SHA-256\nRSA key size  \: 2048 bits\n"
+
 X509 CSR Information EC with SHA1
 depends_on:MBEDTLS_ECDSA_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA1_C:!MBEDTLS_X509_REMOVE_INFO
 mbedtls_x509_csr_info:"data_files/server5.req.sha1":"CSR version   \: 1\nsubject name  \: C=NL, O=PolarSSL, CN=localhost\nsigned using  \: ECDSA with SHA1\nEC key size   \: 256 bits\n"
@@ -375,6 +379,42 @@
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
 mbedtls_x509_dn_gets:"data_files/server2.crt":"issuer":"C=NL, O=PolarSSL, CN=PolarSSL Test CA"
 
+X509 Get Distinguished Name #5
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
+mbedtls_x509_dn_gets:"data_files/server1.commas.crt":"subject":"C=NL, O=PolarSSL\, Commas, CN=PolarSSL Server 1"
+
+X509 Get Modified DN #1
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
+mbedtls_x509_dn_gets_subject_replace:"data_files/server1.crt":"Modified":"C=NL, O=Modified, CN=PolarSSL Server 1":0
+
+X509 Get Modified DN #2 Name exactly 255 bytes
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
+mbedtls_x509_dn_gets_subject_replace:"data_files/server1.crt":"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345":"C=NL, O=123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345, CN=PolarSSL Server 1":0
+
+X509 Get Modified DN #3 Name exceeds 255 bytes
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
+mbedtls_x509_dn_gets_subject_replace:"data_files/server1.crt":"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456":"":MBEDTLS_ERR_X509_BUFFER_TOO_SMALL
+
+X509 Get Modified DN #4 Name exactly 255 bytes, with comma requiring escaping
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
+mbedtls_x509_dn_gets_subject_replace:"data_files/server1.crt":"1234567890,1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234":"":MBEDTLS_ERR_X509_BUFFER_TOO_SMALL
+
+X509 Get Modified DN #5 Name exactly 255 bytes, ending with comma requiring escaping
+depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_SHA1_C
+mbedtls_x509_dn_gets_subject_replace:"data_files/server1.crt":"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234,":"":MBEDTLS_ERR_X509_BUFFER_TOO_SMALL
+
+X509 Get Next DN #1 No Multivalue RDNs
+mbedtls_x509_dn_get_next:"C=NL, O=PolarSSL, CN=PolarSSL Server 1":0:"C O CN":3:"C=NL, O=PolarSSL, CN=PolarSSL Server 1"
+
+X509 Get Next DN #2 Initial Multivalue RDN
+mbedtls_x509_dn_get_next:"C=NL, O=PolarSSL, CN=PolarSSL Server 1":0x01:"C CN":2:"C=NL + O=PolarSSL, CN=PolarSSL Server 1"
+
+X509 Get Next DN #3 Single Multivalue RDN
+mbedtls_x509_dn_get_next:"C=NL, O=PolarSSL, CN=PolarSSL Server 1":0x03:"C":1:"C=NL + O=PolarSSL + CN=PolarSSL Server 1"
+
+X509 Get Next DN #4 Consecutive Multivalue RDNs
+mbedtls_x509_dn_get_next:"C=NL, O=PolarSSL, title=Example, CN=PolarSSL Server 1":0x05:"C title":2:"C=NL + O=PolarSSL, title=Example + CN=PolarSSL Server 1"
+
 X509 Time Expired #1
 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_HAVE_TIME_DATE:MBEDTLS_SHA1_C
 mbedtls_x509_time_is_past:"data_files/server1.crt":"valid_from":1
diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function
index 1d06fe3..3bb68d9 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -758,6 +758,37 @@
 /* END_CASE */
 
 /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:!MBEDTLS_X509_REMOVE_INFO */
+void mbedtls_x509_dn_gets_subject_replace( char * crt_file, char * new_subject_ou, char * result_str, int ret )
+{
+    mbedtls_x509_crt   crt;
+    char buf[2000];
+    int res = 0;
+
+    mbedtls_x509_crt_init( &crt );
+    memset( buf, 0, 2000 );
+
+    TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 );
+    crt.subject.next->val.p = (unsigned char *) new_subject_ou;
+    crt.subject.next->val.len = strlen( new_subject_ou );
+
+    res =  mbedtls_x509_dn_gets( buf, 2000, &crt.subject );
+
+    if ( ret != 0 )
+    {
+        TEST_ASSERT( res == ret );
+    }
+    else
+    {
+        TEST_ASSERT( res != -1 );
+        TEST_ASSERT( res != -2 );
+        TEST_ASSERT( strcmp( buf, result_str ) == 0 );
+    }
+exit:
+    mbedtls_x509_crt_free( &crt );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:!MBEDTLS_X509_REMOVE_INFO */
 void mbedtls_x509_dn_gets( char * crt_file, char * entity, char * result_str )
 {
     mbedtls_x509_crt   crt;
@@ -785,6 +816,77 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_X509_CREATE_C:MBEDTLS_X509_USE_C:MBEDTLS_X509_CRT_PARSE_C:!MBEDTLS_X509_REMOVE_INFO */
+void mbedtls_x509_dn_get_next( char * name_str, int next_merged, char * expected_oids, int exp_count, char * exp_dn_gets )
+{
+    int ret = 0, i;
+    size_t len = 0, out_size;
+    mbedtls_asn1_named_data *names = NULL;
+    mbedtls_x509_name parsed, *parsed_cur, *parsed_prv;
+    // Size of buf is maximum required for test cases
+    unsigned char buf[80], *out = NULL, *c;
+    const char *short_name;
+
+    memset( &parsed, 0, sizeof( parsed ) );
+    memset( buf, 0, sizeof( buf ) );
+    c = buf + sizeof( buf );
+    // Additional size required for trailing space
+    out_size = strlen( expected_oids ) + 2;
+    ASSERT_ALLOC( out, out_size );
+
+    TEST_EQUAL( mbedtls_x509_string_to_names( &names, name_str ), 0 );
+
+    ret = mbedtls_x509_write_names( &c, buf, names );
+    TEST_LE_S( 0, ret );
+
+    TEST_EQUAL( mbedtls_asn1_get_tag( &c, buf + sizeof( buf ), &len,
+                       MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ), 0 );
+    TEST_EQUAL( mbedtls_x509_get_name( &c, buf + sizeof( buf ), &parsed ), 0 );
+
+    // Iterate over names and set next_merged nodes
+    parsed_cur = &parsed;
+    for( ; next_merged != 0 && parsed_cur != NULL; next_merged = next_merged >> 1 )
+    {
+        parsed_cur->next_merged = next_merged & 0x01;
+        parsed_cur = parsed_cur->next;
+    }
+
+    // Iterate over RDN nodes and print OID of first element to buffer
+    parsed_cur = &parsed;
+    len = 0;
+    for( i = 0; parsed_cur != NULL; i++ )
+    {
+        TEST_EQUAL( mbedtls_oid_get_attr_short_name( &parsed_cur->oid,
+                                                      &short_name ), 0 );
+        len += mbedtls_snprintf( (char*) out + len, out_size - len, "%s ", short_name );
+        parsed_cur = mbedtls_x509_dn_get_next( parsed_cur );
+    }
+    out[len-1] = 0;
+
+    TEST_EQUAL( exp_count, i );
+    TEST_EQUAL( strcmp( (char *) out, expected_oids ), 0 );
+    mbedtls_free( out );
+    out = NULL;
+
+    out_size = strlen( exp_dn_gets ) + 1;
+    ASSERT_ALLOC( out, out_size );
+
+    TEST_LE_S( 0, mbedtls_x509_dn_gets( (char *) out, out_size, &parsed ) );
+    TEST_EQUAL( strcmp( (char *) out, exp_dn_gets ), 0 );
+exit:
+    mbedtls_free( out );
+    mbedtls_asn1_free_named_data_list( &names );
+
+    parsed_cur = parsed.next;
+    while( parsed_cur != 0 )
+    {
+        parsed_prv = parsed_cur;
+        parsed_cur = parsed_cur->next;
+        mbedtls_free( parsed_prv );
+    }
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C */
 void mbedtls_x509_time_is_past( char * crt_file, char * entity, int result )
 {
diff --git a/tests/suites/test_suite_x509write.data b/tests/suites/test_suite_x509write.data
index 8d9a11a..91fdd86 100644
--- a/tests/suites/test_suite_x509write.data
+++ b/tests/suites/test_suite_x509write.data
@@ -139,7 +139,7 @@
 x509_crt_check:"data_files/server5.key":"":"C=NL,O=PolarSSL,CN=PolarSSL Server 1":"data_files/test-ca2.key":"PolarSSLTest":"C=NL,O=PolarSSL,CN=Polarssl Test EC CA":"1":"20190210144406":"20290210144406":MBEDTLS_MD_SHA256:0:0:0:0:1:-1:"":2:0:"data_files/test-ca2.crt"
 
 X509 String to Names #1
-mbedtls_x509_string_to_names:"C=NL,O=Offspark\, Inc., OU=PolarSSL":"C=NL, O=Offspark, Inc., OU=PolarSSL":0
+mbedtls_x509_string_to_names:"C=NL,O=Offspark\, Inc., OU=PolarSSL":"C=NL, O=Offspark\, Inc., OU=PolarSSL":0
 
 X509 String to Names #2
 mbedtls_x509_string_to_names:"C=NL, O=Offspark, Inc., OU=PolarSSL":"":MBEDTLS_ERR_X509_UNKNOWN_OID