/* * TLS Channel * (C) 2011,2012,2014,2015 Jack Lloyd * 2016 Matthias Gierlings * 2021 Elektrobit Automotive GmbH * 2022 René Meusel, Hannes Rantzsch - neXenio GmbH * * Botan is released under the Simplified BSD License (see license.txt) */ #ifndef BOTAN_TLS_CHANNEL_IMPL_H_ #define BOTAN_TLS_CHANNEL_IMPL_H_ #include #include #include #include #include #include #include namespace Botan { class Credentials_Manager; class X509_Certificate; namespace TLS { class Client; class Server; enum class Record_Type : uint8_t { Invalid = 0, // RFC 8446 (TLS 1.3) ChangeCipherSpec = 20, Alert = 21, Handshake = 22, ApplicationData = 23, Heartbeat = 24, // RFC 6520 (TLS 1.3) }; class Channel_Impl { public: virtual ~Channel_Impl() = default; /** * Inject TLS traffic received from counterparty * @return a hint as the how many more bytes we need to q the * current record (this may be 0 if on a record boundary) */ virtual size_t from_peer(std::span data) = 0; /** * Inject plaintext intended for counterparty * Throws an exception if is_active() is false */ virtual void to_peer(std::span data) = 0; /** * Send a TLS alert message. If the alert is fatal, the internal * state (keys, etc) will be reset. * @param alert the Alert to send */ virtual void send_alert(const Alert& alert) = 0; /** * Send a warning alert */ void send_warning_alert(Alert::Type type) { send_alert(Alert(type, false)); } /** * Send a fatal alert */ void send_fatal_alert(Alert::Type type) { send_alert(Alert(type, true)); } /** * Send a close notification alert */ void close() { send_warning_alert(Alert::CloseNotify); } /** * @return true iff the TLS handshake has finished successfully */ virtual bool is_handshake_complete() const = 0; /** * @return true iff the connection is active for sending application data */ virtual bool is_active() const = 0; /** * @return true iff the connection has been definitely closed */ virtual bool is_closed() const = 0; /** * @return true iff the connection is active for sending application data */ virtual bool is_closed_for_reading() const = 0; /** * @return true iff the connection has been definitely closed */ virtual bool is_closed_for_writing() const = 0; /** * @return certificate chain of the peer (may be empty) */ virtual std::vector peer_cert_chain() const = 0; /** * @return raw public key of the peer (may be nullptr) */ virtual std::shared_ptr peer_raw_public_key() const = 0; /** * @return identity of the PSK used for this connection * or std::nullopt if no PSK was used. */ virtual std::optional external_psk_identity() const = 0; /** * Key material export (RFC 5705) * @param label a disambiguating label string * @param context a per-association context value * @param length the length of the desired key in bytes * @return key of length bytes */ virtual SymmetricKey key_material_export(std::string_view label, std::string_view context, size_t length) const = 0; /** * Attempt to renegotiate the session * @param force_full_renegotiation if true, require a full renegotiation, * otherwise allow session resumption */ virtual void renegotiate(bool force_full_renegotiation = false) = 0; /** * @return true if this channel can issue TLS 1.3 style session tickets. */ virtual bool new_session_ticket_supported() const { return false; } /** * Send @p tickets new session tickets to the peer. This is only supported * on TLS 1.3 servers. * * If the server's Session_Manager does not accept the generated Session * objects, the server implementation won't be able to send new tickets. * Additionally, anything but TLS 1.3 servers will return 0 (because they * don't support sending such session tickets). * * @returns the number of session tickets successfully sent to the client */ virtual size_t send_new_session_tickets(const size_t /* tickets */) { return 0; } /** * Attempt to update the session's traffic key material * Note that this is possible with a TLS 1.3 channel, only. * * @param request_peer_update if true, require a reciprocal key update */ virtual void update_traffic_keys(bool request_peer_update = false) = 0; /** * @return true iff the counterparty supports the secure * renegotiation extensions. */ virtual bool secure_renegotiation_supported() const = 0; /** * Perform a handshake timeout check. This does nothing unless * this is a DTLS channel with a pending handshake state, in * which case we check for timeout and potentially retransmit * handshake packets. */ virtual bool timeout_check() = 0; /** * Return the protocol notification set for this connection, if any (ALPN). * This value is not tied to the session and a later renegotiation of the * same session can choose a new protocol. */ virtual std::string application_protocol() const = 0; protected: /** * This struct collect all information required to perform a downgrade from TLS 1.3 to TLS 1.2. * * The downgrade process is (currently) triggered when a TLS 1.3 client receives a downgrade request * in the server hello message (@sa `Client_Impl_13::handle(Server_Hello_12)`). As a result, * `Client::received_data` should detect this condition and replace its `Channel_Impl_13` member by a * `Channel_Impl_12`. * * Note that the downgrade process for the server implementation will likely differ. */ struct Downgrade_Information { /// The client hello message including the handshake header bytes as transferred to the peer. std::vector client_hello_message; /// The full data transcript received from the peer. This will contain the server hello message that forced us to downgrade. std::vector peer_transcript; /// The TLS 1.2 session information found by a TLS 1.3 client that /// caused it to initiate a downgrade before even sending a client hello. std::optional tls12_session; Server_Information server_info; std::vector next_protocols; size_t io_buffer_size; std::shared_ptr callbacks; std::shared_ptr session_manager; std::shared_ptr creds; std::shared_ptr rng; std::shared_ptr policy; bool received_tls_13_error_alert; bool will_downgrade; }; std::unique_ptr m_downgrade_info; void preserve_peer_transcript(std::span input) { BOTAN_STATE_CHECK(m_downgrade_info); m_downgrade_info->peer_transcript.insert(m_downgrade_info->peer_transcript.end(), input.begin(), input.end()); } void preserve_client_hello(std::span msg) { BOTAN_STATE_CHECK(m_downgrade_info); m_downgrade_info->client_hello_message.assign(msg.begin(), msg.end()); } friend class Client; friend class Server; void set_io_buffer_size(size_t io_buf_sz) { BOTAN_STATE_CHECK(m_downgrade_info); m_downgrade_info->io_buffer_size = io_buf_sz; } /** * Implementations use this to signal that the peer indicated a protocol * version downgrade. After calling `request_downgrade()` no further * state changes must be perfomed by the implementation. Particularly, no * further handshake messages must be emitted. Instead, they must yield * control flow back to the underlying Channel implementation to perform * the protocol version downgrade. */ void request_downgrade() { BOTAN_STATE_CHECK(m_downgrade_info && !m_downgrade_info->will_downgrade); m_downgrade_info->will_downgrade = true; } void request_downgrade_for_resumption(Session_with_Handle session) { BOTAN_STATE_CHECK(m_downgrade_info && m_downgrade_info->client_hello_message.empty() && m_downgrade_info->peer_transcript.empty() && !m_downgrade_info->tls12_session.has_value()); BOTAN_ASSERT_NOMSG(session.session.version().is_pre_tls_13()); m_downgrade_info->tls12_session = std::move(session); request_downgrade(); } public: /** * Indicates whether a downgrade to TLS 1.2 or lower is in progress * * @sa Downgrade_Information */ bool is_downgrading() const { return m_downgrade_info && m_downgrade_info->will_downgrade; } /** * @sa Downgrade_Information */ std::unique_ptr extract_downgrade_info() { return std::exchange(m_downgrade_info, {}); } bool expects_downgrade() const { return m_downgrade_info != nullptr; } }; } // namespace TLS } // namespace Botan #endif