Botan 3.12.0
Crypto and TLS for C&
Botan::TLS::Client_Hello_13 Class Referencefinal

#include <tls_messages_13.h>

Inheritance diagram for Botan::TLS::Client_Hello_13:
Botan::TLS::Client_Hello Botan::TLS::Handshake_Message

Public Member Functions

std::vector< Signature_Schemecertificate_signature_schemes () const
const std::vector< uint16_t > & ciphersuites () const
 Client_Hello_13 (const Policy &policy, Callbacks &cb, RandomNumberGenerator &rng, std::string_view hostname, const std::vector< std::string > &next_protocols, std::optional< Session_with_Handle > &session, std::vector< ExternalPSK > psks)
const std::vector< uint8_t > & cookie () const
std::vector< uint8_t > cookie_input_data () const
std::set< Extension_Codeextension_types () const
const Extensionsextensions () const
std::optional< Protocol_Versionhighest_supported_version (const Policy &policy) const
Protocol_Version legacy_version () const
std::vector< std::string > next_protocols () const
bool offered_suite (uint16_t ciphersuite) const
const std::vector< uint8_t > & random () const
void retry (const Hello_Retry_Request &hrr, const Transcript_Hash_State &transcript_hash_state, Callbacks &cb, RandomNumberGenerator &rng)
bool sent_signature_algorithms () const
std::vector< uint8_t > serialize () const override
const Session_IDsession_id () const
std::vector< Signature_Schemesignature_schemes () const
std::string sni_hostname () const
std::vector< uint16_t > srtp_profiles () const
std::vector< Group_Paramssupported_dh_groups () const
std::vector< Group_Paramssupported_ecc_curves () const
std::vector< Protocol_Versionsupported_versions () const
bool supports_alpn () const
Handshake_Type type () const override
std::string type_string () const
void validate_updates (const Client_Hello_13 &new_ch)
virtual Handshake_Type wire_type () const

Static Public Member Functions

static std::variant< Client_Hello_13, Client_Hello_12_Shimparse (const std::vector< uint8_t > &buf)

Protected Member Functions

const std::vector< uint8_t > & compression_methods () const

Protected Attributes

std::unique_ptr< Client_Hello_Internalm_data

Detailed Description

Definition at line 29 of file tls_messages_13.h.

Constructor & Destructor Documentation

◆ Client_Hello_13()

Botan::TLS::Client_Hello_13::Client_Hello_13 ( const Policy & policy,
Callbacks & cb,
RandomNumberGenerator & rng,
std::string_view hostname,
const std::vector< std::string > & next_protocols,
std::optional< Session_with_Handle > & session,
std::vector< ExternalPSK > psks )

Creates a client hello which might optionally use the passed-in session for resumption. In that case, this will "extract" the master secret from the passed-in session.

Definition at line 154 of file msg_client_hello_13.cpp.

