Botan
1.11.15
|
#include <tls_handshake_io.h>
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< byte > | format (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< byte > | send (const Handshake_Message &msg) override |
bool | timeout_check () override |
Handshake IO for datagram-based handshakes
Definition at line 96 of file tls_handshake_io.h.
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.
Botan::TLS::Datagram_Handshake_IO::Datagram_Handshake_IO | ( | writer_fn | writer, |
class Connection_Sequence_Numbers & | seq, | ||
u16bit | mtu | ||
) | [inline] |
Definition at line 101 of file tls_handshake_io.h.
: m_seqs(seq), m_flights(1), m_send_hs(writer), m_mtu(mtu) {}
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(); }
Protocol_Version Botan::TLS::Datagram_Handshake_IO::initial_record_version | ( | ) | const [override, virtual] |
Implements Botan::TLS::Handshake_IO.
Definition at line 118 of file tls_handshake_io.cpp.
References Botan::TLS::Protocol_Version::DTLS_V10.
{ return Protocol_Version::DTLS_V10; }
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); }
bool Botan::TLS::Datagram_Handshake_IO::timeout_check | ( | ) | [override, virtual] |
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; }