Botan 3.12.0
Crypto and TLS for C&
Botan::TLS::Client_Impl_12 Class Referencefinalabstract

#include <tls_client_impl_12.h>

Inheritance diagram for Botan::TLS::Client_Impl_12:
Botan::TLS::Channel_Impl_12 Botan::TLS::Channel_Impl

Public Member Functions

std::string application_protocol () const override
 Client_Impl_12 (const Channel_Impl::Downgrade_Information &downgrade_info)
 Client_Impl_12 (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(), bool datagram=false, const std::vector< std::string > &next_protocols={}, size_t reserved_io_buffer_size=TLS::Channel::IO_BUF_DEFAULT_SIZE)
void close ()
bool expects_downgrade () const
std::optional< std::string > external_psk_identity () const override
std::unique_ptr< Downgrade_Informationextract_downgrade_info ()
size_t from_peer (std::span< const uint8_t > data) override
bool is_active () const override
bool is_closed () const override
bool is_closed_for_reading () const override
bool is_closed_for_writing () const override
bool is_downgrading () const
bool is_handshake_complete () const override
SymmetricKey key_material_export (std::string_view label, std::string_view context, size_t length) const override
virtual bool new_session_ticket_supported () const
std::vector< X509_Certificatepeer_cert_chain () const override
std::shared_ptr< const Public_Keypeer_raw_public_key () const override
void renegotiate (bool force_full_renegotiation=false) override
bool secure_renegotiation_supported () const override
void send_alert (const Alert &alert) override
void send_fatal_alert (Alert::Type type)
virtual size_t send_new_session_tickets (const size_t)
void send_warning_alert (Alert::Type type)
bool timeout_check () override
void to_peer (std::span< const uint8_t > data) override
void update_traffic_keys (bool request_peer_update=false) override

Protected Member Functions

void activate_session ()
const std::optional< Active_Connection_State_12 > & active_state () const
Callbackscallbacks () const
void change_cipher_spec_reader (Connection_Side side)
void change_cipher_spec_writer (Connection_Side side)
Handshake_Statecreate_handshake_state (Protocol_Version version)
void inspect_handshake_message (const Handshake_Message &msg)
virtual std::unique_ptr< Handshake_Statenew_handshake_state (std::unique_ptr< class Handshake_IO > io)=0
const Policypolicy () const
void preserve_client_hello (std::span< const uint8_t > msg)
void preserve_peer_transcript (std::span< const uint8_t > input)
void request_downgrade ()
void request_downgrade_for_resumption (Session_with_Handle session)
void reset_active_association_state ()
RandomNumberGeneratorrng ()
void secure_renegotiation_check (const Client_Hello_12 *client_hello)
void secure_renegotiation_check (const Server_Hello_12 *server_hello)
std::vector< uint8_t > secure_renegotiation_data_for_client_hello () const
std::vector< uint8_t > secure_renegotiation_data_for_server_hello () const
Session_Managersession_manager ()
void set_io_buffer_size (size_t io_buf_sz)

Protected Attributes

std::unique_ptr< Downgrade_Informationm_downgrade_info

Detailed Description

SSL/TLS Client 1.2 implementation

Definition at line 23 of file tls_client_impl_12.h.

Constructor & Destructor Documentation

◆ Client_Impl_12() [1/2]

Botan::TLS::Client_Impl_12::Client_Impl_12 ( 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(),
bool datagram = false,
const std::vector< std::string > & next_protocols = {},
size_t reserved_io_buffer_size = TLS::Channel::IO_BUF_DEFAULT_SIZE )
explicit

Set up a new TLS client session

Parameters
callbackscontains a set of callback function references required by the TLS client.
session_managermanages session state
credsmanages application/user credentials
policyspecifies other connection policy information
rnga random number generator
server_infois identifying information about the TLS server
datagramspecifies whether to use TLS 1.2 or DTLS 1.2
next_protocolsspecifies protocols to advertise with ALPN
reserved_io_buffer_sizeThis many bytes of memory will be preallocated for the read and write buffers. Smaller values just mean reallocations and copies are more likely.

Definition at line 100 of file tls_client_impl_12.cpp.

108 :
109 Channel_Impl_12(callbacks, session_manager, rng, policy, false, datagram, io_buf_sz),
110 m_creds(creds),
111 m_info(std::move(info)) {
112 BOTAN_ASSERT_NONNULL(m_creds);
113 const auto version = datagram ? Protocol_Version::DTLS_V12 : Protocol_Version::TLS_V12;
114 Handshake_State& state = create_handshake_state(version);
115 send_client_hello(state, false, version, std::nullopt /* no a-priori session to resume */, next_protocols);
116}
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
RandomNumberGenerator & rng()
Handshake_State & create_handshake_state(Protocol_Version version)
Session_Manager & session_manager()
const Policy & policy() const
Channel_Impl_12(const std::shared_ptr< Callbacks > &callbacks, const std::shared_ptr< Session_Manager > &session_manager, const std::shared_ptr< RandomNumberGenerator > &rng, const std::shared_ptr< const Policy > &policy, bool is_server, bool is_datagram, size_t io_buf_sz=TLS::Channel::IO_BUF_DEFAULT_SIZE)

References BOTAN_ASSERT_NONNULL, Botan::TLS::Channel_Impl_12::callbacks(), Botan::TLS::Channel_Impl_12::Channel_Impl_12(), Botan::TLS::Channel_Impl_12::create_handshake_state(), Botan::TLS::Channel_Impl_12::policy(), Botan::TLS::Channel_Impl_12::rng(), and Botan::TLS::Channel_Impl_12::session_manager().

