Botan 2.19.5 Crypto and TLS for C&

Public Types | Public Member Functions | Static Public Attributes | Protected Member Functions | List of all members
Botan::TLS::Client Class Referencefinal

`#include <tls_client.h>`

Inheritance diagram for Botan::TLS::Client:

## Public Types
typedef std::function< void(Alert, const uint8_t[], size_t)> | alert_cb
typedef std::function< void(const uint8_t[], size_t)> | data_cb
typedef std::function< bool(const Session &)> | handshake_cb
typedef std::function< void(const Handshake_Message &)> | handshake_msg_cb
typedef std::function< void(const uint8_t[], size_t)> | output_fn

## Public Member Functions
std::string | application_protocol () const override
| Client (Callbacks &callbacks, Session_Manager &session_manager, Credentials_Manager &creds, const Policy &policy, RandomNumberGenerator &rng, const Server_Information &server_info=Server_Information(), const Protocol_Version &offer_version=Protocol_Version::latest_tls_version(), const std::vector< std::string > &next_protocols={}, size_t reserved_io_buffer_size=TLS::Client::IO_BUF_DEFAULT_SIZE)
| Client (output_fn data_output_fn, data_cb app_data_cb, alert_cb recv_alert_cb, handshake_cb hs_cb, Session_Manager &session_manager, Credentials_Manager &creds, const Policy &policy, RandomNumberGenerator &rng, const Server_Information &server_info=Server_Information(), const Protocol_Version &offer_version=Protocol_Version::latest_tls_version(), const std::vector< std::string > &next_protocols={}, size_t reserved_io_buffer_size=TLS::Client::IO_BUF_DEFAULT_SIZE)
| Client (output_fn out, data_cb app_data_cb, alert_cb alert_cb, handshake_cb hs_cb, handshake_msg_cb hs_msg_cb, Session_Manager &session_manager, Credentials_Manager &creds, const Policy &policy, RandomNumberGenerator &rng, const Server_Information &server_info=Server_Information(), const Protocol_Version &offer_version=Protocol_Version::latest_tls_version(), const std::vector< std::string > &next_protocols={})
void | close ()
bool | is_active () const
bool | is_closed () const
SymmetricKey | key_material_export (const std::string &label, const std::string &context, size_t length) const
std::vector< X509_Certificate > | peer_cert_chain () const
size_t | received_data (const std::vector< uint8_t > &buf)
size_t | received_data (const uint8_t buf[], size_t buf_size)
void | renegotiate (bool force_full_renegotiation=false)
bool | secure_renegotiation_supported () const
void | send (const std::string &val)
template<typename Alloc >
void | send (const std::vector< unsigned char, Alloc > &val)
void | send (const uint8_t buf[], size_t buf_size)
void | send_alert (const Alert &alert)
void | send_fatal_alert (Alert::Type type)
void | send_warning_alert (Alert::Type type)
bool | timeout_check ()

## Static Public Attributes
static size_t | IO_BUF_DEFAULT_SIZE = 10*1024