160 {
161 // RFC 8446 4.1.2
162 // In TLS 1.3, the client indicates its version preferences in the
163 // "supported_versions" extension (Section 4.2.1) and the
164 // legacy_version field MUST be set to 0x0303, which is the version
165 // number for TLS 1.2.
166 m_data->m_legacy_version = Protocol_Version::TLS_V12;
167 m_data->m_random = make_hello_random(rng, cb, policy);
168 m_data->m_suites = policy.ciphersuite_list(Protocol_Version::TLS_V13);
169
170 if(policy.allow_tls12()) {
171 // Note: DTLS 1.3 is NYI, hence dtls_12 is not checked
172 const auto legacy_suites = policy.ciphersuite_list(Protocol_Version::TLS_V12);
173 m_data->m_suites.insert(m_data->m_suites.end(), legacy_suites.cbegin(), legacy_suites.cend());
174 }
175
176 if(policy.tls_13_middlebox_compatibility_mode()) {
177 // RFC 8446 4.1.2
178 // In compatibility mode (see Appendix D.4), this field MUST be non-empty,
179 // so a client not offering a pre-TLS 1.3 session MUST generate a new
180 // 32-byte value.
181 //
182 // Note: we won't ever offer a TLS 1.2 session. In such a case we would
183 // have instantiated a TLS 1.2 client in the first place.
184 m_data->m_session_id = Session_ID(make_hello_random(rng, cb, policy));
185 }
186
187 // NOLINTBEGIN(*-owning-memory)
189 m_data->extensions().add(new Server_Name_Indicator(hostname));
190 }
191
192 m_data->extensions().add(new Supported_Groups(policy.key_exchange_groups()));
193
194 m_data->extensions().add(new Key_Share(policy, cb, rng));
195
196 m_data->extensions().add(new Supported_Versions(Protocol_Version::TLS_V13, policy));
197
198 m_data->extensions().add(new Signature_Algorithms(policy.acceptable_signature_schemes()));
199 if(auto cert_signing_prefs = policy.acceptable_certificate_signature_schemes()) {
200 // RFC 8446 4.2.3
201 // Implementations which have the same policy in both cases MAY omit
202 // the "signature_algorithms_cert" extension.
203 m_data->extensions().add(new Signature_Algorithms_Cert(std::move(cert_signing_prefs.value())));
204 }
205
206 // TODO: Support for PSK-only mode without a key exchange.
207 // This should be configurable in TLS::Policy and should allow no PSK
208 // support at all (e.g. to disable support for session resumption).
209 m_data->extensions().add(new PSK_Key_Exchange_Modes({PSK_Key_Exchange_Mode::PSK_DHE_KE}));
210
211 if(policy.support_cert_status_message()) {
212 m_data->extensions().add(new Certificate_Status_Request({}, {}));
213 }
214
215 // We currently support "record_size_limit" for TLS 1.3 exclusively. Hence,
216 // when TLS 1.2 is advertised as a supported protocol, we must not offer this
217 // extension.
218 if(policy.record_size_limit().has_value() && !policy.allow_tls12()) {
219 m_data->extensions().add(new Record_Size_Limit(policy.record_size_limit().value()));
220 }
221
222 /*
223 * Right now raw public key support is not implemented for TLS 1.2, so we only offer
224 * certificate_types (which is used to request raw public key) if additionally TLS 1.2
225 * support is disabled. Otherwise a peer might reply with a 1.2 server hello + a certificate_type
226 * extension indicating it wishes to use RPK, which would lead to errors later.
227 */
228 if(!policy.allow_tls12()) {
229 m_data->extensions().add(new Client_Certificate_Type(policy.accepted_client_certificate_types()));
230 m_data->extensions().add(new Server_Certificate_Type(policy.accepted_server_certificate_types()));
231 }
232
233 if(!next_protocols.empty()) {
234 m_data->extensions().add(new Application_Layer_Protocol_Notification(next_protocols));
235 }
236
237#if defined(BOTAN_HAS_TLS_12)
238 if(policy.allow_tls12()) {
239 m_data->extensions().add(new Renegotiation_Extension());
240 m_data->extensions().add(new Session_Ticket_Extension());
241
242 // EMS must always be used with TLS 1.2, regardless of the policy
243 m_data->extensions().add(new Extended_Master_Secret);
244
245 if(policy.negotiate_encrypt_then_mac()) {
246 m_data->extensions().add(new Encrypt_then_MAC);
247 }
248
249 if(m_data->extensions().has<Supported_Groups>() &&
250 !m_data->extensions().get<Supported_Groups>()->ec_groups().empty()) {
251 m_data->extensions().add(new Supported_Point_Formats(policy.use_ecc_point_compression()));
252 }
253 }
254#endif
255
256 if(session.has_value() || !psks.empty()) {
257 m_data->extensions().add(new PSK(session, std::move(psks), cb));
258 }
259 // NOLINTEND(*-owning-memory)
260
261 cb.tls_modify_extensions(m_data->extensions(), Connection_Side::Client, type());
262
263 // The application's tls_modify_extensions callback could have stripped
264 // Supported_Groups or Key_Share, which must be there.
265 if(!m_data->extensions().has<Supported_Groups>()) {
266 throw TLS_Exception(Alert::InternalError,
267 "Application tls_modify_extensions callback removed Supported_Groups from the ClientHello");
268 }
269 if(!m_data->extensions().has<Key_Share>()) {
270 throw TLS_Exception(Alert::InternalError,
271 "Application tls_modify_extensions callback removed Key_Share from the ClientHello");
272 }
273
274 if(m_data->extensions().has<PSK>()) {
275 // RFC 8446 4.2.11
276 // The "pre_shared_key" extension MUST be the last extension in the
277 // ClientHello (this facilitates implementation [...]).
278 if(m_data->extensions().last_added() != Extension_Code::PresharedKey) {
279 throw TLS_Exception(Alert::InternalError,
280 "Application modified extensions of Client Hello, PSK is not last anymore");
281 }
282 calculate_psk_binders({});
283 }
284}
std::unique_ptr< Client_Hello_Internal > m_data
std::vector< std::string > next_protocols() const
virtual Handshake_Type type() const =0
static bool hostname_acceptable_for_sni(std::string_view hostname)
std::vector< uint8_t > make_hello_random(RandomNumberGenerator &rng, Callbacks &cb, const Policy &policy)
Strong< std::vector< uint8_t >, struct Session_ID_ > Session_ID
holds a TLS 1.2 session ID for stateful resumption