◆ Client_Impl_12() [2/2]

Botan::TLS::Client_Impl_12::Client_Impl_12 ( const Channel_Impl::Downgrade_Information & downgrade_info)
explicit

Definition at line 118 of file tls_client_impl_12.cpp.

118 :
119 Channel_Impl_12(downgrade_info.callbacks,
120 downgrade_info.session_manager,
121 downgrade_info.rng,
122 downgrade_info.policy,
123 false /* is_server */,
124 false /* datagram -- not supported by Botan in TLS 1.3 */,
125 downgrade_info.io_buffer_size),
126 m_creds(downgrade_info.creds),
127 m_info(downgrade_info.server_info) {
128 Handshake_State& state = create_handshake_state(Protocol_Version::TLS_V12);
129
130 if(!downgrade_info.client_hello_message.empty()) {
131 // Downgrade detected after receiving a TLS 1.2 server hello. We need to
132 // recreate the state as if this implementation issued the client hello.
133 const std::vector<uint8_t> client_hello_msg(
134 downgrade_info.client_hello_message.begin() + 4 /* handshake header length */,
135 downgrade_info.client_hello_message.end());
136
137 state.client_hello(std::make_unique<Client_Hello_12>(client_hello_msg));
138 state.hash().update(downgrade_info.client_hello_message);
139
140 secure_renegotiation_check(state.client_hello());
141 state.set_expected_next(Handshake_Type::ServerHello);
142 } else {
143 // Downgrade initiated after a TLS 1.2 session was found. No communication
144 // has happened yet but the found session should be used for resumption.
145 BOTAN_ASSERT_NOMSG(downgrade_info.tls12_session.has_value() &&
146 downgrade_info.tls12_session->session.version().is_pre_tls_13());
147 send_client_hello(state,
148 false,
149 downgrade_info.tls12_session->session.version(),
150 downgrade_info.tls12_session,
151 downgrade_info.next_protocols);
152 }
153}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
void secure_renegotiation_check(const Client_Hello_12 *client_hello)

References BOTAN_ASSERT_NOMSG, Botan::TLS::Channel_Impl_12::callbacks(), Botan::TLS::Channel_Impl_12::Channel_Impl_12(), Botan::TLS::Handshake_State::client_hello(), Botan::TLS::Channel_Impl::Downgrade_Information::client_hello_message, Botan::TLS::Channel_Impl_12::create_handshake_state(), Botan::TLS::Handshake_State::hash(), Botan::TLS::Channel_Impl::Downgrade_Information::next_protocols, Botan::TLS::Channel_Impl_12::policy(), Botan::TLS::Channel_Impl_12::rng(), Botan::TLS::Channel_Impl_12::secure_renegotiation_check(), Botan::TLS::ServerHello, Botan::TLS::Channel_Impl_12::session_manager(), Botan::TLS::Handshake_State::set_expected_next(), Botan::TLS::Channel_Impl::Downgrade_Information::tls12_session, and Botan::TLS::Handshake_Hash::update().

Member Function Documentation

◆ activate_session()

void Botan::TLS::Channel_Impl_12::activate_session ( )
protectedinherited

Definition at line 266 of file tls_channel_impl_12.cpp.

266 {
267 BOTAN_ASSERT_NONNULL(m_pending_state);
268
269 const auto& state = *m_pending_state;
270
271 if(!state.version().is_datagram_protocol()) {
272 // TLS is easy just remove all but the current state
273 const uint16_t current_epoch = sequence_numbers().current_write_epoch();
274
275 const auto not_current_epoch = [current_epoch](uint16_t epoch) { return (epoch != current_epoch); };
276
277 map_remove_if(not_current_epoch, m_write_cipher_states);
278 map_remove_if(not_current_epoch, m_read_cipher_states);
279 }
280
281 // For DTLS, keep the handshake IO for last-flight retransmission.
282 if(m_is_datagram) {
283 m_active_state = Active_Connection_State_12(state, application_protocol(), m_pending_state->take_handshake_io());
284 } else {
285 m_active_state = Active_Connection_State_12(state, application_protocol());
286 }
287
288 m_pending_state.reset();
289
291}
virtual void tls_session_activated()
virtual std::string application_protocol() const =0
void map_remove_if(Pred pred, T &assoc)
Definition stl_util.h:54

References Botan::TLS::Channel_Impl::application_protocol(), BOTAN_ASSERT_NONNULL, callbacks(), Botan::map_remove_if(), and Botan::TLS::Callbacks::tls_session_activated().

◆ active_state()

const std::optional< Active_Connection_State_12 > & Botan::TLS::Channel_Impl_12::active_state ( ) const
inlineprotectedinherited

Definition at line 153 of file tls_channel_impl_12.h.

153{ return m_active_state; }

◆ application_protocol()

std::string Botan::TLS::Client_Impl_12::application_protocol ( ) const
inlineoverridevirtual
Returns
network protocol as advertised by the TLS server, if server sent the ALPN extension

Implements Botan::TLS::Channel_Impl.

Definition at line 64 of file tls_client_impl_12.h.

64{ return m_application_protocol; }

◆ callbacks()

◆ change_cipher_spec_reader()

void Botan::TLS::Channel_Impl_12::change_cipher_spec_reader ( Connection_Side side)
protectedinherited

Definition at line 202 of file tls_channel_impl_12.cpp.

