Botan 3.5.0
Crypto and TLS for C&
Botan::TLS::Server_Hello_13 Class Reference

#include <tls_messages.h>

Inheritance diagram for Botan::TLS::Server_Hello_13:
Botan::TLS::Server_Hello Botan::TLS::Handshake_Message Botan::TLS::Hello_Retry_Request

Classes

struct  Hello_Retry_Request_Creation_Tag
 
struct  Hello_Retry_Request_Tag
 
struct  Server_Hello_Tag
 

Public Member Functions

uint16_t ciphersuite () const
 
const Extensionsextensions () const
 
std::optional< Protocol_Versionrandom_signals_downgrade () const
 
Protocol_Version selected_version () const final
 
std::vector< uint8_t > serialize () const override
 
const Session_IDsession_id () const
 
Handshake_Type type () const override
 
std::string type_string () const
 
virtual Handshake_Type wire_type () const
 

Static Public Member Functions

static std::variant< Hello_Retry_Request, Server_Hello_13create (const Client_Hello_13 &ch, bool hello_retry_request_allowed, Session_Manager &session_mgr, Credentials_Manager &credentials_mgr, RandomNumberGenerator &rng, const Policy &policy, Callbacks &cb)
 
static std::variant< Hello_Retry_Request, Server_Hello_13, Server_Hello_12parse (const std::vector< uint8_t > &buf)
 

Protected Member Functions

void basic_validation () const
 
uint8_t compression_method () const
 
std::set< Extension_Codeextension_types () const
 
Protocol_Version legacy_version () const
 
const std::vector< uint8_t > & random () const
 
 Server_Hello_13 (const Client_Hello_13 &ch, std::optional< Named_Group > key_exchange_group, Session_Manager &session_mgr, Credentials_Manager &credentials_mgr, RandomNumberGenerator &rng, Callbacks &cb, const Policy &policy)
 
 Server_Hello_13 (std::unique_ptr< Server_Hello_Internal > data, Hello_Retry_Request_Creation_Tag tag)
 
 Server_Hello_13 (std::unique_ptr< Server_Hello_Internal > data, Hello_Retry_Request_Tag tag)
 
 Server_Hello_13 (std::unique_ptr< Server_Hello_Internal > data, Server_Hello_Tag tag=as_server_hello)
 

Protected Attributes

std::unique_ptr< Server_Hello_Internal > m_data
 

Static Protected Attributes

static const struct Botan::TLS::Server_Hello_13::Hello_Retry_Request_Tag as_hello_retry_request
 
static const struct Botan::TLS::Server_Hello_13::Hello_Retry_Request_Creation_Tag as_new_hello_retry_request
 
static const struct Botan::TLS::Server_Hello_13::Server_Hello_Tag as_server_hello
 

Detailed Description

Definition at line 400 of file tls_messages.h.

Constructor & Destructor Documentation

◆ Server_Hello_13() [1/4]

Botan::TLS::Server_Hello_13::Server_Hello_13 ( std::unique_ptr< Server_Hello_Internal > data,
Server_Hello_13::Server_Hello_Tag tag = as_server_hello )
explicitprotected

Definition at line 585 of file msg_server_hello.cpp.

585 :
586 Server_Hello(std::move(data)) {
587 BOTAN_ASSERT_NOMSG(!m_data->is_hello_retry_request());
589
590 const auto& exts = extensions();
591
592 // RFC 8446 4.1.3
593 // The ServerHello MUST only include extensions which are required to
594 // establish the cryptographic context and negotiate the protocol version.
595 // [...]
596 // Other extensions (see Section 4.2) are sent separately in the
597 // EncryptedExtensions message.
598 //
599 // Note that further validation dependent on the client hello is done in the
600 // TLS client implementation.
601 const std::set<Extension_Code> allowed = {
605 };
606
607 // As the ServerHello shall only contain essential extensions, we don't give
608 // any slack for extensions not implemented by Botan here.
609 if(exts.contains_other_than(allowed)) {
610 throw TLS_Exception(Alert::UnsupportedExtension, "Server Hello contained an extension that is not allowed");
611 }
612
613 // RFC 8446 4.1.3
614 // Current ServerHello messages additionally contain
615 // either the "pre_shared_key" extension or the "key_share"
616 // extension, or both [...].
617 if(!exts.has<Key_Share>() && !exts.has<PSK_Key_Exchange_Modes>()) {
618 throw TLS_Exception(Alert::MissingExtension, "server hello must contain key exchange information");
619 }
620}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
Server_Hello(const Server_Hello &)=delete
std::unique_ptr< Server_Hello_Internal > m_data
const Extensions & extensions() const