References Botan::TLS::Policy::acceptable_certificate_signature_schemes(), Botan::TLS::Policy::acceptable_signature_schemes(), Botan::TLS::Policy::accepted_client_certificate_types(), Botan::TLS::Policy::accepted_server_certificate_types(), Botan::TLS::Policy::allow_tls12(), Botan::TLS::Policy::ciphersuite_list(), Botan::TLS::Client, Client_Hello_13(), Botan::TLS::Supported_Groups::ec_groups(), Botan::TLS::Server_Name_Indicator::hostname_acceptable_for_sni(), Botan::TLS::Policy::key_exchange_groups(), Botan::TLS::Client_Hello::m_data, Botan::TLS::make_hello_random(), Botan::TLS::Policy::negotiate_encrypt_then_mac(), Botan::TLS::Client_Hello::next_protocols(), Botan::TLS::PresharedKey, Botan::TLS::PSK_DHE_KE, Botan::TLS::Policy::record_size_limit(), Botan::TLS::Policy::support_cert_status_message(), Botan::TLS::Policy::tls_13_middlebox_compatibility_mode(), Botan::TLS::Callbacks::tls_modify_extensions(), Botan::TLS::Client_Hello::type(), and Botan::TLS::Policy::use_ecc_point_compression().

Referenced by Client_Hello_13(), parse(), and validate_updates().

Member Function Documentation

◆ certificate_signature_schemes()

std::vector< Signature_Scheme > Botan::TLS::Client_Hello::certificate_signature_schemes ( ) const
inherited

Definition at line 221 of file msg_client_hello.cpp.

221 {
222 // RFC 8446 4.2.3
223 // If no "signature_algorithms_cert" extension is present, then the
224 // "signature_algorithms" extension also applies to signatures appearing
225 // in certificates.
226 if(const Signature_Algorithms_Cert* sigs = m_data->extensions().get<Signature_Algorithms_Cert>()) {
227 return sigs->supported_schemes();
228 } else {
229 return signature_schemes();
230 }
231}
std::vector< Signature_Scheme > signature_schemes() const

References m_data, and signature_schemes().

Referenced by ~Client_Hello().

◆ ciphersuites()

const std::vector< uint16_t > & Botan::TLS::Client_Hello::ciphersuites ( ) const
inherited

Definition at line 157 of file msg_client_hello.cpp.

157 {
158 return m_data->ciphersuites();
159}

References m_data.

Referenced by ~Client_Hello().

◆ compression_methods()

const std::vector< uint8_t > & Botan::TLS::Client_Hello::compression_methods ( ) const
protectedinherited

Definition at line 153 of file msg_client_hello.cpp.

153 {
154 return m_data->comp_methods();
155}

References m_data.

Referenced by ~Client_Hello().

◆ cookie()

const std::vector< uint8_t > & Botan::TLS::Client_Hello::cookie ( ) const
inherited

Definition at line 283 of file msg_client_hello.cpp.

283 {
284 return m_data->hello_cookie();
285}

References m_data.

Referenced by ~Client_Hello().

◆ cookie_input_data()