202 {
203 const auto* pending = pending_state();
204
205 BOTAN_ASSERT(pending && pending->server_hello(), "Have received server hello");
206
207 if(pending->server_hello()->compression_method() != 0) {
208 throw Internal_Error("Negotiated unknown compression algorithm");
209 }
210
211 sequence_numbers().new_read_cipher_state();
212
213 const uint16_t epoch = sequence_numbers().current_read_epoch();
214
215 BOTAN_ASSERT(!m_read_cipher_states.contains(epoch), "No read cipher state currently set for next epoch");
216
217 // flip side as we are reading
218 auto read_state = std::make_shared<Connection_Cipher_State>(
219 pending->version(),
221 false,
222 pending->ciphersuite(),
223 pending->session_keys(),
224 pending->server_hello()->supports_encrypt_then_mac());
225
226 m_read_cipher_states[epoch] = read_state;
227}
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:62

References BOTAN_ASSERT, Botan::TLS::Client, and Botan::TLS::Server.

◆ change_cipher_spec_writer()

void Botan::TLS::Channel_Impl_12::change_cipher_spec_writer ( Connection_Side side)
protectedinherited

Definition at line 229 of file tls_channel_impl_12.cpp.

229 {
230 const auto* pending = pending_state();
231
232 BOTAN_ASSERT(pending && pending->server_hello(), "Have received server hello");
233
234 if(pending->server_hello()->compression_method() != 0) {
235 throw Internal_Error("Negotiated unknown compression algorithm");
236 }
237
238 sequence_numbers().new_write_cipher_state();
239
240 const uint16_t epoch = sequence_numbers().current_write_epoch();
241
242 BOTAN_ASSERT(!m_write_cipher_states.contains(epoch), "No write cipher state currently set for next epoch");
243
244 auto write_state = std::make_shared<Connection_Cipher_State>(pending->version(),
245 side,
246 true,
247 pending->ciphersuite(),
248 pending->session_keys(),
249 pending->server_hello()->supports_encrypt_then_mac());
250
251 m_write_cipher_states[epoch] = write_state;
252}

References BOTAN_ASSERT.

◆ close()

void Botan::TLS::Channel_Impl::close ( )
inlineinherited

Send a close notification alert

Definition at line 76 of file tls_channel_impl.h.

76{ send_warning_alert(Alert::CloseNotify); }
void send_warning_alert(Alert::Type type)

References send_warning_alert().

◆ create_handshake_state()

Handshake_State & Botan::TLS::Channel_Impl_12::create_handshake_state ( Protocol_Version version)
protectedinherited

Definition at line 117 of file tls_channel_impl_12.cpp.

117 {
118 if(pending_state() != nullptr) {
119 throw Internal_Error("create_handshake_state called during handshake");
120 }
121
122 if(m_active_state.has_value()) {
123 const Protocol_Version active_version = m_active_state->version();
124
125 if(active_version.is_datagram_protocol() != version.is_datagram_protocol()) {
126 throw TLS_Exception(Alert::ProtocolVersion,
127 "Active state using version " + active_version.to_string() + " cannot change to " +
128 version.to_string() + " in pending");
129 }
130 }
131
132 if(!m_sequence_numbers) {
133 if(version.is_datagram_protocol()) {
134 m_sequence_numbers = std::make_unique<Datagram_Sequence_Numbers>();
135 } else {
136 m_sequence_numbers = std::make_unique<Stream_Sequence_Numbers>();
137 }
138 }
139
140 using namespace std::placeholders;
141
142 std::unique_ptr<Handshake_IO> io;
143 if(version.is_datagram_protocol()) {
144 const uint16_t mtu = static_cast<uint16_t>(policy().dtls_default_mtu());
145 const size_t initial_timeout_ms = policy().dtls_initial_timeout();
146 const size_t max_timeout_ms = policy().dtls_maximum_timeout();
147
148 auto send_record_f = [this](uint16_t epoch, Record_Type record_type, const std::vector<uint8_t>& record) {
149 send_record_under_epoch(epoch, record_type, record);
150 };
151 io = std::make_unique<Datagram_Handshake_IO>(send_record_f,
152 sequence_numbers(),
153 mtu,
154 initial_timeout_ms,
155 max_timeout_ms,
156 policy().maximum_handshake_message_size());
157 } else {
158 auto send_record_f = [this](Record_Type rec_type, const std::vector<uint8_t>& record) {
159 send_record(rec_type, record);
160 };
161 io = std::make_unique<Stream_Handshake_IO>(send_record_f);
162 }
163
164 m_pending_state = new_handshake_state(std::move(io));
165
166 if(m_active_state.has_value()) {
167 m_pending_state->set_version(m_active_state->version());
168 }
169
170 return *m_pending_state;
171}
virtual std::unique_ptr< Handshake_State > new_handshake_state(std::unique_ptr< class Handshake_IO > io)=0
virtual size_t dtls_maximum_timeout() const
virtual size_t dtls_default_mtu() const
virtual size_t dtls_initial_timeout() const

References Botan::TLS::Policy::dtls_default_mtu(), Botan::TLS::Policy::dtls_initial_timeout(), Botan::TLS::Policy::dtls_maximum_timeout(), Botan::TLS::Protocol_Version::is_datagram_protocol(), new_handshake_state(), policy(), and Botan::TLS::Protocol_Version::to_string().

Referenced by Botan::TLS::Client_Impl_12::Client_Impl_12(), Botan::TLS::Client_Impl_12::Client_Impl_12(), and renegotiate().

◆ expects_downgrade()

bool Botan::TLS::Channel_Impl::expects_downgrade ( ) const
inlineinherited

Definition at line 276 of file tls_channel_impl.h.

