10#include <botan/internal/tls_channel_impl_13.h>
12#include <botan/tls_callbacks.h>
13#include <botan/tls_exceptn.h>
14#include <botan/tls_messages_13.h>
15#include <botan/tls_policy.h>
16#include <botan/internal/concat_util.h>
17#include <botan/internal/tls_cipher_state.h>
24 return alert.
type() == Botan::TLS::Alert::UserCanceled;
28 return alert.
type() == Botan::TLS::Alert::CloseNotify;
34 return !is_close_notify_alert(alert) && !is_user_canceled_alert(alert);
43 const std::shared_ptr<RandomNumberGenerator>&
rng,
44 const std::shared_ptr<const Policy>&
policy,
52 m_record_layer(
m_side, m_policy),
56 m_opportunistic_key_update(false),
57 m_first_message_sent(false),
58 m_first_message_received(false) {
78#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
80 preserve_peer_transcript(data);
84 m_record_layer.copy_data(data);
97 if(std::holds_alternative<BytesNeeded>(result)) {
98 return std::get<BytesNeeded>(result);
101 const auto& record = std::get<Record>(result);
110 m_handshake_layer.copy_data(record.fragment);
134 m_handshake_layer.has_pending_data()) {
135 throw Unexpected_Message(
"Unexpected additional handshake message data found in record");
140#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
144 }
else if(m_downgrade_info !=
nullptr) {
147 if(m_downgrade_info->received_tls_13_error_alert) {
152 m_downgrade_info.reset();
159 if(!m_first_message_received) {
160 m_record_layer.disable_receiving_compat_mode();
161 m_first_message_received =
true;
165 while(
auto handshake_msg = m_handshake_layer.next_post_handshake_message(
policy())) {
180 if(!record.seq_no.has_value()) {
185 process_alert(record.fragment);
187 throw Unexpected_Message(
"Unexpected record type " + std::to_string(
static_cast<size_t>(record.type)) +
188 " from counterparty");
211 if(m_handshake_layer.has_pending_data()) {
212 throw Unexpected_Message(
"Unexpected additional post-handshake message data found in record");
215 if(
const uint64_t min_interval =
policy().minimum_key_update_interval_ms(); min_interval > 0) {
217 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch())
220 if(m_last_key_update_ms != 0 && (now - m_last_key_update_ms) < min_interval) {
221 throw TLS_Exception(Alert::UnexpectedMessage,
"Peer is requesting KeyUpdates too frequently");
224 m_last_key_update_ms = now;
254 std::visit([&](
const auto msg) {
m_channel.callbacks().tls_inspect_handshake_msg(msg.get()); }, message);
261 std::visit([&](
const auto& msg) {
m_channel.callbacks().tls_inspect_handshake_msg(msg); }, message);
287 throw Invalid_State(
"Data cannot be sent on inactive TLS connection");
298 if(m_opportunistic_key_update) {
300 m_opportunistic_key_update =
false;
307 if(alert.
is_valid() && m_can_write) {
320 if(is_close_notify_alert(alert) && m_can_write) {
327 if(is_error_alert(alert)) {
338 std::string_view context,
339 size_t length)
const {
352void Channel_Impl_13::send_record(
Record_Type type,
const std::vector<uint8_t>& record) {
364 auto to_write = m_record_layer.
prepare_records(type, record, cipher_state);
372 m_first_message_sent =
true;
379 const Alert alert(record);
381 if(is_close_notify_alert(alert)) {
386 m_record_layer.clear_read_buffer();
396 if(is_error_alert(alert) && !alert.
is_fatal()) {
398 throw TLS_Exception(Alert::DecodeError,
"Error alert not marked fatal");
401#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
408 m_downgrade_info->received_tls_13_error_alert =
true;
419 if(is_close_notify_alert(alert) &&
callbacks().tls_peer_closed_connection()) {
424void Channel_Impl_13::shutdown() {
434#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
436void Channel_Impl_13::expect_downgrade(
const Server_Information& server_info,
437 const std::vector<std::string>& next_protocols) {
438 Downgrade_Information di{
447 m_credentials_manager,
453 m_downgrade_info = std::make_unique<Downgrade_Information>(std::move(di));
459 m_record_layer.set_record_size_limits(outgoing_limit, incoming_limit);
463 m_handshake_layer.set_selected_certificate_type(cert_type);
#define BOTAN_DEBUG_ASSERT(expr)
#define BOTAN_STATE_CHECK(expr)
#define BOTAN_ASSERT_NONNULL(ptr)
std::vector< uint8_t > serialize() const
virtual void tls_record_received(uint64_t seq_no, std::span< const uint8_t > data)=0
virtual void tls_alert(Alert alert)=0
virtual void tls_emit_data(std::span< const uint8_t > data)=0
AggregatedHandshakeMessages & add(Handshake_Message_13_Ref message)
AggregatedHandshakeMessages(Channel_Impl_13 &channel, Handshake_Layer &handshake_layer, Transcript_Hash_State &transcript_hash)
bool contains_messages() const
std::vector< uint8_t > m_message_buffer
AggregatedMessages(Channel_Impl_13 &channel, Handshake_Layer &handshake_layer)
Handshake_Layer & m_handshake_layer
Channel_Impl_13 & m_channel
AggregatedPostHandshakeMessages & add(Post_Handshake_Message_13 message)
~Channel_Impl_13() override
virtual void maybe_handle_compatibility_mode(Compat_Mode_Situation situation)=0
const Policy & policy() const
SymmetricKey key_material_export(std::string_view label, std::string_view context, size_t length) const override
void handle(const Key_Update &key_update)
Credentials_Manager & credentials_manager()
void send_dummy_change_cipher_spec()
void send_post_handshake_message(Post_Handshake_Message_13 message)
RandomNumberGenerator & rng()
void opportunistically_update_traffic_keys()
void to_peer(std::span< const uint8_t > data) override
Transcript_Hash_State m_transcript_hash
virtual void process_post_handshake_msg(Post_Handshake_Message_13 msg)=0
std::optional< Active_Connection_State_13 > m_active_state
virtual void process_handshake_msg(Handshake_Message_13 msg)=0
Channel_Impl_13(const std::shared_ptr< Callbacks > &callbacks, const std::shared_ptr< Session_Manager > &session_manager, const std::shared_ptr< Credentials_Manager > &credentials_manager, const std::shared_ptr< RandomNumberGenerator > &rng, const std::shared_ptr< const Policy > &policy, bool is_server)
void send_alert(const Alert &alert) override
size_t from_peer(std::span< const uint8_t > data) override
void update_traffic_keys(bool request_peer_update=false) override
virtual void process_dummy_change_cipher_spec()=0
Session_Manager & session_manager()
std::unique_ptr< Cipher_State > m_cipher_state
const Connection_Side m_side
bool is_active() const override
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)
bool is_downgrading() const
bool expects_downgrade() const
void send_fatal_alert(Alert::Type type)
virtual bool is_handshake_complete() const =0
static constexpr size_t IO_BUF_DEFAULT_SIZE
bool expects_reciprocation() const
void disable_sending_compat_mode()
std::vector< uint8_t > prepare_records(Record_Type type, std::span< const uint8_t > data, Cipher_State *cipher_state=nullptr) const
detail::as_wrapped_references_t< Handshake_Message_13 > Handshake_Message_13_Ref
std::variant< New_Session_Ticket_13, Key_Update > Post_Handshake_Message_13
constexpr bool holds_any_of(const std::variant< Ts... > &v) noexcept
std::vector< T, secure_allocator< T > > secure_vector