References basic_validation(), BOTAN_ASSERT_NOMSG, Botan::TLS::Server_Hello::extensions(), Botan::TLS::KeyShare, Botan::TLS::Server_Hello::m_data, Botan::TLS::PresharedKey, and Botan::TLS::SupportedVersions.

Referenced by create(), and parse().

◆ Server_Hello_13() [2/4]

Botan::TLS::Server_Hello_13::Server_Hello_13 ( std::unique_ptr< Server_Hello_Internal > data,
Server_Hello_13::Hello_Retry_Request_Tag tag )
explicitprotected

Definition at line 622 of file msg_server_hello.cpp.

623 :
624 Server_Hello(std::move(data)) {
625 BOTAN_ASSERT_NOMSG(m_data->is_hello_retry_request());
627
628 const auto& exts = extensions();
629
630 // RFC 8446 4.1.4
631 // The HelloRetryRequest extensions defined in this specification are:
632 // - supported_versions (see Section 4.2.1)
633 // - cookie (see Section 4.2.2)
634 // - key_share (see Section 4.2.8)
635 const std::set<Extension_Code> allowed = {
639 };
640
641 // As the Hello Retry Request shall only contain essential extensions, we
642 // don't give any slack for extensions not implemented by Botan here.
643 if(exts.contains_other_than(allowed)) {
644 throw TLS_Exception(Alert::UnsupportedExtension,
645 "Hello Retry Request contained an extension that is not allowed");
646 }
647
648 // RFC 8446 4.1.4
649 // Clients MUST abort the handshake with an "illegal_parameter" alert if
650 // the HelloRetryRequest would not result in any change in the ClientHello.
651 if(!exts.has<Key_Share>() && !exts.has<Cookie>()) {
652 throw TLS_Exception(Alert::IllegalParameter, "Hello Retry Request does not request any changes to Client Hello");
653 }
654}

References basic_validation(), BOTAN_ASSERT_NOMSG, Botan::TLS::Cookie, Botan::TLS::Server_Hello::extensions(), Botan::TLS::KeyShare, Botan::TLS::Server_Hello::m_data, and Botan::TLS::SupportedVersions.

◆ Server_Hello_13() [3/4]

Botan::TLS::Server_Hello_13::Server_Hello_13 ( const Client_Hello_13 & ch,
std::optional< Named_Group > key_exchange_group,
Session_Manager & session_mgr,
Credentials_Manager & credentials_mgr,
RandomNumberGenerator & rng,
Callbacks & cb,
const Policy & policy )
protected

Definition at line 705 of file msg_server_hello.cpp.