276{ return m_downgrade_info != nullptr; }
std::unique_ptr< Downgrade_Information > m_downgrade_info

References m_downgrade_info.

Referenced by Botan::TLS::Client_Impl_13::Client_Impl_13(), and Botan::TLS::Channel_Impl_13::from_peer().

◆ external_psk_identity()

std::optional< std::string > Botan::TLS::Channel_Impl_12::external_psk_identity ( ) const
overridevirtualinherited
Returns
identity of the PSK used for this connection or std::nullopt if no PSK was used.

Implements Botan::TLS::Channel_Impl.

Definition at line 107 of file tls_channel_impl_12.cpp.

107 {
108 if(m_active_state.has_value()) {
109 return m_active_state->psk_identity();
110 }
111 if(const auto* state = pending_state()) {
112 return state->psk_identity();
113 }
114 return std::nullopt;
115}

◆ extract_downgrade_info()

std::unique_ptr< Downgrade_Information > Botan::TLS::Channel_Impl::extract_downgrade_info ( )
inlineinherited
See also
Downgrade_Information

Definition at line 274 of file tls_channel_impl.h.

274{ return std::exchange(m_downgrade_info, {}); }

References m_downgrade_info.

◆ from_peer()

size_t Botan::TLS::Channel_Impl_12::from_peer ( std::span< const uint8_t > data)
overridevirtualinherited

Inject TLS traffic received from counterparty

Returns
a hint as the how many more bytes we need to q the current record (this may be 0 if on a record boundary)

Implements Botan::TLS::Channel_Impl.

Definition at line 293 of file tls_channel_impl_12.cpp.

293 {
294 const bool allow_epoch0_restart = m_is_datagram && m_is_server && policy().allow_dtls_epoch0_restart();
295
296 const auto* input = data.data();
297 auto input_size = data.size();
298
299 try {
300 while(input_size > 0) {
301 size_t consumed = 0;
302
303 auto get_epoch = [this](uint16_t epoch) { return read_cipher_state_epoch(epoch); };
304
305 const Record_Header record = read_record(m_is_datagram,
306 m_readbuf,
307 input,
308 input_size,
309 consumed,
310 m_record_buf,
311 m_sequence_numbers.get(),
312 get_epoch,
313 allow_epoch0_restart);
314
315 const size_t needed = record.needed();
316
317 BOTAN_ASSERT(consumed > 0, "Got to eat something");
318
319 BOTAN_ASSERT(consumed <= input_size, "Record reader consumed sane amount");
320
321 input += consumed;
322 input_size -= consumed;
323
324 BOTAN_ASSERT(input_size == 0 || needed == 0, "Got a full record or consumed all input");
325
326 if(input_size == 0 && needed != 0) {
327 return needed; // need more data to complete record
328 }
329
330 // Ignore invalid records in DTLS
331 if(m_is_datagram && record.type() == Record_Type::Invalid) {
332 return 0;
333 }
334
335 if(m_record_buf.size() > MAX_PLAINTEXT_SIZE) {
336 throw TLS_Exception(Alert::RecordOverflow, "TLS plaintext record is larger than allowed maximum");
337 }
338
339 const bool epoch0_restart = m_is_datagram && record.epoch() == 0 && m_active_state.has_value();
340 BOTAN_ASSERT_IMPLICATION(epoch0_restart, allow_epoch0_restart, "Allowed state");
341
342 const bool initial_record = epoch0_restart || (pending_state() == nullptr && !m_active_state.has_value());
343 bool initial_handshake_message = false;
344 if(record.type() == Record_Type::Handshake && !m_record_buf.empty()) {
345 const Handshake_Type type = static_cast<Handshake_Type>(m_record_buf[0]);
346 initial_handshake_message = (type == Handshake_Type::ClientHello);
347 }
348
349 if(record.type() != Record_Type::Alert) {
350 if(initial_record) {
351 // For initial records just check for basic sanity
352 if(record.version().major_version() != 3 && record.version().major_version() != 0xFE) {
353 throw TLS_Exception(Alert::ProtocolVersion, "Received unexpected record version in initial record");
354 }
355 } else if(const auto* pending = pending_state()) {
356 if(pending->server_hello() != nullptr && !initial_handshake_message &&
357 record.version() != pending->version()) {
358 throw TLS_Exception(Alert::ProtocolVersion, "Received unexpected record version");
359 }
360 } else if(m_active_state.has_value()) {
361 if(record.version() != m_active_state->version() && !initial_handshake_message) {
362 throw TLS_Exception(Alert::ProtocolVersion, "Received unexpected record version");
363 }
364 }
365 }
366
367 if(record.type() == Record_Type::Handshake || record.type() == Record_Type::ChangeCipherSpec) {
368 if(m_has_been_closed) {
369 throw TLS_Exception(Alert::UnexpectedMessage, "Received handshake data after connection closure");
370 }
371 process_handshake_ccs(m_record_buf, record.sequence(), record.type(), record.version(), epoch0_restart);
372 } else if(record.type() == Record_Type::ApplicationData) {
373 if(m_has_been_closed) {
374 throw TLS_Exception(Alert::UnexpectedMessage, "Received application data after connection closure");
375 }
376 if(pending_state() != nullptr) {
377 throw TLS_Exception(Alert::UnexpectedMessage, "Can't interleave application and handshake data");
378 }
379 process_application_data(record.sequence(), m_record_buf);
380 } else if(record.type() == Record_Type::Alert) {
381 process_alert(m_record_buf);
382 } else if(record.type() != Record_Type::Invalid) {
383 throw Unexpected_Message("Unexpected record type " + std::to_string(static_cast<size_t>(record.type())) +
384 " from counterparty");
385 }
386 }
387
388 return 0; // on a record boundary
389 } catch(TLS_Exception& e) {
390 send_fatal_alert(e.type());
391 throw;
392 } catch(Invalid_Authentication_Tag&) {
393 send_fatal_alert(Alert::BadRecordMac);
394 throw;
395 } catch(Decoding_Error&) {
396 send_fatal_alert(Alert::DecodeError);
397 throw;
398 } catch(...) {
399 send_fatal_alert(Alert::InternalError);
400 throw;
401 }
402}
#define BOTAN_ASSERT_IMPLICATION(expr1, expr2, msg)
Definition assert.h:101
void send_fatal_alert(Alert::Type type)
virtual bool allow_dtls_epoch0_restart() const
Record_Header read_record(bool is_datagram, secure_vector< uint8_t > &readbuf, const uint8_t input[], size_t input_len, size_t &consumed, secure_vector< uint8_t > &recbuf, Connection_Sequence_Numbers *sequence_numbers, const get_cipherstate_fn &get_cipherstate, bool allow_epoch0_restart)
@ MAX_PLAINTEXT_SIZE
Definition tls_magic.h:31

