Botan 2.19.2
Crypto and TLS for C&
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 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
 
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 101 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 104 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 106 of file tls_handshake_io.h.

108 :
109 m_seqs(seq),
110 m_flights(1),
111 m_initial_timeout(initial_timeout_ms),
112 m_max_timeout(max_timeout_ms),
113 m_send_hs(writer),
114 m_mtu(mtu)
115 {}

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

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

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

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

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

References 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 249 of file tls_handshake_io.cpp.

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

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

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

391 {
392 return this->send_under_epoch(msg, m_seqs.current_write_epoch());
393 }
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 396 of file tls_handshake_io.cpp.

397 {
398 const std::vector<uint8_t> msg_bits = msg.serialize();
399 const Handshake_Type msg_type = msg.type();
400
401 if(msg_type == HANDSHAKE_CCS)
402 {
403 m_send_hs(epoch, CHANGE_CIPHER_SPEC, msg_bits);
404 return std::vector<uint8_t>(); // not included in handshake hashes
405 }
406 else if(msg_type == HELLO_VERIFY_REQUEST)
407 {
408 // This message is not included in the handshake hashes
409 send_message(m_out_message_seq, epoch, msg_type, msg_bits);
410 m_out_message_seq += 1;
411 return std::vector<uint8_t>();
412 }
413
414 // Note: not saving CCS, instead we know it was there due to change in epoch
415 m_flights.rbegin()->push_back(m_out_message_seq);
416 m_flight_data[m_out_message_seq] = Message_Info(epoch, msg_type, msg_bits);
417
418 m_out_message_seq += 1;
419 m_last_write = steady_clock_ms();
420 m_next_timeout = m_initial_timeout;
421
422 return send_message(m_out_message_seq - 1, epoch, msg_type, msg_bits);
423 }
@ HELLO_VERIFY_REQUEST
Definition: tls_magic.h:49

References Botan::TLS::CHANGE_CIPHER_SPEC, Botan::TLS::HANDSHAKE_CCS, Botan::TLS::HELLO_VERIFY_REQUEST, 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 172 of file tls_handshake_io.cpp.

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

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