Botan  2.18.1
Crypto and TLS for C++11
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 
24 namespace Botan {
25 
26 namespace 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 
86 std::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 
122 std::vector<uint8_t>
123 Connection_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 
162 std::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 
180 namespace {
181 
182 inline 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 
190 void 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 
266 namespace {
267 
268 size_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 
287 void 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 
325 Record_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 
414 Record_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 
514 Record_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,
519  secure_vector<uint8_t>& recbuf,
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 }
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)
Definition: tls_record.cpp:514
std::string mac_algo() const
size_t nonce_bytes_from_record(Protocol_Version version) const
size_t nonce_bytes_from_handshake() const
Definition: tls_record.h:59
std::vector< uint8_t > aead_nonce(uint64_t seq, RandomNumberGenerator &rng)
Definition: tls_record.cpp:86
Nonce_Format nonce_format() const
Definition: tls_record.h:62
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:438
uint8_t minor_version() const
Definition: tls_version.h:84
virtual void randomize(uint8_t output[], size_t length)=0
std::function< std::shared_ptr< Connection_Cipher_State >uint16_t)> get_cipherstate_fn
Definition: tls_record.h:168
constexpr uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:41
Definition: bigint.h:1143
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:68
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:28
void set_ad(const std::vector< uint8_t, Alloc > &ad)
Definition: aead.h:121
MechanismType type
void start(const std::vector< uint8_t, Alloc > &nonce)
Definition: cipher_mode.h:69
size_t nonce_bytes_from_record() const
Definition: tls_record.h:60
Nonce_Format nonce_format() const
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
uint64_t load_be< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:217
size_t cipher_keylen() const
virtual size_t output_length(size_t input_length) const =0
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:262
std::vector< uint8_t > format_ad(uint64_t seq, uint8_t type, Protocol_Version version, uint16_t ptext_length)
Definition: tls_record.cpp:163
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:81
size_t nonce_bytes_from_handshake() const
const secure_vector< uint8_t > & aead_key(Connection_Side side) const
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:133
Definition: alg_id.cpp:13
#define BOTAN_UNUSED(...)
Definition: assert.h:142
static std::unique_ptr< BlockCipher > create_or_throw(const std::string &algo_spec, const std::string &provider="")
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)
Definition: tls_record.cpp:224
uint8_t major_version() const
Definition: tls_version.h:79
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(const std::string &algo_spec, const std::string &provider="")
Definition: mac.cpp:141
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
std::string cipher_algo() const
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)
Definition: loadstor.h:54
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)
Definition: tls_record.cpp:210
const std::vector< uint8_t > & nonce(Connection_Side side) const
static std::unique_ptr< AEAD_Mode > create_or_throw(const std::string &algo, Cipher_Dir direction, const std::string &provider="")
Definition: aead.cpp:50
virtual void finish(secure_vector< uint8_t > &final_block, size_t offset=0)=0