References Botan::TLS::Alert, Botan::TLS::Policy::allow_dtls_epoch0_restart(), Botan::TLS::ApplicationData, BOTAN_ASSERT, BOTAN_ASSERT_IMPLICATION, Botan::TLS::ChangeCipherSpec, Botan::TLS::ClientHello, Botan::TLS::Record_Header::epoch(), Botan::TLS::Handshake, Botan::TLS::Invalid, Botan::TLS::Protocol_Version::major_version(), Botan::TLS::MAX_PLAINTEXT_SIZE, Botan::TLS::Record_Header::needed(), policy(), Botan::TLS::read_record(), Botan::TLS::Channel_Impl::send_fatal_alert(), Botan::TLS::Record_Header::sequence(), Botan::TLS::Record_Header::type(), Botan::TLS::TLS_Exception::type(), and Botan::TLS::Record_Header::version().

◆ inspect_handshake_message()

void Botan::TLS::Channel_Impl_12::inspect_handshake_message ( const Handshake_Message & msg)
protectedinherited

◆ is_active()

bool Botan::TLS::Channel_Impl_12::is_active ( ) const
overridevirtualinherited
Returns
true iff the connection is active for sending application data

Implements Botan::TLS::Channel_Impl.

Definition at line 258 of file tls_channel_impl_12.cpp.

258 {
259 return !is_closed() && is_handshake_complete();
260}
bool is_handshake_complete() const override

References is_closed(), and is_handshake_complete().

Referenced by to_peer().

◆ is_closed()

bool Botan::TLS::Channel_Impl_12::is_closed ( ) const
overridevirtualinherited
Returns
true iff the connection has been definitely closed

Implements Botan::TLS::Channel_Impl.

Definition at line 262 of file tls_channel_impl_12.cpp.

262 {
263 return m_has_been_closed;
264}

Referenced by is_active(), is_closed_for_reading(), is_closed_for_writing(), and send_alert().

◆ is_closed_for_reading()

bool Botan::TLS::Channel_Impl_12::is_closed_for_reading ( ) const
inlineoverridevirtualinherited
Returns
true iff the connection is active for sending application data

Implements Botan::TLS::Channel_Impl.

Definition at line 95 of file tls_channel_impl_12.h.

95{ return is_closed(); }

References is_closed().

◆ is_closed_for_writing()

bool Botan::TLS::Channel_Impl_12::is_closed_for_writing ( ) const
inlineoverridevirtualinherited
Returns
true iff the connection has been definitely closed

Implements Botan::TLS::Channel_Impl.

Definition at line 97 of file tls_channel_impl_12.h.

97{ return is_closed(); }

References is_closed().

◆ is_downgrading()

bool Botan::TLS::Channel_Impl::is_downgrading ( ) const
inlineinherited

Indicates whether a downgrade to TLS 1.2 or lower is in progress

See also
Downgrade_Information

Definition at line 269 of file tls_channel_impl.h.

269{ return m_downgrade_info && m_downgrade_info->will_downgrade; }

References m_downgrade_info.

Referenced by Botan::TLS::Channel_Impl_13::from_peer(), Botan::TLS::Channel_Impl_13::key_material_export(), and Botan::TLS::Channel_Impl_13::update_traffic_keys().

◆ is_handshake_complete()

bool Botan::TLS::Channel_Impl_12::is_handshake_complete ( ) const
overridevirtualinherited
Returns
true iff the TLS handshake completed successfully

Implements Botan::TLS::Channel_Impl.

Definition at line 254 of file tls_channel_impl_12.cpp.

254 {
255 return m_active_state.has_value();
256}

Referenced by is_active().

◆ key_material_export()

SymmetricKey Botan::TLS::Channel_Impl_12::key_material_export ( std::string_view label,
std::string_view context,
size_t length ) const
overridevirtualinherited

Key material export (RFC 5705)

Parameters
labela disambiguating label string
contexta per-association context value
lengththe length of the desired key in bytes
Returns
key of length bytes

Implements Botan::TLS::Channel_Impl.

Definition at line 653 of file tls_channel_impl_12.cpp.

