Botan  2.7.0
Crypto and TLS for C++11
tls_channel.cpp
Go to the documentation of this file.
1 /*
2 * TLS Channels
3 * (C) 2011,2012,2014,2015,2016 Jack Lloyd
4 * 2016 Matthias Gierlings
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/tls_channel.h>
10 #include <botan/tls_policy.h>
11 #include <botan/tls_messages.h>
12 #include <botan/kdf.h>
13 #include <botan/internal/tls_handshake_state.h>
14 #include <botan/internal/tls_record.h>
15 #include <botan/internal/tls_seq_numbers.h>
16 #include <botan/internal/rounding.h>
17 #include <botan/internal/stl_util.h>
18 #include <botan/loadstor.h>
19 
20 namespace Botan {
21 
22 namespace TLS {
23 
24 size_t TLS::Channel::IO_BUF_DEFAULT_SIZE = 10*1024;
25 
27  Session_Manager& session_manager,
29  const Policy& policy,
30  bool is_datagram,
31  size_t reserved_io_buffer_size) :
32  m_is_datagram(is_datagram),
33  m_callbacks(callbacks),
34  m_session_manager(session_manager),
35  m_policy(policy),
36  m_rng(rng)
37  {
38  init(reserved_io_buffer_size);
39  }
40 
42  data_cb app_data_cb,
43  alert_cb recv_alert_cb,
44  handshake_cb hs_cb,
45  handshake_msg_cb hs_msg_cb,
46  Session_Manager& session_manager,
48  const Policy& policy,
49  bool is_datagram,
50  size_t io_buf_sz) :
51  m_is_datagram(is_datagram),
52  m_compat_callbacks(new Compat_Callbacks(
53  /*
54  this Channel constructor is also deprecated so its ok that it
55  relies on a deprecated API
56  */
57  Compat_Callbacks::SILENCE_DEPRECATION_WARNING::PLEASE,
58  out, app_data_cb, recv_alert_cb, hs_cb, hs_msg_cb)),
59  m_callbacks(*m_compat_callbacks.get()),
60  m_session_manager(session_manager),
61  m_policy(policy),
62  m_rng(rng)
63  {
64  init(io_buf_sz);
65  }
66 
67 void Channel::init(size_t io_buf_sz)
68  {
69  /* epoch 0 is plaintext, thus null cipher state */
70  m_write_cipher_states[0] = nullptr;
71  m_read_cipher_states[0] = nullptr;
72 
73  m_writebuf.reserve(io_buf_sz);
74  m_readbuf.reserve(io_buf_sz);
75  }
76 
77 void Channel::reset_state()
78  {
79  m_active_state.reset();
80  m_pending_state.reset();
81  m_readbuf.clear();
82  m_write_cipher_states.clear();
83  m_read_cipher_states.clear();
84  }
85 
87  {
88  // So unique_ptr destructors run correctly
89  }
90 
91 Connection_Sequence_Numbers& Channel::sequence_numbers() const
92  {
93  BOTAN_ASSERT(m_sequence_numbers, "Have a sequence numbers object");
94  return *m_sequence_numbers;
95  }
96 
97 std::shared_ptr<Connection_Cipher_State> Channel::read_cipher_state_epoch(uint16_t epoch) const
98  {
99  auto i = m_read_cipher_states.find(epoch);
100  if(i == m_read_cipher_states.end())
101  throw Internal_Error("TLS::Channel No read cipherstate for epoch " + std::to_string(epoch));
102  return i->second;
103  }
104 
105 std::shared_ptr<Connection_Cipher_State> Channel::write_cipher_state_epoch(uint16_t epoch) const
106  {
107  auto i = m_write_cipher_states.find(epoch);
108  if(i == m_write_cipher_states.end())
109  throw Internal_Error("TLS::Channel No write cipherstate for epoch " + std::to_string(epoch));
110  return i->second;
111  }
112 
113 std::vector<X509_Certificate> Channel::peer_cert_chain() const
114  {
115  if(auto active = active_state())
116  return get_peer_cert_chain(*active);
117  return std::vector<X509_Certificate>();
118  }
119 
120 bool Channel::save_session(const Session& session)
121  {
122  return callbacks().tls_session_established(session);
123  }
124 
126  {
127  if(pending_state())
128  throw Internal_Error("create_handshake_state called during handshake");
129 
130  if(auto active = active_state())
131  {
132  Protocol_Version active_version = active->version();
133 
134  if(active_version.is_datagram_protocol() != version.is_datagram_protocol())
135  throw Exception("Active state using version " +
136  active_version.to_string() +
137  " cannot change to " +
138  version.to_string() +
139  " in pending");
140  }
141 
142  if(!m_sequence_numbers)
143  {
144  if(version.is_datagram_protocol())
145  m_sequence_numbers.reset(new Datagram_Sequence_Numbers);
146  else
147  m_sequence_numbers.reset(new Stream_Sequence_Numbers);
148  }
149 
150  using namespace std::placeholders;
151 
152  std::unique_ptr<Handshake_IO> io;
153  if(version.is_datagram_protocol())
154  {
155  io.reset(new Datagram_Handshake_IO(
156  std::bind(&Channel::send_record_under_epoch, this, _1, _2, _3),
157  sequence_numbers(),
158  static_cast<uint16_t>(m_policy.dtls_default_mtu()),
159  m_policy.dtls_initial_timeout(),
160  m_policy.dtls_maximum_timeout()));
161  }
162  else
163  {
164  io.reset(new Stream_Handshake_IO(std::bind(&Channel::send_record, this, _1, _2)));
165  }
166 
167  m_pending_state.reset(new_handshake_state(io.release()));
168 
169  if(auto active = active_state())
170  m_pending_state->set_version(active->version());
171 
172  return *m_pending_state.get();
173  }
174 
176  {
177  if(m_pending_state)
178  return m_pending_state->handshake_io().timeout_check();
179 
180  //FIXME: scan cipher suites and remove epochs older than 2*MSL
181  return false;
182  }
183 
184 void Channel::renegotiate(bool force_full_renegotiation)
185  {
186  if(pending_state()) // currently in handshake?
187  return;
188 
189  if(auto active = active_state())
190  initiate_handshake(create_handshake_state(active->version()),
191  force_full_renegotiation);
192  else
193  throw Exception("Cannot renegotiate on inactive connection");
194  }
195 
197  {
198  auto pending = pending_state();
199 
200  BOTAN_ASSERT(pending && pending->server_hello(),
201  "Have received server hello");
202 
203  if(pending->server_hello()->compression_method() != 0)
204  throw Internal_Error("Negotiated unknown compression algorithm");
205 
206  sequence_numbers().new_read_cipher_state();
207 
208  const uint16_t epoch = sequence_numbers().current_read_epoch();
209 
210  BOTAN_ASSERT(m_read_cipher_states.count(epoch) == 0,
211  "No read cipher state currently set for next epoch");
212 
213  // flip side as we are reading
214  std::shared_ptr<Connection_Cipher_State> read_state(
215  new Connection_Cipher_State(pending->version(),
216  (side == CLIENT) ? SERVER : CLIENT,
217  false,
218  pending->ciphersuite(),
219  pending->session_keys(),
220  pending->server_hello()->supports_encrypt_then_mac()));
221 
222  m_read_cipher_states[epoch] = read_state;
223  }
224 
226  {
227  auto pending = pending_state();
228 
229  BOTAN_ASSERT(pending && pending->server_hello(),
230  "Have received server hello");
231 
232  if(pending->server_hello()->compression_method() != 0)
233  throw Internal_Error("Negotiated unknown compression algorithm");
234 
235  sequence_numbers().new_write_cipher_state();
236 
237  const uint16_t epoch = sequence_numbers().current_write_epoch();
238 
239  BOTAN_ASSERT(m_write_cipher_states.count(epoch) == 0,
240  "No write cipher state currently set for next epoch");
241 
242  std::shared_ptr<Connection_Cipher_State> write_state(
243  new Connection_Cipher_State(pending->version(),
244  side,
245  true,
246  pending->ciphersuite(),
247  pending->session_keys(),
248  pending->server_hello()->supports_encrypt_then_mac()));
249 
250  m_write_cipher_states[epoch] = write_state;
251  }
252 
253 bool Channel::is_active() const
254  {
255  return (active_state() != nullptr);
256  }
257 
258 bool Channel::is_closed() const
259  {
260  if(active_state() || pending_state())
261  return false;
262 
263  /*
264  * If no active or pending state, then either we had a connection
265  * and it has been closed, or we are a server which has never
266  * received a connection. This case is detectable by also lacking
267  * m_sequence_numbers
268  */
269  return (m_sequence_numbers != nullptr);
270  }
271 
273  {
274  std::swap(m_active_state, m_pending_state);
275  m_pending_state.reset();
276 
277  if(!m_active_state->version().is_datagram_protocol())
278  {
279  // TLS is easy just remove all but the current state
280  const uint16_t current_epoch = sequence_numbers().current_write_epoch();
281 
282  const auto not_current_epoch =
283  [current_epoch](uint16_t epoch) { return (epoch != current_epoch); };
284 
285  map_remove_if(not_current_epoch, m_write_cipher_states);
286  map_remove_if(not_current_epoch, m_read_cipher_states);
287  }
288 
290  }
291 
292 size_t Channel::received_data(const std::vector<uint8_t>& buf)
293  {
294  return this->received_data(buf.data(), buf.size());
295  }
296 
297 size_t Channel::received_data(const uint8_t input[], size_t input_size)
298  {
299  try
300  {
301  while(!is_closed() && input_size)
302  {
303  secure_vector<uint8_t> record_data;
304  uint64_t record_sequence = 0;
305  Record_Type record_type = NO_RECORD;
306  Protocol_Version record_version;
307 
308  size_t consumed = 0;
309 
310  Record_Raw_Input raw_input(input, input_size, consumed, m_is_datagram);
311  Record record(record_data, &record_sequence, &record_version, &record_type);
312  const size_t needed =
313  read_record(m_readbuf,
314  raw_input,
315  record,
316  m_sequence_numbers.get(),
317  [this](uint16_t epoch) { return read_cipher_state_epoch(epoch); });
318 
319  BOTAN_ASSERT(consumed > 0, "Got to eat something");
320 
321  BOTAN_ASSERT(consumed <= input_size,
322  "Record reader consumed sane amount");
323 
324  input += consumed;
325  input_size -= consumed;
326 
327  BOTAN_ASSERT(input_size == 0 || needed == 0,
328  "Got a full record or consumed all input");
329 
330  if(input_size == 0 && needed != 0)
331  return needed; // need more data to complete record
332 
333  if(record_data.size() > MAX_PLAINTEXT_SIZE)
335  "TLS plaintext record is larger than allowed maximum");
336 
337  if(record_type == HANDSHAKE || record_type == CHANGE_CIPHER_SPEC)
338  {
339  process_handshake_ccs(record_data, record_sequence, record_type, record_version);
340  }
341  else if(record_type == APPLICATION_DATA)
342  {
343  process_application_data(record_sequence, record_data);
344  }
345  else if(record_type == ALERT)
346  {
347  process_alert(record_data);
348  }
349  else if(record_type != NO_RECORD)
350  throw Unexpected_Message("Unexpected record type " +
351  std::to_string(record_type) +
352  " from counterparty");
353  }
354 
355  return 0; // on a record boundary
356  }
357  catch(TLS_Exception& e)
358  {
359  send_fatal_alert(e.type());
360  throw;
361  }
362  catch(Integrity_Failure&)
363  {
365  throw;
366  }
367  catch(Decoding_Error&)
368  {
370  throw;
371  }
372  catch(...)
373  {
375  throw;
376  }
377  }
378 
379 void Channel::process_handshake_ccs(const secure_vector<uint8_t>& record,
380  uint64_t record_sequence,
381  Record_Type record_type,
382  Protocol_Version record_version)
383  {
384  if(!m_pending_state)
385  {
386  // No pending handshake, possibly new:
387  if(record_version.is_datagram_protocol())
388  {
389  if(m_sequence_numbers)
390  {
391  /*
392  * Might be a peer retransmit under epoch - 1 in which
393  * case we must retransmit last flight
394  */
395  sequence_numbers().read_accept(record_sequence);
396 
397  const uint16_t epoch = record_sequence >> 48;
398 
399  if(epoch == sequence_numbers().current_read_epoch())
400  {
401  create_handshake_state(record_version);
402  }
403  else if(epoch == sequence_numbers().current_read_epoch() - 1)
404  {
405  BOTAN_ASSERT(m_active_state, "Have active state here");
406  m_active_state->handshake_io().add_record(unlock(record),
407  record_type,
408  record_sequence);
409  }
410  }
411  else if(record_sequence == 0)
412  {
413  create_handshake_state(record_version);
414  }
415  }
416  else
417  {
418  create_handshake_state(record_version);
419  }
420  }
421 
422  // May have been created in above conditional
423  if(m_pending_state)
424  {
425  m_pending_state->handshake_io().add_record(unlock(record),
426  record_type,
427  record_sequence);
428 
429  while(auto pending = m_pending_state.get())
430  {
431  auto msg = pending->get_next_handshake_msg();
432 
433  if(msg.first == HANDSHAKE_NONE) // no full handshake yet
434  break;
435 
436  process_handshake_msg(active_state(), *pending,
437  msg.first, msg.second);
438  }
439  }
440  }
441 
442 void Channel::process_application_data(uint64_t seq_no, const secure_vector<uint8_t>& record)
443  {
444  if(!active_state())
445  throw Unexpected_Message("Application data before handshake done");
446 
447  /*
448  * OpenSSL among others sends empty records in versions
449  * before TLS v1.1 in order to randomize the IV of the
450  * following record. Avoid spurious callbacks.
451  */
452  if(record.size() > 0)
453  callbacks().tls_record_received(seq_no, record.data(), record.size());
454  }
455 
456 void Channel::process_alert(const secure_vector<uint8_t>& record)
457  {
458  Alert alert_msg(record);
459 
460  if(alert_msg.type() == Alert::NO_RENEGOTIATION)
461  m_pending_state.reset();
462 
463  callbacks().tls_alert(alert_msg);
464 
465  if(alert_msg.is_fatal())
466  {
467  if(auto active = active_state())
468  m_session_manager.remove_entry(active->server_hello()->session_id());
469  }
470 
471  if(alert_msg.type() == Alert::CLOSE_NOTIFY)
472  send_warning_alert(Alert::CLOSE_NOTIFY); // reply in kind
473 
474  if(alert_msg.type() == Alert::CLOSE_NOTIFY || alert_msg.is_fatal())
475  {
476  reset_state();
477  }
478  }
479 
480 
481 void Channel::write_record(Connection_Cipher_State* cipher_state, uint16_t epoch,
482  uint8_t record_type, const uint8_t input[], size_t length)
483  {
484  BOTAN_ASSERT(m_pending_state || m_active_state, "Some connection state exists");
485 
486  Protocol_Version record_version =
487  (m_pending_state) ? (m_pending_state->version()) : (m_active_state->version());
488 
489  Record_Message record_message(record_type, 0, input, length);
490 
491  TLS::write_record(m_writebuf,
492  record_message,
493  record_version,
494  sequence_numbers().next_write_sequence(epoch),
495  cipher_state,
496  m_rng);
497 
498  callbacks().tls_emit_data(m_writebuf.data(), m_writebuf.size());
499  }
500 
501 void Channel::send_record_array(uint16_t epoch, uint8_t type, const uint8_t input[], size_t length)
502  {
503  if(length == 0)
504  return;
505 
506  /*
507  * In versions without an explicit IV field (only TLS v1.0 now that
508  * SSLv3 has been removed) send a single byte record first to randomize
509  * the following (implicit) IV of the following record.
510  *
511  * This isn't needed in TLS v1.1 or higher.
512  *
513  * An empty record also works but apparently some implementations do
514  * not like this (https://bugzilla.mozilla.org/show_bug.cgi?id=665814)
515  *
516  * See https://www.openssl.org/~bodo/tls-cbc.txt for background.
517  */
518 
519  auto cipher_state = write_cipher_state_epoch(epoch);
520 
521  if(type == APPLICATION_DATA && m_active_state->version().supports_explicit_cbc_ivs() == false)
522  {
523  write_record(cipher_state.get(), epoch, type, input, 1);
524  input += 1;
525  length -= 1;
526  }
527 
528  while(length)
529  {
530  const size_t sending = std::min<size_t>(length, MAX_PLAINTEXT_SIZE);
531  write_record(cipher_state.get(), epoch, type, input, sending);
532 
533  input += sending;
534  length -= sending;
535  }
536  }
537 
538 void Channel::send_record(uint8_t record_type, const std::vector<uint8_t>& record)
539  {
540  send_record_array(sequence_numbers().current_write_epoch(),
541  record_type, record.data(), record.size());
542  }
543 
544 void Channel::send_record_under_epoch(uint16_t epoch, uint8_t record_type,
545  const std::vector<uint8_t>& record)
546  {
547  send_record_array(epoch, record_type, record.data(), record.size());
548  }
549 
550 void Channel::send(const uint8_t buf[], size_t buf_size)
551  {
552  if(!is_active())
553  throw Exception("Data cannot be sent on inactive TLS connection");
554 
555  send_record_array(sequence_numbers().current_write_epoch(),
556  APPLICATION_DATA, buf, buf_size);
557  }
558 
559 void Channel::send(const std::string& string)
560  {
561  this->send(cast_char_ptr_to_uint8(string.data()), string.size());
562  }
563 
564 void Channel::send_alert(const Alert& alert)
565  {
566  if(alert.is_valid() && !is_closed())
567  {
568  try
569  {
570  send_record(ALERT, alert.serialize());
571  }
572  catch(...) { /* swallow it */ }
573  }
574 
575  if(alert.type() == Alert::NO_RENEGOTIATION)
576  m_pending_state.reset();
577 
578  if(alert.is_fatal())
579  if(auto active = active_state())
580  m_session_manager.remove_entry(active->server_hello()->session_id());
581 
582  if(alert.type() == Alert::CLOSE_NOTIFY || alert.is_fatal())
583  reset_state();
584  }
585 
587  {
588  const bool secure_renegotiation = client_hello->secure_renegotiation();
589 
590  if(auto active = active_state())
591  {
592  const bool active_sr = active->client_hello()->secure_renegotiation();
593 
594  if(active_sr != secure_renegotiation)
596  "Client changed its mind about secure renegotiation");
597  }
598 
599  if(secure_renegotiation)
600  {
601  const std::vector<uint8_t>& data = client_hello->renegotiation_info();
602 
605  "Client sent bad values for secure renegotiation");
606  }
607  }
608 
610  {
611  const bool secure_renegotiation = server_hello->secure_renegotiation();
612 
613  if(auto active = active_state())
614  {
615  const bool active_sr = active->server_hello()->secure_renegotiation();
616 
617  if(active_sr != secure_renegotiation)
619  "Server changed its mind about secure renegotiation");
620  }
621 
622  if(secure_renegotiation)
623  {
624  const std::vector<uint8_t>& data = server_hello->renegotiation_info();
625 
628  "Server sent bad values for secure renegotiation");
629  }
630  }
631 
633  {
634  if(auto active = active_state())
635  return active->client_finished()->verify_data();
636  return std::vector<uint8_t>();
637  }
638 
640  {
641  if(auto active = active_state())
642  {
643  std::vector<uint8_t> buf = active->client_finished()->verify_data();
644  buf += active->server_finished()->verify_data();
645  return buf;
646  }
647 
648  return std::vector<uint8_t>();
649  }
650 
652  {
653  if(auto active = active_state())
654  return active->server_hello()->secure_renegotiation();
655 
656  if(auto pending = pending_state())
657  if(auto hello = pending->server_hello())
658  return hello->secure_renegotiation();
659 
660  return false;
661  }
662 
664  const std::string& context,
665  size_t length) const
666  {
667  if(auto active = active_state())
668  {
669  std::unique_ptr<KDF> prf(active->protocol_specific_prf());
670 
671  const secure_vector<uint8_t>& master_secret =
672  active->session_keys().master_secret();
673 
674  std::vector<uint8_t> salt;
675  salt += active->client_hello()->random();
676  salt += active->server_hello()->random();
677 
678  if(context != "")
679  {
680  size_t context_size = context.length();
681  if(context_size > 0xFFFF)
682  throw Exception("key_material_export context is too long");
683  salt.push_back(get_byte(0, static_cast<uint16_t>(context_size)));
684  salt.push_back(get_byte(1, static_cast<uint16_t>(context_size)));
685  salt += to_byte_vector(context);
686  }
687 
688  return prf->derive_key(length, master_secret, salt, to_byte_vector(label));
689  }
690  else
691  throw Exception("Channel::key_material_export connection not active");
692  }
693 
694 }
695 
696 }
virtual bool tls_session_established(const Session &session)=0
virtual std::vector< X509_Certificate > get_peer_cert_chain(const Handshake_State &state) const =0
virtual void remove_entry(const std::vector< uint8_t > &session_id)=0
bool is_closed() const
Type type() const
Definition: tls_alert.h:79
bool is_fatal() const
Definition: tls_alert.h:74
std::function< void(Alert, const uint8_t[], size_t)> alert_cb
Definition: tls_channel.h:42
SymmetricKey key_material_export(const std::string &label, const std::string &context, size_t length) const
std::vector< uint8_t > renegotiation_info() const
void change_cipher_spec_reader(Connection_Side side)
std::vector< uint8_t > serialize() const
Definition: tls_alert.cpp:31
size_t read_record(secure_vector< uint8_t > &readbuf, Record_Raw_Input &raw_input, Record &rec, Connection_Sequence_Numbers *sequence_numbers, get_cipherstate_fn get_cipherstate)
Definition: tls_record.cpp:504
void change_cipher_spec_writer(Connection_Side side)
const uint8_t * cast_char_ptr_to_uint8(const char *s)
Definition: mem_ops.h:131
void send_warning_alert(Alert::Type type)
Definition: tls_channel.h:141
std::function< void(const uint8_t[], size_t)> output_fn
Definition: tls_channel.h:40
bool secure_renegotiation_supported() const
virtual void tls_alert(Alert alert)=0
Handshake_State & create_handshake_state(Protocol_Version version)
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:210
MechanismType type
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:43
void send_alert(const Alert &alert)
std::vector< uint8_t > secure_renegotiation_data_for_client_hello() const
std::vector< X509_Certificate > peer_cert_chain() const
virtual void tls_record_received(uint64_t seq_no, const uint8_t data[], size_t size)=0
std::string to_string() const
Definition: tls_version.cpp:15
std::function< bool(const Session &)> handshake_cb
Definition: tls_channel.h:43
void send(const uint8_t buf[], size_t buf_size)
bool save_session(const Session &session)
std::vector< uint8_t > secure_renegotiation_data_for_server_hello() const
static size_t IO_BUF_DEFAULT_SIZE
Definition: tls_channel.h:45
virtual Handshake_State * new_handshake_state(class Handshake_IO *io)=0
std::vector< uint8_t > renegotiation_info() const
Definition: tls_messages.h:231
Definition: alg_id.cpp:13
std::vector< uint8_t > to_byte_vector(const std::string &s)
Definition: stl_util.h:20
void send_fatal_alert(Alert::Type type)
Definition: tls_channel.h:146
void secure_renegotiation_check(const Client_Hello *client_hello)
size_t length() const
Definition: symkey.h:25
size_t received_data(const uint8_t buf[], size_t buf_size)
Alert::Type type() const
Definition: tls_exceptn.h:24
std::function< void(const uint8_t[], size_t)> data_cb
Definition: tls_channel.h:41
virtual void tls_session_activated()
Definition: tls_callbacks.h:96
std::vector< T > unlock(const secure_vector< T > &in)
Definition: secmem.h:95
bool secure_renegotiation() const
Definition: tls_messages.h:226
void map_remove_if(Pred pred, T &assoc)
Definition: stl_util.h:96
Channel(Callbacks &callbacks, Session_Manager &session_manager, RandomNumberGenerator &rng, const Policy &policy, bool is_datagram, size_t io_buf_sz=IO_BUF_DEFAULT_SIZE)
Definition: tls_channel.cpp:26
Callbacks & callbacks() const
Definition: tls_channel.h:242
virtual uint16_t current_write_epoch() const =0
virtual void tls_emit_data(const uint8_t data[], size_t size)=0
void renegotiate(bool force_full_renegotiation=false)
void write_record(secure_vector< uint8_t > &output, Record_Message msg, Protocol_Version version, uint64_t seq, Connection_Cipher_State *cs, RandomNumberGenerator &rng)
Definition: tls_record.cpp:210
uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:39
bool is_valid() const
Definition: tls_alert.h:69
virtual void read_accept(uint64_t seq)=0
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
virtual void process_handshake_msg(const Handshake_State *active_state, Handshake_State &pending_state, Handshake_Type type, const std::vector< uint8_t > &contents)=0
virtual uint16_t current_read_epoch() const =0
bool is_active() const
std::function< void(const Handshake_Message &)> handshake_msg_cb
Definition: tls_channel.h:44
virtual void initiate_handshake(Handshake_State &state, bool force_full_renegotiation)=0