Botan  2.15.0
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  const Protocol_Version version(readbuf[1], readbuf[2]);
344 
345  if(version.is_datagram_protocol())
346  throw TLS_Exception(Alert::PROTOCOL_VERSION,
347  "Expected TLS but got a record with DTLS version");
348 
349  const size_t record_size = make_uint16(readbuf[TLS_HEADER_SIZE-2],
350  readbuf[TLS_HEADER_SIZE-1]);
351 
352  if(record_size > MAX_CIPHERTEXT_SIZE)
353  throw TLS_Exception(Alert::RECORD_OVERFLOW,
354  "Received a record that exceeds maximum size");
355 
356  if(record_size == 0)
357  throw TLS_Exception(Alert::DECODE_ERROR,
358  "Received a completely empty record");
359 
360  if(size_t needed = fill_buffer_to(readbuf, input, input_len, consumed, TLS_HEADER_SIZE + record_size))
361  {
362  return Record_Header(needed);
363  }
364 
365  BOTAN_ASSERT_EQUAL(static_cast<size_t>(TLS_HEADER_SIZE) + record_size,
366  readbuf.size(),
367  "Have the full record");
368 
369  const Record_Type type = static_cast<Record_Type>(readbuf[0]);
370 
371  uint16_t epoch = 0;
372 
373  uint64_t sequence = 0;
374  if(sequence_numbers)
375  {
376  sequence = sequence_numbers->next_read_sequence();
377  epoch = sequence_numbers->current_read_epoch();
378  }
379  else
380  {
381  // server initial handshake case
382  epoch = 0;
383  }
384 
385  if(epoch == 0) // Unencrypted initial handshake
386  {
387  recbuf.assign(readbuf.begin() + TLS_HEADER_SIZE, readbuf.begin() + TLS_HEADER_SIZE + record_size);
388  readbuf.clear();
389  return Record_Header(sequence, version, type);
390  }
391 
392  // Otherwise, decrypt, check MAC, return plaintext
393  auto cs = get_cipherstate(epoch);
394 
395  BOTAN_ASSERT(cs, "Have cipherstate for this epoch");
396 
397  decrypt_record(recbuf,
398  &readbuf[TLS_HEADER_SIZE],
399  record_size,
400  sequence,
401  version,
402  type,
403  *cs);
404 
405  if(sequence_numbers)
406  sequence_numbers->read_accept(sequence);
407 
408  readbuf.clear();
409  return Record_Header(sequence, version, type);
410  }
411 
412 Record_Header read_dtls_record(secure_vector<uint8_t>& readbuf,
413  const uint8_t input[],
414  size_t input_len,
415  size_t& consumed,
416  secure_vector<uint8_t>& recbuf,
417  Connection_Sequence_Numbers* sequence_numbers,
418  get_cipherstate_fn get_cipherstate,
419  bool allow_epoch0_restart)
420  {
421  if(readbuf.size() < DTLS_HEADER_SIZE) // header incomplete?
422  {
423  if(fill_buffer_to(readbuf, input, input_len, consumed, DTLS_HEADER_SIZE))
424  {
425  readbuf.clear();
426  return Record_Header(0);
427  }
428 
429  BOTAN_ASSERT_EQUAL(readbuf.size(), DTLS_HEADER_SIZE, "Have an entire header");
430  }
431 
432  const Protocol_Version version(readbuf[1], readbuf[2]);
433 
434  if(version.is_datagram_protocol() == false)
435  {
436  readbuf.clear();
437  return Record_Header(0);
438  }
439 
440  const size_t record_size = make_uint16(readbuf[DTLS_HEADER_SIZE-2],
441  readbuf[DTLS_HEADER_SIZE-1]);
442 
443  if(record_size > MAX_CIPHERTEXT_SIZE)
444  {
445  // Too large to be valid, ignore it
446  readbuf.clear();
447  return Record_Header(0);
448  }
449 
450  if(fill_buffer_to(readbuf, input, input_len, consumed, DTLS_HEADER_SIZE + record_size))
451  {
452  // Truncated packet?
453  readbuf.clear();
454  return Record_Header(0);
455  }
456 
457  BOTAN_ASSERT_EQUAL(static_cast<size_t>(DTLS_HEADER_SIZE) + record_size, readbuf.size(),
458  "Have the full record");
459 
460  const Record_Type type = static_cast<Record_Type>(readbuf[0]);
461 
462  const uint64_t sequence = load_be<uint64_t>(&readbuf[3], 0);
463  const uint16_t epoch = (sequence >> 48);
464 
465  const bool already_seen = sequence_numbers && sequence_numbers->already_seen(sequence);
466 
467  if(already_seen && !(epoch == 0 && allow_epoch0_restart))
468  {
469  readbuf.clear();
470  return Record_Header(0);
471  }
472 
473  if(epoch == 0) // Unencrypted initial handshake
474  {
475  recbuf.assign(readbuf.begin() + DTLS_HEADER_SIZE, readbuf.begin() + DTLS_HEADER_SIZE + record_size);
476  readbuf.clear();
477  if(sequence_numbers)
478  sequence_numbers->read_accept(sequence);
479  return Record_Header(sequence, version, type);
480  }
481 
482  try
483  {
484  // Otherwise, decrypt, check MAC, return plaintext
485  auto cs = get_cipherstate(epoch);
486 
487  BOTAN_ASSERT(cs, "Have cipherstate for this epoch");
488 
489  decrypt_record(recbuf,
490  &readbuf[DTLS_HEADER_SIZE],
491  record_size,
492  sequence,
493  version,
494  type,
495  *cs);
496  }
497  catch(std::exception&)
498  {
499  readbuf.clear();
500  return Record_Header(0);
501  }
502 
503  if(sequence_numbers)
504  sequence_numbers->read_accept(sequence);
505 
506  readbuf.clear();
507  return Record_Header(sequence, version, type);
508  }
509 
510 }
511 
512 Record_Header read_record(bool is_datagram,
513  secure_vector<uint8_t>& readbuf,
514  const uint8_t input[],
515  size_t input_len,
516  size_t& consumed,
517  secure_vector<uint8_t>& recbuf,
518  Connection_Sequence_Numbers* sequence_numbers,
519  get_cipherstate_fn get_cipherstate,
520  bool allow_epoch0_restart)
521  {
522  if(is_datagram)
523  return read_dtls_record(readbuf, input, input_len, consumed,
524  recbuf, sequence_numbers, get_cipherstate, allow_epoch0_restart);
525  else
526  return read_tls_record(readbuf, input, input_len, consumed,
527  recbuf, sequence_numbers, get_cipherstate);
528  }
529 
530 }
531 
532 }
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:512
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:1142
#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:95
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:233
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:42
virtual void finish(secure_vector< uint8_t > &final_block, size_t offset=0)=0