## Protected Member Functions
void | activate_session ()
Callbacks & | callbacks () const
void | change_cipher_spec_reader (Connection_Side side)
void | change_cipher_spec_writer (Connection_Side side)
Handshake_State & | create_handshake_state (Protocol_Version version)
void | inspect_handshake_message (const Handshake_Message &msg)
const Policy & | policy () const
void | reset_active_association_state ()
RandomNumberGenerator & | rng ()
bool | save_session (const Session &session)
void | secure_renegotiation_check (const Client_Hello *client_hello)
void | secure_renegotiation_check (const Server_Hello *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_Manager & | session_manager ()

## Detailed Description

SSL/TLS Client

Definition at line 24 of file tls_client.h.

## Member Typedef Documentation

## ◆ alert_cb

typedef std::function<void (Alert, const uint8_t[], size_t)> Botan::TLS::Channel::alert_cb
| inherited

Definition at line 42 of file tls_channel.h.

## ◆ data_cb

typedef std::function<void (const uint8_t[], size_t)> Botan::TLS::Channel::data_cb
| inherited

Definition at line 41 of file tls_channel.h.

## ◆ handshake_cb

typedef std::function<bool (const Session&)> Botan::TLS::Channel::handshake_cb
| inherited

Definition at line 43 of file tls_channel.h.

## ◆ handshake_msg_cb

typedef std::function<void (const Handshake_Message&)> Botan::TLS::Channel::handshake_msg_cb
| inherited

Definition at line 44 of file tls_channel.h.

## ◆ output_fn

typedef std::function<void (const uint8_t[], size_t)> Botan::TLS::Channel::output_fn
| inherited

Definition at line 40 of file tls_channel.h.

## Constructor & Destructor Documentation

## ◆ Client() [1/3]

Botan::TLS::Client::Client | ( | Callbacks & | callbacks,
|  | Session_Manager & | session_manager,
|  | Credentials_Manager & | creds,
|  | const Policy & | policy,
|  | RandomNumberGenerator & | rng,
|  | const Server_Information & | server_info = `Server_Information()`,
|  | const Protocol_Version & | offer_version = `Protocol_Version::latest_tls_version()`,
|  | const std::vector< std::string > & | next_protocols = `{}`,
|  | size_t | reserved_io_buffer_size = `TLS::Client::IO_BUF_DEFAULT_SIZE`
| ) |  |

Set up a new TLS client session

Parameters

  callbacks | contains a set of callback function references required by the TLS client.
  session_manager | manages session state
  creds | manages application/user credentials
  policy | specifies other connection policy information
  rng | a random number generator
  server_info | is identifying information about the TLS server
  offer_version | specifies which version we will offer to the TLS server.
  next_protocols | specifies protocols to advertise with ALPN
  reserved_io_buffer_size | This 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 64 of file tls_client.cpp.

72 :
73 Channel(callbacks, session_manager, rng, policy,
74 false, offer_version.is_datagram_protocol(), io_buf_sz),
75 m_creds(creds),
76 m_info(info)
77 {
78 init(offer_version, next_protos);
79 }
Botan::TLS::Channel::Channel
Channel(Callbacks &callbacks, Session_Manager &session_manager, RandomNumberGenerator &rng, const Policy &policy, bool is_server, bool is_datagram, size_t io_buf_sz=IO_BUF_DEFAULT_SIZE)
Definition: tls_channel.cpp:26
Botan::TLS::Channel::callbacks
Callbacks & callbacks() const
Definition: tls_channel.h:242
Botan::TLS::Channel::session_manager
Session_Manager & session_manager()
Definition: tls_channel.h:236
Botan::TLS::Channel::policy
const Policy & policy() const
Definition: tls_channel.h:238
Botan::TLS::Channel::rng
RandomNumberGenerator & rng()
Definition: tls_channel.h:234

## ◆ Client() [2/3]

Botan::TLS::Client::Client | ( | output_fn | data_output_fn,
|  | data_cb | app_data_cb,
|  | alert_cb | recv_alert_cb,
|  | handshake_cb | hs_cb,
|  | Session_Manager & | session_manager,
|  | Credentials_Manager & | creds,
|  | const Policy & | policy,
|  | RandomNumberGenerator & | rng,
|  | const Server_Information & | server_info = `Server_Information()`,
|  | const Protocol_Version & | offer_version = `Protocol_Version::latest_tls_version()`,
|  | const std::vector< std::string > & | next_protocols = `{}`,
|  | size_t | reserved_io_buffer_size = `TLS::Client::IO_BUF_DEFAULT_SIZE`
| ) |  |

DEPRECATED. This constructor is only provided for backward compatibility and should not be used in new code. It will be removed in a future release.

Set up a new TLS client session

Parameters

  data_output_fn | is called with data for the outbound socket
  app_data_cb | is called when new application data is received
  recv_alert_cb | is called when a TLS alert is received
  hs_cb | is called when a handshake is completed
  session_manager | manages session state
  creds | manages application/user credentials
  policy | specifies other connection policy information
  rng | a random number generator
  server_info | is identifying information about the TLS server
  offer_version | specifies which version we will offer to the TLS server.
  next_protocols | specifies protocols to advertise with ALPN
  reserved_io_buffer_size | This 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 81 of file tls_client.cpp.

92 :
93 Channel(data_output_fn, proc_cb, recv_alert_cb, hs_cb, Channel::handshake_msg_cb(),
94 session_manager, rng, policy, false, offer_version.is_datagram_protocol(), io_buf_sz),
95 m_creds(creds),
96 m_info(info)
97 {
98 init(offer_version, next_protos);
99 }
Botan::TLS::Channel::handshake_msg_cb
std::function< void(const Handshake_Message &)> handshake_msg_cb
Definition: tls_channel.h:44

## ◆ Client() [3/3]

Botan::TLS::Client::Client | ( | output_fn | out,
|  | data_cb | app_data_cb,
|  | alert_cb | alert_cb,
|  | handshake_cb | hs_cb,
|  | handshake_msg_cb | hs_msg_cb,
|  | Session_Manager & | session_manager,
|  | Credentials_Manager & | creds,
|  | const Policy & | policy,
|  | RandomNumberGenerator & | rng,
|  | const Server_Information & | server_info = `Server_Information()`,
|  | const Protocol_Version & | offer_version = `Protocol_Version::latest_tls_version()`,
|  | const std::vector< std::string > & | next_protocols = `{}`
| ) |  |

DEPRECATED. This constructor is only provided for backward compatibility and should not be used in new implementations.

Definition at line 101 of file tls_client.cpp.

112 :
113 Channel(data_output_fn, proc_cb, recv_alert_cb, hs_cb, hs_msg_cb,
114 session_manager, rng, policy, false, offer_version.is_datagram_protocol()),
115 m_creds(creds),
116 m_info(info)
117 {
118 init(offer_version, next_protos);
119 }

## Member Function Documentation

## ◆ activate_session()

void Botan::TLS::Channel::activate_session | ( |  | ) |
| protected inherited

Definition at line 291 of file tls_channel.cpp.

292 {
293 std::swap(m_active_state, m_pending_state);
294 m_pending_state.reset();
295
296 if(!m_active_state->version().is_datagram_protocol())
297 {
298 // TLS is easy just remove all but the current state
299 const uint16_t current_epoch = sequence_numbers().current_write_epoch();
300
301 const auto not_current_epoch =
302 [current_epoch](uint16_t epoch) { return (epoch != current_epoch); };
303
304 map_remove_if(not_current_epoch, m_write_cipher_states);
305 map_remove_if(not_current_epoch, m_read_cipher_states);
306 }
307
308 callbacks().tls_session_activated();
309 }
Botan::TLS::Callbacks::tls_session_activated
virtual void tls_session_activated()
Definition: tls_callbacks.h:97
Botan::TLS::Connection_Sequence_Numbers::current_write_epoch
virtual uint16_t current_write_epoch() const =0
Botan::map_remove_if
void map_remove_if(Pred pred, T &assoc)
Definition: stl_util.h:96

References Botan::TLS::Channel::callbacks(), Botan::TLS::Connection_Sequence_Numbers::current_write_epoch(), Botan::map_remove_if(), and Botan::TLS::Callbacks::tls_session_activated().

## ◆ application_protocol()

std::string Botan::TLS::Client::application_protocol | ( |  | ) | const
| inline override virtual

Returns
  network protocol as advertised by the TLS server, if server sent the ALPN extension

Implements Botan::TLS::Channel.

Definition at line 135 of file tls_client.h.

135{ return m_application_protocol; }

## ◆ callbacks()

Callbacks & Botan::TLS::Channel::callbacks | ( |  | ) | const
| inline protected inherited

Definition at line 242 of file tls_channel.h.

242{ return m_callbacks; }

Referenced by Botan::TLS::Channel::activate_session(), and Botan::TLS::Channel::save_session().

## ◆ change_cipher_spec_reader()

void Botan::TLS::Channel::change_cipher_spec_reader | ( | Connection_Side | side | ) |
| protected inherited

Definition at line 222 of file tls_channel.cpp.

223 {
224 auto pending = pending_state();
225
226 BOTAN_ASSERT(pending && pending->server_hello(),
227 "Have received server hello");
228
229 if(pending->server_hello()->compression_method() != 0)
230 throw Internal_Error("Negotiated unknown compression algorithm");
231
232 sequence_numbers().new_read_cipher_state();
233
234 const uint16_t epoch = sequence_numbers().current_read_epoch();
235
236 BOTAN_ASSERT(m_read_cipher_states.count(epoch) == 0,
237 "No read cipher state currently set for next epoch");
238
239 // flip side as we are reading
240 std::shared_ptr<Connection_Cipher_State> read_state(
241 new Connection_Cipher_State(pending->version(),
242 (side == CLIENT) ? SERVER : CLIENT,
243 false,
244 pending->ciphersuite(),
245 pending->session_keys(),
246 pending->server_hello()->supports_encrypt_then_mac()));
247
248 m_read_cipher_states[epoch] = read_state;
249 }
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
Botan::TLS::Connection_Sequence_Numbers::current_read_epoch
virtual uint16_t current_read_epoch() const =0
Botan::TLS::Connection_Sequence_Numbers::new_read_cipher_state
virtual void new_read_cipher_state()=0
Botan::OCSP::Response_Status_Code::Internal_Error
@ Internal_Error
Botan::TLS::CLIENT
@ CLIENT
Definition: tls_magic.h:32
Botan::TLS::SERVER
@ SERVER
Definition: tls_magic.h:32

References BOTAN_ASSERT, Botan::TLS::CLIENT, Botan::TLS::Connection_Sequence_Numbers::current_read_epoch(), Botan::TLS::Connection_Sequence_Numbers::new_read_cipher_state(), and Botan::TLS::SERVER.

## ◆ change_cipher_spec_writer()

void Botan::TLS::Channel::change_cipher_spec_writer | ( | Connection_Side | side | ) |
| protected inherited

Definition at line 251 of file tls_channel.cpp.

252 {
253 auto pending = pending_state();
254
255 BOTAN_ASSERT(pending && pending->server_hello(),
256 "Have received server hello");
257
258 if(pending->server_hello()->compression_method() != 0)
259 throw Internal_Error("Negotiated unknown compression algorithm");
260
261 sequence_numbers().new_write_cipher_state();
262
263 const uint16_t epoch = sequence_numbers().current_write_epoch();
264
265 BOTAN_ASSERT(m_write_cipher_states.count(epoch) == 0,
266 "No write cipher state currently set for next epoch");
267
268 std::shared_ptr<Connection_Cipher_State> write_state(
269 new Connection_Cipher_State(pending->version(),
270 side,
271 true,
272 pending->ciphersuite(),
273 pending->session_keys(),
274 pending->server_hello()->supports_encrypt_then_mac()));
275
276 m_write_cipher_states[epoch] = write_state;
277 }
Botan::TLS::Connection_Sequence_Numbers::new_write_cipher_state
virtual void new_write_cipher_state()=0

References BOTAN_ASSERT, Botan::TLS::Connection_Sequence_Numbers::current_write_epoch(), and Botan::TLS::Connection_Sequence_Numbers::new_write_cipher_state().

## ◆ close()

void Botan::TLS::Channel::close | ( |  | ) |
| inline inherited

Send a close notification alert

Definition at line 149 of file tls_channel.h.

149{ send_warning_alert(Alert::CLOSE_NOTIFY); }
Botan::TLS::Alert::CLOSE_NOTIFY
@ CLOSE_NOTIFY
Definition: tls_alert.h:28
Botan::TLS::Channel::send_warning_alert
void send_warning_alert(Alert::Type type)
Definition: tls_channel.h:139

References Botan::TLS::Alert::CLOSE_NOTIFY.

## ◆ create_handshake_state()

Handshake_State & Botan::TLS::Channel::create_handshake_state | ( | Protocol_Version | version | ) |
| protected inherited

Definition at line 146 of file tls_channel.cpp.

147 {
148 if(pending_state())
149 throw Internal_Error("create_handshake_state called during handshake");
150
151 if(auto active = active_state())
152 {
153 Protocol_Version active_version = active->version();
154
155 if(active_version.is_datagram_protocol() != version.is_datagram_protocol())
156 {
157 throw TLS_Exception(Alert::PROTOCOL_VERSION,
158 "Active state using version " + active_version.to_string() +
159 " cannot change to " + version.to_string() + " in pending");
160 }
161 }
162
163 if(!m_sequence_numbers)
164 {
165 if(version.is_datagram_protocol())
166 m_sequence_numbers.reset(new Datagram_Sequence_Numbers);
167 else
168 m_sequence_numbers.reset(new Stream_Sequence_Numbers);
169 }
170
171 using namespace std::placeholders;
172
173 std::unique_ptr<Handshake_IO> io;
174 if(version.is_datagram_protocol())
175 {
176 io.reset(new Datagram_Handshake_IO(
177 std::bind(&Channel::send_record_under_epoch, this, _1, _2, _3),
178 sequence_numbers(),
179 static_cast<uint16_t>(m_policy.dtls_default_mtu()),
180 m_policy.dtls_initial_timeout(),
181 m_policy.dtls_maximum_timeout()));
182 }
183 else
184 {
185 io.reset(new Stream_Handshake_IO(std::bind(&Channel::send_record, this, _1, _2)));
186 }
187
188 m_pending_state.reset(new_handshake_state(io.release()));
189
190 if(auto active = active_state())
191 m_pending_state->set_version(active->version());
192
193 return *m_pending_state.get();
194 }
Botan::TLS::Alert::PROTOCOL_VERSION
@ PROTOCOL_VERSION
Definition: tls_alert.h:47
Botan::TLS::Channel::new_handshake_state
virtual Handshake_State * new_handshake_state(class Handshake_IO *io)=0
Botan::TLS::Policy::dtls_maximum_timeout
virtual size_t dtls_maximum_timeout() const
Definition: tls_policy.cpp:356
Botan::TLS::Policy::dtls_default_mtu
virtual size_t dtls_default_mtu() const
Definition: tls_policy.cpp:358
Botan::TLS::Policy::dtls_initial_timeout
virtual size_t dtls_initial_timeout() const
Definition: tls_policy.cpp:355

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(), Botan::TLS::Channel::new_handshake_state(), Botan::TLS::Alert::PROTOCOL_VERSION, and Botan::TLS::Protocol_Version::to_string().

Referenced by Botan::TLS::Channel::renegotiate().

## ◆ inspect_handshake_message()

void Botan::TLS::Channel::inspect_handshake_message | ( | const Handshake_Message & | msg | ) |
| protected inherited

## ◆ is_active()

bool Botan::TLS::Channel::is_active | ( |  | ) | const
| inherited

Returns
  true iff the connection is active for sending application data

Definition at line 279 of file tls_channel.cpp.

280 {
281 if(is_closed())
282 return false;
283 return (active_state() != nullptr);
284 }
Botan::TLS::Channel::is_closed
bool is_closed() const
Definition: tls_channel.cpp:286

References Botan::TLS::Channel::is_closed().

Referenced by Botan::TLS::Blocking_Client::do_handshake(), and Botan::TLS::Channel::send().

## ◆ is_closed()

bool Botan::TLS::Channel::is_closed | ( |  | ) | const
| inherited

Returns
  true iff the connection has been definitely closed

Definition at line 286 of file tls_channel.cpp.

287 {
288 return m_has_been_closed;
289 }

Referenced by Botan::TLS::Blocking_Client::do_handshake(), Botan::TLS::Channel::is_active(), Botan::TLS::Blocking_Client::read(), and Botan::TLS::Channel::send_alert().

## ◆ key_material_export()

SymmetricKey Botan::TLS::Channel::key_material_export | ( | const std::string & | label,
|  | const std::string & | context,
|  | size_t | length
| ) |  | const
| inherited

Key material export (RFC 5705)

Parameters

  label | a disambiguating label string
  context | a per-association context value
  length | the length of the desired key in bytes

Returns
  key of length bytes

Definition at line 757 of file tls_channel.cpp.

760 {
761 if(auto active = active_state())
762 {
763 if(pending_state() != nullptr)
764 throw Invalid_State("Channel::key_material_export cannot export during renegotiation");
765
766 std::unique_ptr<KDF> prf(active->protocol_specific_prf());
767
768 const secure_vector<uint8_t>& master_secret =
769 active->session_keys().master_secret();
770
771 std::vector<uint8_t> salt;
772 salt += active->client_hello()->random();
773 salt += active->server_hello()->random();
774
775 if(context != "")
776 {
777 size_t context_size = context.length();
778 if(context_size > 0xFFFF)
779 throw Invalid_Argument("key_material_export context is too long");
780 salt.push_back(get_byte(0, static_cast<uint16_t>(context_size)));
781 salt.push_back(get_byte(1, static_cast<uint16_t>(context_size)));
782 salt += to_byte_vector(context);
783 }
784
785 return prf->derive_key(length, master_secret, salt, to_byte_vector(label));
786 }
787 else
788 {
789 throw Invalid_State("Channel::key_material_export connection not active");
790 }
791 }
Botan::get_byte
constexpr uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:41
Botan::to_byte_vector
std::vector< uint8_t > to_byte_vector(const std::string &s)
Definition: stl_util.h:20

References Botan::get_byte(), and Botan::to_byte_vector().

## ◆ peer_cert_chain()

std::vector< X509_Certificate > Botan::TLS::Channel::peer_cert_chain | ( |  | ) | const
| inherited

Returns
  certificate chain of the peer (may be empty)

Definition at line 134 of file tls_channel.cpp.

135 {
136 if(auto active = active_state())
137 return get_peer_cert_chain(*active);
138 return std::vector<X509_Certificate>();
139 }
Botan::TLS::Channel::get_peer_cert_chain
virtual std::vector< X509_Certificate > get_peer_cert_chain(const Handshake_State &state) const =0

References Botan::TLS::Channel::get_peer_cert_chain().

## ◆ policy()

const Policy & Botan::TLS::Channel::policy | ( |  | ) | const
| inline protected inherited

Definition at line 238 of file tls_channel.h.

238{ return m_policy; }

Referenced by Botan::TLS::Channel::received_data(), and Botan::TLS::Channel::renegotiate().

## ◆ received_data() [1/2]

size_t Botan::TLS::Channel::received_data | ( | const std::vector< uint8_t > & | buf | ) |
| inherited

Inject TLS traffic received from counterparty

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

Definition at line 311 of file tls_channel.cpp.

312 {
313 return this->received_data(buf.data(), buf.size());
314 }
Botan::TLS::Channel::received_data
size_t received_data(const uint8_t buf[], size_t buf_size)
Definition: tls_channel.cpp:316

References Botan::TLS::Channel::received_data().

## ◆ received_data() [2/2]

size_t Botan::TLS::Channel::received_data | ( | const uint8_t | buf[],
|  | size_t | buf_size
| ) |  |
| inherited

Inject TLS traffic received from counterparty

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

Definition at line 316 of file tls_channel.cpp.

317 {
318 const bool allow_epoch0_restart = m_is_datagram && m_is_server && policy().allow_dtls_epoch0_restart();
319
320 try
321 {
322 while(input_size)
323 {
324 size_t consumed = 0;
325
326 auto get_epoch = [this](uint16_t epoch) { return read_cipher_state_epoch(epoch); };
327
328 const Record_Header record =
329 read_record(m_is_datagram,
330 m_readbuf,
331 input,
332 input_size,
333 consumed,
334 m_record_buf,
335 m_sequence_numbers.get(),
336 get_epoch,
337 allow_epoch0_restart);
338
339 const size_t needed = record.needed();
340
341 BOTAN_ASSERT(consumed > 0, "Got to eat something");
342
343 BOTAN_ASSERT(consumed <= input_size,
344 "Record reader consumed sane amount");
345
346 input += consumed;
347 input_size -= consumed;
348
349 BOTAN_ASSERT(input_size == 0 || needed == 0,
350 "Got a full record or consumed all input");
351
352 if(input_size == 0 && needed != 0)
353 return needed; // need more data to complete record
354
355 // Ignore invalid records in DTLS
356 if(m_is_datagram && record.type() == NO_RECORD)
357 {
358 return 0;
359 }
360
361 if(m_record_buf.size() > MAX_PLAINTEXT_SIZE)
362 throw TLS_Exception(Alert::RECORD_OVERFLOW,
363 "TLS plaintext record is larger than allowed maximum");
364
365
366 const bool epoch0_restart = m_is_datagram && record.epoch() == 0 && active_state();
367 BOTAN_ASSERT_IMPLICATION(epoch0_restart, allow_epoch0_restart, "Allowed state");
368
369 const bool initial_record = epoch0_restart || (!pending_state() && !active_state());
370
371 if(record.type() != ALERT)
372 {
373 if(initial_record)
374 {
375 // For initial records just check for basic sanity
376 if(record.version().major_version() != 3 &&
377 record.version().major_version() != 0xFE)
378 {
379 throw TLS_Exception(Alert::PROTOCOL_VERSION,
380 "Received unexpected record version in initial record");
381 }
382 }
383 else if(auto pending = pending_state())
384 {
385 if(pending->server_hello() != nullptr && record.version() != pending->version())
386 {
387 if(record.version() != pending->version())
388 {
389 throw TLS_Exception(Alert::PROTOCOL_VERSION,
390 "Received unexpected record version");
391 }
392 }
393 }
394 else if(auto active = active_state())
395 {
396 if(record.version() != active->version())
397 {
398 throw TLS_Exception(Alert::PROTOCOL_VERSION,
399 "Received unexpected record version");
400 }
401 }
402 }
403
404 if(record.type() == HANDSHAKE || record.type() == CHANGE_CIPHER_SPEC)
405 {
406 if(m_has_been_closed)
407 throw TLS_Exception(Alert::UNEXPECTED_MESSAGE, "Received handshake data after connection closure");
408 process_handshake_ccs(m_record_buf, record.sequence(), record.type(), record.version(), epoch0_restart);
409 }
410 else if(record.type() == APPLICATION_DATA)
411 {
412 if(m_has_been_closed)
413 throw TLS_Exception(Alert::UNEXPECTED_MESSAGE, "Received application data after connection closure");
414 if(pending_state() != nullptr)
415 throw TLS_Exception(Alert::UNEXPECTED_MESSAGE, "Can't interleave application and handshake data");
416 process_application_data(record.sequence(), m_record_buf);
417 }
418 else if(record.type() == ALERT)
419 {
420 process_alert(m_record_buf);
421 }
422 else if(record.type() != NO_RECORD)
423 throw Unexpected_Message("Unexpected record type " +
424 std::to_string(record.type()) +
425 " from counterparty");
426 }
427
428 return 0; // on a record boundary
429 }
430 catch(TLS_Exception& e)
431 {
432 send_fatal_alert(e.type());
433 throw;
434 }
435 catch(Invalid_Authentication_Tag&)
436 {
437 send_fatal_alert(Alert::BAD_RECORD_MAC);
438 throw;
439 }
440 catch(Decoding_Error&)
441 {
442 send_fatal_alert(Alert::DECODE_ERROR);
443 throw;
444 }
445 catch(...)
446 {
447 send_fatal_alert(Alert::INTERNAL_ERROR);
448 throw;
449 }
450 }
BOTAN_ASSERT_IMPLICATION
#define BOTAN_ASSERT_IMPLICATION(expr1, expr2, msg)
Definition: assert.h:94
Botan::TLS::Alert::UNEXPECTED_MESSAGE
@ UNEXPECTED_MESSAGE
Definition: tls_alert.h:29
Botan::TLS::Alert::RECORD_OVERFLOW
@ RECORD_OVERFLOW
Definition: tls_alert.h:32
Botan::TLS::Alert::DECODE_ERROR
@ DECODE_ERROR
Definition: tls_alert.h:44
Botan::TLS::Alert::BAD_RECORD_MAC
@ BAD_RECORD_MAC
Definition: tls_alert.h:30
Botan::TLS::Alert::INTERNAL_ERROR
@ INTERNAL_ERROR
Definition: tls_alert.h:49
Botan::TLS::Channel::send_fatal_alert
void send_fatal_alert(Alert::Type type)
Definition: tls_channel.h:144
Botan::TLS::Policy::allow_dtls_epoch0_restart
virtual bool allow_dtls_epoch0_restart() const
Definition: tls_policy.cpp:350
Botan::ASN1::to_string
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
Botan::TLS::CHANGE_CIPHER_SPEC
@ CHANGE_CIPHER_SPEC
Definition: tls_magic.h:36
Botan::TLS::APPLICATION_DATA
@ APPLICATION_DATA
Definition: tls_magic.h:39
Botan::TLS::NO_RECORD
@ NO_RECORD
Definition: tls_magic.h:41
Botan::TLS::HANDSHAKE
@ HANDSHAKE
Definition: tls_magic.h:38
Botan::TLS::ALERT
@ ALERT
Definition: tls_magic.h:37
Botan::TLS::read_record
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, get_cipherstate_fn get_cipherstate, bool allow_epoch0_restart)
Definition: tls_record.cpp:514
Botan::TLS::MAX_PLAINTEXT_SIZE
@ MAX_PLAINTEXT_SIZE
Definition: tls_magic.h:26

