]> git.ipfire.org Git - thirdparty/openssl.git/blobdiff - ssl/statem/extensions.c
RFC7250 (RPK) support
[thirdparty/openssl.git] / ssl / statem / extensions.c
index 7f9fd5f02e0453d588cd2ce5ddf402309bbf0e6f..3bb7c4af2625beabb3a9844bdd0ba16051947684 100644 (file)
@@ -1,61 +1,76 @@
 /*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * 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
  */
 
+#if defined(__TANDEM) && defined(_SPT_MODEL_)
+# include <spthread.h>
+# include <spt_extensions.h> /* timeval */
+#endif
+
 #include <string.h>
 #include "internal/nelem.h"
 #include "internal/cryptlib.h"
-#include "../ssl_locl.h"
-#include "statem_locl.h"
-#include "internal/cryptlib.h"
-
-static int final_renegotiate(SSL *s, unsigned int context, int sent);
-static int init_server_name(SSL *s, unsigned int context);
-static int final_server_name(SSL *s, unsigned int context, int sent);
-#ifndef OPENSSL_NO_EC
-static int final_ec_pt_formats(SSL *s, unsigned int context, int sent);
-#endif
-static int init_session_ticket(SSL *s, unsigned int context);
+#include "../ssl_local.h"
+#include "statem_local.h"
+
+static int final_renegotiate(SSL_CONNECTION *s, unsigned int context, int sent);
+static int init_server_name(SSL_CONNECTION *s, unsigned int context);
+static int final_server_name(SSL_CONNECTION *s, unsigned int context, int sent);
+static int final_ec_pt_formats(SSL_CONNECTION *s, unsigned int context,
+                               int sent);
+static int init_session_ticket(SSL_CONNECTION *s, unsigned int context);
 #ifndef OPENSSL_NO_OCSP
-static int init_status_request(SSL *s, unsigned int context);
+static int init_status_request(SSL_CONNECTION *s, unsigned int context);
 #endif
 #ifndef OPENSSL_NO_NEXTPROTONEG
-static int init_npn(SSL *s, unsigned int context);
+static int init_npn(SSL_CONNECTION *s, unsigned int context);
 #endif
-static int init_alpn(SSL *s, unsigned int context);
-static int final_alpn(SSL *s, unsigned int context, int sent);
-static int init_sig_algs_cert(SSL *s, unsigned int context);
-static int init_sig_algs(SSL *s, unsigned int context);
-static int init_certificate_authorities(SSL *s, unsigned int context);
-static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
+static int init_alpn(SSL_CONNECTION *s, unsigned int context);
+static int final_alpn(SSL_CONNECTION *s, unsigned int context, int sent);
+static int init_sig_algs_cert(SSL_CONNECTION *s, unsigned int context);
+static int init_sig_algs(SSL_CONNECTION *s, unsigned int context);
+static int init_server_cert_type(SSL_CONNECTION *sc, unsigned int context);
+static int init_client_cert_type(SSL_CONNECTION *sc, unsigned int context);
+static int init_certificate_authorities(SSL_CONNECTION *s,
+                                        unsigned int context);
+static EXT_RETURN tls_construct_certificate_authorities(SSL_CONNECTION *s,
+                                                        WPACKET *pkt,
                                                         unsigned int context,
                                                         X509 *x,
                                                         size_t chainidx);
-static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
+static int tls_parse_certificate_authorities(SSL_CONNECTION *s, PACKET *pkt,
                                              unsigned int context, X509 *x,
                                              size_t chainidx);
 #ifndef OPENSSL_NO_SRP
-static int init_srp(SSL *s, unsigned int context);
-#endif
-static int init_etm(SSL *s, unsigned int context);
-static int init_ems(SSL *s, unsigned int context);
-static int final_ems(SSL *s, unsigned int context, int sent);
-static int init_psk_kex_modes(SSL *s, unsigned int context);
-#ifndef OPENSSL_NO_EC
-static int final_key_share(SSL *s, unsigned int context, int sent);
+static int init_srp(SSL_CONNECTION *s, unsigned int context);
 #endif
+static int init_ec_point_formats(SSL_CONNECTION *s, unsigned int context);
+static int init_etm(SSL_CONNECTION *s, unsigned int context);
+static int init_ems(SSL_CONNECTION *s, unsigned int context);
+static int final_ems(SSL_CONNECTION *s, unsigned int context, int sent);
+static int init_psk_kex_modes(SSL_CONNECTION *s, unsigned int context);
+static int final_key_share(SSL_CONNECTION *s, unsigned int context, int sent);
 #ifndef OPENSSL_NO_SRTP
-static int init_srtp(SSL *s, unsigned int context);
+static int init_srtp(SSL_CONNECTION *s, unsigned int context);
 #endif
-static int final_sig_algs(SSL *s, unsigned int context, int sent);
-static int final_early_data(SSL *s, unsigned int context, int sent);
-static int final_maxfragmentlen(SSL *s, unsigned int context, int sent);
-static int init_post_handshake_auth(SSL *s, unsigned int context);
+static int final_sig_algs(SSL_CONNECTION *s, unsigned int context, int sent);
+static int final_early_data(SSL_CONNECTION *s, unsigned int context, int sent);
+static int final_maxfragmentlen(SSL_CONNECTION *s, unsigned int context,
+                                int sent);
+static int init_post_handshake_auth(SSL_CONNECTION *s, unsigned int context);
+static int final_psk(SSL_CONNECTION *s, unsigned int context, int sent);
+static int tls_init_compress_certificate(SSL_CONNECTION *sc, unsigned int context);
+static EXT_RETURN tls_construct_compress_certificate(SSL_CONNECTION *sc, WPACKET *pkt,
+                                                     unsigned int context,
+                                                     X509 *x, size_t chainidx);
+static int tls_parse_compress_certificate(SSL_CONNECTION *sc, PACKET *pkt,
+                                          unsigned int context,
+                                          X509 *x, size_t chainidx);
 
 /* Structure to define a built-in extension */
 typedef struct extensions_definition_st {
@@ -70,31 +85,36 @@ typedef struct extensions_definition_st {
      * Initialise extension before parsing. Always called for relevant contexts
      * even if extension not present
      */
-    int (*init)(SSL *s, unsigned int context);
+    int (*init)(SSL_CONNECTION *s, unsigned int context);
     /* Parse extension sent from client to server */
-    int (*parse_ctos)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                      size_t chainidx);
+    int (*parse_ctos)(SSL_CONNECTION *s, PACKET *pkt, unsigned int context,
+                      X509 *x, size_t chainidx);
     /* Parse extension send from server to client */
-    int (*parse_stoc)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
-                      size_t chainidx);
+    int (*parse_stoc)(SSL_CONNECTION *s, PACKET *pkt, unsigned int context,
+                      X509 *x, size_t chainidx);
     /* Construct extension sent from server to client */
