Botan  2.13.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 }
191 
193  uint8_t record_type,
194  Protocol_Version version,
195  uint64_t record_sequence,
196  const uint8_t* message,
197  size_t message_len,
200  {
201  output.clear();
202 
203  output.push_back(record_type);
204  output.push_back(version.major_version());
205  output.push_back(version.minor_version());
206 
207  if(version.is_datagram_protocol())
208  {
209  for(size_t i = 0; i != 8; ++i)
210  output.push_back(get_byte(i, record_sequence));
211  }
212 
213  if(!cs) // initial unencrypted handshake records
214  {
215  append_u16_len(output, message_len);
216  output.insert(output.end(), message, message + message_len);
217  return;
218  }
219 
220  AEAD_Mode& aead = cs->aead();
221  std::vector<uint8_t> aad = cs->format_ad(record_sequence, record_type, version, static_cast<uint16_t>(message_len));
222 
223  const size_t ctext_size = aead.output_length(message_len);
224 
225  const size_t rec_size = ctext_size + cs->nonce_bytes_from_record();
226 
227  aead.set_ad(aad);
228 
229  const std::vector<uint8_t> nonce = cs->aead_nonce(record_sequence, rng);
230 
231  append_u16_len(output, rec_size);
232 
233  if(cs->nonce_bytes_from_record() > 0)
234  {
236  output += nonce;
237  else
238  output += std::make_pair(&nonce[cs->nonce_bytes_from_handshake()], cs->nonce_bytes_from_record());
239  }
240 
241  const size_t header_size = output.size();
242  output += std::make_pair(message, message_len);
243 
244  aead.start(nonce);
245  aead.finish(output, header_size);
246 
247  BOTAN_ASSERT(output.size() < MAX_CIPHERTEXT_SIZE,
248  "Produced ciphertext larger than protocol allows");
249  }
250 
251 namespace {
252 
253 size_t fill_buffer_to(secure_vector<uint8_t>& readbuf,
254  const uint8_t*& input,
255  size_t& input_size,
256  size_t& input_consumed,
257  size_t desired)
258  {
259  if(readbuf.size() >= desired)
260  return 0; // already have it
261 
262  const size_t taken = std::min(input_size, desired - readbuf.size());
263 
264  readbuf.insert(readbuf.end(), input, input + taken);
265  input_consumed += taken;
266  input_size -= taken;
267  input += taken;
268 
269  return (desired - readbuf.size()); // how many bytes do we still need?
270  }
271 
272 void decrypt_record(secure_vector<uint8_t>& output,
273  uint8_t record_contents[], size_t record_len,
274  uint64_t record_sequence,
275  Protocol_Version record_version,
276  Record_Type record_type,
277  Connection_Cipher_State& cs)
278  {
279  AEAD_Mode& aead = cs.aead();
280 
281  const std::vector<uint8_t> nonce = cs.aead_nonce(record_contents, record_len, record_sequence);
282  const uint8_t* msg = &record_contents[cs.nonce_bytes_from_record()];
283  const size_t msg_length = record_len - cs.nonce_bytes_from_record();
284 
285  /*
286  * This early rejection is based just on public information (length of the
287  * encrypted packet) and so does not leak any information. We used to use
288  * decode_error here which really is more appropriate, but that confuses some
289  * tools which are attempting automated detection of padding oracles,
290  * including older versions of TLS-Attacker.
291  */
292  if(msg_length < aead.minimum_final_size())
293  throw TLS_Exception(Alert::BAD_RECORD_MAC, "AEAD packet is shorter than the tag");
294 
295  const size_t ptext_size = aead.output_length(msg_length);
296 
297  aead.set_associated_data_vec(
298  cs.format_ad(record_sequence,
299  static_cast<uint8_t>(record_type),
300  record_version,
301  static_cast<uint16_t>(ptext_size))
302  );
303 
304  aead.start(nonce);
305 
306  output.assign(msg, msg + msg_length);
307  aead.finish(output, 0);
308  }
309 
310 Record_Header read_tls_record(secure_vector<uint8_t>& readbuf,
311  const uint8_t input[],
312  size_t input_len,
313  size_t& consumed,
314  secure_vector<uint8_t>& recbuf,
315  Connection_Sequence_Numbers* sequence_numbers,
316  get_cipherstate_fn get_cipherstate)
317  {
318  if(readbuf.size() < TLS_HEADER_SIZE) // header incomplete?
319  {
320  if(size_t needed = fill_buffer_to(readbuf, input, input_len, consumed, TLS_HEADER_SIZE))
321  {
322  return Record_Header(needed);
323  }
324 
325  BOTAN_ASSERT_EQUAL(readbuf.size(), TLS_HEADER_SIZE, "Have an entire header");
326  }
327 
328  const Protocol_Version version(readbuf[1], readbuf[2]);
329 
330  if(version.is_datagram_protocol())
331  throw TLS_Exception(Alert::PROTOCOL_VERSION,
332  "Expected TLS but got a record with DTLS version");
333 
334  const size_t record_size = make_uint16(readbuf[TLS_HEADER_SIZE-2],
335  readbuf[TLS_HEADER_SIZE-1]);
336 
337  if(record_size > MAX_CIPHERTEXT_SIZE)
338  throw TLS_Exception(Alert::RECORD_OVERFLOW,
339  "Received a record that exceeds maximum size");
340 
341  if(record_size == 0)
342  throw TLS_Exception(Alert::DECODE_ERROR,
343  "Received a completely empty record");
344 
345  if(size_t needed = fill_buffer_to(readbuf, input, input_len, consumed, TLS_HEADER_SIZE + record_size))
346  {
347  return Record_Header(needed);
348  }
349 
350  BOTAN_ASSERT_EQUAL(static_cast<size_t>(TLS_HEADER_SIZE) + record_size,
351  readbuf.size(),
352  "Have the full record");
353 
354  const Record_Type type = static_cast<Record_Type>(readbuf[0]);
355 
356  uint16_t epoch = 0;
357 
358  uint64_t sequence = 0;
359  if(sequence_numbers)
360  {
361  sequence = sequence_numbers->next_read_sequence();
362  epoch = sequence_numbers->current_read_epoch();
363  }
364  else
365  {
366  // server initial handshake case
367  epoch = 0;
368  }
369 
370  if(epoch == 0) // Unencrypted initial handshake
371  {
372  recbuf.assign(readbuf.begin() + TLS_HEADER_SIZE, readbuf.begin() + TLS_HEADER_SIZE + record_size);
373  readbuf.clear();
374  return Record_Header(sequence, version, type);
375  }
376 
377  // Otherwise, decrypt, check MAC, return plaintext
378  auto cs = get_cipherstate(epoch);
379 
380  BOTAN_ASSERT(cs, "Have cipherstate for this epoch");
381 
382  decrypt_record(recbuf,
383  &readbuf[TLS_HEADER_SIZE],
384  record_size,
385  sequence,
386  version,
387  type,
388  *cs);
389 
390  if(sequence_numbers)
391  sequence_numbers->read_accept(sequence);
392 
393  readbuf.clear();
394  return Record_Header(sequence, version, type);
395  }
396 
397 Record_Header read_dtls_record(secure_vector<uint8_t>& readbuf,
398  const uint8_t input[],
399  size_t input_len,
400  size_t& consumed,
401  secure_vector<uint8_t>& recbuf,
402  Connection_Sequence_Numbers* sequence_numbers,
403  get_cipherstate_fn get_cipherstate,
404  bool allow_epoch0_restart)
405  {
406  if(readbuf.size() < DTLS_HEADER_SIZE) // header incomplete?
407  {
408  if(fill_buffer_to(readbuf, input, input_len, consumed, DTLS_HEADER_SIZE))
409  {
410  readbuf.clear();
411  return Record_Header(0);
412  }
413 
414  BOTAN_ASSERT_EQUAL(readbuf.size(), DTLS_HEADER_SIZE, "Have an entire header");
415  }
416 
417  const Protocol_Version version(readbuf[1], readbuf[2]);
418 
419  if(version.is_datagram_protocol() == false)
420  {
421  readbuf.clear();
422  return Record_Header(0);
423  }
424 
425  const size_t record_size = make_uint16(readbuf[DTLS_HEADER_SIZE-2],
426  readbuf[DTLS_HEADER_SIZE-1]);
427 
428  if(record_size > MAX_CIPHERTEXT_SIZE)
429  {
430  // Too large to be valid, ignore it
431  readbuf.clear();
432  return Record_Header(0);
433  }
434 
435  if(fill_buffer_to(readbuf, input, input_len, consumed, DTLS_HEADER_SIZE + record_size))
436  {
437  // Truncated packet?
438  readbuf.clear();
439  return Record_Header(0);
440  }
441 
442  BOTAN_ASSERT_EQUAL(static_cast<size_t>(DTLS_HEADER_SIZE) + record_size, readbuf.size(),
443  "Have the full record");
444 
445  const Record_Type type = static_cast<Record_Type>(readbuf[0]);
446 
447  const uint64_t sequence = load_be<uint64_t>(&readbuf[3], 0);
448  const uint16_t epoch = (sequence >> 48);
449 
450  const bool already_seen = sequence_numbers && sequence_numbers->already_seen(sequence);
451 
452  if(already_seen && !(epoch == 0 && allow_epoch0_restart))
453  {
454  readbuf.clear();
455  return Record_Header(0);
456  }
457 
458  if(epoch == 0) // Unencrypted initial handshake
459  {
460  recbuf.assign(readbuf.begin() + DTLS_HEADER_SIZE, readbuf.begin() + DTLS_HEADER_SIZE + record_size);
461  readbuf.clear();
462  if(sequence_numbers)
463  sequence_numbers->read_accept(sequence);
464  return Record_Header(sequence, version, type);
465  }
466 
467  try
468  {
469  // Otherwise, decrypt, check MAC, return plaintext
470  auto cs = get_cipherstate(epoch);
471 
472  BOTAN_ASSERT(cs, "Have cipherstate for this epoch");
473 
474  decrypt_record(recbuf,
475  &readbuf[DTLS_HEADER_SIZE],
476  record_size,
477  sequence,
478  version,
479  type,
480  *cs);
481  }
482  catch(std::exception&)
483  {
484  readbuf.clear();
485  return Record_Header(0);
486  }
487 
488  if(sequence_numbers)
489  sequence_numbers->read_accept(sequence);
490 
491  readbuf.clear();
492  return Record_Header(sequence, version, type);
493  }
494 
495 }
496 
497 Record_Header read_record(bool is_datagram,
498  secure_vector<uint8_t>& readbuf,
499  const uint8_t input[],
500  size_t input_len,
501  size_t& consumed,
502  secure_vector<uint8_t>& recbuf,
503  Connection_Sequence_Numbers* sequence_numbers,
504  get_cipherstate_fn get_cipherstate,
505  bool allow_epoch0_restart)
506  {
507  if(is_datagram)
508  return read_dtls_record(readbuf, input, input_len, consumed,
509  recbuf, sequence_numbers, get_cipherstate, allow_epoch0_restart);
510  else
511  return read_tls_record(readbuf, input, input_len, consumed,
512  recbuf, sequence_numbers, get_cipherstate);
513  }
514 
515 }
516 
517 }
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:497
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:152
constexpr uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:41
Definition: bigint.h:1135
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:192
#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:232
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:132
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="")
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
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