| /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 
 |  * All rights reserved. | 
 |  * | 
 |  * This package is an SSL implementation written | 
 |  * by Eric Young (eay@cryptsoft.com). | 
 |  * The implementation was written so as to conform with Netscapes SSL. | 
 |  * | 
 |  * This library is free for commercial and non-commercial use as long as | 
 |  * the following conditions are aheared to.  The following conditions | 
 |  * apply to all code found in this distribution, be it the RC4, RSA, | 
 |  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation | 
 |  * included with this distribution is covered by the same copyright terms | 
 |  * except that the holder is Tim Hudson (tjh@cryptsoft.com). | 
 |  * | 
 |  * Copyright remains Eric Young's, and as such any Copyright notices in | 
 |  * the code are not to be removed. | 
 |  * If this package is used in a product, Eric Young should be given attribution | 
 |  * as the author of the parts of the library used. | 
 |  * This can be in the form of a textual message at program startup or | 
 |  * in documentation (online or textual) provided with the package. | 
 |  * | 
 |  * Redistribution and use in source and binary forms, with or without | 
 |  * modification, are permitted provided that the following conditions | 
 |  * are met: | 
 |  * 1. Redistributions of source code must retain the copyright | 
 |  *    notice, this list of conditions and the following disclaimer. | 
 |  * 2. Redistributions in binary form must reproduce the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer in the | 
 |  *    documentation and/or other materials provided with the distribution. | 
 |  * 3. All advertising materials mentioning features or use of this software | 
 |  *    must display the following acknowledgement: | 
 |  *    "This product includes cryptographic software written by | 
 |  *     Eric Young (eay@cryptsoft.com)" | 
 |  *    The word 'cryptographic' can be left out if the rouines from the library | 
 |  *    being used are not cryptographic related :-). | 
 |  * 4. If you include any Windows specific code (or a derivative thereof) from | 
 |  *    the apps directory (application code) you must include an acknowledgement: | 
 |  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | 
 |  * | 
 |  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND | 
 |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
 |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 
 |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
 |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
 |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
 |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
 |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
 |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
 |  * SUCH DAMAGE. | 
 |  * | 
 |  * The licence and distribution terms for any publically available version or | 
 |  * derivative of this code cannot be changed.  i.e. this code cannot simply be | 
 |  * copied and put under another distribution licence | 
 |  * [including the GNU Public Licence.] | 
 |  */ | 
 | /* ==================================================================== | 
 |  * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved. | 
 |  * | 
 |  * Redistribution and use in source and binary forms, with or without | 
 |  * modification, are permitted provided that the following conditions | 
 |  * are met: | 
 |  * | 
 |  * 1. Redistributions of source code must retain the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer. | 
 |  * | 
 |  * 2. Redistributions in binary form must reproduce the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer in | 
 |  *    the documentation and/or other materials provided with the | 
 |  *    distribution. | 
 |  * | 
 |  * 3. All advertising materials mentioning features or use of this | 
 |  *    software must display the following acknowledgment: | 
 |  *    "This product includes software developed by the OpenSSL Project | 
 |  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | 
 |  * | 
 |  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | 
 |  *    endorse or promote products derived from this software without | 
 |  *    prior written permission. For written permission, please contact | 
 |  *    openssl-core@openssl.org. | 
 |  * | 
 |  * 5. Products derived from this software may not be called "OpenSSL" | 
 |  *    nor may "OpenSSL" appear in their names without prior written | 
 |  *    permission of the OpenSSL Project. | 
 |  * | 
 |  * 6. Redistributions of any form whatsoever must retain the following | 
 |  *    acknowledgment: | 
 |  *    "This product includes software developed by the OpenSSL Project | 
 |  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" | 
 |  * | 
 |  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | 
 |  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
 |  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR | 
 |  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
 |  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 
 |  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 
 |  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
 |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | 
 |  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 
 |  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 
 |  * OF THE POSSIBILITY OF SUCH DAMAGE. | 
 |  * ==================================================================== | 
 |  * | 
 |  * This product includes cryptographic software written by Eric Young | 
 |  * (eay@cryptsoft.com).  This product includes software written by Tim | 
 |  * Hudson (tjh@cryptsoft.com). */ | 
 |  | 
 | #include <openssl/ssl.h> | 
 |  | 
 | #include <assert.h> | 
 | #include <limits.h> | 
 | #include <stdlib.h> | 
 | #include <string.h> | 
 |  | 
 | #include <algorithm> | 
 | #include <utility> | 
 |  | 
 | #include <openssl/aead.h> | 
 | #include <openssl/bytestring.h> | 
 | #include <openssl/chacha.h> | 
 | #include <openssl/curve25519.h> | 
 | #include <openssl/digest.h> | 
 | #include <openssl/err.h> | 
 | #include <openssl/evp.h> | 
 | #include <openssl/hmac.h> | 
 | #include <openssl/hpke.h> | 
 | #include <openssl/mem.h> | 
 | #include <openssl/nid.h> | 
 | #include <openssl/rand.h> | 
 |  | 
 | #include "../crypto/internal.h" | 
 | #include "internal.h" | 
 |  | 
 |  | 
 | BSSL_NAMESPACE_BEGIN | 
 |  | 
 | static bool ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs); | 
 | static bool ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs); | 
 |  | 
 | static int compare_uint16_t(const void *p1, const void *p2) { | 
 |   uint16_t u1 = *((const uint16_t *)p1); | 
 |   uint16_t u2 = *((const uint16_t *)p2); | 
 |   if (u1 < u2) { | 
 |     return -1; | 
 |   } else if (u1 > u2) { | 
 |     return 1; | 
 |   } else { | 
 |     return 0; | 
 |   } | 
 | } | 
 |  | 
 | // Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be | 
 | // more than one extension of the same type in a ClientHello or ServerHello. | 
 | // This function does an initial scan over the extensions block to filter those | 
 | // out. | 
 | static bool tls1_check_duplicate_extensions(const CBS *cbs) { | 
 |   // First pass: count the extensions. | 
 |   size_t num_extensions = 0; | 
 |   CBS extensions = *cbs; | 
 |   while (CBS_len(&extensions) > 0) { | 
 |     uint16_t type; | 
 |     CBS extension; | 
 |  | 
 |     if (!CBS_get_u16(&extensions, &type) || | 
 |         !CBS_get_u16_length_prefixed(&extensions, &extension)) { | 
 |       return false; | 
 |     } | 
 |  | 
 |     num_extensions++; | 
 |   } | 
 |  | 
 |   if (num_extensions == 0) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   Array<uint16_t> extension_types; | 
 |   if (!extension_types.Init(num_extensions)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Second pass: gather the extension types. | 
 |   extensions = *cbs; | 
 |   for (size_t i = 0; i < extension_types.size(); i++) { | 
 |     CBS extension; | 
 |  | 
 |     if (!CBS_get_u16(&extensions, &extension_types[i]) || | 
 |         !CBS_get_u16_length_prefixed(&extensions, &extension)) { | 
 |       // This should not happen. | 
 |       return false; | 
 |     } | 
 |   } | 
 |   assert(CBS_len(&extensions) == 0); | 
 |  | 
 |   // Sort the extensions and make sure there are no duplicates. | 
 |   qsort(extension_types.data(), extension_types.size(), sizeof(uint16_t), | 
 |         compare_uint16_t); | 
 |   for (size_t i = 1; i < num_extensions; i++) { | 
 |     if (extension_types[i - 1] == extension_types[i]) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool is_post_quantum_group(uint16_t id) { | 
 |   switch (id) { | 
 |     case SSL_GROUP_X25519_KYBER768_DRAFT00: | 
 |       return true; | 
 |     default: | 
 |       return false; | 
 |   } | 
 | } | 
 |  | 
 | bool ssl_client_hello_init(const SSL *ssl, SSL_CLIENT_HELLO *out, | 
 |                            Span<const uint8_t> body) { | 
 |   CBS cbs = body; | 
 |   if (!ssl_parse_client_hello_with_trailing_data(ssl, &cbs, out) || | 
 |       CBS_len(&cbs) != 0) { | 
 |     return false; | 
 |   } | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_parse_client_hello_with_trailing_data(const SSL *ssl, CBS *cbs, | 
 |                                                SSL_CLIENT_HELLO *out) { | 
 |   OPENSSL_memset(out, 0, sizeof(*out)); | 
 |   out->ssl = const_cast<SSL *>(ssl); | 
 |  | 
 |   CBS copy = *cbs; | 
 |   CBS random, session_id; | 
 |   if (!CBS_get_u16(cbs, &out->version) || | 
 |       !CBS_get_bytes(cbs, &random, SSL3_RANDOM_SIZE) || | 
 |       !CBS_get_u8_length_prefixed(cbs, &session_id) || | 
 |       CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   out->random = CBS_data(&random); | 
 |   out->random_len = CBS_len(&random); | 
 |   out->session_id = CBS_data(&session_id); | 
 |   out->session_id_len = CBS_len(&session_id); | 
 |  | 
 |   // Skip past DTLS cookie | 
 |   if (SSL_is_dtls(out->ssl)) { | 
 |     CBS cookie; | 
 |     if (!CBS_get_u8_length_prefixed(cbs, &cookie)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   CBS cipher_suites, compression_methods; | 
 |   if (!CBS_get_u16_length_prefixed(cbs, &cipher_suites) || | 
 |       CBS_len(&cipher_suites) < 2 || (CBS_len(&cipher_suites) & 1) != 0 || | 
 |       !CBS_get_u8_length_prefixed(cbs, &compression_methods) || | 
 |       CBS_len(&compression_methods) < 1) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   out->cipher_suites = CBS_data(&cipher_suites); | 
 |   out->cipher_suites_len = CBS_len(&cipher_suites); | 
 |   out->compression_methods = CBS_data(&compression_methods); | 
 |   out->compression_methods_len = CBS_len(&compression_methods); | 
 |  | 
 |   // If the ClientHello ends here then it's valid, but doesn't have any | 
 |   // extensions. | 
 |   if (CBS_len(cbs) == 0) { | 
 |     out->extensions = nullptr; | 
 |     out->extensions_len = 0; | 
 |   } else { | 
 |     // Extract extensions and check it is valid. | 
 |     CBS extensions; | 
 |     if (!CBS_get_u16_length_prefixed(cbs, &extensions) || | 
 |         !tls1_check_duplicate_extensions(&extensions)) { | 
 |       return false; | 
 |     } | 
 |     out->extensions = CBS_data(&extensions); | 
 |     out->extensions_len = CBS_len(&extensions); | 
 |   } | 
 |  | 
 |   out->client_hello = CBS_data(©); | 
 |   out->client_hello_len = CBS_len(©) - CBS_len(cbs); | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello, | 
 |                                     CBS *out, uint16_t extension_type) { | 
 |   CBS extensions; | 
 |   CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len); | 
 |   while (CBS_len(&extensions) != 0) { | 
 |     // Decode the next extension. | 
 |     uint16_t type; | 
 |     CBS extension; | 
 |     if (!CBS_get_u16(&extensions, &type) || | 
 |         !CBS_get_u16_length_prefixed(&extensions, &extension)) { | 
 |       return false; | 
 |     } | 
 |  | 
 |     if (type == extension_type) { | 
 |       *out = extension; | 
 |       return true; | 
 |     } | 
 |   } | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | static const uint16_t kDefaultGroups[] = { | 
 |     SSL_GROUP_X25519, | 
 |     SSL_GROUP_SECP256R1, | 
 |     SSL_GROUP_SECP384R1, | 
 | }; | 
 |  | 
 | Span<const uint16_t> tls1_get_grouplist(const SSL_HANDSHAKE *hs) { | 
 |   if (!hs->config->supported_group_list.empty()) { | 
 |     return hs->config->supported_group_list; | 
 |   } | 
 |   return Span<const uint16_t>(kDefaultGroups); | 
 | } | 
 |  | 
 | bool tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   assert(ssl->server); | 
 |  | 
 |   // Clients are not required to send a supported_groups extension. In this | 
 |   // case, the server is free to pick any group it likes. See RFC 4492, | 
 |   // section 4, paragraph 3. | 
 |   // | 
 |   // However, in the interests of compatibility, we will skip ECDH if the | 
 |   // client didn't send an extension because we can't be sure that they'll | 
 |   // support our favoured group. Thus we do not special-case an emtpy | 
 |   // |peer_supported_group_list|. | 
 |  | 
 |   Span<const uint16_t> groups = tls1_get_grouplist(hs); | 
 |   Span<const uint16_t> pref, supp; | 
 |   if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) { | 
 |     pref = groups; | 
 |     supp = hs->peer_supported_group_list; | 
 |   } else { | 
 |     pref = hs->peer_supported_group_list; | 
 |     supp = groups; | 
 |   } | 
 |  | 
 |   for (uint16_t pref_group : pref) { | 
 |     for (uint16_t supp_group : supp) { | 
 |       if (pref_group == supp_group && | 
 |           // Post-quantum key agreements don't fit in the u8-length-prefixed | 
 |           // ECPoint field in TLS 1.2 and below. | 
 |           (ssl_protocol_version(ssl) >= TLS1_3_VERSION || | 
 |            !is_post_quantum_group(pref_group))) { | 
 |         *out_group_id = pref_group; | 
 |         return true; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | bool tls1_check_group_id(const SSL_HANDSHAKE *hs, uint16_t group_id) { | 
 |   if (is_post_quantum_group(group_id) && | 
 |       ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) { | 
 |     // Post-quantum "groups" require TLS 1.3. | 
 |     return false; | 
 |   } | 
 |  | 
 |   // We internally assume zero is never allocated as a group ID. | 
 |   if (group_id == 0) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   for (uint16_t supported : tls1_get_grouplist(hs)) { | 
 |     if (supported == group_id) { | 
 |       return true; | 
 |     } | 
 |   } | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | // kVerifySignatureAlgorithms is the default list of accepted signature | 
 | // algorithms for verifying. | 
 | static const uint16_t kVerifySignatureAlgorithms[] = { | 
 |     // List our preferred algorithms first. | 
 |     SSL_SIGN_ECDSA_SECP256R1_SHA256, | 
 |     SSL_SIGN_RSA_PSS_RSAE_SHA256, | 
 |     SSL_SIGN_RSA_PKCS1_SHA256, | 
 |  | 
 |     // Larger hashes are acceptable. | 
 |     SSL_SIGN_ECDSA_SECP384R1_SHA384, | 
 |     SSL_SIGN_RSA_PSS_RSAE_SHA384, | 
 |     SSL_SIGN_RSA_PKCS1_SHA384, | 
 |  | 
 |     SSL_SIGN_RSA_PSS_RSAE_SHA512, | 
 |     SSL_SIGN_RSA_PKCS1_SHA512, | 
 |  | 
 |     // For now, SHA-1 is still accepted but least preferable. | 
 |     SSL_SIGN_RSA_PKCS1_SHA1, | 
 | }; | 
 |  | 
 | // kSignSignatureAlgorithms is the default list of supported signature | 
 | // algorithms for signing. | 
 | static const uint16_t kSignSignatureAlgorithms[] = { | 
 |     // List our preferred algorithms first. | 
 |     SSL_SIGN_ED25519, | 
 |     SSL_SIGN_ECDSA_SECP256R1_SHA256, | 
 |     SSL_SIGN_RSA_PSS_RSAE_SHA256, | 
 |     SSL_SIGN_RSA_PKCS1_SHA256, | 
 |  | 
 |     // If needed, sign larger hashes. | 
 |     // | 
 |     // TODO(davidben): Determine which of these may be pruned. | 
 |     SSL_SIGN_ECDSA_SECP384R1_SHA384, | 
 |     SSL_SIGN_RSA_PSS_RSAE_SHA384, | 
 |     SSL_SIGN_RSA_PKCS1_SHA384, | 
 |  | 
 |     SSL_SIGN_ECDSA_SECP521R1_SHA512, | 
 |     SSL_SIGN_RSA_PSS_RSAE_SHA512, | 
 |     SSL_SIGN_RSA_PKCS1_SHA512, | 
 |  | 
 |     // If the peer supports nothing else, sign with SHA-1. | 
 |     SSL_SIGN_ECDSA_SHA1, | 
 |     SSL_SIGN_RSA_PKCS1_SHA1, | 
 | }; | 
 |  | 
 | static Span<const uint16_t> tls12_get_verify_sigalgs(const SSL_HANDSHAKE *hs) { | 
 |   if (hs->config->verify_sigalgs.empty()) { | 
 |     return Span<const uint16_t>(kVerifySignatureAlgorithms); | 
 |   } | 
 |   return hs->config->verify_sigalgs; | 
 | } | 
 |  | 
 | bool tls12_add_verify_sigalgs(const SSL_HANDSHAKE *hs, CBB *out) { | 
 |   for (uint16_t sigalg : tls12_get_verify_sigalgs(hs)) { | 
 |     if (!CBB_add_u16(out, sigalg)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |   return true; | 
 | } | 
 |  | 
 | bool tls12_check_peer_sigalg(const SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                              uint16_t sigalg) { | 
 |   for (uint16_t verify_sigalg : tls12_get_verify_sigalgs(hs)) { | 
 |     if (verify_sigalg == sigalg) { | 
 |       return true; | 
 |     } | 
 |   } | 
 |  | 
 |   OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE); | 
 |   *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |   return false; | 
 | } | 
 |  | 
 | // tls_extension represents a TLS extension that is handled internally. | 
 | // | 
 | // The parse callbacks receive a |CBS| that contains the contents of the | 
 | // extension (i.e. not including the type and length bytes). If an extension is | 
 | // not received then the parse callbacks will be called with a NULL CBS so that | 
 | // they can do any processing needed to handle the absence of an extension. | 
 | // | 
 | // The add callbacks receive a |CBB| to which the extension can be appended but | 
 | // the function is responsible for appending the type and length bytes too. | 
 | // | 
 | // |add_clienthello| may be called multiple times and must not mutate |hs|. It | 
 | // is additionally passed two output |CBB|s. If the extension is the same | 
 | // independent of the value of |type|, the callback may write to | 
 | // |out_compressible| instead of |out|. When serializing the ClientHelloInner, | 
 | // all compressible extensions will be made continguous and replaced with | 
 | // ech_outer_extensions when encrypted. When serializing the ClientHelloOuter | 
 | // or not offering ECH, |out| will be equal to |out_compressible|, so writing to | 
 | // |out_compressible| still works. | 
 | // | 
 | // Note the |parse_serverhello| and |add_serverhello| callbacks refer to the | 
 | // TLS 1.2 ServerHello. In TLS 1.3, these callbacks act on EncryptedExtensions, | 
 | // with ServerHello extensions handled elsewhere in the handshake. | 
 | // | 
 | // All callbacks return true for success and false for error. If a parse | 
 | // function returns zero then a fatal alert with value |*out_alert| will be | 
 | // sent. If |*out_alert| isn't set, then a |decode_error| alert will be sent. | 
 | struct tls_extension { | 
 |   uint16_t value; | 
 |  | 
 |   bool (*add_clienthello)(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                           CBB *out_compressible, ssl_client_hello_type_t type); | 
 |   bool (*parse_serverhello)(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                             CBS *contents); | 
 |  | 
 |   bool (*parse_clienthello)(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                             CBS *contents); | 
 |   bool (*add_serverhello)(SSL_HANDSHAKE *hs, CBB *out); | 
 | }; | 
 |  | 
 | static bool forbid_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                      CBS *contents) { | 
 |   if (contents != NULL) { | 
 |     // Servers MUST NOT send this extension. | 
 |     *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ignore_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                      CBS *contents) { | 
 |   // This extension from the client is handled elsewhere. | 
 |   return true; | 
 | } | 
 |  | 
 | static bool dont_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   return true; | 
 | } | 
 |  | 
 | // Server name indication (SNI). | 
 | // | 
 | // https://tools.ietf.org/html/rfc6066#section-3. | 
 |  | 
 | static bool ext_sni_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                     CBB *out_compressible, | 
 |                                     ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   // If offering ECH, send the public name instead of the configured name. | 
 |   Span<const uint8_t> hostname; | 
 |   if (type == ssl_client_hello_outer) { | 
 |     hostname = hs->selected_ech_config->public_name; | 
 |   } else { | 
 |     if (ssl->hostname == nullptr) { | 
 |       return true; | 
 |     } | 
 |     hostname = | 
 |         MakeConstSpan(reinterpret_cast<const uint8_t *>(ssl->hostname.get()), | 
 |                       strlen(ssl->hostname.get())); | 
 |   } | 
 |  | 
 |   CBB contents, server_name_list, name; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_server_name) || | 
 |       !CBB_add_u16_length_prefixed(out, &contents) || | 
 |       !CBB_add_u16_length_prefixed(&contents, &server_name_list) || | 
 |       !CBB_add_u8(&server_name_list, TLSEXT_NAMETYPE_host_name) || | 
 |       !CBB_add_u16_length_prefixed(&server_name_list, &name) || | 
 |       !CBB_add_bytes(&name, hostname.data(), hostname.size()) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_sni_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                       CBS *contents) { | 
 |   // The server may acknowledge SNI with an empty extension. We check the syntax | 
 |   // but otherwise ignore this signal. | 
 |   return contents == NULL || CBS_len(contents) == 0; | 
 | } | 
 |  | 
 | static bool ext_sni_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                       CBS *contents) { | 
 |   // SNI has already been parsed earlier in the handshake. See |extract_sni|. | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_sni_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   if (hs->ssl->s3->session_reused || | 
 |       !hs->should_ack_sni) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_server_name) || | 
 |       !CBB_add_u16(out, 0 /* length */)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Encrypted ClientHello (ECH) | 
 | // | 
 | // https://tools.ietf.org/html/draft-ietf-tls-esni-13 | 
 |  | 
 | static bool ext_ech_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                     CBB *out_compressible, | 
 |                                     ssl_client_hello_type_t type) { | 
 |   if (type == ssl_client_hello_inner) { | 
 |     if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) || | 
 |         !CBB_add_u16(out, /* length */ 1) || | 
 |         !CBB_add_u8(out, ECH_CLIENT_INNER)) { | 
 |       return false; | 
 |     } | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (hs->ech_client_outer.empty()) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBB ech_body; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) || | 
 |       !CBB_add_u16_length_prefixed(out, &ech_body) || | 
 |       !CBB_add_u8(&ech_body, ECH_CLIENT_OUTER) || | 
 |       !CBB_add_bytes(&ech_body, hs->ech_client_outer.data(), | 
 |                      hs->ech_client_outer.size()) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ech_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                       CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   // The ECH extension may not be sent in TLS 1.2 ServerHello, only TLS 1.3 | 
 |   // EncryptedExtensions. It also may not be sent in response to an inner ECH | 
 |   // extension. | 
 |   if (ssl_protocol_version(ssl) < TLS1_3_VERSION || | 
 |       ssl->s3->ech_status == ssl_ech_accepted) { | 
 |     *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (!ssl_is_valid_ech_config_list(*contents)) { | 
 |     *out_alert = SSL_AD_DECODE_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (ssl->s3->ech_status == ssl_ech_rejected && | 
 |       !hs->ech_retry_configs.CopyFrom(*contents)) { | 
 |     *out_alert = SSL_AD_INTERNAL_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ech_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                       CBS *contents) { | 
 |   if (contents == nullptr) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   uint8_t type; | 
 |   if (!CBS_get_u8(contents, &type)) { | 
 |     return false; | 
 |   } | 
 |   if (type == ECH_CLIENT_OUTER) { | 
 |     // Outer ECH extensions are handled outside the callback. | 
 |     return true; | 
 |   } | 
 |   if (type != ECH_CLIENT_INNER || CBS_len(contents) != 0) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   hs->ech_is_inner = true; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ech_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (ssl_protocol_version(ssl) < TLS1_3_VERSION || | 
 |       ssl->s3->ech_status == ssl_ech_accepted ||  // | 
 |       hs->ech_keys == nullptr) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   // Write the list of retry configs to |out|. Note |SSL_CTX_set1_ech_keys| | 
 |   // ensures |ech_keys| contains at least one retry config. | 
 |   CBB body, retry_configs; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_encrypted_client_hello) || | 
 |       !CBB_add_u16_length_prefixed(out, &body) || | 
 |       !CBB_add_u16_length_prefixed(&body, &retry_configs)) { | 
 |     return false; | 
 |   } | 
 |   for (const auto &config : hs->ech_keys->configs) { | 
 |     if (!config->is_retry_config()) { | 
 |       continue; | 
 |     } | 
 |     if (!CBB_add_bytes(&retry_configs, config->ech_config().raw.data(), | 
 |                        config->ech_config().raw.size())) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |   return CBB_flush(out); | 
 | } | 
 |  | 
 |  | 
 | // Renegotiation indication. | 
 | // | 
 | // https://tools.ietf.org/html/rfc5746 | 
 |  | 
 | static bool ext_ri_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                    CBB *out_compressible, | 
 |                                    ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   // Renegotiation indication is not necessary in TLS 1.3. | 
 |   if (hs->min_version >= TLS1_3_VERSION || | 
 |      type == ssl_client_hello_inner) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   assert(ssl->s3->initial_handshake_complete == | 
 |          (ssl->s3->previous_client_finished_len != 0)); | 
 |  | 
 |   CBB contents, prev_finished; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) || | 
 |       !CBB_add_u16_length_prefixed(out, &contents) || | 
 |       !CBB_add_u8_length_prefixed(&contents, &prev_finished) || | 
 |       !CBB_add_bytes(&prev_finished, ssl->s3->previous_client_finished, | 
 |                      ssl->s3->previous_client_finished_len) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ri_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                      CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents != NULL && ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Servers may not switch between omitting the extension and supporting it. | 
 |   // See RFC 5746, sections 3.5 and 4.2. | 
 |   if (ssl->s3->initial_handshake_complete && | 
 |       (contents != NULL) != ssl->s3->send_connection_binding) { | 
 |     *out_alert = SSL_AD_HANDSHAKE_FAILURE; | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH); | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (contents == NULL) { | 
 |     // Strictly speaking, if we want to avoid an attack we should *always* see | 
 |     // RI even on initial ServerHello because the client doesn't see any | 
 |     // renegotiation during an attack. However this would mean we could not | 
 |     // connect to any server which doesn't support RI. | 
 |     // | 
 |     // OpenSSL has |SSL_OP_LEGACY_SERVER_CONNECT| to control this, but in | 
 |     // practical terms every client sets it so it's just assumed here. | 
 |     return true; | 
 |   } | 
 |  | 
 |   const size_t expected_len = ssl->s3->previous_client_finished_len + | 
 |                               ssl->s3->previous_server_finished_len; | 
 |  | 
 |   // Check for logic errors | 
 |   assert(!expected_len || ssl->s3->previous_client_finished_len); | 
 |   assert(!expected_len || ssl->s3->previous_server_finished_len); | 
 |   assert(ssl->s3->initial_handshake_complete == | 
 |          (ssl->s3->previous_client_finished_len != 0)); | 
 |   assert(ssl->s3->initial_handshake_complete == | 
 |          (ssl->s3->previous_server_finished_len != 0)); | 
 |  | 
 |   // Parse out the extension contents. | 
 |   CBS renegotiated_connection; | 
 |   if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) || | 
 |       CBS_len(contents) != 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR); | 
 |     *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Check that the extension matches. | 
 |   if (CBS_len(&renegotiated_connection) != expected_len) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH); | 
 |     *out_alert = SSL_AD_HANDSHAKE_FAILURE; | 
 |     return false; | 
 |   } | 
 |  | 
 |   const uint8_t *d = CBS_data(&renegotiated_connection); | 
 |   bool ok = CRYPTO_memcmp(d, ssl->s3->previous_client_finished, | 
 |                           ssl->s3->previous_client_finished_len) == 0; | 
 | #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) | 
 |   ok = true; | 
 | #endif | 
 |   if (!ok) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH); | 
 |     *out_alert = SSL_AD_HANDSHAKE_FAILURE; | 
 |     return false; | 
 |   } | 
 |   d += ssl->s3->previous_client_finished_len; | 
 |  | 
 |   ok = CRYPTO_memcmp(d, ssl->s3->previous_server_finished, | 
 |                      ssl->s3->previous_server_finished_len) == 0; | 
 | #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) | 
 |   ok = true; | 
 | #endif | 
 |   if (!ok) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH); | 
 |     *out_alert = SSL_AD_HANDSHAKE_FAILURE; | 
 |     return false; | 
 |   } | 
 |   ssl->s3->send_connection_binding = true; | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ri_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                      CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   // Renegotiation isn't supported as a server so this function should never be | 
 |   // called after the initial handshake. | 
 |   assert(!ssl->s3->initial_handshake_complete); | 
 |  | 
 |   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBS renegotiated_connection; | 
 |   if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) || | 
 |       CBS_len(contents) != 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR); | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Check that the extension matches. We do not support renegotiation as a | 
 |   // server, so this must be empty. | 
 |   if (CBS_len(&renegotiated_connection) != 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH); | 
 |     *out_alert = SSL_AD_HANDSHAKE_FAILURE; | 
 |     return false; | 
 |   } | 
 |  | 
 |   ssl->s3->send_connection_binding = true; | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ri_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   // Renegotiation isn't supported as a server so this function should never be | 
 |   // called after the initial handshake. | 
 |   assert(!ssl->s3->initial_handshake_complete); | 
 |  | 
 |   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) || | 
 |       !CBB_add_u16(out, 1 /* length */) || | 
 |       !CBB_add_u8(out, 0 /* empty renegotiation info */)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Extended Master Secret. | 
 | // | 
 | // https://tools.ietf.org/html/rfc7627 | 
 |  | 
 | static bool ext_ems_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                     CBB *out_compressible, | 
 |                                     ssl_client_hello_type_t type) { | 
 |   // Extended master secret is not necessary in TLS 1.3. | 
 |   if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_extended_master_secret) || | 
 |       !CBB_add_u16(out, 0 /* length */)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ems_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                       CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |  | 
 |   if (contents != NULL) { | 
 |     if (ssl_protocol_version(ssl) >= TLS1_3_VERSION || | 
 |         CBS_len(contents) != 0) { | 
 |       return false; | 
 |     } | 
 |  | 
 |     hs->extended_master_secret = true; | 
 |   } | 
 |  | 
 |   // Whether EMS is negotiated may not change on renegotiation. | 
 |   if (ssl->s3->established_session != nullptr && | 
 |       hs->extended_master_secret != | 
 |           !!ssl->s3->established_session->extended_master_secret) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_EMS_MISMATCH); | 
 |     *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ems_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                       CBS *contents) { | 
 |   if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (CBS_len(contents) != 0) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   hs->extended_master_secret = true; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ems_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   if (!hs->extended_master_secret) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_extended_master_secret) || | 
 |       !CBB_add_u16(out, 0 /* length */)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Session tickets. | 
 | // | 
 | // https://tools.ietf.org/html/rfc5077 | 
 |  | 
 | static bool ext_ticket_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                        CBB *out_compressible, | 
 |                                        ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   // TLS 1.3 uses a different ticket extension. | 
 |   if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner || | 
 |       SSL_get_options(ssl) & SSL_OP_NO_TICKET) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   Span<const uint8_t> ticket; | 
 |  | 
 |   // Renegotiation does not participate in session resumption. However, still | 
 |   // advertise the extension to avoid potentially breaking servers which carry | 
 |   // over the state from the previous handshake, such as OpenSSL servers | 
 |   // without upstream's 3c3f0259238594d77264a78944d409f2127642c4. | 
 |   if (!ssl->s3->initial_handshake_complete && | 
 |       ssl->session != nullptr && | 
 |       !ssl->session->ticket.empty() && | 
 |       // Don't send TLS 1.3 session tickets in the ticket extension. | 
 |       ssl_session_protocol_version(ssl->session.get()) < TLS1_3_VERSION) { | 
 |     ticket = ssl->session->ticket; | 
 |   } | 
 |  | 
 |   CBB ticket_cbb; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) || | 
 |       !CBB_add_u16_length_prefixed(out, &ticket_cbb) || | 
 |       !CBB_add_bytes(&ticket_cbb, ticket.data(), ticket.size()) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ticket_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                          CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // If |SSL_OP_NO_TICKET| is set then no extension will have been sent and | 
 |   // this function should never be called, even if the server tries to send the | 
 |   // extension. | 
 |   assert((SSL_get_options(ssl) & SSL_OP_NO_TICKET) == 0); | 
 |  | 
 |   if (CBS_len(contents) != 0) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   hs->ticket_expected = true; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ticket_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   if (!hs->ticket_expected) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   // If |SSL_OP_NO_TICKET| is set, |ticket_expected| should never be true. | 
 |   assert((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) == 0); | 
 |  | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) || | 
 |       !CBB_add_u16(out, 0 /* length */)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Signature Algorithms. | 
 | // | 
 | // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 | 
 |  | 
 | static bool ext_sigalgs_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                         CBB *out_compressible, | 
 |                                         ssl_client_hello_type_t type) { | 
 |   if (hs->max_version < TLS1_2_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBB contents, sigalgs_cbb; | 
 |   if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_signature_algorithms) || | 
 |       !CBB_add_u16_length_prefixed(out_compressible, &contents) || | 
 |       !CBB_add_u16_length_prefixed(&contents, &sigalgs_cbb) || | 
 |       !tls12_add_verify_sigalgs(hs, &sigalgs_cbb) || | 
 |       !CBB_flush(out_compressible)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_sigalgs_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                           CBS *contents) { | 
 |   hs->peer_sigalgs.Reset(); | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBS supported_signature_algorithms; | 
 |   if (!CBS_get_u16_length_prefixed(contents, &supported_signature_algorithms) || | 
 |       CBS_len(contents) != 0 || | 
 |       !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // OCSP Stapling. | 
 | // | 
 | // https://tools.ietf.org/html/rfc6066#section-8 | 
 |  | 
 | static bool ext_ocsp_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                      CBB *out_compressible, | 
 |                                      ssl_client_hello_type_t type) { | 
 |   if (!hs->config->ocsp_stapling_enabled) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBB contents; | 
 |   if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_status_request) || | 
 |       !CBB_add_u16_length_prefixed(out_compressible, &contents) || | 
 |       !CBB_add_u8(&contents, TLSEXT_STATUSTYPE_ocsp) || | 
 |       !CBB_add_u16(&contents, 0 /* empty responder ID list */) || | 
 |       !CBB_add_u16(&contents, 0 /* empty request extensions */) || | 
 |       !CBB_flush(out_compressible)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ocsp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                        CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   // TLS 1.3 OCSP responses are included in the Certificate extensions. | 
 |   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // OCSP stapling is forbidden on non-certificate ciphers. | 
 |   if (CBS_len(contents) != 0 || | 
 |       !ssl_cipher_uses_certificate_auth(hs->new_cipher)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Note this does not check for resumption in TLS 1.2. Sending | 
 |   // status_request here does not make sense, but OpenSSL does so and the | 
 |   // specification does not say anything. Tolerate it but ignore it. | 
 |  | 
 |   hs->certificate_status_expected = true; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ocsp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                        CBS *contents) { | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   uint8_t status_type; | 
 |   if (!CBS_get_u8(contents, &status_type)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // We cannot decide whether OCSP stapling will occur yet because the correct | 
 |   // SSL_CTX might not have been selected. | 
 |   hs->ocsp_stapling_requested = status_type == TLSEXT_STATUSTYPE_ocsp; | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ocsp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION || | 
 |       !hs->ocsp_stapling_requested || hs->config->cert->ocsp_response == NULL || | 
 |       ssl->s3->session_reused || | 
 |       !ssl_cipher_uses_certificate_auth(hs->new_cipher)) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   hs->certificate_status_expected = true; | 
 |  | 
 |   return CBB_add_u16(out, TLSEXT_TYPE_status_request) && | 
 |          CBB_add_u16(out, 0 /* length */); | 
 | } | 
 |  | 
 |  | 
 | // Next protocol negotiation. | 
 | // | 
 | // https://htmlpreview.github.io/?https://github.com/agl/technotes/blob/master/nextprotoneg.html | 
 |  | 
 | static bool ext_npn_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                     CBB *out_compressible, | 
 |                                     ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   if (ssl->ctx->next_proto_select_cb == NULL || | 
 |       // Do not allow NPN to change on renegotiation. | 
 |       ssl->s3->initial_handshake_complete || | 
 |       // NPN is not defined in DTLS or TLS 1.3. | 
 |       SSL_is_dtls(ssl) || hs->min_version >= TLS1_3_VERSION || | 
 |       type == ssl_client_hello_inner) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_next_proto_neg) || | 
 |       !CBB_add_u16(out, 0 /* length */)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_npn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                       CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // If any of these are false then we should never have sent the NPN | 
 |   // extension in the ClientHello and thus this function should never have been | 
 |   // called. | 
 |   assert(!ssl->s3->initial_handshake_complete); | 
 |   assert(!SSL_is_dtls(ssl)); | 
 |   assert(ssl->ctx->next_proto_select_cb != NULL); | 
 |  | 
 |   if (!ssl->s3->alpn_selected.empty()) { | 
 |     // NPN and ALPN may not be negotiated in the same connection. | 
 |     *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN); | 
 |     return false; | 
 |   } | 
 |  | 
 |   const uint8_t *const orig_contents = CBS_data(contents); | 
 |   const size_t orig_len = CBS_len(contents); | 
 |  | 
 |   while (CBS_len(contents) != 0) { | 
 |     CBS proto; | 
 |     if (!CBS_get_u8_length_prefixed(contents, &proto) || | 
 |         CBS_len(&proto) == 0) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   // |orig_len| fits in |unsigned| because TLS extensions use 16-bit lengths. | 
 |   uint8_t *selected; | 
 |   uint8_t selected_len; | 
 |   if (ssl->ctx->next_proto_select_cb( | 
 |           ssl, &selected, &selected_len, orig_contents, | 
 |           static_cast<unsigned>(orig_len), | 
 |           ssl->ctx->next_proto_select_cb_arg) != SSL_TLSEXT_ERR_OK || | 
 |       !ssl->s3->next_proto_negotiated.CopyFrom( | 
 |           MakeConstSpan(selected, selected_len))) { | 
 |     *out_alert = SSL_AD_INTERNAL_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   hs->next_proto_neg_seen = true; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_npn_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                       CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (contents != NULL && CBS_len(contents) != 0) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (contents == NULL || | 
 |       ssl->s3->initial_handshake_complete || | 
 |       ssl->ctx->next_protos_advertised_cb == NULL || | 
 |       SSL_is_dtls(ssl)) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   hs->next_proto_neg_seen = true; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_npn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   // |next_proto_neg_seen| might have been cleared when an ALPN extension was | 
 |   // parsed. | 
 |   if (!hs->next_proto_neg_seen) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   const uint8_t *npa; | 
 |   unsigned npa_len; | 
 |  | 
 |   if (ssl->ctx->next_protos_advertised_cb( | 
 |           ssl, &npa, &npa_len, ssl->ctx->next_protos_advertised_cb_arg) != | 
 |       SSL_TLSEXT_ERR_OK) { | 
 |     hs->next_proto_neg_seen = false; | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBB contents; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_next_proto_neg) || | 
 |       !CBB_add_u16_length_prefixed(out, &contents) || | 
 |       !CBB_add_bytes(&contents, npa, npa_len) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Signed certificate timestamps. | 
 | // | 
 | // https://tools.ietf.org/html/rfc6962#section-3.3.1 | 
 |  | 
 | static bool ext_sct_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                     CBB *out_compressible, | 
 |                                     ssl_client_hello_type_t type) { | 
 |   if (!hs->config->signed_cert_timestamps_enabled) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_certificate_timestamp) || | 
 |       !CBB_add_u16(out_compressible, 0 /* length */)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_sct_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                       CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   // TLS 1.3 SCTs are included in the Certificate extensions. | 
 |   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     *out_alert = SSL_AD_DECODE_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   // If this is false then we should never have sent the SCT extension in the | 
 |   // ClientHello and thus this function should never have been called. | 
 |   assert(hs->config->signed_cert_timestamps_enabled); | 
 |  | 
 |   if (!ssl_is_sct_list_valid(contents)) { | 
 |     *out_alert = SSL_AD_DECODE_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Session resumption uses the original session information. The extension | 
 |   // should not be sent on resumption, but RFC 6962 did not make it a | 
 |   // requirement, so tolerate this. | 
 |   // | 
 |   // TODO(davidben): Enforce this anyway. | 
 |   if (!ssl->s3->session_reused) { | 
 |     hs->new_session->signed_cert_timestamp_list.reset( | 
 |         CRYPTO_BUFFER_new_from_CBS(contents, ssl->ctx->pool)); | 
 |     if (hs->new_session->signed_cert_timestamp_list == nullptr) { | 
 |       *out_alert = SSL_AD_INTERNAL_ERROR; | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_sct_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                       CBS *contents) { | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (CBS_len(contents) != 0) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   hs->scts_requested = true; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_sct_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   // The extension shouldn't be sent when resuming sessions. | 
 |   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION || ssl->s3->session_reused || | 
 |       hs->config->cert->signed_cert_timestamp_list == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBB contents; | 
 |   return CBB_add_u16(out, TLSEXT_TYPE_certificate_timestamp) && | 
 |          CBB_add_u16_length_prefixed(out, &contents) && | 
 |          CBB_add_bytes( | 
 |              &contents, | 
 |              CRYPTO_BUFFER_data( | 
 |                  hs->config->cert->signed_cert_timestamp_list.get()), | 
 |              CRYPTO_BUFFER_len( | 
 |                  hs->config->cert->signed_cert_timestamp_list.get())) && | 
 |          CBB_flush(out); | 
 | } | 
 |  | 
 |  | 
 | // Application-level Protocol Negotiation. | 
 | // | 
 | // https://tools.ietf.org/html/rfc7301 | 
 |  | 
 | static bool ext_alpn_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                      CBB *out_compressible, | 
 |                                      ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   if (hs->config->alpn_client_proto_list.empty() && ssl->quic_method) { | 
 |     // ALPN MUST be used with QUIC. | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL); | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (hs->config->alpn_client_proto_list.empty() || | 
 |       ssl->s3->initial_handshake_complete) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBB contents, proto_list; | 
 |   if (!CBB_add_u16(out_compressible, | 
 |                    TLSEXT_TYPE_application_layer_protocol_negotiation) || | 
 |       !CBB_add_u16_length_prefixed(out_compressible, &contents) || | 
 |       !CBB_add_u16_length_prefixed(&contents, &proto_list) || | 
 |       !CBB_add_bytes(&proto_list, hs->config->alpn_client_proto_list.data(), | 
 |                      hs->config->alpn_client_proto_list.size()) || | 
 |       !CBB_flush(out_compressible)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_alpn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                        CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents == NULL) { | 
 |     if (ssl->quic_method) { | 
 |       // ALPN is required when QUIC is used. | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL); | 
 |       *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL; | 
 |       return false; | 
 |     } | 
 |     return true; | 
 |   } | 
 |  | 
 |   assert(!ssl->s3->initial_handshake_complete); | 
 |   assert(!hs->config->alpn_client_proto_list.empty()); | 
 |  | 
 |   if (hs->next_proto_neg_seen) { | 
 |     // NPN and ALPN may not be negotiated in the same connection. | 
 |     *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN); | 
 |     return false; | 
 |   } | 
 |  | 
 |   // The extension data consists of a ProtocolNameList which must have | 
 |   // exactly one ProtocolName. Each of these is length-prefixed. | 
 |   CBS protocol_name_list, protocol_name; | 
 |   if (!CBS_get_u16_length_prefixed(contents, &protocol_name_list) || | 
 |       CBS_len(contents) != 0 || | 
 |       !CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) || | 
 |       // Empty protocol names are forbidden. | 
 |       CBS_len(&protocol_name) == 0 || | 
 |       CBS_len(&protocol_name_list) != 0) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (!ssl_is_alpn_protocol_allowed(hs, protocol_name)) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL); | 
 |     *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (!ssl->s3->alpn_selected.CopyFrom(protocol_name)) { | 
 |     *out_alert = SSL_AD_INTERNAL_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_is_valid_alpn_list(Span<const uint8_t> in) { | 
 |   CBS protocol_name_list = in; | 
 |   if (CBS_len(&protocol_name_list) == 0) { | 
 |     return false; | 
 |   } | 
 |   while (CBS_len(&protocol_name_list) > 0) { | 
 |     CBS protocol_name; | 
 |     if (!CBS_get_u8_length_prefixed(&protocol_name_list, &protocol_name) || | 
 |         // Empty protocol names are forbidden. | 
 |         CBS_len(&protocol_name) == 0) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_is_alpn_protocol_allowed(const SSL_HANDSHAKE *hs, | 
 |                                   Span<const uint8_t> protocol) { | 
 |   if (hs->config->alpn_client_proto_list.empty()) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (hs->ssl->ctx->allow_unknown_alpn_protos) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   // Check that the protocol name is one of the ones we advertised. | 
 |   CBS client_protocol_name_list = | 
 |           MakeConstSpan(hs->config->alpn_client_proto_list), | 
 |       client_protocol_name; | 
 |   while (CBS_len(&client_protocol_name_list) > 0) { | 
 |     if (!CBS_get_u8_length_prefixed(&client_protocol_name_list, | 
 |                                     &client_protocol_name)) { | 
 |       return false; | 
 |     } | 
 |  | 
 |     if (client_protocol_name == protocol) { | 
 |       return true; | 
 |     } | 
 |   } | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | bool ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                         const SSL_CLIENT_HELLO *client_hello) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   CBS contents; | 
 |   if (ssl->ctx->alpn_select_cb == NULL || | 
 |       !ssl_client_hello_get_extension( | 
 |           client_hello, &contents, | 
 |           TLSEXT_TYPE_application_layer_protocol_negotiation)) { | 
 |     if (ssl->quic_method) { | 
 |       // ALPN is required when QUIC is used. | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL); | 
 |       *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL; | 
 |       return false; | 
 |     } | 
 |     // Ignore ALPN if not configured or no extension was supplied. | 
 |     return true; | 
 |   } | 
 |  | 
 |   // ALPN takes precedence over NPN. | 
 |   hs->next_proto_neg_seen = false; | 
 |  | 
 |   CBS protocol_name_list; | 
 |   if (!CBS_get_u16_length_prefixed(&contents, &protocol_name_list) || | 
 |       CBS_len(&contents) != 0 || | 
 |       !ssl_is_valid_alpn_list(protocol_name_list)) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT); | 
 |     *out_alert = SSL_AD_DECODE_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   // |protocol_name_list| fits in |unsigned| because TLS extensions use 16-bit | 
 |   // lengths. | 
 |   const uint8_t *selected; | 
 |   uint8_t selected_len; | 
 |   int ret = ssl->ctx->alpn_select_cb( | 
 |       ssl, &selected, &selected_len, CBS_data(&protocol_name_list), | 
 |       static_cast<unsigned>(CBS_len(&protocol_name_list)), | 
 |       ssl->ctx->alpn_select_cb_arg); | 
 |   // ALPN is required when QUIC is used. | 
 |   if (ssl->quic_method && | 
 |       (ret == SSL_TLSEXT_ERR_NOACK || ret == SSL_TLSEXT_ERR_ALERT_WARNING)) { | 
 |     ret = SSL_TLSEXT_ERR_ALERT_FATAL; | 
 |   } | 
 |   switch (ret) { | 
 |     case SSL_TLSEXT_ERR_OK: | 
 |       if (selected_len == 0) { | 
 |         OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL); | 
 |         *out_alert = SSL_AD_INTERNAL_ERROR; | 
 |         return false; | 
 |       } | 
 |       if (!ssl->s3->alpn_selected.CopyFrom( | 
 |               MakeConstSpan(selected, selected_len))) { | 
 |         *out_alert = SSL_AD_INTERNAL_ERROR; | 
 |         return false; | 
 |       } | 
 |       break; | 
 |     case SSL_TLSEXT_ERR_NOACK: | 
 |     case SSL_TLSEXT_ERR_ALERT_WARNING: | 
 |       break; | 
 |     case SSL_TLSEXT_ERR_ALERT_FATAL: | 
 |       *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL; | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_NO_APPLICATION_PROTOCOL); | 
 |       return false; | 
 |     default: | 
 |       // Invalid return value. | 
 |       *out_alert = SSL_AD_INTERNAL_ERROR; | 
 |       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | 
 |       return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_alpn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (ssl->s3->alpn_selected.empty()) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBB contents, proto_list, proto; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_application_layer_protocol_negotiation) || | 
 |       !CBB_add_u16_length_prefixed(out, &contents) || | 
 |       !CBB_add_u16_length_prefixed(&contents, &proto_list) || | 
 |       !CBB_add_u8_length_prefixed(&proto_list, &proto) || | 
 |       !CBB_add_bytes(&proto, ssl->s3->alpn_selected.data(), | 
 |                      ssl->s3->alpn_selected.size()) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Channel ID. | 
 | // | 
 | // https://tools.ietf.org/html/draft-balfanz-tls-channelid-01 | 
 |  | 
 | static bool ext_channel_id_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                            CBB *out_compressible, | 
 |                                            ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   if (!hs->config->channel_id_private || SSL_is_dtls(ssl) || | 
 |       // Don't offer Channel ID in ClientHelloOuter. ClientHelloOuter handshakes | 
 |       // are not authenticated for the name that can learn the Channel ID. | 
 |       // | 
 |       // We could alternatively offer the extension but sign with a random key. | 
 |       // For other extensions, we try to align |ssl_client_hello_outer| and | 
 |       // |ssl_client_hello_unencrypted|, to improve the effectiveness of ECH | 
 |       // GREASE. However, Channel ID is deprecated and unlikely to be used with | 
 |       // ECH, so do the simplest thing. | 
 |       type == ssl_client_hello_outer) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_channel_id) || | 
 |       !CBB_add_u16(out, 0 /* length */)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_channel_id_parse_serverhello(SSL_HANDSHAKE *hs, | 
 |                                              uint8_t *out_alert, | 
 |                                              CBS *contents) { | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   assert(!SSL_is_dtls(hs->ssl)); | 
 |   assert(hs->config->channel_id_private); | 
 |  | 
 |   if (CBS_len(contents) != 0) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   hs->channel_id_negotiated = true; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_channel_id_parse_clienthello(SSL_HANDSHAKE *hs, | 
 |                                              uint8_t *out_alert, | 
 |                                              CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents == NULL || !hs->config->channel_id_enabled || SSL_is_dtls(ssl)) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (CBS_len(contents) != 0) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   hs->channel_id_negotiated = true; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_channel_id_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   if (!hs->channel_id_negotiated) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_channel_id) || | 
 |       !CBB_add_u16(out, 0 /* length */)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Secure Real-time Transport Protocol (SRTP) extension. | 
 | // | 
 | // https://tools.ietf.org/html/rfc5764 | 
 |  | 
 | static bool ext_srtp_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                      CBB *out_compressible, | 
 |                                      ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   const STACK_OF(SRTP_PROTECTION_PROFILE) *profiles = | 
 |       SSL_get_srtp_profiles(ssl); | 
 |   if (profiles == NULL || | 
 |       sk_SRTP_PROTECTION_PROFILE_num(profiles) == 0 || | 
 |       !SSL_is_dtls(ssl)) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBB contents, profile_ids; | 
 |   if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_srtp) || | 
 |       !CBB_add_u16_length_prefixed(out_compressible, &contents) || | 
 |       !CBB_add_u16_length_prefixed(&contents, &profile_ids)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   for (const SRTP_PROTECTION_PROFILE *profile : profiles) { | 
 |     if (!CBB_add_u16(&profile_ids, profile->id)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   if (!CBB_add_u8(&contents, 0 /* empty use_mki value */) || | 
 |       !CBB_flush(out_compressible)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_srtp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                        CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   // The extension consists of a u16-prefixed profile ID list containing a | 
 |   // single uint16_t profile ID, then followed by a u8-prefixed srtp_mki field. | 
 |   // | 
 |   // See https://tools.ietf.org/html/rfc5764#section-4.1.1 | 
 |   assert(SSL_is_dtls(ssl)); | 
 |   CBS profile_ids, srtp_mki; | 
 |   uint16_t profile_id; | 
 |   if (!CBS_get_u16_length_prefixed(contents, &profile_ids) || | 
 |       !CBS_get_u16(&profile_ids, &profile_id) || | 
 |       CBS_len(&profile_ids) != 0 || | 
 |       !CBS_get_u8_length_prefixed(contents, &srtp_mki) || | 
 |       CBS_len(contents) != 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (CBS_len(&srtp_mki) != 0) { | 
 |     // Must be no MKI, since we never offer one. | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_MKI_VALUE); | 
 |     *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Check to see if the server gave us something we support and offered. | 
 |   for (const SRTP_PROTECTION_PROFILE *profile : SSL_get_srtp_profiles(ssl)) { | 
 |     if (profile->id == profile_id) { | 
 |       ssl->s3->srtp_profile = profile; | 
 |       return true; | 
 |     } | 
 |   } | 
 |  | 
 |   OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); | 
 |   *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |   return false; | 
 | } | 
 |  | 
 | static bool ext_srtp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                        CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   // DTLS-SRTP is only defined for DTLS. | 
 |   if (contents == NULL || !SSL_is_dtls(ssl)) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBS profile_ids, srtp_mki; | 
 |   if (!CBS_get_u16_length_prefixed(contents, &profile_ids) || | 
 |       CBS_len(&profile_ids) < 2 || | 
 |       !CBS_get_u8_length_prefixed(contents, &srtp_mki) || | 
 |       CBS_len(contents) != 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST); | 
 |     return false; | 
 |   } | 
 |   // Discard the MKI value for now. | 
 |  | 
 |   const STACK_OF(SRTP_PROTECTION_PROFILE) *server_profiles = | 
 |       SSL_get_srtp_profiles(ssl); | 
 |  | 
 |   // Pick the server's most preferred profile. | 
 |   for (const SRTP_PROTECTION_PROFILE *server_profile : server_profiles) { | 
 |     CBS profile_ids_tmp; | 
 |     CBS_init(&profile_ids_tmp, CBS_data(&profile_ids), CBS_len(&profile_ids)); | 
 |  | 
 |     while (CBS_len(&profile_ids_tmp) > 0) { | 
 |       uint16_t profile_id; | 
 |       if (!CBS_get_u16(&profile_ids_tmp, &profile_id)) { | 
 |         return false; | 
 |       } | 
 |  | 
 |       if (server_profile->id == profile_id) { | 
 |         ssl->s3->srtp_profile = server_profile; | 
 |         return true; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_srtp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (ssl->s3->srtp_profile == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   assert(SSL_is_dtls(ssl)); | 
 |   CBB contents, profile_ids; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_srtp) || | 
 |       !CBB_add_u16_length_prefixed(out, &contents) || | 
 |       !CBB_add_u16_length_prefixed(&contents, &profile_ids) || | 
 |       !CBB_add_u16(&profile_ids, ssl->s3->srtp_profile->id) || | 
 |       !CBB_add_u8(&contents, 0 /* empty MKI */) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // EC point formats. | 
 | // | 
 | // https://tools.ietf.org/html/rfc4492#section-5.1.2 | 
 |  | 
 | static bool ext_ec_point_add_extension(const SSL_HANDSHAKE *hs, CBB *out) { | 
 |   CBB contents, formats; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_ec_point_formats) || | 
 |       !CBB_add_u16_length_prefixed(out, &contents) || | 
 |       !CBB_add_u8_length_prefixed(&contents, &formats) || | 
 |       !CBB_add_u8(&formats, TLSEXT_ECPOINTFORMAT_uncompressed) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ec_point_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                          CBB *out_compressible, | 
 |                                          ssl_client_hello_type_t type) { | 
 |   // The point format extension is unnecessary in TLS 1.3. | 
 |   if (hs->min_version >= TLS1_3_VERSION || type == ssl_client_hello_inner) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   return ext_ec_point_add_extension(hs, out); | 
 | } | 
 |  | 
 | static bool ext_ec_point_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                            CBS *contents) { | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   CBS ec_point_format_list; | 
 |   if (!CBS_get_u8_length_prefixed(contents, &ec_point_format_list) || | 
 |       CBS_len(contents) != 0) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Per RFC 4492, section 5.1.2, implementations MUST support the uncompressed | 
 |   // point format. | 
 |   if (OPENSSL_memchr(CBS_data(&ec_point_format_list), | 
 |                      TLSEXT_ECPOINTFORMAT_uncompressed, | 
 |                      CBS_len(&ec_point_format_list)) == NULL) { | 
 |     *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_ec_point_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                                           CBS *contents) { | 
 |   if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   return ext_ec_point_parse_serverhello(hs, out_alert, contents); | 
 | } | 
 |  | 
 | static bool ext_ec_point_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   const uint32_t alg_k = hs->new_cipher->algorithm_mkey; | 
 |   const uint32_t alg_a = hs->new_cipher->algorithm_auth; | 
 |   const bool using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA); | 
 |  | 
 |   if (!using_ecc) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   return ext_ec_point_add_extension(hs, out); | 
 | } | 
 |  | 
 |  | 
 | // Pre Shared Key | 
 | // | 
 | // https://tools.ietf.org/html/rfc8446#section-4.2.11 | 
 |  | 
 | static bool should_offer_psk(const SSL_HANDSHAKE *hs, | 
 |                              ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   if (hs->max_version < TLS1_3_VERSION || ssl->session == nullptr || | 
 |       ssl_session_protocol_version(ssl->session.get()) < TLS1_3_VERSION || | 
 |       // TODO(https://crbug.com/boringssl/275): Should we synthesize a | 
 |       // placeholder PSK, at least when we offer early data? Otherwise | 
 |       // ClientHelloOuter will contain an early_data extension without a | 
 |       // pre_shared_key extension and potentially break the recovery flow. | 
 |       type == ssl_client_hello_outer) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Per RFC 8446 section 4.1.4, skip offering the session if the selected | 
 |   // cipher in HelloRetryRequest does not match. This avoids performing the | 
 |   // transcript hash transformation for multiple hashes. | 
 |   if (ssl->s3->used_hello_retry_request && | 
 |       ssl->session->cipher->algorithm_prf != hs->new_cipher->algorithm_prf) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static size_t ext_pre_shared_key_clienthello_length( | 
 |     const SSL_HANDSHAKE *hs, ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   if (!should_offer_psk(hs, type)) { | 
 |     return 0; | 
 |   } | 
 |  | 
 |   size_t binder_len = EVP_MD_size(ssl_session_get_digest(ssl->session.get())); | 
 |   return 15 + ssl->session->ticket.size() + binder_len; | 
 | } | 
 |  | 
 | static bool ext_pre_shared_key_add_clienthello(const SSL_HANDSHAKE *hs, | 
 |                                                CBB *out, bool *out_needs_binder, | 
 |                                                ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   *out_needs_binder = false; | 
 |   if (!should_offer_psk(hs, type)) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   struct OPENSSL_timeval now; | 
 |   ssl_get_current_time(ssl, &now); | 
 |   uint32_t ticket_age = 1000 * (now.tv_sec - ssl->session->time); | 
 |   uint32_t obfuscated_ticket_age = ticket_age + ssl->session->ticket_age_add; | 
 |  | 
 |   // Fill in a placeholder zero binder of the appropriate length. It will be | 
 |   // computed and filled in later after length prefixes are computed. | 
 |   size_t binder_len = EVP_MD_size(ssl_session_get_digest(ssl->session.get())); | 
 |  | 
 |   CBB contents, identity, ticket, binders, binder; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_pre_shared_key) || | 
 |       !CBB_add_u16_length_prefixed(out, &contents) || | 
 |       !CBB_add_u16_length_prefixed(&contents, &identity) || | 
 |       !CBB_add_u16_length_prefixed(&identity, &ticket) || | 
 |       !CBB_add_bytes(&ticket, ssl->session->ticket.data(), | 
 |                      ssl->session->ticket.size()) || | 
 |       !CBB_add_u32(&identity, obfuscated_ticket_age) || | 
 |       !CBB_add_u16_length_prefixed(&contents, &binders) || | 
 |       !CBB_add_u8_length_prefixed(&binders, &binder) || | 
 |       !CBB_add_zeros(&binder, binder_len)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   *out_needs_binder = true; | 
 |   return CBB_flush(out); | 
 | } | 
 |  | 
 | bool ssl_ext_pre_shared_key_parse_serverhello(SSL_HANDSHAKE *hs, | 
 |                                               uint8_t *out_alert, | 
 |                                               CBS *contents) { | 
 |   uint16_t psk_id; | 
 |   if (!CBS_get_u16(contents, &psk_id) || | 
 |       CBS_len(contents) != 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | 
 |     *out_alert = SSL_AD_DECODE_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   // We only advertise one PSK identity, so the only legal index is zero. | 
 |   if (psk_id != 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND); | 
 |     *out_alert = SSL_AD_UNKNOWN_PSK_IDENTITY; | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_ext_pre_shared_key_parse_clienthello( | 
 |     SSL_HANDSHAKE *hs, CBS *out_ticket, CBS *out_binders, | 
 |     uint32_t *out_obfuscated_ticket_age, uint8_t *out_alert, | 
 |     const SSL_CLIENT_HELLO *client_hello, CBS *contents) { | 
 |   // Verify that the pre_shared_key extension is the last extension in | 
 |   // ClientHello. | 
 |   if (CBS_data(contents) + CBS_len(contents) != | 
 |       client_hello->extensions + client_hello->extensions_len) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST); | 
 |     *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |     return false; | 
 |   } | 
 |  | 
 |   // We only process the first PSK identity since we don't support pure PSK. | 
 |   CBS identities, binders; | 
 |   if (!CBS_get_u16_length_prefixed(contents, &identities) || | 
 |       !CBS_get_u16_length_prefixed(&identities, out_ticket) || | 
 |       !CBS_get_u32(&identities, out_obfuscated_ticket_age) || | 
 |       !CBS_get_u16_length_prefixed(contents, &binders) || | 
 |       CBS_len(&binders) == 0 || | 
 |       CBS_len(contents) != 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | 
 |     *out_alert = SSL_AD_DECODE_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   *out_binders = binders; | 
 |  | 
 |   // Check the syntax of the remaining identities, but do not process them. | 
 |   size_t num_identities = 1; | 
 |   while (CBS_len(&identities) != 0) { | 
 |     CBS unused_ticket; | 
 |     uint32_t unused_obfuscated_ticket_age; | 
 |     if (!CBS_get_u16_length_prefixed(&identities, &unused_ticket) || | 
 |         !CBS_get_u32(&identities, &unused_obfuscated_ticket_age)) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | 
 |       *out_alert = SSL_AD_DECODE_ERROR; | 
 |       return false; | 
 |     } | 
 |  | 
 |     num_identities++; | 
 |   } | 
 |  | 
 |   // Check the syntax of the binders. The value will be checked later if | 
 |   // resuming. | 
 |   size_t num_binders = 0; | 
 |   while (CBS_len(&binders) != 0) { | 
 |     CBS binder; | 
 |     if (!CBS_get_u8_length_prefixed(&binders, &binder)) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | 
 |       *out_alert = SSL_AD_DECODE_ERROR; | 
 |       return false; | 
 |     } | 
 |  | 
 |     num_binders++; | 
 |   } | 
 |  | 
 |   if (num_identities != num_binders) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_BINDER_COUNT_MISMATCH); | 
 |     *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_ext_pre_shared_key_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   if (!hs->ssl->s3->session_reused) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBB contents; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_pre_shared_key) || | 
 |       !CBB_add_u16_length_prefixed(out, &contents) || | 
 |       // We only consider the first identity for resumption | 
 |       !CBB_add_u16(&contents, 0) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Pre-Shared Key Exchange Modes | 
 | // | 
 | // https://tools.ietf.org/html/rfc8446#section-4.2.9 | 
 |  | 
 | static bool ext_psk_key_exchange_modes_add_clienthello( | 
 |     const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible, | 
 |     ssl_client_hello_type_t type) { | 
 |   if (hs->max_version < TLS1_3_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBB contents, ke_modes; | 
 |   if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_psk_key_exchange_modes) || | 
 |       !CBB_add_u16_length_prefixed(out_compressible, &contents) || | 
 |       !CBB_add_u8_length_prefixed(&contents, &ke_modes) || | 
 |       !CBB_add_u8(&ke_modes, SSL_PSK_DHE_KE)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return CBB_flush(out_compressible); | 
 | } | 
 |  | 
 | static bool ext_psk_key_exchange_modes_parse_clienthello(SSL_HANDSHAKE *hs, | 
 |                                                          uint8_t *out_alert, | 
 |                                                          CBS *contents) { | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBS ke_modes; | 
 |   if (!CBS_get_u8_length_prefixed(contents, &ke_modes) || | 
 |       CBS_len(&ke_modes) == 0 || | 
 |       CBS_len(contents) != 0) { | 
 |     *out_alert = SSL_AD_DECODE_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   // We only support tickets with PSK_DHE_KE. | 
 |   hs->accept_psk_mode = OPENSSL_memchr(CBS_data(&ke_modes), SSL_PSK_DHE_KE, | 
 |                                        CBS_len(&ke_modes)) != NULL; | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Early Data Indication | 
 | // | 
 | // https://tools.ietf.org/html/rfc8446#section-4.2.10 | 
 |  | 
 | static bool ext_early_data_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                            CBB *out_compressible, | 
 |                                            ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   // The second ClientHello never offers early data, and we must have already | 
 |   // filled in |early_data_reason| by this point. | 
 |   if (ssl->s3->used_hello_retry_request) { | 
 |     assert(ssl->s3->early_data_reason != ssl_early_data_unknown); | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (!hs->early_data_offered) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   // If offering ECH, the extension only applies to ClientHelloInner, but we | 
 |   // send the extension in both ClientHellos. This ensures that, if the server | 
 |   // handshakes with ClientHelloOuter, it can skip past early data. See | 
 |   // draft-ietf-tls-esni-13, section 6.1. | 
 |   if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_early_data) || | 
 |       !CBB_add_u16(out_compressible, 0) || | 
 |       !CBB_flush(out_compressible)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_early_data_parse_serverhello(SSL_HANDSHAKE *hs, | 
 |                                              uint8_t *out_alert, | 
 |                                              CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents == NULL) { | 
 |     if (hs->early_data_offered && !ssl->s3->used_hello_retry_request) { | 
 |       ssl->s3->early_data_reason = ssl->s3->session_reused | 
 |                                        ? ssl_early_data_peer_declined | 
 |                                        : ssl_early_data_session_not_resumed; | 
 |     } else { | 
 |       // We already filled in |early_data_reason| when declining to offer 0-RTT | 
 |       // or handling the implicit HelloRetryRequest reject. | 
 |       assert(ssl->s3->early_data_reason != ssl_early_data_unknown); | 
 |     } | 
 |     return true; | 
 |   } | 
 |  | 
 |   // If we received an HRR, the second ClientHello never offers early data, so | 
 |   // the extensions logic will automatically reject early data extensions as | 
 |   // unsolicited. This covered by the ServerAcceptsEarlyDataOnHRR test. | 
 |   assert(!ssl->s3->used_hello_retry_request); | 
 |  | 
 |   if (CBS_len(contents) != 0) { | 
 |     *out_alert = SSL_AD_DECODE_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (!ssl->s3->session_reused) { | 
 |     *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); | 
 |     return false; | 
 |   } | 
 |  | 
 |   ssl->s3->early_data_reason = ssl_early_data_accepted; | 
 |   ssl->s3->early_data_accepted = true; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_early_data_parse_clienthello(SSL_HANDSHAKE *hs, | 
 |                                              uint8_t *out_alert, CBS *contents) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents == NULL || | 
 |       ssl_protocol_version(ssl) < TLS1_3_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (CBS_len(contents) != 0) { | 
 |     *out_alert = SSL_AD_DECODE_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   hs->early_data_offered = true; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_early_data_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   if (!hs->ssl->s3->early_data_accepted) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_early_data) || | 
 |       !CBB_add_u16(out, 0) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Key Share | 
 | // | 
 | // https://tools.ietf.org/html/rfc8446#section-4.2.8 | 
 |  | 
 | bool ssl_setup_key_shares(SSL_HANDSHAKE *hs, uint16_t override_group_id) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   hs->key_shares[0].reset(); | 
 |   hs->key_shares[1].reset(); | 
 |   hs->key_share_bytes.Reset(); | 
 |  | 
 |   if (hs->max_version < TLS1_3_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   bssl::ScopedCBB cbb; | 
 |   if (!CBB_init(cbb.get(), 64)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (override_group_id == 0 && ssl->ctx->grease_enabled) { | 
 |     // Add a fake group. See RFC 8701. | 
 |     if (!CBB_add_u16(cbb.get(), ssl_get_grease_value(hs, ssl_grease_group)) || | 
 |         !CBB_add_u16(cbb.get(), 1 /* length */) || | 
 |         !CBB_add_u8(cbb.get(), 0 /* one byte key share */)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   uint16_t group_id = override_group_id; | 
 |   uint16_t second_group_id = 0; | 
 |   if (override_group_id == 0) { | 
 |     // Predict the most preferred group. | 
 |     Span<const uint16_t> groups = tls1_get_grouplist(hs); | 
 |     if (groups.empty()) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_NO_GROUPS_SPECIFIED); | 
 |       return false; | 
 |     } | 
 |  | 
 |     group_id = groups[0]; | 
 |  | 
 |     // We'll try to include one post-quantum and one classical initial key | 
 |     // share. | 
 |     for (size_t i = 1; i < groups.size() && second_group_id == 0; i++) { | 
 |       if (is_post_quantum_group(group_id) != is_post_quantum_group(groups[i])) { | 
 |         second_group_id = groups[i]; | 
 |         assert(second_group_id != group_id); | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   CBB key_exchange; | 
 |   hs->key_shares[0] = SSLKeyShare::Create(group_id); | 
 |   if (!hs->key_shares[0] ||  // | 
 |       !CBB_add_u16(cbb.get(), group_id) || | 
 |       !CBB_add_u16_length_prefixed(cbb.get(), &key_exchange) || | 
 |       !hs->key_shares[0]->Generate(&key_exchange)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (second_group_id != 0) { | 
 |     hs->key_shares[1] = SSLKeyShare::Create(second_group_id); | 
 |     if (!hs->key_shares[1] ||  // | 
 |         !CBB_add_u16(cbb.get(), second_group_id) || | 
 |         !CBB_add_u16_length_prefixed(cbb.get(), &key_exchange) || | 
 |         !hs->key_shares[1]->Generate(&key_exchange)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   return CBBFinishArray(cbb.get(), &hs->key_share_bytes); | 
 | } | 
 |  | 
 | static bool ext_key_share_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                           CBB *out_compressible, | 
 |                                           ssl_client_hello_type_t type) { | 
 |   if (hs->max_version < TLS1_3_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   assert(!hs->key_share_bytes.empty()); | 
 |   CBB contents, kse_bytes; | 
 |   if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_key_share) || | 
 |       !CBB_add_u16_length_prefixed(out_compressible, &contents) || | 
 |       !CBB_add_u16_length_prefixed(&contents, &kse_bytes) || | 
 |       !CBB_add_bytes(&kse_bytes, hs->key_share_bytes.data(), | 
 |                      hs->key_share_bytes.size()) || | 
 |       !CBB_flush(out_compressible)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs, | 
 |                                          Array<uint8_t> *out_secret, | 
 |                                          uint8_t *out_alert, CBS *contents) { | 
 |   CBS ciphertext; | 
 |   uint16_t group_id; | 
 |   if (!CBS_get_u16(contents, &group_id) || | 
 |       !CBS_get_u16_length_prefixed(contents, &ciphertext) || | 
 |       CBS_len(contents) != 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | 
 |     *out_alert = SSL_AD_DECODE_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   SSLKeyShare *key_share = hs->key_shares[0].get(); | 
 |   if (key_share->GroupID() != group_id) { | 
 |     if (!hs->key_shares[1] || hs->key_shares[1]->GroupID() != group_id) { | 
 |       *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE); | 
 |       return false; | 
 |     } | 
 |     key_share = hs->key_shares[1].get(); | 
 |   } | 
 |  | 
 |   if (!key_share->Decap(out_secret, out_alert, ciphertext)) { | 
 |     *out_alert = SSL_AD_INTERNAL_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   hs->new_session->group_id = group_id; | 
 |   hs->key_shares[0].reset(); | 
 |   hs->key_shares[1].reset(); | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, bool *out_found, | 
 |                                          Span<const uint8_t> *out_peer_key, | 
 |                                          uint8_t *out_alert, | 
 |                                          const SSL_CLIENT_HELLO *client_hello) { | 
 |   // We only support connections that include an ECDHE key exchange. | 
 |   CBS contents; | 
 |   if (!ssl_client_hello_get_extension(client_hello, &contents, | 
 |                                       TLSEXT_TYPE_key_share)) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE); | 
 |     *out_alert = SSL_AD_MISSING_EXTENSION; | 
 |     return false; | 
 |   } | 
 |  | 
 |   CBS key_shares; | 
 |   if (!CBS_get_u16_length_prefixed(&contents, &key_shares) || | 
 |       CBS_len(&contents) != 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Find the corresponding key share. | 
 |   const uint16_t group_id = hs->new_session->group_id; | 
 |   CBS peer_key; | 
 |   CBS_init(&peer_key, nullptr, 0); | 
 |   while (CBS_len(&key_shares) > 0) { | 
 |     uint16_t id; | 
 |     CBS peer_key_tmp; | 
 |     if (!CBS_get_u16(&key_shares, &id) || | 
 |         !CBS_get_u16_length_prefixed(&key_shares, &peer_key_tmp) || | 
 |         CBS_len(&peer_key_tmp) == 0) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | 
 |       return false; | 
 |     } | 
 |  | 
 |     if (id == group_id) { | 
 |       if (CBS_len(&peer_key) != 0) { | 
 |         OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_KEY_SHARE); | 
 |         *out_alert = SSL_AD_ILLEGAL_PARAMETER; | 
 |         return false; | 
 |       } | 
 |  | 
 |       peer_key = peer_key_tmp; | 
 |       // Continue parsing the structure to keep peers honest. | 
 |     } | 
 |   } | 
 |  | 
 |   if (out_peer_key != nullptr) { | 
 |     *out_peer_key = peer_key; | 
 |   } | 
 |   *out_found = CBS_len(&peer_key) != 0; | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   CBB entry, ciphertext; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) || | 
 |       !CBB_add_u16_length_prefixed(out, &entry) || | 
 |       !CBB_add_u16(&entry, hs->new_session->group_id) || | 
 |       !CBB_add_u16_length_prefixed(&entry, &ciphertext) || | 
 |       !CBB_add_bytes(&ciphertext, hs->key_share_ciphertext.data(), | 
 |                      hs->key_share_ciphertext.size()) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Supported Versions | 
 | // | 
 | // https://tools.ietf.org/html/rfc8446#section-4.2.1 | 
 |  | 
 | static bool ext_supported_versions_add_clienthello( | 
 |     const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible, | 
 |     ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   if (hs->max_version <= TLS1_2_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   // supported_versions is compressible in ECH if ClientHelloOuter already | 
 |   // requires TLS 1.3. Otherwise the extensions differ in the older versions. | 
 |   if (hs->min_version >= TLS1_3_VERSION) { | 
 |     out = out_compressible; | 
 |   } | 
 |  | 
 |   CBB contents, versions; | 
 |   if (!CBB_add_u16(out, TLSEXT_TYPE_supported_versions) || | 
 |       !CBB_add_u16_length_prefixed(out, &contents) || | 
 |       !CBB_add_u8_length_prefixed(&contents, &versions)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Add a fake version. See RFC 8701. | 
 |   if (ssl->ctx->grease_enabled && | 
 |       !CBB_add_u16(&versions, ssl_get_grease_value(hs, ssl_grease_version))) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Encrypted ClientHellos requires TLS 1.3 or later. | 
 |   uint16_t extra_min_version = | 
 |       type == ssl_client_hello_inner ? TLS1_3_VERSION : 0; | 
 |   if (!ssl_add_supported_versions(hs, &versions, extra_min_version) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Cookie | 
 | // | 
 | // https://tools.ietf.org/html/rfc8446#section-4.2.2 | 
 |  | 
 | static bool ext_cookie_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                        CBB *out_compressible, | 
 |                                        ssl_client_hello_type_t type) { | 
 |   if (hs->cookie.empty()) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBB contents, cookie; | 
 |   if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_cookie) || | 
 |       !CBB_add_u16_length_prefixed(out_compressible, &contents) || | 
 |       !CBB_add_u16_length_prefixed(&contents, &cookie) || | 
 |       !CBB_add_bytes(&cookie, hs->cookie.data(), hs->cookie.size()) || | 
 |       !CBB_flush(out_compressible)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // Supported Groups | 
 | // | 
 | // https://tools.ietf.org/html/rfc4492#section-5.1.1 | 
 | // https://tools.ietf.org/html/rfc8446#section-4.2.7 | 
 |  | 
 | static bool ext_supported_groups_add_clienthello(const SSL_HANDSHAKE *hs, | 
 |                                                  CBB *out, | 
 |                                                  CBB *out_compressible, | 
 |                                                  ssl_client_hello_type_t type) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   CBB contents, groups_bytes; | 
 |   if (!CBB_add_u16(out_compressible, TLSEXT_TYPE_supported_groups) || | 
 |       !CBB_add_u16_length_prefixed(out_compressible, &contents) || | 
 |       !CBB_add_u16_length_prefixed(&contents, &groups_bytes)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Add a fake group. See RFC 8701. | 
 |   if (ssl->ctx->grease_enabled && | 
 |       !CBB_add_u16(&groups_bytes, | 
 |                    ssl_get_grease_value(hs, ssl_grease_group))) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   for (uint16_t group : tls1_get_grouplist(hs)) { | 
 |     if (is_post_quantum_group(group) && | 
 |         hs->max_version < TLS1_3_VERSION) { | 
 |       continue; | 
 |     } | 
 |     if (!CBB_add_u16(&groups_bytes, group)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   return CBB_flush(out_compressible); | 
 | } | 
 |  | 
 | static bool ext_supported_groups_parse_serverhello(SSL_HANDSHAKE *hs, | 
 |                                                    uint8_t *out_alert, | 
 |                                                    CBS *contents) { | 
 |   // This extension is not expected to be echoed by servers in TLS 1.2, but some | 
 |   // BigIP servers send it nonetheless, so do not enforce this. | 
 |   return true; | 
 | } | 
 |  | 
 | static bool parse_u16_array(const CBS *cbs, Array<uint16_t> *out) { | 
 |   CBS copy = *cbs; | 
 |   if ((CBS_len(©) & 1) != 0) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | 
 |     return false; | 
 |   } | 
 |  | 
 |   Array<uint16_t> ret; | 
 |   if (!ret.Init(CBS_len(©) / 2)) { | 
 |     return false; | 
 |   } | 
 |   for (size_t i = 0; i < ret.size(); i++) { | 
 |     if (!CBS_get_u16(©, &ret[i])) { | 
 |       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   assert(CBS_len(©) == 0); | 
 |   *out = std::move(ret); | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_supported_groups_parse_clienthello(SSL_HANDSHAKE *hs, | 
 |                                                   uint8_t *out_alert, | 
 |                                                    CBS *contents) { | 
 |   if (contents == NULL) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   CBS supported_group_list; | 
 |   if (!CBS_get_u16_length_prefixed(contents, &supported_group_list) || | 
 |       CBS_len(&supported_group_list) == 0 || | 
 |       CBS_len(contents) != 0 || | 
 |       !parse_u16_array(&supported_group_list, &hs->peer_supported_group_list)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 |  | 
 | // QUIC Transport Parameters | 
 |  | 
 | static bool ext_quic_transport_params_add_clienthello_impl( | 
 |     const SSL_HANDSHAKE *hs, CBB *out, bool use_legacy_codepoint) { | 
 |   if (hs->config->quic_transport_params.empty() && !hs->ssl->quic_method) { | 
 |     return true; | 
 |   } | 
 |   if (hs->config->quic_transport_params.empty() || !hs->ssl->quic_method) { | 
 |     // QUIC Transport Parameters must be sent over QUIC, and they must not be | 
 |     // sent over non-QUIC transports. If transport params are set, then | 
 |     // SSL(_CTX)_set_quic_method must also be called. | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED); | 
 |     return false; | 
 |   } | 
 |   assert(hs->min_version > TLS1_2_VERSION); | 
 |   if (use_legacy_codepoint != hs->config->quic_use_legacy_codepoint) { | 
 |     // Do nothing, we'll send the other codepoint. | 
 |     return true; | 
 |   } | 
 |  | 
 |   uint16_t extension_type = TLSEXT_TYPE_quic_transport_parameters; | 
 |   if (hs->config->quic_use_legacy_codepoint) { | 
 |     extension_type = TLSEXT_TYPE_quic_transport_parameters_legacy; | 
 |   } | 
 |  | 
 |   CBB contents; | 
 |   if (!CBB_add_u16(out, extension_type) || | 
 |       !CBB_add_u16_length_prefixed(out, &contents) || | 
 |       !CBB_add_bytes(&contents, hs->config->quic_transport_params.data(), | 
 |                      hs->config->quic_transport_params.size()) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_quic_transport_params_add_clienthello( | 
 |     const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible, | 
 |     ssl_client_hello_type_t type) { | 
 |   return ext_quic_transport_params_add_clienthello_impl( | 
 |       hs, out_compressible, /*use_legacy_codepoint=*/false); | 
 | } | 
 |  | 
 | static bool ext_quic_transport_params_add_clienthello_legacy( | 
 |     const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible, | 
 |     ssl_client_hello_type_t type) { | 
 |   return ext_quic_transport_params_add_clienthello_impl( | 
 |       hs, out_compressible, /*use_legacy_codepoint=*/true); | 
 | } | 
 |  | 
 | static bool ext_quic_transport_params_parse_serverhello_impl( | 
 |     SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents, | 
 |     bool used_legacy_codepoint) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents == nullptr) { | 
 |     if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) { | 
 |       // Silently ignore because we expect the other QUIC codepoint. | 
 |       return true; | 
 |     } | 
 |     if (!ssl->quic_method) { | 
 |       return true; | 
 |     } | 
 |     *out_alert = SSL_AD_MISSING_EXTENSION; | 
 |     return false; | 
 |   } | 
 |   // The extensions parser will check for unsolicited extensions before | 
 |   // calling the callback. | 
 |   assert(ssl->quic_method != nullptr); | 
 |   assert(ssl_protocol_version(ssl) == TLS1_3_VERSION); | 
 |   assert(used_legacy_codepoint == hs->config->quic_use_legacy_codepoint); | 
 |   return ssl->s3->peer_quic_transport_params.CopyFrom(*contents); | 
 | } | 
 |  | 
 | static bool ext_quic_transport_params_parse_serverhello(SSL_HANDSHAKE *hs, | 
 |                                                         uint8_t *out_alert, | 
 |                                                         CBS *contents) { | 
 |   return ext_quic_transport_params_parse_serverhello_impl( | 
 |       hs, out_alert, contents, /*used_legacy_codepoint=*/false); | 
 | } | 
 |  | 
 | static bool ext_quic_transport_params_parse_serverhello_legacy( | 
 |     SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents) { | 
 |   return ext_quic_transport_params_parse_serverhello_impl( | 
 |       hs, out_alert, contents, /*used_legacy_codepoint=*/true); | 
 | } | 
 |  | 
 | static bool ext_quic_transport_params_parse_clienthello_impl( | 
 |     SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents, | 
 |     bool used_legacy_codepoint) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (!contents) { | 
 |     if (!ssl->quic_method) { | 
 |       if (hs->config->quic_transport_params.empty()) { | 
 |         return true; | 
 |       } | 
 |       // QUIC transport parameters must not be set if |ssl| is not configured | 
 |       // for QUIC. | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED); | 
 |       *out_alert = SSL_AD_INTERNAL_ERROR; | 
 |       return false; | 
 |     } | 
 |     if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) { | 
 |       // Silently ignore because we expect the other QUIC codepoint. | 
 |       return true; | 
 |     } | 
 |     *out_alert = SSL_AD_MISSING_EXTENSION; | 
 |     return false; | 
 |   } | 
 |   if (!ssl->quic_method) { | 
 |     if (used_legacy_codepoint) { | 
 |       // Ignore the legacy private-use codepoint because that could be sent | 
 |       // to mean something else than QUIC transport parameters. | 
 |       return true; | 
 |     } | 
 |     // Fail if we received the codepoint registered with IANA for QUIC | 
 |     // because that is not allowed outside of QUIC. | 
 |     *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; | 
 |     return false; | 
 |   } | 
 |   assert(ssl_protocol_version(ssl) == TLS1_3_VERSION); | 
 |   if (used_legacy_codepoint != hs->config->quic_use_legacy_codepoint) { | 
 |     // Silently ignore because we expect the other QUIC codepoint. | 
 |     return true; | 
 |   } | 
 |   return ssl->s3->peer_quic_transport_params.CopyFrom(*contents); | 
 | } | 
 |  | 
 | static bool ext_quic_transport_params_parse_clienthello(SSL_HANDSHAKE *hs, | 
 |                                                         uint8_t *out_alert, | 
 |                                                         CBS *contents) { | 
 |   return ext_quic_transport_params_parse_clienthello_impl( | 
 |       hs, out_alert, contents, /*used_legacy_codepoint=*/false); | 
 | } | 
 |  | 
 | static bool ext_quic_transport_params_parse_clienthello_legacy( | 
 |     SSL_HANDSHAKE *hs, uint8_t *out_alert, CBS *contents) { | 
 |   return ext_quic_transport_params_parse_clienthello_impl( | 
 |       hs, out_alert, contents, /*used_legacy_codepoint=*/true); | 
 | } | 
 |  | 
 | static bool ext_quic_transport_params_add_serverhello_impl( | 
 |     SSL_HANDSHAKE *hs, CBB *out, bool use_legacy_codepoint) { | 
 |   if (hs->ssl->quic_method == nullptr && use_legacy_codepoint) { | 
 |     // Ignore the legacy private-use codepoint because that could be sent | 
 |     // to mean something else than QUIC transport parameters. | 
 |     return true; | 
 |   } | 
 |   assert(hs->ssl->quic_method != nullptr); | 
 |   if (hs->config->quic_transport_params.empty()) { | 
 |     // Transport parameters must be set when using QUIC. | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED); | 
 |     return false; | 
 |   } | 
 |   if (use_legacy_codepoint != hs->config->quic_use_legacy_codepoint) { | 
 |     // Do nothing, we'll send the other codepoint. | 
 |     return true; | 
 |   } | 
 |  | 
 |   uint16_t extension_type = TLSEXT_TYPE_quic_transport_parameters; | 
 |   if (hs->config->quic_use_legacy_codepoint) { | 
 |     extension_type = TLSEXT_TYPE_quic_transport_parameters_legacy; | 
 |   } | 
 |  | 
 |   CBB contents; | 
 |   if (!CBB_add_u16(out, extension_type) || | 
 |       !CBB_add_u16_length_prefixed(out, &contents) || | 
 |       !CBB_add_bytes(&contents, hs->config->quic_transport_params.data(), | 
 |                      hs->config->quic_transport_params.size()) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_quic_transport_params_add_serverhello(SSL_HANDSHAKE *hs, | 
 |                                                       CBB *out) { | 
 |   return ext_quic_transport_params_add_serverhello_impl( | 
 |       hs, out, /*use_legacy_codepoint=*/false); | 
 | } | 
 |  | 
 | static bool ext_quic_transport_params_add_serverhello_legacy(SSL_HANDSHAKE *hs, | 
 |                                                              CBB *out) { | 
 |   return ext_quic_transport_params_add_serverhello_impl( | 
 |       hs, out, /*use_legacy_codepoint=*/true); | 
 | } | 
 |  | 
 | // Delegated credentials. | 
 | // | 
 | // https://tools.ietf.org/html/draft-ietf-tls-subcerts | 
 |  | 
 | static bool ext_delegated_credential_add_clienthello( | 
 |     const SSL_HANDSHAKE *hs, CBB *out, CBB *out_compressible, | 
 |     ssl_client_hello_type_t type) { | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_delegated_credential_parse_clienthello(SSL_HANDSHAKE *hs, | 
 |                                                        uint8_t *out_alert, | 
 |                                                        CBS *contents) { | 
 |   if (contents == nullptr || ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) { | 
 |     // Don't use delegated credentials unless we're negotiating TLS 1.3 or | 
 |     // higher. | 
 |     return true; | 
 |   } | 
 |  | 
 |   // The contents of the extension are the signature algorithms the client will | 
 |   // accept for a delegated credential. | 
 |   CBS sigalg_list; | 
 |   if (!CBS_get_u16_length_prefixed(contents, &sigalg_list) || | 
 |       CBS_len(&sigalg_list) == 0 || | 
 |       CBS_len(contents) != 0 || | 
 |       !parse_u16_array(&sigalg_list, &hs->peer_delegated_credential_sigalgs)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   hs->delegated_credential_requested = true; | 
 |   return true; | 
 | } | 
 |  | 
 | // Certificate compression | 
 |  | 
 | static bool cert_compression_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                              CBB *out_compressible, | 
 |                                              ssl_client_hello_type_t type) { | 
 |   bool first = true; | 
 |   CBB contents, algs; | 
 |  | 
 |   for (const auto &alg : hs->ssl->ctx->cert_compression_algs) { | 
 |     if (alg.decompress == nullptr) { | 
 |       continue; | 
 |     } | 
 |  | 
 |     if (first && | 
 |         (!CBB_add_u16(out_compressible, TLSEXT_TYPE_cert_compression) || | 
 |          !CBB_add_u16_length_prefixed(out_compressible, &contents) || | 
 |          !CBB_add_u8_length_prefixed(&contents, &algs))) { | 
 |       return false; | 
 |     } | 
 |     first = false; | 
 |     if (!CBB_add_u16(&algs, alg.alg_id)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   return first || CBB_flush(out_compressible); | 
 | } | 
 |  | 
 | static bool cert_compression_parse_serverhello(SSL_HANDSHAKE *hs, | 
 |                                                uint8_t *out_alert, | 
 |                                                CBS *contents) { | 
 |   if (contents == nullptr) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   // The server may not echo this extension. Any server to client negotiation is | 
 |   // advertised in the CertificateRequest message. | 
 |   return false; | 
 | } | 
 |  | 
 | static bool cert_compression_parse_clienthello(SSL_HANDSHAKE *hs, | 
 |                                                uint8_t *out_alert, | 
 |                                                CBS *contents) { | 
 |   if (contents == nullptr) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   const SSL_CTX *ctx = hs->ssl->ctx.get(); | 
 |   const size_t num_algs = ctx->cert_compression_algs.size(); | 
 |  | 
 |   CBS alg_ids; | 
 |   if (!CBS_get_u8_length_prefixed(contents, &alg_ids) || | 
 |       CBS_len(contents) != 0 || | 
 |       CBS_len(&alg_ids) == 0 || | 
 |       CBS_len(&alg_ids) % 2 == 1) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   const size_t num_given_alg_ids = CBS_len(&alg_ids) / 2; | 
 |   Array<uint16_t> given_alg_ids; | 
 |   if (!given_alg_ids.Init(num_given_alg_ids)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   size_t best_index = num_algs; | 
 |   size_t given_alg_idx = 0; | 
 |  | 
 |   while (CBS_len(&alg_ids) > 0) { | 
 |     uint16_t alg_id; | 
 |     if (!CBS_get_u16(&alg_ids, &alg_id)) { | 
 |       return false; | 
 |     } | 
 |  | 
 |     given_alg_ids[given_alg_idx++] = alg_id; | 
 |  | 
 |     for (size_t i = 0; i < num_algs; i++) { | 
 |       const auto &alg = ctx->cert_compression_algs[i]; | 
 |       if (alg.alg_id == alg_id && alg.compress != nullptr) { | 
 |         if (i < best_index) { | 
 |           best_index = i; | 
 |         } | 
 |         break; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   qsort(given_alg_ids.data(), given_alg_ids.size(), sizeof(uint16_t), | 
 |         compare_uint16_t); | 
 |   for (size_t i = 1; i < num_given_alg_ids; i++) { | 
 |     if (given_alg_ids[i - 1] == given_alg_ids[i]) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   if (best_index < num_algs && | 
 |       ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) { | 
 |     hs->cert_compression_negotiated = true; | 
 |     hs->cert_compression_alg_id = ctx->cert_compression_algs[best_index].alg_id; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool cert_compression_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   return true; | 
 | } | 
 |  | 
 | // Application-level Protocol Settings | 
 | // | 
 | // https://tools.ietf.org/html/draft-vvv-tls-alps-01 | 
 |  | 
 | bool ssl_get_local_application_settings(const SSL_HANDSHAKE *hs, | 
 |                                         Span<const uint8_t> *out_settings, | 
 |                                         Span<const uint8_t> protocol) { | 
 |   for (const ALPSConfig &config : hs->config->alps_configs) { | 
 |     if (protocol == config.protocol) { | 
 |       *out_settings = config.settings; | 
 |       return true; | 
 |     } | 
 |   } | 
 |   return false; | 
 | } | 
 |  | 
 | static bool ext_alps_add_clienthello_impl(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                           CBB *out_compressible, | 
 |                                           ssl_client_hello_type_t type, | 
 |                                           bool use_new_codepoint) { | 
 |   const SSL *const ssl = hs->ssl; | 
 |   if (// ALPS requires TLS 1.3. | 
 |       hs->max_version < TLS1_3_VERSION || | 
 |       // Do not offer ALPS without ALPN. | 
 |       hs->config->alpn_client_proto_list.empty() || | 
 |       // Do not offer ALPS if not configured. | 
 |       hs->config->alps_configs.empty() || | 
 |       // Do not offer ALPS on renegotiation handshakes. | 
 |       ssl->s3->initial_handshake_complete) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   if (use_new_codepoint != hs->config->alps_use_new_codepoint) { | 
 |     // Do nothing, we'll send the other codepoint. | 
 |     return true; | 
 |   } | 
 |  | 
 |   uint16_t extension_type = TLSEXT_TYPE_application_settings_old; | 
 |   if (hs->config->alps_use_new_codepoint) { | 
 |     extension_type = TLSEXT_TYPE_application_settings; | 
 |   } | 
 |  | 
 |   CBB contents, proto_list, proto; | 
 |   if (!CBB_add_u16(out_compressible, extension_type) || | 
 |       !CBB_add_u16_length_prefixed(out_compressible, &contents) || | 
 |       !CBB_add_u16_length_prefixed(&contents, &proto_list)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   for (const ALPSConfig &config : hs->config->alps_configs) { | 
 |     if (!CBB_add_u8_length_prefixed(&proto_list, &proto) || | 
 |         !CBB_add_bytes(&proto, config.protocol.data(), | 
 |                        config.protocol.size())) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   return CBB_flush(out_compressible); | 
 | } | 
 |  | 
 | static bool ext_alps_add_clienthello(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                      CBB *out_compressible, | 
 |                                      ssl_client_hello_type_t type) { | 
 |   return ext_alps_add_clienthello_impl(hs, out, out_compressible, type, | 
 |                                        /*use_new_codepoint=*/true); | 
 | } | 
 |  | 
 | static bool ext_alps_add_clienthello_old(const SSL_HANDSHAKE *hs, CBB *out, | 
 |                                          CBB *out_compressible, | 
 |                                          ssl_client_hello_type_t type) { | 
 |   return ext_alps_add_clienthello_impl(hs, out, out_compressible, type, | 
 |                                        /*use_new_codepoint=*/false); | 
 | } | 
 |  | 
 | static bool ext_alps_parse_serverhello_impl(SSL_HANDSHAKE *hs, | 
 |                                             uint8_t *out_alert, | 
 |                                             CBS *contents, | 
 |                                             bool use_new_codepoint) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (contents == nullptr) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   assert(!ssl->s3->initial_handshake_complete); | 
 |   assert(!hs->config->alpn_client_proto_list.empty()); | 
 |   assert(!hs->config->alps_configs.empty()); | 
 |   assert(use_new_codepoint == hs->config->alps_use_new_codepoint); | 
 |  | 
 |   // ALPS requires TLS 1.3. | 
 |   if (ssl_protocol_version(ssl) < TLS1_3_VERSION) { | 
 |     *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Note extension callbacks may run in any order, so we defer checking | 
 |   // consistency with ALPN to |ssl_check_serverhello_tlsext|. | 
 |   if (!hs->new_session->peer_application_settings.CopyFrom(*contents)) { | 
 |     *out_alert = SSL_AD_INTERNAL_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   hs->new_session->has_application_settings = true; | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_alps_parse_serverhello(SSL_HANDSHAKE *hs, | 
 |                                        uint8_t *out_alert, | 
 |                                        CBS *contents) { | 
 |   return ext_alps_parse_serverhello_impl(hs, out_alert, contents, | 
 |                                          /*use_new_codepoint=*/true); | 
 | } | 
 |  | 
 | static bool ext_alps_parse_serverhello_old(SSL_HANDSHAKE *hs, | 
 |                                            uint8_t *out_alert, | 
 |                                            CBS *contents) { | 
 |   return ext_alps_parse_serverhello_impl(hs, out_alert, contents, | 
 |                                          /*use_new_codepoint=*/false); | 
 | } | 
 |  | 
 | static bool ext_alps_add_serverhello_impl(SSL_HANDSHAKE *hs, CBB *out, | 
 |                                           bool use_new_codepoint) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   // If early data is accepted, we omit the ALPS extension. It is implicitly | 
 |   // carried over from the previous connection. | 
 |   if (hs->new_session == nullptr || | 
 |       !hs->new_session->has_application_settings || | 
 |       ssl->s3->early_data_accepted) { | 
 |     return true; | 
 |   } | 
 |  | 
 |    if (use_new_codepoint != hs->config->alps_use_new_codepoint) { | 
 |     // Do nothing, we'll send the other codepoint. | 
 |     return true; | 
 |   } | 
 |  | 
 |   uint16_t extension_type = TLSEXT_TYPE_application_settings_old; | 
 |   if (hs->config->alps_use_new_codepoint) { | 
 |     extension_type = TLSEXT_TYPE_application_settings; | 
 |   } | 
 |  | 
 |   CBB contents; | 
 |   if (!CBB_add_u16(out, extension_type) || | 
 |       !CBB_add_u16_length_prefixed(out, &contents) || | 
 |       !CBB_add_bytes(&contents, | 
 |                      hs->new_session->local_application_settings.data(), | 
 |                      hs->new_session->local_application_settings.size()) || | 
 |       !CBB_flush(out)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ext_alps_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   return ext_alps_add_serverhello_impl(hs, out, /*use_new_codepoint=*/true); | 
 | } | 
 |  | 
 | static bool ext_alps_add_serverhello_old(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   return ext_alps_add_serverhello_impl(hs, out, /*use_new_codepoint=*/false); | 
 | } | 
 |  | 
 | bool ssl_negotiate_alps(SSL_HANDSHAKE *hs, uint8_t *out_alert, | 
 |                         const SSL_CLIENT_HELLO *client_hello) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (ssl->s3->alpn_selected.empty()) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   // If we negotiate ALPN over TLS 1.3, try to negotiate ALPS. | 
 |   CBS alps_contents; | 
 |   Span<const uint8_t> settings; | 
 |   uint16_t extension_type = TLSEXT_TYPE_application_settings_old; | 
 |   if (hs->config->alps_use_new_codepoint) { | 
 |     extension_type = TLSEXT_TYPE_application_settings; | 
 |   } | 
 |   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION && | 
 |       ssl_get_local_application_settings(hs, &settings, | 
 |                                          ssl->s3->alpn_selected) && | 
 |       ssl_client_hello_get_extension(client_hello, &alps_contents, | 
 |                                      extension_type)) { | 
 |     // Check if the client supports ALPS with the selected ALPN. | 
 |     bool found = false; | 
 |     CBS alps_list; | 
 |     if (!CBS_get_u16_length_prefixed(&alps_contents, &alps_list) || | 
 |         CBS_len(&alps_contents) != 0 || | 
 |         CBS_len(&alps_list) == 0) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | 
 |       *out_alert = SSL_AD_DECODE_ERROR; | 
 |       return false; | 
 |     } | 
 |     while (CBS_len(&alps_list) > 0) { | 
 |       CBS protocol_name; | 
 |       if (!CBS_get_u8_length_prefixed(&alps_list, &protocol_name) || | 
 |           // Empty protocol names are forbidden. | 
 |           CBS_len(&protocol_name) == 0) { | 
 |         OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | 
 |         *out_alert = SSL_AD_DECODE_ERROR; | 
 |         return false; | 
 |       } | 
 |       if (protocol_name == MakeConstSpan(ssl->s3->alpn_selected)) { | 
 |         found = true; | 
 |       } | 
 |     } | 
 |  | 
 |     // Negotiate ALPS if both client also supports ALPS for this protocol. | 
 |     if (found) { | 
 |       hs->new_session->has_application_settings = true; | 
 |       if (!hs->new_session->local_application_settings.CopyFrom(settings)) { | 
 |         *out_alert = SSL_AD_INTERNAL_ERROR; | 
 |         return false; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | // kExtensions contains all the supported extensions. | 
 | static const struct tls_extension kExtensions[] = { | 
 |   { | 
 |     TLSEXT_TYPE_server_name, | 
 |     ext_sni_add_clienthello, | 
 |     ext_sni_parse_serverhello, | 
 |     ext_sni_parse_clienthello, | 
 |     ext_sni_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_encrypted_client_hello, | 
 |     ext_ech_add_clienthello, | 
 |     ext_ech_parse_serverhello, | 
 |     ext_ech_parse_clienthello, | 
 |     ext_ech_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_extended_master_secret, | 
 |     ext_ems_add_clienthello, | 
 |     ext_ems_parse_serverhello, | 
 |     ext_ems_parse_clienthello, | 
 |     ext_ems_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_renegotiate, | 
 |     ext_ri_add_clienthello, | 
 |     ext_ri_parse_serverhello, | 
 |     ext_ri_parse_clienthello, | 
 |     ext_ri_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_supported_groups, | 
 |     ext_supported_groups_add_clienthello, | 
 |     ext_supported_groups_parse_serverhello, | 
 |     ext_supported_groups_parse_clienthello, | 
 |     dont_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_ec_point_formats, | 
 |     ext_ec_point_add_clienthello, | 
 |     ext_ec_point_parse_serverhello, | 
 |     ext_ec_point_parse_clienthello, | 
 |     ext_ec_point_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_session_ticket, | 
 |     ext_ticket_add_clienthello, | 
 |     ext_ticket_parse_serverhello, | 
 |     // Ticket extension client parsing is handled in ssl_session.c | 
 |     ignore_parse_clienthello, | 
 |     ext_ticket_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_application_layer_protocol_negotiation, | 
 |     ext_alpn_add_clienthello, | 
 |     ext_alpn_parse_serverhello, | 
 |     // ALPN is negotiated late in |ssl_negotiate_alpn|. | 
 |     ignore_parse_clienthello, | 
 |     ext_alpn_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_status_request, | 
 |     ext_ocsp_add_clienthello, | 
 |     ext_ocsp_parse_serverhello, | 
 |     ext_ocsp_parse_clienthello, | 
 |     ext_ocsp_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_signature_algorithms, | 
 |     ext_sigalgs_add_clienthello, | 
 |     forbid_parse_serverhello, | 
 |     ext_sigalgs_parse_clienthello, | 
 |     dont_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_next_proto_neg, | 
 |     ext_npn_add_clienthello, | 
 |     ext_npn_parse_serverhello, | 
 |     ext_npn_parse_clienthello, | 
 |     ext_npn_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_certificate_timestamp, | 
 |     ext_sct_add_clienthello, | 
 |     ext_sct_parse_serverhello, | 
 |     ext_sct_parse_clienthello, | 
 |     ext_sct_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_channel_id, | 
 |     ext_channel_id_add_clienthello, | 
 |     ext_channel_id_parse_serverhello, | 
 |     ext_channel_id_parse_clienthello, | 
 |     ext_channel_id_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_srtp, | 
 |     ext_srtp_add_clienthello, | 
 |     ext_srtp_parse_serverhello, | 
 |     ext_srtp_parse_clienthello, | 
 |     ext_srtp_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_key_share, | 
 |     ext_key_share_add_clienthello, | 
 |     forbid_parse_serverhello, | 
 |     ignore_parse_clienthello, | 
 |     dont_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_psk_key_exchange_modes, | 
 |     ext_psk_key_exchange_modes_add_clienthello, | 
 |     forbid_parse_serverhello, | 
 |     ext_psk_key_exchange_modes_parse_clienthello, | 
 |     dont_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_early_data, | 
 |     ext_early_data_add_clienthello, | 
 |     ext_early_data_parse_serverhello, | 
 |     ext_early_data_parse_clienthello, | 
 |     ext_early_data_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_supported_versions, | 
 |     ext_supported_versions_add_clienthello, | 
 |     forbid_parse_serverhello, | 
 |     ignore_parse_clienthello, | 
 |     dont_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_cookie, | 
 |     ext_cookie_add_clienthello, | 
 |     forbid_parse_serverhello, | 
 |     ignore_parse_clienthello, | 
 |     dont_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_quic_transport_parameters, | 
 |     ext_quic_transport_params_add_clienthello, | 
 |     ext_quic_transport_params_parse_serverhello, | 
 |     ext_quic_transport_params_parse_clienthello, | 
 |     ext_quic_transport_params_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_quic_transport_parameters_legacy, | 
 |     ext_quic_transport_params_add_clienthello_legacy, | 
 |     ext_quic_transport_params_parse_serverhello_legacy, | 
 |     ext_quic_transport_params_parse_clienthello_legacy, | 
 |     ext_quic_transport_params_add_serverhello_legacy, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_cert_compression, | 
 |     cert_compression_add_clienthello, | 
 |     cert_compression_parse_serverhello, | 
 |     cert_compression_parse_clienthello, | 
 |     cert_compression_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_delegated_credential, | 
 |     ext_delegated_credential_add_clienthello, | 
 |     forbid_parse_serverhello, | 
 |     ext_delegated_credential_parse_clienthello, | 
 |     dont_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_application_settings, | 
 |     ext_alps_add_clienthello, | 
 |     ext_alps_parse_serverhello, | 
 |     // ALPS is negotiated late in |ssl_negotiate_alpn|. | 
 |     ignore_parse_clienthello, | 
 |     ext_alps_add_serverhello, | 
 |   }, | 
 |   { | 
 |     TLSEXT_TYPE_application_settings_old, | 
 |     ext_alps_add_clienthello_old, | 
 |     ext_alps_parse_serverhello_old, | 
 |     // ALPS is negotiated late in |ssl_negotiate_alpn|. | 
 |     ignore_parse_clienthello, | 
 |     ext_alps_add_serverhello_old, | 
 |   }, | 
 | }; | 
 |  | 
 | #define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension)) | 
 |  | 
 | static_assert(kNumExtensions <= | 
 |                   sizeof(((SSL_HANDSHAKE *)NULL)->extensions.sent) * 8, | 
 |               "too many extensions for sent bitset"); | 
 | static_assert(kNumExtensions <= | 
 |                   sizeof(((SSL_HANDSHAKE *)NULL)->extensions.received) * 8, | 
 |               "too many extensions for received bitset"); | 
 |  | 
 | bool ssl_setup_extension_permutation(SSL_HANDSHAKE *hs) { | 
 |   if (!hs->config->permute_extensions) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   static_assert(kNumExtensions <= UINT8_MAX, | 
 |                 "extensions_permutation type is too small"); | 
 |   uint32_t seeds[kNumExtensions - 1]; | 
 |   Array<uint8_t> permutation; | 
 |   if (!RAND_bytes(reinterpret_cast<uint8_t *>(seeds), sizeof(seeds)) || | 
 |       !permutation.Init(kNumExtensions)) { | 
 |     return false; | 
 |   } | 
 |   for (size_t i = 0; i < kNumExtensions; i++) { | 
 |     permutation[i] = i; | 
 |   } | 
 |   for (size_t i = kNumExtensions - 1; i > 0; i--) { | 
 |     // Set element |i| to a randomly-selected element 0 <= j <= i. | 
 |     std::swap(permutation[i], permutation[seeds[i - 1] % (i + 1)]); | 
 |   } | 
 |   hs->extension_permutation = std::move(permutation); | 
 |   return true; | 
 | } | 
 |  | 
 | static const struct tls_extension *tls_extension_find(uint32_t *out_index, | 
 |                                                       uint16_t value) { | 
 |   unsigned i; | 
 |   for (i = 0; i < kNumExtensions; i++) { | 
 |     if (kExtensions[i].value == value) { | 
 |       *out_index = i; | 
 |       return &kExtensions[i]; | 
 |     } | 
 |   } | 
 |  | 
 |   return NULL; | 
 | } | 
 |  | 
 | static bool add_padding_extension(CBB *cbb, uint16_t ext, size_t len) { | 
 |   CBB child; | 
 |   if (!CBB_add_u16(cbb, ext) ||  // | 
 |       !CBB_add_u16_length_prefixed(cbb, &child) || | 
 |       !CBB_add_zeros(&child, len)) { | 
 |     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | 
 |     return false; | 
 |   } | 
 |   return CBB_flush(cbb); | 
 | } | 
 |  | 
 | static bool ssl_add_clienthello_tlsext_inner(SSL_HANDSHAKE *hs, CBB *out, | 
 |                                              CBB *out_encoded, | 
 |                                              bool *out_needs_psk_binder) { | 
 |   // When writing ClientHelloInner, we construct the real and encoded | 
 |   // ClientHellos concurrently, to handle compression. Uncompressed extensions | 
 |   // are written to |extensions| and copied to |extensions_encoded|. Compressed | 
 |   // extensions are buffered in |compressed| and written to the end. (ECH can | 
 |   // only compress continguous extensions.) | 
 |   SSL *const ssl = hs->ssl; | 
 |   bssl::ScopedCBB compressed, outer_extensions; | 
 |   CBB extensions, extensions_encoded; | 
 |   if (!CBB_add_u16_length_prefixed(out, &extensions) || | 
 |       !CBB_add_u16_length_prefixed(out_encoded, &extensions_encoded) || | 
 |       !CBB_init(compressed.get(), 64) || | 
 |       !CBB_init(outer_extensions.get(), 64)) { | 
 |     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | 
 |     return false; | 
 |   } | 
 |  | 
 |   hs->inner_extensions_sent = 0; | 
 |  | 
 |   if (ssl->ctx->grease_enabled) { | 
 |     // Add a fake empty extension. See RFC 8701. This always matches | 
 |     // |ssl_add_clienthello_tlsext|, so compress it. | 
 |     uint16_t grease_ext = ssl_get_grease_value(hs, ssl_grease_extension1); | 
 |     if (!add_padding_extension(compressed.get(), grease_ext, 0) || | 
 |         !CBB_add_u16(outer_extensions.get(), grease_ext)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   for (size_t unpermuted = 0; unpermuted < kNumExtensions; unpermuted++) { | 
 |     size_t i = hs->extension_permutation.empty() | 
 |                    ? unpermuted | 
 |                    : hs->extension_permutation[unpermuted]; | 
 |     const size_t len_before = CBB_len(&extensions); | 
 |     const size_t len_compressed_before = CBB_len(compressed.get()); | 
 |     if (!kExtensions[i].add_clienthello(hs, &extensions, compressed.get(), | 
 |                                         ssl_client_hello_inner)) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION); | 
 |       ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value); | 
 |       return false; | 
 |     } | 
 |  | 
 |     const size_t bytes_written = CBB_len(&extensions) - len_before; | 
 |     const size_t bytes_written_compressed = | 
 |         CBB_len(compressed.get()) - len_compressed_before; | 
 |     // The callback may write to at most one output. | 
 |     assert(bytes_written == 0 || bytes_written_compressed == 0); | 
 |     if (bytes_written != 0 || bytes_written_compressed != 0) { | 
 |       hs->inner_extensions_sent |= (1u << i); | 
 |     } | 
 |     // If compressed, update the running ech_outer_extensions extension. | 
 |     if (bytes_written_compressed != 0 && | 
 |         !CBB_add_u16(outer_extensions.get(), kExtensions[i].value)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   if (ssl->ctx->grease_enabled) { | 
 |     // Add a fake non-empty extension. See RFC 8701. This always matches | 
 |     // |ssl_add_clienthello_tlsext|, so compress it. | 
 |     uint16_t grease_ext = ssl_get_grease_value(hs, ssl_grease_extension2); | 
 |     if (!add_padding_extension(compressed.get(), grease_ext, 1) || | 
 |         !CBB_add_u16(outer_extensions.get(), grease_ext)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   // Uncompressed extensions are encoded as-is. | 
 |   if (!CBB_add_bytes(&extensions_encoded, CBB_data(&extensions), | 
 |                      CBB_len(&extensions))) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Flush all the compressed extensions. | 
 |   if (CBB_len(compressed.get()) != 0) { | 
 |     CBB extension, child; | 
 |     // Copy them as-is in the real ClientHelloInner. | 
 |     if (!CBB_add_bytes(&extensions, CBB_data(compressed.get()), | 
 |                        CBB_len(compressed.get())) || | 
 |         // Replace with ech_outer_extensions in the encoded form. | 
 |         !CBB_add_u16(&extensions_encoded, TLSEXT_TYPE_ech_outer_extensions) || | 
 |         !CBB_add_u16_length_prefixed(&extensions_encoded, &extension) || | 
 |         !CBB_add_u8_length_prefixed(&extension, &child) || | 
 |         !CBB_add_bytes(&child, CBB_data(outer_extensions.get()), | 
 |                        CBB_len(outer_extensions.get())) || | 
 |         !CBB_flush(&extensions_encoded)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   // The PSK extension must be last. It is never compressed. Note, if there is a | 
 |   // binder, the caller will need to update both ClientHelloInner and | 
 |   // EncodedClientHelloInner after computing it. | 
 |   const size_t len_before = CBB_len(&extensions); | 
 |   if (!ext_pre_shared_key_add_clienthello(hs, &extensions, out_needs_psk_binder, | 
 |                                           ssl_client_hello_inner) || | 
 |       !CBB_add_bytes(&extensions_encoded, CBB_data(&extensions) + len_before, | 
 |                      CBB_len(&extensions) - len_before) || | 
 |       !CBB_flush(out) ||  // | 
 |       !CBB_flush(out_encoded)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, CBB *out_encoded, | 
 |                                 bool *out_needs_psk_binder, | 
 |                                 ssl_client_hello_type_t type, | 
 |                                 size_t header_len) { | 
 |   *out_needs_psk_binder = false; | 
 |  | 
 |   if (type == ssl_client_hello_inner) { | 
 |     return ssl_add_clienthello_tlsext_inner(hs, out, out_encoded, | 
 |                                             out_needs_psk_binder); | 
 |   } | 
 |  | 
 |   assert(out_encoded == nullptr);  // Only ClientHelloInner needs two outputs. | 
 |   SSL *const ssl = hs->ssl; | 
 |   CBB extensions; | 
 |   if (!CBB_add_u16_length_prefixed(out, &extensions)) { | 
 |     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | 
 |     return false; | 
 |   } | 
 |  | 
 |   // Note we may send multiple ClientHellos for DTLS HelloVerifyRequest and TLS | 
 |   // 1.3 HelloRetryRequest. For the latter, the extensions may change, so it is | 
 |   // important to reset this value. | 
 |   hs->extensions.sent = 0; | 
 |  | 
 |   // Add a fake empty extension. See RFC 8701. | 
 |   if (ssl->ctx->grease_enabled && | 
 |       !add_padding_extension( | 
 |           &extensions, ssl_get_grease_value(hs, ssl_grease_extension1), 0)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   bool last_was_empty = false; | 
 |   for (size_t unpermuted = 0; unpermuted < kNumExtensions; unpermuted++) { | 
 |     size_t i = hs->extension_permutation.empty() | 
 |                    ? unpermuted | 
 |                    : hs->extension_permutation[unpermuted]; | 
 |     const size_t len_before = CBB_len(&extensions); | 
 |     if (!kExtensions[i].add_clienthello(hs, &extensions, &extensions, type)) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION); | 
 |       ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value); | 
 |       return false; | 
 |     } | 
 |  | 
 |     const size_t bytes_written = CBB_len(&extensions) - len_before; | 
 |     if (bytes_written != 0) { | 
 |       hs->extensions.sent |= (1u << i); | 
 |     } | 
 |     // If the difference in lengths is only four bytes then the extension had | 
 |     // an empty body. | 
 |     last_was_empty = (bytes_written == 4); | 
 |   } | 
 |  | 
 |   if (ssl->ctx->grease_enabled) { | 
 |     // Add a fake non-empty extension. See RFC 8701. | 
 |     if (!add_padding_extension( | 
 |             &extensions, ssl_get_grease_value(hs, ssl_grease_extension2), 1)) { | 
 |       return false; | 
 |     } | 
 |     last_was_empty = false; | 
 |   } | 
 |  | 
 |   // In cleartext ClientHellos, we add the padding extension to work around | 
 |   // bugs. We also apply this padding to ClientHelloOuter, to keep the wire | 
 |   // images aligned. | 
 |   size_t psk_extension_len = ext_pre_shared_key_clienthello_length(hs, type); | 
 |   if (!SSL_is_dtls(ssl) && !ssl->quic_method && | 
 |       !ssl->s3->used_hello_retry_request) { | 
 |     header_len += | 
 |         SSL3_HM_HEADER_LENGTH + 2 + CBB_len(&extensions) + psk_extension_len; | 
 |     size_t padding_len = 0; | 
 |  | 
 |     // The final extension must be non-empty. WebSphere Application | 
 |     // Server 7.0 is intolerant to the last extension being zero-length. See | 
 |     // https://crbug.com/363583. | 
 |     if (last_was_empty && psk_extension_len == 0) { | 
 |       padding_len = 1; | 
 |       // The addition of the padding extension may push us into the F5 bug. | 
 |       header_len += 4 + padding_len; | 
 |     } | 
 |  | 
 |     // Add padding to workaround bugs in F5 terminators. See RFC 7685. | 
 |     // | 
 |     // NB: because this code works out the length of all existing extensions | 
 |     // it MUST always appear last (save for any PSK extension). | 
 |     if (header_len > 0xff && header_len < 0x200) { | 
 |       // If our calculations already included a padding extension, remove that | 
 |       // factor because we're about to change its length. | 
 |       if (padding_len != 0) { | 
 |         header_len -= 4 + padding_len; | 
 |       } | 
 |       padding_len = 0x200 - header_len; | 
 |       // Extensions take at least four bytes to encode. Always include at least | 
 |       // one byte of data if including the extension. WebSphere Application | 
 |       // Server 7.0 is intolerant to the last extension being zero-length. See | 
 |       // https://crbug.com/363583. | 
 |       if (padding_len >= 4 + 1) { | 
 |         padding_len -= 4; | 
 |       } else { | 
 |         padding_len = 1; | 
 |       } | 
 |     } | 
 |  | 
 |     if (padding_len != 0 && | 
 |         !add_padding_extension(&extensions, TLSEXT_TYPE_padding, padding_len)) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   // The PSK extension must be last, including after the padding. | 
 |   const size_t len_before = CBB_len(&extensions); | 
 |   if (!ext_pre_shared_key_add_clienthello(hs, &extensions, out_needs_psk_binder, | 
 |                                           type)) { | 
 |     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | 
 |     return false; | 
 |   } | 
 |   assert(psk_extension_len == CBB_len(&extensions) - len_before); | 
 |   (void)len_before;  // |assert| is omitted in release builds. | 
 |  | 
 |   // Discard empty extensions blocks. | 
 |   if (CBB_len(&extensions) == 0) { | 
 |     CBB_discard_child(out); | 
 |   } | 
 |  | 
 |   return CBB_flush(out); | 
 | } | 
 |  | 
 | bool ssl_add_serverhello_tlsext(SSL_HANDSHAKE *hs, CBB *out) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   CBB extensions; | 
 |   if (!CBB_add_u16_length_prefixed(out, &extensions)) { | 
 |     goto err; | 
 |   } | 
 |  | 
 |   for (unsigned i = 0; i < kNumExtensions; i++) { | 
 |     if (!(hs->extensions.received & (1u << i))) { | 
 |       // Don't send extensions that were not received. | 
 |       continue; | 
 |     } | 
 |  | 
 |     if (!kExtensions[i].add_serverhello(hs, &extensions)) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION); | 
 |       ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value); | 
 |       goto err; | 
 |     } | 
 |   } | 
 |  | 
 |   // Discard empty extensions blocks before TLS 1.3. | 
 |   if (ssl_protocol_version(ssl) < TLS1_3_VERSION && | 
 |       CBB_len(&extensions) == 0) { | 
 |     CBB_discard_child(out); | 
 |   } | 
 |  | 
 |   return CBB_flush(out); | 
 |  | 
 | err: | 
 |   OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | 
 |   return false; | 
 | } | 
 |  | 
 | static bool ssl_scan_clienthello_tlsext(SSL_HANDSHAKE *hs, | 
 |                                         const SSL_CLIENT_HELLO *client_hello, | 
 |                                         int *out_alert) { | 
 |   hs->extensions.received = 0; | 
 |   CBS extensions; | 
 |   CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len); | 
 |   while (CBS_len(&extensions) != 0) { | 
 |     uint16_t type; | 
 |     CBS extension; | 
 |  | 
 |     // Decode the next extension. | 
 |     if (!CBS_get_u16(&extensions, &type) || | 
 |         !CBS_get_u16_length_prefixed(&extensions, &extension)) { | 
 |       *out_alert = SSL_AD_DECODE_ERROR; | 
 |       return false; | 
 |     } | 
 |  | 
 |     unsigned ext_index; | 
 |     const struct tls_extension *const ext = | 
 |         tls_extension_find(&ext_index, type); | 
 |     if (ext == NULL) { | 
 |       continue; | 
 |     } | 
 |  | 
 |     hs->extensions.received |= (1u << ext_index); | 
 |     uint8_t alert = SSL_AD_DECODE_ERROR; | 
 |     if (!ext->parse_clienthello(hs, &alert, &extension)) { | 
 |       *out_alert = alert; | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); | 
 |       ERR_add_error_dataf("extension %u", (unsigned)type); | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   for (size_t i = 0; i < kNumExtensions; i++) { | 
 |     if (hs->extensions.received & (1u << i)) { | 
 |       continue; | 
 |     } | 
 |  | 
 |     CBS *contents = NULL, fake_contents; | 
 |     static const uint8_t kFakeRenegotiateExtension[] = {0}; | 
 |     if (kExtensions[i].value == TLSEXT_TYPE_renegotiate && | 
 |         ssl_client_cipher_list_contains_cipher(client_hello, | 
 |                                                SSL3_CK_SCSV & 0xffff)) { | 
 |       // The renegotiation SCSV was received so pretend that we received a | 
 |       // renegotiation extension. | 
 |       CBS_init(&fake_contents, kFakeRenegotiateExtension, | 
 |                sizeof(kFakeRenegotiateExtension)); | 
 |       contents = &fake_contents; | 
 |       hs->extensions.received |= (1u << i); | 
 |     } | 
 |  | 
 |     // Extension wasn't observed so call the callback with a NULL | 
 |     // parameter. | 
 |     uint8_t alert = SSL_AD_DECODE_ERROR; | 
 |     if (!kExtensions[i].parse_clienthello(hs, &alert, contents)) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION); | 
 |       ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value); | 
 |       *out_alert = alert; | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs, | 
 |                                   const SSL_CLIENT_HELLO *client_hello) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   int alert = SSL_AD_DECODE_ERROR; | 
 |   if (!ssl_scan_clienthello_tlsext(hs, client_hello, &alert)) { | 
 |     ssl_send_alert(ssl, SSL3_AL_FATAL, alert); | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (!ssl_check_clienthello_tlsext(hs)) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_TLSEXT); | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *cbs, | 
 |                                         int *out_alert) { | 
 |   CBS extensions = *cbs; | 
 |   if (!tls1_check_duplicate_extensions(&extensions)) { | 
 |     *out_alert = SSL_AD_DECODE_ERROR; | 
 |     return false; | 
 |   } | 
 |  | 
 |   uint32_t received = 0; | 
 |   while (CBS_len(&extensions) != 0) { | 
 |     uint16_t type; | 
 |     CBS extension; | 
 |  | 
 |     // Decode the next extension. | 
 |     if (!CBS_get_u16(&extensions, &type) || | 
 |         !CBS_get_u16_length_prefixed(&extensions, &extension)) { | 
 |       *out_alert = SSL_AD_DECODE_ERROR; | 
 |       return false; | 
 |     } | 
 |  | 
 |     unsigned ext_index; | 
 |     const struct tls_extension *const ext = | 
 |         tls_extension_find(&ext_index, type); | 
 |  | 
 |     if (ext == NULL) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); | 
 |       ERR_add_error_dataf("extension %u", (unsigned)type); | 
 |       *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; | 
 |       return false; | 
 |     } | 
 |  | 
 |     static_assert(kNumExtensions <= sizeof(hs->extensions.sent) * 8, | 
 |                   "too many bits"); | 
 |  | 
 |     if (!(hs->extensions.sent & (1u << ext_index))) { | 
 |       // If the extension was never sent then it is illegal. | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); | 
 |       ERR_add_error_dataf("extension :%u", (unsigned)type); | 
 |       *out_alert = SSL_AD_UNSUPPORTED_EXTENSION; | 
 |       return false; | 
 |     } | 
 |  | 
 |     received |= (1u << ext_index); | 
 |  | 
 |     uint8_t alert = SSL_AD_DECODE_ERROR; | 
 |     if (!ext->parse_serverhello(hs, &alert, &extension)) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); | 
 |       ERR_add_error_dataf("extension %u", (unsigned)type); | 
 |       *out_alert = alert; | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   for (size_t i = 0; i < kNumExtensions; i++) { | 
 |     if (!(received & (1u << i))) { | 
 |       // Extension wasn't observed so call the callback with a NULL | 
 |       // parameter. | 
 |       uint8_t alert = SSL_AD_DECODE_ERROR; | 
 |       if (!kExtensions[i].parse_serverhello(hs, &alert, NULL)) { | 
 |         OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION); | 
 |         ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value); | 
 |         *out_alert = alert; | 
 |         return false; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static bool ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   int ret = SSL_TLSEXT_ERR_NOACK; | 
 |   int al = SSL_AD_UNRECOGNIZED_NAME; | 
 |   if (ssl->ctx->servername_callback != 0) { | 
 |     ret = ssl->ctx->servername_callback(ssl, &al, ssl->ctx->servername_arg); | 
 |   } else if (ssl->session_ctx->servername_callback != 0) { | 
 |     ret = ssl->session_ctx->servername_callback( | 
 |         ssl, &al, ssl->session_ctx->servername_arg); | 
 |   } | 
 |  | 
 |   switch (ret) { | 
 |     case SSL_TLSEXT_ERR_ALERT_FATAL: | 
 |       ssl_send_alert(ssl, SSL3_AL_FATAL, al); | 
 |       return false; | 
 |  | 
 |     case SSL_TLSEXT_ERR_NOACK: | 
 |       hs->should_ack_sni = false; | 
 |       return true; | 
 |  | 
 |     default: | 
 |       return true; | 
 |   } | 
 | } | 
 |  | 
 | static bool ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   // ALPS and ALPN have a dependency between each other, so we defer checking | 
 |   // consistency to after the callbacks run. | 
 |   if (hs->new_session != nullptr && hs->new_session->has_application_settings) { | 
 |     // ALPN must be negotiated. | 
 |     if (ssl->s3->alpn_selected.empty()) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_ALPS_WITHOUT_ALPN); | 
 |       ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); | 
 |       return false; | 
 |     } | 
 |  | 
 |     // The negotiated protocol must be one of the ones we advertised for ALPS. | 
 |     Span<const uint8_t> settings; | 
 |     if (!ssl_get_local_application_settings(hs, &settings, | 
 |                                             ssl->s3->alpn_selected)) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL); | 
 |       ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER); | 
 |       return false; | 
 |     } | 
 |  | 
 |     if (!hs->new_session->local_application_settings.CopyFrom(settings)) { | 
 |       ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, const CBS *cbs) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   int alert = SSL_AD_DECODE_ERROR; | 
 |   if (!ssl_scan_serverhello_tlsext(hs, cbs, &alert)) { | 
 |     ssl_send_alert(ssl, SSL3_AL_FATAL, alert); | 
 |     return false; | 
 |   } | 
 |  | 
 |   if (!ssl_check_serverhello_tlsext(hs)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | static enum ssl_ticket_aead_result_t decrypt_ticket_with_cipher_ctx( | 
 |     Array<uint8_t> *out, EVP_CIPHER_CTX *cipher_ctx, HMAC_CTX *hmac_ctx, | 
 |     Span<const uint8_t> ticket) { | 
 |   size_t iv_len = EVP_CIPHER_CTX_iv_length(cipher_ctx); | 
 |  | 
 |   // Check the MAC at the end of the ticket. | 
 |   uint8_t mac[EVP_MAX_MD_SIZE]; | 
 |   size_t mac_len = HMAC_size(hmac_ctx); | 
 |   if (ticket.size() < SSL_TICKET_KEY_NAME_LEN + iv_len + 1 + mac_len) { | 
 |     // The ticket must be large enough for key name, IV, data, and MAC. | 
 |     return ssl_ticket_aead_ignore_ticket; | 
 |   } | 
 |   // Split the ticket into the ticket and the MAC. | 
 |   auto ticket_mac = ticket.last(mac_len); | 
 |   ticket = ticket.first(ticket.size() - mac_len); | 
 |   HMAC_Update(hmac_ctx, ticket.data(), ticket.size()); | 
 |   HMAC_Final(hmac_ctx, mac, NULL); | 
 |   assert(mac_len == ticket_mac.size()); | 
 |   bool mac_ok = CRYPTO_memcmp(mac, ticket_mac.data(), mac_len) == 0; | 
 | #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) | 
 |   mac_ok = true; | 
 | #endif | 
 |   if (!mac_ok) { | 
 |     return ssl_ticket_aead_ignore_ticket; | 
 |   } | 
 |  | 
 |   // Decrypt the session data. | 
 |   auto ciphertext = ticket.subspan(SSL_TICKET_KEY_NAME_LEN + iv_len); | 
 |   Array<uint8_t> plaintext; | 
 | #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) | 
 |   if (!plaintext.CopyFrom(ciphertext)) { | 
 |     return ssl_ticket_aead_error; | 
 |   } | 
 | #else | 
 |   if (ciphertext.size() >= INT_MAX) { | 
 |     return ssl_ticket_aead_ignore_ticket; | 
 |   } | 
 |   if (!plaintext.Init(ciphertext.size())) { | 
 |     return ssl_ticket_aead_error; | 
 |   } | 
 |   int len1, len2; | 
 |   if (!EVP_DecryptUpdate(cipher_ctx, plaintext.data(), &len1, ciphertext.data(), | 
 |                          (int)ciphertext.size()) || | 
 |       !EVP_DecryptFinal_ex(cipher_ctx, plaintext.data() + len1, &len2)) { | 
 |     ERR_clear_error(); | 
 |     return ssl_ticket_aead_ignore_ticket; | 
 |   } | 
 |   plaintext.Shrink(static_cast<size_t>(len1) + len2); | 
 | #endif | 
 |  | 
 |   *out = std::move(plaintext); | 
 |   return ssl_ticket_aead_success; | 
 | } | 
 |  | 
 | static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_cb( | 
 |     SSL_HANDSHAKE *hs, Array<uint8_t> *out, bool *out_renew_ticket, | 
 |     Span<const uint8_t> ticket) { | 
 |   assert(ticket.size() >= SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH); | 
 |   ScopedEVP_CIPHER_CTX cipher_ctx; | 
 |   ScopedHMAC_CTX hmac_ctx; | 
 |   auto name = ticket.subspan(0, SSL_TICKET_KEY_NAME_LEN); | 
 |   // The actual IV is shorter, but the length is determined by the callback's | 
 |   // chosen cipher. Instead we pass in |EVP_MAX_IV_LENGTH| worth of IV to ensure | 
 |   // the callback has enough. | 
 |   auto iv = ticket.subspan(SSL_TICKET_KEY_NAME_LEN, EVP_MAX_IV_LENGTH); | 
 |   int cb_ret = hs->ssl->session_ctx->ticket_key_cb( | 
 |       hs->ssl, const_cast<uint8_t *>(name.data()), | 
 |       const_cast<uint8_t *>(iv.data()), cipher_ctx.get(), hmac_ctx.get(), | 
 |       0 /* decrypt */); | 
 |   if (cb_ret < 0) { | 
 |     return ssl_ticket_aead_error; | 
 |   } else if (cb_ret == 0) { | 
 |     return ssl_ticket_aead_ignore_ticket; | 
 |   } else if (cb_ret == 2) { | 
 |     *out_renew_ticket = true; | 
 |   } else { | 
 |     assert(cb_ret == 1); | 
 |   } | 
 |   return decrypt_ticket_with_cipher_ctx(out, cipher_ctx.get(), hmac_ctx.get(), | 
 |                                         ticket); | 
 | } | 
 |  | 
 | static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_ticket_keys( | 
 |     SSL_HANDSHAKE *hs, Array<uint8_t> *out, Span<const uint8_t> ticket) { | 
 |   assert(ticket.size() >= SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH); | 
 |   SSL_CTX *ctx = hs->ssl->session_ctx.get(); | 
 |  | 
 |   // Rotate the ticket key if necessary. | 
 |   if (!ssl_ctx_rotate_ticket_encryption_key(ctx)) { | 
 |     return ssl_ticket_aead_error; | 
 |   } | 
 |  | 
 |   const EVP_CIPHER *cipher = EVP_aes_128_cbc(); | 
 |   auto name = ticket.subspan(0, SSL_TICKET_KEY_NAME_LEN); | 
 |   auto iv = | 
 |       ticket.subspan(SSL_TICKET_KEY_NAME_LEN, EVP_CIPHER_iv_length(cipher)); | 
 |  | 
 |   // Pick the matching ticket key and decrypt. | 
 |   ScopedEVP_CIPHER_CTX cipher_ctx; | 
 |   ScopedHMAC_CTX hmac_ctx; | 
 |   { | 
 |     MutexReadLock lock(&ctx->lock); | 
 |     const TicketKey *key; | 
 |     if (ctx->ticket_key_current && name == ctx->ticket_key_current->name) { | 
 |       key = ctx->ticket_key_current.get(); | 
 |     } else if (ctx->ticket_key_prev && name == ctx->ticket_key_prev->name) { | 
 |       key = ctx->ticket_key_prev.get(); | 
 |     } else { | 
 |       return ssl_ticket_aead_ignore_ticket; | 
 |     } | 
 |     if (!HMAC_Init_ex(hmac_ctx.get(), key->hmac_key, sizeof(key->hmac_key), | 
 |                       tlsext_tick_md(), NULL) || | 
 |         !EVP_DecryptInit_ex(cipher_ctx.get(), cipher, NULL, | 
 |                             key->aes_key, iv.data())) { | 
 |       return ssl_ticket_aead_error; | 
 |     } | 
 |   } | 
 |   return decrypt_ticket_with_cipher_ctx(out, cipher_ctx.get(), hmac_ctx.get(), | 
 |                                         ticket); | 
 | } | 
 |  | 
 | static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_method( | 
 |     SSL_HANDSHAKE *hs, Array<uint8_t> *out, bool *out_renew_ticket, | 
 |     Span<const uint8_t> ticket) { | 
 |   Array<uint8_t> plaintext; | 
 |   if (!plaintext.Init(ticket.size())) { | 
 |     return ssl_ticket_aead_error; | 
 |   } | 
 |  | 
 |   size_t plaintext_len; | 
 |   const enum ssl_ticket_aead_result_t result = | 
 |       hs->ssl->session_ctx->ticket_aead_method->open( | 
 |           hs->ssl, plaintext.data(), &plaintext_len, ticket.size(), | 
 |           ticket.data(), ticket.size()); | 
 |   if (result != ssl_ticket_aead_success) { | 
 |     return result; | 
 |   } | 
 |  | 
 |   plaintext.Shrink(plaintext_len); | 
 |   *out = std::move(plaintext); | 
 |   return ssl_ticket_aead_success; | 
 | } | 
 |  | 
 | enum ssl_ticket_aead_result_t ssl_process_ticket( | 
 |     SSL_HANDSHAKE *hs, UniquePtr<SSL_SESSION> *out_session, | 
 |     bool *out_renew_ticket, Span<const uint8_t> ticket, | 
 |     Span<const uint8_t> session_id) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   *out_renew_ticket = false; | 
 |   out_session->reset(); | 
 |  | 
 |   if ((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) || | 
 |       session_id.size() > SSL_MAX_SSL_SESSION_ID_LENGTH) { | 
 |     return ssl_ticket_aead_ignore_ticket; | 
 |   } | 
 |  | 
 |   // Tickets in TLS 1.3 are tied into pre-shared keys (PSKs), unlike in TLS 1.2 | 
 |   // where that concept doesn't exist. The |decrypted_psk| and |ignore_psk| | 
 |   // hints only apply to PSKs. We check the version to determine which this is. | 
 |   const bool is_psk = ssl_protocol_version(ssl) >= TLS1_3_VERSION; | 
 |  | 
 |   Array<uint8_t> plaintext; | 
 |   enum ssl_ticket_aead_result_t result; | 
 |   SSL_HANDSHAKE_HINTS *const hints = hs->hints.get(); | 
 |   if (is_psk && hints && !hs->hints_requested && | 
 |       !hints->decrypted_psk.empty()) { | 
 |     result = plaintext.CopyFrom(hints->decrypted_psk) ? ssl_ticket_aead_success | 
 |                                                       : ssl_ticket_aead_error; | 
 |   } else if (is_psk && hints && !hs->hints_requested && hints->ignore_psk) { | 
 |     result = ssl_ticket_aead_ignore_ticket; | 
 |   } else if (!is_psk && hints && !hs->hints_requested && | 
 |              !hints->decrypted_ticket.empty()) { | 
 |     if (plaintext.CopyFrom(hints->decrypted_ticket)) { | 
 |       result = ssl_ticket_aead_success; | 
 |       *out_renew_ticket = hints->renew_ticket; | 
 |     } else { | 
 |       result = ssl_ticket_aead_error; | 
 |     } | 
 |   } else if (!is_psk && hints && !hs->hints_requested && hints->ignore_ticket) { | 
 |     result = ssl_ticket_aead_ignore_ticket; | 
 |   } else if (ssl->session_ctx->ticket_aead_method != NULL) { | 
 |     result = ssl_decrypt_ticket_with_method(hs, &plaintext, out_renew_ticket, | 
 |                                             ticket); | 
 |   } else { | 
 |     // Ensure there is room for the key name and the largest IV |ticket_key_cb| | 
 |     // may try to consume. The real limit may be lower, but the maximum IV | 
 |     // length should be well under the minimum size for the session material and | 
 |     // HMAC. | 
 |     if (ticket.size() < SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH) { | 
 |       result = ssl_ticket_aead_ignore_ticket; | 
 |     } else if (ssl->session_ctx->ticket_key_cb != NULL) { | 
 |       result = | 
 |           ssl_decrypt_ticket_with_cb(hs, &plaintext, out_renew_ticket, ticket); | 
 |     } else { | 
 |       result = ssl_decrypt_ticket_with_ticket_keys(hs, &plaintext, ticket); | 
 |     } | 
 |   } | 
 |  | 
 |   if (hints && hs->hints_requested) { | 
 |     if (result == ssl_ticket_aead_ignore_ticket) { | 
 |       if (is_psk) { | 
 |         hints->ignore_psk = true; | 
 |       } else { | 
 |         hints->ignore_ticket = true; | 
 |       } | 
 |     } else if (result == ssl_ticket_aead_success) { | 
 |       if (is_psk) { | 
 |         if (!hints->decrypted_psk.CopyFrom(plaintext)) { | 
 |           return ssl_ticket_aead_error; | 
 |         } | 
 |       } else { | 
 |         if (!hints->decrypted_ticket.CopyFrom(plaintext)) { | 
 |           return ssl_ticket_aead_error; | 
 |         } | 
 |         hints->renew_ticket = *out_renew_ticket; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   if (result != ssl_ticket_aead_success) { | 
 |     return result; | 
 |   } | 
 |  | 
 |   // Decode the session. | 
 |   UniquePtr<SSL_SESSION> session(SSL_SESSION_from_bytes( | 
 |       plaintext.data(), plaintext.size(), ssl->ctx.get())); | 
 |   if (!session) { | 
 |     ERR_clear_error();  // Don't leave an error on the queue. | 
 |     return ssl_ticket_aead_ignore_ticket; | 
 |   } | 
 |  | 
 |   // Envoy's tests expect the session to have a session ID that matches the | 
 |   // placeholder used by the client. It's unclear whether this is a good idea, | 
 |   // but we maintain it for now. | 
 |   SHA256(ticket.data(), ticket.size(), session->session_id); | 
 |   // Other consumers may expect a non-empty session ID to indicate resumption. | 
 |   session->session_id_length = SHA256_DIGEST_LENGTH; | 
 |  | 
 |   *out_session = std::move(session); | 
 |   return ssl_ticket_aead_success; | 
 | } | 
 |  | 
 | bool tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *in_sigalgs) { | 
 |   // Extension ignored for inappropriate versions | 
 |   if (ssl_protocol_version(hs->ssl) < TLS1_2_VERSION) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   // In all contexts, the signature algorithms list may not be empty. (It may be | 
 |   // omitted by clients in TLS 1.2, but then the entire extension is omitted.) | 
 |   return CBS_len(in_sigalgs) != 0 && | 
 |          parse_u16_array(in_sigalgs, &hs->peer_sigalgs); | 
 | } | 
 |  | 
 | bool tls1_get_legacy_signature_algorithm(uint16_t *out, const EVP_PKEY *pkey) { | 
 |   switch (EVP_PKEY_id(pkey)) { | 
 |     case EVP_PKEY_RSA: | 
 |       *out = SSL_SIGN_RSA_PKCS1_MD5_SHA1; | 
 |       return true; | 
 |     case EVP_PKEY_EC: | 
 |       *out = SSL_SIGN_ECDSA_SHA1; | 
 |       return true; | 
 |     default: | 
 |       return false; | 
 |   } | 
 | } | 
 |  | 
 | bool tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   CERT *cert = hs->config->cert.get(); | 
 |   DC *dc = cert->dc.get(); | 
 |  | 
 |   // Before TLS 1.2, the signature algorithm isn't negotiated as part of the | 
 |   // handshake. | 
 |   if (ssl_protocol_version(ssl) < TLS1_2_VERSION) { | 
 |     if (!tls1_get_legacy_signature_algorithm(out, hs->local_pubkey.get())) { | 
 |       OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS); | 
 |       return false; | 
 |     } | 
 |     return true; | 
 |   } | 
 |  | 
 |   Span<const uint16_t> sigalgs = kSignSignatureAlgorithms; | 
 |   if (ssl_signing_with_dc(hs)) { | 
 |     sigalgs = MakeConstSpan(&dc->expected_cert_verify_algorithm, 1); | 
 |   } else if (!cert->sigalgs.empty()) { | 
 |     sigalgs = cert->sigalgs; | 
 |   } | 
 |  | 
 |   Span<const uint16_t> peer_sigalgs = tls1_get_peer_verify_algorithms(hs); | 
 |  | 
 |   for (uint16_t sigalg : sigalgs) { | 
 |     if (!ssl_private_key_supports_signature_algorithm(hs, sigalg)) { | 
 |       continue; | 
 |     } | 
 |  | 
 |     for (uint16_t peer_sigalg : peer_sigalgs) { | 
 |       if (sigalg == peer_sigalg) { | 
 |         *out = sigalg; | 
 |         return true; | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS); | 
 |   return false; | 
 | } | 
 |  | 
 | Span<const uint16_t> tls1_get_peer_verify_algorithms(const SSL_HANDSHAKE *hs) { | 
 |   Span<const uint16_t> peer_sigalgs = hs->peer_sigalgs; | 
 |   if (peer_sigalgs.empty() && ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) { | 
 |     // If the client didn't specify any signature_algorithms extension then | 
 |     // we can assume that it supports SHA1. See | 
 |     // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 | 
 |     static const uint16_t kDefaultPeerAlgorithms[] = {SSL_SIGN_RSA_PKCS1_SHA1, | 
 |                                                       SSL_SIGN_ECDSA_SHA1}; | 
 |     peer_sigalgs = kDefaultPeerAlgorithms; | 
 |   } | 
 |   return peer_sigalgs; | 
 | } | 
 |  | 
 | bool tls1_verify_channel_id(SSL_HANDSHAKE *hs, const SSLMessage &msg) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   // A Channel ID handshake message is structured to contain multiple | 
 |   // extensions, but the only one that can be present is Channel ID. | 
 |   uint16_t extension_type; | 
 |   CBS channel_id = msg.body, extension; | 
 |   if (!CBS_get_u16(&channel_id, &extension_type) || | 
 |       !CBS_get_u16_length_prefixed(&channel_id, &extension) || | 
 |       CBS_len(&channel_id) != 0 || | 
 |       extension_type != TLSEXT_TYPE_channel_id || | 
 |       CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | 
 |     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | 
 |     return false; | 
 |   } | 
 |  | 
 |   const EC_GROUP *p256 = EC_group_p256(); | 
 |   UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new()); | 
 |   UniquePtr<BIGNUM> x(BN_new()), y(BN_new()); | 
 |   if (!sig || !x || !y) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   const uint8_t *p = CBS_data(&extension); | 
 |   if (BN_bin2bn(p + 0, 32, x.get()) == NULL || | 
 |       BN_bin2bn(p + 32, 32, y.get()) == NULL || | 
 |       BN_bin2bn(p + 64, 32, sig->r) == NULL || | 
 |       BN_bin2bn(p + 96, 32, sig->s) == NULL) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   UniquePtr<EC_KEY> key(EC_KEY_new()); | 
 |   UniquePtr<EC_POINT> point(EC_POINT_new(p256)); | 
 |   if (!key || !point || | 
 |       !EC_POINT_set_affine_coordinates_GFp(p256, point.get(), x.get(), y.get(), | 
 |                                            nullptr) || | 
 |       !EC_KEY_set_group(key.get(), p256) || | 
 |       !EC_KEY_set_public_key(key.get(), point.get())) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   uint8_t digest[EVP_MAX_MD_SIZE]; | 
 |   size_t digest_len; | 
 |   if (!tls1_channel_id_hash(hs, digest, &digest_len)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   bool sig_ok = ECDSA_do_verify(digest, digest_len, sig.get(), key.get()); | 
 | #if defined(BORINGSSL_UNSAFE_FUZZER_MODE) | 
 |   sig_ok = true; | 
 |   ERR_clear_error(); | 
 | #endif | 
 |   if (!sig_ok) { | 
 |     OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID); | 
 |     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR); | 
 |     return false; | 
 |   } | 
 |  | 
 |   OPENSSL_memcpy(ssl->s3->channel_id, p, 64); | 
 |   ssl->s3->channel_id_valid = true; | 
 |   return true; | 
 | } | 
 |  | 
 | bool tls1_write_channel_id(SSL_HANDSHAKE *hs, CBB *cbb) { | 
 |   uint8_t digest[EVP_MAX_MD_SIZE]; | 
 |   size_t digest_len; | 
 |   if (!tls1_channel_id_hash(hs, digest, &digest_len)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(hs->config->channel_id_private.get()); | 
 |   if (ec_key == nullptr) { | 
 |     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | 
 |     return false; | 
 |   } | 
 |  | 
 |   UniquePtr<BIGNUM> x(BN_new()), y(BN_new()); | 
 |   if (!x || !y || | 
 |       !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key), | 
 |                                            EC_KEY_get0_public_key(ec_key), | 
 |                                            x.get(), y.get(), nullptr)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   UniquePtr<ECDSA_SIG> sig(ECDSA_do_sign(digest, digest_len, ec_key)); | 
 |   if (!sig) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   CBB child; | 
 |   if (!CBB_add_u16(cbb, TLSEXT_TYPE_channel_id) || | 
 |       !CBB_add_u16_length_prefixed(cbb, &child) || | 
 |       !BN_bn2cbb_padded(&child, 32, x.get()) || | 
 |       !BN_bn2cbb_padded(&child, 32, y.get()) || | 
 |       !BN_bn2cbb_padded(&child, 32, sig->r) || | 
 |       !BN_bn2cbb_padded(&child, 32, sig->s) || | 
 |       !CBB_flush(cbb)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | bool tls1_channel_id_hash(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | 
 |     Array<uint8_t> msg; | 
 |     if (!tls13_get_cert_verify_signature_input(hs, &msg, | 
 |                                                ssl_cert_verify_channel_id)) { | 
 |       return false; | 
 |     } | 
 |     SHA256(msg.data(), msg.size(), out); | 
 |     *out_len = SHA256_DIGEST_LENGTH; | 
 |     return true; | 
 |   } | 
 |  | 
 |   SHA256_CTX ctx; | 
 |  | 
 |   SHA256_Init(&ctx); | 
 |   static const char kClientIDMagic[] = "TLS Channel ID signature"; | 
 |   SHA256_Update(&ctx, kClientIDMagic, sizeof(kClientIDMagic)); | 
 |  | 
 |   if (ssl->session != NULL) { | 
 |     static const char kResumptionMagic[] = "Resumption"; | 
 |     SHA256_Update(&ctx, kResumptionMagic, sizeof(kResumptionMagic)); | 
 |     if (ssl->session->original_handshake_hash_len == 0) { | 
 |       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | 
 |       return false; | 
 |     } | 
 |     SHA256_Update(&ctx, ssl->session->original_handshake_hash, | 
 |                   ssl->session->original_handshake_hash_len); | 
 |   } | 
 |  | 
 |   uint8_t hs_hash[EVP_MAX_MD_SIZE]; | 
 |   size_t hs_hash_len; | 
 |   if (!hs->transcript.GetHash(hs_hash, &hs_hash_len)) { | 
 |     return false; | 
 |   } | 
 |   SHA256_Update(&ctx, hs_hash, (size_t)hs_hash_len); | 
 |   SHA256_Final(out, &ctx); | 
 |   *out_len = SHA256_DIGEST_LENGTH; | 
 |   return true; | 
 | } | 
 |  | 
 | bool tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs) { | 
 |   SSL *const ssl = hs->ssl; | 
 |   // This function should never be called for a resumed session because the | 
 |   // handshake hashes that we wish to record are for the original, full | 
 |   // handshake. | 
 |   if (ssl->session != NULL) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   static_assert( | 
 |       sizeof(hs->new_session->original_handshake_hash) == EVP_MAX_MD_SIZE, | 
 |       "original_handshake_hash is too small"); | 
 |  | 
 |   size_t digest_len; | 
 |   if (!hs->transcript.GetHash(hs->new_session->original_handshake_hash, | 
 |                               &digest_len)) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   static_assert(EVP_MAX_MD_SIZE <= 0xff, | 
 |                 "EVP_MAX_MD_SIZE does not fit in uint8_t"); | 
 |   hs->new_session->original_handshake_hash_len = (uint8_t)digest_len; | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | bool ssl_is_sct_list_valid(const CBS *contents) { | 
 |   // Shallow parse the SCT list for sanity. By the RFC | 
 |   // (https://tools.ietf.org/html/rfc6962#section-3.3) neither the list nor any | 
 |   // of the SCTs may be empty. | 
 |   CBS copy = *contents; | 
 |   CBS sct_list; | 
 |   if (!CBS_get_u16_length_prefixed(©, &sct_list) || | 
 |       CBS_len(©) != 0 || | 
 |       CBS_len(&sct_list) == 0) { | 
 |     return false; | 
 |   } | 
 |  | 
 |   while (CBS_len(&sct_list) > 0) { | 
 |     CBS sct; | 
 |     if (!CBS_get_u16_length_prefixed(&sct_list, &sct) || | 
 |         CBS_len(&sct) == 0) { | 
 |       return false; | 
 |     } | 
 |   } | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | BSSL_NAMESPACE_END | 
 |  | 
 | using namespace bssl; | 
 |  | 
 | int SSL_early_callback_ctx_extension_get(const SSL_CLIENT_HELLO *client_hello, | 
 |                                          uint16_t extension_type, | 
 |                                          const uint8_t **out_data, | 
 |                                          size_t *out_len) { | 
 |   CBS cbs; | 
 |   if (!ssl_client_hello_get_extension(client_hello, &cbs, extension_type)) { | 
 |     return 0; | 
 |   } | 
 |  | 
 |   *out_data = CBS_data(&cbs); | 
 |   *out_len = CBS_len(&cbs); | 
 |   return 1; | 
 | } |