std::vector< uint8_t > Botan::TLS::Client_Hello::cookie_input_data ( ) const
inherited

Definition at line 200 of file msg_client_hello.cpp.

200 {
201 BOTAN_STATE_CHECK(!m_data->hello_cookie_input_bits().empty());
202
203 return m_data->hello_cookie_input_bits();
204}
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49

References BOTAN_STATE_CHECK, and m_data.

Referenced by ~Client_Hello().

◆ extension_types()

std::set< Extension_Code > Botan::TLS::Client_Hello::extension_types ( ) const
inherited

Definition at line 161 of file msg_client_hello.cpp.

161 {
162 return m_data->extensions().extension_types();
163}

References m_data.

Referenced by Botan::TLS::Server_Hello_12::Server_Hello_12(), Botan::TLS::Client_Hello_13::validate_updates(), and ~Client_Hello().

◆ extensions()

◆ highest_supported_version()

std::optional< Protocol_Version > Botan::TLS::Client_Hello_13::highest_supported_version ( const Policy & policy) const

Select the highest protocol version from the list of versions supported by the client. If no such version can be determined this returns std::nullopt.

Definition at line 486 of file msg_client_hello_13.cpp.

486 {
487 // RFC 8446 4.2.1
488 // The "supported_versions" extension is used by the client to indicate
489 // which versions of TLS it supports and by the server to indicate which
490 // version it is using. The extension contains a list of supported
491 // versions in preference order, with the most preferred version first.
492 auto* const supvers = m_data->extensions().get<Supported_Versions>();
493 BOTAN_ASSERT_NONNULL(supvers);
494
495 std::optional<Protocol_Version> result;
496
497 for(const auto& v : supvers->versions()) {
498 // RFC 8446 4.2.1
499 // Servers MUST only select a version of TLS present in that extension
500 // and MUST ignore any unknown versions that are present in that
501 // extension.
502 if(!v.known_version() || !policy.acceptable_protocol_version(v)) {
503 continue;
504 }
505
506 result = (result.has_value()) ? std::optional(std::max(result.value(), v)) : std::optional(v);
507 }
508
509 return result;
510}
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114

References Botan::TLS::Policy::acceptable_protocol_version(), BOTAN_ASSERT_NONNULL, highest_supported_version(), and Botan::TLS::Client_Hello::m_data.

Referenced by highest_supported_version().

◆ legacy_version()

Protocol_Version Botan::TLS::Client_Hello::legacy_version ( ) const
inherited

Return the version indicated in the ClientHello. This may differ from the version indicated in the supported_versions extension.

See RFC 8446 4.1.2: 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.

Definition at line 141 of file msg_client_hello.cpp.

141 {
142 return m_data->legacy_version();
143}

Referenced by ~Client_Hello().

◆ next_protocols()

std::vector< std::string > Botan::TLS::Client_Hello::next_protocols ( ) const
inherited

Definition at line 269 of file msg_client_hello.cpp.

269 {
270 if(auto* alpn = m_data->extensions().get<Application_Layer_Protocol_Notification>()) {
271 return alpn->protocols();
272 }
273 return {};
274}

References m_data.

Referenced by Botan::TLS::Client_Hello_12::Client_Hello_12(), Botan::TLS::Client_Hello_12::Client_Hello_12(), Botan::TLS::Client_Hello_13::Client_Hello_13(), and ~Client_Hello().

◆ offered_suite()

bool Botan::TLS::Client_Hello::offered_suite ( uint16_t ciphersuite) const
inherited

Definition at line 209 of file msg_client_hello.cpp.

209 {
210 return std::find(m_data->ciphersuites().cbegin(), m_data->ciphersuites().cend(), ciphersuite) !=
211 m_data->ciphersuites().cend();
212}

References m_data.

Referenced by ~Client_Hello().

◆ parse()

std::variant< Client_Hello_13, Client_Hello_12_Shim > Botan::TLS::Client_Hello_13::parse ( const std::vector< uint8_t > & buf)
static

Definition at line 286 of file msg_client_hello_13.cpp.