711 :
712 Server_Hello(std::make_unique<Server_Hello_Internal>(
713 Protocol_Version::TLS_V12,
714 ch.session_id(),
715 make_server_hello_random(rng, Protocol_Version::TLS_V13, cb, policy),
716 choose_ciphersuite(ch, policy),
717 uint8_t(0) /* compression method */
718 )) {
719 // RFC 8446 4.2.1
720 // A server which negotiates TLS 1.3 MUST respond by sending a
721 // "supported_versions" extension containing the selected version
722 // value (0x0304). It MUST set the ServerHello.legacy_version field to
723 // 0x0303 (TLS 1.2).
724 //
725 // Note that the legacy version (TLS 1.2) is set in this constructor's
726 // initializer list, accordingly.
727 m_data->extensions().add(new Supported_Versions(Protocol_Version::TLS_V13));
728
729 if(key_exchange_group.has_value()) {
730 BOTAN_ASSERT_NOMSG(ch.extensions().has<Key_Share>());
732 key_exchange_group.value(), *ch.extensions().get<Key_Share>(), policy, cb, rng));
733 }
734
735 auto& ch_exts = ch.extensions();
736
737 if(ch_exts.has<PSK>()) {
738 const auto cs = Ciphersuite::by_id(m_data->ciphersuite());
740
741 // RFC 8446 4.2.9
742 // A client MUST provide a "psk_key_exchange_modes" extension if it
743 // offers a "pre_shared_key" extension.
744 //
745 // Note: Client_Hello_13 constructor already performed a graceful check.
746 const auto psk_modes = ch_exts.get<PSK_Key_Exchange_Modes>();
747 BOTAN_ASSERT_NONNULL(psk_modes);
748
749 // TODO: also support PSK_Key_Exchange_Mode::PSK_KE
750 // (PSK-based handshake without an additional ephemeral key exchange)
751 if(value_exists(psk_modes->modes(), PSK_Key_Exchange_Mode::PSK_DHE_KE)) {
752 if(auto server_psk = ch_exts.get<PSK>()->select_offered_psk(
753 ch.sni_hostname(), cs.value(), session_mgr, credentials_mgr, cb, policy)) {
754 // RFC 8446 4.2.11
755 // In order to accept PSK key establishment, the server sends a
756 // "pre_shared_key" extension indicating the selected identity.
757 m_data->extensions().add(std::move(server_psk));
758 }
759 }
760 }
761
762 cb.tls_modify_extensions(m_data->extensions(), Connection_Side::Server, type());
763}
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:86
static std::optional< Ciphersuite > by_id(uint16_t suite)
static std::unique_ptr< Key_Share > create_as_encapsulation(Group_Params selected_group, const Key_Share &client_keyshare, const Policy &policy, Callbacks &cb, RandomNumberGenerator &rng)
Handshake_Type type() const override
bool value_exists(const std::vector< T > &vec, const OT &val)
Definition stl_util.h:60

References Botan::TLS::Extensions::add(), BOTAN_ASSERT_NOMSG, BOTAN_ASSERT_NONNULL, Botan::TLS::Ciphersuite::by_id(), Botan::TLS::Key_Share::create_as_encapsulation(), Botan::TLS::Client_Hello::extensions(), Botan::TLS::Server_Hello::extensions(), Botan::TLS::Extensions::get(), Botan::TLS::Extensions::has(), Botan::TLS::Server_Hello::m_data, Botan::TLS::PSK_DHE_KE, Botan::TLS::PSK::select_offered_psk(), Botan::TLS::Server, Botan::TLS::Client_Hello::sni_hostname(), Botan::TLS::Callbacks::tls_modify_extensions(), Botan::TLS::Server_Hello::type(), and Botan::value_exists().

◆ Server_Hello_13() [4/4]

Botan::TLS::Server_Hello_13::Server_Hello_13 ( std::unique_ptr< Server_Hello_Internal > data,
Hello_Retry_Request_Creation_Tag tag )
explicitprotected

Definition at line 656 of file msg_server_hello.cpp.

656 :
657 Server_Hello(std::move(data)) {}

Member Function Documentation

◆ basic_validation()

void Botan::TLS::Server_Hello_13::basic_validation ( ) const
protected

Validation that applies to both Server Hello and Hello Retry Request

Definition at line 540 of file msg_server_hello.cpp.

