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