286 {
287 auto data = std::make_unique<Client_Hello_Internal>(buf);
288 const auto version = data->version();
289
290 if(version.is_pre_tls_13()) {
291 return Client_Hello_12_Shim(std::move(data));
292 } else {
293 return Client_Hello_13(std::move(data));
294 }
295}
Client_Hello_13(const Policy &policy, Callbacks &cb, RandomNumberGenerator &rng, std::string_view hostname, const std::vector< std::string > &next_protocols, std::optional< Session_with_Handle > &session, std::vector< ExternalPSK > psks)

References Client_Hello_13(), and parse().

Referenced by parse().

◆ random()

const std::vector< uint8_t > & Botan::TLS::Client_Hello::random ( ) const
inherited

Definition at line 145 of file msg_client_hello.cpp.

145 {
146 return m_data->random();
147}

Referenced by ~Client_Hello().

◆ retry()

void Botan::TLS::Client_Hello_13::retry ( const Hello_Retry_Request & hrr,
const Transcript_Hash_State & transcript_hash_state,
Callbacks & cb,
RandomNumberGenerator & rng )

Definition at line 297 of file msg_client_hello_13.cpp.

300 {
301 BOTAN_STATE_CHECK(m_data->extensions().has<Supported_Groups>());
302 BOTAN_STATE_CHECK(m_data->extensions().has<Key_Share>());
303
304 auto* hrr_ks = hrr.extensions().get<Key_Share>();
305 const auto& supported_groups = m_data->extensions().get<Supported_Groups>()->groups();
306
307 if(hrr.extensions().has<Key_Share>()) {
308 m_data->extensions().get<Key_Share>()->retry_offer(*hrr_ks, supported_groups, cb, rng);
309 }
310
311 // RFC 8446 4.2.2
312 // When sending the new ClientHello, the client MUST copy
313 // the contents of the extension received in the HelloRetryRequest into
314 // a "cookie" extension in the new ClientHello.
315 //
316 // RFC 8446 4.2.2
317 // Clients MUST NOT use cookies in their initial ClientHello in subsequent
318 // connections.
319 if(hrr.extensions().has<Cookie>()) {
320 BOTAN_STATE_CHECK(!m_data->extensions().has<Cookie>());
321 m_data->extensions().add(new Cookie(hrr.extensions().get<Cookie>()->get_cookie())); // NOLINT(*-owning-memory)
322 }
323
324 // Note: the consumer of the TLS implementation won't be able to distinguish
325 // invocations to this callback due to the first Client_Hello or the
326 // retried Client_Hello after receiving a Hello_Retry_Request. We assume
327 // that the user keeps and detects this state themselves.
328 cb.tls_modify_extensions(m_data->extensions(), Connection_Side::Client, type());
329
330 // Same invariants as in the constructor: the callback must not strip
331 // Supported_Groups or Key_Share
332 if(!m_data->extensions().has<Supported_Groups>()) {
333 throw TLS_Exception(
334 Alert::InternalError,
335 "Application tls_modify_extensions callback removed Supported_Groups from the retried ClientHello");
336 }
337 if(!m_data->extensions().has<Key_Share>()) {
338 throw TLS_Exception(Alert::InternalError,
339 "Application tls_modify_extensions callback removed Key_Share from the retried ClientHello");
340 }
341
342 auto* psk = m_data->extensions().get<PSK>();
343 if(psk != nullptr) {
344 // RFC 8446 4.2.11
345 // The "pre_shared_key" extension MUST be the last extension in the
346 // ClientHello (this facilitates implementation [...]).
347 m_data->extensions().reorder({Extension_Code::PresharedKey});
348
349 // Cipher suite should always be a known suite as this is checked upstream
350 const auto cipher = Ciphersuite::by_id(hrr.ciphersuite());
351 BOTAN_ASSERT_NOMSG(cipher.has_value());
352
353 // RFC 8446 4.1.4
354 // In [...] its updated ClientHello, the client SHOULD NOT offer
355 // any pre-shared keys associated with a hash other than that of the
356 // selected cipher suite.
357 psk->filter(cipher.value());
358
359 // RFC 8446 4.2.11.2
360 // If the server responds with a HelloRetryRequest and the client
361 // then sends ClientHello2, its binder will be computed over: [...].
362 calculate_psk_binders(transcript_hash_state.clone());
363 }
364}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
static std::optional< Ciphersuite > by_id(uint16_t suite)