References Botan::TLS::ALERT, Botan::TLS::Policy::allow_dtls_epoch0_restart(), Botan::TLS::APPLICATION_DATA, Botan::TLS::Alert::BAD_RECORD_MAC, BOTAN_ASSERT, BOTAN_ASSERT_IMPLICATION, Botan::TLS::CHANGE_CIPHER_SPEC, Botan::TLS::Alert::DECODE_ERROR, Botan::TLS::Record_Header::epoch(), Botan::TLS::HANDSHAKE, Botan::TLS::Alert::INTERNAL_ERROR, Botan::TLS::Protocol_Version::major_version(), Botan::TLS::MAX_PLAINTEXT_SIZE, Botan::TLS::Record_Header::needed(), Botan::TLS::NO_RECORD, Botan::TLS::Channel::policy(), Botan::TLS::Alert::PROTOCOL_VERSION, Botan::TLS::read_record(), Botan::TLS::Alert::RECORD_OVERFLOW, Botan::TLS::Channel::send_fatal_alert(), Botan::TLS::Record_Header::sequence(), Botan::ASN1::to_string(), Botan::TLS::TLS_Exception::type(), Botan::TLS::Record_Header::type(), Botan::TLS::Alert::UNEXPECTED_MESSAGE, and Botan::TLS::Record_Header::version().

