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