Botan  2.4.0
Crypto and TLS for C++11
Classes | Public Types | Public Member Functions | List of all members
Botan::TLS::Datagram_Handshake_IO Class Referencefinal

#include <tls_handshake_io.h>

Inheritance diagram for Botan::TLS::Datagram_Handshake_IO:
Botan::TLS::Handshake_IO

Public Types

typedef std::function< void(uint16_t, uint8_t, const std::vector< uint8_t > &)> writer_fn
 

Public Member Functions

void add_record (const std::vector< uint8_t > &record, Record_Type type, uint64_t sequence_number) override
 
 Datagram_Handshake_IO (writer_fn writer, class Connection_Sequence_Numbers &seq, uint16_t mtu, uint64_t initial_timeout_ms, uint64_t max_timeout_ms)
 
std::vector< uint8_t > format (const std::vector< uint8_t > &handshake_msg, Handshake_Type handshake_type) const override
 
std::pair< Handshake_Type, std::vector< uint8_t > > get_next_record (bool expecting_ccs) override
 
Protocol_Version initial_record_version () const override
 
std::vector< uint8_t > send (const Handshake_Message &msg) override
 
bool timeout_check () override
 

Detailed Description

Handshake IO for datagram-based handshakes

Definition at line 95 of file tls_handshake_io.h.

Member Typedef Documentation

◆ writer_fn

typedef std::function<void (uint16_t, uint8_t, const std::vector<uint8_t>&)> Botan::TLS::Datagram_Handshake_IO::writer_fn

Definition at line 98 of file tls_handshake_io.h.

Constructor & Destructor Documentation

◆ Datagram_Handshake_IO()

Botan::TLS::Datagram_Handshake_IO::Datagram_Handshake_IO ( writer_fn  writer,
class Connection_Sequence_Numbers seq,
uint16_t  mtu,
uint64_t  initial_timeout_ms,
uint64_t  max_timeout_ms 
)
inline

Definition at line 100 of file tls_handshake_io.h.

References Botan::TLS::Handshake_IO::add_record(), Botan::TLS::Handshake_IO::format(), Botan::TLS::Handshake_IO::get_next_record(), Botan::TLS::HANDSHAKE_NONE, Botan::TLS::Handshake_IO::initial_record_version(), Botan::TLS::Handshake_IO::send(), Botan::TLS::Handshake_IO::timeout_check(), and type.

102  :
103  m_seqs(seq),
104  m_flights(1),
105  m_initial_timeout(initial_timeout_ms),
106  m_max_timeout(max_timeout_ms),
107  m_send_hs(writer),
108  m_mtu(mtu)
109  {}

Member Function Documentation

◆ add_record()

void Botan::TLS::Datagram_Handshake_IO::add_record ( const std::vector< uint8_t > &  record,
Record_Type  type,
uint64_t  sequence_number 
)
overridevirtual

Implements Botan::TLS::Handshake_IO.

Definition at line 196 of file tls_handshake_io.cpp.

References Botan::TLS::CHANGE_CIPHER_SPEC, and Botan::load_be< uint16_t >().

199  {
200  const uint16_t epoch = static_cast<uint16_t>(record_sequence >> 48);
201 
202  if(record_type == CHANGE_CIPHER_SPEC)
203  {
204  // TODO: check this is otherwise empty
205  m_ccs_epochs.insert(epoch);
206  return;
207  }
208 
209  const size_t DTLS_HANDSHAKE_HEADER_LEN = 12;
210 
211  const uint8_t* record_bits = record.data();
212  size_t record_size = record.size();
213 
214  while(record_size)
215  {
216  if(record_size < DTLS_HANDSHAKE_HEADER_LEN)
217  return; // completely bogus? at least degenerate/weird
218 
219  const uint8_t msg_type = record_bits[0];
220  const size_t msg_len = load_be24(&record_bits[1]);
221  const uint16_t message_seq = load_be<uint16_t>(&record_bits[4], 0);
222  const size_t fragment_offset = load_be24(&record_bits[6]);
223  const size_t fragment_length = load_be24(&record_bits[9]);
224 
225  const size_t total_size = DTLS_HANDSHAKE_HEADER_LEN + fragment_length;
226 
227  if(record_size < total_size)
228  throw Decoding_Error("Bad lengths in DTLS header");
229 
230  if(message_seq >= m_in_message_seq)
231  {
232  m_messages[message_seq].add_fragment(&record_bits[DTLS_HANDSHAKE_HEADER_LEN],
233  fragment_length,
234  fragment_offset,
235  epoch,
236  msg_type,
237  msg_len);
238  }
239  else
240  {
241  // TODO: detect retransmitted flight
242  }
243 
244  record_bits += total_size;
245  record_size -= total_size;
246  }
247  }
uint16_t load_be< uint16_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:137