Referenced by Botan::TLS::Blocking_Client::do_handshake(), Botan::TLS::Blocking_Client::read(), and Botan::TLS::Channel::received_data().

## ◆ renegotiate()

void Botan::TLS::Channel::renegotiate | ( | bool | force_full_renegotiation = `false` | ) |
| inherited

Attempt to renegotiate the session

Parameters

  force_full_renegotiation | if true, require a full renegotiation, otherwise allow session resumption

Definition at line 205 of file tls_channel.cpp.

206 {
207 if(pending_state()) // currently in handshake?
208 return;
209
210 if(auto active = active_state())
211 {
212 if(force_full_renegotiation == false)
213 force_full_renegotiation = !policy().allow_resumption_for_renegotiation();
214
215 initiate_handshake(create_handshake_state(active->version()),
216 force_full_renegotiation);
217 }
218 else
219 throw Invalid_State("Cannot renegotiate on inactive connection");
220 }
Botan::TLS::Channel::create_handshake_state
Handshake_State & create_handshake_state(Protocol_Version version)
Definition: tls_channel.cpp:146
Botan::TLS::Channel::initiate_handshake
virtual void initiate_handshake(Handshake_State &state, bool force_full_renegotiation)=0
Botan::TLS::Policy::allow_resumption_for_renegotiation
virtual bool allow_resumption_for_renegotiation() const
Definition: tls_policy.cpp:345

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

