Botan 3.13.0
Crypto and TLS for C&
tls_handshake_io.cpp
Go to the documentation of this file.
1/*
2* TLS Handshake IO
3* (C) 2012,2014,2015 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/internal/tls_handshake_io.h>
9
10#include <botan/assert.h>
11#include <botan/exceptn.h>
12#include <botan/tls_exceptn.h>
13#include <botan/tls_handshake_msg.h>
14#include <botan/internal/fmt.h>
15#include <botan/internal/loadstor.h>
16#include <botan/internal/tls_record.h>
17#include <botan/internal/tls_seq_numbers.h>
18
19namespace Botan::TLS {
20
21namespace {
22
23constexpr size_t DTLS_HANDSHAKE_HEADER_SIZE = 12;
24
25// Bound on peer-cued flight replays when the policy leaves the timer's own retransmission
26// count unlimited. Matches the default value of Policy::dtls_maximum_retransmissions.
27constexpr size_t DEFAULT_PEER_REPLAY_BUDGET = 12;
28
29inline size_t load_be24(const uint8_t q[3]) {
30 return make_uint32(0, q[0], q[1], q[2]);
31}
32
33// Reject handshake type values that are internal sentinels, not wire values
34void verify_is_expected_wire_handshake_type(Handshake_Type type) {
35 switch(type) {
39 throw TLS_Exception(Alert::UnexpectedMessage, "Invalid handshake message type");
40 default:
41 break;
42 }
43}
44
45void store_be24(uint8_t out[3], size_t val) {
46 out[0] = get_byte<1>(static_cast<uint32_t>(val));
47 out[1] = get_byte<2>(static_cast<uint32_t>(val));
48 out[2] = get_byte<3>(static_cast<uint32_t>(val));
49}
50
51} // namespace
52
54 return Protocol_Version::TLS_V12;
55}
56
57void Stream_Handshake_IO::add_record(const uint8_t record[],
58 size_t record_len,
59 Record_Type record_type,
60 uint64_t /*sequence_number*/) {
61 if(record_type == Record_Type::Handshake) {
62 m_queue.insert(m_queue.end(), record, record + record_len);
63 } else if(record_type == Record_Type::ChangeCipherSpec) {
64 if(record_len != 1 || record[0] != 1) {
65 throw Decoding_Error("Invalid ChangeCipherSpec");
66 }
67
68 // Pretend it's a regular handshake message of zero length
69 const uint8_t ccs_hs[] = {static_cast<uint8_t>(Handshake_Type::HandshakeCCS), 0, 0, 0};
70 m_queue.insert(m_queue.end(), ccs_hs, ccs_hs + sizeof(ccs_hs));
71 } else {
72 throw Decoding_Error("Unknown message type " + std::to_string(static_cast<size_t>(record_type)) +
73 " in handshake processing");
74 }
75}
76
77std::pair<Handshake_Type, std::vector<uint8_t>> Stream_Handshake_IO::get_next_record(bool expecting_ccs,
78 size_t max_message_size) {
79 if(m_queue.size() >= 4) {
80 const Handshake_Type type = static_cast<Handshake_Type>(m_queue[0]);
81
82 const size_t rec_length = make_uint32(0, m_queue[1], m_queue[2], m_queue[3]);
83
84 // If we are expecting a CCS but the next queued message is not a CCS,
85 // the peer has skipped the CCS message. This can happen when the peer
86 // sends an encrypted Finished without the preceding CCS, in which case
87 // the encrypted bytes are misinterpreted as a handshake message.
88 if(expecting_ccs) {
89 const bool is_ccs = (type == Handshake_Type::HandshakeCCS && rec_length == 0);
90 if(!is_ccs) {
91 throw TLS_Exception(Alert::UnexpectedMessage, "Expected ChangeCipherSpec but got a handshake message");
92 }
93 } else {
94 verify_is_expected_wire_handshake_type(type);
95
96 if(max_message_size > 0 && rec_length > max_message_size) {
97 throw TLS_Exception(
98 Alert::HandshakeFailure,
99 Botan::fmt("Handshake message is {} bytes, policy maximum is {}", rec_length, max_message_size));
100 }
101 }
102
103 const size_t length = 4 + rec_length;
104
105 if(m_queue.size() >= length) {
106 const std::vector<uint8_t> contents(m_queue.begin() + 4, m_queue.begin() + length);
107
108 m_queue.erase(m_queue.begin(), m_queue.begin() + length);
109
110 return std::make_pair(type, contents);
111 }
112 }
113
114 return std::make_pair(Handshake_Type::None, std::vector<uint8_t>());
115}
116
117std::vector<uint8_t> Stream_Handshake_IO::format(const std::vector<uint8_t>& msg, Handshake_Type type) const {
118 std::vector<uint8_t> send_buf(4 + msg.size());
119
120 const size_t buf_size = msg.size();
121
122 send_buf[0] = static_cast<uint8_t>(type);
123
124 store_be24(&send_buf[1], buf_size);
125
126 if(!msg.empty()) {
127 copy_mem(&send_buf[4], msg.data(), msg.size());
128 }
129
130 return send_buf;
131}
132
133std::vector<uint8_t> Stream_Handshake_IO::send_under_epoch(const Handshake_Message& /*msg*/, uint16_t /*epoch*/) {
134 throw Invalid_State("Not possible to send under arbitrary epoch with stream based TLS");
135}
136
137std::vector<uint8_t> Stream_Handshake_IO::send(const Handshake_Message& msg) {
138 const std::vector<uint8_t> msg_bits = msg.serialize();
139
141 m_send_hs(Record_Type::ChangeCipherSpec, msg_bits);
142 return std::vector<uint8_t>(); // not included in handshake hashes
143 }
144
145 auto buf = format(msg_bits, msg.wire_type());
146 m_send_hs(Record_Type::Handshake, buf);
147 return buf;
148}
149
150#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
151
152std::vector<uint8_t> Stream_Handshake_IO::start_with_client_hello_from_downgrade(
153 const Handshake_Message& client_hello) {
155 "Expected ClientHello message for TLS downgrade");
156
157 // In TLS we don't have to update any internal state, we just need to
158 // format the Client Hello message for absorption into the handshake hash.
159 return format(client_hello.serialize(), client_hello.wire_type());
160}
161
162#endif
163
164namespace {
165
166size_t max_pending_reassembly(size_t policy_hs_max) {
167 /*
168 * Here we set arbitrary but probably more than sufficient bounds on the *overall*
169 * allocation that is allowed across the entire handshake.
170 *
171 * If the policy set a limit on individual handshake message sizes, accept up to 4
172 * times that for the whole handshake. This is more than generous considering most
173 * handshake messages are fixed length or are relatively tightly bounded. The default
174 * per-handshake message bound is 64 KiB so without application intervention this will
175 * top out at 256 KiB for a handshake.
176 *
177 * If the application explicitly disables the per handshake message bound, still apply
178 * an arbitrary upper bound of 16 MiB for the handshake.
179 */
180 constexpr size_t overall_cap = 16 * 1024 * 1024;
181
182 if(policy_hs_max == 0 || policy_hs_max >= overall_cap / 4) {
183 // If disabled or huge just take our max
184 return overall_cap;
185 } else {
186 // Otherwise 4x the per-message max
187 return policy_hs_max * 4;
188 }
189}
190
191} // namespace
192
194 steady_clock_fn steady_clock_ms,
196 uint16_t mtu,
197 uint64_t initial_timeout_ms,
198 uint64_t max_timeout_ms,
199 std::optional<size_t> max_retransmissions,
200 size_t max_handshake_msg_size,
201 uint16_t initial_epoch) :
202 m_seqs(seq),
203 m_flights(1),
204 m_flight_ccs(1),
205 m_initial_timeout(initial_timeout_ms),
206 m_max_timeout(max_timeout_ms),
207 m_max_retransmissions(max_retransmissions),
208 m_initial_epoch(initial_epoch),
209 m_last_delivered_epoch(initial_epoch),
210 m_send_hs(std::move(writer)),
211 m_steady_clock_ms(std::move(steady_clock_ms)),
212 m_mtu(mtu),
213 m_max_handshake_msg_size(max_handshake_msg_size),
214 m_max_pending_reassembly(max_pending_reassembly(m_max_handshake_msg_size)) {}
215
217 return Protocol_Version::DTLS_V12;
218}
219
220std::optional<size_t> Datagram_Handshake_IO::last_completed_flight_index() const {
221 // m_flights keeps an empty trailing slot while waiting for the peer, so the
222 // last completed flight is normally the one before it.
223 const size_t flight_idx = (m_flights.size() == 1) ? 0 : (m_flights.size() - 2);
224
225 // A peer can ask us to replay a flight before we have sent one, eg
226 // with a ClientHello whose message_seq is past the reassembly
227 // window. In that case there is nothing to retransmit.
228 if(m_flights[flight_idx].empty()) {
229 return std::nullopt;
230 }
231
232 return flight_idx;
233}
234
235void Datagram_Handshake_IO::retransmit_last_flight() {
236 if(const auto flight_idx = last_completed_flight_index()) {
237 retransmit_flight(*flight_idx);
238 m_last_write = m_steady_clock_ms();
239 }
240}
241
242/*
243* RFC 6347 4.2.4 gives the WAITING state a "read retransmit" transition that
244* replays our flight when the peer retransmits theirs.
245*
246* The cue for it is unauthenticated epoch-zero data, so this deliberately is not
247* retransmit_last_flight(). Re-anchoring m_last_write the way that does means a
248* peer cueing faster than the timeout keeps next_retransmission_timeout() from
249* ever expiring, so m_retransmit_count never advances and the handshake never
250* gives up; and unbounded, each cue draws a whole flight toward whatever address
251* the cue claims to come from.
252*
253* Spending the timer's own budget, reset by the same forward progress, caps a
254* continuously cueing peer at doubling the flight traffic the handshake would
255* emit anyway. Counting rather than rate limiting answers a legitimate peer's
256* retransmit promptly, which BoGo's DTLS-Retransmit-Client-Basic requires.
257*/
258void Datagram_Handshake_IO::replay_last_flight_for_peer() {
259 // An unset m_max_retransmissions means "retransmit on my own timer forever",
260 // which is a different proposition from "replay whenever an unauthenticated
261 // packet asks me to". This path is never unbounded, whatever the policy.
262 const size_t bound = m_max_retransmissions.value_or(DEFAULT_PEER_REPLAY_BUDGET);
263
264 if(m_peer_replay_count >= bound) {
265 return;
266 }
267
268 if(const auto flight_idx = last_completed_flight_index()) {
269 m_peer_replay_count += 1;
270 retransmit_flight(*flight_idx);
271 }
272}
273
274void Datagram_Handshake_IO::retransmit_flight(size_t flight_idx) {
275 const auto& flight = m_flights.at(flight_idx);
276 const auto& ccs_records = m_flight_ccs.at(flight_idx);
277 const std::vector<uint8_t> ccs = {1};
278
279 BOTAN_ASSERT(!flight.empty(), "Nonempty flight to retransmit");
280
281 size_t ccs_idx = 0;
282 for(size_t msg_idx = 0; msg_idx != flight.size(); ++msg_idx) {
283 while(ccs_idx != ccs_records.size() && ccs_records[ccs_idx].first == msg_idx) {
284 m_send_hs(ccs_records[ccs_idx].second, Record_Type::ChangeCipherSpec, ccs);
285 ++ccs_idx;
286 }
287
288 const auto msg_seq = flight[msg_idx];
289 const auto& msg = m_flight_data.at(msg_seq);
290 send_message(msg_seq, msg.epoch, msg.msg_type, msg.msg_bits);
291 }
292
293 while(ccs_idx != ccs_records.size() && ccs_records[ccs_idx].first == flight.size()) {
294 m_send_hs(ccs_records[ccs_idx].second, Record_Type::ChangeCipherSpec, ccs);
295 ++ccs_idx;
296 }
297}
298
300 // Future or incomplete fragments remain buffered, but only a complete
301 // next-in-sequence message is trailing handshake data.
302 const auto next = m_messages.find(m_in_message_seq);
303 return next != m_messages.end() && next->second.complete();
304}
305
306void Datagram_Handshake_IO::finalize_handshake(bool retransmit_terminal_flight) {
307 // Keep an empty trailing flight to mean "we are waiting for the peer".
308 // Retransmission then replays the previous, completed flight instead of
309 // appending to it.
310 if(!m_flights.rbegin()->empty()) {
311 m_flights.emplace_back();
312 m_flight_ccs.emplace_back();
313 }
314
315 // RFC 6347 4.2.4: "Once the messages have been sent, the implementation
316 // then enters the FINISHED state if this is the last flight in the
317 // handshake." Keep the flight for reactive replay when the peer
318 // retransmits, but do not arm a proactive retransmission timer.
319 m_finished = true;
320 m_retransmit_terminal_flight = retransmit_terminal_flight;
321}
322
324 const auto timeout = next_retransmission_timeout();
325 if(!timeout || timeout->count() > 0) {
326 return false;
327 }
328
329 // The retransmit timer has expired. Count this attempt and, once the
330 // configured cap is reached, abandon the handshake rather than retransmit
331 // forever. RFC 6347 4.2.4.1 gives the backoff schedule but states no
332 // condition for giving up, so the cap is local policy, not a requirement.
333 // No alert is sent - the peer is by definition unresponsive.
334 m_retransmit_count += 1;
335 if(m_max_retransmissions.has_value() && m_retransmit_count > m_max_retransmissions.value()) {
336 throw TLS_Exception(Alert::None, "DTLS handshake timed out: maximum retransmissions exceeded");
337 }
338
339 // retransmit_last_flight re-anchors m_last_write. Without that, once
340 // m_next_timeout saturates at m_max_timeout the elapsed time keeps growing
341 // and every subsequent poll fires another retransmission.
342 retransmit_last_flight();
343
344 m_next_timeout = std::min(2 * m_next_timeout, m_max_timeout);
345 return true;
346}
347
348std::optional<std::chrono::milliseconds> Datagram_Handshake_IO::next_retransmission_timeout() const {
349 if(m_finished) {
350 return std::nullopt;
351 }
352
353 // Without an outgoing flight, or while constructing one, there is nothing
354 // complete that timeout_check() could retransmit.
355 if(!m_last_write.has_value() || (m_flights.size() > 1 && !m_flights.rbegin()->empty())) {
356 return std::nullopt;
357 }
358
359 const uint64_t ms_since_write = m_steady_clock_ms() - m_last_write.value();
360 if(ms_since_write >= m_next_timeout) {
361 return std::chrono::milliseconds(0);
362 }
363
364 // BoringSSL reports a sub-15ms remainder as zero (ssl/d1_lib.cc
365 // DTLSTimer::MicrosecondsRemaining) to absorb divergence with caller
366 // scheduling; BoGo's DTLS-Retransmit-Fudge test requires it. The cap keeps
367 // the fudge from swallowing the very short timers some tests configure.
368 const uint64_t fudge_ms = std::min<uint64_t>(15, m_initial_timeout / 2);
369 const uint64_t remaining_ms = m_next_timeout - ms_since_write;
370
371 return std::chrono::milliseconds(remaining_ms <= fudge_ms ? 0 : remaining_ms);
372}
373
374void Datagram_Handshake_IO::add_record(const uint8_t record[],
375 size_t record_len,
376 Record_Type record_type,
377 uint64_t record_sequence) {
378 add_record(record, record_len, record_type, record_sequence, false);
379}
380
382 size_t record_len,
383 Record_Type record_type,
384 uint64_t record_sequence) {
385 add_record(record, record_len, record_type, record_sequence, true);
386}
387
388bool Datagram_Handshake_IO::reassemble_retransmitted_fragment(const uint8_t fragment[],
389 size_t fragment_length,
390 size_t fragment_offset,
391 uint16_t epoch,
392 Handshake_Type msg_type,
393 size_t msg_length,
394 uint16_t message_seq) {
395 auto [i, inserted] = m_retransmitted_messages.try_emplace(msg_type, message_seq, Handshake_Reassembly{});
396
397 if(!inserted && i->second.first != message_seq) {
398 release_reassembly_bytes(i->second.second);
399 i->second = std::make_pair(message_seq, Handshake_Reassembly());
400 }
401
402 auto& reassembly = i->second.second;
403
404 // These buffers hold unauthenticated input, so they are charged against the
405 // same budget as the main reassembly path rather than growing on their own.
406 if(!charged_add_fragment(reassembly,
407 m_max_pending_reassembly,
408 fragment,
409 fragment_length,
410 fragment_offset,
411 epoch,
412 msg_type,
413 msg_length)) {
414 return false;
415 }
416
417 if(!reassembly.complete()) {
418 return false;
419 }
420
421 release_reassembly_bytes(reassembly);
422 m_retransmitted_messages.erase(i);
423 return true;
424}
425
426bool Datagram_Handshake_IO::charged_add_fragment(Handshake_Reassembly& reassembly,
427 size_t ceiling,
428 const uint8_t fragment[],
429 size_t fragment_length,
430 size_t fragment_offset,
431 uint16_t epoch,
432 Handshake_Type msg_type,
433 size_t msg_length) {
434 // We allocate the entire block on the first fragment, so charge it against
435 // the bound at that point. Later fragments must agree with the declared
436 // length, so admission is decided once per slot and retransmissions are
437 // never re-charged.
438 if(!reassembly.initialized()) {
439 if(m_pending_reassembly_bytes + msg_length > ceiling) {
440 return false;
441 }
442 m_pending_reassembly_bytes += msg_length;
443 }
444
445 reassembly.add_fragment(fragment, fragment_length, fragment_offset, epoch, msg_type, msg_length);
446 return true;
447}
448
449void Datagram_Handshake_IO::release_reassembly_bytes(const Handshake_Reassembly& reassembly) {
450 BOTAN_ASSERT_NOMSG(m_pending_reassembly_bytes >= reassembly.msg_length());
451 m_pending_reassembly_bytes -= reassembly.msg_length();
452}
453
454bool Datagram_Handshake_IO::process_previous_handshake_fragment(const uint8_t fragment[],
455 size_t fragment_length,
456 size_t fragment_offset,
457 uint16_t epoch,
458 Handshake_Type msg_type,
459 size_t msg_length,
460 uint16_t message_seq,
461 bool retransmitted_flight) {
462 // Empty fragments of non-empty messages add no information and must not
463 // trigger a flight retransmission. A zero-length message such as
464 // ServerHelloDone is not an empty fragment in this sense.
465 if(fragment_length == 0 && msg_length != 0) {
466 return false;
467 }
468
469 // HelloVerifyRequest has no retransmission timer or cached flight. Feed a
470 // retransmitted initial ClientHello back to the server handshake logic so
471 // it can recreate the stateless cookie response instead.
472 if(msg_type == Handshake_Type::ClientHello) {
473 if(!retransmitted_flight && m_awaiting_cookie_client_hello) {
474 if(!m_retransmitted_client_hello.has_value() || m_retransmitted_client_hello->first != message_seq) {
475 if(m_retransmitted_client_hello.has_value()) {
476 release_reassembly_bytes(m_retransmitted_client_hello->second);
477 }
478 m_retransmitted_client_hello = std::make_pair(message_seq, Handshake_Reassembly());
479 }
480
481 charged_add_fragment(m_retransmitted_client_hello->second,
482 m_max_pending_reassembly,
483 fragment,
484 fragment_length,
485 fragment_offset,
486 epoch,
487 msg_type,
488 msg_length);
489 return false;
490 }
491
492 // RFC 6347 4.2.4 makes the terminal-flight sender "respond to a retransmit
493 // of the peer's last flight with a retransmit of the last flight". Once our
494 // handshake has completed, the peer's last flight is the one ending in its
495 // Finished, never a ClientHello.
496 if(m_finished) {
497 return false;
498 }
499
500 return reassemble_retransmitted_fragment(
501 fragment, fragment_length, fragment_offset, epoch, msg_type, msg_length, message_seq);
502 }
503
504 // Only an association that has already completed its handshake answers a
505 // retransmitted peer flight here.
506 //
507 // RFC 6347 4.2.4 also gives the WAITING state a "read retransmit" exit that
508 // replays the outgoing flight immediately. Applying that while the handshake
509 // is still pending misfires under fragment reordering: a late duplicate
510 // fragment of an already-consumed message is indistinguishable from a
511 // genuine retransmission, so the peer sees a flight replay it never asked
512 // for (BoGo ReorderHandshakeFragments-Large). Recovery is left to the local
513 // retransmission timer, which costs latency but cannot desynchronise a peer
514 // that was not retransmitting. A retransmitted ClientHello is handled above,
515 // because the stateless cookie response has no timer of its own.
516 if(!retransmitted_flight) {
517 return false;
518 }
519
520 // A genuine Finished follows a ChangeCipherSpec, so it is authenticated
521 // under a non-zero epoch. An unauthenticated epoch-zero record claiming to
522 // be one is spoofable off-path, and must not clear a ChangeCipherSpec we
523 // have legitimately saved to pair against the real Finished.
524 if(msg_type == Handshake_Type::Finished && epoch > 0 &&
525 reassemble_retransmitted_fragment(
526 fragment, fragment_length, fragment_offset, epoch, msg_type, msg_length, message_seq)) {
527 // A final-flight retransmission includes CCS, but UDP may deliver its
528 // records in either order. Wait until both have been observed.
529 if(m_retransmitted_ccs_epoch == epoch) {
530 m_retransmitted_ccs_epoch.reset();
531 return true;
532 }
533
534 // Only the matching pair means anything, so a half seen for some other
535 // epoch is stale. Leaving it set would keep this armed indefinitely for an
536 // epoch an attacker chose, since epoch-zero CCS records are unauthenticated.
537 m_retransmitted_ccs_epoch.reset();
538 m_retransmitted_finished_epoch = epoch;
539 }
540
541 return false;
542}
543
544void Datagram_Handshake_IO::add_record(const uint8_t record[],
545 size_t record_len,
546 Record_Type record_type,
547 uint64_t record_sequence,
548 bool retransmitted_flight) {
549 const uint16_t epoch = static_cast<uint16_t>(record_sequence >> 48);
550
551 // A record under a non-zero epoch authenticated at the record layer, so the
552 // peer is live and is who it claims to be. Restore the peer-cued replay
553 // budget: RFC 6347 4.2.4 requires the terminal-flight sender to answer a
554 // retransmit of the peer's last flight for as long as the association lasts,
555 // and the retained IO never sends a new flight to reset the count otherwise.
556 //
557 // Only once our handshake has finished, though. While it is still pending,
558 // forward progress already resets the count in send_under_epoch, so
559 // restoring it here as well would let a peer alternate a cheap out-of-window
560 // protected record with an epoch-zero cue to draw the pending flight without
561 // bound.
562 if(epoch > 0 && m_finished) {
563 m_peer_replay_count = 0;
564 }
565
566 if(record_type == Record_Type::ChangeCipherSpec) {
567 if(record_len != 1 || record[0] != 1) {
568 throw Decoding_Error("Invalid ChangeCipherSpec");
569 }
570
571 // TODO: check this is otherwise empty
572 m_ccs_epochs.insert(epoch);
573 if(retransmitted_flight) {
574 // Retransmitted final flights cross the epoch boundary: CCS is sent
575 // under the previous epoch and Finished under the newly activated one.
576 // Keep both observations because their datagrams may arrive reordered.
577 const uint16_t finished_epoch = static_cast<uint16_t>(epoch + 1);
578 if(m_retransmitted_finished_epoch == finished_epoch) {
579 m_retransmitted_finished_epoch.reset();
580 if(m_retransmit_terminal_flight) {
581 replay_last_flight_for_peer();
582 }
583 } else {
584 m_retransmitted_finished_epoch.reset();
585 m_retransmitted_ccs_epoch = finished_epoch;
586 }
587 }
588 return;
589 }
590
591 bool retransmit_response = false;
592
593 while(record_len > 0) {
594 if(record_len < DTLS_HANDSHAKE_HEADER_SIZE) {
595 return; // completely bogus? at least degenerate/weird
596 }
597
598 const Handshake_Type msg_type = static_cast<Handshake_Type>(record[0]);
599
600 verify_is_expected_wire_handshake_type(msg_type);
601
602 const size_t msg_len = load_be24(&record[1]);
603
604 if(m_max_handshake_msg_size > 0 && msg_len > m_max_handshake_msg_size) {
605 throw TLS_Exception(
606 Alert::HandshakeFailure,
607 Botan::fmt("Handshake message is {} bytes, policy maximum is {}", msg_len, m_max_handshake_msg_size));
608 }
609
610 const uint16_t message_seq = load_be<uint16_t>(&record[4], 0);
611 const size_t fragment_offset = load_be24(&record[6]);
612 const size_t fragment_length = load_be24(&record[9]);
613
614 const size_t total_size = DTLS_HANDSHAKE_HEADER_SIZE + fragment_length;
615
616 if(record_len < total_size) {
617 throw Decoding_Error("Bad lengths in DTLS header");
618 }
619
620 // Bound the out-of-order reassembly window.
621 constexpr uint16_t reassembly_window = 16;
622
623 if(message_seq >= m_in_message_seq && (message_seq - m_in_message_seq) < reassembly_window) {
624 // A wrapped counter would alias new messages onto long-delivered
625 // sequence numbers. No legitimate handshake gets here, so go quiet.
626 if(m_in_message_seq_wrapped) {
627 record += total_size;
628 record_len -= total_size;
629 continue;
630 }
631
632 // Epochs never decrease within a handshake, so a fragment carrying an
633 // older epoch belongs to an earlier handshake whose records were
634 // delayed into this one. Renegotiation restarts message_seq at zero,
635 // so without this such a record can occupy a slot the current
636 // handshake still needs.
637 if(epoch < m_last_delivered_epoch) {
638 record += total_size;
639 record_len -= total_size;
640 continue;
641 }
642
643 /*
644 RFC 6347 4.2.2 keeps message_seq across a retransmission but gives the
645 record a new sequence number, and a rehandshake restarts message_seq at
646 zero. A delayed Finished from the previous handshake therefore arrives
647 with a plausible sequence number and, before this handshake's own
648 ChangeCipherSpec, the same epoch as its pre-CCS records, so neither the
649 sequence nor the epoch floor tells it apart. It cannot be genuine
650 though: a Finished is sent under the epoch its own ChangeCipherSpec
651 installed, which is always above the one this handshake began in.
652
653 Left in, it takes the slot the real Finished needs, and a complete slot
654 is never replaced, so verification fails against the wrong transcript.
655 */
656 if(msg_type == Handshake_Type::Finished && epoch <= m_initial_epoch) {
657 record += total_size;
658 record_len -= total_size;
659 continue;
660 }
661
662 if(retransmitted_flight) {
663 if(fragment_length == 0) {
664 record += total_size;
665 record_len -= total_size;
666 continue;
667 }
668
669 throw TLS_Exception(Alert::UnexpectedMessage, "Unexpected new DTLS handshake message");
670 }
671
672 // An empty fragment for a non-empty message is garbage; drop it
673 // before it can create and charge a reassembly slot.
674 if(fragment_length == 0 && msg_len > 0) {
675 record += total_size;
676 record_len -= total_size;
677 continue;
678 }
679
680 // Reserve headroom for the message actually being waited on. Otherwise
681 // fragments for the fifteen slots beyond it can consume the whole
682 // budget, after which every fragment of the expected message is
683 // silently dropped and the handshake cannot proceed.
684 const size_t ceiling =
685 (message_seq == m_in_message_seq) ? m_max_pending_reassembly : m_max_pending_reassembly / 2;
686
687 auto [it, inserted] = m_messages.try_emplace(message_seq);
688
689 const bool accepted = charged_add_fragment(it->second,
690 ceiling,
691 &record[DTLS_HANDSHAKE_HEADER_SIZE],
692 fragment_length,
693 fragment_offset,
694 epoch,
695 msg_type,
696 msg_len);
697 if(!accepted && inserted) {
698 m_messages.erase(it);
699 }
700 } else if(message_seq < m_in_message_seq) {
701 retransmit_response |= process_previous_handshake_fragment(&record[DTLS_HANDSHAKE_HEADER_SIZE],
702 fragment_length,
703 fragment_offset,
704 epoch,
705 msg_type,
706 msg_len,
707 message_seq,
708 retransmitted_flight);
709 }
710 // else: beyond the reassembly window is not a retransmission of anything
711 // we have seen, so it must not be able to pull a flight replay out of
712 // us. Drop it silently: the sender has proven nothing at this point.
713
714 record += total_size;
715 record_len -= total_size;
716 }
717
718 if(retransmit_response && (!m_finished || m_retransmit_terminal_flight)) {
719 replay_last_flight_for_peer();
720 }
721}
722
723void Datagram_Handshake_IO::discard_stale_epoch_messages() {
724 for(auto i = m_messages.lower_bound(m_in_message_seq); i != m_messages.end();) {
725 if(i->second.epoch() < m_last_delivered_epoch) {
726 release_reassembly_bytes(i->second);
727 i = m_messages.erase(i);
728 } else {
729 ++i;
730 }
731 }
732}
733
734std::pair<Handshake_Type, std::vector<uint8_t>> Datagram_Handshake_IO::get_next_record(bool expecting_ccs,
735 size_t /*max_message_size*/) {
736 // Expecting a message means the last flight is concluded
737 if(!m_flights.rbegin()->empty()) {
738 m_flights.emplace_back();
739 m_flight_ccs.emplace_back();
740 }
741
742 if(expecting_ccs) {
743 // CCS is expected under the epoch the peer's handshake messages have
744 // been arriving on, and always follows at least one delivered message.
745 if(m_first_delivered_epoch.has_value() && m_ccs_epochs.contains(*m_first_delivered_epoch)) {
746 return std::make_pair(Handshake_Type::HandshakeCCS, std::vector<uint8_t>());
747 }
748 return std::make_pair(Handshake_Type::None, std::vector<uint8_t>());
749 }
750
751 if(m_retransmitted_client_hello.has_value() && m_retransmitted_client_hello->second.complete()) {
752 auto result = m_retransmitted_client_hello->second.message();
753 release_reassembly_bytes(m_retransmitted_client_hello->second);
754 m_retransmitted_client_hello.reset();
755 m_recreating_hello_verify_request = true;
756 return result;
757 }
758
759 auto i = m_messages.find(m_in_message_seq);
760
761 if(i == m_messages.end() || !i->second.complete()) {
762 return std::make_pair(Handshake_Type::None, std::vector<uint8_t>());
763 }
764
765 m_in_message_seq += 1;
766 if(m_in_message_seq == 0) {
767 m_in_message_seq_wrapped = true;
768 }
769
770 if(!m_first_delivered_epoch.has_value()) {
771 m_first_delivered_epoch = i->second.epoch();
772 }
773
774 auto result = i->second.message();
775
776 if(result.first == Handshake_Type::ClientHello) {
777 m_awaiting_cookie_client_hello = false;
778 }
779
780 const uint16_t delivered_epoch = i->second.epoch();
781
782 release_reassembly_bytes(i->second);
783 m_messages.erase(i);
784
785 if(delivered_epoch > m_last_delivered_epoch) {
786 m_last_delivered_epoch = delivered_epoch;
787 discard_stale_epoch_messages();
788 }
789
790 return result;
791}
792
793void Datagram_Handshake_IO::Handshake_Reassembly::add_fragment(const uint8_t fragment[],
794 size_t fragment_length,
795 size_t fragment_offset,
796 uint16_t epoch,
797 Handshake_Type msg_type,
798 size_t msg_length) {
799 if(m_msg_type == Handshake_Type::None) {
800 // First fragment for this message_seq
801 m_epoch = epoch;
802 m_msg_type = msg_type;
803 m_msg_length = msg_length;
804 m_message.resize(msg_length);
805 m_received_mask.assign(msg_length, 0);
806 } else {
807 if(complete()) {
808 // Ignore even if the header fields disagree: a stray or forged
809 // retransmission must not tear down the connection once the
810 // message has already been fully received.
811 return;
812 }
813
814 if(msg_type != m_msg_type || msg_length != m_msg_length || epoch != m_epoch) {
815 throw Decoding_Error("Inconsistent values in fragmented DTLS handshake header");
816 }
817 }
818
819 if(fragment_offset > m_msg_length) {
820 throw Decoding_Error("Fragment offset past end of message");
821 }
822
823 if(fragment_offset + fragment_length > m_msg_length) {
824 throw Decoding_Error("Fragment overlaps past end of message");
825 }
826
827 BOTAN_ASSERT_NOMSG(m_received_mask.size() == m_msg_length);
828
829 for(size_t i = 0; i != fragment_length; ++i) {
830 const size_t off = fragment_offset + i;
831 if(m_received_mask[off] != 0) {
832 // RFC 6347 4.2.3 permits overlapping retransmissions, but the
833 // overlapping bytes must agree.
834 if(m_message[off] != fragment[i]) {
835 throw Decoding_Error("Inconsistent overlapping DTLS handshake fragment");
836 }
837 } else {
838 m_message[off] = fragment[i];
839 m_received_mask[off] = 1;
840 ++m_bytes_received;
841 }
842 }
843}
844
845bool Datagram_Handshake_IO::Handshake_Reassembly::complete() const {
846 return (m_msg_type != Handshake_Type::None && m_bytes_received == m_msg_length);
847}
848
849std::pair<Handshake_Type, std::vector<uint8_t>> Datagram_Handshake_IO::Handshake_Reassembly::message() const {
850 if(!complete()) {
851 throw Internal_Error("Datagram_Handshake_IO - message not complete");
852 }
853
854 return std::make_pair(m_msg_type, m_message);
855}
856
857std::vector<uint8_t> Datagram_Handshake_IO::format_fragment(const uint8_t fragment[],
858 size_t frag_len,
859 uint32_t frag_offset,
860 uint32_t msg_len,
861 Handshake_Type type,
862 uint16_t msg_sequence) const {
863 std::vector<uint8_t> send_buf(12 + frag_len);
864
865 send_buf[0] = static_cast<uint8_t>(type);
866
867 store_be24(&send_buf[1], msg_len);
868
869 store_be(msg_sequence, &send_buf[4]);
870
871 store_be24(&send_buf[6], frag_offset);
872 store_be24(&send_buf[9], frag_len);
873
874 if(frag_len > 0) {
875 copy_mem(&send_buf[12], fragment, frag_len);
876 }
877
878 return send_buf;
879}
880
881std::vector<uint8_t> Datagram_Handshake_IO::format_w_seq(const std::vector<uint8_t>& msg,
882 Handshake_Type type,
883 uint16_t msg_sequence) const {
884 return format_fragment(msg.data(), msg.size(), 0, static_cast<uint32_t>(msg.size()), type, msg_sequence);
885}
886
887std::vector<uint8_t> Datagram_Handshake_IO::format(const std::vector<uint8_t>& msg, Handshake_Type type) const {
888 // Formats the message just delivered, so the guard is that one exists, not
889 // that the counter is non-zero. Those differ once m_in_message_seq wraps,
890 // where the subtraction wraps to 65535 of its own accord, which is the
891 // right sequence number for that message.
892 BOTAN_ASSERT_NOMSG(m_first_delivered_epoch.has_value());
893 return format_w_seq(msg, type, static_cast<uint16_t>(m_in_message_seq - 1));
894}
895
896std::vector<uint8_t> Datagram_Handshake_IO::send(const Handshake_Message& msg) {
897 return this->send_under_epoch(msg, m_seqs.current_write_epoch());
898}
899
900std::vector<uint8_t> Datagram_Handshake_IO::send_under_epoch(const Handshake_Message& msg, uint16_t epoch) {
901 const std::vector<uint8_t> msg_bits = msg.serialize();
902 const Handshake_Type msg_type = msg.type();
903
904 if(msg_type == Handshake_Type::HandshakeCCS) {
905 m_flight_ccs.rbegin()->emplace_back(m_flights.rbegin()->size(), epoch);
906 m_send_hs(epoch, Record_Type::ChangeCipherSpec, msg_bits);
907 return {}; // not included in handshake hashes
908 } else if(msg_type == Handshake_Type::HelloVerifyRequest) {
909 // RFC 6347 3.2.1 explicitly excludes HelloVerifyRequest from timeout
910 // retransmission. A repeated ClientHello recreates the response using
911 // the original message sequence number without retaining a flight.
912 const uint16_t msg_seq = m_recreating_hello_verify_request ? m_out_message_seq - 1 : m_out_message_seq++;
913 m_awaiting_cookie_client_hello = true;
914 m_recreating_hello_verify_request = false;
915 send_message(msg_seq, epoch, msg_type, msg_bits);
916 return {};
917 }
918
919 m_flights.rbegin()->push_back(m_out_message_seq);
920 m_flight_data.insert_or_assign(m_out_message_seq, Message_Info(epoch, msg_type, msg_bits));
921
922 m_out_message_seq += 1;
923 m_last_write = m_steady_clock_ms();
924 m_next_timeout = m_initial_timeout;
925 // Sending a new flight is forward progress: reset the give-up counter so the
926 // retransmission budget applies per flight, not across the whole handshake.
927 m_retransmit_count = 0;
928 m_peer_replay_count = 0;
929
930 return send_message(m_out_message_seq - 1, epoch, msg_type, msg_bits);
931}
932
933#if defined(BOTAN_HAS_TLS_DOWNGRADE_SUPPORT)
934
935std::vector<uint8_t> Datagram_Handshake_IO::start_with_client_hello_from_downgrade(
936 const Handshake_Message& client_hello) {
938 "Expected ClientHello message for DTLS downgrade");
939 BOTAN_STATE_CHECK(m_out_message_seq == 0);
941 return format_w_seq(client_hello.serialize(), client_hello.wire_type(), m_out_message_seq++);
942}
943
944#endif
945
946std::vector<uint8_t> Datagram_Handshake_IO::send_message(uint16_t msg_seq,
947 uint16_t epoch,
948 Handshake_Type msg_type,
949 const std::vector<uint8_t>& msg_bits) {
950 auto no_fragment = format_w_seq(msg_bits, msg_type, msg_seq);
951
952 /**
953 * Since CBC suites are no longer supported/allowed in DTLS, the largest
954 * possible ciphersuite overhead is 48 bytes, from NULL_WITH_SHA384. The AEAD
955 * suites add at most 24 bytes (8 byte explicit nonce plus 16 byte tag).
956 */
957 const size_t ciphersuite_overhead = (epoch > 0) ? 48 : 0;
958
959 if(no_fragment.size() + DTLS_HEADER_SIZE + ciphersuite_overhead <= m_mtu) {
960 // We think the entire final packet will fit into the MTU
961 m_send_hs(epoch, Record_Type::Handshake, no_fragment);
962 } else {
963 size_t frag_offset = 0;
964
965 constexpr size_t DTLS_HANDSHAKE_OVERHEAD = DTLS_HEADER_SIZE + DTLS_HANDSHAKE_HEADER_SIZE;
966
967 if(m_mtu <= (DTLS_HANDSHAKE_OVERHEAD + ciphersuite_overhead)) {
968 throw Invalid_Argument("DTLS MTU is too small to send headers");
969 }
970
971 const size_t max_rec_size = m_mtu - (DTLS_HANDSHAKE_OVERHEAD + ciphersuite_overhead);
972
973 while(frag_offset != msg_bits.size()) {
974 const size_t frag_len = std::min<size_t>(msg_bits.size() - frag_offset, max_rec_size);
975
976 const std::vector<uint8_t> frag = format_fragment(&msg_bits[frag_offset],
977 frag_len,
978 static_cast<uint32_t>(frag_offset),
979 static_cast<uint32_t>(msg_bits.size()),
980 msg_type,
981 msg_seq);
982
983 m_send_hs(epoch, Record_Type::Handshake, frag);
984
985 frag_offset += frag_len;
986 }
987 }
988
989 return no_fragment;
990}
991
992} // namespace Botan::TLS
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:62
virtual uint16_t current_write_epoch() const =0
std::function< uint64_t()> steady_clock_fn
std::function< void(uint16_t, Record_Type, const std::vector< uint8_t > &)> writer_fn
std::vector< uint8_t > send_under_epoch(const Handshake_Message &msg, uint16_t epoch) override
std::optional< std::chrono::milliseconds > next_retransmission_timeout() const override
std::pair< Handshake_Type, std::vector< uint8_t > > get_next_record(bool expecting_ccs, size_t max_message_size) override
void add_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number) override
std::vector< uint8_t > format(const std::vector< uint8_t > &handshake_msg, Handshake_Type handshake_type) const override
Protocol_Version initial_record_version() const override
void finalize_handshake(bool retransmit_terminal_flight)
void add_retransmitted_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number)
std::vector< uint8_t > send(const Handshake_Message &msg) override
Datagram_Handshake_IO(writer_fn writer, steady_clock_fn clock_ms, class Connection_Sequence_Numbers &seq, uint16_t mtu, uint64_t initial_timeout_ms, uint64_t max_timeout_ms, std::optional< size_t > max_retransmissions, size_t max_handshake_msg_size, uint16_t initial_epoch=0)
virtual Handshake_Type type() const =0
virtual std::vector< uint8_t > serialize() const =0
virtual Handshake_Type wire_type() const
std::vector< uint8_t > send_under_epoch(const Handshake_Message &msg, uint16_t epoch) override
std::vector< uint8_t > format(const std::vector< uint8_t > &handshake_msg, Handshake_Type handshake_type) const override
Protocol_Version initial_record_version() const override
std::vector< uint8_t > send(const Handshake_Message &msg) override
std::pair< Handshake_Type, std::vector< uint8_t > > get_next_record(bool expecting_ccs, size_t max_message_size) override
void add_record(const uint8_t record[], size_t record_len, Record_Type type, uint64_t sequence_number) override
@ DTLS_HEADER_SIZE
Definition tls_magic.h:31
constexpr uint8_t get_byte(T input)
Definition loadstor.h:79
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:144
constexpr uint32_t make_uint32(uint8_t i0, uint8_t i1, uint8_t i2, uint8_t i3)
Definition loadstor.h:104
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:745
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:504