-    EXT_RETURN (*construct_stoc)(SSL *s, WPACKET *pkt, unsigned int context,
+    EXT_RETURN (*construct_stoc)(SSL_CONNECTION *s, WPACKET *pkt,
+                                 unsigned int context,
                                  X509 *x, size_t chainidx);
     /* Construct extension sent from client to server */
-    EXT_RETURN (*construct_ctos)(SSL *s, WPACKET *pkt, unsigned int context,
+    EXT_RETURN (*construct_ctos)(SSL_CONNECTION *s, WPACKET *pkt,
+                                 unsigned int context,
                                  X509 *x, size_t chainidx);
     /*
      * Finalise extension after parsing. Always called where an extensions was
      * initialised even if the extension was not present. |sent| is set to 1 if
      * the extension was seen, or 0 otherwise.
      */
-    int (*final)(SSL *s, unsigned int context, int sent);
+    int (*final)(SSL_CONNECTION *s, unsigned int context, int sent);
 } EXTENSION_DEFINITION;
 
 /*
  * Definitions of all built-in extensions. NOTE: Changes in the number or order
  * of these extensions should be mirrored with equivalent changes to the
- * indexes ( TLSEXT_IDX_* ) defined in ssl_locl.h.
+ * indexes ( TLSEXT_IDX_* ) defined in ssl_local.h.
+ * Extensions should be added to test/ext_internal_test.c as well, as that
+ * tests the ordering of the extensions.
+ *
  * Each extension has an initialiser, a client and
  * server side parser and a finaliser. The initialiser is called (if the
  * extension is relevant to the given context) even if we did not see the
@@ -112,12 +132,10 @@ typedef struct extensions_definition_st {
  * messages the extension is relevant to. These flags also specify whether the
  * extension is relevant to a particular protocol or protocol version.
  *
- * TODO(TLS1.3): Make sure we have a test to check the consistency of these
- *
  * NOTE: WebSphere Application Server 7+ cannot handle empty extensions at
  * the end, keep these extensions before signature_algorithm.
  */
-#define INVALID_EXTENSION { 0x10000, 0, NULL, NULL, NULL, NULL, NULL, NULL }
+#define INVALID_EXTENSION { TLSEXT_TYPE_invalid, 0, NULL, NULL, NULL, NULL, NULL, NULL }
 static const EXTENSION_DEFINITION ext_defs[] = {
     {
         TLSEXT_TYPE_renegotiate,
@@ -153,12 +171,11 @@ static const EXTENSION_DEFINITION ext_defs[] = {
 #else
     INVALID_EXTENSION,
 #endif
-#ifndef OPENSSL_NO_EC
     {
         TLSEXT_TYPE_ec_point_formats,
         SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
         | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
-        NULL, tls_parse_ctos_ec_pt_formats, tls_parse_stoc_ec_pt_formats,
+        init_ec_point_formats, tls_parse_ctos_ec_pt_formats, tls_parse_stoc_ec_pt_formats,
         tls_construct_stoc_ec_pt_formats, tls_construct_ctos_ec_pt_formats,
         final_ec_pt_formats
     },
@@ -195,10 +212,6 @@ static const EXTENSION_DEFINITION ext_defs[] = {
         tls_construct_stoc_supported_groups,
         tls_construct_ctos_supported_groups, NULL
     },
-#else
-    INVALID_EXTENSION,
-    INVALID_EXTENSION,
-#endif
     {
         TLSEXT_TYPE_session_ticket,
         SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
@@ -298,6 +311,24 @@ static const EXTENSION_DEFINITION ext_defs[] = {
         NULL, tls_construct_ctos_post_handshake_auth,
         NULL,
     },
+    {
+        TLSEXT_TYPE_client_cert_type,
+        SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
+        | SSL_EXT_TLS1_2_SERVER_HELLO,
+        init_client_cert_type,
+        tls_parse_ctos_client_cert_type, tls_parse_stoc_client_cert_type,
+        tls_construct_stoc_client_cert_type, tls_construct_ctos_client_cert_type,
+        NULL
+    },
+    {
+        TLSEXT_TYPE_server_cert_type,
+        SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
+        | SSL_EXT_TLS1_2_SERVER_HELLO,
+        init_server_cert_type,
+        tls_parse_ctos_server_cert_type, tls_parse_stoc_server_cert_type,
+        tls_construct_stoc_server_cert_type, tls_construct_ctos_server_cert_type,
+        NULL
+    },
     {
         TLSEXT_TYPE_signature_algorithms,
         SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
@@ -322,7 +353,6 @@ static const EXTENSION_DEFINITION ext_defs[] = {
         init_psk_kex_modes, tls_parse_ctos_psk_kex_modes, NULL, NULL,
         tls_construct_ctos_psk_kex_modes, NULL
     },
-#ifndef OPENSSL_NO_EC
     {
         /*
          * Must be in this list after supported_groups. We need that to have
@@ -336,7 +366,6 @@ static const EXTENSION_DEFINITION ext_defs[] = {
         tls_construct_stoc_key_share, tls_construct_ctos_key_share,
         final_key_share
     },
-#endif
     {
         /* Must be after key_share */
         TLSEXT_TYPE_cookie,
@@ -348,12 +377,23 @@ static const EXTENSION_DEFINITION ext_defs[] = {
     {
         /*
          * Special unsolicited ServerHello extension only used when
-         * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set
+         * SSL_OP_CRYPTOPRO_TLSEXT_BUG is set. We allow it in a ClientHello but
+         * ignore it.
          */
         TLSEXT_TYPE_cryptopro_bug,
-        SSL_EXT_TLS1_2_SERVER_HELLO | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
+        SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
+        | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
         NULL, NULL, NULL, tls_construct_stoc_cryptopro_bug, NULL, NULL
     },
+    {
+        TLSEXT_TYPE_compress_certificate,
+        SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
+        | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
+        tls_init_compress_certificate,
+        tls_parse_compress_certificate, tls_parse_compress_certificate,
+        tls_construct_compress_certificate, tls_construct_compress_certificate,
+        NULL
+    },
     {
         TLSEXT_TYPE_early_data,
         SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
@@ -385,18 +425,30 @@ static const EXTENSION_DEFINITION ext_defs[] = {
         SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
         | SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
         NULL, tls_parse_ctos_psk, tls_parse_stoc_psk, tls_construct_stoc_psk,
-        tls_construct_ctos_psk, NULL
+        tls_construct_ctos_psk, final_psk
     }
 };
 
+/* Returns a TLSEXT_TYPE for the given index */
+unsigned int ossl_get_extension_type(size_t idx)
+{
+    size_t num_exts = OSSL_NELEM(ext_defs);
+
+    if (idx >= num_exts)
+        return TLSEXT_TYPE_out_of_range;
+
+    return ext_defs[idx].type;
+}
+
 /* Check whether an extension's context matches the current context */
-static int validate_context(SSL *s, unsigned int extctx, unsigned int thisctx)
+static int validate_context(SSL_CONNECTION *s, unsigned int extctx,
+                            unsigned int thisctx)
 {
     /* Check we're allowed to use this extension in this context */
     if ((thisctx & extctx) == 0)
         return 0;
 
-    if (SSL_IS_DTLS(s)) {
+    if (SSL_CONNECTION_IS_DTLS(s)) {
         if ((extctx & SSL_EXT_TLS_ONLY) != 0)
             return 0;
     } else if ((extctx & SSL_EXT_DTLS_ONLY) != 0) {
@@ -406,7 +458,8 @@ static int validate_context(SSL *s, unsigned int extctx, unsigned int thisctx)
     return 1;
 }
 
-int tls_validate_all_contexts(SSL *s, unsigned int thisctx, RAW_EXTENSION *exts)
+int tls_validate_all_contexts(SSL_CONNECTION *s, unsigned int thisctx,
+                              RAW_EXTENSION *exts)
 {
     size_t i, num_exts, builtin_num = OSSL_NELEM(ext_defs), offset;
     RAW_EXTENSION *thisext;
@@ -450,9 +503,9 @@ int tls_validate_all_contexts(SSL *s, unsigned int thisctx, RAW_EXTENSION *exts)
  * indicate the extension is not allowed. If returning 1 then |*found| is set to
  * the definition for the extension we found.
  */
-static int verify_extension(SSL *s, unsigned int context, unsigned int type,
-                            custom_ext_methods *meths, RAW_EXTENSION *rawexlist,
-                            RAW_EXTENSION **found)
+static int verify_extension(SSL_CONNECTION *s, unsigned int context,
+                            unsigned int type, custom_ext_methods *meths,
+                            RAW_EXTENSION *rawexlist, RAW_EXTENSION **found)
 {
     size_t i;
     size_t builtin_num = OSSL_NELEM(ext_defs);
@@ -498,7 +551,8 @@ static int verify_extension(SSL *s, unsigned int context, unsigned int type,
  * the extension is relevant for the current context |thisctx| or not. Returns
  * 1 if the extension is relevant for this context, and 0 otherwise
  */
-int extension_is_relevant(SSL *s, unsigned int extctx, unsigned int thisctx)
+int extension_is_relevant(SSL_CONNECTION *s, unsigned int extctx,
+                          unsigned int thisctx)
 {
     int is_tls13;
 
@@ -509,9 +563,9 @@ int extension_is_relevant(SSL *s, unsigned int extctx, unsigned int thisctx)
     if ((thisctx & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0)
         is_tls13 = 1;
     else
-        is_tls13 = SSL_IS_TLS13(s);
+        is_tls13 = SSL_CONNECTION_IS_TLS13(s);
 
-    if ((SSL_IS_DTLS(s)
+    if ((SSL_CONNECTION_IS_DTLS(s)
                 && (extctx & SSL_EXT_TLS_IMPLEMENTATION_ONLY) != 0)
             || (s->version == SSL3_VERSION
                     && (extctx & SSL_EXT_SSL3_ALLOWED) == 0)
@@ -548,7 +602,8 @@ int extension_is_relevant(SSL *s, unsigned int extctx, unsigned int thisctx)
  * found, or an internal error occurred. We only check duplicates for
  * extensions that we know about. We ignore others.
  */
-int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
+int tls_collect_extensions(SSL_CONNECTION *s, PACKET *packet,
+                           unsigned int context,
                            RAW_EXTENSION **res, size_t *len, int init)
 {
     PACKET extensions = *packet;
@@ -570,8 +625,7 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
     num_exts = OSSL_NELEM(ext_defs) + (exts != NULL ? exts->meths_count : 0);
     raw_extensions = OPENSSL_zalloc(num_exts * sizeof(*raw_extensions));
     if (raw_extensions == NULL) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
-                 ERR_R_MALLOC_FAILURE);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
         return 0;
     }
 
@@ -583,8 +637,7 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
 
         if (!PACKET_get_net_2(&extensions, &type) ||
             !PACKET_get_length_prefixed_2(&extensions, &extension)) {
-            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
-                     SSL_R_BAD_EXTENSION);
+            SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
             goto err;
         }
         /*
@@ -597,8 +650,7 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
                 || (type == TLSEXT_TYPE_psk
                     && (context & SSL_EXT_CLIENT_HELLO) != 0
                     && PACKET_remaining(&extensions) != 0)) {
-            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_COLLECT_EXTENSIONS,
-                     SSL_R_BAD_EXTENSION);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EXTENSION);
             goto err;
         }
         idx = thisex - raw_extensions;
@@ -623,9 +675,14 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
                 && type != TLSEXT_TYPE_cookie
                 && type != TLSEXT_TYPE_renegotiate
                 && type != TLSEXT_TYPE_signed_certificate_timestamp
-                && (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0) {
+                && (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0
+#ifndef OPENSSL_NO_GOST
+                && !((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0
+                     && type == TLSEXT_TYPE_cryptopro_bug)
+#endif
+                                                                ) {
             SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
-                     SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_UNSOLICITED_EXTENSION);
+                     SSL_R_UNSOLICITED_EXTENSION);
             goto err;
         }
         if (thisex != NULL) {
@@ -634,8 +691,8 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
             thisex->type = type;
             thisex->received_order = i++;
             if (s->ext.debug_cb)
-                s->ext.debug_cb(s, !s->server, thisex->type,
-                                PACKET_data(&thisex->data),
+                s->ext.debug_cb(SSL_CONNECTION_GET_SSL(s), !s->server,
+                                thisex->type, PACKET_data(&thisex->data),
                                 PACKET_remaining(&thisex->data),
                                 s->ext.debug_arg);
         }
@@ -677,11 +734,11 @@ int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
  * Certificate. Returns 1 on success or 0 on failure. If an extension is not
  * present this counted as success.
  */
-int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
+int tls_parse_extension(SSL_CONNECTION *s, TLSEXT_INDEX idx, int context,
                         RAW_EXTENSION *exts, X509 *x, size_t chainidx)
 {
     RAW_EXTENSION *currext = &exts[idx];
-    int (*parser)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
+    int (*parser)(SSL_CONNECTION *s, PACKET *pkt, unsigned int context, X509 *x,
                   size_t chainidx) = NULL;
 
     /* Skip if the extension is not present */
@@ -727,7 +784,8 @@ int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
  * working on a Certificate message then we also pass the Certificate |x| and
  * its position in the |chainidx|, with 0 being the first certificate.
  */
-int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts, X509 *x,
+int tls_parse_all_extensions(SSL_CONNECTION *s, int context,
+                             RAW_EXTENSION *exts, X509 *x,
                              size_t chainidx, int fin)
 {
     size_t i, numexts = OSSL_NELEM(ext_defs);
@@ -762,8 +820,8 @@ int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts, X509 *x,
     return 1;
 }
 
-int should_add_extension(SSL *s, unsigned int extctx, unsigned int thisctx,
-                         int max_version)
+int should_add_extension(SSL_CONNECTION *s, unsigned int extctx,
+                         unsigned int thisctx, int max_version)
 {
     /* Skip if not relevant for our context */
     if ((extctx & thisctx) == 0)
@@ -773,7 +831,7 @@ int should_add_extension(SSL *s, unsigned int extctx, unsigned int thisctx,
     if (!extension_is_relevant(s, extctx, thisctx)
             || ((extctx & SSL_EXT_TLS1_3_ONLY) != 0
                 && (thisctx & SSL_EXT_CLIENT_HELLO) != 0
-                && (SSL_IS_DTLS(s) || max_version < TLS1_3_VERSION)))
+                && (SSL_CONNECTION_IS_DTLS(s) || max_version < TLS1_3_VERSION)))
         return 0;
 
     return 1;
@@ -787,12 +845,14 @@ int should_add_extension(SSL *s, unsigned int extctx, unsigned int thisctx,
  * 0 being the first in the chain). Returns 1 on success or 0 on failure. On a
  * failure construction stops at the first extension to fail to construct.
  */
-int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
+int tls_construct_extensions(SSL_CONNECTION *s, WPACKET *pkt,
+                             unsigned int context,
                              X509 *x, size_t chainidx)
 {
     size_t i;
     int min_version, max_version = 0, reason;
     const EXTENSION_DEFINITION *thisexd;
+    int for_comp = (context & SSL_EXT_TLS1_3_CERTIFICATE_COMPRESSION) != 0;
 
     if (!WPACKET_start_sub_packet_u16(pkt)
                /*
@@ -803,17 +863,17 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
             || ((context &
                  (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0
                 && !WPACKET_set_flags(pkt,
-                                     WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
-                 ERR_R_INTERNAL_ERROR);
+                                      WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) {
+        if (!for_comp)
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
     if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
-        reason = ssl_get_min_max_version(s, &min_version, &max_version);
+        reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL);
         if (reason != 0) {
-            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
-                     reason);
+            if (!for_comp)
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, reason);
             return 0;
         }
     }
@@ -829,7 +889,8 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
     }
 
     for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs); i++, thisexd++) {
-        EXT_RETURN (*construct)(SSL *s, WPACKET *pkt, unsigned int context,
+        EXT_RETURN (*construct)(SSL_CONNECTION *s, WPACKET *pkt,
+                                unsigned int context,
                                 X509 *x, size_t chainidx);
         EXT_RETURN ret;
 
@@ -856,8 +917,8 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
     }
 
     if (!WPACKET_close(pkt)) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
-                 ERR_R_INTERNAL_ERROR);
+        if (!for_comp)
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
@@ -871,7 +932,7 @@ int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
  * otherwise. These functions return 1 on success or 0 on failure.
  */
 
-static int final_renegotiate(SSL *s, unsigned int context, int sent)
+static int final_renegotiate(SSL_CONNECTION *s, unsigned int context, int sent)
 {
     if (!s->server) {
         /*
@@ -881,7 +942,7 @@ static int final_renegotiate(SSL *s, unsigned int context, int sent)
         if (!(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
                 && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
                 && !sent) {
-            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
                      SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
             return 0;
         }
@@ -893,7 +954,7 @@ static int final_renegotiate(SSL *s, unsigned int context, int sent)
     if (s->renegotiate
             && !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
             && !sent) {
-        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
                  SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
         return 0;
     }
@@ -902,36 +963,64 @@ static int final_renegotiate(SSL *s, unsigned int context, int sent)
     return 1;
 }
 
-static int init_server_name(SSL *s, unsigned int context)
+static ossl_inline void ssl_tsan_decr(const SSL_CTX *ctx,
+                                      TSAN_QUALIFIER int *stat)
 {
-    if (s->server)
+    if (ssl_tsan_lock(ctx)) {
+        tsan_decr(stat);
+        ssl_tsan_unlock(ctx);
+    }
+}
+
+static int init_server_name(SSL_CONNECTION *s, unsigned int context)
+{
+    if (s->server) {
         s->servername_done = 0;
 
+        OPENSSL_free(s->ext.hostname);
+        s->ext.hostname = NULL;
+    }
+
     return 1;
 }
 
-static int final_server_name(SSL *s, unsigned int context, int sent)
+static int final_server_name(SSL_CONNECTION *s, unsigned int context, int sent)
 {
-    int ret = SSL_TLSEXT_ERR_NOACK, discard;
+    int ret = SSL_TLSEXT_ERR_NOACK;
     int altmp = SSL_AD_UNRECOGNIZED_NAME;
-    int was_ticket = (SSL_get_options(s) & SSL_OP_NO_TICKET) == 0;
+    SSL *ssl = SSL_CONNECTION_GET_SSL(s);
+    SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
+    int was_ticket = (SSL_get_options(ssl) & SSL_OP_NO_TICKET) == 0;
 
-    if (!ossl_assert(s->ctx != NULL) || !ossl_assert(s->session_ctx != NULL)) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
-                 ERR_R_INTERNAL_ERROR);
+    if (!ossl_assert(sctx != NULL) || !ossl_assert(s->session_ctx != NULL)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         return 0;
     }
 
-    if (s->ctx->ext.servername_cb != NULL)
-        ret = s->ctx->ext.servername_cb(s, &altmp,
-                                        s->ctx->ext.servername_arg);
+    if (sctx->ext.servername_cb != NULL)
+        ret = sctx->ext.servername_cb(ssl, &altmp,
+                                      sctx->ext.servername_arg);
     else if (s->session_ctx->ext.servername_cb != NULL)
-        ret = s->session_ctx->ext.servername_cb(s, &altmp,
+        ret = s->session_ctx->ext.servername_cb(ssl, &altmp,
                                        s->session_ctx->ext.servername_arg);
 
-    if (!sent) {
-        OPENSSL_free(s->session->ext.hostname);
-        s->session->ext.hostname = NULL;
+    /*
+     * For servers, propagate the SNI hostname from the temporary
+     * storage in the SSL to the persistent SSL_SESSION, now that we
+     * know we accepted it.
+     * Clients make this copy when parsing the server's response to
+     * the extension, which is when they find out that the negotiation
+     * was successful.
+     */
+    if (s->server) {
+        if (sent && ret == SSL_TLSEXT_ERR_OK && !s->hit) {
+            /* Only store the hostname in the session if we accepted it. */
+            OPENSSL_free(s->session->ext.hostname);
+            s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname);
+            if (s->session->ext.hostname == NULL && s->ext.hostname != NULL) {
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+            }
+        }
     }
 
     /*
@@ -940,11 +1029,10 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
      * context, to avoid the confusing situation of having sess_accept_good
      * exceed sess_accept (zero) for the new context.
      */
-    if (SSL_IS_FIRST_HANDSHAKE(s) && s->ctx != s->session_ctx) {
-        CRYPTO_atomic_add(&s->ctx->stats.sess_accept, 1, &discard,
-                          s->ctx->lock);
-        CRYPTO_atomic_add(&s->session_ctx->stats.sess_accept, -1, &discard,
-                          s->session_ctx->lock);
+    if (SSL_IS_FIRST_HANDSHAKE(s) && sctx != s->session_ctx
+            && s->hello_retry_request == SSL_HRR_NONE) {
+        ssl_tsan_counter(sctx, &sctx->stats.sess_accept);
+        ssl_tsan_decr(s->session_ctx, &s->session_ctx->stats.sess_accept);
     }
 
     /*
@@ -953,10 +1041,10 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
      * Also, if this is not a resumption, create a new session ID
      */
     if (ret == SSL_TLSEXT_ERR_OK && s->ext.ticket_expected
-            && was_ticket && (SSL_get_options(s) & SSL_OP_NO_TICKET) != 0) {
+            && was_ticket && (SSL_get_options(ssl) & SSL_OP_NO_TICKET) != 0) {
         s->ext.ticket_expected = 0;
         if (!s->hit) {
-            SSL_SESSION* ss = SSL_get_session(s);
+            SSL_SESSION* ss = SSL_get_session(ssl);
 
             if (ss != NULL) {
                 OPENSSL_free(ss->ext.tick);
@@ -964,15 +1052,12 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
                 ss->ext.ticklen = 0;
                 ss->ext.tick_lifetime_hint = 0;
                 ss->ext.tick_age_add = 0;
-                ss->ext.tick_identity = 0;
                 if (!ssl_generate_session_id(s, ss)) {
-                    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
-                             ERR_R_INTERNAL_ERROR);
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
                     return 0;
                 }
             } else {
-                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
-                         ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
                 return 0;
             }
         }
@@ -980,11 +1065,14 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
 
     switch (ret) {
     case SSL_TLSEXT_ERR_ALERT_FATAL:
-        SSLfatal(s, altmp, SSL_F_FINAL_SERVER_NAME, SSL_R_CALLBACK_FAILED);
+        SSLfatal(s, altmp, SSL_R_CALLBACK_FAILED);
         return 0;
 
     case SSL_TLSEXT_ERR_ALERT_WARNING:
-        ssl3_send_alert(s, SSL3_AL_WARNING, altmp);
+        /* TLSv1.3 doesn't have warning alerts so we suppress this */
+        if (!SSL_CONNECTION_IS_TLS13(s))
+            ssl3_send_alert(s, SSL3_AL_WARNING, altmp);
+        s->servername_done = 0;
         return 1;
 
     case SSL_TLSEXT_ERR_NOACK:
@@ -996,16 +1084,16 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
     }
 }
 
-#ifndef OPENSSL_NO_EC
-static int final_ec_pt_formats(SSL *s, unsigned int context, int sent)
+static int final_ec_pt_formats(SSL_CONNECTION *s, unsigned int context,
+                               int sent)
 {
     unsigned long alg_k, alg_a;
 
     if (s->server)
         return 1;
 
-    alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
-    alg_a = s->s3->tmp.new_cipher->algorithm_auth;
+    alg_k = s->s3.tmp.new_cipher->algorithm_mkey;
+    alg_a = s->s3.tmp.new_cipher->algorithm_auth;
 
     /*
      * If we are client and using an elliptic curve cryptography cipher
@@ -1014,19 +1102,19 @@ static int final_ec_pt_formats(SSL *s, unsigned int context, int sent)
      */
     if (s->ext.ecpointformats != NULL
             && s->ext.ecpointformats_len > 0
-            && s->session->ext.ecpointformats != NULL
-            && s->session->ext.ecpointformats_len > 0
+            && s->ext.peer_ecpointformats != NULL
+            && s->ext.peer_ecpointformats_len > 0
             && ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) {
         /* we are using an ECC cipher */
         size_t i;
-        unsigned char *list = s->session->ext.ecpointformats;
+        unsigned char *list = s->ext.peer_ecpointformats;
 
-        for (i = 0; i < s->session->ext.ecpointformats_len; i++) {
+        for (i = 0; i < s->ext.peer_ecpointformats_len; i++) {
             if (*list++ == TLSEXT_ECPOINTFORMAT_uncompressed)
                 break;
         }
-        if (i == s->session->ext.ecpointformats_len) {
-            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EC_PT_FORMATS,
+        if (i == s->ext.peer_ecpointformats_len) {
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
                      SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
             return 0;
         }
@@ -1034,9 +1122,8 @@ static int final_ec_pt_formats(SSL *s, unsigned int context, int sent)
 
     return 1;
 }
-#endif
 
-static int init_session_ticket(SSL *s, unsigned int context)
+static int init_session_ticket(SSL_CONNECTION *s, unsigned int context)
 {
     if (!s->server)
         s->ext.ticket_expected = 0;
@@ -1045,7 +1132,7 @@ static int init_session_ticket(SSL *s, unsigned int context)
 }
 
 #ifndef OPENSSL_NO_OCSP
-static int init_status_request(SSL *s, unsigned int context)
+static int init_status_request(SSL_CONNECTION *s, unsigned int context)
 {
     if (s->server) {
         s->ext.status_type = TLSEXT_STATUSTYPE_nothing;
@@ -1064,33 +1151,33 @@ static int init_status_request(SSL *s, unsigned int context)
 #endif
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
-static int init_npn(SSL *s, unsigned int context)
+static int init_npn(SSL_CONNECTION *s, unsigned int context)
 {
-    s->s3->npn_seen = 0;
+    s->s3.npn_seen = 0;
 
     return 1;
 }
 #endif
 
-static int init_alpn(SSL *s, unsigned int context)
+static int init_alpn(SSL_CONNECTION *s, unsigned int context)
 {
-    OPENSSL_free(s->s3->alpn_selected);
-    s->s3->alpn_selected = NULL;
-    s->s3->alpn_selected_len = 0;
+    OPENSSL_free(s->s3.alpn_selected);
+    s->s3.alpn_selected = NULL;
+    s->s3.alpn_selected_len = 0;
     if (s->server) {
-        OPENSSL_free(s->s3->alpn_proposed);
-        s->s3->alpn_proposed = NULL;
-        s->s3->alpn_proposed_len = 0;
+        OPENSSL_free(s->s3.alpn_proposed);
+        s->s3.alpn_proposed = NULL;
+        s->s3.alpn_proposed_len = 0;
     }
     return 1;
 }
 
-static int final_alpn(SSL *s, unsigned int context, int sent)
+static int final_alpn(SSL_CONNECTION *s, unsigned int context, int sent)
 {
     if (!s->server && !sent && s->session->ext.alpn_selected != NULL)
             s->ext.early_data_ok = 0;
 
-    if (!s->server || !SSL_IS_TLS13(s))
+    if (!s->server || !SSL_CONNECTION_IS_TLS13(s))
         return 1;
 
     /*
@@ -1105,26 +1192,29 @@ static int final_alpn(SSL *s, unsigned int context, int sent)
     return tls_handle_alpn(s);
 }
 
-static int init_sig_algs(SSL *s, unsigned int context)
+static int init_sig_algs(SSL_CONNECTION *s, unsigned int context)
 {
     /* Clear any signature algorithms extension received */
-    OPENSSL_free(s->s3->tmp.peer_sigalgs);
-    s->s3->tmp.peer_sigalgs = NULL;
+    OPENSSL_free(s->s3.tmp.peer_sigalgs);
+    s->s3.tmp.peer_sigalgs = NULL;
+    s->s3.tmp.peer_sigalgslen = 0;
 
     return 1;
 }
 
-static int init_sig_algs_cert(SSL *s, unsigned int context)
+static int init_sig_algs_cert(SSL_CONNECTION *s,
+                              ossl_unused unsigned int context)
 {
     /* Clear any signature algorithms extension received */
-    OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
-    s->s3->tmp.peer_cert_sigalgs = NULL;
+    OPENSSL_free(s->s3.tmp.peer_cert_sigalgs);
+    s->s3.tmp.peer_cert_sigalgs = NULL;
+    s->s3.tmp.peer_cert_sigalgslen = 0;
 
     return 1;
 }
 
 #ifndef OPENSSL_NO_SRP
-static int init_srp(SSL *s, unsigned int context)
+static int init_srp(SSL_CONNECTION *s, unsigned int context)
 {
     OPENSSL_free(s->srp_ctx.login);
     s->srp_ctx.login = NULL;
@@ -1133,32 +1223,51 @@ static int init_srp(SSL *s, unsigned int context)
 }
 #endif
 
-static int init_etm(SSL *s, unsigned int context)
+static int init_ec_point_formats(SSL_CONNECTION *s, unsigned int context)
+{
+    OPENSSL_free(s->ext.peer_ecpointformats);
+    s->ext.peer_ecpointformats = NULL;
+    s->ext.peer_ecpointformats_len = 0;
+
+    return 1;
+}
+
+static int init_etm(SSL_CONNECTION *s, unsigned int context)
 {
     s->ext.use_etm = 0;
 
     return 1;
 }
 
-static int init_ems(SSL *s, unsigned int context)
+static int init_ems(SSL_CONNECTION *s, unsigned int context)
 {
-    if (!s->server)
-        s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
+    if (s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) {
+        s->s3.flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
+        s->s3.flags |= TLS1_FLAGS_REQUIRED_EXTMS;
+    }
 
     return 1;
 }
 
-static int final_ems(SSL *s, unsigned int context, int sent)
+static int final_ems(SSL_CONNECTION *s, unsigned int context, int sent)
 {
+    /*
+     * Check extended master secret extension is not dropped on
+     * renegotiation.
+     */
+    if (!(s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS)
+        && (s->s3.flags & TLS1_FLAGS_REQUIRED_EXTMS)) {
+        SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_INCONSISTENT_EXTMS);
+        return 0;
+    }
     if (!s->server && s->hit) {
         /*
          * Check extended master secret extension is consistent with
          * original session.
          */
-        if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) !=
+        if (!(s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) !=
             !(s->session->flags & SSL_SESS_FLAG_EXTMS)) {
-            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_EMS,
-                     SSL_R_INCONSISTENT_EXTMS);
+            SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_INCONSISTENT_EXTMS);
             return 0;
         }
     }
@@ -1166,62 +1275,58 @@ static int final_ems(SSL *s, unsigned int context, int sent)
     return 1;
 }
 
-static int init_certificate_authorities(SSL *s, unsigned int context)
+static int init_certificate_authorities(SSL_CONNECTION *s, unsigned int context)
 {
-    sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
-    s->s3->tmp.peer_ca_names = NULL;
+    sk_X509_NAME_pop_free(s->s3.tmp.peer_ca_names, X509_NAME_free);
+    s->s3.tmp.peer_ca_names = NULL;
     return 1;
 }
 
-static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
+static EXT_RETURN tls_construct_certificate_authorities(SSL_CONNECTION *s,
+                                                        WPACKET *pkt,
                                                         unsigned int context,
                                                         X509 *x,
                                                         size_t chainidx)
 {
-    const STACK_OF(X509_NAME) *ca_sk = SSL_get0_CA_list(s);
+    const STACK_OF(X509_NAME) *ca_sk = get_ca_names(s);
 
     if (ca_sk == NULL || sk_X509_NAME_num(ca_sk) == 0)
         return EXT_RETURN_NOT_SENT;
 
     if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_certificate_authorities)
         || !WPACKET_start_sub_packet_u16(pkt)) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                 SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
-               ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
-    if (!construct_ca_names(s, pkt)) {
+    if (!construct_ca_names(s, ca_sk, pkt)) {
         /* SSLfatal() already called */
         return EXT_RETURN_FAIL;
     }
 
     if (!WPACKET_close(pkt)) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR,
-                 SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
-                 ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         return EXT_RETURN_FAIL;
     }
 
     return EXT_RETURN_SENT;
 }
 
-static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
+static int tls_parse_certificate_authorities(SSL_CONNECTION *s, PACKET *pkt,
                                              unsigned int context, X509 *x,
                                              size_t chainidx)
 {
     if (!parse_ca_names(s, pkt))
         return 0;
     if (PACKET_remaining(pkt) != 0) {
-        SSLfatal(s, SSL_AD_DECODE_ERROR,
-                 SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES, SSL_R_BAD_EXTENSION);
+        SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
         return 0;
     }
     return 1;
 }
 
 #ifndef OPENSSL_NO_SRTP
-static int init_srtp(SSL *s, unsigned int context)
+static int init_srtp(SSL_CONNECTION *s, unsigned int context)
 {
     if (s->server)
         s->srtp_profile = NULL;
@@ -1230,10 +1335,10 @@ static int init_srtp(SSL *s, unsigned int context)
 }
 #endif
 
-static int final_sig_algs(SSL *s, unsigned int context, int sent)
+static int final_sig_algs(SSL_CONNECTION *s, unsigned int context, int sent)
 {
-    if (!sent && SSL_IS_TLS13(s) && !s->hit) {
-        SSLfatal(s, TLS13_AD_MISSING_EXTENSION, SSL_F_FINAL_SIG_ALGS,
+    if (!sent && SSL_CONNECTION_IS_TLS13(s) && !s->hit) {
+        SSLfatal(s, TLS13_AD_MISSING_EXTENSION,
                  SSL_R_MISSING_SIGALGS_EXTENSION);
         return 0;
     }
@@ -1241,10 +1346,10 @@ static int final_sig_algs(SSL *s, unsigned int context, int sent)
     return 1;
 }
 
-#ifndef OPENSSL_NO_EC
-static int final_key_share(SSL *s, unsigned int context, int sent)
+static int final_key_share(SSL_CONNECTION *s, unsigned int context, int sent)
 {
-    if (!SSL_IS_TLS13(s))
+#if !defined(OPENSSL_NO_TLS1_3)
+    if (!SSL_CONNECTION_IS_TLS13(s))
         return 1;
 
     /* Nothing to do for key_share in an HRR */
@@ -1267,8 +1372,7 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
             && (!s->hit
                 || (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0)) {
         /* Nothing left we can do - just fail */
-        SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_KEY_SHARE,
-                 SSL_R_NO_SUITABLE_KEY_SHARE);
+        SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_R_NO_SUITABLE_KEY_SHARE);
         return 0;
     }
     /*
@@ -1306,9 +1410,9 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
      *             send a HelloRetryRequest
      */
     if (s->server) {
-        if (s->s3->peer_tmp != NULL) {
+        if (s->s3.peer_tmp != NULL) {
             /* We have a suitable key_share */
-            if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0
+            if ((s->s3.flags & TLS1_FLAGS_STATELESS) != 0
                     && !s->ext.cookieok) {
                 if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) {
                     /*
@@ -1316,8 +1420,7 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
                      * previously sent HRR - so how can this be anything other
                      * than 0?
                      */
-                    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
-                             ERR_R_INTERNAL_ERROR);
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
                     return 0;
                 }
                 s->hello_retry_request = SSL_HRR_PENDING;
@@ -1352,7 +1455,7 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
 
                 if (i < num_groups) {
                     /* A shared group exists so send a HelloRetryRequest */
-                    s->s3->group_id = group_id;
+                    s->s3.group_id = group_id;
                     s->hello_retry_request = SSL_HRR_PENDING;
                     return 1;
                 }
@@ -1362,11 +1465,11 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
                 /* Nothing left we can do - just fail */
                 SSLfatal(s, sent ? SSL_AD_HANDSHAKE_FAILURE
                                  : SSL_AD_MISSING_EXTENSION,
-                         SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
+                         SSL_R_NO_SUITABLE_KEY_SHARE);
                 return 0;
             }
 
-            if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0
+            if ((s->s3.flags & TLS1_FLAGS_STATELESS) != 0
                     && !s->ext.cookieok) {
                 if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) {
                     /*
@@ -1374,8 +1477,7 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
                      * previously sent HRR - so how can this be anything other
                      * than 0?
                      */
-                    SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
-                             ERR_R_INTERNAL_ERROR);
+                    SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
                     return 0;
                 }
                 s->hello_retry_request = SSL_HRR_PENDING;
@@ -1396,23 +1498,22 @@ static int final_key_share(SSL *s, unsigned int context, int sent)
          * processing).
          */
         if (!sent && !tls13_generate_handshake_secret(s, NULL, 0)) {
-            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
-                     ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
             return 0;
         }
     }
-
+#endif /* !defined(OPENSSL_NO_TLS1_3) */
     return 1;
 }
-#endif
 
-static int init_psk_kex_modes(SSL *s, unsigned int context)
+static int init_psk_kex_modes(SSL_CONNECTION *s, unsigned int context)
 {
     s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_NONE;
     return 1;
 }
 
-int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
+int tls_psk_do_binder(SSL_CONNECTION *s, const EVP_MD *md,
+                      const unsigned char *msgstart,
                       size_t binderoffset, const unsigned char *binderin,
                       unsigned char *binderout, SSL_SESSION *sess, int sign,
                       int external)
@@ -1421,15 +1522,24 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
     EVP_MD_CTX *mctx = NULL;
     unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE];
     unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE];
-    unsigned char tmppsk[EVP_MAX_MD_SIZE];
-    unsigned char *early_secret, *psk;
-    const char resumption_label[] = "res binder";
-    const char external_label[] = "ext binder";
-    const char nonce_label[] = "resumption";
-    const char *label;
-    size_t bindersize, labelsize, psklen, hashsize = EVP_MD_size(md);
+    unsigned char *early_secret;
+    /* ASCII: "res binder", in hex for EBCDIC compatibility */
+    static const unsigned char resumption_label[] = "\x72\x65\x73\x20\x62\x69\x6E\x64\x65\x72";
+    /* ASCII: "ext binder", in hex for EBCDIC compatibility */
+    static const unsigned char external_label[] = "\x65\x78\x74\x20\x62\x69\x6E\x64\x65\x72";
+    const unsigned char *label;
+    size_t bindersize, labelsize, hashsize;
+    int hashsizei = EVP_MD_get_size(md);
     int ret = -1;
     int usepskfored = 0;
+    SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
+
+    /* Ensure cast to size_t is safe */
+    if (!ossl_assert(hashsizei >= 0)) {
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+    hashsize = (size_t)hashsizei;
 
     if (external
             && s->early_data_state == SSL_EARLY_DATA_CONNECTING
@@ -1445,21 +1555,6 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
         labelsize = sizeof(resumption_label) - 1;
     }
 
-    if (external) {
-        psk = sess->master_key;
-        psklen = sess->master_key_length;
-    } else {
-        psk = tmppsk;
-        psklen = hashsize;
-        if (!tls13_hkdf_expand(s, md, sess->master_key,
-                               (const unsigned char *)nonce_label,
-                               sizeof(nonce_label) - 1, sess->ext.tick_nonce,
-                               sess->ext.tick_nonce_len, psk, hashsize)) {
-            /* SSLfatal() already called */
-            goto err;
-        }
-    }
-
     /*
      * Generate the early_secret. On the server side we've selected a PSK to
      * resume with (internal or external) so we always do this. On the client
@@ -1472,7 +1567,9 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
         early_secret = (unsigned char *)s->early_secret;
     else
         early_secret = (unsigned char *)sess->early_secret;
-    if (!tls13_generate_secret(s, md, NULL, psk, psklen, early_secret)) {
+
+    if (!tls13_generate_secret(s, md, NULL, sess->master_key,
+                               sess->master_key_length, early_secret)) {
         /* SSLfatal() already called */
         goto err;
     }
@@ -1485,14 +1582,13 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
     if (mctx == NULL
             || EVP_DigestInit_ex(mctx, md, NULL) <= 0
             || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
-                 ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
     /* Generate the binder key */
-    if (!tls13_hkdf_expand(s, md, early_secret, (unsigned char *)label,
-                           labelsize, hash, hashsize, binderkey, hashsize)) {
+    if (!tls13_hkdf_expand(s, md, early_secret, label, labelsize, hash,
+                           hashsize, binderkey, hashsize, 1)) {
         /* SSLfatal() already called */
         goto err;
     }
@@ -1504,8 +1600,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
     }
 
     if (EVP_DigestInit_ex(mctx, md, NULL) <= 0) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
-                 ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
@@ -1516,12 +1611,13 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
      */
     if (s->hello_retry_request == SSL_HRR_PENDING) {
         size_t hdatalen;
+        long hdatalen_l;
         void *hdata;
 
-        hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
-        if (hdatalen <= 0) {
-            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
-                     SSL_R_BAD_HANDSHAKE_LENGTH);
+        hdatalen = hdatalen_l =
+            BIO_get_mem_data(s->s3.handshake_buffer, &hdata);
+        if (hdatalen_l <= 0) {
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_HANDSHAKE_LENGTH);
             goto err;
         }
 
@@ -1538,32 +1634,29 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
                     || !PACKET_get_length_prefixed_3(&hashprefix, &msg)
                     || !PACKET_forward(&hashprefix, 1)
                     || !PACKET_get_length_prefixed_3(&hashprefix, &msg)) {
-                SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
-                         ERR_R_INTERNAL_ERROR);
+                SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
                 goto err;
             }
             hdatalen -= PACKET_remaining(&hashprefix);
         }
 
         if (EVP_DigestUpdate(mctx, hdata, hdatalen) <= 0) {
-            SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
-                     ERR_R_INTERNAL_ERROR);
+            SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
             goto err;
         }
     }
 
     if (EVP_DigestUpdate(mctx, msgstart, binderoffset) <= 0
             || EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
-                 ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
-    mackey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finishedkey,
-                                          hashsize);
+    mackey = EVP_PKEY_new_raw_private_key_ex(sctx->libctx, "HMAC",
+                                             sctx->propq, finishedkey,
+                                             hashsize);
     if (mackey == NULL) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
-                 ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
@@ -1571,12 +1664,12 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
         binderout = tmpbinder;
 
     bindersize = hashsize;
-    if (EVP_DigestSignInit(mctx, NULL, md, NULL, mackey) <= 0
+    if (EVP_DigestSignInit_ex(mctx, NULL, EVP_MD_get0_name(md), sctx->libctx,
+                              sctx->propq, mackey, NULL) <= 0
             || EVP_DigestSignUpdate(mctx, hash, hashsize) <= 0
             || EVP_DigestSignFinal(mctx, binderout, &bindersize) <= 0
             || bindersize != hashsize) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
-                 ERR_R_INTERNAL_ERROR);
+        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         goto err;
     }
 
@@ -1586,8 +1679,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
         /* HMAC keys can't do EVP_DigestVerify* - use CRYPTO_memcmp instead */
         ret = (CRYPTO_memcmp(binderin, binderout, hashsize) == 0);
         if (!ret)
-            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PSK_DO_BINDER,
-                     SSL_R_BINDER_DOES_NOT_VERIFY);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BINDER_DOES_NOT_VERIFY);
     }
 
  err:
@@ -1599,7 +1691,7 @@ int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
     return ret;
 }
 
-static int final_early_data(SSL *s, unsigned int context, int sent)
+static int final_early_data(SSL_CONNECTION *s, unsigned int context, int sent)
 {
     if (!sent)
         return 1;
@@ -1613,8 +1705,7 @@ static int final_early_data(SSL *s, unsigned int context, int sent)
              * later realised that it shouldn't have done (e.g. inconsistent
              * ALPN)
              */
-            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EARLY_DATA,
-                     SSL_R_BAD_EARLY_DATA);
+            SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_EARLY_DATA);
             return 0;
         }
 
@@ -1623,10 +1714,12 @@ static int final_early_data(SSL *s, unsigned int context, int sent)
 
     if (s->max_early_data == 0
             || !s->hit
-            || s->session->ext.tick_identity != 0
             || s->early_data_state != SSL_EARLY_DATA_ACCEPTING
             || !s->ext.early_data_ok
-            || s->hello_retry_request != SSL_HRR_NONE) {
+            || s->hello_retry_request != SSL_HRR_NONE
+            || (s->allow_early_data_cb != NULL
+                && !s->allow_early_data_cb(SSL_CONNECTION_GET_SSL(s),
+                                         s->allow_early_data_cb_data))) {
         s->ext.early_data = SSL_EARLY_DATA_REJECTED;
     } else {
         s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
@@ -1641,7 +1734,8 @@ static int final_early_data(SSL *s, unsigned int context, int sent)
     return 1;
 }
 
-static int final_maxfragmentlen(SSL *s, unsigned int context, int sent)
+static int final_maxfragmentlen(SSL_CONNECTION *s, unsigned int context,
+                                int sent)
 {
     /*
      * Session resumption on server-side with MFL extension active
@@ -1649,26 +1743,187 @@ static int final_maxfragmentlen(SSL *s, unsigned int context, int sent)
      */
     if (s->server && s->hit && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
             && !sent ) {
-        SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_MAXFRAGMENTLEN,
-                 SSL_R_BAD_EXTENSION);
+        SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_R_BAD_EXTENSION);
         return 0;
     }
 
-    /* Current SSL buffer is lower than requested MFL */
-    if (s->session && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
-            && s->max_send_fragment < GET_MAX_FRAGMENT_LENGTH(s->session))
-        /* trigger a larger buffer reallocation */
-        if (!ssl3_setup_buffers(s)) {
-            /* SSLfatal() already called */
-            return 0;
-        }
+    if (s->session && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)) {
+        s->rlayer.rrlmethod->set_max_frag_len(s->rlayer.rrl,
+                                              GET_MAX_FRAGMENT_LENGTH(s->session));
+        s->rlayer.wrlmethod->set_max_frag_len(s->rlayer.wrl,
+                                              ssl_get_max_send_fragment(s));
+    }
 
     return 1;
 }
 