## ◆ reset_active_association_state()

void Botan::TLS::Channel::reset_active_association_state | ( |  | ) |
| protected inherited

Definition at line 92 of file tls_channel.cpp.

93 {
94 // This operation only makes sense for DTLS
95 BOTAN_ASSERT_NOMSG(m_is_datagram);
96 m_active_state.reset();
97 m_read_cipher_states.clear();
98 m_write_cipher_states.clear();
99
100 m_write_cipher_states[0] = nullptr;
101 m_read_cipher_states[0] = nullptr;
102
103 if(m_sequence_numbers)
104 m_sequence_numbers->reset();
105 }
BOTAN_ASSERT_NOMSG
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:68

References BOTAN_ASSERT_NOMSG.

## ◆ rng()

RandomNumberGenerator & Botan::TLS::Channel::rng | ( |  | ) |
| inline protected inherited

Definition at line 234 of file tls_channel.h.

234{ return m_rng; }

## ◆ save_session()

bool Botan::TLS::Channel::save_session | ( | const Session & | session | ) |
| protected inherited

Definition at line 141 of file tls_channel.cpp.

142 {
143 return callbacks().tls_session_established(session);
144 }
Botan::TLS::Callbacks::tls_session_established
virtual bool tls_session_established(const Session &session)=0