540 {
541 BOTAN_ASSERT_NOMSG(m_data->version() == Protocol_Version::TLS_V13);
542
543 // Note: checks that cannot be performed without contextual information
544 // are done in the specific TLS client implementation.
545 // Note: The Supported_Version extension makes sure internally that
546 // exactly one entry is provided.
547
548 // Note: Hello Retry Request basic validation is equivalent with the
549 // basic validations required for Server Hello
550 //
551 // RFC 8446 4.1.4
552 // Upon receipt of a HelloRetryRequest, the client MUST check the
553 // legacy_version, [...], and legacy_compression_method as specified in
554 // Section 4.1.3 and then process the extensions, starting with determining
555 // the version using "supported_versions".
556
557 // RFC 8446 4.1.3
558 // In TLS 1.3, [...] the legacy_version field MUST be set to 0x0303
559 if(legacy_version() != Protocol_Version::TLS_V12) {
560 throw TLS_Exception(Alert::ProtocolVersion,
561 "legacy_version '" + legacy_version().to_string() + "' is not allowed");
562 }
563
564 // RFC 8446 4.1.3
565 // legacy_compression_method: A single byte which MUST have the value 0.
566 if(compression_method() != 0x00) {
567 throw TLS_Exception(Alert::DecodeError, "compression is not supported in TLS 1.3");
568 }
569
570 // RFC 8446 4.1.3
571 // All TLS 1.3 ServerHello messages MUST contain the "supported_versions" extension.
572 if(!extensions().has<Supported_Versions>()) {
573 throw TLS_Exception(Alert::MissingExtension, "server hello did not contain 'supported version' extension");
574 }
575
576 // RFC 8446 4.2.1
577 // A server which negotiates TLS 1.3 MUST respond by sending
578 // a "supported_versions" extension containing the selected version
579 // value (0x0304).
580 if(selected_version() != Protocol_Version::TLS_V13) {
581 throw TLS_Exception(Alert::IllegalParameter, "TLS 1.3 Server Hello selected a different version");
582 }
583}
Protocol_Version selected_version() const final
Protocol_Version legacy_version() const
std::string to_string(ErrorType type)
Convert an ErrorType to string.
Definition exceptn.cpp:13

References BOTAN_ASSERT_NOMSG, Botan::TLS::Server_Hello::compression_method(), Botan::TLS::Server_Hello::extensions(), Botan::TLS::Server_Hello::legacy_version(), Botan::TLS::Server_Hello::m_data, selected_version(), and Botan::to_string().

Referenced by Server_Hello_13(), and Server_Hello_13().

◆ ciphersuite()

uint16_t Botan::TLS::Server_Hello::ciphersuite ( ) const
inherited

Definition at line 218 of file msg_server_hello.cpp.

218 {
219 return m_data->ciphersuite();
220}

References Botan::TLS::Server_Hello::m_data.

Referenced by Botan::TLS::Client_Hello_13::retry().

◆ compression_method()

uint8_t Botan::TLS::Server_Hello::compression_method ( ) const
protectedinherited

Definition at line 210 of file msg_server_hello.cpp.

210 {
211 return m_data->comp_method();
212}

References Botan::TLS::Server_Hello::m_data.

Referenced by basic_validation().

◆ create()

std::variant< Hello_Retry_Request, Server_Hello_13 > Botan::TLS::Server_Hello_13::create ( const Client_Hello_13 & ch,
bool hello_retry_request_allowed,
Session_Manager & session_mgr,
Credentials_Manager & credentials_mgr,
RandomNumberGenerator & rng,
const Policy & policy,
Callbacks & cb )
static

Definition at line 459 of file msg_server_hello.cpp.