-static int init_post_handshake_auth(SSL *s, unsigned int context)
+static int init_post_handshake_auth(SSL_CONNECTION *s,
+                                    ossl_unused unsigned int context)
 {
     s->post_handshake_auth = SSL_PHA_NONE;
 
     return 1;
 }
+
+/*
+ * If clients offer "pre_shared_key" without a "psk_key_exchange_modes"
+ * extension, servers MUST abort the handshake.
+ */
+static int final_psk(SSL_CONNECTION *s, unsigned int context, int sent)
+{
+    if (s->server && sent && s->clienthello != NULL
+            && !s->clienthello->pre_proc_exts[TLSEXT_IDX_psk_kex_modes].present) {
+        SSLfatal(s, TLS13_AD_MISSING_EXTENSION,
+                 SSL_R_MISSING_PSK_KEX_MODES_EXTENSION);
+        return 0;
+    }
+
+    return 1;
+}
+
+static int tls_init_compress_certificate(SSL_CONNECTION *sc, unsigned int context)
+{
+    memset(sc->ext.compress_certificate_from_peer, 0,
+           sizeof(sc->ext.compress_certificate_from_peer));
+    return 1;
+}
+
+/* The order these are put into the packet imply a preference order: [brotli, zlib, zstd] */
+static EXT_RETURN tls_construct_compress_certificate(SSL_CONNECTION *sc, WPACKET *pkt,
+                                                     unsigned int context,
+                                                     X509 *x, size_t chainidx)
+{
+#ifndef OPENSSL_NO_COMP_ALG
+    int i;
+
+    if (!ossl_comp_has_alg(0))
+        return EXT_RETURN_NOT_SENT;
+
+    /* Server: Don't attempt to compress a non-X509 (i.e. an RPK) */
+    if (sc->server && sc->ext.server_cert_type != TLSEXT_cert_type_x509) {
+        sc->cert_comp_prefs[0] = TLSEXT_comp_cert_none;
+        return EXT_RETURN_NOT_SENT;
+    }
+
+    /* Client: If we sent a client cert-type extension, don't indicate compression */
+    if (!sc->server && sc->ext.client_cert_type_ctos) {
+        sc->cert_comp_prefs[0] = TLSEXT_comp_cert_none;
+        return EXT_RETURN_NOT_SENT;
+    }
+
+    /* Do not indicate we support receiving compressed certificates */
+    if ((sc->options & SSL_OP_NO_RX_CERTIFICATE_COMPRESSION) != 0)
+        return EXT_RETURN_NOT_SENT;
+
+    if (sc->cert_comp_prefs[0] == TLSEXT_comp_cert_none)
+        return EXT_RETURN_NOT_SENT;
+
+    if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_compress_certificate)
+            || !WPACKET_start_sub_packet_u16(pkt)
+            || !WPACKET_start_sub_packet_u8(pkt))
+        goto err;
+
+    for (i = 0; sc->cert_comp_prefs[i] != TLSEXT_comp_cert_none; i++) {
+        if (!WPACKET_put_bytes_u16(pkt, sc->cert_comp_prefs[i]))
+            goto err;
+    }
+    if (!WPACKET_close(pkt) || !WPACKET_close(pkt))
+        goto err;
+
+    sc->ext.compress_certificate_sent = 1;
+    return EXT_RETURN_SENT;
+ err:
+    SSLfatal(sc, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+    return EXT_RETURN_FAIL;
+#else
+    return EXT_RETURN_NOT_SENT;
+#endif
+}
+
+#ifndef OPENSSL_NO_COMP_ALG
+static int tls_comp_in_pref(SSL_CONNECTION *sc, int alg)
+{
+    int i;
+
+    /* ossl_comp_has_alg() considers 0 as "any" */
+    if (alg == 0)
+        return 0;
+    /* Make sure algorithm is enabled */
+    if (!ossl_comp_has_alg(alg))
+        return 0;
+    /* If no preferences are set, it's ok */
+    if (sc->cert_comp_prefs[0] == TLSEXT_comp_cert_none)
+        return 1;
+    /* Find the algorithm */
+    for (i = 0; i < TLSEXT_comp_cert_limit; i++)
+        if (sc->cert_comp_prefs[i] == alg)
+            return 1;
+    return 0;
+}
+#endif
+
+int tls_parse_compress_certificate(SSL_CONNECTION *sc, PACKET *pkt, unsigned int context,
+                                   X509 *x, size_t chainidx)
+{
+#ifndef OPENSSL_NO_COMP_ALG
+    PACKET supported_comp_algs;
+    unsigned int comp;
+    int already_set[TLSEXT_comp_cert_limit];
+    int j = 0;
+
+    /* If no algorithms are available, ignore the extension */
+    if (!ossl_comp_has_alg(0))
+        return 1;
+
+    /* Don't attempt to compress a non-X509 (i.e. an RPK) */
+    if (sc->server && sc->ext.server_cert_type != TLSEXT_cert_type_x509)
+        return 1;
+    if (!sc->server && sc->ext.client_cert_type != TLSEXT_cert_type_x509)
+        return 1;
+
+    /* Ignore the extension and don't send compressed certificates */
+    if ((sc->options & SSL_OP_NO_TX_CERTIFICATE_COMPRESSION) != 0)
+        return 1;
+
+    if (!PACKET_as_length_prefixed_1(pkt, &supported_comp_algs)
+            || PACKET_remaining(&supported_comp_algs) == 0) {
+        SSLfatal(sc, SSL_AD_DECODE_ERROR, SSL_R_BAD_EXTENSION);
+        return 0;
+    }
+
+    memset(already_set, 0, sizeof(already_set));
+    /*
+     * The preference array has real values, so take a look at each
+     * value coming in, and make sure it's in our preference list
+     * The array is 0 (i.e. "none") terminated
+     * The preference list only contains supported algorithms
+     */
+    while (PACKET_get_net_2(&supported_comp_algs, &comp)) {
+        if (tls_comp_in_pref(sc, comp) && !already_set[comp]) {
+            sc->ext.compress_certificate_from_peer[j++] = comp;
+            already_set[comp] = 1;
+        }
+    }
+#endif
+    return 1;
+}
+
+static int init_server_cert_type(SSL_CONNECTION *sc, unsigned int context)
+{
+    /* Only reset when parsing client hello */
+    if (sc->server) {
+        sc->ext.server_cert_type_ctos = OSSL_CERT_TYPE_CTOS_NONE;
+        sc->ext.server_cert_type = TLSEXT_cert_type_x509;
+    }
+    return 1;
+}
+
+static int init_client_cert_type(SSL_CONNECTION *sc, unsigned int context)
+{
+    /* Only reset when parsing client hello */
+    if (sc->server) {
+        sc->ext.client_cert_type_ctos = OSSL_CERT_TYPE_CTOS_NONE;
+        sc->ext.client_cert_type = TLSEXT_cert_type_x509;
+    }
+    return 1;
+}