References Botan::TLS::Channel::callbacks(), and Botan::TLS::Callbacks::tls_session_established().

## ◆ secure_renegotiation_check() [1/2]

void Botan::TLS::Channel::secure_renegotiation_check | ( | const Client_Hello * | client_hello | ) |
| protected inherited

Definition at line 680 of file tls_channel.cpp.

681 {
682 const bool secure_renegotiation = client_hello->secure_renegotiation();
683
684 if(auto active = active_state())
685 {
686 const bool active_sr = active->client_hello()->secure_renegotiation();
687
688 if(active_sr != secure_renegotiation)
689 throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
690 "Client changed its mind about secure renegotiation");
691 }
692
693 if(secure_renegotiation)
694 {
695 const std::vector<uint8_t>& data = client_hello->renegotiation_info();
696
697 if(data != secure_renegotiation_data_for_client_hello())
698 throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
699 "Client sent bad values for secure renegotiation");
700 }
701 }
Botan::TLS::Alert::HANDSHAKE_FAILURE
@ HANDSHAKE_FAILURE
Definition: tls_alert.h:34
Botan::TLS::Channel::secure_renegotiation_data_for_client_hello
std::vector< uint8_t > secure_renegotiation_data_for_client_hello() const
Definition: tls_channel.cpp:726

