Botan 3.4.0
Crypto and TLS for C&
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, Record_Type, const std::vector< uint8_t > &) writer_fn)
 

Public Member Functions

void add_record (const uint8_t record[], size_t record_len, 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
 
bool have_more_data () const override
 
Protocol_Version initial_record_version () const override
 
std::vector< uint8_t > send (const Handshake_Message &msg) override
 
std::vector< uint8_t > send_under_epoch (const Handshake_Message &msg, uint16_t epoch) override
 
bool timeout_check () override
 

Detailed Description

Handshake IO for datagram-based handshakes

Definition at line 112 of file tls_handshake_io.h.

Member Typedef Documentation

◆ writer_fn

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

Definition at line 114 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 116 of file tls_handshake_io.h.

120 :
121 m_seqs(seq),
122 m_flights(1),
123 m_initial_timeout(initial_timeout_ms),
124 m_max_timeout(max_timeout_ms),
125 m_send_hs(writer),
126 m_mtu(mtu) {}

Member Function Documentation

◆ add_record()

void Botan::TLS::Datagram_Handshake_IO::add_record ( const uint8_t record[],
size_t record_len,
Record_Type type,
uint64_t sequence_number )
overridevirtual

Implements Botan::TLS::Handshake_IO.

Definition at line 172 of file tls_handshake_io.cpp.

175 {
176 const uint16_t epoch = static_cast<uint16_t>(record_sequence >> 48);
177
178 if(record_type == Record_Type::ChangeCipherSpec) {
179 if(record_len != 1 || record[0] != 1) {
180 throw Decoding_Error("Invalid ChangeCipherSpec");
181 }
182
183 // TODO: check this is otherwise empty
184 m_ccs_epochs.insert(epoch);
185 return;
186 }
187
188 const size_t DTLS_HANDSHAKE_HEADER_LEN = 12;
189
190 while(record_len) {
191 if(record_len < DTLS_HANDSHAKE_HEADER_LEN) {
192 return; // completely bogus? at least degenerate/weird
193 }
194
195 const Handshake_Type msg_type = static_cast<Handshake_Type>(record[0]);
196 const size_t msg_len = load_be24(&record[1]);
197 const uint16_t message_seq = load_be<uint16_t>(&record[4], 0);
198 const size_t fragment_offset = load_be24(&record[6]);
199 const size_t fragment_length = load_be24(&record[9]);
200
201 const size_t total_size = DTLS_HANDSHAKE_HEADER_LEN + fragment_length;
202
203 if(record_len < total_size) {
204 throw Decoding_Error("Bad lengths in DTLS header");
205 }
206
207 if(message_seq >= m_in_message_seq) {
208 m_messages[message_seq].add_fragment(
209 &record[DTLS_HANDSHAKE_HEADER_LEN], fragment_length, fragment_offset, epoch, msg_type, msg_len);
210 } else {
211 // TODO: detect retransmitted flight
212 }
213
214 record += total_size;
215 record_len -= total_size;
216 }
217}

References Botan::TLS::ChangeCipherSpec.

◆ 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 343 of file tls_handshake_io.cpp.

343 {
344 return format_w_seq(msg, type, m_in_message_seq - 1);
345}

◆ 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 219 of file tls_handshake_io.cpp.

219 {
220 // Expecting a message means the last flight is concluded
221 if(!m_flights.rbegin()->empty()) {
222 m_flights.push_back(std::vector<uint16_t>());
223 }
224
225 if(expecting_ccs) {
226 if(!m_messages.empty()) {
227 const uint16_t current_epoch = m_messages.begin()->second.epoch();
228
229 if(m_ccs_epochs.contains(current_epoch)) {
230 return std::make_pair(Handshake_Type::HandshakeCCS, std::vector<uint8_t>());
231 }
232 }
233 return std::make_pair(Handshake_Type::None, std::vector<uint8_t>());
234 }
235
236 auto i = m_messages.find(m_in_message_seq);
237
238 if(i == m_messages.end() || !i->second.complete()) {
239 return std::make_pair(Handshake_Type::None, std::vector<uint8_t>());
240 }
241
242 m_in_message_seq += 1;
243
244 return i->second.message();
245}

References Botan::TLS::HandshakeCCS, and Botan::TLS::None.

◆ have_more_data()

bool Botan::TLS::Datagram_Handshake_IO::have_more_data ( ) const
overridevirtual

Implements Botan::TLS::Handshake_IO.

Definition at line 147 of file tls_handshake_io.cpp.

147 {
148 return false;
149}

◆ initial_record_version()

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

Implements Botan::TLS::Handshake_IO.

Definition at line 117 of file tls_handshake_io.cpp.

117 {
118 return Protocol_Version::DTLS_V12;
119}

◆ send()

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

Implements Botan::TLS::Handshake_IO.

Definition at line 347 of file tls_handshake_io.cpp.

347 {
348 return this->send_under_epoch(msg, m_seqs.current_write_epoch());
349}
virtual uint16_t current_write_epoch() const =0
std::vector< uint8_t > send_under_epoch(const Handshake_Message &msg, uint16_t epoch) override

References Botan::TLS::Connection_Sequence_Numbers::current_write_epoch(), and send_under_epoch().

◆ send_under_epoch()

std::vector< uint8_t > Botan::TLS::Datagram_Handshake_IO::send_under_epoch ( const Handshake_Message & msg,
uint16_t epoch )
overridevirtual

Implements Botan::TLS::Handshake_IO.

Definition at line 351 of file tls_handshake_io.cpp.

351 {
352 const std::vector<uint8_t> msg_bits = msg.serialize();
353 const Handshake_Type msg_type = msg.type();
354
355 if(msg_type == Handshake_Type::HandshakeCCS) {
356 m_send_hs(epoch, Record_Type::ChangeCipherSpec, msg_bits);
357 return std::vector<uint8_t>(); // not included in handshake hashes
358 } else if(msg_type == Handshake_Type::HelloVerifyRequest) {
359 // This message is not included in the handshake hashes
360 send_message(m_out_message_seq, epoch, msg_type, msg_bits);
361 m_out_message_seq += 1;
362 return std::vector<uint8_t>();
363 }
364
365 // Note: not saving CCS, instead we know it was there due to change in epoch
366 m_flights.rbegin()->push_back(m_out_message_seq);
367 m_flight_data[m_out_message_seq] = Message_Info(epoch, msg_type, msg_bits);
368
369 m_out_message_seq += 1;
370 m_last_write = steady_clock_ms();
371 m_next_timeout = m_initial_timeout;
372
373 return send_message(m_out_message_seq - 1, epoch, msg_type, msg_bits);
374}

References Botan::TLS::ChangeCipherSpec, Botan::TLS::HandshakeCCS, Botan::TLS::HelloVerifyRequest, Botan::TLS::Handshake_Message::serialize(), and Botan::TLS::Handshake_Message::type().

Referenced by send().

◆ timeout_check()

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

Implements Botan::TLS::Handshake_IO.

Definition at line 151 of file tls_handshake_io.cpp.

151 {
152 if(m_last_write == 0 || (m_flights.size() > 1 && !m_flights.rbegin()->empty())) {
153 /*
154 If we haven't written anything yet obviously no timeout.
155 Also no timeout possible if we are mid-flight,
156 */
157 return false;
158 }
159
160 const uint64_t ms_since_write = steady_clock_ms() - m_last_write;
161
162 if(ms_since_write < m_next_timeout) {
163 return false;
164 }
165
166 retransmit_last_flight();
167
168 m_next_timeout = std::min(2 * m_next_timeout, m_max_timeout);
169 return true;
170}

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