Botan  1.11.15
Classes | Public Types | Public Member Functions
Botan::TLS::Datagram_Handshake_IO Class Reference

#include <tls_handshake_io.h>

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

List of all members.

Classes

class  Handshake_Reassembly
struct  Message_Info

Public Types

typedef std::function< void(u16bit,
byte, const std::vector< byte > &)> 
writer_fn

Public Member Functions

void add_record (const std::vector< byte > &record, Record_Type type, u64bit sequence_number) override
 Datagram_Handshake_IO (writer_fn writer, class Connection_Sequence_Numbers &seq, u16bit mtu)
std::vector< byteformat (const std::vector< byte > &handshake_msg, Handshake_Type handshake_type) const override
std::pair< Handshake_Type,
std::vector< byte > > 
get_next_record (bool expecting_ccs) override
Protocol_Version initial_record_version () const override
std::vector< bytesend (const Handshake_Message &msg) override
bool timeout_check () override

Detailed Description

Handshake IO for datagram-based handshakes

Definition at line 96 of file tls_handshake_io.h.


Member Typedef Documentation

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

Definition at line 99 of file tls_handshake_io.h.


Constructor & Destructor Documentation

Definition at line 101 of file tls_handshake_io.h.

                                        :
         m_seqs(seq), m_flights(1), m_send_hs(writer), m_mtu(mtu) {}

Member Function Documentation

void Botan::TLS::Datagram_Handshake_IO::add_record ( const std::vector< byte > &  record,
Record_Type  type,
u64bit  sequence_number 
) [override, virtual]

Implements Botan::TLS::Handshake_IO.

Definition at line 182 of file tls_handshake_io.cpp.

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

   {
   const u16bit epoch = static_cast<u16bit>(record_sequence >> 48);

   if(record_type == CHANGE_CIPHER_SPEC)
      {
      // TODO: check this is otherwise empty
      m_ccs_epochs.insert(epoch);
      return;
      }

   const size_t DTLS_HANDSHAKE_HEADER_LEN = 12;

   const byte* record_bits = &record[0];
   size_t record_size = record.size();

   while(record_size)
      {
      if(record_size < DTLS_HANDSHAKE_HEADER_LEN)
         return; // completely bogus? at least degenerate/weird

      const byte msg_type = record_bits[0];
      const size_t msg_len = load_be24(&record_bits[1]);
      const u16bit message_seq = load_be<u16bit>(&record_bits[4], 0);
      const size_t fragment_offset = load_be24(&record_bits[6]);
      const size_t fragment_length = load_be24(&record_bits[9]);

      const size_t total_size = DTLS_HANDSHAKE_HEADER_LEN + fragment_length;

      if(record_size < total_size)
         throw Decoding_Error("Bad lengths in DTLS header");

      if(message_seq >= m_in_message_seq)
         {
         m_messages[message_seq].add_fragment(&record_bits[DTLS_HANDSHAKE_HEADER_LEN],
                                              fragment_length,
                                              fragment_offset,
                                              epoch,
                                              msg_type,
                                              msg_len);
         }
      else
         {
         // TODO: detect retransmitted flight
         }

      record_bits += total_size;
      record_size -= total_size;
      }
   }
std::vector< byte > Botan::TLS::Datagram_Handshake_IO::format ( const std::vector< byte > &  handshake_msg,
Handshake_Type  handshake_type 
) const [override, virtual]

Implements Botan::TLS::Handshake_IO.

Definition at line 367 of file tls_handshake_io.cpp.

   {
   return format_w_seq(msg, type, m_in_message_seq - 1);
   }
std::pair< Handshake_Type, std::vector< byte > > Botan::TLS::Datagram_Handshake_IO::get_next_record ( bool  expecting_ccs) [override, virtual]

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

Implements Botan::TLS::Handshake_IO.

Definition at line 236 of file tls_handshake_io.cpp.

References Botan::TLS::HANDSHAKE_CCS, and Botan::TLS::HANDSHAKE_NONE.

   {
   // Expecting a message means the last flight is concluded
   if(!m_flights.rbegin()->empty())
      m_flights.push_back(std::vector<u16bit>());

   if(expecting_ccs)
      {
      if(!m_messages.empty())
         {
         const u16bit current_epoch = m_messages.begin()->second.epoch();

         if(m_ccs_epochs.count(current_epoch))
            return std::make_pair(HANDSHAKE_CCS, std::vector<byte>());
         }

      return std::make_pair(HANDSHAKE_NONE, std::vector<byte>());
      }

   auto i = m_messages.find(m_in_message_seq);

   if(i == m_messages.end() || !i->second.complete())
      return std::make_pair(HANDSHAKE_NONE, std::vector<byte>());

   m_in_message_seq += 1;

   return i->second.message();
   }
std::vector< byte > Botan::TLS::Datagram_Handshake_IO::send ( const Handshake_Message msg) [override, virtual]

Implements Botan::TLS::Handshake_IO.

Definition at line 390 of file tls_handshake_io.cpp.

References Botan::TLS::CHANGE_CIPHER_SPEC, Botan::TLS::Connection_Sequence_Numbers::current_write_epoch(), Botan::TLS::HANDSHAKE_CCS, Botan::TLS::Handshake_Message::serialize(), and Botan::TLS::Handshake_Message::type().

   {
   const std::vector<byte> msg_bits = msg.serialize();
   const u16bit epoch = m_seqs.current_write_epoch();
   const Handshake_Type msg_type = msg.type();

   if(msg_type == HANDSHAKE_CCS)
      {
      m_send_hs(epoch, CHANGE_CIPHER_SPEC, msg_bits);
      return std::vector<byte>(); // not included in handshake hashes
      }

   // Note: not saving CCS, instead we know it was there due to change in epoch
   m_flights.rbegin()->push_back(m_out_message_seq);
   m_flight_data[m_out_message_seq] = Message_Info(epoch, msg_type, msg_bits);

   m_out_message_seq += 1;
   m_last_write = steady_clock_ms();
   m_next_timeout = INITIAL_TIMEOUT;

   return send_message(m_out_message_seq - 1, epoch, msg_type, msg_bits);
   }

Implements Botan::TLS::Handshake_IO.

Definition at line 137 of file tls_handshake_io.cpp.

References BOTAN_ASSERT, and Botan::TLS::CHANGE_CIPHER_SPEC.

   {
   if(m_last_write == 0 || (m_flights.size() > 1 && !m_flights.rbegin()->empty()))
      {
      /*
      If we haven't written anything yet obviously no timeout.
      Also no timeout possible if we are mid-flight,
      */
      return false;
      }

   const u64bit ms_since_write = steady_clock_ms() - m_last_write;

   if(ms_since_write < m_next_timeout)
      return false;

   std::vector<u16bit> flight;
   if(m_flights.size() == 1)
      flight = m_flights.at(0); // lost initial client hello
   else
      flight = m_flights.at(m_flights.size() - 2);

   BOTAN_ASSERT(flight.size() > 0, "Nonempty flight to retransmit");

   u16bit epoch = m_flight_data[flight[0]].epoch;

   for(auto msg_seq : flight)
      {
      auto& msg = m_flight_data[msg_seq];

      if(msg.epoch != epoch)
         {
         // Epoch gap: insert the CCS
         std::vector<byte> ccs(1, 1);
         m_send_hs(epoch, CHANGE_CIPHER_SPEC, ccs);
         }

      send_message(msg_seq, msg.epoch, msg.msg_type, msg.msg_bits);
      epoch = msg.epoch;
      }

   m_next_timeout = std::min(2 * m_next_timeout, MAXIMUM_TIMEOUT);
   return true;
   }

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