References Botan::TLS::Alert::HANDSHAKE_FAILURE, Botan::TLS::Client_Hello::renegotiation_info(), Botan::TLS::Client_Hello::secure_renegotiation(), and Botan::TLS::Channel::secure_renegotiation_data_for_client_hello().

## ◆ secure_renegotiation_check() [2/2]

void Botan::TLS::Channel::secure_renegotiation_check | ( | const Server_Hello * | server_hello | ) |
| protected inherited

Definition at line 703 of file tls_channel.cpp.

704 {
705 const bool secure_renegotiation = server_hello->secure_renegotiation();
706
707 if(auto active = active_state())
708 {
709 const bool active_sr = active->server_hello()->secure_renegotiation();
710
711 if(active_sr != secure_renegotiation)
712 throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
713 "Server changed its mind about secure renegotiation");
714 }
715
716 if(secure_renegotiation)
717 {
718 const std::vector<uint8_t>& data = server_hello->renegotiation_info();
719
720 if(data != secure_renegotiation_data_for_server_hello())
721 throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
722 "Server sent bad values for secure renegotiation");
723 }
724 }
Botan::TLS::Channel::secure_renegotiation_data_for_server_hello
std::vector< uint8_t > secure_renegotiation_data_for_server_hello() const
Definition: tls_channel.cpp:733

References Botan::TLS::Alert::HANDSHAKE_FAILURE, Botan::TLS::Server_Hello::renegotiation_info(), Botan::TLS::Server_Hello::secure_renegotiation(), and Botan::TLS::Channel::secure_renegotiation_data_for_server_hello().

## ◆ secure_renegotiation_data_for_client_hello()

std::vector< uint8_t > Botan::TLS::Channel::secure_renegotiation_data_for_client_hello | ( |  | ) | const
| protected inherited

Definition at line 726 of file tls_channel.cpp.

727 {
728 if(auto active = active_state())
729 return active->client_finished()->verify_data();
730 return std::vector<uint8_t>();
731 }

Referenced by Botan::TLS::Channel::secure_renegotiation_check().

## ◆ secure_renegotiation_data_for_server_hello()

std::vector< uint8_t > Botan::TLS::Channel::secure_renegotiation_data_for_server_hello | ( |  | ) | const
| protected inherited

Definition at line 733 of file tls_channel.cpp.

734 {
735 if(auto active = active_state())
736 {
737 std::vector<uint8_t> buf = active->client_finished()->verify_data();
738 buf += active->server_finished()->verify_data();
739 return buf;
740 }
741
742 return std::vector<uint8_t>();
743 }

Referenced by Botan::TLS::Channel::secure_renegotiation_check().

## ◆ secure_renegotiation_supported()

