Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/bogo_shim/bogo_shim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,9 @@ std::string map_to_bogo_error(const std::string& e) noexcept {
{"Received an encrypted record that exceeds maximum size", ":ENCRYPTED_LENGTH_TOO_LONG:"},
{"received an illegal handshake message", ":UNEXPECTED_MESSAGE:"},
{"Received a legacy Client Hello", ":UNSUPPORTED_PROTOCOL:"},
{"Received an unsupported Client Hello", ":UNSUPPORTED_PROTOCOL:"},
{"Received an unexpected legacy Server Hello", ":UNSUPPORTED_PROTOCOL:"},
{"Received an unsupported Server Hello", ":UNSUPPORTED_PROTOCOL:"},
{"Received application data after connection closure", ":APPLICATION_DATA_ON_SHUTDOWN:"},
{"Received handshake data after connection closure", ":NO_RENEGOTIATION:"},
{"Received multiple key share entries for the same group", ":DUPLICATE_KEY_SHARE:"},
Expand Down
4 changes: 4 additions & 0 deletions src/lib/tls/tls12/tls_client_impl_12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ Client_Impl_12::Client_Impl_12(const std::shared_ptr<Callbacks>& callbacks,
send_client_hello(state, false, version, std::nullopt /* no a-priori session to resume */, next_protocols);
}

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)

Client_Impl_12::Client_Impl_12(const Channel_Impl::Downgrade_Information& downgrade_info) :
Channel_Impl_12(downgrade_info.callbacks,
downgrade_info.session_manager,
Expand Down Expand Up @@ -152,6 +154,8 @@ Client_Impl_12::Client_Impl_12(const Channel_Impl::Downgrade_Information& downgr
}
}

#endif

std::unique_ptr<Handshake_State> Client_Impl_12::new_handshake_state(std::unique_ptr<Handshake_IO> io) {
return std::make_unique<Client_Handshake_State_12>(std::move(io), callbacks());
}
Expand Down
4 changes: 4 additions & 0 deletions src/lib/tls/tls12/tls_client_impl_12.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,12 @@ class Client_Impl_12 final : public Channel_Impl_12 {
const std::vector<std::string>& next_protocols = {},
size_t reserved_io_buffer_size = TLS::Channel::IO_BUF_DEFAULT_SIZE);

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)

explicit Client_Impl_12(const Channel_Impl::Downgrade_Information& downgrade_info);

#endif

/**
* @return network protocol as advertised by the TLS server, if server sent the ALPN extension
*/
Expand Down
4 changes: 4 additions & 0 deletions src/lib/tls/tls12/tls_server_impl_12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ Server_Impl_12::Server_Impl_12(const std::shared_ptr<Callbacks>& callbacks,
}
}

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)