655 {
656 if(!m_active_state.has_value()) {
657 throw Invalid_State("Channel_Impl_12::key_material_export connection not active");
658 }
659
660 if(pending_state() != nullptr) {
661 throw Invalid_State("Channel_Impl_12::key_material_export cannot export during renegotiation");
662 }
663
664 auto prf = callbacks().tls12_protocol_specific_kdf(m_active_state->prf_algo());
665
666 const auto salt = [&] {
667 if(context.empty()) {
668 return concat(m_active_state->client_random(), m_active_state->server_random());
669 } else {
670 return concat(m_active_state->client_random(),
671 m_active_state->server_random(),
672 store_be(static_cast<uint16_t>(context.size())),
673 as_span_of_bytes(context));
674 }
675 }();
676
677 return SymmetricKey(prf->derive_key(length, m_active_state->master_secret(), salt, as_span_of_bytes(label)));
678}
virtual std::unique_ptr< KDF > tls12_protocol_specific_kdf(std::string_view prf_algo) const
OctetString SymmetricKey
Definition symkey.h:140
std::span< const uint8_t > as_span_of_bytes(const char *s, size_t len)
Definition mem_utils.h:59
constexpr auto concat(Rs &&... ranges)
Definition concat_util.h:90
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:745

References Botan::as_span_of_bytes(), callbacks(), Botan::concat(), Botan::store_be(), and Botan::TLS::Callbacks::tls12_protocol_specific_kdf().

◆ new_handshake_state()

virtual std::unique_ptr< Handshake_State > Botan::TLS::Channel_Impl_12::new_handshake_state ( std::unique_ptr< class Handshake_IO > io)
protectedpure virtualinherited

Referenced by create_handshake_state().

◆ new_session_ticket_supported()

virtual bool Botan::TLS::Channel_Impl::new_session_ticket_supported ( ) const
inlinevirtualinherited
Returns
true if this channel can issue TLS 1.3 style session tickets.

Reimplemented in Botan::TLS::Server_Impl_13.

Definition at line 140 of file tls_channel_impl.h.

140{ return false; }

◆ peer_cert_chain()

std::vector< X509_Certificate > Botan::TLS::Channel_Impl_12::peer_cert_chain ( ) const
overridevirtualinherited
Returns
certificate chain of the peer (may be empty)

Implements Botan::TLS::Channel_Impl.

Definition at line 100 of file tls_channel_impl_12.cpp.

100 {
101 if(m_active_state.has_value()) {
102 return m_active_state->peer_certs();
103 }
104 return std::vector<X509_Certificate>();
105}

◆ peer_raw_public_key()

std::shared_ptr< const Public_Key > Botan::TLS::Channel_Impl_12::peer_raw_public_key ( ) const
inlineoverridevirtualinherited

Note: Raw public key for authentication (RFC7250) is currently not implemented for TLS 1.2.

Returns
raw public key of the peer (will be nullptr)

Implements Botan::TLS::Channel_Impl.

Definition at line 110 of file tls_channel_impl_12.h.

110{ return nullptr; }

◆ policy()

◆ preserve_client_hello()

void Botan::TLS::Channel_Impl::preserve_client_hello ( std::span< const uint8_t > msg)
inlineprotectedinherited

Definition at line 229 of file tls_channel_impl.h.

229 {
231 m_downgrade_info->client_hello_message.assign(msg.begin(), msg.end());
232 }
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49

References BOTAN_STATE_CHECK, and m_downgrade_info.

Referenced by Botan::TLS::Client_Impl_13::Client_Impl_13().

◆ preserve_peer_transcript()

void Botan::TLS::Channel_Impl::preserve_peer_transcript ( std::span< const uint8_t > input)
inlineprotectedinherited

Definition at line 224 of file tls_channel_impl.h.

224 {
226 m_downgrade_info->peer_transcript.insert(m_downgrade_info->peer_transcript.end(), input.begin(), input.end());
227 }

References BOTAN_STATE_CHECK, and m_downgrade_info.

Referenced by Botan::TLS::Channel_Impl_13::from_peer().

◆ renegotiate()

void Botan::TLS::Channel_Impl_12::renegotiate ( bool force_full_renegotiation = false)
overridevirtualinherited

Attempt to renegotiate the session

Parameters
force_full_renegotiationif true, require a full renegotiation, otherwise allow session resumption

Implements Botan::TLS::Channel_Impl.

Definition at line 182 of file tls_channel_impl_12.cpp.

182 {
183 if(pending_state() != nullptr) { // currently in handshake?
184 return;
185 }
186
187 if(m_active_state.has_value()) {
188 if(!force_full_renegotiation) {
189 force_full_renegotiation = !policy().allow_resumption_for_renegotiation();
190 }
191
192 initiate_handshake(create_handshake_state(m_active_state->version()), force_full_renegotiation);
193 } else {
194 throw Invalid_State("Cannot renegotiate on inactive connection");
195 }
196}
virtual void initiate_handshake(Handshake_State &state, bool force_full_renegotiation)=0
virtual bool allow_resumption_for_renegotiation() const

References Botan::TLS::Policy::allow_resumption_for_renegotiation(), create_handshake_state(), initiate_handshake(), and policy().

◆ request_downgrade()

void Botan::TLS::Channel_Impl::request_downgrade ( )
inlineprotectedinherited

Implementations use this to signal that the peer indicated a protocol version downgrade. After calling request_downgrade() no further state changes must be performed 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.

Definition at line 250 of file tls_channel_impl.h.

250 {
252 m_downgrade_info->will_downgrade = true;
253 }

References BOTAN_STATE_CHECK, and m_downgrade_info.

Referenced by request_downgrade_for_resumption().

◆ request_downgrade_for_resumption()

void Botan::TLS::Channel_Impl::request_downgrade_for_resumption ( Session_with_Handle session)
inlineprotectedinherited

