Botan  2.15.0
Crypto and TLS for C++11
Public Types | Public Member Functions | Static Public Attributes | Protected Member Functions | List of all members
Botan::TLS::Channel Class Referenceabstract

#include <tls_channel.h>

Inheritance diagram for Botan::TLS::Channel:
Botan::TLS::Client Botan::TLS::Server

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

virtual std::string application_protocol () const =0
 
 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)
 
 Channel (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, RandomNumberGenerator &rng, const Policy &policy, bool is_server, bool is_datagram, size_t io_buf_sz=IO_BUF_DEFAULT_SIZE)
 
 Channel (const Channel &)=delete
 
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
 
Channeloperator= (const Channel &)=delete
 
std::vector< X509_Certificatepeer_cert_chain () const
 
size_t received_data (const uint8_t buf[], size_t buf_size)
 
size_t received_data (const std::vector< uint8_t > &buf)
 
void renegotiate (bool force_full_renegotiation=false)
 
bool secure_renegotiation_supported () const
 
void send (const uint8_t buf[], size_t buf_size)
 
void send (const std::string &val)
 
template<typename Alloc >
void send (const std::vector< unsigned char, Alloc > &val)
 
void send_alert (const Alert &alert)
 
void send_fatal_alert (Alert::Type type)
 
void send_warning_alert (Alert::Type type)
 
bool timeout_check ()
 
virtual ~Channel ()
 

Static Public Attributes

static size_t IO_BUF_DEFAULT_SIZE = 10*1024
 

Protected Member Functions

void activate_session ()
 
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)
 
virtual std::vector< X509_Certificateget_peer_cert_chain (const Handshake_State &state) const =0
 
virtual void initiate_handshake (Handshake_State &state, bool force_full_renegotiation)=0
 
void inspect_handshake_message (const Handshake_Message &msg)
 
virtual Handshake_Statenew_handshake_state (class Handshake_IO *io)=0
 
const Policypolicy () const
 
virtual void process_handshake_msg (const Handshake_State *active_state, Handshake_State &pending_state, Handshake_Type type, const std::vector< uint8_t > &contents, bool epoch0_restart)=0
 
void reset_active_association_state ()
 
RandomNumberGeneratorrng ()
 
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_Managersession_manager ()
 

Detailed Description

Generic interface for TLS endpoint

Definition at line 37 of file tls_channel.h.

Member Typedef Documentation

◆ alert_cb

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

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

Definition at line 41 of file tls_channel.h.

◆ handshake_cb

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

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

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

Definition at line 40 of file tls_channel.h.

Constructor & Destructor Documentation

◆ Channel() [1/3]

Botan::TLS::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 
)

Set up a new TLS session

Parameters
callbackscontains a set of callback function references required by the TLS endpoint.
session_managermanages session state
rnga random number generator
policyspecifies other connection policy information
is_serverwhether this is a server session or not
is_datagramwhether this is a DTLS session
io_buf_szThis 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 26 of file tls_channel.cpp.

32  :
33  m_is_server(is_server),
34  m_is_datagram(is_datagram),
35  m_callbacks(callbacks),
36  m_session_manager(session_manager),
37  m_policy(policy),
38  m_rng(rng),
39  m_has_been_closed(false)
40  {
41  init(reserved_io_buffer_size);
42  }
RandomNumberGenerator & rng()
Definition: tls_channel.h:234
Callbacks & callbacks() const
Definition: tls_channel.h:242
const Policy & policy() const
Definition: tls_channel.h:238
Session_Manager & session_manager()
Definition: tls_channel.h:236

◆ Channel() [2/3]

Botan::TLS::Channel::Channel ( 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,
RandomNumberGenerator rng,
const Policy policy,
bool  is_server,
bool  is_datagram,
size_t  io_buf_sz = IO_BUF_DEFAULT_SIZE 
)

DEPRECATED. This constructor is only provided for backward compatibility and should not be used in new implementations. (Not marked deprecated since it is only called internally, by other deprecated constructors)

Definition at line 44 of file tls_channel.cpp.

54  :
55  m_is_server(is_server),
56  m_is_datagram(is_datagram),
57  m_compat_callbacks(new Compat_Callbacks(
58  /*
59  this Channel constructor is also deprecated so its ok that it
60  relies on a deprecated API
61  */
63  out, app_data_cb, recv_alert_cb, hs_cb, hs_msg_cb)),
64  m_callbacks(*m_compat_callbacks.get()),
65  m_session_manager(session_manager),
66  m_policy(policy),
67  m_rng(rng),
68  m_has_been_closed(false)
69  {
70  init(io_buf_sz);
71  }
RandomNumberGenerator & rng()
Definition: tls_channel.h:234
const Policy & policy() const
Definition: tls_channel.h:238
Session_Manager & session_manager()
Definition: tls_channel.h:236

