/* * TLS Client Hello Messages * (C) 2004-2011,2015,2016 Jack Lloyd * 2021 Elektrobit Automotive GmbH * 2022 René Meusel, Hannes Rantzsch - neXenio GmbH * 2026 René Meusel - Rohde & Schwarz Cybersecurity GmbH * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include #include #include #include #include #include #include #include #include #include #if defined(BOTAN_HAS_TLS_12) #include #endif namespace Botan::TLS { Client_Hello_13::Client_Hello_13(std::unique_ptr data) : Client_Hello(std::move(data)) { const auto& exts = m_data->extensions(); // RFC 8446 4.1.2 // TLS 1.3 ClientHellos are identified as having a legacy_version of // 0x0303 and a "supported_versions" extension present with 0x0304 as the // highest version indicated therein. // // Note that we already checked for "supported_versions" before entering this // c'tor in `Client_Hello_13::parse()`. This is just to be doubly sure. BOTAN_ASSERT_NOMSG(exts.has()); // RFC 8446 4.2.1 // Servers MAY abort the handshake upon receiving a ClientHello with // legacy_version 0x0304 or later. if(m_data->legacy_version().is_tls_13_or_later()) { throw TLS_Exception(Alert::DecodeError, "TLS 1.3 Client Hello has invalid legacy_version"); } // RFC 8446 D.5 // Any endpoint receiving a Hello message with ClientHello.legacy_version [...] // set to 0x0300 MUST abort the handshake with a "protocol_version" alert. if(m_data->legacy_version().major_version() == 3 && m_data->legacy_version().minor_version() == 0) { throw TLS_Exception(Alert::ProtocolVersion, "TLS 1.3 Client Hello has invalid legacy_version"); } // RFC 8446 4.1.2 // For every TLS 1.3 ClientHello, [the compression method] MUST contain // exactly one byte, set to zero, [...]. If a TLS 1.3 ClientHello is // received with any other value in this field, the server MUST abort the // handshake with an "illegal_parameter" alert. if(m_data->comp_methods().size() != 1 || m_data->comp_methods().front() != 0) { throw TLS_Exception(Alert::IllegalParameter, "Client did not offer NULL compression"); } // RFC 8446 4.2.9 // A client MUST provide a "psk_key_exchange_modes" extension if it // offers a "pre_shared_key" extension. If clients offer "pre_shared_key" // without a "psk_key_exchange_modes" extension, servers MUST abort // the handshake. if(exts.has()) { if(!exts.has()) { throw TLS_Exception(Alert::MissingExtension, "Client Hello offered a PSK without a psk_key_exchange_modes extension"); } // RFC 8446 4.2.11 // The "pre_shared_key" extension MUST be the last extension in the // ClientHello [...]. Servers MUST check that it is the last extension // and otherwise fail the handshake with an "illegal_parameter" alert. if(exts.all().back()->type() != Extension_Code::PresharedKey) { throw TLS_Exception(Alert::IllegalParameter, "PSK extension was not at the very end of the Client Hello"); } } // RFC 8446 9.2 // [A TLS 1.3 ClientHello] message MUST meet the following requirements: // // - If not containing a "pre_shared_key" extension, it MUST contain // both a "signature_algorithms" extension and a "supported_groups" // extension. // // - If containing a "supported_groups" extension, it MUST also contain // a "key_share" extension, and vice versa. An empty // KeyShare.client_shares vector is permitted. // // Servers receiving a ClientHello which does not conform to these // requirements MUST abort the handshake with a "missing_extension" // alert. if(!exts.has()) { if(!exts.has() || !exts.has()) { throw TLS_Exception( Alert::MissingExtension, "Non-PSK Client Hello did not contain supported_groups and signature_algorithms extensions"); } } if(exts.has() != exts.has()) { throw TLS_Exception(Alert::MissingExtension, "Client Hello must either contain both key_share and supported_groups extensions or neither"); } if(exts.has()) { auto* const supported_ext = exts.get(); BOTAN_ASSERT_NONNULL(supported_ext); const auto supports = supported_ext->groups(); const auto offers = exts.get()->offered_groups(); // RFC 8446 4.2.8 // Each KeyShareEntry value MUST correspond to a group offered in the // "supported_groups" extension and MUST appear in the same order. // [...] // Clients MUST NOT offer any KeyShareEntry values for groups not // listed in the client's "supported_groups" extension. // // Note: We can assume that both `offers` and `supports` are unique lists // as this is ensured in the parsing code of the extensions. auto found_in_supported_groups = [&supports, support_offset = -1](auto group) mutable { const auto i = std::find(supports.begin(), supports.end(), group); if(i == supports.end()) { return false; } const auto found_at = std::distance(supports.begin(), i); if(found_at <= support_offset) { return false; // The order that groups appear in "key_share" and // "supported_groups" must be the same } support_offset = static_cast(found_at); return true; }; for(const auto offered : offers) { // RFC 8446 4.2.8 // Servers MAY check for violations of these rules and abort the // handshake with an "illegal_parameter" alert if one is violated. if(!found_in_supported_groups(offered)) { throw TLS_Exception(Alert::IllegalParameter, "Offered key exchange groups do not align with claimed supported groups"); } } } // TODO: Reject oid_filters extension if found (which is the only known extension that // must not occur in the TLS 1.3 client hello. // RFC 8446 4.2.5 // [The oid_filters extension] MUST only be sent in the CertificateRequest message. } /* * Create a new Client Hello message */ Client_Hello_13::Client_Hello_13(const Policy& policy, Callbacks& cb, RandomNumberGenerator& rng, std::string_view hostname, const std::vector& next_protocols, std::optional& session, std::vector psks) { // RFC 8446 4.1.2 // In TLS 1.3, the client indicates its version preferences in the // "supported_versions" extension (Section 4.2.1) and the // legacy_version field MUST be set to 0x0303, which is the version // number for TLS 1.2. m_data->m_legacy_version = Protocol_Version::TLS_V12; m_data->m_random = make_hello_random(rng, cb, policy); m_data->m_suites = policy.ciphersuite_list(Protocol_Version::TLS_V13); if(policy.allow_tls12()) { // Note: DTLS 1.3 is NYI, hence dtls_12 is not checked const auto legacy_suites = policy.ciphersuite_list(Protocol_Version::TLS_V12); m_data->m_suites.insert(m_data->m_suites.end(), legacy_suites.cbegin(), legacy_suites.cend()); } if(policy.tls_13_middlebox_compatibility_mode()) { // RFC 8446 4.1.2 // In compatibility mode (see Appendix D.4), this field MUST be non-empty, // so a client not offering a pre-TLS 1.3 session MUST generate a new // 32-byte value. // // Note: we won't ever offer a TLS 1.2 session. In such a case we would // have instantiated a TLS 1.2 client in the first place. m_data->m_session_id = Session_ID(make_hello_random(rng, cb, policy)); } // NOLINTBEGIN(*-owning-memory) if(Server_Name_Indicator::hostname_acceptable_for_sni(hostname)) { m_data->extensions().add(new Server_Name_Indicator(hostname)); } m_data->extensions().add(new Supported_Groups(policy.key_exchange_groups())); m_data->extensions().add(new Key_Share(policy, cb, rng)); m_data->extensions().add(new Supported_Versions(Protocol_Version::TLS_V13, policy)); m_data->extensions().add(new Signature_Algorithms(policy.acceptable_signature_schemes())); if(auto cert_signing_prefs = policy.acceptable_certificate_signature_schemes()) { // RFC 8446 4.2.3 // Implementations which have the same policy in both cases MAY omit // the "signature_algorithms_cert" extension. m_data->extensions().add(new Signature_Algorithms_Cert(std::move(cert_signing_prefs.value()))); } // TODO: Support for PSK-only mode without a key exchange. // This should be configurable in TLS::Policy and should allow no PSK // support at all (e.g. to disable support for session resumption). m_data->extensions().add(new PSK_Key_Exchange_Modes({PSK_Key_Exchange_Mode::PSK_DHE_KE})); if(policy.support_cert_status_message()) { m_data->extensions().add(new Certificate_Status_Request({}, {})); } // We currently support "record_size_limit" for TLS 1.3 exclusively. Hence, // when TLS 1.2 is advertised as a supported protocol, we must not offer this // extension. if(policy.record_size_limit().has_value() && !policy.allow_tls12()) { m_data->extensions().add(new Record_Size_Limit(policy.record_size_limit().value())); } if(!next_protocols.empty()) { m_data->extensions().add(new Application_Layer_Protocol_Notification(next_protocols)); } // RFC 7250 4.1 // In order to indicate the support of raw public keys, clients include // the client_certificate_type and/or the server_certificate_type // extensions in an extended client hello message. m_data->extensions().add(new Client_Certificate_Type(policy.accepted_client_certificate_types())); m_data->extensions().add(new Server_Certificate_Type(policy.accepted_server_certificate_types())); #if defined(BOTAN_HAS_TLS_12) if(policy.allow_tls12()) { m_data->extensions().add(new Renegotiation_Extension()); m_data->extensions().add(new Session_Ticket_Extension()); // EMS must always be used with TLS 1.2, regardless of the policy m_data->extensions().add(new Extended_Master_Secret); if(policy.negotiate_encrypt_then_mac()) { m_data->extensions().add(new Encrypt_then_MAC); } if(m_data->extensions().has() && !m_data->extensions().get()->ec_groups().empty()) { m_data->extensions().add(new Supported_Point_Formats(policy.use_ecc_point_compression())); } } #endif if(session.has_value() || !psks.empty()) { m_data->extensions().add(new PSK(session, std::move(psks), cb)); } // NOLINTEND(*-owning-memory) cb.tls_modify_extensions(m_data->extensions(), Connection_Side::Client, type()); if(m_data->extensions().has()) { // RFC 8446 4.2.11 // The "pre_shared_key" extension MUST be the last extension in the // ClientHello (this facilitates implementation [...]). if(m_data->extensions().all().back()->type() != Extension_Code::PresharedKey) { throw TLS_Exception(Alert::InternalError, "Application modified extensions of Client Hello, PSK is not last anymore"); } calculate_psk_binders({}); } } std::variant Client_Hello_13::parse(const std::vector& buf) { auto data = std::make_unique(buf); const auto version = data->version(); if(version.is_pre_tls_13()) { return Client_Hello_12_Shim(std::move(data)); } else { return Client_Hello_13(std::move(data)); } } void Client_Hello_13::retry(const Hello_Retry_Request& hrr, const Transcript_Hash_State& transcript_hash_state, Callbacks& cb, RandomNumberGenerator& rng) { BOTAN_STATE_CHECK(m_data->extensions().has()); BOTAN_STATE_CHECK(m_data->extensions().has()); auto* hrr_ks = hrr.extensions().get(); const auto& supported_groups = m_data->extensions().get()->groups(); if(hrr.extensions().has()) { m_data->extensions().get()->retry_offer(*hrr_ks, supported_groups, cb, rng); } // RFC 8446 4.2.2 // When sending the new ClientHello, the client MUST copy // the contents of the extension received in the HelloRetryRequest into // a "cookie" extension in the new ClientHello. // // RFC 8446 4.2.2 // Clients MUST NOT use cookies in their initial ClientHello in subsequent // connections. if(hrr.extensions().has()) { BOTAN_STATE_CHECK(!m_data->extensions().has()); m_data->extensions().add(new Cookie(hrr.extensions().get()->get_cookie())); // NOLINT(*-owning-memory) } // Note: the consumer of the TLS implementation won't be able to distinguish // invocations to this callback due to the first Client_Hello or the // retried Client_Hello after receiving a Hello_Retry_Request. We assume // that the user keeps and detects this state themselves. cb.tls_modify_extensions(m_data->extensions(), Connection_Side::Client, type()); auto* psk = m_data->extensions().get(); if(psk != nullptr) { // Cipher suite should always be a known suite as this is checked upstream const auto cipher = Ciphersuite::by_id(hrr.ciphersuite()); BOTAN_ASSERT_NOMSG(cipher.has_value()); // RFC 8446 4.1.4 // In [...] its updated ClientHello, the client SHOULD NOT offer // any pre-shared keys associated with a hash other than that of the // selected cipher suite. psk->filter(cipher.value()); // RFC 8446 4.2.11.2 // If the server responds with a HelloRetryRequest and the client // then sends ClientHello2, its binder will be computed over: [...]. calculate_psk_binders(transcript_hash_state.clone()); } } void Client_Hello_13::validate_updates(const Client_Hello_13& new_ch) { // RFC 8446 4.1.2 // The client will also send a ClientHello when the server has responded // to its ClientHello with a HelloRetryRequest. In that case, the client // MUST send the same ClientHello without modification, except as follows: if(m_data->session_id() != new_ch.m_data->session_id() || m_data->random() != new_ch.m_data->random() || m_data->ciphersuites() != new_ch.m_data->ciphersuites() || m_data->comp_methods() != new_ch.m_data->comp_methods()) { throw TLS_Exception(Alert::IllegalParameter, "Client Hello core values changed after Hello Retry Request"); } const auto oldexts = extension_types(); const auto newexts = new_ch.extension_types(); // Check that extension omissions are justified for(const auto oldext : oldexts) { if(!newexts.contains(oldext)) { auto* const ext = extensions().get(oldext); // We don't make any assumptions about unimplemented extensions. if(!ext->is_implemented()) { continue; } // RFC 8446 4.1.2 // Removing the "early_data" extension (Section 4.2.10) if one was // present. Early data is not permitted after a HelloRetryRequest. if(oldext == EarlyDataIndication::static_type()) { continue; } // RFC 8446 4.1.2 // Optionally adding, removing, or changing the length of the // "padding" extension. // // TODO: implement the Padding extension // if(oldext == Padding::static_type()) // continue; throw TLS_Exception(Alert::IllegalParameter, "Extension removed in updated Client Hello"); } } // Check that extension additions are justified for(const auto newext : newexts) { if(!oldexts.contains(newext)) { auto* const ext = new_ch.extensions().get(newext); // We don't make any assumptions about unimplemented extensions. if(!ext->is_implemented()) { continue; } // RFC 8446 4.1.2 // Including a "cookie" extension if one was provided in the // HelloRetryRequest. if(newext == Cookie::static_type()) { continue; } // RFC 8446 4.1.2 // Optionally adding, removing, or changing the length of the // "padding" extension. // // TODO: implement the Padding extension // if(newext == Padding::static_type()) // continue; throw TLS_Exception(Alert::UnsupportedExtension, "Added an extension in updated Client Hello"); } } // RFC 8446 4.1.2 // Removing the "early_data" extension (Section 4.2.10) if one was // present. Early data is not permitted after a HelloRetryRequest. if(new_ch.extensions().has()) { throw TLS_Exception(Alert::IllegalParameter, "Updated Client Hello indicates early data"); } // TODO: Contents of extensions are not checked for update compatibility, see: // // RFC 8446 4.1.2 // If a "key_share" extension was supplied in the HelloRetryRequest, // replacing the list of shares with a list containing a single // KeyShareEntry from the indicated group. // // Updating the "pre_shared_key" extension if present by recomputing // the "obfuscated_ticket_age" and binder values and (optionally) // removing any PSKs which are incompatible with the server's // indicated cipher suite. // // Optionally adding, removing, or changing the length of the // "padding" extension. } void Client_Hello_13::calculate_psk_binders(Transcript_Hash_State transcript_hash) { auto* psk = m_data->extensions().get(); if(psk == nullptr || psk->empty()) { return; } // RFC 8446 4.2.11.2 // Each entry in the binders list is computed as an HMAC over a // transcript hash (see Section 4.4.1) containing a partial ClientHello // [...]. // // Therefore we marshal the entire message prematurely to obtain the // (truncated) transcript hash, calculate the PSK binders with it, update // the Client Hello thus finalizing the message. Down the road, it will be // re-marshalled with the correct binders and sent over the wire. Handshake_Layer::prepare_message(*this, transcript_hash); psk->calculate_binders(transcript_hash); } std::optional Client_Hello_13::highest_supported_version(const Policy& policy) const { // RFC 8446 4.2.1 // The "supported_versions" extension is used by the client to indicate // which versions of TLS it supports and by the server to indicate which // version it is using. The extension contains a list of supported // versions in preference order, with the most preferred version first. auto* const supvers = m_data->extensions().get(); BOTAN_ASSERT_NONNULL(supvers); std::optional result; for(const auto& v : supvers->versions()) { // RFC 8446 4.2.1 // Servers MUST only select a version of TLS present in that extension // and MUST ignore any unknown versions that are present in that // extension. if(!v.known_version() || !policy.acceptable_protocol_version(v)) { continue; } result = (result.has_value()) ? std::optional(std::max(result.value(), v)) : std::optional(v); } return result; } } // namespace Botan::TLS