References BOTAN_ASSERT_NOMSG, BOTAN_STATE_CHECK, Botan::TLS::Ciphersuite::by_id(), Botan::TLS::Server_Hello::ciphersuite(), Botan::TLS::Client, Botan::TLS::Transcript_Hash_State::clone(), Botan::TLS::Server_Hello::extensions(), Botan::TLS::Extensions::get(), Botan::TLS::Cookie::get_cookie(), Botan::TLS::Extensions::has(), Botan::TLS::Client_Hello::m_data, Botan::TLS::PresharedKey, retry(), Botan::TLS::Callbacks::tls_modify_extensions(), and Botan::TLS::Client_Hello::type().

Referenced by retry().

◆ sent_signature_algorithms()

bool Botan::TLS::Client_Hello::sent_signature_algorithms ( ) const
inherited

Definition at line 265 of file msg_client_hello.cpp.

265 {
266 return m_data->extensions().has<Signature_Algorithms>();
267}

References m_data.

Referenced by ~Client_Hello().

◆ serialize()

std::vector< uint8_t > Botan::TLS::Client_Hello::serialize ( ) const
overridevirtualinherited
Returns
DER representation of this message

Implements Botan::TLS::Handshake_Message.

Definition at line 172 of file msg_client_hello.cpp.

172 {
173 std::vector<uint8_t> buf;
174 buf.reserve(1024); // working around GCC warning
175
176 buf.push_back(m_data->legacy_version().major_version());
177 buf.push_back(m_data->legacy_version().minor_version());
178 buf += m_data->random();
179
180 append_tls_length_value(buf, m_data->session_id().get(), 1);
181
182 if(m_data->legacy_version().is_datagram_protocol()) {
183 append_tls_length_value(buf, m_data->hello_cookie(), 1);
184 }
185
186 append_tls_length_value(buf, m_data->ciphersuites(), 2);
187 append_tls_length_value(buf, m_data->comp_methods(), 1);
188
189 /*
190 * May not want to send extensions at all in some cases. If so,
191 * should include SCSV value (if reneg info is empty, if not we are
192 * renegotiating with a modern server)
193 */
194
195 buf += m_data->extensions().serialize(Connection_Side::Client);
196
197 return buf;
198}
void append_tls_length_value(std::vector< uint8_t, Alloc > &buf, const T *vals, size_t vals_size, size_t tag_size)
Definition tls_reader.h:177

References Botan::TLS::append_tls_length_value(), Botan::TLS::Client, and m_data.

Referenced by ~Client_Hello().

◆ session_id()

const Session_ID & Botan::TLS::Client_Hello::session_id ( ) const
inherited

Definition at line 149 of file msg_client_hello.cpp.

149 {
150 return m_data->session_id();
151}

References m_data.

Referenced by Botan::TLS::Client_Hello_12::session_handle(), and ~Client_Hello().

◆ signature_schemes()

std::vector< Signature_Scheme > Botan::TLS::Client_Hello::signature_schemes ( ) const
inherited

Definition at line 214 of file msg_client_hello.cpp.

214 {
215 if(const Signature_Algorithms* sigs = m_data->extensions().get<Signature_Algorithms>()) {
216 return sigs->supported_schemes();
217 }
218 return {};
219}

References m_data.

Referenced by Botan::TLS::Certificate_13::Certificate_13(), certificate_signature_schemes(), Botan::TLS::Handshake_State::choose_sig_format(), and ~Client_Hello().

◆ sni_hostname()

std::string Botan::TLS::Client_Hello::sni_hostname ( ) const
inherited

Definition at line 247 of file msg_client_hello.cpp.

247 {
248 if(const Server_Name_Indicator* sni = m_data->extensions().get<Server_Name_Indicator>()) {
249 return sni->host_name();
250 }
251 return "";
252}

References m_data.

Referenced by Botan::TLS::Certificate_13::Certificate_13(), Botan::TLS::Certificate_Request_13::maybe_create(), and ~Client_Hello().

◆ srtp_profiles()

std::vector< uint16_t > Botan::TLS::Client_Hello::srtp_profiles ( ) const
inherited

