diff -Nru openssl-3.2.1/debian/changelog openssl-3.2.1/debian/changelog
--- openssl-3.2.1/debian/changelog	2024-07-11 17:11:09.000000000 +0800
+++ openssl-3.2.1/debian/changelog	2025-02-25 14:23:13.000000000 +0800
@@ -1,3 +1,16 @@
+openssl (3.2.1-ok7) nile; urgency=medium
+
+  * Fix the CVE-2024-13176
+
+ -- songjuntao <songjuntao@kylinos.cn>  Tue, 25 Feb 2025 14:23:13 +0800
+
+openssl (3.2.1-ok6) nile; urgency=medium
+
+  * Fix the CVE-2024-2511, CVE-2024-4603, CVE-2024-4741, CVE-2024-5535,
+    CVE-2024-6119, CVE-2024-9143
+
+ -- songjuntao <songjuntao@kylinos.cn>  Fri, 24 Jan 2025 11:22:34 +0800
+
 openssl (3.2.1-ok5) nile; urgency=medium
 
   * Non-maintainer upload.
diff -Nru openssl-3.2.1/debian/patches/14-CVE.patch openssl-3.2.1/debian/patches/14-CVE.patch
--- openssl-3.2.1/debian/patches/14-CVE.patch	1970-01-01 08:00:00.000000000 +0800
+++ openssl-3.2.1/debian/patches/14-CVE.patch	2025-02-25 14:23:13.000000000 +0800
@@ -0,0 +1,3356 @@
+From: yuejiayuan <yuejiayuan@kylinos.cn>
+Date: Wed, 12 Feb 2025 02:23:26 +0000
+Subject: =?utf-8?b?ITE0IOaPkOS6pOS/ruWkjeWkmuS4qkNWRea8j+a0niBNZXJnZSBwdWxs?=
+ =?utf-8?b?IHJlcXVlc3QgITE0IGZyb20g5a6LY29yd2luL29wZW5reWxpbi9uaWxl?=
+
+---
+ CHANGES.md                                         |  80 ++-
+ NEWS.md                                            |  22 +-
+ crypto/bn/bn_gf2m.c                                |  28 +-
+ crypto/dsa/dsa_check.c                             |  44 +-
+ crypto/x509/v3_utl.c                               |  78 ++-
+ doc/man3/SSL_CTX_set_alpn_select_cb.pod            |  26 +-
+ ssl/quic/quic_tserver.c                            |   2 +-
+ ssl/record/methods/tls_common.c                    |  13 +-
+ ssl/ssl_lib.c                                      |  68 +-
+ ssl/ssl_sess.c                                     |  34 +-
+ ssl/statem/extensions_clnt.c                       |  28 +-
+ ssl/statem/extensions_srvr.c                       |   3 +-
+ ssl/statem/statem_srvr.c                           |   5 +-
+ test/ec_internal_test.c                            |  51 ++
+ test/helpers/handshake.c                           |   6 +
+ test/helpers/ssltestlib.c                          |  33 +
+ test/helpers/ssltestlib.h                          |   2 +
+ .../invalid/p10240_q256_too_big.pem                |  57 ++
+ test/recipes/25-test_eai_data.t                    |  12 +-
+ test/recipes/25-test_eai_data/kdc-cert.pem         |  21 +
+ test/recipes/25-test_eai_data/kdc-root-cert.pem    |  16 +
+ test/recipes/25-test_eai_data/kdc.sh               |  41 ++
+ test/recipes/70-test_npn.t                         |  73 +++
+ test/ssl-tests/08-npn.cnf                          | 553 +++++++++--------
+ test/ssl-tests/08-npn.cnf.in                       |  35 ++
+ test/ssl-tests/09-alpn.cnf                         |  66 +-
+ test/ssl-tests/09-alpn.cnf.in                      |  33 +
+ test/sslapitest.c                                  | 683 ++++++++++++++++++++-
+ test/sslbuffertest.c                               | 174 ++++++
+ util/perl/TLSProxy/Message.pm                      |   9 +
+ util/perl/TLSProxy/NextProto.pm                    |  54 ++
+ util/perl/TLSProxy/Proxy.pm                        |   1 +
+ 32 files changed, 1998 insertions(+), 353 deletions(-)
+ create mode 100644 test/recipes/15-test_dsaparam_data/invalid/p10240_q256_too_big.pem
+ create mode 100644 test/recipes/25-test_eai_data/kdc-cert.pem
+ create mode 100644 test/recipes/25-test_eai_data/kdc-root-cert.pem
+ create mode 100755 test/recipes/25-test_eai_data/kdc.sh
+ create mode 100644 test/recipes/70-test_npn.t
+ create mode 100644 util/perl/TLSProxy/NextProto.pm
+
+diff --git a/CHANGES.md b/CHANGES.md
+index ca29762ac21e..b8f07885c368 100644
+--- a/CHANGES.md
++++ b/CHANGES.md
+@@ -27,6 +27,81 @@ OpenSSL 3.2
+ 
+ ### Changes between 3.2.0 and 3.2.1 [30 Jan 2024]
+ 
++ * Fixed possible OOB memory access with invalid low-level GF(2^m) elliptic
++   curve parameters.
++
++   Use of the low-level GF(2^m) elliptic curve APIs with untrusted
++   explicit values for the field polynomial can lead to out-of-bounds memory
++   reads or writes.
++   Applications working with "exotic" explicit binary (GF(2^m)) curve
++   parameters, that make it possible to represent invalid field polynomials
++   with a zero constant term, via the above or similar APIs, may terminate
++   abruptly as a result of reading or writing outside of array bounds. Remote
++   code execution cannot easily be ruled out.
++
++   ([CVE-2024-9143])
++
++   *Viktor Dukhovni*
++
++ * Fixed possible denial of service in X.509 name checks.
++
++   Applications performing certificate name checks (e.g., TLS clients checking
++   server certificates) may attempt to read an invalid memory address when
++   comparing the expected name with an `otherName` subject alternative name of
++   an X.509 certificate. This may result in an exception that terminates the
++   application program.
++
++   ([CVE-2024-6119])
++
++   *Viktor Dukhovni*
++
++ * Fixed possible buffer overread in SSL_select_next_proto().
++
++   Calling the OpenSSL API function SSL_select_next_proto with an empty
++   supported client protocols buffer may cause a crash or memory contents
++   to be sent to the peer.
++
++   ([CVE-2024-5535])
++
++   *Matt Caswell*
++
++ * Fixed an issue where checking excessively long DSA keys or parameters may
++   be very slow.
++
++   Applications that use the functions EVP_PKEY_param_check() or
++   EVP_PKEY_public_check() to check a DSA public key or DSA parameters may
++   experience long delays. Where the key or parameters that are being checked
++   have been obtained from an untrusted source this may lead to a Denial of
++   Service.
++
++   To resolve this issue DSA keys larger than OPENSSL_DSA_MAX_MODULUS_BITS
++   will now fail the check immediately with a DSA_R_MODULUS_TOO_LARGE error
++   reason.
++
++   ([CVE-2024-4603])
++
++   *Tomáš Mráz*
++
++
++ * Fixed an issue where some non-default TLS server configurations can cause
++   unbounded memory growth when processing TLSv1.3 sessions. An attacker may
++   exploit certain server configurations to trigger unbounded memory growth that
++   would lead to a Denial of Service
++
++   This problem can occur in TLSv1.3 if the non-default SSL_OP_NO_TICKET option
++   is being used (but not if early_data is also configured and the default
++   anti-replay protection is in use). In this case, under certain conditions,
++   the session cache can get into an incorrect state and it will fail to flush
++   properly as it fills. The session cache will continue to grow in an unbounded
++   manner. A malicious client could deliberately create the scenario for this
++   failure to force a Denial of Service. It may also happen by accident in
++   normal operation.
++
++   ([CVE-2024-2511])
++
++   *Matt Caswell*
++
++
+  * A file in PKCS12 format can contain certificates and keys and may come from
+    an untrusted source. The PKCS12 specification allows certain fields to be
+    NULL, but OpenSSL did not correctly check for this case. A fix has been
+@@ -20391,7 +20466,10 @@ ndif
+    *Edward Bishop <ebishop@spyglass.com>*
+ 
+ <!-- Links -->
+-
++[CVE-2024-9143]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-9143
++[CVE-2024-6119]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-6119
++[CVE-2024-5535]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-5535
++[CVE-2024-2511]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-2511
+ [CVE-2024-0727]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-0727
+ [CVE-2023-6237]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-6237
+ [CVE-2023-6129]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-6129
+diff --git a/NEWS.md b/NEWS.md
+index d35d2f81b182..70e8dc8ee07a 100644
+--- a/NEWS.md
++++ b/NEWS.md
+@@ -22,6 +22,23 @@ OpenSSL 3.2
+ 
+ ### Major changes between OpenSSL 3.2.0 and OpenSSL 3.2.1 [30 Jan 2024]
+ 
++This release incorporates the following bug fixes and mitigations:
++
++  * Fixed possible OOB memory access with invalid low-level GF(2^m) elliptic
++    curve parameters.
++    ([CVE-2024-9143])
++
++  * Fixed possible denial of service in X.509 name checks
++    ([CVE-2024-6119])
++
++  * Fixed possible buffer overread in SSL_select_next_proto()
++    ([CVE-2024-5535])
++
++
++  * Fixed unbounded memory growth with session handling in TLSv1.3
++    ([CVE-2024-2511])
++
++
+ OpenSSL 3.2.1 is a security patch release. The most severe CVE fixed in this
+ release is Low.
+ 
+@@ -1579,7 +1596,10 @@ OpenSSL 0.9.x
+   * Support for various new platforms
+ 
+ <!-- Links -->
+-
++[CVE-2024-9143]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-9143
++[CVE-2024-6119]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-6119
++[CVE-2024-5535]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-5535
++[CVE-2024-2511]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-2511
+ [CVE-2024-0727]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-0727
+ [CVE-2023-6237]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-6237
+ [CVE-2023-6129]: https://www.openssl.org/news/vulnerabilities.html#CVE-2023-6129
+diff --git a/crypto/bn/bn_gf2m.c b/crypto/bn/bn_gf2m.c
+index 444c5ca7a375..ae7e9d751c29 100644
+--- a/crypto/bn/bn_gf2m.c
++++ b/crypto/bn/bn_gf2m.c
+@@ -15,6 +15,7 @@
+ #include "bn_local.h"
+ 
+ #ifndef OPENSSL_NO_EC2M
++# include <openssl/ec.h>
+ 
+ /*
+  * Maximum number of iterations before BN_GF2m_mod_solve_quad_arr should
+@@ -1130,16 +1131,26 @@ int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ /*
+  * Convert the bit-string representation of a polynomial ( \sum_{i=0}^n a_i *
+  * x^i) into an array of integers corresponding to the bits with non-zero
+- * coefficient.  Array is terminated with -1. Up to max elements of the array
+- * will be filled.  Return value is total number of array elements that would
+- * be filled if array was large enough.
++ * coefficient.  The array is intended to be suitable for use with
++ * `BN_GF2m_mod_arr()`, and so the constant term of the polynomial must not be
++ * zero.  This translates to a requirement that the input BIGNUM `a` is odd.
++ *
++ * Given sufficient room, the array is terminated with -1.  Up to max elements
++ * of the array will be filled.
++ *
++ * The return value is total number of array elements that would be filled if
++ * array was large enough, including the terminating `-1`.  It is `0` when `a`
++ * is not odd or the constant term is zero contrary to requirement.
++ *
++ * The return value is also `0` when the leading exponent exceeds
++ * `OPENSSL_ECC_MAX_FIELD_BITS`, this guards against CPU exhaustion attacks,
+  */
+ int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max)
+ {
+     int i, j, k = 0;
+     BN_ULONG mask;
+ 
+-    if (BN_is_zero(a))
++    if (!BN_is_odd(a))
+         return 0;
+ 
+     for (i = a->top - 1; i >= 0; i--) {
+@@ -1157,12 +1168,13 @@ int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max)
+         }
+     }
+ 
+-    if (k < max) {
++    if (k > 0 && p[0] > OPENSSL_ECC_MAX_FIELD_BITS)
++        return 0;
++
++    if (k < max)
+         p[k] = -1;
+-        k++;
+-    }
+ 
+-    return k;
++    return k + 1;
+ }
+ 
+ /*
+diff --git a/crypto/dsa/dsa_check.c b/crypto/dsa/dsa_check.c
+index fb0e9129a295..122449a7bf08 100644
+--- a/crypto/dsa/dsa_check.c
++++ b/crypto/dsa/dsa_check.c
+@@ -19,8 +19,34 @@
+ #include "dsa_local.h"
+ #include "crypto/dsa.h"
+ 
++static int dsa_precheck_params(const DSA *dsa, int *ret)
++{
++    if (dsa->params.p == NULL || dsa->params.q == NULL) {
++        ERR_raise(ERR_LIB_DSA, DSA_R_BAD_FFC_PARAMETERS);
++        *ret = FFC_CHECK_INVALID_PQ;
++        return 0;
++    }
++
++    if (BN_num_bits(dsa->params.p) > OPENSSL_DSA_MAX_MODULUS_BITS) {
++        ERR_raise(ERR_LIB_DSA, DSA_R_MODULUS_TOO_LARGE);
++        *ret = FFC_CHECK_INVALID_PQ;
++        return 0;
++    }
++
++    if (BN_num_bits(dsa->params.q) >= BN_num_bits(dsa->params.p)) {
++        ERR_raise(ERR_LIB_DSA, DSA_R_BAD_Q_VALUE);
++        *ret = FFC_CHECK_INVALID_PQ;
++        return 0;
++    }
++
++    return 1;
++}
++
+ int ossl_dsa_check_params(const DSA *dsa, int checktype, int *ret)
+ {
++    if (!dsa_precheck_params(dsa, ret))
++        return 0;
++
+     if (checktype == OSSL_KEYMGMT_VALIDATE_QUICK_CHECK)
+         return ossl_ffc_params_simple_validate(dsa->libctx, &dsa->params,
+                                                FFC_PARAM_TYPE_DSA, ret);
+@@ -39,6 +65,9 @@ int ossl_dsa_check_params(const DSA *dsa, int checktype, int *ret)
+  */
+ int ossl_dsa_check_pub_key(const DSA *dsa, const BIGNUM *pub_key, int *ret)
+ {
++    if (!dsa_precheck_params(dsa, ret))
++        return 0;
++
+     return ossl_ffc_validate_public_key(&dsa->params, pub_key, ret)
+            && *ret == 0;
+ }
+@@ -50,6 +79,9 @@ int ossl_dsa_check_pub_key(const DSA *dsa, const BIGNUM *pub_key, int *ret)
+  */
+ int ossl_dsa_check_pub_key_partial(const DSA *dsa, const BIGNUM *pub_key, int *ret)
+ {
++    if (!dsa_precheck_params(dsa, ret))
++        return 0;
++
+     return ossl_ffc_validate_public_key_partial(&dsa->params, pub_key, ret)
+            && *ret == 0;
+ }
+@@ -58,8 +90,10 @@ int ossl_dsa_check_priv_key(const DSA *dsa, const BIGNUM *priv_key, int *ret)
+ {
+     *ret = 0;
+ 
+-    return (dsa->params.q != NULL
+-            && ossl_ffc_validate_private_key(dsa->params.q, priv_key, ret));
++    if (!dsa_precheck_params(dsa, ret))
++        return 0;
++
++    return ossl_ffc_validate_private_key(dsa->params.q, priv_key, ret);
+ }
+ 
+ /*
+@@ -72,8 +106,10 @@ int ossl_dsa_check_pairwise(const DSA *dsa)
+     BN_CTX *ctx = NULL;
+     BIGNUM *pub_key = NULL;
+ 
+-    if (dsa->params.p == NULL
+-        || dsa->params.g == NULL
++    if (!dsa_precheck_params(dsa, &ret))
++        return 0;
++
++    if (dsa->params.g == NULL
+         || dsa->priv_key == NULL
+         || dsa->pub_key == NULL)
+         return 0;
+diff --git a/crypto/x509/v3_utl.c b/crypto/x509/v3_utl.c
+index 1a1817499519..a09414c972fa 100644
+--- a/crypto/x509/v3_utl.c
++++ b/crypto/x509/v3_utl.c
+@@ -916,36 +916,64 @@ static int do_x509_check(X509 *x, const char *chk, size_t chklen,
+             ASN1_STRING *cstr;
+ 
+             gen = sk_GENERAL_NAME_value(gens, i);
+-            if ((gen->type == GEN_OTHERNAME) && (check_type == GEN_EMAIL)) {
+-                if (OBJ_obj2nid(gen->d.otherName->type_id) ==
+-                    NID_id_on_SmtpUTF8Mailbox) {
+-                    san_present = 1;
+-
+-                    /*
+-                     * If it is not a UTF8String then that is unexpected and we
+-                     * treat it as no match
+-                     */
+-                    if (gen->d.otherName->value->type == V_ASN1_UTF8STRING) {
+-                        cstr = gen->d.otherName->value->value.utf8string;
+-
+-                        /* Positive on success, negative on error! */
+-                        if ((rv = do_check_string(cstr, 0, equal, flags,
+-                                                chk, chklen, peername)) != 0)
+-                            break;
+-                    }
+-                } else
++            switch (gen->type) {
++            default:
++                continue;
++            case GEN_OTHERNAME:
++		switch (OBJ_obj2nid(gen->d.otherName->type_id)) {
++                default:
+                     continue;
+-            } else {
+-                if ((gen->type != check_type) && (gen->type != GEN_OTHERNAME))
++                case NID_id_on_SmtpUTF8Mailbox:
++                    /*-
++                     * https://datatracker.ietf.org/doc/html/rfc8398#section-3
++                     *
++                     *   Due to name constraint compatibility reasons described
++                     *   in Section 6, SmtpUTF8Mailbox subjectAltName MUST NOT
++                     *   be used unless the local-part of the email address
++                     *   contains non-ASCII characters. When the local-part is
++                     *   ASCII, rfc822Name subjectAltName MUST be used instead
++                     *   of SmtpUTF8Mailbox. This is compatible with legacy
++                     *   software that supports only rfc822Name (and not
++                     *   SmtpUTF8Mailbox). [...]
++                     *
++                     *   SmtpUTF8Mailbox is encoded as UTF8String.
++                     *
++                     * If it is not a UTF8String then that is unexpected, and
++                     * we ignore the invalid SAN (neither set san_present nor
++                     * consider it a candidate for equality).  This does mean
++                     * that the subject CN may be considered, as would be the
++                     * case when the malformed SmtpUtf8Mailbox SAN is instead
++                     * simply absent.
++                     *
++                     * When CN-ID matching is not desirable, applications can
++                     * choose to turn it off, doing so is at this time a best
++                     * practice.
++                     */
++                    if (check_type != GEN_EMAIL
++                        || gen->d.otherName->value->type != V_ASN1_UTF8STRING)
++                        continue;
++                    alt_type = 0;
++                    cstr = gen->d.otherName->value->value.utf8string;
++                    break;
++                }
++                break;
++            case GEN_EMAIL:
++                if (check_type != GEN_EMAIL)
+                     continue;
+-            }
+-            san_present = 1;
+-            if (check_type == GEN_EMAIL)
+                 cstr = gen->d.rfc822Name;
+-            else if (check_type == GEN_DNS)
++                break;
++            case GEN_DNS:
++                if (check_type != GEN_DNS)
++                    continue;
+                 cstr = gen->d.dNSName;
+-            else
++                break;
++            case GEN_IPADD:
++                if (check_type != GEN_IPADD)
++                    continue;
+                 cstr = gen->d.iPAddress;
++                break;
++            }
++            san_present = 1;
+             /* Positive on success, negative on error! */
+             if ((rv = do_check_string(cstr, alt_type, equal, flags,
+                                       chk, chklen, peername)) != 0)
+diff --git a/doc/man3/SSL_CTX_set_alpn_select_cb.pod b/doc/man3/SSL_CTX_set_alpn_select_cb.pod
+index 05fee2fbecbc..79e1a252f6bf 100644
+--- a/doc/man3/SSL_CTX_set_alpn_select_cb.pod
++++ b/doc/man3/SSL_CTX_set_alpn_select_cb.pod
+@@ -52,7 +52,8 @@ SSL_select_next_proto, SSL_get0_alpn_selected, SSL_get0_next_proto_negotiated
+ SSL_CTX_set_alpn_protos() and SSL_set_alpn_protos() are used by the client to
+ set the list of protocols available to be negotiated. The B<protos> must be in
+ protocol-list format, described below. The length of B<protos> is specified in
+-B<protos_len>.
++B<protos_len>. Setting B<protos_len> to 0 clears any existing list of ALPN
++protocols and no ALPN extension will be sent to the server.
+ 
+ SSL_CTX_set_alpn_select_cb() sets the application callback B<cb> used by a
+ server to select which protocol to use for the incoming connection. When B<cb>
+@@ -73,9 +74,16 @@ B<server_len> and B<client>, B<client_len> must be in the protocol-list format
+ described below. The first item in the B<server>, B<server_len> list that
+ matches an item in the B<client>, B<client_len> list is selected, and returned
+ in B<out>, B<outlen>. The B<out> value will point into either B<server> or
+-B<client>, so it should be copied immediately. If no match is found, the first
+-item in B<client>, B<client_len> is returned in B<out>, B<outlen>. This
+-function can also be used in the NPN callback.
++B<client>, so it should be copied immediately. The client list must include at
++least one valid (nonempty) protocol entry in the list.
++
++The SSL_select_next_proto() helper function can be useful from either the ALPN
++callback or the NPN callback (described below). If no match is found, the first
++item in B<client>, B<client_len> is returned in B<out>, B<outlen> and
++B<OPENSSL_NPN_NO_OVERLAP> is returned. This can be useful when implementating
++the NPN callback. In the ALPN case, the value returned in B<out> and B<outlen>
++must be ignored if B<OPENSSL_NPN_NO_OVERLAP> has been returned from
++SSL_select_next_proto().
+ 
+ SSL_CTX_set_next_proto_select_cb() sets a callback B<cb> that is called when a
+ client needs to select a protocol from the server's provided list, and a
+@@ -85,9 +93,10 @@ must be set to point to the selected protocol (which may be within B<in>).
+ The length of the protocol name must be written into B<outlen>. The
+ server's advertised protocols are provided in B<in> and B<inlen>. The
+ callback can assume that B<in> is syntactically valid. The client must
+-select a protocol. It is fatal to the connection if this callback returns
+-a value other than B<SSL_TLSEXT_ERR_OK>. The B<arg> parameter is the pointer
+-set via SSL_CTX_set_next_proto_select_cb().
++select a protocol (although it may be an empty, zero length protocol). It is
++fatal to the connection if this callback returns a value other than
++B<SSL_TLSEXT_ERR_OK> or if the zero length protocol is selected. The B<arg>
++parameter is the pointer set via SSL_CTX_set_next_proto_select_cb().
+ 
+ SSL_CTX_set_next_protos_advertised_cb() sets a callback B<cb> that is called
+ when a TLS server needs a list of supported protocols for Next Protocol
+@@ -154,7 +163,8 @@ A match was found and is returned in B<out>, B<outlen>.
+ =item OPENSSL_NPN_NO_OVERLAP
+ 
+ No match was found. The first item in B<client>, B<client_len> is returned in
+-B<out>, B<outlen>.
++B<out>, B<outlen> (or B<NULL> and 0 in the case where the first entry in
++B<client> is invalid).
+ 
+ =back
+ 
+diff --git a/ssl/quic/quic_tserver.c b/ssl/quic/quic_tserver.c
+index 3fc51b4a778a..eb3660df781d 100644
+--- a/ssl/quic/quic_tserver.c
++++ b/ssl/quic/quic_tserver.c
+@@ -58,7 +58,7 @@ static int alpn_select_cb(SSL *ssl, const unsigned char **out,
+ 
+     if (srv->args.alpn == NULL) {
+         alpn = alpndeflt;
+-        alpnlen = sizeof(alpn);
++        alpnlen = sizeof(alpndeflt);
+     } else {
+         alpn = srv->args.alpn;
+         alpnlen = srv->args.alpnlen;
+diff --git a/ssl/record/methods/tls_common.c b/ssl/record/methods/tls_common.c
+index 08e519ac7a38..4cc432ee59e1 100644
+--- a/ssl/record/methods/tls_common.c
++++ b/ssl/record/methods/tls_common.c
+@@ -283,6 +283,8 @@ static int tls_release_read_buffer(OSSL_RECORD_LAYER *rl)
+         OPENSSL_cleanse(b->buf, b->len);
+     OPENSSL_free(b->buf);
+     b->buf = NULL;
++    rl->packet = NULL;
++    rl->packet_length = 0;
+     return 1;
+ }
+ 
+@@ -325,6 +327,12 @@ int tls_default_read_n(OSSL_RECORD_LAYER *rl, size_t n, size_t max, int extend,
+         /* ... now we can act as if 'extend' was set */
+     }
+ 
++    if (!ossl_assert(rl->packet != NULL)) {
++        /* does not happen */
++        RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
++        return OSSL_RECORD_RETURN_FATAL;
++    }
++
+     len = rl->packet_length;
+     pkt = rb->buf + align;
+     /*
+@@ -2129,7 +2137,10 @@ int tls_free_buffers(OSSL_RECORD_LAYER *rl)
+     /* Read direction */
+ 
+     /* If we have pending data to be read then fail */
+-    if (rl->curr_rec < rl->num_recs || TLS_BUFFER_get_left(&rl->rbuf) != 0)
++    if (rl->curr_rec < rl->num_recs
++            || rl->curr_rec != rl->num_released
++            || TLS_BUFFER_get_left(&rl->rbuf) != 0
++            || rl->rstate == SSL_ST_READ_BODY)
+         return 0;
+ 
+     return tls_release_read_buffer(rl);
+diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
+index cf59d2dfa572..234a81190d98 100644
+--- a/ssl/ssl_lib.c
++++ b/ssl/ssl_lib.c
+@@ -3547,37 +3547,54 @@ int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
+                           unsigned int server_len,
+                           const unsigned char *client, unsigned int client_len)
+ {
+-    unsigned int i, j;
+-    const unsigned char *result;
+-    int status = OPENSSL_NPN_UNSUPPORTED;
++    PACKET cpkt, csubpkt, spkt, ssubpkt;
++
++    if (!PACKET_buf_init(&cpkt, client, client_len)
++            || !PACKET_get_length_prefixed_1(&cpkt, &csubpkt)
++            || PACKET_remaining(&csubpkt) == 0) {
++        *out = NULL;
++        *outlen = 0;
++        return OPENSSL_NPN_NO_OVERLAP;
++    }
++
++    /*
++     * Set the default opportunistic protocol. Will be overwritten if we find
++     * a match.
++     */
++    *out = (unsigned char *)PACKET_data(&csubpkt);
++    *outlen = (unsigned char)PACKET_remaining(&csubpkt);
+ 
+     /*
+      * For each protocol in server preference order, see if we support it.
+      */
+-    for (i = 0; i < server_len;) {
+-        for (j = 0; j < client_len;) {
+-            if (server[i] == client[j] &&
+-                memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) {
+-                /* We found a match */
+-                result = &server[i];
+-                status = OPENSSL_NPN_NEGOTIATED;
+-                goto found;
++    if (PACKET_buf_init(&spkt, server, server_len)) {
++        while (PACKET_get_length_prefixed_1(&spkt, &ssubpkt)) {
++            if (PACKET_remaining(&ssubpkt) == 0)
++                continue; /* Invalid - ignore it */
++            if (PACKET_buf_init(&cpkt, client, client_len)) {
++                while (PACKET_get_length_prefixed_1(&cpkt, &csubpkt)) {
++                    if (PACKET_equal(&csubpkt, PACKET_data(&ssubpkt),
++                                     PACKET_remaining(&ssubpkt))) {
++                        /* We found a match */
++                        *out = (unsigned char *)PACKET_data(&ssubpkt);
++                        *outlen = (unsigned char)PACKET_remaining(&ssubpkt);
++                        return OPENSSL_NPN_NEGOTIATED;
++                    }
++                }
++                /* Ignore spurious trailing bytes in the client list */
++            } else {
++                /* This should never happen */
++                return OPENSSL_NPN_NO_OVERLAP;
+             }
+-            j += client[j];
+-            j++;
+         }
+-        i += server[i];
+-        i++;
++        /* Ignore spurious trailing bytes in the server list */
+     }
+ 
+-    /* There's no overlap between our protocols and the server's list. */
+-    result = client;
+-    status = OPENSSL_NPN_NO_OVERLAP;
+-
+- found:
+-    *out = (unsigned char *)result + 1;
+-    *outlen = result[0];
+-    return status;
++    /*
++     * There's no overlap between our protocols and the server's list. We use
++     * the default opportunistic protocol selected earlier
++     */
++    return OPENSSL_NPN_NO_OVERLAP;
+ }
+ 
+ #ifndef OPENSSL_NO_NEXTPROTONEG
+@@ -4485,9 +4502,10 @@ void ssl_update_cache(SSL_CONNECTION *s, int mode)
+ 
+     /*
+      * If the session_id_length is 0, we are not supposed to cache it, and it
+-     * would be rather hard to do anyway :-)
++     * would be rather hard to do anyway :-). Also if the session has already
++     * been marked as not_resumable we should not cache it for later reuse.
+      */
+-    if (s->session->session_id_length == 0)
++    if (s->session->session_id_length == 0 || s->session->not_resumable)
+         return;
+ 
+     /*
+diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
+index 3dcc4d81e5bc..5d1ade9efa9d 100644
+--- a/ssl/ssl_sess.c
++++ b/ssl/ssl_sess.c
+@@ -127,16 +127,11 @@ SSL_SESSION *SSL_SESSION_new(void)
+     return ss;
+ }
+ 
+-SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src)
+-{
+-    return ssl_session_dup(src, 1);
+-}
+-
+ /*
+  * Create a new SSL_SESSION and duplicate the contents of |src| into it. If
+  * ticket == 0 then no ticket information is duplicated, otherwise it is.
+  */
+-SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket)
++static SSL_SESSION *ssl_session_dup_intern(const SSL_SESSION *src, int ticket)
+ {
+     SSL_SESSION *dest;
+ 
+@@ -265,6 +260,27 @@ SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket)
+     return NULL;
+ }
+ 
++SSL_SESSION *SSL_SESSION_dup(const SSL_SESSION *src)
++{
++    return ssl_session_dup_intern(src, 1);
++}
++
++/*
++ * Used internally when duplicating a session which might be already shared.
++ * We will have resumed the original session. Subsequently we might have marked
++ * it as non-resumable (e.g. in another thread) - but this copy should be ok to
++ * resume from.
++ */
++SSL_SESSION *ssl_session_dup(const SSL_SESSION *src, int ticket)
++{
++    SSL_SESSION *sess = ssl_session_dup_intern(src, ticket);
++
++    if (sess != NULL)
++        sess->not_resumable = 0;
++
++    return sess;
++}
++
+ const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len)
+ {
+     if (len)
+@@ -503,6 +519,12 @@ SSL_SESSION *lookup_sess_in_cache(SSL_CONNECTION *s,
+                                              sess_id, sess_id_len, &copy);
+ 
+         if (ret != NULL) {
++            if (ret->not_resumable) {
++                /* If its not resumable then ignore this session */
++                if (!copy)
++                    SSL_SESSION_free(ret);
++                return NULL;
++            }
+             ssl_tsan_counter(s->session_ctx,
+                              &s->session_ctx->stats.sess_cb_hit);
+ 
+diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
+index 381a6c9d7b90..ff9c009ee529 100644
+--- a/ssl/statem/extensions_clnt.c
++++ b/ssl/statem/extensions_clnt.c
+@@ -1560,8 +1560,8 @@ int tls_parse_stoc_npn(SSL_CONNECTION *s, PACKET *pkt, unsigned int context,
+     if (sctx->ext.npn_select_cb(SSL_CONNECTION_GET_SSL(s),
+                                 &selected, &selected_len,
+                                 PACKET_data(pkt), PACKET_remaining(pkt),
+-                                sctx->ext.npn_select_cb_arg) !=
+-             SSL_TLSEXT_ERR_OK) {
++                                sctx->ext.npn_select_cb_arg) != SSL_TLSEXT_ERR_OK
++            || selected_len == 0) {
+         SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_BAD_EXTENSION);
+         return 0;
+     }
+@@ -1590,6 +1590,8 @@ int tls_parse_stoc_alpn(SSL_CONNECTION *s, PACKET *pkt, unsigned int context,
+                         X509 *x, size_t chainidx)
+ {
+     size_t len;
++    PACKET confpkt, protpkt;
++    int valid = 0;
+ 
+     /* We must have requested it. */
+     if (!s->s3.alpn_sent) {
+@@ -1608,6 +1610,28 @@ int tls_parse_stoc_alpn(SSL_CONNECTION *s, PACKET *pkt, unsigned int context,
+         SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
+         return 0;
+     }
++
++    /* It must be a protocol that we sent */
++    if (!PACKET_buf_init(&confpkt, s->ext.alpn, s->ext.alpn_len)) {
++        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
++        return 0;
++    }
++    while (PACKET_get_length_prefixed_1(&confpkt, &protpkt)) {
++        if (PACKET_remaining(&protpkt) != len)
++            continue;
++        if (memcmp(PACKET_data(pkt), PACKET_data(&protpkt), len) == 0) {
++            /* Valid protocol found */
++            valid = 1;
++            break;
++        }
++    }
++
++    if (!valid) {
++        /* The protocol sent from the server does not match one we advertised */
++        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
++        return 0;
++    }
++
+     OPENSSL_free(s->s3.alpn_selected);
+     s->s3.alpn_selected = OPENSSL_malloc(len);
+     if (s->s3.alpn_selected == NULL) {
+diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
+index 64ccb3ed6d1b..b821c7cbe291 100644
+--- a/ssl/statem/extensions_srvr.c
++++ b/ssl/statem/extensions_srvr.c
+@@ -1496,9 +1496,10 @@ EXT_RETURN tls_construct_stoc_next_proto_neg(SSL_CONNECTION *s, WPACKET *pkt,
+             return EXT_RETURN_FAIL;
+         }
+         s->s3.npn_seen = 1;
++        return EXT_RETURN_SENT;
+     }
+ 
+-    return EXT_RETURN_SENT;
++    return EXT_RETURN_NOT_SENT;
+ }
+ #endif
+ 
+diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
+index 853af8c0aa9f..d5f0ab091dac 100644
+--- a/ssl/statem/statem_srvr.c
++++ b/ssl/statem/statem_srvr.c
+@@ -2445,9 +2445,8 @@ CON_FUNC_RETURN tls_construct_server_hello(SSL_CONNECTION *s, WPACKET *pkt)
+      * so the following won't overwrite an ID that we're supposed
+      * to send back.
+      */
+-    if (s->session->not_resumable ||
+-        (!(SSL_CONNECTION_GET_CTX(s)->session_cache_mode & SSL_SESS_CACHE_SERVER)
+-         && !s->hit))
++    if (!(SSL_CONNECTION_GET_CTX(s)->session_cache_mode & SSL_SESS_CACHE_SERVER)
++            && !s->hit)
+         s->session->session_id_length = 0;
+ 
+     if (usetls13) {
+diff --git a/test/ec_internal_test.c b/test/ec_internal_test.c
+index 5076f9894d5b..92904cfc42b2 100644
+--- a/test/ec_internal_test.c
++++ b/test/ec_internal_test.c
+@@ -155,6 +155,56 @@ static int field_tests_ecp_mont(void)
+ }
+ 
+ #ifndef OPENSSL_NO_EC2M
++/* Test that decoding of invalid GF2m field parameters fails. */
++static int ec2m_field_sanity(void)
++{
++    int ret = 0;
++    BN_CTX *ctx = BN_CTX_new();
++    BIGNUM *p, *a, *b;
++    EC_GROUP *group1 = NULL, *group2 = NULL, *group3 = NULL;
++
++    TEST_info("Testing GF2m hardening\n");
++
++    BN_CTX_start(ctx);
++    p = BN_CTX_get(ctx);
++    a = BN_CTX_get(ctx);
++    if (!TEST_ptr(b = BN_CTX_get(ctx))
++        || !TEST_true(BN_one(a))
++        || !TEST_true(BN_one(b)))
++        goto out;
++
++    /* Even pentanomial value should be rejected */
++    if (!TEST_true(BN_set_word(p, 0xf2)))
++        goto out;
++    if (!TEST_ptr_null(group1 = EC_GROUP_new_curve_GF2m(p, a, b, ctx)))
++        TEST_error("Zero constant term accepted in GF2m polynomial");
++
++    /* Odd hexanomial should also be rejected */
++    if (!TEST_true(BN_set_word(p, 0xf3)))
++        goto out;
++    if (!TEST_ptr_null(group2 = EC_GROUP_new_curve_GF2m(p, a, b, ctx)))
++        TEST_error("Hexanomial accepted as GF2m polynomial");
++
++    /* Excessive polynomial degree should also be rejected */
++    if (!TEST_true(BN_set_word(p, 0x71))
++        || !TEST_true(BN_set_bit(p, OPENSSL_ECC_MAX_FIELD_BITS + 1)))
++        goto out;
++    if (!TEST_ptr_null(group3 = EC_GROUP_new_curve_GF2m(p, a, b, ctx)))
++        TEST_error("GF2m polynomial degree > %d accepted",
++                   OPENSSL_ECC_MAX_FIELD_BITS);
++
++    ret = group1 == NULL && group2 == NULL && group3 == NULL;
++
++ out:
++    EC_GROUP_free(group1);
++    EC_GROUP_free(group2);
++    EC_GROUP_free(group3);
++    BN_CTX_end(ctx);
++    BN_CTX_free(ctx);
++
++    return ret;
++}
++
+ /* test EC_GF2m_simple_method directly */
+ static int field_tests_ec2_simple(void)
+ {
+@@ -443,6 +493,7 @@ int setup_tests(void)
+     ADD_TEST(field_tests_ecp_simple);
+     ADD_TEST(field_tests_ecp_mont);
+ #ifndef OPENSSL_NO_EC2M
++    ADD_TEST(ec2m_field_sanity);
+     ADD_TEST(field_tests_ec2_simple);
+ #endif
+     ADD_ALL_TESTS(field_tests_default, crv_len);
+diff --git a/test/helpers/handshake.c b/test/helpers/handshake.c
+index e0422469e4c2..6b1629b942b2 100644
+--- a/test/helpers/handshake.c
++++ b/test/helpers/handshake.c
+@@ -348,6 +348,12 @@ static int parse_protos(const char *protos, unsigned char **out, size_t *outlen)
+ 
+     len = strlen(protos);
+ 
++    if (len == 0) {
++        *out = NULL;
++        *outlen = 0;
++        return 1;
++    }
++
+     /* Should never have reuse. */
+     if (!TEST_ptr_null(*out)
+             /* Test values are small, so we omit length limit checks. */
+diff --git a/test/helpers/ssltestlib.c b/test/helpers/ssltestlib.c
+index 906aed4b4757..b2ebed55311d 100644
+--- a/test/helpers/ssltestlib.c
++++ b/test/helpers/ssltestlib.c
+@@ -7,8 +7,17 @@
+  * https://www.openssl.org/source/license.html
+  */
+ 
++/*
++ * We need access to the deprecated low level ENGINE APIs for legacy purposes
++ * when the deprecated calls are not hidden
++ */
++#ifndef OPENSSL_NO_DEPRECATED_3_0
++# define OPENSSL_SUPPRESS_DEPRECATED
++#endif
++
+ #include <string.h>
+ 
++#include <openssl/engine.h>
+ #include "internal/e_os.h"
+ #include "internal/nelem.h"
+ #include "ssltestlib.h"
+@@ -1451,3 +1460,27 @@ int ssl_ctx_add_large_cert_chain(OSSL_LIB_CTX *libctx, SSL_CTX *sctx,
+     X509_free(chaincert);
+     return ret;
+ }
++
++ENGINE *load_dasync(void)
++{
++#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE)
++    ENGINE *e;
++
++    if (!TEST_ptr(e = ENGINE_by_id("dasync")))
++        return NULL;
++
++    if (!TEST_true(ENGINE_init(e))) {
++        ENGINE_free(e);
++        return NULL;
++    }
++
++    if (!TEST_true(ENGINE_register_ciphers(e))) {
++        ENGINE_free(e);
++        return NULL;
++    }
++
++    return e;
++#else
++    return NULL;
++#endif
++}
+diff --git a/test/helpers/ssltestlib.h b/test/helpers/ssltestlib.h
+index 871f9bd52e09..bb73b58ee17f 100644
+--- a/test/helpers/ssltestlib.h
++++ b/test/helpers/ssltestlib.h
+@@ -81,4 +81,6 @@ SSL_SESSION *create_a_psk(SSL *ssl, size_t mdsize);
+ int ssl_ctx_add_large_cert_chain(OSSL_LIB_CTX *libctx, SSL_CTX *sctx,
+                                  const char *cert_file);
+ 
++ENGINE *load_dasync(void);
++
+ #endif /* OSSL_TEST_SSLTESTLIB_H */
+diff --git a/test/recipes/15-test_dsaparam_data/invalid/p10240_q256_too_big.pem b/test/recipes/15-test_dsaparam_data/invalid/p10240_q256_too_big.pem
+new file mode 100644
+index 000000000000..e85e2953b7a2
+--- /dev/null
++++ b/test/recipes/15-test_dsaparam_data/invalid/p10240_q256_too_big.pem
+@@ -0,0 +1,57 @@
++-----BEGIN DSA PARAMETERS-----
++MIIKLAKCBQEAym47LzPFZdbz16WvjczLKuzLtsP8yRk/exxL4bBthJhP1qOwctja
++p1586SF7gDxCMn7yWVEYdfRbFefGoq0gj1XOE917XqlbnkmZhMgxut2KbNJo/xil
++XNFUjGvKs3F413U9rAodC8f07cWHP1iTcWL+vPe6u2yilKWYYfnLWHQH+Z6aPrrF
++x/R08LI6DZ6nEsIo+hxaQnEtx+iqNTJC6Q1RIjWDqxQkFVTkJ0Y7miRDXmRdneWk
++oLrMZRpaXr5l5tSjEghh1pBgJcdyOv0lh4dlDy/alAiqE2Qlb667yHl6A9dDPlpW
++dAntpffy4LwOxfbuEhISvKjjQoBwIvYE4TBPqL0Q6bC6HgQ4+tqd9b44pQjdIQjb
++Xcjc6azheITSnPEex3OdKtKoQeRq01qCeLBpMXu1c+CTf4ApKArZvT3vZSg0hM1O
++pR71bRZrEEegDj0LH2HCgI5W6H3blOS9A0kUTddCoQXr2lsVdiPtRbPKH1gcd9FQ
++P8cGrvbakpTiC0dCczOMDaCteM1QNILlkM7ZoV6VghsKvDnFPxFsiIr5GgjasXP5
++hhbn3g7sDoq1LiTEo+IKQY28pBWx7etSOSRuXW/spnvCkivZla7lSEGljoy9QlQ2
++UZmsEQI9G3YyzgpxHvKZBK1CiZVTywdYKTZ4TYCxvqzhYhjv2bqbpjI12HRFLojB
++koyEmMSp53lldCzp158PrIanqSp2rksMR8SmmCL3FwfAp2OjqFMEglG9DT8x0WaN
++TLSkjGC6t2csMte7WyU1ekNoFDKfMjDSAz0+xIx21DEmZtYqFOg1DNPK1xYLS0pl
++RSMRRkJVN2mk/G7/1oxlB8Wb9wgi3GKUqqCYT11SnBjzq0NdoJ3E4GMedp5Lx3AZ
++4mFuRPUd4iV86tE0XDSHSFE7Y3ZkrOjD7Q/26/L53L/UH5z4HW6CHP5os7QERJjg
++c1S3x87wXWo9QXbB9b2xmf+c+aWwAAr1cviw38tru58jF3/IGyduj9H8claKQqBG
++cIOUF4aNe1hK2K3ArAOApUxr4KE+tCvrltRfiTmVFip0g9Jt1CPY3Zu7Bd4Z2ZkE
++DtSztpwa49HrWF5E9xpquvBL2U8jQ68E7Xd8Wp4orI/TIChriamBmdkgRz3H2LvN
++Ozb6+hsnEGrz3sp2RVAToSqA9ysa6nHZdfufPNtMEbQdO/k1ehmGRb0ljBRsO6b2
++rsG2eYuC8tg8eCrIkua0TGRI7g6a4K32AJdzaX6NsISaaIW+OYJuoDSscvD3oOg8
++PPEhU+zM7xJskTA+jxvPlikKx8V7MNHOCQECldJlUBwzJvqp40JvwfnDsF+8VYwd
++UaiieR3pzMzyTjpReXRmZbnRPusRcsVzxb2OhB79wmuy4UPjjQBX+7eD0rs8xxvW
++5a5q1Cjq4AvbwmmcA/wDrHDOjcbD/zodad2O1QtBWa/R4xyWea4zKsflgACE1zY9
++wW2br7+YQFekcrXkkkEzgxd6zxv8KVEDpXRZjmAM1cI5LvkoN64To4GedN8Qe/G7
++R9SZh9gnS17PTP64hK+aYqhFafMdu87q/+qLfxaSux727qE5hiW01u4nnWhACf9s
++xuOozowKqxZxkolMIyZv6Lddwy1Zv5qjCyd0DvM/1skpXWkb9kfabYC+OhjsjVhs
++0Ktfs6a5B3eixiw5x94hhIcTEcS4hmvhGUL72FiTca6ZeSERTKmNBy8CIQC9/ZUN
++uU/V5JTcnYyUGHzm7+XcZBjyGBagBj9rCmW3SQKCBQAJ/k9rb39f1cO+/3XDEMjy
++9bIEXSuS48g5RAc1UGd5nrrBQwuDxGWFyz0yvAY7LgyidZuJS21+MAp9EY7AOMmx
++TDttifNaBJYt4GZ8of166PcqTKkHQwq5uBpxeSDv/ZE8YbYfaCtLTcUC8KlO+l36
++gjJHSkdkflSsGy1yObSNDQDfVAAwQs//TjDMnuEtvlNXZllsTvFFBceXVETn10K2
++ZMmdSIJNfLnjReUKEN6PfeGqv7F4xoyGwUybEfRE4u5RmXrqCODaIjY3SNMrOq8B
++R3Ata/cCozsM1jIdIW2z+OybDJH+BYsYm2nkSZQjZS6javTYClLrntEKG/hAQwL8
++F16YLOQXpHhgiAaWnTZzANtLppB2+5qCVy5ElzKongOwT8JTjTFXOaRnqe/ngm9W
++SSbrxfDaoWUOyK9XD8Cydzpv3n4Y8nWNGayi7/yAFCU36Ri040ufgv/TZLuKacnl
+++3ga3ZUpRlSigzx0kb1+KjTSWeQ8vE/psdWjvBukVEbzdUauMLyRLo/6znSVvvPX
++UGhviThE5uhrsUg+wEPFINriSHfF7JDKVhDcJnLBdaXvfN52pkF/naLBF5Rt3Gvq
++fjCxjx0Sy9Lag1hDN4dor7dzuO7wmwOS01DJW1PtNLuuH0Bbqh1kYSaQkmyXBZWX
++qo8K3nkoDM0niOtJJubOhTNrGmSaZpNXkK3Mcy9rBbdvEs5O0Jmqaax/eOdU0Yot
++B3lX+3ddOseT2ZEFjzObqTtkWuFBeBxuYNcRTsu3qMdIBsEb8URQdsTtjoIja2fK
++hreVgjK36GW70KXEl8V/vq5qjQulmqkBEjmilcDuiREKqQuyeagUOnhQaBplqVco
++4xznh5DMBMRbpGb5lHxKv4cPNi+uNAJ5i98zWUM1JRt6aXnRCuWcll1z8fRZ+5kD
++vK9FaZU3VRMK/eknEG49cGr8OuJ6ZRSaC+tKwV1y+amkSZpKPWnk2bUnQI3ApJv3
++k1e1EToeECpMUkLMDgNbpKBoz4nqMEvAAlYgw9xKNbLlQlahqTVEAmaJHh4yDMDy
++i7IZ9Wrn47IGoR7s3cvhDHUpRPeW4nsmgzj+tf5EAxemI61STZJTTWo0iaPGJxct
++9nhOOhw1I38Mvm4vkAbFH7YJ0B6QrjjYL2MbOTp5JiIh4vdOeWwNo9/y4ffyaN5+
++ADpxuuIAmcbdr6GPOhkOFFixRJa0B2eP1i032HESlLs8RB9oYtdTXdXQotnIgJGd
++Y8tSKOa1zjzeLHn3AVpRZTUW++/BxmApV3GKIeG8fsUjg/df0QRrBcdC/1uccdaG
++KKlAOwlywVn5jUlwHkTmDiTM9w5AqVVGHZ2b+4ZgQW8jnPKN0SrKf6U555D+zp7E
++x4uXoE8ojN9y8m8UKf0cTLnujH2XgZorjPfuMOt5VZEhQFMS2QaljSeni5CJJ8gk
++XtztNqfBlAtWR4V5iAHeQOfIB2YaOy8GESda89tyKraKeaez41VblpTVHTeq9IIF
++YB4cQA2PfuNaGVRGLMAgT3Dvl+mxxxeJyxnGAiUcETU/jJJt9QombiuszBlYGQ5d
++ELOSm/eQSRARV9zNSt5jaQlMSjMBqenIEM09BzYqa7jDwqoztFxNdO8bcuQPuKwa
++4z3bBZ1yYm63WFdNbQqqGEwc0OYmqg1raJ0zltgHyjFyw8IGu4g/wETs+nVQcH7D
++vKuje86bePD6kD/LH3wmkA==
++-----END DSA PARAMETERS-----
+diff --git a/test/recipes/25-test_eai_data.t b/test/recipes/25-test_eai_data.t
+index 522982ddfb80..e18735d89aad 100644
+--- a/test/recipes/25-test_eai_data.t
++++ b/test/recipes/25-test_eai_data.t
+@@ -21,16 +21,18 @@ setup("test_eai_data");
+ #./util/wrap.pl apps/openssl verify -nameopt utf8 -no_check_time -CAfile test/recipes/25-test_eai_data/utf8_chain.pem test/recipes/25-test_eai_data/ascii_leaf.pem
+ #./util/wrap.pl apps/openssl verify -nameopt utf8 -no_check_time -CAfile test/recipes/25-test_eai_data/ascii_chain.pem test/recipes/25-test_eai_data/utf8_leaf.pem
+ 
+-plan tests => 12;
++plan tests => 16;
+ 
+ require_ok(srctop_file('test','recipes','tconversion.pl'));
+ my $folder = "test/recipes/25-test_eai_data";
+ 
+ my $ascii_pem = srctop_file($folder, "ascii_leaf.pem");
+ my $utf8_pem  = srctop_file($folder, "utf8_leaf.pem");
++my $kdc_pem   = srctop_file($folder, "kdc-cert.pem");
+ 
+ my $ascii_chain_pem = srctop_file($folder, "ascii_chain.pem");
+ my $utf8_chain_pem  = srctop_file($folder, "utf8_chain.pem");
++my $kdc_chain_pem  = srctop_file($folder, "kdc-root-cert.pem");
+ 
+ my $out;
+ my $outcnt = 0;
+@@ -56,10 +58,18 @@ SKIP: {
+ 
+ ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $ascii_chain_pem, $ascii_pem])));
+ ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $utf8_chain_pem, $utf8_pem])));
++ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $kdc_chain_pem, $kdc_pem])));
+ 
+ ok(!run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $ascii_chain_pem, $utf8_pem])));
+ ok(!run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-CAfile", $utf8_chain_pem,  $ascii_pem])));
+ 
++# Check an otherName does not get misparsed as an DNS name, (should trigger ASAN errors if violated).
++ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-verify_hostname", 'mx1.example.com', "-CAfile", $kdc_chain_pem,  $kdc_pem])));
++# Check an otherName does not get misparsed as an email address, (should trigger ASAN errors if violated).
++ok(run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-verify_email", 'joe@example.com', "-CAfile", $kdc_chain_pem,  $kdc_pem])));
++# We expect SmtpUTF8Mailbox to be a UTF8 String, not an IA5String.
++ok(!run(app(["openssl", "verify", "-nameopt", "utf8", "-no_check_time", "-verify_email", 'moe@example.com', "-CAfile", $kdc_chain_pem,  $kdc_pem])));
++
+ #Check that we get the expected failure return code
+ with({ exit_checker => sub { return shift == 2; } },
+      sub {
+diff --git a/test/recipes/25-test_eai_data/kdc-cert.pem b/test/recipes/25-test_eai_data/kdc-cert.pem
+new file mode 100644
+index 000000000000..e8a2c6f55d45
+--- /dev/null
++++ b/test/recipes/25-test_eai_data/kdc-cert.pem
+@@ -0,0 +1,21 @@
++-----BEGIN CERTIFICATE-----
++MIIDbDCCAlSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARSb290
++MCAXDTI0MDYyMDA2MTQxNVoYDzIxMjQwNjIwMDYxNDE1WjAXMRUwEwYDVQQDDAxU
++RVNULkVYQU1QTEUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6wfP+
++6go79dkpo/dGLMlPZ7Gw/Q6gUYrCWZWUEgEeRVHCrqOlgUEyA+PcWas/XDPUxXry
++BQlJHLvlqamAQn8gs4QPBARFYWKNiTVGyaRkgNA1N5gqyZdrP9UE+ZJmdqxRAAe8
++vvpGZWSgevPhLUiSCFYDiD0Rtji2Hm3rGUrReQFBQDEw2pNGwz9zIaxUs08kQZcx
++Yzyiplz5Oau+R/6sAgUwDlrD9xOlUxx/tA/MSDIfkK8qioU11uUZtO5VjkNQy/bT
++7zQMmXxWgm2MIgOs1u4YN7YGOtgqHE9v9iPHHfgrkbQDtVDGQsa8AQEhkUDSCtW9
++3VFAKx6dGNXYzFwfAgMBAAGjgcgwgcUwHQYDVR0OBBYEFFR5tZycW19DmtbL4Zqj
++te1c2vZLMAkGA1UdIwQCMAAwCQYDVR0TBAIwADCBjQYDVR0RBIGFMIGCoD8GBisG
++AQUCAqA1MDOgDhsMVEVTVC5FWEFNUExFoSEwH6ADAgEBoRgwFhsGa3JidGd0GwxU
++RVNULkVYQU1QTEWgHQYIKwYBBQUHCAmgERYPbW9lQGV4YW1wbGUuY29tgQ9qb2VA
++ZXhhbXBsZS5jb22CD214MS5leGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEA
++T0xzVtVpRtaOzIhgzw7XQUdzWD5UEGSJJ1cBCOmKUWwDLTAouCYLFB4TbEE7MMUb
++iuMy60bjmVtvfJIXorGUgSadRe5RWJ5DamJWvPA0Q9x7blnEcXqEF+9Td+ypevgU
++UYHFmg83OYwxOsFXZ5cRuXMk3WCsDHQIBi6D1L6oDDZ2pfArs5mqm3thQKVlqyl1
++El3XRYEdqAz/5eCOFNfwxF0ALxjxVr/Z50StUZU8I7Zfev6+kHhyrR7dqzYJImv9
++0fTCOBEMjIETDsrA70OxAMu4V16nrWZdJdvzblS2qrt97Omkj+2kiPAJFB76RpwI
++oDQ9fKfUOAmUFth2/R/eGA==
++-----END CERTIFICATE-----
+diff --git a/test/recipes/25-test_eai_data/kdc-root-cert.pem b/test/recipes/25-test_eai_data/kdc-root-cert.pem
+new file mode 100644
+index 000000000000..a74c96bf3146
+--- /dev/null
++++ b/test/recipes/25-test_eai_data/kdc-root-cert.pem
+@@ -0,0 +1,16 @@
++-----BEGIN CERTIFICATE-----
++MIICnDCCAYQCCQCBswYcrlZSHjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDARS
++b290MCAXDTI0MDYyMDA2MTQxNVoYDzIxMjQwNjIwMDYxNDE1WjAPMQ0wCwYDVQQD
++DARSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqRj8S4kBbIUj
++61kZfi6nE35Q38U140+qt4uAiwAhKumfVHlBM0zQ98WFt5zMHIBQwIb3yjc2zj+0
++qzUnQfwm1r/RfcMmBPEti9Ge+aEMSsds2gMXziOFM8wd2aAFPy7UVE0XpEWofsRK
++MGi61MKVdPSbGIxBwY9VW38/7D/wf1HtJe7y0xpuecR7GB2XAs+qST59NjuF+7wS
++dLM8Hb3TATgeYbXXWsRJgwz+SPzExg5WmLnU+7y4brZ32dHtdSmkRVSgSlaIf7Xj
++3Tc6Zi7I+W/JYk7hy1zUexVdWCak4PHcoWrXe0gNNN/t8VfLfMExt5z/HIylXnU7
++pGUyqZlTGQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAHpLF1UCRy7b6Hk0rLokxI
++lgwiH9BU9mktigAGASvkbllpt+YbUbWnuYAvpHBGiP1qZtfX2r96UrSJaGO9BEzT
++Gp9ThnSjoj4Srul0+s/NArU22irFLmDzbalgevAmm9gMGkdqkiIm/mXbwrPj0ncl
++KGicevXryVpvaP62eZ8cc3C4p97frMmXxRX8sTdQpD/gRI7prdEILRSKveqT+AEW
++7rFGM5AOevb4U8ddop8A3D/kX0wcCAIBF6jCNk3uEJ57jVcagL04kPnVfdRiedTS
++vfq1DRNcD29d1H/9u0fHdSn1/+8Ep3X+afQ3C6//5NvOEaXcIGO4QSwkprQydfv8
++-----END CERTIFICATE-----
+diff --git a/test/recipes/25-test_eai_data/kdc.sh b/test/recipes/25-test_eai_data/kdc.sh
+new file mode 100755
+index 000000000000..7a8dbc719fb7
+--- /dev/null
++++ b/test/recipes/25-test_eai_data/kdc.sh
+@@ -0,0 +1,41 @@
++#! /usr/bin/env bash
++
++# Create a root CA, signing a leaf cert with a KDC principal otherName SAN, and
++# also a non-UTF8 smtpUtf8Mailbox SAN followed by an rfc822Name SAN and a DNS
++# name SAN.  In the vulnerable EAI code, the KDC principal `otherName` should
++# trigger ASAN errors in DNS name checks, while the non-UTF8 `smtpUtf8Mailbox`
++# should likewise lead to ASAN issues with email name checks.
++
++rm -f root-key.pem root-cert.pem
++openssl req -nodes -new -newkey rsa:2048 -keyout kdc-root-key.pem \
++        -x509 -subj /CN=Root -days 36524 -out kdc-root-cert.pem
++
++exts=$(
++    printf "%s\n%s\n%s\n%s = " \
++        "subjectKeyIdentifier = hash" \
++        "authorityKeyIdentifier = keyid" \
++        "basicConstraints = CA:false" \
++        "subjectAltName"
++    printf "%s, " "otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name"
++    printf "%s, " "otherName:1.3.6.1.5.5.7.8.9;IA5:moe@example.com"
++    printf "%s, " "email:joe@example.com"
++    printf "%s\n" "DNS:mx1.example.com"
++    printf "[kdc_princ_name]\n"
++    printf "realm = EXP:0, GeneralString:TEST.EXAMPLE\n"
++    printf "principal_name = EXP:1, SEQUENCE:kdc_principal_seq\n"
++    printf "[kdc_principal_seq]\n"
++    printf "name_type = EXP:0, INTEGER:1\n"
++    printf "name_string = EXP:1, SEQUENCE:kdc_principal_components\n"
++    printf "[kdc_principal_components]\n"
++    printf "princ1 = GeneralString:krbtgt\n"
++    printf "princ2 = GeneralString:TEST.EXAMPLE\n"
++    )
++
++printf "%s\n" "$exts"
++
++openssl req -nodes -new -newkey rsa:2048 -keyout kdc-key.pem \
++    -subj "/CN=TEST.EXAMPLE" |
++    openssl x509 -req -out kdc-cert.pem \
++        -CA "kdc-root-cert.pem" -CAkey "kdc-root-key.pem" \
++        -set_serial 2 -days 36524 \
++        -extfile <(printf "%s\n" "$exts")
+diff --git a/test/recipes/70-test_npn.t b/test/recipes/70-test_npn.t
+new file mode 100644
+index 000000000000..f82e71af6aca
+--- /dev/null
++++ b/test/recipes/70-test_npn.t
+@@ -0,0 +1,73 @@
++#! /usr/bin/env perl
++# Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
++#
++# Licensed under the Apache License 2.0 (the "License").  You may not use
++# this file except in compliance with the License.  You can obtain a copy
++# in the file LICENSE in the source distribution or at
++# https://www.openssl.org/source/license.html
++
++use strict;
++use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file/;
++use OpenSSL::Test::Utils;
++
++use TLSProxy::Proxy;
++
++my $test_name = "test_npn";
++setup($test_name);
++
++plan skip_all => "TLSProxy isn't usable on $^O"
++    if $^O =~ /^(VMS)$/;
++
++plan skip_all => "$test_name needs the dynamic engine feature enabled"
++    if disabled("engine") || disabled("dynamic-engine");
++
++plan skip_all => "$test_name needs the sock feature enabled"
++    if disabled("sock");
++
++plan skip_all => "$test_name needs NPN enabled"
++    if disabled("nextprotoneg");
++
++plan skip_all => "$test_name needs TLSv1.2 enabled"
++    if disabled("tls1_2");
++
++my $proxy = TLSProxy::Proxy->new(
++    undef,
++    cmdstr(app(["openssl"]), display => 1),
++    srctop_file("apps", "server.pem"),
++    (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
++);
++
++$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
++plan tests => 1;
++
++my $npnseen = 0;
++
++# Test 1: Check sending an empty NextProto message from the client works. This is
++#         valid as per the spec, but OpenSSL does not allow you to send it.
++#         Therefore we must be prepared to receive such a message but we cannot
++#         generate it except via TLSProxy
++$proxy->clear();
++$proxy->filter(\&npn_filter);
++$proxy->clientflags("-nextprotoneg foo -no_tls1_3");
++$proxy->serverflags("-nextprotoneg foo");
++$proxy->start();
++ok($npnseen && TLSProxy::Message->success(), "Empty NPN message");
++
++sub npn_filter
++{
++    my $proxy = shift;
++    my $message;
++
++    # The NextProto message always appears in flight 2
++    return if $proxy->flight != 2;
++
++    foreach my $message (@{$proxy->message_list}) {
++        if ($message->mt == TLSProxy::Message::MT_NEXT_PROTO) {
++            # Our TLSproxy NextProto message support doesn't support parsing of
++            # the message. If we repack it just creates an empty NextProto
++            # message - which is exactly the scenario we want to test here.
++            $message->repack();
++            $npnseen = 1;
++        }
++    }
++}
+diff --git a/test/ssl-tests/08-npn.cnf b/test/ssl-tests/08-npn.cnf
+index f38b3f6975ce..1931d02de4ba 100644
+--- a/test/ssl-tests/08-npn.cnf
++++ b/test/ssl-tests/08-npn.cnf
+@@ -1,6 +1,6 @@
+ # Generated with generate_ssl_tests.pl
+ 
+-num_tests = 20
++num_tests = 22
+ 
+ test-0 = 0-npn-simple
+ test-1 = 1-npn-client-finds-match
+@@ -8,20 +8,22 @@ test-2 = 2-npn-client-honours-server-pref
+ test-3 = 3-npn-client-first-pref-on-mismatch
+ test-4 = 4-npn-no-server-support
+ test-5 = 5-npn-no-client-support
+-test-6 = 6-npn-with-sni-no-context-switch
+-test-7 = 7-npn-with-sni-context-switch
+-test-8 = 8-npn-selected-sni-server-supports-npn
+-test-9 = 9-npn-selected-sni-server-does-not-support-npn
+-test-10 = 10-alpn-preferred-over-npn
+-test-11 = 11-sni-npn-preferred-over-alpn
+-test-12 = 12-npn-simple-resumption
+-test-13 = 13-npn-server-switch-resumption
+-test-14 = 14-npn-client-switch-resumption
+-test-15 = 15-npn-client-first-pref-on-mismatch-resumption
+-test-16 = 16-npn-no-server-support-resumption
+-test-17 = 17-npn-no-client-support-resumption
+-test-18 = 18-alpn-preferred-over-npn-resumption
+-test-19 = 19-npn-used-if-alpn-not-supported-resumption
++test-6 = 6-npn-empty-client-list
++test-7 = 7-npn-empty-server-list
++test-8 = 8-npn-with-sni-no-context-switch
++test-9 = 9-npn-with-sni-context-switch
++test-10 = 10-npn-selected-sni-server-supports-npn
++test-11 = 11-npn-selected-sni-server-does-not-support-npn
++test-12 = 12-alpn-preferred-over-npn
++test-13 = 13-sni-npn-preferred-over-alpn
++test-14 = 14-npn-simple-resumption
++test-15 = 15-npn-server-switch-resumption
++test-16 = 16-npn-client-switch-resumption
++test-17 = 17-npn-client-first-pref-on-mismatch-resumption
++test-18 = 18-npn-no-server-support-resumption
++test-19 = 19-npn-no-client-support-resumption
++test-20 = 20-alpn-preferred-over-npn-resumption
++test-21 = 21-npn-used-if-alpn-not-supported-resumption
+ # ===========================================================
+ 
+ [0-npn-simple]
+@@ -206,253 +208,318 @@ NPNProtocols = foo
+ 
+ # ===========================================================
+ 
+-[6-npn-with-sni-no-context-switch]
+-ssl_conf = 6-npn-with-sni-no-context-switch-ssl
++[6-npn-empty-client-list]
++ssl_conf = 6-npn-empty-client-list-ssl
+ 
+-[6-npn-with-sni-no-context-switch-ssl]
+-server = 6-npn-with-sni-no-context-switch-server
+-client = 6-npn-with-sni-no-context-switch-client
+-server2 = 6-npn-with-sni-no-context-switch-server2
++[6-npn-empty-client-list-ssl]
++server = 6-npn-empty-client-list-server
++client = 6-npn-empty-client-list-client
+ 
+-[6-npn-with-sni-no-context-switch-server]
++[6-npn-empty-client-list-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[6-npn-with-sni-no-context-switch-server2]
++[6-npn-empty-client-list-client]
++CipherString = DEFAULT
++MaxProtocol = TLSv1.2
++VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
++VerifyMode = Peer
++
++[test-6]
++ExpectedClientAlert = HandshakeFailure
++ExpectedResult = ClientFail
++server = 6-npn-empty-client-list-server-extra
++client = 6-npn-empty-client-list-client-extra
++
++[6-npn-empty-client-list-server-extra]
++NPNProtocols = foo
++
++[6-npn-empty-client-list-client-extra]
++NPNProtocols = 
++
++
++# ===========================================================
++
++[7-npn-empty-server-list]
++ssl_conf = 7-npn-empty-server-list-ssl
++
++[7-npn-empty-server-list-ssl]
++server = 7-npn-empty-server-list-server
++client = 7-npn-empty-server-list-client
++
++[7-npn-empty-server-list-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[6-npn-with-sni-no-context-switch-client]
++[7-npn-empty-server-list-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-6]
++[test-7]
++ExpectedNPNProtocol = foo
++server = 7-npn-empty-server-list-server-extra
++client = 7-npn-empty-server-list-client-extra
++
++[7-npn-empty-server-list-server-extra]
++NPNProtocols = 
++
++[7-npn-empty-server-list-client-extra]
++NPNProtocols = foo
++
++
++# ===========================================================
++
++[8-npn-with-sni-no-context-switch]
++ssl_conf = 8-npn-with-sni-no-context-switch-ssl
++
++[8-npn-with-sni-no-context-switch-ssl]
++server = 8-npn-with-sni-no-context-switch-server
++client = 8-npn-with-sni-no-context-switch-client
++server2 = 8-npn-with-sni-no-context-switch-server2
++
++[8-npn-with-sni-no-context-switch-server]
++Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
++CipherString = DEFAULT
++PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
++
++[8-npn-with-sni-no-context-switch-server2]
++Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
++CipherString = DEFAULT
++PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
++
++[8-npn-with-sni-no-context-switch-client]
++CipherString = DEFAULT
++MaxProtocol = TLSv1.2
++VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
++VerifyMode = Peer
++
++[test-8]
+ ExpectedNPNProtocol = foo
+ ExpectedServerName = server1
+-server = 6-npn-with-sni-no-context-switch-server-extra
+-server2 = 6-npn-with-sni-no-context-switch-server2-extra
+-client = 6-npn-with-sni-no-context-switch-client-extra
++server = 8-npn-with-sni-no-context-switch-server-extra
++server2 = 8-npn-with-sni-no-context-switch-server2-extra
++client = 8-npn-with-sni-no-context-switch-client-extra
+ 
+-[6-npn-with-sni-no-context-switch-server-extra]
++[8-npn-with-sni-no-context-switch-server-extra]
+ NPNProtocols = foo
+ ServerNameCallback = IgnoreMismatch
+ 
+-[6-npn-with-sni-no-context-switch-server2-extra]
++[8-npn-with-sni-no-context-switch-server2-extra]
+ NPNProtocols = bar
+ 
+-[6-npn-with-sni-no-context-switch-client-extra]
++[8-npn-with-sni-no-context-switch-client-extra]
+ NPNProtocols = foo,bar
+ ServerName = server1
+ 
+ 
+ # ===========================================================
+ 
+-[7-npn-with-sni-context-switch]
+-ssl_conf = 7-npn-with-sni-context-switch-ssl
++[9-npn-with-sni-context-switch]
++ssl_conf = 9-npn-with-sni-context-switch-ssl
+ 
+-[7-npn-with-sni-context-switch-ssl]
+-server = 7-npn-with-sni-context-switch-server
+-client = 7-npn-with-sni-context-switch-client
+-server2 = 7-npn-with-sni-context-switch-server2
++[9-npn-with-sni-context-switch-ssl]
++server = 9-npn-with-sni-context-switch-server
++client = 9-npn-with-sni-context-switch-client
++server2 = 9-npn-with-sni-context-switch-server2
+ 
+-[7-npn-with-sni-context-switch-server]
++[9-npn-with-sni-context-switch-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[7-npn-with-sni-context-switch-server2]
++[9-npn-with-sni-context-switch-server2]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[7-npn-with-sni-context-switch-client]
++[9-npn-with-sni-context-switch-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-7]
++[test-9]
+ ExpectedNPNProtocol = bar
+ ExpectedServerName = server2
+-server = 7-npn-with-sni-context-switch-server-extra
+-server2 = 7-npn-with-sni-context-switch-server2-extra
+-client = 7-npn-with-sni-context-switch-client-extra
++server = 9-npn-with-sni-context-switch-server-extra
++server2 = 9-npn-with-sni-context-switch-server2-extra
++client = 9-npn-with-sni-context-switch-client-extra
+ 
+-[7-npn-with-sni-context-switch-server-extra]
++[9-npn-with-sni-context-switch-server-extra]
+ NPNProtocols = foo
+ ServerNameCallback = IgnoreMismatch
+ 
+-[7-npn-with-sni-context-switch-server2-extra]
++[9-npn-with-sni-context-switch-server2-extra]
+ NPNProtocols = bar
+ 
+-[7-npn-with-sni-context-switch-client-extra]
++[9-npn-with-sni-context-switch-client-extra]
+ NPNProtocols = foo,bar
+ ServerName = server2
+ 
+ 
+ # ===========================================================
+ 
+-[8-npn-selected-sni-server-supports-npn]
+-ssl_conf = 8-npn-selected-sni-server-supports-npn-ssl
++[10-npn-selected-sni-server-supports-npn]
++ssl_conf = 10-npn-selected-sni-server-supports-npn-ssl
+ 
+-[8-npn-selected-sni-server-supports-npn-ssl]
+-server = 8-npn-selected-sni-server-supports-npn-server
+-client = 8-npn-selected-sni-server-supports-npn-client
+-server2 = 8-npn-selected-sni-server-supports-npn-server2
++[10-npn-selected-sni-server-supports-npn-ssl]
++server = 10-npn-selected-sni-server-supports-npn-server
++client = 10-npn-selected-sni-server-supports-npn-client
++server2 = 10-npn-selected-sni-server-supports-npn-server2
+ 
+-[8-npn-selected-sni-server-supports-npn-server]
++[10-npn-selected-sni-server-supports-npn-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[8-npn-selected-sni-server-supports-npn-server2]
++[10-npn-selected-sni-server-supports-npn-server2]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[8-npn-selected-sni-server-supports-npn-client]
++[10-npn-selected-sni-server-supports-npn-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-8]
++[test-10]
+ ExpectedNPNProtocol = bar
+ ExpectedServerName = server2
+-server = 8-npn-selected-sni-server-supports-npn-server-extra
+-server2 = 8-npn-selected-sni-server-supports-npn-server2-extra
+-client = 8-npn-selected-sni-server-supports-npn-client-extra
++server = 10-npn-selected-sni-server-supports-npn-server-extra
++server2 = 10-npn-selected-sni-server-supports-npn-server2-extra
++client = 10-npn-selected-sni-server-supports-npn-client-extra
+ 
+-[8-npn-selected-sni-server-supports-npn-server-extra]
++[10-npn-selected-sni-server-supports-npn-server-extra]
+ ServerNameCallback = IgnoreMismatch
+ 
+-[8-npn-selected-sni-server-supports-npn-server2-extra]
++[10-npn-selected-sni-server-supports-npn-server2-extra]
+ NPNProtocols = bar
+ 
+-[8-npn-selected-sni-server-supports-npn-client-extra]
++[10-npn-selected-sni-server-supports-npn-client-extra]
+ NPNProtocols = foo,bar
+ ServerName = server2
+ 
+ 
+ # ===========================================================
+ 
+-[9-npn-selected-sni-server-does-not-support-npn]
+-ssl_conf = 9-npn-selected-sni-server-does-not-support-npn-ssl
++[11-npn-selected-sni-server-does-not-support-npn]
++ssl_conf = 11-npn-selected-sni-server-does-not-support-npn-ssl
+ 
+-[9-npn-selected-sni-server-does-not-support-npn-ssl]
+-server = 9-npn-selected-sni-server-does-not-support-npn-server
+-client = 9-npn-selected-sni-server-does-not-support-npn-client
+-server2 = 9-npn-selected-sni-server-does-not-support-npn-server2
++[11-npn-selected-sni-server-does-not-support-npn-ssl]
++server = 11-npn-selected-sni-server-does-not-support-npn-server
++client = 11-npn-selected-sni-server-does-not-support-npn-client
++server2 = 11-npn-selected-sni-server-does-not-support-npn-server2
+ 
+-[9-npn-selected-sni-server-does-not-support-npn-server]
++[11-npn-selected-sni-server-does-not-support-npn-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[9-npn-selected-sni-server-does-not-support-npn-server2]
++[11-npn-selected-sni-server-does-not-support-npn-server2]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[9-npn-selected-sni-server-does-not-support-npn-client]
++[11-npn-selected-sni-server-does-not-support-npn-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-9]
++[test-11]
+ ExpectedServerName = server2
+-server = 9-npn-selected-sni-server-does-not-support-npn-server-extra
+-client = 9-npn-selected-sni-server-does-not-support-npn-client-extra
++server = 11-npn-selected-sni-server-does-not-support-npn-server-extra
++client = 11-npn-selected-sni-server-does-not-support-npn-client-extra
+ 
+-[9-npn-selected-sni-server-does-not-support-npn-server-extra]
++[11-npn-selected-sni-server-does-not-support-npn-server-extra]
+ NPNProtocols = bar
+ ServerNameCallback = IgnoreMismatch
+ 
+-[9-npn-selected-sni-server-does-not-support-npn-client-extra]
++[11-npn-selected-sni-server-does-not-support-npn-client-extra]
+ NPNProtocols = foo,bar
+ ServerName = server2
+ 
+ 
+ # ===========================================================
+ 
+-[10-alpn-preferred-over-npn]
+-ssl_conf = 10-alpn-preferred-over-npn-ssl
++[12-alpn-preferred-over-npn]
++ssl_conf = 12-alpn-preferred-over-npn-ssl
+ 
+-[10-alpn-preferred-over-npn-ssl]
+-server = 10-alpn-preferred-over-npn-server
+-client = 10-alpn-preferred-over-npn-client
++[12-alpn-preferred-over-npn-ssl]
++server = 12-alpn-preferred-over-npn-server
++client = 12-alpn-preferred-over-npn-client
+ 
+-[10-alpn-preferred-over-npn-server]
++[12-alpn-preferred-over-npn-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[10-alpn-preferred-over-npn-client]
++[12-alpn-preferred-over-npn-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-10]
++[test-12]
+ ExpectedALPNProtocol = foo
+-server = 10-alpn-preferred-over-npn-server-extra
+-client = 10-alpn-preferred-over-npn-client-extra
++server = 12-alpn-preferred-over-npn-server-extra
++client = 12-alpn-preferred-over-npn-client-extra
+ 
+-[10-alpn-preferred-over-npn-server-extra]
++[12-alpn-preferred-over-npn-server-extra]
+ ALPNProtocols = foo
+ NPNProtocols = bar
+ 
+-[10-alpn-preferred-over-npn-client-extra]
++[12-alpn-preferred-over-npn-client-extra]
+ ALPNProtocols = foo
+ NPNProtocols = bar
+ 
+ 
+ # ===========================================================
+ 
+-[11-sni-npn-preferred-over-alpn]
+-ssl_conf = 11-sni-npn-preferred-over-alpn-ssl
++[13-sni-npn-preferred-over-alpn]
++ssl_conf = 13-sni-npn-preferred-over-alpn-ssl
+ 
+-[11-sni-npn-preferred-over-alpn-ssl]
+-server = 11-sni-npn-preferred-over-alpn-server
+-client = 11-sni-npn-preferred-over-alpn-client
+-server2 = 11-sni-npn-preferred-over-alpn-server2
++[13-sni-npn-preferred-over-alpn-ssl]
++server = 13-sni-npn-preferred-over-alpn-server
++client = 13-sni-npn-preferred-over-alpn-client
++server2 = 13-sni-npn-preferred-over-alpn-server2
+ 
+-[11-sni-npn-preferred-over-alpn-server]
++[13-sni-npn-preferred-over-alpn-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[11-sni-npn-preferred-over-alpn-server2]
++[13-sni-npn-preferred-over-alpn-server2]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[11-sni-npn-preferred-over-alpn-client]
++[13-sni-npn-preferred-over-alpn-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-11]
++[test-13]
+ ExpectedNPNProtocol = bar
+ ExpectedServerName = server2
+-server = 11-sni-npn-preferred-over-alpn-server-extra
+-server2 = 11-sni-npn-preferred-over-alpn-server2-extra
+-client = 11-sni-npn-preferred-over-alpn-client-extra
++server = 13-sni-npn-preferred-over-alpn-server-extra
++server2 = 13-sni-npn-preferred-over-alpn-server2-extra
++client = 13-sni-npn-preferred-over-alpn-client-extra
+ 
+-[11-sni-npn-preferred-over-alpn-server-extra]
++[13-sni-npn-preferred-over-alpn-server-extra]
+ ALPNProtocols = foo
+ ServerNameCallback = IgnoreMismatch
+ 
+-[11-sni-npn-preferred-over-alpn-server2-extra]
++[13-sni-npn-preferred-over-alpn-server2-extra]
+ NPNProtocols = bar
+ 
+-[11-sni-npn-preferred-over-alpn-client-extra]
++[13-sni-npn-preferred-over-alpn-client-extra]
+ ALPNProtocols = foo
+ NPNProtocols = bar
+ ServerName = server2
+@@ -460,356 +527,356 @@ ServerName = server2
+ 
+ # ===========================================================
+ 
+-[12-npn-simple-resumption]
+-ssl_conf = 12-npn-simple-resumption-ssl
++[14-npn-simple-resumption]
++ssl_conf = 14-npn-simple-resumption-ssl
+ 
+-[12-npn-simple-resumption-ssl]
+-server = 12-npn-simple-resumption-server
+-client = 12-npn-simple-resumption-client
+-resume-server = 12-npn-simple-resumption-server
+-resume-client = 12-npn-simple-resumption-client
++[14-npn-simple-resumption-ssl]
++server = 14-npn-simple-resumption-server
++client = 14-npn-simple-resumption-client
++resume-server = 14-npn-simple-resumption-server
++resume-client = 14-npn-simple-resumption-client
+ 
+-[12-npn-simple-resumption-server]
++[14-npn-simple-resumption-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[12-npn-simple-resumption-client]
++[14-npn-simple-resumption-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-12]
++[test-14]
+ ExpectedNPNProtocol = foo
+ HandshakeMode = Resume
+ ResumptionExpected = Yes
+-server = 12-npn-simple-resumption-server-extra
+-resume-server = 12-npn-simple-resumption-server-extra
+-client = 12-npn-simple-resumption-client-extra
+-resume-client = 12-npn-simple-resumption-client-extra
++server = 14-npn-simple-resumption-server-extra
++resume-server = 14-npn-simple-resumption-server-extra
++client = 14-npn-simple-resumption-client-extra
++resume-client = 14-npn-simple-resumption-client-extra
+ 
+-[12-npn-simple-resumption-server-extra]
++[14-npn-simple-resumption-server-extra]
+ NPNProtocols = foo
+ 
+-[12-npn-simple-resumption-client-extra]
++[14-npn-simple-resumption-client-extra]
+ NPNProtocols = foo
+ 
+ 
+ # ===========================================================
+ 
+-[13-npn-server-switch-resumption]
+-ssl_conf = 13-npn-server-switch-resumption-ssl
++[15-npn-server-switch-resumption]
++ssl_conf = 15-npn-server-switch-resumption-ssl
+ 
+-[13-npn-server-switch-resumption-ssl]
+-server = 13-npn-server-switch-resumption-server
+-client = 13-npn-server-switch-resumption-client
+-resume-server = 13-npn-server-switch-resumption-resume-server
+-resume-client = 13-npn-server-switch-resumption-client
++[15-npn-server-switch-resumption-ssl]
++server = 15-npn-server-switch-resumption-server
++client = 15-npn-server-switch-resumption-client
++resume-server = 15-npn-server-switch-resumption-resume-server
++resume-client = 15-npn-server-switch-resumption-client
+ 
+-[13-npn-server-switch-resumption-server]
++[15-npn-server-switch-resumption-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[13-npn-server-switch-resumption-resume-server]
++[15-npn-server-switch-resumption-resume-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[13-npn-server-switch-resumption-client]
++[15-npn-server-switch-resumption-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-13]
++[test-15]
+ ExpectedNPNProtocol = baz
+ HandshakeMode = Resume
+ ResumptionExpected = Yes
+-server = 13-npn-server-switch-resumption-server-extra
+-resume-server = 13-npn-server-switch-resumption-resume-server-extra
+-client = 13-npn-server-switch-resumption-client-extra
+-resume-client = 13-npn-server-switch-resumption-client-extra
++server = 15-npn-server-switch-resumption-server-extra
++resume-server = 15-npn-server-switch-resumption-resume-server-extra
++client = 15-npn-server-switch-resumption-client-extra
++resume-client = 15-npn-server-switch-resumption-client-extra
+ 
+-[13-npn-server-switch-resumption-server-extra]
++[15-npn-server-switch-resumption-server-extra]
+ NPNProtocols = bar,foo
+ 
+-[13-npn-server-switch-resumption-resume-server-extra]
++[15-npn-server-switch-resumption-resume-server-extra]
+ NPNProtocols = baz,foo
+ 
+-[13-npn-server-switch-resumption-client-extra]
++[15-npn-server-switch-resumption-client-extra]
+ NPNProtocols = foo,bar,baz
+ 
+ 
+ # ===========================================================
+ 
+-[14-npn-client-switch-resumption]
+-ssl_conf = 14-npn-client-switch-resumption-ssl
++[16-npn-client-switch-resumption]
++ssl_conf = 16-npn-client-switch-resumption-ssl
+ 
+-[14-npn-client-switch-resumption-ssl]
+-server = 14-npn-client-switch-resumption-server
+-client = 14-npn-client-switch-resumption-client
+-resume-server = 14-npn-client-switch-resumption-server
+-resume-client = 14-npn-client-switch-resumption-resume-client
++[16-npn-client-switch-resumption-ssl]
++server = 16-npn-client-switch-resumption-server
++client = 16-npn-client-switch-resumption-client
++resume-server = 16-npn-client-switch-resumption-server
++resume-client = 16-npn-client-switch-resumption-resume-client
+ 
+-[14-npn-client-switch-resumption-server]
++[16-npn-client-switch-resumption-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[14-npn-client-switch-resumption-client]
++[16-npn-client-switch-resumption-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[14-npn-client-switch-resumption-resume-client]
++[16-npn-client-switch-resumption-resume-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-14]
++[test-16]
+ ExpectedNPNProtocol = bar
+ HandshakeMode = Resume
+ ResumptionExpected = Yes
+-server = 14-npn-client-switch-resumption-server-extra
+-resume-server = 14-npn-client-switch-resumption-server-extra
+-client = 14-npn-client-switch-resumption-client-extra
+-resume-client = 14-npn-client-switch-resumption-resume-client-extra
++server = 16-npn-client-switch-resumption-server-extra
++resume-server = 16-npn-client-switch-resumption-server-extra
++client = 16-npn-client-switch-resumption-client-extra
++resume-client = 16-npn-client-switch-resumption-resume-client-extra
+ 
+-[14-npn-client-switch-resumption-server-extra]
++[16-npn-client-switch-resumption-server-extra]
+ NPNProtocols = foo,bar,baz
+ 
+-[14-npn-client-switch-resumption-client-extra]
++[16-npn-client-switch-resumption-client-extra]
+ NPNProtocols = foo,baz
+ 
+-[14-npn-client-switch-resumption-resume-client-extra]
++[16-npn-client-switch-resumption-resume-client-extra]
+ NPNProtocols = bar,baz
+ 
+ 
+ # ===========================================================
+ 
+-[15-npn-client-first-pref-on-mismatch-resumption]
+-ssl_conf = 15-npn-client-first-pref-on-mismatch-resumption-ssl
++[17-npn-client-first-pref-on-mismatch-resumption]
++ssl_conf = 17-npn-client-first-pref-on-mismatch-resumption-ssl
+ 
+-[15-npn-client-first-pref-on-mismatch-resumption-ssl]
+-server = 15-npn-client-first-pref-on-mismatch-resumption-server
+-client = 15-npn-client-first-pref-on-mismatch-resumption-client
+-resume-server = 15-npn-client-first-pref-on-mismatch-resumption-resume-server
+-resume-client = 15-npn-client-first-pref-on-mismatch-resumption-client
++[17-npn-client-first-pref-on-mismatch-resumption-ssl]
++server = 17-npn-client-first-pref-on-mismatch-resumption-server
++client = 17-npn-client-first-pref-on-mismatch-resumption-client
++resume-server = 17-npn-client-first-pref-on-mismatch-resumption-resume-server
++resume-client = 17-npn-client-first-pref-on-mismatch-resumption-client
+ 
+-[15-npn-client-first-pref-on-mismatch-resumption-server]
++[17-npn-client-first-pref-on-mismatch-resumption-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[15-npn-client-first-pref-on-mismatch-resumption-resume-server]
++[17-npn-client-first-pref-on-mismatch-resumption-resume-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[15-npn-client-first-pref-on-mismatch-resumption-client]
++[17-npn-client-first-pref-on-mismatch-resumption-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-15]
++[test-17]
+ ExpectedNPNProtocol = foo
+ HandshakeMode = Resume
+ ResumptionExpected = Yes
+-server = 15-npn-client-first-pref-on-mismatch-resumption-server-extra
+-resume-server = 15-npn-client-first-pref-on-mismatch-resumption-resume-server-extra
+-client = 15-npn-client-first-pref-on-mismatch-resumption-client-extra
+-resume-client = 15-npn-client-first-pref-on-mismatch-resumption-client-extra
++server = 17-npn-client-first-pref-on-mismatch-resumption-server-extra
++resume-server = 17-npn-client-first-pref-on-mismatch-resumption-resume-server-extra
++client = 17-npn-client-first-pref-on-mismatch-resumption-client-extra
++resume-client = 17-npn-client-first-pref-on-mismatch-resumption-client-extra
+ 
+-[15-npn-client-first-pref-on-mismatch-resumption-server-extra]
++[17-npn-client-first-pref-on-mismatch-resumption-server-extra]
+ NPNProtocols = bar
+ 
+-[15-npn-client-first-pref-on-mismatch-resumption-resume-server-extra]
++[17-npn-client-first-pref-on-mismatch-resumption-resume-server-extra]
+ NPNProtocols = baz
+ 
+-[15-npn-client-first-pref-on-mismatch-resumption-client-extra]
++[17-npn-client-first-pref-on-mismatch-resumption-client-extra]
+ NPNProtocols = foo,bar
+ 
+ 
+ # ===========================================================
+ 
+-[16-npn-no-server-support-resumption]
+-ssl_conf = 16-npn-no-server-support-resumption-ssl
++[18-npn-no-server-support-resumption]
++ssl_conf = 18-npn-no-server-support-resumption-ssl
+ 
+-[16-npn-no-server-support-resumption-ssl]
+-server = 16-npn-no-server-support-resumption-server
+-client = 16-npn-no-server-support-resumption-client
+-resume-server = 16-npn-no-server-support-resumption-resume-server
+-resume-client = 16-npn-no-server-support-resumption-client
++[18-npn-no-server-support-resumption-ssl]
++server = 18-npn-no-server-support-resumption-server
++client = 18-npn-no-server-support-resumption-client
++resume-server = 18-npn-no-server-support-resumption-resume-server
++resume-client = 18-npn-no-server-support-resumption-client
+ 
+-[16-npn-no-server-support-resumption-server]
++[18-npn-no-server-support-resumption-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[16-npn-no-server-support-resumption-resume-server]
++[18-npn-no-server-support-resumption-resume-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[16-npn-no-server-support-resumption-client]
++[18-npn-no-server-support-resumption-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-16]
++[test-18]
+ HandshakeMode = Resume
+ ResumptionExpected = Yes
+-server = 16-npn-no-server-support-resumption-server-extra
+-client = 16-npn-no-server-support-resumption-client-extra
+-resume-client = 16-npn-no-server-support-resumption-client-extra
++server = 18-npn-no-server-support-resumption-server-extra
++client = 18-npn-no-server-support-resumption-client-extra
++resume-client = 18-npn-no-server-support-resumption-client-extra
+ 
+-[16-npn-no-server-support-resumption-server-extra]
++[18-npn-no-server-support-resumption-server-extra]
+ NPNProtocols = foo
+ 
+-[16-npn-no-server-support-resumption-client-extra]
++[18-npn-no-server-support-resumption-client-extra]
+ NPNProtocols = foo
+ 
+ 
+ # ===========================================================
+ 
+-[17-npn-no-client-support-resumption]
+-ssl_conf = 17-npn-no-client-support-resumption-ssl
++[19-npn-no-client-support-resumption]
++ssl_conf = 19-npn-no-client-support-resumption-ssl
+ 
+-[17-npn-no-client-support-resumption-ssl]
+-server = 17-npn-no-client-support-resumption-server
+-client = 17-npn-no-client-support-resumption-client
+-resume-server = 17-npn-no-client-support-resumption-server
+-resume-client = 17-npn-no-client-support-resumption-resume-client
++[19-npn-no-client-support-resumption-ssl]
++server = 19-npn-no-client-support-resumption-server
++client = 19-npn-no-client-support-resumption-client
++resume-server = 19-npn-no-client-support-resumption-server
++resume-client = 19-npn-no-client-support-resumption-resume-client
+ 
+-[17-npn-no-client-support-resumption-server]
++[19-npn-no-client-support-resumption-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[17-npn-no-client-support-resumption-client]
++[19-npn-no-client-support-resumption-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[17-npn-no-client-support-resumption-resume-client]
++[19-npn-no-client-support-resumption-resume-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-17]
++[test-19]
+ HandshakeMode = Resume
+ ResumptionExpected = Yes
+-server = 17-npn-no-client-support-resumption-server-extra
+-resume-server = 17-npn-no-client-support-resumption-server-extra
+-client = 17-npn-no-client-support-resumption-client-extra
++server = 19-npn-no-client-support-resumption-server-extra
++resume-server = 19-npn-no-client-support-resumption-server-extra
++client = 19-npn-no-client-support-resumption-client-extra
+ 
+-[17-npn-no-client-support-resumption-server-extra]
++[19-npn-no-client-support-resumption-server-extra]
+ NPNProtocols = foo
+ 
+-[17-npn-no-client-support-resumption-client-extra]
++[19-npn-no-client-support-resumption-client-extra]
+ NPNProtocols = foo
+ 
+ 
+ # ===========================================================
+ 
+-[18-alpn-preferred-over-npn-resumption]
+-ssl_conf = 18-alpn-preferred-over-npn-resumption-ssl
++[20-alpn-preferred-over-npn-resumption]
++ssl_conf = 20-alpn-preferred-over-npn-resumption-ssl
+ 
+-[18-alpn-preferred-over-npn-resumption-ssl]
+-server = 18-alpn-preferred-over-npn-resumption-server
+-client = 18-alpn-preferred-over-npn-resumption-client
+-resume-server = 18-alpn-preferred-over-npn-resumption-resume-server
+-resume-client = 18-alpn-preferred-over-npn-resumption-client
++[20-alpn-preferred-over-npn-resumption-ssl]
++server = 20-alpn-preferred-over-npn-resumption-server
++client = 20-alpn-preferred-over-npn-resumption-client
++resume-server = 20-alpn-preferred-over-npn-resumption-resume-server
++resume-client = 20-alpn-preferred-over-npn-resumption-client
+ 
+-[18-alpn-preferred-over-npn-resumption-server]
++[20-alpn-preferred-over-npn-resumption-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[18-alpn-preferred-over-npn-resumption-resume-server]
++[20-alpn-preferred-over-npn-resumption-resume-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[18-alpn-preferred-over-npn-resumption-client]
++[20-alpn-preferred-over-npn-resumption-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-18]
++[test-20]
+ ExpectedALPNProtocol = foo
+ HandshakeMode = Resume
+ ResumptionExpected = Yes
+-server = 18-alpn-preferred-over-npn-resumption-server-extra
+-resume-server = 18-alpn-preferred-over-npn-resumption-resume-server-extra
+-client = 18-alpn-preferred-over-npn-resumption-client-extra
+-resume-client = 18-alpn-preferred-over-npn-resumption-client-extra
++server = 20-alpn-preferred-over-npn-resumption-server-extra
++resume-server = 20-alpn-preferred-over-npn-resumption-resume-server-extra
++client = 20-alpn-preferred-over-npn-resumption-client-extra
++resume-client = 20-alpn-preferred-over-npn-resumption-client-extra
+ 
+-[18-alpn-preferred-over-npn-resumption-server-extra]
++[20-alpn-preferred-over-npn-resumption-server-extra]
+ NPNProtocols = bar
+ 
+-[18-alpn-preferred-over-npn-resumption-resume-server-extra]
++[20-alpn-preferred-over-npn-resumption-resume-server-extra]
+ ALPNProtocols = foo
+ NPNProtocols = baz
+ 
+-[18-alpn-preferred-over-npn-resumption-client-extra]
++[20-alpn-preferred-over-npn-resumption-client-extra]
+ ALPNProtocols = foo
+ NPNProtocols = bar,baz
+ 
+ 
+ # ===========================================================
+ 
+-[19-npn-used-if-alpn-not-supported-resumption]
+-ssl_conf = 19-npn-used-if-alpn-not-supported-resumption-ssl
++[21-npn-used-if-alpn-not-supported-resumption]
++ssl_conf = 21-npn-used-if-alpn-not-supported-resumption-ssl
+ 
+-[19-npn-used-if-alpn-not-supported-resumption-ssl]
+-server = 19-npn-used-if-alpn-not-supported-resumption-server
+-client = 19-npn-used-if-alpn-not-supported-resumption-client
+-resume-server = 19-npn-used-if-alpn-not-supported-resumption-resume-server
+-resume-client = 19-npn-used-if-alpn-not-supported-resumption-client
++[21-npn-used-if-alpn-not-supported-resumption-ssl]
++server = 21-npn-used-if-alpn-not-supported-resumption-server
++client = 21-npn-used-if-alpn-not-supported-resumption-client
++resume-server = 21-npn-used-if-alpn-not-supported-resumption-resume-server
++resume-client = 21-npn-used-if-alpn-not-supported-resumption-client
+ 
+-[19-npn-used-if-alpn-not-supported-resumption-server]
++[21-npn-used-if-alpn-not-supported-resumption-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[19-npn-used-if-alpn-not-supported-resumption-resume-server]
++[21-npn-used-if-alpn-not-supported-resumption-resume-server]
+ Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+ CipherString = DEFAULT
+ PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+ 
+-[19-npn-used-if-alpn-not-supported-resumption-client]
++[21-npn-used-if-alpn-not-supported-resumption-client]
+ CipherString = DEFAULT
+ MaxProtocol = TLSv1.2
+ VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+ VerifyMode = Peer
+ 
+-[test-19]
++[test-21]
+ ExpectedNPNProtocol = baz
+ HandshakeMode = Resume
+ ResumptionExpected = Yes
+-server = 19-npn-used-if-alpn-not-supported-resumption-server-extra
+-resume-server = 19-npn-used-if-alpn-not-supported-resumption-resume-server-extra
+-client = 19-npn-used-if-alpn-not-supported-resumption-client-extra
+-resume-client = 19-npn-used-if-alpn-not-supported-resumption-client-extra
++server = 21-npn-used-if-alpn-not-supported-resumption-server-extra
++resume-server = 21-npn-used-if-alpn-not-supported-resumption-resume-server-extra
++client = 21-npn-used-if-alpn-not-supported-resumption-client-extra
++resume-client = 21-npn-used-if-alpn-not-supported-resumption-client-extra
+ 
+-[19-npn-used-if-alpn-not-supported-resumption-server-extra]
++[21-npn-used-if-alpn-not-supported-resumption-server-extra]
+ ALPNProtocols = foo
+ NPNProtocols = bar
+ 
+-[19-npn-used-if-alpn-not-supported-resumption-resume-server-extra]
++[21-npn-used-if-alpn-not-supported-resumption-resume-server-extra]
+ NPNProtocols = baz
+ 
+-[19-npn-used-if-alpn-not-supported-resumption-client-extra]
++[21-npn-used-if-alpn-not-supported-resumption-client-extra]
+ ALPNProtocols = foo
+ NPNProtocols = bar,baz
+ 
+diff --git a/test/ssl-tests/08-npn.cnf.in b/test/ssl-tests/08-npn.cnf.in
+index 30783e45eb59..1dc2704bdba8 100644
+--- a/test/ssl-tests/08-npn.cnf.in
++++ b/test/ssl-tests/08-npn.cnf.in
+@@ -110,6 +110,41 @@ our @tests = (
+             "ExpectedNPNProtocol" => undef,
+         },
+     },
++    {
++        name => "npn-empty-client-list",
++        server => {
++            extra => {
++                "NPNProtocols" => "foo",
++            },
++        },
++        client => {
++            extra => {
++                "NPNProtocols" => "",
++            },
++            "MaxProtocol" => "TLSv1.2"
++        },
++        test => {
++            "ExpectedResult" => "ClientFail",
++            "ExpectedClientAlert" => "HandshakeFailure"
++        },
++    },
++    {
++        name => "npn-empty-server-list",
++        server => {
++            extra => {
++                "NPNProtocols" => "",
++            },
++        },
++        client => {
++            extra => {
++                "NPNProtocols" => "foo",
++            },
++            "MaxProtocol" => "TLSv1.2"
++        },
++        test => {
++            "ExpectedNPNProtocol" => "foo"
++        },
++    },
+     {
+         name => "npn-with-sni-no-context-switch",
+         server => {
+diff --git a/test/ssl-tests/09-alpn.cnf b/test/ssl-tests/09-alpn.cnf
+index e7e6cb95348b..dd668739ab9a 100644
+--- a/test/ssl-tests/09-alpn.cnf
++++ b/test/ssl-tests/09-alpn.cnf
+@@ -1,6 +1,6 @@
+ # Generated with generate_ssl_tests.pl
+ 
+-num_tests = 16
++num_tests = 18
+ 
+ test-0 = 0-alpn-simple
+ test-1 = 1-alpn-server-finds-match
+@@ -18,6 +18,8 @@ test-12 = 12-alpn-client-switch-resumption
+ test-13 = 13-alpn-alert-on-mismatch-resumption
+ test-14 = 14-alpn-no-server-support-resumption
+ test-15 = 15-alpn-no-client-support-resumption
++test-16 = 16-alpn-empty-client-list
++test-17 = 17-alpn-empty-server-list
+ # ===========================================================
+ 
+ [0-alpn-simple]
+@@ -617,3 +619,65 @@ ALPNProtocols = foo
+ ALPNProtocols = foo
+ 
+ 
++# ===========================================================
++
++[16-alpn-empty-client-list]
++ssl_conf = 16-alpn-empty-client-list-ssl
++
++[16-alpn-empty-client-list-ssl]
++server = 16-alpn-empty-client-list-server
++client = 16-alpn-empty-client-list-client
++
++[16-alpn-empty-client-list-server]
++Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
++CipherString = DEFAULT
++PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
++
++[16-alpn-empty-client-list-client]
++CipherString = DEFAULT
++VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
++VerifyMode = Peer
++
++[test-16]
++server = 16-alpn-empty-client-list-server-extra
++client = 16-alpn-empty-client-list-client-extra
++
++[16-alpn-empty-client-list-server-extra]
++ALPNProtocols = foo
++
++[16-alpn-empty-client-list-client-extra]
++ALPNProtocols = 
++
++
++# ===========================================================
++
++[17-alpn-empty-server-list]
++ssl_conf = 17-alpn-empty-server-list-ssl
++
++[17-alpn-empty-server-list-ssl]
++server = 17-alpn-empty-server-list-server
++client = 17-alpn-empty-server-list-client
++
++[17-alpn-empty-server-list-server]
++Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
++CipherString = DEFAULT
++PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
++
++[17-alpn-empty-server-list-client]
++CipherString = DEFAULT
++VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
++VerifyMode = Peer
++
++[test-17]
++ExpectedResult = ServerFail
++ExpectedServerAlert = NoApplicationProtocol
++server = 17-alpn-empty-server-list-server-extra
++client = 17-alpn-empty-server-list-client-extra
++
++[17-alpn-empty-server-list-server-extra]
++ALPNProtocols = 
++
++[17-alpn-empty-server-list-client-extra]
++ALPNProtocols = foo
++
++
+diff --git a/test/ssl-tests/09-alpn.cnf.in b/test/ssl-tests/09-alpn.cnf.in
+index 81330756c62c..322b7096a6e4 100644
+--- a/test/ssl-tests/09-alpn.cnf.in
++++ b/test/ssl-tests/09-alpn.cnf.in
+@@ -322,4 +322,37 @@ our @tests = (
+             "ExpectedALPNProtocol" => undef,
+         },
+     },
++    {
++        name => "alpn-empty-client-list",
++        server => {
++            extra => {
++                "ALPNProtocols" => "foo",
++            },
++        },
++        client => {
++            extra => {
++                "ALPNProtocols" => "",
++            },
++        },
++        test => {
++            "ExpectedALPNProtocol" => undef,
++        },
++    },
++    {
++        name => "alpn-empty-server-list",
++        server => {
++            extra => {
++                "ALPNProtocols" => "",
++            },
++        },
++        client => {
++            extra => {
++                "ALPNProtocols" => "foo",
++            },
++        },
++        test => {
++            "ExpectedResult" => "ServerFail",
++            "ExpectedServerAlert" => "NoApplicationProtocol",
++        },
++    },
+ );
+diff --git a/test/sslapitest.c b/test/sslapitest.c
+index a95f5636094e..55b770f8cf77 100644
+--- a/test/sslapitest.c
++++ b/test/sslapitest.c
+@@ -2424,7 +2424,6 @@ static int test_session_wo_ca_names(void)
+ #endif
+ }
+ 
+-
+ #ifndef OSSL_NO_USABLE_TLS1_3
+ static SSL_SESSION *sesscache[6];
+ static int do_cache;
+@@ -9122,6 +9121,126 @@ static int test_session_timeout(int test)
+     return testresult;
+ }
+ 
++/*
++ * Test that a session cache overflow works as expected
++ * Test 0: TLSv1.3, timeout on new session later than old session
++ * Test 1: TLSv1.2, timeout on new session later than old session
++ * Test 2: TLSv1.3, timeout on new session earlier than old session
++ * Test 3: TLSv1.2, timeout on new session earlier than old session
++ */
++#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
++static int test_session_cache_overflow(int idx)
++{
++    SSL_CTX *sctx = NULL, *cctx = NULL;
++    SSL *serverssl = NULL, *clientssl = NULL;
++    int testresult = 0;
++    SSL_SESSION *sess = NULL;
++
++#ifdef OSSL_NO_USABLE_TLS1_3
++    /* If no TLSv1.3 available then do nothing in this case */
++    if (idx % 2 == 0)
++        return TEST_skip("No TLSv1.3 available");
++#endif
++#ifdef OPENSSL_NO_TLS1_2
++    /* If no TLSv1.2 available then do nothing in this case */
++    if (idx % 2 == 1)
++        return TEST_skip("No TLSv1.2 available");
++#endif
++
++    if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
++                                       TLS_client_method(), TLS1_VERSION,
++                                       (idx % 2 == 0) ? TLS1_3_VERSION
++                                                      : TLS1_2_VERSION,
++                                       &sctx, &cctx, cert, privkey))
++            || !TEST_true(SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET)))
++        goto end;
++
++    SSL_CTX_sess_set_get_cb(sctx, get_session_cb);
++    get_sess_val = NULL;
++
++    SSL_CTX_sess_set_cache_size(sctx, 1);
++
++    if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
++                                      NULL, NULL)))
++        goto end;
++
++    if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
++        goto end;
++
++    if (idx > 1) {
++        sess = SSL_get_session(serverssl);
++        if (!TEST_ptr(sess))
++            goto end;
++
++        /*
++         * Cause this session to have a longer timeout than the next session to
++         * be added.
++         */
++        if (!TEST_true(SSL_SESSION_set_timeout(sess, LONG_MAX))) {
++            sess = NULL;
++            goto end;
++        }
++        sess = NULL;
++    }
++
++    SSL_shutdown(serverssl);
++    SSL_shutdown(clientssl);
++    SSL_free(serverssl);
++    SSL_free(clientssl);
++    serverssl = clientssl = NULL;
++
++    /*
++     * Session cache size is 1 and we already populated the cache with a session
++     * so the next connection should cause an overflow.
++     */
++
++    if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
++                                      NULL, NULL)))
++        goto end;
++
++    if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
++        goto end;
++
++    /*
++     * The session we just negotiated may have been already removed from the
++     * internal cache - but we will return it anyway from our external cache.
++     */
++    get_sess_val = SSL_get_session(serverssl);
++    if (!TEST_ptr(get_sess_val))
++        goto end;
++    sess = SSL_get1_session(clientssl);
++    if (!TEST_ptr(sess))
++        goto end;
++
++    SSL_shutdown(serverssl);
++    SSL_shutdown(clientssl);
++    SSL_free(serverssl);
++    SSL_free(clientssl);
++    serverssl = clientssl = NULL;
++
++    if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
++                                      NULL, NULL)))
++        goto end;
++
++    if (!TEST_true(SSL_set_session(clientssl, sess)))
++        goto end;
++
++    if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
++        goto end;
++
++    testresult = 1;
++
++ end:
++    SSL_free(serverssl);
++    SSL_free(clientssl);
++    SSL_CTX_free(sctx);
++    SSL_CTX_free(cctx);
++    SSL_SESSION_free(sess);
++
++    return testresult;
++}
++#endif /* !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2) */
++
+ /*
+  * Test 0: Client sets servername and server acknowledges it (TLSv1.2)
+  * Test 1: Client sets servername and server does not acknowledge it (TLSv1.2)
+@@ -10621,27 +10740,6 @@ end:
+ #endif /* OSSL_NO_USABLE_TLS1_3 */
+ 
+ #if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE)
+-
+-static ENGINE *load_dasync(void)
+-{
+-    ENGINE *e;
+-
+-    if (!TEST_ptr(e = ENGINE_by_id("dasync")))
+-        return NULL;
+-
+-    if (!TEST_true(ENGINE_init(e))) {
+-        ENGINE_free(e);
+-        return NULL;
+-    }
+-
+-    if (!TEST_true(ENGINE_register_ciphers(e))) {
+-        ENGINE_free(e);
+-        return NULL;
+-    }
+-
+-    return e;
+-}
+-
+ /*
+  * Test TLSv1.2 with a pipeline capable cipher. TLSv1.3 and DTLS do not
+  * support this yet. The only pipeline capable cipher that we have is in the
+@@ -11251,6 +11349,538 @@ end:
+     return testresult;
+ }
+ 
++struct resume_servername_cb_data {
++    int i;
++    SSL_CTX *cctx;
++    SSL_CTX *sctx;
++    SSL_SESSION *sess;
++    int recurse;
++};
++
++/*
++ * Servername callback. We use it here to run another complete handshake using
++ * the same session - and mark the session as not_resuamble at the end
++ */
++static int resume_servername_cb(SSL *s, int *ad, void *arg)
++{
++    struct resume_servername_cb_data *cbdata = arg;
++    SSL *serverssl = NULL, *clientssl = NULL;
++    int ret = SSL_TLSEXT_ERR_ALERT_FATAL;
++
++    if (cbdata->recurse)
++        return SSL_TLSEXT_ERR_ALERT_FATAL;
++
++    if ((cbdata->i % 3) != 1)
++        return SSL_TLSEXT_ERR_OK;
++
++    cbdata->recurse = 1;
++
++    if (!TEST_true(create_ssl_objects(cbdata->sctx, cbdata->cctx, &serverssl,
++                                      &clientssl, NULL, NULL))
++            || !TEST_true(SSL_set_session(clientssl, cbdata->sess)))
++        goto end;
++
++    ERR_set_mark();
++    /*
++     * We expect this to fail - because the servername cb will fail. This will
++     * mark the session as not_resumable.
++     */
++    if (!TEST_false(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE))) {
++        ERR_clear_last_mark();
++        goto end;
++    }
++    ERR_pop_to_mark();
++
++    ret = SSL_TLSEXT_ERR_OK;
++ end:
++    SSL_free(serverssl);
++    SSL_free(clientssl);
++    cbdata->recurse = 0;
++    return ret;
++}
++/*
++ * Test multiple resumptions and cache size handling
++ * Test 0: TLSv1.3 (max_early_data set)
++ * Test 1: TLSv1.3 (SSL_OP_NO_TICKET set)
++ * Test 2: TLSv1.3 (max_early_data and SSL_OP_NO_TICKET set)
++ * Test 3: TLSv1.3 (SSL_OP_NO_TICKET, simultaneous resumes)
++ * Test 4: TLSv1.2
++ */
++static int test_multi_resume(int idx)
++{
++    SSL_CTX *sctx = NULL, *cctx = NULL;
++    SSL *serverssl = NULL, *clientssl = NULL;
++    SSL_SESSION *sess = NULL;
++    int max_version = TLS1_3_VERSION;
++    int i, testresult = 0;
++    struct resume_servername_cb_data cbdata;
++
++#if defined(OPENSSL_NO_TLS1_2)
++    if (idx == 4)
++        return TEST_skip("TLSv1.2 is disabled in this build");
++#else
++    if (idx == 4)
++        max_version = TLS1_2_VERSION;
++#endif
++#if defined(OSSL_NO_USABLE_TLS1_3)
++    if (idx != 4)
++        return TEST_skip("No usable TLSv1.3 in this build");
++#endif
++
++    if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
++                                       TLS_client_method(), TLS1_VERSION,
++                                       max_version, &sctx, &cctx, cert,
++                                       privkey)))
++        goto end;
++
++    /*
++     * TLSv1.3 only uses a session cache if either max_early_data > 0 (used for
++     * replay protection), or if SSL_OP_NO_TICKET is in use
++     */
++    if (idx == 0 || idx == 2)  {
++        if (!TEST_true(SSL_CTX_set_max_early_data(sctx, 1024)))
++            goto end;
++    }
++    if (idx == 1 || idx == 2 || idx == 3)
++        SSL_CTX_set_options(sctx, SSL_OP_NO_TICKET);
++
++    SSL_CTX_sess_set_cache_size(sctx, 5);
++
++    if (idx == 3) {
++        SSL_CTX_set_tlsext_servername_callback(sctx, resume_servername_cb);
++        SSL_CTX_set_tlsext_servername_arg(sctx, &cbdata);
++        cbdata.cctx = cctx;
++        cbdata.sctx = sctx;
++        cbdata.recurse = 0;
++    }
++
++    for (i = 0; i < 30; i++) {
++        if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
++                                                NULL, NULL))
++                || !TEST_true(SSL_set_session(clientssl, sess)))
++            goto end;
++
++        /*
++         * Check simultaneous resumes. We pause the connection part way through
++         * the handshake by (mis)using the servername_cb. The pause occurs after
++         * session resumption has already occurred, but before any session
++         * tickets have been issued. While paused we run another complete
++         * handshake resuming the same session.
++         */
++        if (idx == 3) {
++            cbdata.i = i;
++            cbdata.sess = sess;
++        }
++
++        /*
++         * Recreate a bug where dynamically changing the max_early_data value
++         * can cause sessions in the session cache which cannot be deleted.
++         */
++        if ((idx == 0 || idx == 2) && (i % 3) == 2)
++            SSL_set_max_early_data(serverssl, 0);
++
++        if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
++            goto end;
++
++        if (sess == NULL || (idx == 0 && (i % 3) == 2)) {
++            if (!TEST_false(SSL_session_reused(clientssl)))
++                goto end;
++        } else {
++            if (!TEST_true(SSL_session_reused(clientssl)))
++                goto end;
++        }
++        SSL_SESSION_free(sess);
++
++        /* Do a full handshake, followed by two resumptions */
++        if ((i % 3) == 2) {
++            sess = NULL;
++        } else {
++            if (!TEST_ptr((sess = SSL_get1_session(clientssl))))
++                goto end;
++        }
++
++        SSL_shutdown(clientssl);
++        SSL_shutdown(serverssl);
++        SSL_free(serverssl);
++        SSL_free(clientssl);
++        serverssl = clientssl = NULL;
++    }
++
++    /* We should never exceed the session cache size limit */
++    if (!TEST_long_le(SSL_CTX_sess_number(sctx), 5))
++        goto end;
++
++    testresult = 1;
++ end:
++    SSL_free(serverssl);
++    SSL_free(clientssl);
++    SSL_CTX_free(sctx);
++    SSL_CTX_free(cctx);
++    SSL_SESSION_free(sess);
++    return testresult;
++}
++
++static struct next_proto_st {
++    int serverlen;
++    unsigned char server[40];
++    int clientlen;
++    unsigned char client[40];
++    int expected_ret;
++    size_t selectedlen;
++    unsigned char selected[40];
++} next_proto_tests[] = {
++    {
++        4, { 3, 'a', 'b', 'c' },
++        4, { 3, 'a', 'b', 'c' },
++        OPENSSL_NPN_NEGOTIATED,
++        3, { 'a', 'b', 'c' }
++    },
++    {
++        7, { 3, 'a', 'b', 'c', 2, 'a', 'b' },
++        4, { 3, 'a', 'b', 'c' },
++        OPENSSL_NPN_NEGOTIATED,
++        3, { 'a', 'b', 'c' }
++    },
++    {
++        7, { 2, 'a', 'b', 3, 'a', 'b', 'c', },
++        4, { 3, 'a', 'b', 'c' },
++        OPENSSL_NPN_NEGOTIATED,
++        3, { 'a', 'b', 'c' }
++    },
++    {
++        4, { 3, 'a', 'b', 'c' },
++        7, { 3, 'a', 'b', 'c', 2, 'a', 'b', },
++        OPENSSL_NPN_NEGOTIATED,
++        3, { 'a', 'b', 'c' }
++    },
++    {
++        4, { 3, 'a', 'b', 'c' },
++        7, { 2, 'a', 'b', 3, 'a', 'b', 'c'},
++        OPENSSL_NPN_NEGOTIATED,
++        3, { 'a', 'b', 'c' }
++    },
++    {
++        7, { 2, 'b', 'c', 3, 'a', 'b', 'c' },
++        7, { 2, 'a', 'b', 3, 'a', 'b', 'c'},
++        OPENSSL_NPN_NEGOTIATED,
++        3, { 'a', 'b', 'c' }
++    },
++    {
++        10, { 2, 'b', 'c', 3, 'a', 'b', 'c', 2, 'a', 'b' },
++        7, { 2, 'a', 'b', 3, 'a', 'b', 'c'},
++        OPENSSL_NPN_NEGOTIATED,
++        3, { 'a', 'b', 'c' }
++    },
++    {
++        4, { 3, 'b', 'c', 'd' },
++        4, { 3, 'a', 'b', 'c' },
++        OPENSSL_NPN_NO_OVERLAP,
++        3, { 'a', 'b', 'c' }
++    },
++    {
++        0, { 0 },
++        4, { 3, 'a', 'b', 'c' },
++        OPENSSL_NPN_NO_OVERLAP,
++        3, { 'a', 'b', 'c' }
++    },
++    {
++        -1, { 0 },
++        4, { 3, 'a', 'b', 'c' },
++        OPENSSL_NPN_NO_OVERLAP,
++        3, { 'a', 'b', 'c' }
++    },
++    {
++        4, { 3, 'a', 'b', 'c' },
++        0, { 0 },
++        OPENSSL_NPN_NO_OVERLAP,
++        0, { 0 }
++    },
++    {
++        4, { 3, 'a', 'b', 'c' },
++        -1, { 0 },
++        OPENSSL_NPN_NO_OVERLAP,
++        0, { 0 }
++    },
++    {
++        3, { 3, 'a', 'b', 'c' },
++        4, { 3, 'a', 'b', 'c' },
++        OPENSSL_NPN_NO_OVERLAP,
++        3, { 'a', 'b', 'c' }
++    },
++    {
++        4, { 3, 'a', 'b', 'c' },
++        3, { 3, 'a', 'b', 'c' },
++        OPENSSL_NPN_NO_OVERLAP,
++        0, { 0 }
++    }
++};
++
++static int test_select_next_proto(int idx)
++{
++    struct next_proto_st *np = &next_proto_tests[idx];
++    int ret = 0;
++    unsigned char *out, *client, *server;
++    unsigned char outlen;
++    unsigned int clientlen, serverlen;
++
++    if (np->clientlen == -1) {
++        client = NULL;
++        clientlen = 0;
++    } else {
++        client = np->client;
++        clientlen = (unsigned int)np->clientlen;
++    }
++    if (np->serverlen == -1) {
++        server = NULL;
++        serverlen = 0;
++    } else {
++        server = np->server;
++        serverlen = (unsigned int)np->serverlen;
++    }
++
++    if (!TEST_int_eq(SSL_select_next_proto(&out, &outlen, server, serverlen,
++                                           client, clientlen),
++                     np->expected_ret))
++        goto err;
++
++    if (np->selectedlen == 0) {
++        if (!TEST_ptr_null(out) || !TEST_uchar_eq(outlen, 0))
++            goto err;
++    } else {
++        if (!TEST_mem_eq(out, outlen, np->selected, np->selectedlen))
++            goto err;
++    }
++
++    ret = 1;
++ err:
++    return ret;
++}
++
++static const unsigned char fooprot[] = {3, 'f', 'o', 'o' };
++static const unsigned char barprot[] = {3, 'b', 'a', 'r' };
++
++#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG)
++static int npn_advert_cb(SSL *ssl, const unsigned char **out,
++                         unsigned int *outlen, void *arg)
++{
++    int *idx = (int *)arg;
++
++    switch (*idx) {
++    default:
++    case 0:
++        *out = fooprot;
++        *outlen = sizeof(fooprot);
++        return SSL_TLSEXT_ERR_OK;
++
++    case 1:
++        *outlen = 0;
++        return SSL_TLSEXT_ERR_OK;
++
++    case 2:
++        return SSL_TLSEXT_ERR_NOACK;
++    }
++}
++
++static int npn_select_cb(SSL *s, unsigned char **out, unsigned char *outlen,
++                         const unsigned char *in, unsigned int inlen, void *arg)
++{
++    int *idx = (int *)arg;
++
++    switch (*idx) {
++    case 0:
++    case 1:
++        *out = (unsigned char *)(fooprot + 1);
++        *outlen = *fooprot;
++        return SSL_TLSEXT_ERR_OK;
++
++    case 3:
++        *out = (unsigned char *)(barprot + 1);
++        *outlen = *barprot;
++        return SSL_TLSEXT_ERR_OK;
++
++    case 4:
++        *outlen = 0;
++        return SSL_TLSEXT_ERR_OK;
++
++    default:
++    case 2:
++        return SSL_TLSEXT_ERR_ALERT_FATAL;
++    }
++}
++
++/*
++ * Test the NPN callbacks
++ * Test 0: advert = foo, select = foo
++ * Test 1: advert = <empty>, select = foo
++ * Test 2: no advert
++ * Test 3: advert = foo, select = bar
++ * Test 4: advert = foo, select = <empty> (should fail)
++ */
++static int test_npn(int idx)
++{
++    SSL_CTX *sctx = NULL, *cctx = NULL;
++    SSL *serverssl = NULL, *clientssl = NULL;
++    int testresult = 0;
++
++    if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
++                                       TLS_client_method(), 0, TLS1_2_VERSION,
++                                       &sctx, &cctx, cert, privkey)))
++        goto end;
++
++    SSL_CTX_set_next_protos_advertised_cb(sctx, npn_advert_cb, &idx);
++    SSL_CTX_set_next_proto_select_cb(cctx, npn_select_cb, &idx);
++
++    if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
++                                      NULL)))
++        goto end;
++
++    if (idx == 4) {
++        /* We don't allow empty selection of NPN, so this should fail */
++        if (!TEST_false(create_ssl_connection(serverssl, clientssl,
++                                              SSL_ERROR_NONE)))
++            goto end;
++    } else {
++        const unsigned char *prot;
++        unsigned int protlen;
++
++        if (!TEST_true(create_ssl_connection(serverssl, clientssl,
++                                             SSL_ERROR_NONE)))
++            goto end;
++
++        SSL_get0_next_proto_negotiated(serverssl, &prot, &protlen);
++        switch (idx) {
++        case 0:
++        case 1:
++            if (!TEST_mem_eq(prot, protlen, fooprot + 1, *fooprot))
++                goto end;
++            break;
++        case 2:
++            if (!TEST_uint_eq(protlen, 0))
++                goto end;
++            break;
++        case 3:
++            if (!TEST_mem_eq(prot, protlen, barprot + 1, *barprot))
++                goto end;
++            break;
++        default:
++            TEST_error("Should not get here");
++            goto end;
++        }
++    }
++
++    testresult = 1;
++ end:
++    SSL_free(serverssl);
++    SSL_free(clientssl);
++    SSL_CTX_free(sctx);
++    SSL_CTX_free(cctx);
++
++    return testresult;
++}
++#endif /* !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG) */
++
++static int alpn_select_cb2(SSL *ssl, const unsigned char **out,
++                           unsigned char *outlen, const unsigned char *in,
++                           unsigned int inlen, void *arg)
++{
++    int *idx = (int *)arg;
++
++    switch (*idx) {
++    case 0:
++        *out = (unsigned char *)(fooprot + 1);
++        *outlen = *fooprot;
++        return SSL_TLSEXT_ERR_OK;
++
++    case 2:
++        *out = (unsigned char *)(barprot + 1);
++        *outlen = *barprot;
++        return SSL_TLSEXT_ERR_OK;
++
++    case 3:
++        *outlen = 0;
++        return SSL_TLSEXT_ERR_OK;
++
++    default:
++    case 1:
++        return SSL_TLSEXT_ERR_ALERT_FATAL;
++    }
++    return 0;
++}
++
++/*
++ * Test the ALPN callbacks
++ * Test 0: client = foo, select = foo
++ * Test 1: client = <empty>, select = none
++ * Test 2: client = foo, select = bar (should fail)
++ * Test 3: client = foo, select = <empty> (should fail)
++ */
++static int test_alpn(int idx)
++{
++    SSL_CTX *sctx = NULL, *cctx = NULL;
++    SSL *serverssl = NULL, *clientssl = NULL;
++    int testresult = 0;
++    const unsigned char *prots = fooprot;
++    unsigned int protslen = sizeof(fooprot);
++
++    if (!TEST_true(create_ssl_ctx_pair(libctx, TLS_server_method(),
++                                       TLS_client_method(), 0, 0,
++                                       &sctx, &cctx, cert, privkey)))
++        goto end;
++
++    SSL_CTX_set_alpn_select_cb(sctx, alpn_select_cb2, &idx);
++
++    if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl, NULL,
++                                      NULL)))
++        goto end;
++
++    if (idx == 1) {
++        prots = NULL;
++        protslen = 0;
++    }
++
++    /* SSL_set_alpn_protos returns 0 for success! */
++    if (!TEST_false(SSL_set_alpn_protos(clientssl, prots, protslen)))
++        goto end;
++
++    if (idx == 2 || idx == 3) {
++        /* We don't allow empty selection of NPN, so this should fail */
++        if (!TEST_false(create_ssl_connection(serverssl, clientssl,
++                                              SSL_ERROR_NONE)))
++            goto end;
++    } else {
++        const unsigned char *prot;
++        unsigned int protlen;
++
++        if (!TEST_true(create_ssl_connection(serverssl, clientssl,
++                                             SSL_ERROR_NONE)))
++            goto end;
++
++        SSL_get0_alpn_selected(clientssl, &prot, &protlen);
++        switch (idx) {
++        case 0:
++            if (!TEST_mem_eq(prot, protlen, fooprot + 1, *fooprot))
++                goto end;
++            break;
++        case 1:
++            if (!TEST_uint_eq(protlen, 0))
++                goto end;
++            break;
++        default:
++            TEST_error("Should not get here");
++            goto end;
++        }
++    }
++
++    testresult = 1;
++ end:
++    SSL_free(serverssl);
++    SSL_free(clientssl);
++    SSL_CTX_free(sctx);
++    SSL_CTX_free(cctx);
++
++    return testresult;
++}
++
+ OPT_TEST_DECLARE_USAGE("certfile privkeyfile srpvfile tmpfile provider config dhfile\n")
+ 
+ int setup_tests(void)
+@@ -11543,6 +12173,9 @@ int setup_tests(void)
+     ADD_TEST(test_set_verify_cert_store_ssl_ctx);
+     ADD_TEST(test_set_verify_cert_store_ssl);
+     ADD_ALL_TESTS(test_session_timeout, 1);
++#if !defined(OSSL_NO_USABLE_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
++    ADD_ALL_TESTS(test_session_cache_overflow, 4);
++#endif
+     ADD_TEST(test_load_dhfile);
+ #ifndef OSSL_NO_USABLE_TLS1_3
+     ADD_TEST(test_read_ahead_key_change);
+@@ -11558,6 +12191,12 @@ int setup_tests(void)
+     ADD_TEST(test_rstate_string);
+     ADD_ALL_TESTS(test_handshake_retry, 16);
+     ADD_TEST(test_data_retry);
++    ADD_ALL_TESTS(test_multi_resume, 5);
++    ADD_ALL_TESTS(test_select_next_proto, OSSL_NELEM(next_proto_tests));
++#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_NEXTPROTONEG)
++    ADD_ALL_TESTS(test_npn, 5);
++#endif
++    ADD_ALL_TESTS(test_alpn, 4);
+     return 1;
+ 
+  err:
+diff --git a/test/sslbuffertest.c b/test/sslbuffertest.c
+index 94229d54d62a..ee585742303b 100644
+--- a/test/sslbuffertest.c
++++ b/test/sslbuffertest.c
+@@ -8,10 +8,19 @@
+  * or in the file LICENSE in the source distribution.
+  */
+ 
++/*
++ * We need access to the deprecated low level Engine APIs for legacy purposes
++ * when the deprecated calls are not hidden
++ */
++#ifndef OPENSSL_NO_DEPRECATED_3_0
++# define OPENSSL_SUPPRESS_DEPRECATED
++#endif
++
+ #include <string.h>
+ #include <openssl/ssl.h>
+ #include <openssl/bio.h>
+ #include <openssl/err.h>
++#include <openssl/engine.h>
+ 
+ /* We include internal headers so we can check if the buffers are allocated */
+ #include "../ssl/ssl_local.h"
+@@ -175,6 +184,166 @@ static int test_func(int test)
+     return result;
+ }
+ 
++/*
++ * Test that attempting to free the buffers at points where they cannot be freed
++ * works as expected
++ * Test 0: Attempt to free buffers after a full record has been processed, but
++ *         the application has only performed a partial read
++ * Test 1: Attempt to free buffers after only a partial record header has been
++ *         received
++ * Test 2: Attempt to free buffers after a full record header but no record body
++ * Test 3: Attempt to free buffers after a full record hedaer and partial record
++ *         body
++ * Test 4-7: We repeat tests 0-3 but including data from a second pipelined
++ *           record
++ */
++static int test_free_buffers(int test)
++{
++    int result = 0;
++    SSL *serverssl = NULL, *clientssl = NULL;
++    const char testdata[] = "Test data";
++    char buf[120];
++    size_t written, readbytes;
++    int i, pipeline = test > 3;
++    ENGINE *e = NULL;
++
++    if (pipeline) {
++        e = load_dasync();
++        if (e == NULL)
++            goto end;
++        test -= 4;
++    }
++
++    if (!TEST_true(create_ssl_objects(serverctx, clientctx, &serverssl,
++                                      &clientssl, NULL, NULL)))
++        goto end;
++
++    if (pipeline) {
++        if (!TEST_true(SSL_set_cipher_list(serverssl, "AES128-SHA"))
++                || !TEST_true(SSL_set_max_proto_version(serverssl,
++                                                        TLS1_2_VERSION))
++                || !TEST_true(SSL_set_max_pipelines(serverssl, 2)))
++            goto end;
++    }
++
++    if (!TEST_true(create_ssl_connection(serverssl, clientssl,
++                                         SSL_ERROR_NONE)))
++        goto end;
++
++    /*
++     * For the non-pipeline case we write one record. For pipelining we write
++     * two records.
++     */
++    for (i = 0; i <= pipeline; i++) {
++        if (!TEST_true(SSL_write_ex(clientssl, testdata, strlen(testdata),
++                                    &written)))
++            goto end;
++    }
++
++    if (test == 0) {
++        size_t readlen = 1;
++
++        /*
++         * Deliberately only read the first byte - so the remaining bytes are
++         * still buffered. In the pipelining case we read as far as the first
++         * byte from the second record.
++         */
++        if (pipeline)
++            readlen += strlen(testdata);
++
++        if (!TEST_true(SSL_read_ex(serverssl, buf, readlen, &readbytes))
++                || !TEST_size_t_eq(readlen, readbytes))
++            goto end;
++    } else {
++        BIO *tmp;
++        size_t partial_len;
++
++        /* Remove all the data that is pending for read by the server */
++        tmp = SSL_get_rbio(serverssl);
++        if (!TEST_true(BIO_read_ex(tmp, buf, sizeof(buf), &readbytes))
++                || !TEST_size_t_lt(readbytes, sizeof(buf))
++                || !TEST_size_t_gt(readbytes, SSL3_RT_HEADER_LENGTH))
++            goto end;
++
++        switch(test) {
++        case 1:
++            partial_len = SSL3_RT_HEADER_LENGTH - 1;
++            break;
++        case 2:
++            partial_len = SSL3_RT_HEADER_LENGTH;
++            break;
++        case 3:
++            partial_len = readbytes - 1;
++            break;
++        default:
++            TEST_error("Invalid test index");
++            goto end;
++        }
++
++        if (pipeline) {
++            /* We happen to know the first record is 57 bytes long */
++            const size_t first_rec_len = 57;
++
++            if (test != 3)
++                partial_len += first_rec_len;
++
++            /*
++             * Sanity check. If we got the record len right then this should
++             * never fail.
++             */
++            if (!TEST_int_eq(buf[first_rec_len], SSL3_RT_APPLICATION_DATA))
++                goto end;
++        }
++
++        /*
++         * Put back just the partial record (plus the whole initial record in
++         * the pipelining case)
++         */
++        if (!TEST_true(BIO_write_ex(tmp, buf, partial_len, &written)))
++            goto end;
++
++        if (pipeline) {
++            /*
++             * Attempt a read. This should pass but only return data from the
++             * first record. Only a partial record is available for the second
++             * record.
++             */
++            if (!TEST_true(SSL_read_ex(serverssl, buf, sizeof(buf),
++                                        &readbytes))
++                    || !TEST_size_t_eq(readbytes, strlen(testdata)))
++                goto end;
++        } else {
++            /*
++            * Attempt a read. This should fail because only a partial record is
++            * available.
++            */
++            if (!TEST_false(SSL_read_ex(serverssl, buf, sizeof(buf),
++                                        &readbytes)))
++                goto end;
++        }
++    }
++
++    /*
++     * Attempting to free the buffers at this point should fail because they are
++     * still in use
++     */
++    if (!TEST_false(SSL_free_buffers(serverssl)))
++        goto end;
++
++    result = 1;
++ end:
++    SSL_free(clientssl);
++    SSL_free(serverssl);
++#ifndef OPENSSL_NO_DYNAMIC_ENGINE
++    if (e != NULL) {
++        ENGINE_unregister_ciphers(e);
++        ENGINE_finish(e);
++        ENGINE_free(e);
++    }
++#endif
++    return result;
++}
++
+ OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n")
+ 
+ int setup_tests(void)
+@@ -198,6 +367,11 @@ int setup_tests(void)
+     }
+ 
+     ADD_ALL_TESTS(test_func, 9);
++#if !defined(OPENSSL_NO_TLS1_2) && !defined(OPENSSL_NO_DYNAMIC_ENGINE)
++    ADD_ALL_TESTS(test_free_buffers, 8);
++#else
++    ADD_ALL_TESTS(test_free_buffers, 4);
++#endif
+     return 1;
+ }
+ 
+diff --git a/util/perl/TLSProxy/Message.pm b/util/perl/TLSProxy/Message.pm
+index ce221875697f..fb41b2ffc8bf 100644
+--- a/util/perl/TLSProxy/Message.pm
++++ b/util/perl/TLSProxy/Message.pm
+@@ -384,6 +384,15 @@ sub create_message
+             [@message_frag_lens]
+         );
+         $message->parse();
++    }  elsif ($mt == MT_NEXT_PROTO) {
++        $message = TLSProxy::NextProto->new(
++            $server,
++            $data,
++            [@message_rec_list],
++            $startoffset,
++            [@message_frag_lens]
++        );
++        $message->parse();
+     } else {
+         #Unknown message type
+         $message = TLSProxy::Message->new(
+diff --git a/util/perl/TLSProxy/NextProto.pm b/util/perl/TLSProxy/NextProto.pm
+new file mode 100644
+index 000000000000..0e1834754667
+--- /dev/null
++++ b/util/perl/TLSProxy/NextProto.pm
+@@ -0,0 +1,54 @@
++# Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
++#
++# Licensed under the Apache License 2.0 (the "License").  You may not use
++# this file except in compliance with the License.  You can obtain a copy
++# in the file LICENSE in the source distribution or at
++# https://www.openssl.org/source/license.html
++
++use strict;
++
++package TLSProxy::NextProto;
++
++use vars '@ISA';
++push @ISA, 'TLSProxy::Message';
++
++sub new
++{
++    my $class = shift;
++    my ($server,
++        $data,
++        $records,
++        $startoffset,
++        $message_frag_lens) = @_;
++
++    my $self = $class->SUPER::new(
++        $server,
++        TLSProxy::Message::MT_NEXT_PROTO,
++        $data,
++        $records,
++        $startoffset,
++        $message_frag_lens);
++
++    return $self;
++}
++
++sub parse
++{
++    # We don't support parsing at the moment
++}
++
++# This is supposed to reconstruct the on-the-wire message data following changes.
++# For now though since we don't support parsing we just create an empty NextProto
++# message - this capability is used in test_npn
++sub set_message_contents
++{
++    my $self = shift;
++    my $data;
++
++    $data = pack("C32", 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++                 0x00, 0x00, 0x00);
++    $self->data($data);
++}
++1;
+diff --git a/util/perl/TLSProxy/Proxy.pm b/util/perl/TLSProxy/Proxy.pm
+index 3de10eccb94e..b707722b6b46 100644
+--- a/util/perl/TLSProxy/Proxy.pm
++++ b/util/perl/TLSProxy/Proxy.pm
+@@ -23,6 +23,7 @@ use TLSProxy::CertificateRequest;
+ use TLSProxy::CertificateVerify;
+ use TLSProxy::ServerKeyExchange;
+ use TLSProxy::NewSessionTicket;
++use TLSProxy::NextProto;
+ 
+ my $have_IPv6;
+ my $IP_factory;
diff -Nru openssl-3.2.1/debian/patches/Merge-remote-tracking-branch-source-openkylin-nile-into-o.patch openssl-3.2.1/debian/patches/Merge-remote-tracking-branch-source-openkylin-nile-into-o.patch
--- openssl-3.2.1/debian/patches/Merge-remote-tracking-branch-source-openkylin-nile-into-o.patch	1970-01-01 08:00:00.000000000 +0800
+++ openssl-3.2.1/debian/patches/Merge-remote-tracking-branch-source-openkylin-nile-into-o.patch	2025-02-25 14:23:13.000000000 +0800
@@ -0,0 +1,160 @@
+From: openkylin-cibot <openkylin-cibot@kylinos.cn>
+Date: Tue, 25 Feb 2025 07:04:58 +0000
+Subject: Merge remote-tracking branch 'source/openkylin/nile' into
+ openkylin/nile
+
+---
+ CHANGES.md          | 14 ++++++++++++++
+ NEWS.md             |  4 ++++
+ crypto/bn/bn_exp.c  | 21 +++++++++++++++------
+ crypto/ec/ec_lib.c  |  7 ++++---
+ include/crypto/bn.h |  3 +++
+ 5 files changed, 40 insertions(+), 9 deletions(-)
+
+diff --git a/CHANGES.md b/CHANGES.md
+index b8f07885c368..bfaf405644f6 100644
+--- a/CHANGES.md
++++ b/CHANGES.md
+@@ -27,6 +27,19 @@ OpenSSL 3.2
+ 
+ ### Changes between 3.2.0 and 3.2.1 [30 Jan 2024]
+ 
++ * Fixed timing side-channel in ECDSA signature computation.
++
++   There is a timing signal of around 300 nanoseconds when the top word of
++   the inverted ECDSA nonce value is zero. This can happen with significant
++   probability only for some of the supported elliptic curves. In particular
++   the NIST P-521 curve is affected. To be able to measure this leak, the
++   attacker process must either be located in the same physical computer or
++   must have a very fast network connection with low latency.
++
++   ([CVE-2024-13176])
++
++   *Tomáš Mráz*
++
+  * Fixed possible OOB memory access with invalid low-level GF(2^m) elliptic
+    curve parameters.
+ 
+@@ -20466,6 +20479,7 @@ ndif
+    *Edward Bishop <ebishop@spyglass.com>*
+ 
+ <!-- Links -->
++[CVE-2024-13176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-13176
+ [CVE-2024-9143]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-9143
+ [CVE-2024-6119]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-6119
+ [CVE-2024-5535]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-5535
+diff --git a/NEWS.md b/NEWS.md
+index 70e8dc8ee07a..86b32beea3e5 100644
+--- a/NEWS.md
++++ b/NEWS.md
+@@ -24,6 +24,9 @@ OpenSSL 3.2
+ 
+ This release incorporates the following bug fixes and mitigations:
+ 
++  * Fixed timing side-channel in ECDSA signature computation.
++    ([CVE-2024-13176])
++
+   * Fixed possible OOB memory access with invalid low-level GF(2^m) elliptic
+     curve parameters.
+     ([CVE-2024-9143])
+@@ -1596,6 +1599,7 @@ OpenSSL 0.9.x
+   * Support for various new platforms
+ 
+ <!-- Links -->
++[CVE-2024-13176]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-13176
+ [CVE-2024-9143]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-9143
+ [CVE-2024-6119]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-6119
+ [CVE-2024-5535]: https://www.openssl.org/news/vulnerabilities.html#CVE-2024-5535
+diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c
+index b876edbfac36..af52e2ced691 100644
+--- a/crypto/bn/bn_exp.c
++++ b/crypto/bn/bn_exp.c
+@@ -606,7 +606,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top,
+  * out by Colin Percival,
+  * http://www.daemonology.net/hyperthreading-considered-harmful/)
+  */
+-int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
++int bn_mod_exp_mont_fixed_top(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+                               const BIGNUM *m, BN_CTX *ctx,
+                               BN_MONT_CTX *in_mont)
+ {
+@@ -623,10 +623,6 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+     unsigned int t4 = 0;
+ #endif
+ 
+-    bn_check_top(a);
+-    bn_check_top(p);
+-    bn_check_top(m);
+-
+     if (!BN_is_odd(m)) {
+         ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS);
+         return 0;
+@@ -1146,7 +1142,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+             goto err;
+     } else
+ #endif
+-    if (!BN_from_montgomery(rr, &tmp, mont, ctx))
++    if (!bn_from_mont_fixed_top(rr, &tmp, mont, ctx))
+         goto err;
+     ret = 1;
+  err:
+@@ -1160,6 +1156,19 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
+     return ret;
+ }
+ 
++int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
++                              const BIGNUM *m, BN_CTX *ctx,
++                              BN_MONT_CTX *in_mont)
++{
++    bn_check_top(a);
++    bn_check_top(p);
++    bn_check_top(m);
++    if (!bn_mod_exp_mont_fixed_top(rr, a, p, m, ctx, in_mont))
++        return 0;
++    bn_correct_top(rr);
++    return 1;
++}
++
+ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
+                          const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
+ {
+diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
+index c92b4dcb0ac4..a79fbb98cf6f 100644
+--- a/crypto/ec/ec_lib.c
++++ b/crypto/ec/ec_lib.c
+@@ -21,6 +21,7 @@
+ #include <openssl/opensslv.h>
+ #include <openssl/param_build.h>
+ #include "crypto/ec.h"
++#include "crypto/bn.h"
+ #include "internal/nelem.h"
+ #include "ec_local.h"
+ 
+@@ -1261,10 +1262,10 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
+     if (!BN_sub(e, group->order, e))
+         goto err;
+     /*-
+-     * Exponent e is public.
+-     * No need for scatter-gather or BN_FLG_CONSTTIME.
++     * Although the exponent is public we want the result to be
++     * fixed top.
+      */
+-    if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data))
++    if (!bn_mod_exp_mont_fixed_top(r, x, e, group->order, ctx, group->mont_data))
+         goto err;
+ 
+     ret = 1;
+diff --git a/include/crypto/bn.h b/include/crypto/bn.h
+index 33f979ce9176..25ac24a65874 100644
+--- a/include/crypto/bn.h
++++ b/include/crypto/bn.h
+@@ -73,6 +73,9 @@ int bn_set_words(BIGNUM *a, const BN_ULONG *words, int num_words);
+  */
+ int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+                           BN_MONT_CTX *mont, BN_CTX *ctx);
++int bn_mod_exp_mont_fixed_top(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
++                              const BIGNUM *m, BN_CTX *ctx,
++                              BN_MONT_CTX *in_mont);
+ int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
+                          BN_CTX *ctx);
+ int bn_from_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
diff -Nru openssl-3.2.1/debian/patches/series openssl-3.2.1/debian/patches/series
--- openssl-3.2.1/debian/patches/series	2024-07-11 17:11:09.000000000 +0800
+++ openssl-3.2.1/debian/patches/series	2025-02-25 14:23:13.000000000 +0800
@@ -9,3 +9,5 @@
 skip_tls1.1_seclevel3_tests.patch
 6-CVE-2023-1255.patch
 10-riscv64.patch
+14-CVE.patch
+Merge-remote-tracking-branch-source-openkylin-nile-into-o.patch