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