465 {
466 const auto& exts = ch.extensions();
467
468 // RFC 8446 4.2.9
469 // [With PSK with (EC)DHE key establishment], the client and server MUST
470 // supply "key_share" values [...].
471 //
472 // Note: We currently do not support PSK without (EC)DHE, hence, we can
473 // assume that those extensions are available.
474 BOTAN_ASSERT_NOMSG(exts.has<Supported_Groups>() && exts.has<Key_Share>());
475 const auto& supported_by_client = exts.get<Supported_Groups>()->groups();
476 const auto& offered_by_client = exts.get<Key_Share>()->offered_groups();
477 const auto selected_group = policy.choose_key_exchange_group(supported_by_client, offered_by_client);
478
479 // RFC 8446 4.1.1
480 // If there is no overlap between the received "supported_groups" and the
481 // groups supported by the server, then the server MUST abort the
482 // handshake with a "handshake_failure" or an "insufficient_security" alert.
483 if(selected_group == Named_Group::NONE) {
484 throw TLS_Exception(Alert::HandshakeFailure, "Client did not offer any acceptable group");
485 }
486
487 // RFC 8446 4.2.8:
488 // Servers MUST NOT send a KeyShareEntry for any group not indicated in the
489 // client's "supported_groups" extension [...]
490 if(!value_exists(supported_by_client, selected_group)) {
491 throw TLS_Exception(Alert::InternalError, "Application selected a group that is not supported by the client");
492 }
493
494 // RFC 8446 4.1.4
495 // The server will send this message in response to a ClientHello
496 // message if it is able to find an acceptable set of parameters but the
497 // ClientHello does not contain sufficient information to proceed with
498 // the handshake.
499 //
500 // In this case, the Client Hello did not contain a key share offer for
501 // the group selected by the application.
502 if(!value_exists(offered_by_client, selected_group)) {
503 // RFC 8446 4.1.4
504 // If a client receives a second HelloRetryRequest in the same
505 // connection (i.e., where the ClientHello was itself in response to a
506 // HelloRetryRequest), it MUST abort the handshake with an
507 // "unexpected_message" alert.
508 BOTAN_STATE_CHECK(hello_retry_request_allowed);
509 return Hello_Retry_Request(ch, selected_group, policy, cb);
510 } else {
511 return Server_Hello_13(ch, selected_group, session_mgr, credentials_mgr, rng, cb, policy);
512 }
513}
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:41
Server_Hello_13(std::unique_ptr< Server_Hello_Internal > data, Server_Hello_Tag tag=as_server_hello)

References BOTAN_ASSERT_NOMSG, BOTAN_STATE_CHECK, Botan::TLS::Policy::choose_key_exchange_group(), Botan::TLS::Client_Hello::extensions(), Server_Hello_13(), and Botan::value_exists().

◆ extension_types()

std::set< Extension_Code > Botan::TLS::Server_Hello::extension_types ( ) const
protectedinherited

Definition at line 222 of file msg_server_hello.cpp.

222 {
223 return m_data->extensions().extension_types();
224}

References Botan::TLS::Server_Hello::m_data.

◆ extensions()

const Extensions & Botan::TLS::Server_Hello::extensions ( ) const
inherited

◆ legacy_version()

Protocol_Version Botan::TLS::Server_Hello::legacy_version ( ) const
protectedinherited

Definition at line 202 of file msg_server_hello.cpp.

202 {
203 return m_data->legacy_version();
204}

References Botan::TLS::Server_Hello::m_data.

Referenced by basic_validation().

◆ parse()

std::variant< Hello_Retry_Request, Server_Hello_13, Server_Hello_12 > Botan::TLS::Server_Hello_13::parse ( const std::vector< uint8_t > & buf)
static

Definition at line 515 of file msg_server_hello.cpp.

516 {
517 auto data = std::make_unique<Server_Hello_Internal>(buf);
518 const auto version = data->version();
519
520 // server hello that appears to be pre-TLS 1.3, takes precedence over...
521 if(version.is_pre_tls_13()) {
522 return Server_Hello_12(std::move(data));
523 }
524
525 // ... the TLS 1.3 "special case" aka. Hello_Retry_Request
526 if(version == Protocol_Version::TLS_V13) {
527 if(data->is_hello_retry_request()) {
528 return Hello_Retry_Request(std::move(data));
529 }
530
531 return Server_Hello_13(std::move(data));
532 }
533
534 throw TLS_Exception(Alert::ProtocolVersion, "unexpected server hello version: " + version.to_string());
535}

References Server_Hello_13().

◆ random()

const std::vector< uint8_t > & Botan::TLS::Server_Hello::random ( ) const
protectedinherited

Definition at line 206 of file msg_server_hello.cpp.

206 {
207 return m_data->random();
208}

References Botan::TLS::Server_Hello::m_data.

Referenced by Botan::TLS::Server_Hello::serialize().