◆ Channel() [3/3]

Botan::TLS::Channel::Channel ( const Channel )
delete

◆ ~Channel()

Botan::TLS::Channel::~Channel ( )
virtual

Definition at line 107 of file tls_channel.cpp.

108  {
109  // So unique_ptr destructors run correctly
110  }

Member Function Documentation

◆ activate_session()

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

Definition at line 291 of file tls_channel.cpp.

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

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 
309  }
virtual void tls_session_activated()
Definition: tls_callbacks.h:97
void map_remove_if(Pred pred, T &assoc)
Definition: stl_util.h:96
Callbacks & callbacks() const
Definition: tls_channel.h:242
virtual uint16_t current_write_epoch() const =0

◆ application_protocol()

virtual std::string Botan::TLS::Channel::application_protocol ( ) const
pure virtual

Implemented in Botan::TLS::Client, and Botan::TLS::Server.

◆ callbacks()

Callbacks& Botan::TLS::Channel::callbacks ( ) const
inlineprotected

Definition at line 242 of file tls_channel.h.

Referenced by activate_session(), and save_session().

242 { return m_callbacks; }

◆ change_cipher_spec_reader()

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

Definition at line 222 of file tls_channel.cpp.

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.

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  }
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
virtual uint16_t current_read_epoch() const =0

◆ change_cipher_spec_writer()

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

Definition at line 251 of file tls_channel.cpp.

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

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  }
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
virtual uint16_t current_write_epoch() const =0

◆ close()

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

Send a close notification alert

Definition at line 149 of file tls_channel.h.

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

◆ create_handshake_state()

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

Definition at line 146 of file tls_channel.cpp.

References Botan::TLS::Protocol_Version::is_datagram_protocol(), new_handshake_state(), Botan::TLS::Alert::PROTOCOL_VERSION, and Botan::TLS::Protocol_Version::to_string().

Referenced by renegotiate().

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  }
virtual Handshake_State * new_handshake_state(class Handshake_IO *io)=0

◆ get_peer_cert_chain()

virtual std::vector<X509_Certificate> Botan::TLS::Channel::get_peer_cert_chain ( const Handshake_State state) const
protectedpure virtual

Referenced by peer_cert_chain().

◆ initiate_handshake()

virtual void Botan::TLS::Channel::initiate_handshake ( Handshake_State state,
bool  force_full_renegotiation 
)
protectedpure virtual

Referenced by renegotiate().

◆ inspect_handshake_message()

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

◆ is_active()

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

Definition at line 279 of file tls_channel.cpp.

References is_closed().

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

280  {
281  if(is_closed())
282  return false;
283  return (active_state() != nullptr);
284  }
bool is_closed() const

◆ is_closed()

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

Definition at line 286 of file tls_channel.cpp.

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

287  {
288  return m_has_been_closed;
289  }

◆ key_material_export()

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

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

Definition at line 757 of file tls_channel.cpp.

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

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  }
constexpr uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:41
std::vector< uint8_t > to_byte_vector(const std::string &s)
Definition: stl_util.h:20

◆ new_handshake_state()

virtual Handshake_State* Botan::TLS::Channel::new_handshake_state ( class Handshake_IO io)
protectedpure virtual

Referenced by create_handshake_state().

◆ operator=()

Channel& Botan::TLS::Channel::operator= ( const Channel )
delete

◆ peer_cert_chain()

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

Definition at line 134 of file tls_channel.cpp.

References get_peer_cert_chain().

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

◆ policy()

const Policy& Botan::TLS::Channel::policy ( ) const
inlineprotected

Definition at line 238 of file tls_channel.h.

Referenced by received_data(), and renegotiate().

238 { return m_policy; }

◆ process_handshake_msg()

virtual void Botan::TLS::Channel::process_handshake_msg ( const Handshake_State active_state,
Handshake_State pending_state,
Handshake_Type  type,
const std::vector< uint8_t > &  contents,
bool  epoch0_restart 
)
protectedpure virtual

