9#include <botan/internal/tls_client_impl_13.h>
11#include <botan/credentials_manager.h>
12#include <botan/hash.h>
13#include <botan/tls_client.h>
14#include <botan/tls_messages.h>
15#include <botan/types.h>
16#include <botan/internal/stl_util.h>
17#include <botan/internal/tls_channel_impl_13.h>
18#include <botan/internal/tls_cipher_state.h>
26 const std::shared_ptr<Session_Manager>& session_manager,
27 const std::shared_ptr<Credentials_Manager>& creds,
28 const std::shared_ptr<const Policy>& policy,
29 const std::shared_ptr<RandomNumberGenerator>& rng,
31 const std::vector<std::string>& next_protocols) :
32 Channel_Impl_13(callbacks, session_manager, creds, rng, policy, false ),
33 m_info(std::move(info)),
34 m_should_send_ccs(false) {
35#if defined(BOTAN_HAS_TLS_12)
37 expect_downgrade(m_info, next_protocols);
41 if(
auto session = find_session_for_resumption()) {
42 if(!session->session.version().is_pre_tls_13()) {
43 m_resumed_session = std::move(session);
72 m_should_send_ccs =
true;
90 m_handshake_state.
received(std::move(message)));
96 std::visit([&](
auto msg) { handle(msg); }, m_handshake_state.
received(std::move(message)));
99void Client_Impl_13::process_dummy_change_cipher_spec() {
105 throw TLS_Exception(Alert::UnexpectedMessage,
"Received an unexpected dummy Change Cipher Spec");
121std::optional<Session_with_Handle> Client_Impl_13::find_session_for_resumption() {
138 if(sessions.empty()) {
145 auto& session_to_resume = sessions.front();
147 return std::move(session_to_resume);
150void Client_Impl_13::handle(
const Server_Hello_12& server_hello_msg) {
152 throw TLS_Exception(Alert::UnexpectedMessage,
"Version downgrade received after Hello Retry");
160 throw TLS_Exception(Alert::ProtocolVersion,
"Received an unexpected legacy Server Hello");
173 if(server_hello_msg.random_signals_downgrade().has_value()) {
174 throw TLS_Exception(Alert::IllegalParameter,
"Downgrade attack detected");
183 if(server_hello_msg.extensions().has<Supported_Versions>()) {
184 throw TLS_Exception(Alert::IllegalParameter,
"Unexpected extension received");
193 if(!client_hello_exts.get<Supported_Versions>()->supports(server_hello_msg.selected_version())) {
194 throw TLS_Exception(Alert::ProtocolVersion,
"Protocol version was not offered");
197 if(
policy().tls_13_middlebox_compatibility_mode() &&
203 throw TLS_Exception(Alert::IllegalParameter,
"Unexpected session ID during downgrade");
215void validate_server_hello_ish(
const Client_Hello_13& ch,
const Server_Hello_13& sh) {
219 if(ch.session_id() != sh.session_id()) {
220 throw TLS_Exception(Alert::IllegalParameter,
"echoed session id did not match");
226 if(!ch.offered_suite(sh.ciphersuite())) {
227 throw TLS_Exception(Alert::IllegalParameter,
"Server replied with ciphersuite we didn't send");
237 if(!ch.extensions().get<Supported_Versions>()->supports(sh.selected_version())) {
238 throw TLS_Exception(Alert::IllegalParameter,
"Protocol version was not offered");
243void Client_Impl_13::handle(
const Server_Hello_13& sh) {
249 validate_server_hello_ish(ch, sh);
256 if(sh.extensions().contains_other_than(ch.extensions().extension_types())) {
257 throw TLS_Exception(Alert::UnsupportedExtension,
"Unsupported extension found in Server Hello");
267 if(hrr.ciphersuite() != sh.ciphersuite()) {
268 throw TLS_Exception(Alert::IllegalParameter,
"server changed its chosen ciphersuite");
275 if(hrr.selected_version() != sh.selected_version()) {
276 throw TLS_Exception(Alert::IllegalParameter,
"server changed its chosen protocol version");
287 if(!cipher->usable_in_version(Protocol_Version::TLS_V13)) {
288 throw TLS_Exception(Alert::IllegalParameter,
289 "Server replied using a ciphersuite not allowed in version it offered");
302 if(!sh.extensions().has<Key_Share>()) {
303 throw TLS_Exception(Alert::IllegalParameter,
"Server Hello did not contain a key share extension");
306 auto my_keyshare = ch.extensions().get<Key_Share>();
307 auto shared_secret = my_keyshare->decapsulate(*sh.extensions().get<Key_Share>(),
policy(),
callbacks(),
rng());
311 if(sh.extensions().has<
PSK>()) {
313 ch.extensions().get<
PSK>()->take_selected_psk_info(*sh.extensions().get<
PSK>(), cipher.value());
318 if(m_psk_identity.has_value() && m_resumed_session.has_value()) {
319 m_resumed_session.reset();
329 m_resumed_session.reset();
339void Client_Impl_13::handle(
const Hello_Retry_Request& hrr) {
346 validate_server_hello_ish(ch, hrr);
352 auto allowed_exts = ch.extensions().extension_types();
354 if(hrr.extensions().contains_other_than(allowed_exts)) {
355 throw TLS_Exception(Alert::UnsupportedExtension,
"Unsupported extension found in Hello Retry Request");
376void Client_Impl_13::handle(
const Encrypted_Extensions& encrypted_extensions_msg) {
377 const auto& exts = encrypted_extensions_msg.extensions();
385 if(exts.contains_other_than(requested_exts)) {
386 throw TLS_Exception(Alert::UnsupportedExtension,
387 "Encrypted Extensions contained an extension that was not offered");
401 const auto outgoing_limit = exts.get<Record_Size_Limit>();
406 if(exts.has<Server_Certificate_Type>() &&
408 const auto* server_cert_type = exts.get<Server_Certificate_Type>();
410 our_server_cert_types->validate_selection(*server_cert_type);
434void Client_Impl_13::handle(
const Certificate_Request_13& certificate_request_msg) {
439 throw TLS_Exception(Alert::DecodeError,
"Certificate_Request context must be empty in the main handshake");
447void Client_Impl_13::handle(
const Certificate_13& certificate_msg) {
451 if(!certificate_msg.request_context().empty()) {
452 throw TLS_Exception(Alert::DecodeError,
"Received a server certificate message with non-empty request context");
468void Client_Impl_13::handle(
const Certificate_Verify_13& certificate_verify_msg) {
478 if(!
value_exists(offered, certificate_verify_msg.signature_scheme())) {
479 throw TLS_Exception(Alert::IllegalParameter,
480 "We did not offer the usage of " + certificate_verify_msg.signature_scheme().to_string() +
481 " as a signature scheme");
484 bool sig_valid = certificate_verify_msg.verify(
488 throw TLS_Exception(Alert::DecryptError,
"Server certificate verification failed");
494void Client_Impl_13::send_client_authentication(Channel_Impl_13::AggregatedHandshakeMessages& flight) {
498 const auto cert_type = [&] {
501 if(exts.has<Client_Certificate_Type>() && chexts.has<Client_Certificate_Type>()) {
502 const auto* client_cert_type = exts.get<Client_Certificate_Type>();
503 chexts.get<Client_Certificate_Type>()->validate_selection(*client_cert_type);
512 return client_cert_type->selected_certificate_type();
526 flight.add(m_handshake_state.
sending(
537 cert_request.signature_schemes(),
548void Client_Impl_13::handle(
const Finished_13& finished_msg) {
554 throw TLS_Exception(Alert::DecryptError,
"Finished message didn't verify");
564 m_resumed_session.has_value(),
578 send_client_authentication(flight);
599void TLS::Client_Impl_13::handle(
const New_Session_Ticket_13& new_session_ticket) {
600 callbacks().tls_examine_extensions(
603 Session session(m_cipher_state->psk(new_session_ticket.nonce()),
604 new_session_ticket.early_data_byte_limit(),
605 new_session_ticket.ticket_age_add(),
606 new_session_ticket.lifetime_hint(),
607 m_handshake_state.server_hello().selected_version(),
608 m_handshake_state.server_hello().ciphersuite(),
611 peer_raw_public_key(),
613 callbacks().tls_current_timestamp());
615 if(callbacks().tls_should_persist_resumption_information(session)) {
616 session_manager().store(session, new_session_ticket.handle());
626 if(m_resumed_session.has_value()) {
627 return m_resumed_session->session.peer_certs();
638 if(m_resumed_session.has_value()) {
639 return m_resumed_session->session.peer_raw_public_key();
646 return m_psk_identity;
649bool Client_Impl_13::prepend_ccs() {
650 return std::exchange(m_should_send_ccs,
false);
653void Client_Impl_13::maybe_log_secret(std::string_view label, std::span<const uint8_t> secret)
const {
654 if(
policy().allow_ssl_key_log_file()) {
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_STATE_CHECK(expr)
virtual void tls_session_established(const Session_Summary &session)
virtual void tls_session_activated()
virtual void tls_ssl_key_log_data(std::string_view label, std::span< const uint8_t > client_random, std::span< const uint8_t > secret) const
virtual void tls_examine_extensions(const Extensions &extn, Connection_Side which_side, Handshake_Type which_message)
virtual void tls_inspect_handshake_msg(const Handshake_Message &message)
std::shared_ptr< const Public_Key > public_key() const
bool is_raw_public_key() const
std::vector< X509_Certificate > cert_chain() const
bool has_certificate_chain() const
const Policy & policy() const
AggregatedHandshakeMessages aggregate_handshake_messages()
Credentials_Manager & credentials_manager()
RandomNumberGenerator & rng()
std::vector< uint8_t > send_handshake_message(const std::variant< MsgTs... > &message)
Transcript_Hash_State m_transcript_hash
Session_Manager & session_manager()
std::unique_ptr< Cipher_State > m_cipher_state
const Connection_Side m_side
Callbacks & callbacks() const
void set_selected_certificate_type(Certificate_Type cert_type)
void set_record_size_limits(uint16_t outgoing_limit, uint16_t incoming_limit)
void request_downgrade_for_resumption(Session_with_Handle session)
void preserve_client_hello(std::span< const uint8_t > msg)
bool expects_downgrade() const
static std::unique_ptr< Cipher_State > init_with_server_hello(Connection_Side side, secure_vector< uint8_t > &&shared_secret, const Ciphersuite &cipher, const Transcript_Hash &transcript_hash, const Secret_Logger &channel)
static std::optional< Ciphersuite > by_id(uint16_t suite)
const std::vector< uint8_t > & random() const
std::vector< Signature_Scheme > signature_schemes() const
const Extensions & extensions() const
const Session_ID & session_id() const
Client_Impl_13(const std::shared_ptr< Callbacks > &callbacks, const std::shared_ptr< Session_Manager > &session_manager, const std::shared_ptr< Credentials_Manager > &creds, const std::shared_ptr< const Policy > &policy, const std::shared_ptr< RandomNumberGenerator > &rng, Server_Information server_info=Server_Information(), const std::vector< std::string > &next_protocols={})
std::optional< std::string > external_psk_identity() const override
std::string application_protocol() const override
std::shared_ptr< const Public_Key > peer_raw_public_key() const override
bool is_handshake_complete() const override
std::vector< X509_Certificate > peer_cert_chain() const override
const Extensions & extensions() const
std::set< Extension_Code > extension_types() const
std::reference_wrapper< MsgT > sending(MsgT msg)
decltype(auto) received(Handshake_Message_13 message)
void confirm_transition_to(Handshake_Type msg_type)
void set_expected_next(Handshake_Type msg_type)
bool has_certificate_request() const
bool has_server_certificate_msg() const
bool has_hello_retry_request() const
Client_Hello_13 & client_hello()
const Hello_Retry_Request & hello_retry_request() const
const Certificate_13 & server_certificate() const
const Certificate_Request_13 & certificate_request() const
const Certificate_13 & client_certificate() const
bool has_client_hello() const
const Encrypted_Extensions & encrypted_extensions() const
const Server_Hello_13 & server_hello() const
bool has_server_finished() const
bool handshake_finished() const
virtual bool allow_tls12() const
virtual bool tls_13_middlebox_compatibility_mode() const
const Extensions & extensions() const
virtual std::vector< Session_with_Handle > find(const Server_Information &info, Callbacks &callbacks, const Policy &policy)
Find all sessions that match a given server info.
const Transcript_Hash & current() const
static Transcript_Hash_State recreate_after_hello_retry_request(std::string_view algo_spec, const Transcript_Hash_State &prev_transcript_hash_state)
void set_algorithm(std::string_view algo_spec)
const Transcript_Hash & previous() const
std::variant< New_Session_Ticket_13, Key_Update > Post_Handshake_Message_13
std::variant< Client_Hello_13, Client_Hello_12, Server_Hello_13, Server_Hello_12, Hello_Retry_Request, Encrypted_Extensions, Certificate_13, Certificate_Request_13, Certificate_Verify_13, Finished_13 > Handshake_Message_13
bool value_exists(const std::vector< T > &vec, const OT &val)