bool Botan::TLS::Channel::secure_renegotiation_supported | ( |  | ) | const
| inherited

Returns
  true iff the counterparty supports the secure renegotiation extensions.

Definition at line 745 of file tls_channel.cpp.

746 {
747 if(auto active = active_state())
748 return active->server_hello()->secure_renegotiation();
749
750 if(auto pending = pending_state())
751 if(auto hello = pending->server_hello())
752 return hello->secure_renegotiation();
753
754 return false;
755 }

## ◆ send() [1/3]

void Botan::TLS::Channel::send | ( | const std::string & | val | ) |
| inherited

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

Definition at line 646 of file tls_channel.cpp.

647 {
648 this->send(cast_char_ptr_to_uint8(string.data()), string.size());
649 }
Botan::TLS::Channel::send
void send(const uint8_t buf[], size_t buf_size)
Definition: tls_channel.cpp:637
Botan::cast_char_ptr_to_uint8
const uint8_t * cast_char_ptr_to_uint8(const char *s)
Definition: mem_ops.h:190

References Botan::cast_char_ptr_to_uint8(), and Botan::TLS::Channel::send().

## ◆ send() [2/3]

template<typename Alloc >

void Botan::TLS::Channel::send | ( | const std::vector< unsigned char, Alloc > & | val | ) |
| inline inherited

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

Definition at line 124 of file tls_channel.h.

125 {
126 send(val.data(), val.size());
127 }

## ◆ send() [3/3]

void Botan::TLS::Channel::send | ( | const uint8_t | buf[],
|  | size_t | buf_size
| ) |  |
| inherited

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

Definition at line 637 of file tls_channel.cpp.

638 {
639 if(!is_active())
640 throw Invalid_State("Data cannot be sent on inactive TLS connection");
641
642 send_record_array(sequence_numbers().current_write_epoch(),
643 APPLICATION_DATA, buf, buf_size);
644 }
Botan::TLS::Channel::is_active
bool is_active() const
Definition: tls_channel.cpp:279

References Botan::TLS::APPLICATION_DATA, and Botan::TLS::Channel::is_active().

Referenced by Botan::TLS::Channel::send().

## ◆ send_alert()

void Botan::TLS::Channel::send_alert | ( | const Alert & | alert | ) |
| inherited

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

Parameters

  alert | the Alert to send

Definition at line 651 of file tls_channel.cpp.

652 {
653 if(alert.is_valid() && !is_closed())
654 {
655 try
656 {
657 send_record(ALERT, alert.serialize());
658 }
659 catch(...) { /* swallow it */ }
660 }
661
662 if(alert.type() == Alert::NO_RENEGOTIATION)
663 m_pending_state.reset();
664
665 if(alert.is_fatal())
666 {
667 if(auto active = active_state())
668 {
669 m_session_manager.remove_entry(active->server_hello()->session_id());
670 }
671 reset_state();
672 }
673
674 if(alert.type() == Alert::CLOSE_NOTIFY || alert.is_fatal())
675 {
676 m_has_been_closed = true;
677 }
678 }
Botan::TLS::Alert::NO_RENEGOTIATION
@ NO_RENEGOTIATION
Definition: tls_alert.h:52
Botan::TLS::Session_Manager::remove_entry
virtual void remove_entry(const std::vector< uint8_t > &session_id)=0

References Botan::TLS::ALERT, Botan::TLS::Alert::CLOSE_NOTIFY, Botan::TLS::Channel::is_closed(), Botan::TLS::Alert::is_fatal(), Botan::TLS::Alert::is_valid(), Botan::TLS::Alert::NO_RENEGOTIATION, Botan::TLS::Session_Manager::remove_entry(), Botan::TLS::Alert::serialize(), and Botan::TLS::Alert::type().

## ◆ send_fatal_alert()

void Botan::TLS::Channel::send_fatal_alert | ( | Alert::Type | type | ) |
| inline inherited

Send a fatal alert

Definition at line 144 of file tls_channel.h.

144{ send_alert(Alert(type, true)); }
Botan::TLS::Channel::send_alert
void send_alert(const Alert &alert)
Definition: tls_channel.cpp:651
type
MechanismType type
Definition: p11_mechanism.cpp:44

References type.

Referenced by Botan::TLS::Channel::received_data().

## ◆ send_warning_alert()

void Botan::TLS::Channel::send_warning_alert | ( | Alert::Type | type | ) |
| inline inherited

Send a warning alert

Definition at line 139 of file tls_channel.h.

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

References type.

## ◆ session_manager()

Session_Manager & Botan::TLS::Channel::session_manager | ( |  | ) |
| inline protected inherited

Definition at line 236 of file tls_channel.h.

236{ return m_session_manager; }

## ◆ timeout_check()

bool Botan::TLS::Channel::timeout_check | ( |  | ) |
| inherited

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.

Definition at line 196 of file tls_channel.cpp.

197 {
198 if(m_pending_state)
199 return m_pending_state->handshake_io().timeout_check();
200
201 //FIXME: scan cipher suites and remove epochs older than 2*MSL
202 return false;
203 }

## Member Data Documentation

## ◆ IO_BUF_DEFAULT_SIZE

size_t Botan::TLS::Channel::IO_BUF_DEFAULT_SIZE = 10*1024
| static inherited

Definition at line 45 of file tls_channel.h.

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

- src/lib/tls/tls_client.h
- src/lib/tls/tls_client.cpp