◆ received_data() [1/2]

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

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.

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, policy(), Botan::TLS::Alert::PROTOCOL_VERSION, Botan::TLS::read_record(), Botan::TLS::Alert::RECORD_OVERFLOW, 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 received_data().

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  {
438  throw;
439  }
440  catch(Decoding_Error&)
441  {
443  throw;
444  }
445  catch(...)
446  {
448  throw;
449  }
450  }
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:512
size_t needed() const
Definition: tls_record.h:99
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
void send_fatal_alert(Alert::Type type)
Definition: tls_channel.h:144
virtual bool allow_dtls_epoch0_restart() const
Definition: tls_policy.cpp:350
#define BOTAN_ASSERT_IMPLICATION(expr1, expr2, msg)
Definition: assert.h:94
const Policy & policy() const
Definition: tls_channel.h:238

◆ received_data() [2/2]

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

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.

References received_data().

312  {
313  return this->received_data(buf.data(), buf.size());
314  }
size_t received_data(const uint8_t buf[], size_t buf_size)

◆ renegotiate()

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

Attempt to renegotiate the session

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

Definition at line 205 of file tls_channel.cpp.

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

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  }
Handshake_State & create_handshake_state(Protocol_Version version)
const Policy & policy() const
Definition: tls_channel.h:238
virtual bool allow_resumption_for_renegotiation() const
Definition: tls_policy.cpp:345
virtual void initiate_handshake(Handshake_State &state, bool force_full_renegotiation)=0

◆ reset_active_association_state()

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

Definition at line 92 of file tls_channel.cpp.

References BOTAN_ASSERT_NOMSG.

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  }
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:68

◆ rng()

RandomNumberGenerator& Botan::TLS::Channel::rng ( )
inlineprotected

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

Definition at line 141 of file tls_channel.cpp.

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

142  {
143  return callbacks().tls_session_established(session);
144  }
virtual bool tls_session_established(const Session &session)=0
Callbacks & callbacks() const
Definition: tls_channel.h:242

◆ secure_renegotiation_check() [1/2]

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

Definition at line 680 of file tls_channel.cpp.

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

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 
698  throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
699  "Client sent bad values for secure renegotiation");
700  }
701  }
std::vector< uint8_t > secure_renegotiation_data_for_client_hello() const

◆ secure_renegotiation_check() [2/2]

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

Definition at line 703 of file tls_channel.cpp.

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

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 
721  throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
722  "Server sent bad values for secure renegotiation");
723  }
724  }
std::vector< uint8_t > secure_renegotiation_data_for_server_hello() const

◆ secure_renegotiation_data_for_client_hello()

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

Definition at line 726 of file tls_channel.cpp.

Referenced by secure_renegotiation_check().

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

◆ secure_renegotiation_data_for_server_hello()

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

Definition at line 733 of file tls_channel.cpp.

Referenced by secure_renegotiation_check().

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  }

◆ secure_renegotiation_supported()

bool Botan::TLS::Channel::secure_renegotiation_supported ( ) const
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 uint8_t  buf[],
size_t  buf_size 
)

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

Definition at line 637 of file tls_channel.cpp.

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

Referenced by send().

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  }
bool is_active() const

◆ send() [2/3]

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

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

Definition at line 646 of file tls_channel.cpp.

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

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

◆ send() [3/3]

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

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  }
void send(const uint8_t buf[], size_t buf_size)

◆ send_alert()

void Botan::TLS::Channel::send_alert ( const Alert alert)

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

Parameters
alertthe Alert to send

Definition at line 651 of file tls_channel.cpp.

References Botan::TLS::ALERT, Botan::TLS::Alert::CLOSE_NOTIFY, 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().

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  }
virtual void remove_entry(const std::vector< uint8_t > &session_id)=0
bool is_closed() const

◆ send_fatal_alert()

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

Send a fatal alert

Definition at line 144 of file tls_channel.h.

References type.

Referenced by received_data().

144 { send_alert(Alert(type, true)); }
MechanismType type
void send_alert(const Alert &alert)

◆ send_warning_alert()

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

Send a warning alert

Definition at line 139 of file tls_channel.h.

References type.

139 { send_alert(Alert(type, false)); }
MechanismType type
void send_alert(const Alert &alert)

◆ session_manager()

Session_Manager& Botan::TLS::Channel::session_manager ( )
inlineprotected

Definition at line 236 of file tls_channel.h.

236 { return m_session_manager; }

◆ timeout_check()

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

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

Definition at line 45 of file tls_channel.h.


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