|
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;
}
1.7.6.1