Definition at line 276 of file msg_client_hello.cpp.

276 {
277 if(const SRTP_Protection_Profiles* srtp = m_data->extensions().get<SRTP_Protection_Profiles>()) {
278 return srtp->profiles();
279 }
280 return {};
281}

References m_data.

Referenced by ~Client_Hello().

◆ supported_dh_groups()

std::vector< Group_Params > Botan::TLS::Client_Hello::supported_dh_groups ( ) const
inherited

Definition at line 240 of file msg_client_hello.cpp.

240 {
241 if(const Supported_Groups* groups = m_data->extensions().get<Supported_Groups>()) {
242 return groups->dh_groups();
243 }
244 return std::vector<Group_Params>();
245}

References m_data.

Referenced by ~Client_Hello().

◆ supported_ecc_curves()

std::vector< Group_Params > Botan::TLS::Client_Hello::supported_ecc_curves ( ) const
inherited

Definition at line 233 of file msg_client_hello.cpp.

233 {
234 if(const Supported_Groups* groups = m_data->extensions().get<Supported_Groups>()) {
235 return groups->ec_groups();
236 }
237 return {};
238}

References m_data.

Referenced by ~Client_Hello().

◆ supported_versions()

std::vector< Protocol_Version > Botan::TLS::Client_Hello::supported_versions ( ) const
inherited

Definition at line 254 of file msg_client_hello.cpp.

254 {
255 if(const Supported_Versions* versions = m_data->extensions().get<Supported_Versions>()) {
256 return versions->versions();
257 }
258 return {};
259}

References m_data.

Referenced by ~Client_Hello().

◆ supports_alpn()

bool Botan::TLS::Client_Hello::supports_alpn ( ) const
inherited

Definition at line 261 of file msg_client_hello.cpp.

261 {
262 return m_data->extensions().has<Application_Layer_Protocol_Notification>();
263}

References m_data.

Referenced by Botan::TLS::Server_Hello_12::Server_Hello_12(), Botan::TLS::Server_Hello_12::Server_Hello_12(), and ~Client_Hello().

◆ type()

◆ type_string()

std::string Botan::TLS::Handshake_Message::type_string ( ) const
inherited
Returns
string representation of this message type

Definition at line 21 of file tls_handshake_state.cpp.

21 {
23}
const char * handshake_type_to_string(Handshake_Type type)
Definition tls_magic.cpp:15

References Botan::TLS::handshake_type_to_string(), and type().

◆ validate_updates()

void Botan::TLS::Client_Hello_13::validate_updates ( const Client_Hello_13 & new_ch)

This validates that a Client Hello received after sending a Hello Retry Request was updated in accordance with RFC 8446 4.1.2. If issues are found, this method throws accordingly.

Definition at line 366 of file msg_client_hello_13.cpp.