◆ format()

std::vector< uint8_t > Botan::TLS::Datagram_Handshake_IO::format ( const std::vector< uint8_t > &  handshake_msg,
Handshake_Type  handshake_type 
) const
overridevirtual

Implements Botan::TLS::Handshake_IO.

Definition at line 383 of file tls_handshake_io.cpp.

385  {
386  return format_w_seq(msg, type, m_in_message_seq - 1);
387  }
MechanismType type

◆ get_next_record()

std::pair< Handshake_Type, std::vector< uint8_t > > Botan::TLS::Datagram_Handshake_IO::get_next_record ( bool  expecting_ccs)
overridevirtual

Returns (HANDSHAKE_NONE, std::vector<>()) if no message currently available

Implements Botan::TLS::Handshake_IO.

Definition at line 250 of file tls_handshake_io.cpp.

References Botan::copy_mem(), Botan::TLS::HANDSHAKE_CCS, Botan::TLS::HANDSHAKE_NONE, Botan::store_be(), and type.

251  {
252  // Expecting a message means the last flight is concluded
253  if(!m_flights.rbegin()->empty())
254  m_flights.push_back(std::vector<uint16_t>());
255 
256  if(expecting_ccs)
257  {
258  if(!m_messages.empty())
259  {
260  const uint16_t current_epoch = m_messages.begin()->second.epoch();
261 
262  if(m_ccs_epochs.count(current_epoch))
263  return std::make_pair(HANDSHAKE_CCS, std::vector<uint8_t>());
264  }
265  return std::make_pair(HANDSHAKE_NONE, std::vector<uint8_t>());
266  }
267 
268  auto i = m_messages.find(m_in_message_seq);
269 
270  if(i == m_messages.end() || !i->second.complete())
271  return std::make_pair(HANDSHAKE_NONE, std::vector<uint8_t>());
272 
273  m_in_message_seq += 1;
274 
275  return i->second.message();
276  }

◆ initial_record_version()

Protocol_Version Botan::TLS::Datagram_Handshake_IO::initial_record_version ( ) const
overridevirtual

◆ send()

std::vector< uint8_t > Botan::TLS::Datagram_Handshake_IO::send ( const Handshake_Message msg)
overridevirtual

Implements Botan::TLS::Handshake_IO.

Definition at line 391 of file tls_handshake_io.cpp.

References Botan::TLS::CHANGE_CIPHER_SPEC, Botan::TLS::DTLS_HEADER_SIZE, Botan::TLS::HANDSHAKE, Botan::TLS::HANDSHAKE_CCS, Botan::TLS::Handshake_Message::serialize(), and Botan::TLS::Handshake_Message::type().

392  {
393  const std::vector<uint8_t> msg_bits = msg.serialize();
394  const uint16_t epoch = m_seqs.current_write_epoch();
395  const Handshake_Type msg_type = msg.type();
396 
397  if(msg_type == HANDSHAKE_CCS)
398  {
399  m_send_hs(epoch, CHANGE_CIPHER_SPEC, msg_bits);
400  return std::vector<uint8_t>(); // not included in handshake hashes
401  }
402 
403  // Note: not saving CCS, instead we know it was there due to change in epoch
404  m_flights.rbegin()->push_back(m_out_message_seq);
405  m_flight_data[m_out_message_seq] = Message_Info(epoch, msg_type, msg_bits);
406 
407  m_out_message_seq += 1;
408  m_last_write = steady_clock_ms();
409  m_next_timeout = m_initial_timeout;
410 
411  return send_message(m_out_message_seq - 1, epoch, msg_type, msg_bits);
412  }
virtual uint16_t current_write_epoch() const =0

◆ timeout_check()

bool Botan::TLS::Datagram_Handshake_IO::timeout_check ( )
overridevirtual

Implements Botan::TLS::Handshake_IO.

Definition at line 174 of file tls_handshake_io.cpp.

175  {
176  if(m_last_write == 0 || (m_flights.size() > 1 && !m_flights.rbegin()->empty()))
177  {
178  /*
179  If we haven't written anything yet obviously no timeout.
180  Also no timeout possible if we are mid-flight,
181  */
182  return false;
183  }
184 
185  const uint64_t ms_since_write = steady_clock_ms() - m_last_write;
186 
187  if(ms_since_write < m_next_timeout)
188  return false;
189 
190  retransmit_last_flight();
191 
192  m_next_timeout = std::min(2 * m_next_timeout, m_max_timeout);
193  return true;
194  }

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