Definition at line 255 of file tls_channel_impl.h.

255 {
256 BOTAN_STATE_CHECK(m_downgrade_info && m_downgrade_info->client_hello_message.empty() &&
257 m_downgrade_info->peer_transcript.empty() && !m_downgrade_info->tls12_session.has_value());
258 BOTAN_ASSERT_NOMSG(session.session.version().is_pre_tls_13());
259 m_downgrade_info->tls12_session = std::move(session);
261 }

References BOTAN_ASSERT_NOMSG, BOTAN_STATE_CHECK, Botan::TLS::Protocol_Version::is_pre_tls_13(), m_downgrade_info, request_downgrade(), Botan::TLS::Session_with_Handle::session, and Botan::TLS::Session_Base::version().

Referenced by Botan::TLS::Client_Impl_13::Client_Impl_13().

◆ reset_active_association_state()

void Botan::TLS::Channel_Impl_12::reset_active_association_state ( )
protectedinherited

Definition at line 62 of file tls_channel_impl_12.cpp.

62 {
63 // This operation only makes sense for DTLS
64 BOTAN_ASSERT_NOMSG(m_is_datagram);
65 m_active_state.reset();
66 m_read_cipher_states.clear();
67 m_write_cipher_states.clear();
68
69 m_write_cipher_states[0] = nullptr;
70 m_read_cipher_states[0] = nullptr;
71
72 if(m_sequence_numbers) {
73 m_sequence_numbers->reset(); // NOLINT(*-ambiguous-smartptr-reset-call)
74 }
75}

References BOTAN_ASSERT_NOMSG.

◆ rng()

◆ secure_renegotiation_check() [1/2]

void Botan::TLS::Channel_Impl_12::secure_renegotiation_check ( const Client_Hello_12 * client_hello)
protectedinherited

Definition at line 588 of file tls_channel_impl_12.cpp.

588 {
589 BOTAN_ASSERT_NONNULL(client_hello);
590 const bool secure_renegotiation = client_hello->secure_renegotiation();
591
592 if(m_active_state && m_active_state->client_supports_secure_renegotiation() != secure_renegotiation) {
593 throw TLS_Exception(Alert::HandshakeFailure, "Client changed its mind about secure renegotiation");
594 }
595
596 if(secure_renegotiation) {
597 const std::vector<uint8_t>& data = client_hello->renegotiation_info();
598
599 const auto expected = secure_renegotiation_data_for_client_hello();
600 if(!CT::is_equal<uint8_t>(data, expected).as_bool()) {
601 throw TLS_Exception(Alert::HandshakeFailure, "Client sent bad values for secure renegotiation");
602 }
603 }
604}
std::vector< uint8_t > secure_renegotiation_data_for_client_hello() const
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
Definition ct_utils.h:798

References BOTAN_ASSERT_NONNULL, Botan::CT::is_equal(), Botan::TLS::Client_Hello_12::renegotiation_info(), Botan::TLS::Client_Hello_12::secure_renegotiation(), and secure_renegotiation_data_for_client_hello().

Referenced by Botan::TLS::Client_Impl_12::Client_Impl_12().

◆ secure_renegotiation_check() [2/2]

void Botan::TLS::Channel_Impl_12::secure_renegotiation_check ( const Server_Hello_12 * server_hello)
protectedinherited

Definition at line 606 of file tls_channel_impl_12.cpp.

606 {
607 BOTAN_ASSERT_NONNULL(server_hello);
608 const bool secure_renegotiation = server_hello->secure_renegotiation();
609
610 if(m_active_state && m_active_state->server_supports_secure_renegotiation() != secure_renegotiation) {
611 throw TLS_Exception(Alert::HandshakeFailure, "Server changed its mind about secure renegotiation");
612 }
613
614 if(secure_renegotiation) {
615 const std::vector<uint8_t>& data = server_hello->renegotiation_info();
616
617 const auto expected = secure_renegotiation_data_for_server_hello();
618 if(!CT::is_equal<uint8_t>(data, expected).as_bool()) {
619 throw TLS_Exception(Alert::HandshakeFailure, "Server sent bad values for secure renegotiation");
620 }
621 }
622}
std::vector< uint8_t > secure_renegotiation_data_for_server_hello() const

References BOTAN_ASSERT_NONNULL, Botan::CT::is_equal(), Botan::TLS::Server_Hello_12::renegotiation_info(), Botan::TLS::Server_Hello_12::secure_renegotiation(), and secure_renegotiation_data_for_server_hello().

◆ secure_renegotiation_data_for_client_hello()

std::vector< uint8_t > Botan::TLS::Channel_Impl_12::secure_renegotiation_data_for_client_hello ( ) const
protectedinherited

Definition at line 624 of file tls_channel_impl_12.cpp.

624 {
625 if(m_active_state.has_value()) {
626 return m_active_state->client_finished_verify_data();
627 }
628 return std::vector<uint8_t>();
629}

Referenced by secure_renegotiation_check().

◆ secure_renegotiation_data_for_server_hello()

std::vector< uint8_t > Botan::TLS::Channel_Impl_12::secure_renegotiation_data_for_server_hello ( ) const
protectedinherited

Definition at line 631 of file tls_channel_impl_12.cpp.

631 {
632 if(m_active_state.has_value()) {
633 return concat(m_active_state->client_finished_verify_data(), m_active_state->server_finished_verify_data());
634 } else {
635 return {};
636 }
637}

References Botan::concat().

Referenced by secure_renegotiation_check().