◆ random_signals_downgrade()

std::optional< Protocol_Version > Botan::TLS::Server_Hello_13::random_signals_downgrade ( ) const

Return desired downgrade version indicated by hello random, if any.

Definition at line 765 of file msg_server_hello.cpp.

765 {
766 const uint64_t last8 = load_be<uint64_t>(m_data->random().data(), 3);
767 if(last8 == DOWNGRADE_TLS11) {
768 return Protocol_Version::TLS_V11;
769 }
770 if(last8 == DOWNGRADE_TLS12) {
771 return Protocol_Version::TLS_V12;
772 }
773
774 return std::nullopt;
775}
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:467

References Botan::load_be(), and Botan::TLS::Server_Hello::m_data.

◆ selected_version()

Protocol_Version Botan::TLS::Server_Hello_13::selected_version ( ) const
finalvirtual
Returns
the selected version as indicated by the supported_versions extension

Implements Botan::TLS::Server_Hello.

Definition at line 777 of file msg_server_hello.cpp.

777 {
778 const auto versions_ext = m_data->extensions().get<Supported_Versions>();
779 BOTAN_ASSERT_NOMSG(versions_ext);
780 const auto& versions = versions_ext->versions();
781 BOTAN_ASSERT_NOMSG(versions.size() == 1);
782 return versions.front();
783}

References BOTAN_ASSERT_NOMSG, and Botan::TLS::Server_Hello::m_data.

Referenced by basic_validation().

◆ serialize()

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

Implements Botan::TLS::Handshake_Message.

Definition at line 178 of file msg_server_hello.cpp.

178 {
179 std::vector<uint8_t> buf;
180 buf.reserve(1024); // working around GCC warning
181
182 buf.push_back(m_data->legacy_version().major_version());
183 buf.push_back(m_data->legacy_version().minor_version());
184 buf += m_data->random();
185
186 append_tls_length_value(buf, m_data->session_id().get(), 1);
187
188 buf.push_back(get_byte<0>(m_data->ciphersuite()));
189 buf.push_back(get_byte<1>(m_data->ciphersuite()));
190
191 buf.push_back(m_data->comp_method());
192
193 buf += m_data->extensions().serialize(Connection_Side::Server);
194
195 return buf;
196}
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:180
constexpr uint8_t get_byte(T input)
Definition loadstor.h:75

References Botan::TLS::append_tls_length_value(), Botan::get_byte(), Botan::TLS::Server_Hello::random(), and Botan::TLS::Server.

◆ session_id()

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

Definition at line 214 of file msg_server_hello.cpp.

214 {
215 return m_data->session_id();
216}

References Botan::TLS::Server_Hello::m_data.

◆ type()

Handshake_Type Botan::TLS::Server_Hello::type ( ) const
overridevirtualinherited
Returns
the message type

Implements Botan::TLS::Handshake_Message.

Definition at line 198 of file msg_server_hello.cpp.

References Botan::TLS::ServerHello.

Referenced by Botan::TLS::Server_Hello_12::Server_Hello_12(), and Server_Hello_13().

◆ type_string()

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

Definition at line 19 of file tls_handshake_state.cpp.

19 {
21}
virtual Handshake_Type type() const =0
const char * handshake_type_to_string(Handshake_Type type)

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

◆ 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 }

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

Member Data Documentation

◆ as_hello_retry_request

const Server_Hello_13::Hello_Retry_Request_Tag Botan::TLS::Server_Hello_13::as_hello_retry_request
staticprotected

Definition at line 456 of file msg_server_hello.cpp.

◆ as_new_hello_retry_request

const Server_Hello_13::Hello_Retry_Request_Creation_Tag Botan::TLS::Server_Hello_13::as_new_hello_retry_request
staticprotected

Definition at line 457 of file msg_server_hello.cpp.

◆ as_server_hello

const Server_Hello_13::Server_Hello_Tag Botan::TLS::Server_Hello_13::as_server_hello
staticprotected

Definition at line 455 of file msg_server_hello.cpp.

◆ m_data


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