Server_Impl_12::Server_Impl_12(const Channel_Impl::Downgrade_Information& downgrade_info) :
Channel_Impl_12(downgrade_info.callbacks,
downgrade_info.session_manager,
Expand All @@ -310,6 +312,8 @@ Server_Impl_12::Server_Impl_12(const Channel_Impl::Downgrade_Information& downgr
downgrade_info.io_buffer_size),
m_creds(downgrade_info.creds) {}

#endif

std::unique_ptr<Handshake_State> Server_Impl_12::new_handshake_state(std::unique_ptr<Handshake_IO> io) {
auto state = std::make_unique<Server_Handshake_State>(std::move(io), callbacks());
state->set_expected_next(Handshake_Type::ClientHello);
Expand Down
2 changes: 2 additions & 0 deletions src/lib/tls/tls12/tls_server_impl_12.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ class Server_Impl_12 final : public Channel_Impl_12 {
bool is_datagram = false,
size_t reserved_io_buffer_size = TLS::Channel::IO_BUF_DEFAULT_SIZE);

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
explicit Server_Impl_12(const Channel_Impl::Downgrade_Information& downgrade_info);
#endif

private:
/**
Expand Down
22 changes: 17 additions & 5 deletions src/lib/tls/tls13/tls_channel_impl_13.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,11 @@ size_t Channel_Impl_13::from_peer(std::span<const uint8_t> data) {
}

try {
#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
if(expects_downgrade()) {
preserve_peer_transcript(data);
}
#endif

m_record_layer.copy_data(data);

Expand Down Expand Up @@ -144,6 +146,7 @@ size_t Channel_Impl_13::from_peer(std::span<const uint8_t> data) {

process_handshake_msg(std::move(handshake_msg.value()));

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
if(is_downgrading()) {
// Downgrade to TLS 1.2 was detected. Stop everything we do and await being replaced by a 1.2 implementation.
return 0;
Expand All @@ -157,6 +160,7 @@ size_t Channel_Impl_13::from_peer(std::span<const uint8_t> data) {
// Downgrade can only be indicated in the first received peer message. This was not the case.
m_downgrade_info.reset();
}
#endif

// After the initial handshake message is received, the record
// layer must be more restrictive.
Expand Down Expand Up @@ -400,15 +404,19 @@ void Channel_Impl_13::process_alert(const secure_vector<uint8_t>& record) {
// regardless of the AlertLevel in the message. Unknown Alert types
// MUST be treated as error alerts.
if(is_error_alert(alert) && !alert.is_fatal()) {
if(!expects_downgrade()) {
throw TLS_Exception(Alert::DecodeError, "Error alert not marked fatal");
}

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
BOTAN_DEBUG_ASSERT(expects_downgrade());

// In TLS 1.2 error alerts might be marked as 'warnings' and would not
// demand an immediate shutdown. Until we are sure to talk to a TLS 1.3
// peer we must defer the shutdown and refrain from raising a decode
// error.
if(expects_downgrade()) {
m_downgrade_info->received_tls_13_error_alert = true;
} else {
throw TLS_Exception(Alert::DecodeError, "Error alert not marked fatal"); // will shutdown in send_alert
}
m_downgrade_info->received_tls_13_error_alert = true;
#endif
}

if(alert.is_fatal()) {
Expand All @@ -433,6 +441,8 @@ void Channel_Impl_13::shutdown() {
m_active_state.reset();
}

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)

void Channel_Impl_13::expect_downgrade(const Server_Information& server_info,
const std::vector<std::string>& next_protocols) {
Downgrade_Information di{
Expand All @@ -453,6 +463,8 @@ void Channel_Impl_13::expect_downgrade(const Server_Information& server_info,
m_downgrade_info = std::make_unique<Downgrade_Information>(std::move(di));
}

#endif

void Channel_Impl_13::set_record_size_limits(const uint16_t outgoing_limit, const uint16_t incoming_limit) {
m_record_layer.set_record_size_limits(outgoing_limit, incoming_limit);
}
Expand Down
2 changes: 2 additions & 0 deletions src/lib/tls/tls13/tls_channel_impl_13.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ class Channel_Impl_13 : public Channel_Impl,
std::unique_ptr<Cipher_State> m_cipher_state; // NOLINT(*non-private-member-variable*)
std::optional<Active_Connection_State_13> m_active_state; // NOLINT(*non-private-member-variable*)

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
/**
* Indicate that we have to expect a downgrade to TLS 1.2. In which case the current
* implementation (i.e. Client_Impl_13 or Server_Impl_13) will need to be replaced
Expand All @@ -303,6 +304,7 @@ class Channel_Impl_13 : public Channel_Impl,
* @sa `Channel_Impl::Downgrade_Information`
*/
void expect_downgrade(const Server_Information& server_info, const std::vector<std::string>& next_protocols);
#endif

/**
* Set the record size limits as negotiated by the "record_size_limit"
Expand Down
17 changes: 14 additions & 3 deletions src/lib/tls/tls13/tls_client_impl_13.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,24 @@ Client_Impl_13::Client_Impl_13(const std::shared_ptr<Callbacks>& callbacks,
Channel_Impl_13(callbacks, session_manager, creds, rng, policy, false /* is_server */),
m_info(std::move(info)),
m_handshake(std::make_unique<Pending_Handshake>()) {
#if defined(BOTAN_HAS_TLS_12)
#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
if(policy->allow_tls12()) {
expect_downgrade(m_info, next_protocols);
}
#endif

if(auto session = find_session_for_resumption()) {
if(!session->session.version().is_pre_tls_13()) {
if(session->session.version().is_tls_13_or_later()) {
m_handshake->resumed_session = std::move(session);
} else if(expects_downgrade()) {
}
#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
else if(expects_downgrade()) {
// If we found a session that was created with TLS 1.2, we downgrade
// the implementation right away, before even issuing a Client Hello.
request_downgrade_for_resumption(std::move(session.value()));
return;
}
#endif
}

auto msg = send_handshake_message(m_handshake->state.sending(
Expand All @@ -59,9 +62,11 @@ Client_Impl_13::Client_Impl_13(const std::shared_ptr<Callbacks>& callbacks,
m_handshake->resumed_session,
creds->find_preshared_keys(m_info.hostname(), Connection_Side::Client))));

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
if(expects_downgrade()) {
preserve_client_hello(msg);
}
#endif

maybe_handle_compatibility_mode(Compat_Mode_Situation::AfterSendingFirstClientHello);

Expand Down Expand Up @@ -155,6 +160,11 @@ void Client_Impl_13::handle(const Server_Hello_12_Shim& server_hello_msg) {
throw TLS_Exception(Alert::UnexpectedMessage, "Version downgrade received after Hello Retry");
}

#if !defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
BOTAN_UNUSED(server_hello_msg);
throw TLS_Exception(Alert::ProtocolVersion, "Received an unsupported Server Hello");
#else

// RFC 8446 Appendix D.1
// If the version chosen by the server is not supported by the client
// (or is not acceptable), the client MUST abort the handshake with a
Expand Down Expand Up @@ -211,6 +221,7 @@ void Client_Impl_13::handle(const Server_Hello_12_Shim& server_hello_msg) {
// After this, no further messages are expected here because this instance will be replaced
// by a Client_Impl_12.
m_handshake->transitions.set_expected_next({});
#endif
}

namespace {
Expand Down
9 changes: 9 additions & 0 deletions src/lib/tls/tls13/tls_server_impl_13.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ void Server_Impl_13::maybe_log_secret(std::string_view label, std::span<const ui
}
}

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)

void Server_Impl_13::downgrade() {
BOTAN_ASSERT_NOMSG(expects_downgrade());

Expand All @@ -220,6 +222,8 @@ void Server_Impl_13::downgrade() {
m_handshake->transitions.set_expected_next({});
}

#endif

void Server_Impl_13::maybe_handle_compatibility_mode(Compat_Mode_Situation situation) {
// RFC 9846 E.4
// This "compatibility mode" is partially negotiated: the client can opt
Expand Down Expand Up @@ -490,6 +494,10 @@ void Server_Impl_13::handle(const Client_Hello_12_Shim& ch) {
throw TLS_Exception(Alert::UnexpectedMessage, "Received a TLS 1.2 Client Hello after Hello Retry Request");
}

#if !defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
throw TLS_Exception(Alert::ProtocolVersion, "Received an unsupported Client Hello");
#else

// RFC 8446 Appendix D.2
// If the "supported_versions" extension is absent and the server only
// supports versions greater than ClientHello.legacy_version, the server
Expand All @@ -501,6 +509,7 @@ void Server_Impl_13::handle(const Client_Hello_12_Shim& ch) {
}

downgrade();
#endif
}

void Server_Impl_13::handle(const Client_Hello_13& client_hello) {
Expand Down
2 changes: 2 additions & 0 deletions src/lib/tls/tls13/tls_server_impl_13.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ class Server_Impl_13 final : public Channel_Impl_13 {
void maybe_handle_compatibility_mode(Compat_Mode_Situation situation) override;
void maybe_log_secret(std::string_view label, std::span<const uint8_t> secret) const override;

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
void downgrade();
#endif

private:
struct Pending_Handshake {
Expand Down
4 changes: 4 additions & 0 deletions src/lib/tls/tls_channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include <string_view>
#include <vector>

#if defined(BOTAN_HAS_TLS_13) && defined(BOTAN_HAS_TLS_12)
#define BOTAN_HAS_TLS_DOWNGRADE_SUPPORT
#endif

namespace Botan {

class Public_Key;
Expand Down
26 changes: 21 additions & 5 deletions src/lib/tls/tls_channel_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ class Channel_Impl {
protected:
Channel_Impl() = default;

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)

/**
* This struct collect all information required to perform a downgrade from TLS 1.3 to TLS 1.2.
*
Expand Down Expand Up @@ -262,18 +264,32 @@ class Channel_Impl {

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; }
std::unique_ptr<Downgrade_Information> extract_downgrade_info() { return std::exchange(m_downgrade_info, {}); }

#endif

/**
* Indicates whether a downgrade to TLS 1.2 or lower is in progress
*
* @sa Downgrade_Information
*/
std::unique_ptr<Downgrade_Information> extract_downgrade_info() { return std::exchange(m_downgrade_info, {}); }
bool is_downgrading() const {
#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
return m_downgrade_info && m_downgrade_info->will_downgrade;
#else
return false;
#endif
}

bool expects_downgrade() const { return m_downgrade_info != nullptr; }
bool expects_downgrade() const {
#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
return m_downgrade_info != nullptr;
#else
return false;
#endif
}
};

} // namespace TLS
Expand Down
14 changes: 8 additions & 6 deletions src/lib/tls/tls_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Client::Client(const std::shared_ptr<Callbacks>& callbacks,
m_impl = std::make_unique<Client_Impl_13>(
callbacks, session_manager, creds, policy, rng, std::move(info), next_protocols);

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
if(m_impl->expects_downgrade()) {
m_impl->set_io_buffer_size(io_buf_sz);
}
Expand All @@ -53,6 +54,7 @@ Client::Client(const std::shared_ptr<Callbacks>& callbacks,
// requested a downgrade right away.
downgrade();
}
#endif

return;
}
Expand All @@ -79,10 +81,11 @@ Client::Client(const std::shared_ptr<Callbacks>& callbacks,

Client::~Client() = default;

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)

size_t Client::downgrade() {
BOTAN_ASSERT_NOMSG(m_impl->is_downgrading());

#if defined(BOTAN_HAS_TLS_12)
auto info = m_impl->extract_downgrade_info();
m_impl = std::make_unique<Client_Impl_12>(*info);

Expand All @@ -94,19 +97,18 @@ size_t Client::downgrade() {
// before any data was transferred
return 0;
}
#else
// If TLS 1.2 is not available, we will never downgrade, the downgrade info
// won't even be created and `is_downgrading()` would always return false.
BOTAN_ASSERT_UNREACHABLE();
#endif
}

#endif

size_t Client::from_peer(std::span<const uint8_t> data) {
auto read = m_impl->from_peer(data);

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
if(m_impl->is_downgrading()) {
read = downgrade();
}
#endif

return read;
}
Expand Down
4 changes: 4 additions & 0 deletions src/lib/tls/tls_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,13 @@ class BOTAN_PUBLIC_API(2, 0) Client final : public Channel {
Client& operator=(const Client& other) = delete;
Client& operator=(Client&& other) = delete;

#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)

private:
size_t downgrade();

#endif

private:
std::unique_ptr<Channel_Impl> m_impl;
};
Expand Down
Loading
Loading