◆ secure_renegotiation_supported()

bool Botan::TLS::Channel_Impl_12::secure_renegotiation_supported ( ) const
overridevirtualinherited
Returns
true iff the counterparty supports the secure renegotiation extensions.

Implements Botan::TLS::Channel_Impl.

Definition at line 639 of file tls_channel_impl_12.cpp.

639 {
640 if(m_active_state.has_value()) {
641 return m_active_state->server_supports_secure_renegotiation();
642 }
643
644 if(const auto* pending = pending_state()) {
645 if(const auto* hello = pending->server_hello()) {
646 return hello->secure_renegotiation();
647 }
648 }
649
650 return false;
651}

◆ send_alert()

void Botan::TLS::Channel_Impl_12::send_alert ( const Alert & alert)
overridevirtualinherited

Send a TLS alert message. If the alert is fatal, the internal state (keys, etc) will be reset.

Parameters
alertthe Alert to send

Implements Botan::TLS::Channel_Impl.

Definition at line 560 of file tls_channel_impl_12.cpp.

560 {
561 const bool ready_to_send_anything = !is_closed() && m_sequence_numbers;
562 if(alert.is_valid() && ready_to_send_anything) {
563 try {
564 send_record(Record_Type::Alert, alert.serialize());
565 } catch(...) { /* swallow it */
566 }
567 }
568
569 if(alert.type() == Alert::NoRenegotiation && m_active_state.has_value()) {
570 m_pending_state.reset();
571 }
572
573 if(alert.is_fatal()) {
574 if(m_active_state.has_value()) {
575 const auto& sid = m_active_state->session_id();
576 if(!sid.empty()) {
577 session_manager().remove(Session_Handle(sid));
578 }
579 }
580 reset_state();
581 }
582
583 if(alert.type() == Alert::CloseNotify || alert.is_fatal()) {
584 m_has_been_closed = true;
585 }
586}
virtual size_t remove(const Session_Handle &handle)=0

References Botan::TLS::Alert, is_closed(), Botan::TLS::Alert::is_fatal(), Botan::TLS::Alert::is_valid(), Botan::TLS::Session_Manager::remove(), Botan::TLS::Alert::serialize(), session_manager(), and Botan::TLS::Alert::type().

◆ send_fatal_alert()

void Botan::TLS::Channel_Impl::send_fatal_alert ( Alert::Type type)
inlineinherited

Send a fatal alert

Definition at line 71 of file tls_channel_impl.h.

71{ send_alert(Alert(type, true)); }
virtual void send_alert(const Alert &alert)=0

References Botan::TLS::Alert, and send_alert().

Referenced by Botan::TLS::Channel_Impl_12::from_peer(), and Botan::TLS::Channel_Impl_13::from_peer().

◆ send_new_session_tickets()

virtual size_t Botan::TLS::Channel_Impl::send_new_session_tickets ( const size_t )
inlinevirtualinherited

Send 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

Reimplemented in Botan::TLS::Server_Impl_13.

Definition at line 153 of file tls_channel_impl.h.

153{ return 0; }

◆ send_warning_alert()

void Botan::TLS::Channel_Impl::send_warning_alert ( Alert::Type type)
inlineinherited

Send a warning alert

Definition at line 66 of file tls_channel_impl.h.

66{ send_alert(Alert(type, false)); }

References Botan::TLS::Alert, and send_alert().

Referenced by close().

◆ session_manager()

Session_Manager & Botan::TLS::Channel_Impl_12::session_manager ( )
inlineprotectedinherited

◆ set_io_buffer_size()

void Botan::TLS::Channel_Impl::set_io_buffer_size ( size_t io_buf_sz)
inlineprotectedinherited

Definition at line 237 of file tls_channel_impl.h.

237 {
239 m_downgrade_info->io_buffer_size = io_buf_sz;
240 }

References BOTAN_STATE_CHECK, and m_downgrade_info.

◆ timeout_check()

bool Botan::TLS::Channel_Impl_12::timeout_check ( )
overridevirtualinherited

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.

Implements Botan::TLS::Channel_Impl.

Definition at line 173 of file tls_channel_impl_12.cpp.

173 {
174 if(m_pending_state) {
175 return m_pending_state->handshake_io().timeout_check();
176 }
177
178 //FIXME: scan cipher suites and remove epochs older than 2*MSL
179 return false;
180}

◆ to_peer()

void Botan::TLS::Channel_Impl_12::to_peer ( std::span< const uint8_t > data)
overridevirtualinherited

Inject plaintext intended for counterparty Throws an exception if is_active() is false

Implements Botan::TLS::Channel_Impl.

Definition at line 552 of file tls_channel_impl_12.cpp.

552 {
553 if(!is_active()) {
554 throw Invalid_State("Data cannot be sent on inactive TLS connection");
555 }
556
557 send_record_array(sequence_numbers().current_write_epoch(), Record_Type::ApplicationData, data.data(), data.size());
558}

References Botan::TLS::ApplicationData, and is_active().

◆ update_traffic_keys()

void Botan::TLS::Channel_Impl_12::update_traffic_keys ( bool request_peer_update = false)
overridevirtualinherited

Attempt to update the session's traffic key material Note that this is possible with a TLS 1.3 channel, only.

Parameters
request_peer_updateif true, require a reciprocal key update

Implements Botan::TLS::Channel_Impl.

Definition at line 198 of file tls_channel_impl_12.cpp.

198 {
199 throw Invalid_Argument("cannot update traffic keys on a TLS 1.2 channel");
200}

Member Data Documentation

◆ m_downgrade_info


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