366 {
367 // RFC 8446 4.1.2
368 // The client will also send a ClientHello when the server has responded
369 // to its ClientHello with a HelloRetryRequest. In that case, the client
370 // MUST send the same ClientHello without modification, except as follows:
371
372 if(m_data->session_id() != new_ch.m_data->session_id() || m_data->random() != new_ch.m_data->random() ||
373 m_data->ciphersuites() != new_ch.m_data->ciphersuites() ||
374 m_data->comp_methods() != new_ch.m_data->comp_methods()) {
375 throw TLS_Exception(Alert::IllegalParameter, "Client Hello core values changed after Hello Retry Request");
376 }
377
378 const auto oldexts = extension_types();
379 const auto newexts = new_ch.extension_types();
380
381 // Check that extension omissions are justified. RFC 8446 4.1.2 lists the
382 // only mutations the client may make between CH1 and CH2; any other
383 // extension removal is an illegal parameter regardless of whether the
384 // extension is one this implementation recognizes.
385 for(const auto oldext : oldexts) {
386 if(!newexts.contains(oldext)) {
387 // RFC 8446 4.1.2
388 // Removing the "early_data" extension (Section 4.2.10) if one was
389 // present. Early data is not permitted after a HelloRetryRequest.
390 if(oldext == EarlyDataIndication::static_type()) {
391 continue;
392 }
393
394 // RFC 8446 4.1.2
395 // Optionally adding, removing, or changing the length of the
396 // "padding" extension.
397 if(oldext == Extension_Code::Padding) {
398 continue;
399 }
400
401 throw TLS_Exception(Alert::IllegalParameter, "Extension removed in updated Client Hello");
402 }
403 }
404
405 // Check that extension additions are justified. Same reasoning: only the
406 // RFC-listed mutations are allowed, including for unknown extension codes.
407 for(const auto newext : newexts) {
408 if(!oldexts.contains(newext)) {
409 // RFC 8446 4.1.2
410 // Including a "cookie" extension if one was provided in the
411 // HelloRetryRequest.
412 if(newext == Cookie::static_type()) {
413 continue;
414 }
415
416 // RFC 8446 4.1.2
417 // Optionally adding, removing, or changing the length of the
418 // "padding" extension.
419 if(newext == Extension_Code::Padding) {
420 continue;
421 }
422
423 throw TLS_Exception(Alert::UnsupportedExtension, "Added an extension in updated Client Hello");
424 }
425 }
426
427 // RFC 8446 4.1.2
428 // Removing the "early_data" extension (Section 4.2.10) if one was
429 // present. Early data is not permitted after a HelloRetryRequest.
430 if(new_ch.extensions().has<EarlyDataIndication>()) {
431 throw TLS_Exception(Alert::IllegalParameter, "Updated Client Hello indicates early data");
432 }
433
434 // RFC 8446 4.1.2
435 // The client MUST send the same ClientHello without modification,
436 // except as follows: [key_share, pre_shared_key, early_data, cookie, padding]
437 //
438 // Verify that extensions whose content must not change between the
439 // initial and retried Client Hello have identical wire encodings.
440 const std::set<Extension_Code> extensions_allowed_to_change = {
446 };
447
448 for(const auto ext_type : oldexts) {
449 if(extensions_allowed_to_change.contains(ext_type)) {
450 continue;
451 }
452
453 const auto old_bytes = extensions().extension_raw_bytes(ext_type);
454 const auto new_bytes = new_ch.extensions().extension_raw_bytes(ext_type);
455
456 // Both Client Hellos validated here are received from the peer and went
457 // through Extensions::deserialize, which records raw bytes for every
458 // parsed extension. A missing raw_bytes on either side would mean an
459 // extension was added by us programmatically - which shouldn't happen
460 BOTAN_ASSERT_NOMSG(old_bytes.has_value() && new_bytes.has_value());
461 if(old_bytes.value() != new_bytes.value()) {
462 throw TLS_Exception(Alert::IllegalParameter, "Extension content changed in updated Client Hello");
463 }
464 }
465}
const Extensions & extensions() const
std::set< Extension_Code > extension_types() const
static Extension_Code static_type()
static Extension_Code static_type()
std::optional< std::vector< uint8_t > > extension_raw_bytes(Extension_Code type) const

References BOTAN_ASSERT_NOMSG, Client_Hello_13(), Botan::TLS::Cookie, Botan::TLS::EarlyData, Botan::TLS::Extensions::extension_raw_bytes(), Botan::TLS::Client_Hello::extension_types(), Botan::TLS::Client_Hello::extensions(), Botan::TLS::Extensions::has(), Botan::TLS::KeyShare, Botan::TLS::Client_Hello::m_data, Botan::TLS::Padding, Botan::TLS::PresharedKey, Botan::TLS::Cookie::static_type(), Botan::TLS::EarlyDataIndication::static_type(), and validate_updates().

Referenced by validate_updates().

◆ wire_type()

virtual Handshake_Type Botan::TLS::Handshake_Message::wire_type ( ) const
inlinevirtualinherited
Returns
the wire representation of the message's type

Reimplemented in Botan::TLS::Hello_Retry_Request.

Definition at line 39 of file tls_handshake_msg.h.

39 {
40 // Usually equal to the Handshake_Type enum value,
41 // with the exception of TLS 1.3 Hello Retry Request.
42 return type();
43 }

References type().

Referenced by Botan::TLS::Stream_Handshake_IO::send().

Member Data Documentation

◆ m_data


The documentation for this class was generated from the following files: