Botan 3.0.0
Crypto and TLS for C&
tls_record.cpp
Go to the documentation of this file.
1/*
2* TLS Record Handling
3* (C) 2012,2013,2014,2015,2016,2019 Jack Lloyd
4* 2016 Juraj Somorovsky
5* 2016 Matthias Gierlings
6*
7* Botan is released under the Simplified BSD License (see license.txt)
8*/
9
10#include <botan/internal/tls_record.h>
11#include <botan/tls_ciphersuite.h>
12#include <botan/tls_callbacks.h>
13#include <botan/tls_exceptn.h>
14#include <botan/internal/loadstor.h>
15#include <botan/internal/tls_seq_numbers.h>
16#include <botan/internal/tls_session_key.h>
17#include <botan/internal/ct_utils.h>
18#include <botan/rng.h>
19#include <sstream>
20
21#if defined(BOTAN_HAS_TLS_CBC)
22 #include <botan/internal/tls_cbc.h>
23#endif
24
25namespace Botan::TLS {
26
28 Connection_Side side,
29 bool our_side,
30 const Ciphersuite& suite,
31 const Session_Keys& keys,
32 bool uses_encrypt_then_mac)
33 {
34 m_nonce_format = suite.nonce_format();
35 m_nonce_bytes_from_record = suite.nonce_bytes_from_record(version);
36 m_nonce_bytes_from_handshake = suite.nonce_bytes_from_handshake();
37
38 const secure_vector<uint8_t>& aead_key = keys.aead_key(side);
39 m_nonce = keys.nonce(side);
40
41 BOTAN_ASSERT_NOMSG(m_nonce.size() == m_nonce_bytes_from_handshake);
42
44 {
45#if defined(BOTAN_HAS_TLS_CBC)
46 // legacy CBC+HMAC mode
47 auto mac = MessageAuthenticationCode::create_or_throw("HMAC(" + suite.mac_algo() + ")");
48 auto cipher = BlockCipher::create_or_throw(suite.cipher_algo());
49
50 if(our_side)
51 {
52 m_aead = std::make_unique<TLS_CBC_HMAC_AEAD_Encryption>(
53 std::move(cipher),
54 std::move(mac),
55 suite.cipher_keylen(),
56 suite.mac_keylen(),
57 version,
58 uses_encrypt_then_mac);
59 }
60 else
61 {
62 m_aead = std::make_unique<TLS_CBC_HMAC_AEAD_Decryption>(
63 std::move(cipher),
64 std::move(mac),
65 suite.cipher_keylen(),
66 suite.mac_keylen(),
67 version,
68 uses_encrypt_then_mac);
69 }
70
71#else
72 BOTAN_UNUSED(uses_encrypt_then_mac);
73 throw Internal_Error("Negotiated disabled TLS CBC+HMAC ciphersuite");
74#endif
75 }
76 else
77 {
79 }
80
81 m_aead->set_key(aead_key);
82 }
83
84std::vector<uint8_t> Connection_Cipher_State::aead_nonce(uint64_t seq, RandomNumberGenerator& rng)
85 {
86 switch(m_nonce_format)
87 {
89 {
90 if(!m_nonce.empty())
91 {
92 std::vector<uint8_t> nonce;
93 nonce.swap(m_nonce);
94 return nonce;
95 }
96 std::vector<uint8_t> nonce(nonce_bytes_from_record());
97 rng.randomize(nonce.data(), nonce.size());
98 return nonce;
99 }
101 {
102 std::vector<uint8_t> nonce(12);
103 store_be(seq, nonce.data() + 4);
104 xor_buf(nonce, m_nonce.data(), m_nonce.size());
105 return nonce;
106 }
108 {
109 BOTAN_ASSERT_NOMSG(m_nonce.size() == 4);
110 std::vector<uint8_t> nonce(12);
111 copy_mem(&nonce[0], m_nonce.data(), 4);
112 store_be(seq, &nonce[nonce_bytes_from_handshake()]);
113 return nonce;
114 }
115 }
116
117 throw Invalid_State("Unknown nonce format specified");
118 }
119
120std::vector<uint8_t>
121Connection_Cipher_State::aead_nonce(const uint8_t record[], size_t record_len, uint64_t seq)
122 {
123 switch(m_nonce_format)
124 {
126 {
127 if(nonce_bytes_from_record() == 0 && !m_nonce.empty())
128 {
129 std::vector<uint8_t> nonce;
130 nonce.swap(m_nonce);
131 return nonce;
132 }
133 if(record_len < nonce_bytes_from_record())
134 throw Decoding_Error("Invalid CBC packet too short to be valid");
135 std::vector<uint8_t> nonce(record, record + nonce_bytes_from_record());
136 return nonce;
137 }
139 {
140 std::vector<uint8_t> nonce(12);
141 store_be(seq, nonce.data() + 4);
142 xor_buf(nonce, m_nonce.data(), m_nonce.size());
143 return nonce;
144 }
146 {
147 BOTAN_ASSERT_NOMSG(m_nonce.size() == 4);
148 if(record_len < nonce_bytes_from_record())
149 throw Decoding_Error("Invalid AEAD packet too short to be valid");
150 std::vector<uint8_t> nonce(12);
151 copy_mem(&nonce[0], m_nonce.data(), 4);
153 return nonce;
154 }
155 }
156
157 throw Invalid_State("Unknown nonce format specified");
158 }
159
160std::vector<uint8_t>
162 Record_Type msg_type,
163 Protocol_Version version,
164 uint16_t msg_length)
165 {
166 std::vector<uint8_t> ad(13);
167
168 store_be(msg_sequence, &ad[0]);
169 ad[8] = static_cast<uint8_t>(msg_type);
170 ad[9] = version.major_version();
171 ad[10] = version.minor_version();
172 ad[11] = get_byte<0>(msg_length);
173 ad[12] = get_byte<1>(msg_length);
174
175 return ad;
176 }
177
178namespace {
179
180inline void append_u16_len(secure_vector<uint8_t>& output, size_t len_field)
181 {
182 const uint16_t len16 = static_cast<uint16_t>(len_field);
183 BOTAN_ASSERT_EQUAL(len_field, len16, "No truncation");
184 output.push_back(get_byte<0>(len16));
185 output.push_back(get_byte<1>(len16));
186 }
187
188void write_record_header(secure_vector<uint8_t>& output,
189 Record_Type record_type,
190 Protocol_Version version,
191 uint64_t record_sequence)
192 {
193 output.clear();
194
195 output.push_back(static_cast<uint8_t>(record_type));
196 output.push_back(version.major_version());
197 output.push_back(version.minor_version());
198
199 if(version.is_datagram_protocol())
200 {
201 for(size_t i = 0; i != 8; ++i)
202 output.push_back(get_byte_var(i, record_sequence));
203 }
204 }
205
206}
207
209 Record_Type record_type,
210 Protocol_Version version,
211 uint64_t record_sequence,
212 const uint8_t* message,
213 size_t message_len)
214 {
215 if(record_type == Record_Type::ApplicationData)
216 throw Internal_Error("Writing an unencrypted TLS application data record");
217 write_record_header(output, record_type, version, record_sequence);
218 append_u16_len(output, message_len);
219 output.insert(output.end(), message, message + message_len);
220 }
221
223 Record_Type record_type,
224 Protocol_Version version,
225 uint64_t record_sequence,
226 const uint8_t* message,
227 size_t message_len,
230 {
231 write_record_header(output, record_type, version, record_sequence);
232
233 AEAD_Mode& aead = cs.aead();
234 std::vector<uint8_t> aad = cs.format_ad(record_sequence, record_type, version, static_cast<uint16_t>(message_len));
235
236 const size_t ctext_size = aead.output_length(message_len);
237
238 const size_t rec_size = ctext_size + cs.nonce_bytes_from_record();
239
240 aead.set_associated_data(aad);
241
242 const std::vector<uint8_t> nonce = cs.aead_nonce(record_sequence, rng);
243
244 append_u16_len(output, rec_size);
245
246 if(cs.nonce_bytes_from_record() > 0)
247 {
249 output += nonce;
250 else
251 output += std::make_pair(&nonce[cs.nonce_bytes_from_handshake()], cs.nonce_bytes_from_record());
252 }
253
254 const size_t header_size = output.size();
255 output += std::make_pair(message, message_len);
256
257 aead.start(nonce);
258 aead.finish(output, header_size);
259
260 BOTAN_ASSERT(output.size() < MAX_CIPHERTEXT_SIZE,
261 "Produced ciphertext larger than protocol allows");
262 }
263
264namespace {
265
266size_t fill_buffer_to(secure_vector<uint8_t>& readbuf,
267 const uint8_t*& input,
268 size_t& input_size,
269 size_t& input_consumed,
270 size_t desired)
271 {
272 if(readbuf.size() >= desired)
273 return 0; // already have it
274
275 const size_t taken = std::min(input_size, desired - readbuf.size());
276
277 readbuf.insert(readbuf.end(), input, input + taken);
278 input_consumed += taken;
279 input_size -= taken;
280 input += taken;
281
282 return (desired - readbuf.size()); // how many bytes do we still need?
283 }
284
285void decrypt_record(secure_vector<uint8_t>& output,
286 uint8_t record_contents[], size_t record_len,
287 uint64_t record_sequence,
288 Protocol_Version record_version,
289 Record_Type record_type,
290 Connection_Cipher_State& cs)
291 {
292 AEAD_Mode& aead = cs.aead();
293
294 const std::vector<uint8_t> nonce = cs.aead_nonce(record_contents, record_len, record_sequence);
295 const uint8_t* msg = &record_contents[cs.nonce_bytes_from_record()];
296 const size_t msg_length = record_len - cs.nonce_bytes_from_record();
297
298 /*
299 * This early rejection is based just on public information (length of the
300 * encrypted packet) and so does not leak any information. We used to use
301 * decode_error here which really is more appropriate, but that confuses some
302 * tools which are attempting automated detection of padding oracles,
303 * including older versions of TLS-Attacker.
304 */
305 if(msg_length < aead.minimum_final_size())
306 throw TLS_Exception(Alert::BadRecordMac, "AEAD packet is shorter than the tag");
307
308 const size_t ptext_size = aead.output_length(msg_length);
309
310 aead.set_associated_data(
311 cs.format_ad(record_sequence,
312 record_type,
313 record_version,
314 static_cast<uint16_t>(ptext_size))
315 );
316
317 aead.start(nonce);
318
319 output.assign(msg, msg + msg_length);
320 aead.finish(output, 0);
321 }
322
323Record_Header read_tls_record(secure_vector<uint8_t>& readbuf,
324 const uint8_t input[],
325 size_t input_len,
326 size_t& consumed,
327 secure_vector<uint8_t>& recbuf,
328 Connection_Sequence_Numbers* sequence_numbers,
329 const get_cipherstate_fn& get_cipherstate)
330 {
331 if(readbuf.size() < TLS_HEADER_SIZE) // header incomplete?
332 {
333 if(size_t needed = fill_buffer_to(readbuf, input, input_len, consumed, TLS_HEADER_SIZE))
334 {
335 return Record_Header(needed);
336 }
337
338 BOTAN_ASSERT_EQUAL(readbuf.size(), TLS_HEADER_SIZE, "Have an entire header");
339 }
340
341 /*
342 Verify that the record type and record version are within some expected
343 range, so we can quickly reject totally invalid packets.
344
345 The version check is a little hacky but given how TLS 1.3 versioning works
346 this is probably safe
347
348 - The first byte is the record version which in TLS 1.2 is always in [20..23)
349 - The second byte is the TLS major version which is effectively fossilized at 3
350 - The third byte is the TLS minor version which (due to TLS 1.3 versioning changes)
351 will never be more than 3 (signifying TLS 1.2)
352 */
353 const bool bad_record_type = readbuf[0] < 20 || readbuf[0] > 23;
354 const bool bad_record_version = readbuf[1] != 3 || readbuf[2] >= 4;
355
356 if(bad_record_type || bad_record_version)
357 {
358 // We know we read up to at least the 5 byte TLS header
359 const std::string first5 = std::string(reinterpret_cast<const char*>(readbuf.data()), 5);
360
361 if(first5 == "GET /" ||
362 first5 == "PUT /" ||
363 first5 == "POST " ||
364 first5 == "HEAD ")
365 {
366 throw TLS_Exception(Alert::ProtocolVersion,
367 "Client sent plaintext HTTP request instead of TLS handshake");
368 }
369
370 if(first5 == "CONNE")
371 {
372 throw TLS_Exception(Alert::ProtocolVersion,
373 "Client sent plaintext HTTP proxy CONNECT request instead of TLS handshake");
374 }
375
376
377 std::ostringstream oss;
378 oss << "TLS record ";
379 if(bad_record_type)
380 oss << "type";
381 else
382 oss << "version";
383 oss << " had unexpected value";
384
385 throw TLS_Exception(Alert::ProtocolVersion, oss.str());
386 }
387
388 const Protocol_Version version(readbuf[1], readbuf[2]);
389
390 if(version.is_datagram_protocol())
391 throw TLS_Exception(Alert::ProtocolVersion,
392 "Expected TLS but got a record with DTLS version");
393
394 const size_t record_size = make_uint16(readbuf[TLS_HEADER_SIZE-2],
395 readbuf[TLS_HEADER_SIZE-1]);
396
397 if(record_size > MAX_CIPHERTEXT_SIZE)
398 throw TLS_Exception(Alert::RecordOverflow,
399 "Received a record that exceeds maximum size");
400
401 if(record_size == 0)
402 throw TLS_Exception(Alert::DecodeError,
403 "Received a completely empty record");
404
405 if(size_t needed = fill_buffer_to(readbuf, input, input_len, consumed, TLS_HEADER_SIZE + record_size))
406 {
407 return Record_Header(needed);
408 }
409
410 BOTAN_ASSERT_EQUAL(static_cast<size_t>(TLS_HEADER_SIZE) + record_size,
411 readbuf.size(),
412 "Have the full record");
413
414 const Record_Type type = static_cast<Record_Type>(readbuf[0]);
415
416 uint16_t epoch = 0;
417
418 uint64_t sequence = 0;
419 if(sequence_numbers)
420 {
421 sequence = sequence_numbers->next_read_sequence();
422 epoch = sequence_numbers->current_read_epoch();
423 }
424 else
425 {
426 // server initial handshake case
427 epoch = 0;
428 }
429
430 if(epoch == 0) // Unencrypted initial handshake
431 {
432 recbuf.assign(readbuf.begin() + TLS_HEADER_SIZE, readbuf.begin() + TLS_HEADER_SIZE + record_size);
433 readbuf.clear();
434 return Record_Header(sequence, version, type);
435 }
436
437 // Otherwise, decrypt, check MAC, return plaintext
438 auto cs = get_cipherstate(epoch);
439
440 BOTAN_ASSERT(cs, "Have cipherstate for this epoch");
441
442 decrypt_record(recbuf,
443 &readbuf[TLS_HEADER_SIZE],
444 record_size,
445 sequence,
446 version,
447 type,
448 *cs);
449
450 if(sequence_numbers)
451 sequence_numbers->read_accept(sequence);
452
453 readbuf.clear();
454 return Record_Header(sequence, version, type);
455 }
456
457Record_Header read_dtls_record(secure_vector<uint8_t>& readbuf,
458 const uint8_t input[],
459 size_t input_len,
460 size_t& consumed,
461 secure_vector<uint8_t>& recbuf,
462 Connection_Sequence_Numbers* sequence_numbers,
463 const get_cipherstate_fn& get_cipherstate,
464 bool allow_epoch0_restart)
465 {
466 if(readbuf.size() < DTLS_HEADER_SIZE) // header incomplete?
467 {
468 if(fill_buffer_to(readbuf, input, input_len, consumed, DTLS_HEADER_SIZE))
469 {
470 readbuf.clear();
471 return Record_Header(0);
472 }
473
474 BOTAN_ASSERT_EQUAL(readbuf.size(), DTLS_HEADER_SIZE, "Have an entire header");
475 }
476
477 const Protocol_Version version(readbuf[1], readbuf[2]);
478
479 if(version.is_datagram_protocol() == false)
480 {
481 readbuf.clear();
482 return Record_Header(0);
483 }
484
485 const size_t record_size = make_uint16(readbuf[DTLS_HEADER_SIZE-2],
486 readbuf[DTLS_HEADER_SIZE-1]);
487
488 if(record_size > MAX_CIPHERTEXT_SIZE)
489 {
490 // Too large to be valid, ignore it
491 readbuf.clear();
492 return Record_Header(0);
493 }
494
495 if(fill_buffer_to(readbuf, input, input_len, consumed, DTLS_HEADER_SIZE + record_size))
496 {
497 // Truncated packet?
498 readbuf.clear();
499 return Record_Header(0);
500 }
501
502 BOTAN_ASSERT_EQUAL(static_cast<size_t>(DTLS_HEADER_SIZE) + record_size, readbuf.size(),
503 "Have the full record");
504
505 const Record_Type type = static_cast<Record_Type>(readbuf[0]);
506
507 const uint64_t sequence = load_be<uint64_t>(&readbuf[3], 0);
508 const uint16_t epoch = (sequence >> 48);
509
510 const bool already_seen = sequence_numbers && sequence_numbers->already_seen(sequence);
511
512 if(already_seen && !(epoch == 0 && allow_epoch0_restart))
513 {
514 readbuf.clear();
515 return Record_Header(0);
516 }
517
518 if(epoch == 0) // Unencrypted initial handshake
519 {
520 recbuf.assign(readbuf.begin() + DTLS_HEADER_SIZE, readbuf.begin() + DTLS_HEADER_SIZE + record_size);
521 readbuf.clear();
522 if(sequence_numbers)
523 sequence_numbers->read_accept(sequence);
524 return Record_Header(sequence, version, type);
525 }
526
527 try
528 {
529 // Otherwise, decrypt, check MAC, return plaintext
530 auto cs = get_cipherstate(epoch);
531
532 BOTAN_ASSERT(cs, "Have cipherstate for this epoch");
533
534 decrypt_record(recbuf,
535 &readbuf[DTLS_HEADER_SIZE],
536 record_size,
537 sequence,
538 version,
539 type,
540 *cs);
541 }
542 catch(std::exception&)
543 {
544 readbuf.clear();
545 return Record_Header(0);
546 }
547
548 if(sequence_numbers)
549 sequence_numbers->read_accept(sequence);
550
551 readbuf.clear();
552 return Record_Header(sequence, version, type);
553 }
554
555}
556
557Record_Header read_record(bool is_datagram,
558 secure_vector<uint8_t>& readbuf,
559 const uint8_t input[],
560 size_t input_len,
561 size_t& consumed,
563 Connection_Sequence_Numbers* sequence_numbers,
564 const get_cipherstate_fn& get_cipherstate,
565 bool allow_epoch0_restart)
566 {
567 if(is_datagram)
568 return read_dtls_record(readbuf, input, input_len, consumed,
569 recbuf, sequence_numbers, get_cipherstate, allow_epoch0_restart);
570 else
571 return read_tls_record(readbuf, input, input_len, consumed,
572 recbuf, sequence_numbers, get_cipherstate);
573 }
574
575}
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:67
#define BOTAN_UNUSED(...)
Definition: assert.h:141
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:80
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:54
void set_associated_data(std::span< const uint8_t > ad)
Definition: aead.h:60
static std::unique_ptr< AEAD_Mode > create_or_throw(std::string_view algo, Cipher_Dir direction, std::string_view provider="")
Definition: aead.cpp:42
static std::unique_ptr< BlockCipher > create_or_throw(std::string_view algo_spec, std::string_view provider="")
void start(std::span< const uint8_t > nonce)
Definition: cipher_mode.h:90
void finish(secure_vector< uint8_t > &final_block, size_t offset=0)
Definition: cipher_mode.h:158
virtual size_t output_length(size_t input_length) const =0
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition: mac.cpp:134
void randomize(std::span< uint8_t > output)
Definition: rng.h:53
size_t nonce_bytes_from_record(Protocol_Version version) const
Nonce_Format nonce_format() const
size_t cipher_keylen() const
size_t nonce_bytes_from_handshake() const
std::string mac_algo() const
std::string cipher_algo() const
size_t nonce_bytes_from_record() const
Definition: tls_record.h:63
Nonce_Format nonce_format() const
Definition: tls_record.h:65
size_t nonce_bytes_from_handshake() const
Definition: tls_record.h:62
Connection_Cipher_State(Protocol_Version version, Connection_Side which_side, bool is_our_side, const Ciphersuite &suite, const Session_Keys &keys, bool uses_encrypt_then_mac)
Definition: tls_record.cpp:27
std::vector< uint8_t > aead_nonce(uint64_t seq, RandomNumberGenerator &rng)
Definition: tls_record.cpp:84
std::vector< uint8_t > format_ad(uint64_t seq, Record_Type type, Protocol_Version version, uint16_t ptext_length)
Definition: tls_record.cpp:161
uint8_t major_version() const
Definition: tls_version.h:86
uint8_t minor_version() const
Definition: tls_version.h:91
const std::vector< uint8_t > & nonce(Connection_Side side) const
const secure_vector< uint8_t > & aead_key(Connection_Side side) const
Record_Header read_record(bool is_datagram, secure_vector< uint8_t > &readbuf, const uint8_t input[], size_t input_len, size_t &consumed, secure_vector< uint8_t > &recbuf, Connection_Sequence_Numbers *sequence_numbers, const get_cipherstate_fn &get_cipherstate, bool allow_epoch0_restart)
Definition: tls_record.cpp:557
@ MAX_CIPHERTEXT_SIZE
Definition: tls_magic.h:35
@ TLS_HEADER_SIZE
Definition: tls_magic.h:27
@ DTLS_HEADER_SIZE
Definition: tls_magic.h:28
void write_unencrypted_record(secure_vector< uint8_t > &output, Record_Type record_type, Protocol_Version version, uint64_t record_sequence, const uint8_t *message, size_t message_len)
Definition: tls_record.cpp:208
std::function< std::shared_ptr< Connection_Cipher_State >(uint16_t)> get_cipherstate_fn
Definition: tls_record.h:164
void write_record(secure_vector< uint8_t > &output, Record_Type record_type, Protocol_Version version, uint64_t record_sequence, const uint8_t *message, size_t message_len, Connection_Cipher_State &cs, RandomNumberGenerator &rng)
Definition: tls_record.cpp:222
constexpr uint64_t load_be< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:228
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:126
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:255
constexpr void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:449
constexpr uint8_t get_byte_var(size_t byte_num, T input)
Definition: loadstor.h:39
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:64
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)
Definition: loadstor.h:65