Botan  2.1.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 = 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,
296  Connection_Cipher_State& cs)
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  const size_t ptext_size = aead->output_length(msg_length);
306 
307  aead->set_associated_data_vec(
308  cs.format_ad(record_sequence, record_type, record_version, static_cast<uint16_t>(ptext_size))
309  );
310 
311  aead->start(nonce);
312 
313  const size_t offset = output.size();
314  output += std::make_pair(msg, msg_length);
315  aead->finish(output, offset);
316  }
317 
318 size_t read_tls_record(secure_vector<uint8_t>& readbuf,
319  Record_Raw_Input& raw_input,
320  Record& rec,
321  Connection_Sequence_Numbers* sequence_numbers,
322  get_cipherstate_fn get_cipherstate)
323  {
324  if(readbuf.size() < TLS_HEADER_SIZE) // header incomplete?
325  {
326  if(size_t needed = fill_buffer_to(readbuf,
327  raw_input.get_data(), raw_input.get_size(), raw_input.get_consumed(),
329  return needed;
330 
331  BOTAN_ASSERT_EQUAL(readbuf.size(), TLS_HEADER_SIZE, "Have an entire header");
332  }
333 
334  *rec.get_protocol_version() = Protocol_Version(readbuf[1], readbuf[2]);
335 
336  BOTAN_ASSERT(!rec.get_protocol_version()->is_datagram_protocol(), "Expected TLS");
337 
338  const size_t record_size = make_uint16(readbuf[TLS_HEADER_SIZE-2],
339  readbuf[TLS_HEADER_SIZE-1]);
340 
341  if(record_size > MAX_CIPHERTEXT_SIZE)
342  throw TLS_Exception(Alert::RECORD_OVERFLOW,
343  "Received a record that exceeds maximum size");
344 
345  if(record_size == 0)
346  throw TLS_Exception(Alert::DECODE_ERROR,
347  "Received a completely empty record");
348 
349  if(size_t needed = fill_buffer_to(readbuf,
350  raw_input.get_data(), raw_input.get_size(), raw_input.get_consumed(),
351  TLS_HEADER_SIZE + record_size))
352  return needed;
353 
354  BOTAN_ASSERT_EQUAL(static_cast<size_t>(TLS_HEADER_SIZE) + record_size,
355  readbuf.size(),
356  "Have the full record");
357 
358  *rec.get_type() = static_cast<Record_Type>(readbuf[0]);
359 
360  uint16_t epoch = 0;
361 
362  if(sequence_numbers)
363  {
364  *rec.get_sequence() = sequence_numbers->next_read_sequence();
365  epoch = sequence_numbers->current_read_epoch();
366  }
367  else
368  {
369  // server initial handshake case
370  *rec.get_sequence() = 0;
371  epoch = 0;
372  }
373 
374  uint8_t* record_contents = &readbuf[TLS_HEADER_SIZE];
375 
376  if(epoch == 0) // Unencrypted initial handshake
377  {
378  rec.get_data().assign(readbuf.begin() + TLS_HEADER_SIZE, readbuf.begin() + TLS_HEADER_SIZE + record_size);
379  readbuf.clear();
380  return 0; // got a full record
381  }
382 
383  // Otherwise, decrypt, check MAC, return plaintext
384  auto cs = get_cipherstate(epoch);
385 
386  BOTAN_ASSERT(cs, "Have cipherstate for this epoch");
387 
388  decrypt_record(rec.get_data(),
389  record_contents,
390  record_size,
391  *rec.get_sequence(),
392  *rec.get_protocol_version(),
393  *rec.get_type(),
394  *cs);
395 
396  if(sequence_numbers)
397  sequence_numbers->read_accept(*rec.get_sequence());
398 
399  readbuf.clear();
400  return 0;
401  }
402 
403 size_t read_dtls_record(secure_vector<uint8_t>& readbuf,
404  Record_Raw_Input& raw_input,
405  Record& rec,
406  Connection_Sequence_Numbers* sequence_numbers,
407  get_cipherstate_fn get_cipherstate)
408  {
409  if(readbuf.size() < DTLS_HEADER_SIZE) // header incomplete?
410  {
411  if(fill_buffer_to(readbuf, raw_input.get_data(), raw_input.get_size(), raw_input.get_consumed(), DTLS_HEADER_SIZE))
412  {
413  readbuf.clear();
414  return 0;
415  }
416 
417  BOTAN_ASSERT_EQUAL(readbuf.size(), DTLS_HEADER_SIZE, "Have an entire header");
418  }
419 
420  *rec.get_protocol_version() = Protocol_Version(readbuf[1], readbuf[2]);
421 
422  BOTAN_ASSERT(rec.get_protocol_version()->is_datagram_protocol(), "Expected DTLS");
423 
424  const size_t record_size = make_uint16(readbuf[DTLS_HEADER_SIZE-2],
425  readbuf[DTLS_HEADER_SIZE-1]);
426 
427  if(record_size > MAX_CIPHERTEXT_SIZE)
428  throw TLS_Exception(Alert::RECORD_OVERFLOW,
429  "Got message that exceeds maximum size");
430 
431  if(fill_buffer_to(readbuf, raw_input.get_data(), raw_input.get_size(), raw_input.get_consumed(), DTLS_HEADER_SIZE + record_size))
432  {
433  // Truncated packet?
434  readbuf.clear();
435  return 0;
436  }
437 
438  BOTAN_ASSERT_EQUAL(static_cast<size_t>(DTLS_HEADER_SIZE) + record_size, readbuf.size(),
439  "Have the full record");
440 
441  *rec.get_type() = static_cast<Record_Type>(readbuf[0]);
442 
443  uint16_t epoch = 0;
444 
445  *rec.get_sequence() = load_be<uint64_t>(&readbuf[3], 0);
446  epoch = (*rec.get_sequence() >> 48);
447 
448  if(sequence_numbers && sequence_numbers->already_seen(*rec.get_sequence()))
449  {
450  readbuf.clear();
451  return 0;
452  }
453 
454  uint8_t* record_contents = &readbuf[DTLS_HEADER_SIZE];
455 
456  if(epoch == 0) // Unencrypted initial handshake
457  {
458  rec.get_data().assign(readbuf.begin() + DTLS_HEADER_SIZE, readbuf.begin() + DTLS_HEADER_SIZE + record_size);
459  readbuf.clear();
460  return 0; // got a full record
461  }
462 
463  try
464  {
465  // Otherwise, decrypt, check MAC, return plaintext
466  auto cs = get_cipherstate(epoch);
467 
468  BOTAN_ASSERT(cs, "Have cipherstate for this epoch");
469 
470  decrypt_record(rec.get_data(),
471  record_contents,
472  record_size,
473  *rec.get_sequence(),
474  *rec.get_protocol_version(),
475  *rec.get_type(),
476  *cs);
477  }
478  catch(std::exception)
479  {
480  readbuf.clear();
481  *rec.get_type() = NO_RECORD;
482  return 0;
483  }
484 
485  if(sequence_numbers)
486  sequence_numbers->read_accept(*rec.get_sequence());
487 
488  readbuf.clear();
489  return 0;
490  }
491 
492 }
493 
495  Record_Raw_Input& raw_input,
496  Record& rec,
497  Connection_Sequence_Numbers* sequence_numbers,
498  get_cipherstate_fn get_cipherstate)
499  {
500  if(raw_input.is_datagram())
501  return read_dtls_record(readbuf, raw_input, rec,
502  sequence_numbers, get_cipherstate);
503  else
504  return read_tls_record(readbuf, raw_input, rec,
505  sequence_numbers, get_cipherstate);
506  }
507 
508 }
509 
510 }
void xor_buf(T out[], const T in[], size_t length)
Definition: mem_ops.h:115
const InitializationVector & client_iv() const
secure_vector< uint8_t > bits_of() const
Definition: symkey.h:31
uint8_t minor_version() const
Definition: tls_version.h:82
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:441
virtual void randomize(uint8_t output[], size_t length)=0
const uint8_t * get_data()
Definition: tls_record.h:114
size_t nonce_bytes_from_record() const
Definition: tls_record.h:56
std::function< std::shared_ptr< Connection_Cipher_State >uint16_t)> get_cipherstate_fn
Definition: tls_record.h:166
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:494
Definition: bigint.h:619
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
size_t length() const
Definition: symkey.h:25
void start(const std::vector< uint8_t, Alloc > &nonce)
Definition: cipher_mode.h:38
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:27
uint64_t load_be< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:223
virtual size_t output_length(size_t input_length) const =0
size_t mac_keylen() const
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:121
const SymmetricKey & client_mac_key() const
bool supports_explicit_cbc_ivs() const
Definition: tls_version.cpp:67
std::vector< uint8_t > format_ad(uint64_t seq, uint8_t type, Protocol_Version version, uint16_t ptext_length)
Definition: tls_record.cpp:184
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:53
uint8_t major_version() const
Definition: tls_version.h:77
const SymmetricKey & server_mac_key() const
AEAD_Mode * get_aead(const std::string &algo, Cipher_Dir dir)
Definition: aead.cpp:41
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:68
Definition: alg_id.cpp:13
std::vector< T > unlock(const secure_vector< T > &in)
Definition: secmem.h:125
size_t nonce_bytes_from_handshake() const
Definition: tls_record.h:55
size_t cipher_keylen() const
std::string mac_algo() const
std::string cipher_algo() const
uint16_t make_uint16(uint8_t i0, uint8_t i1)
Definition: loadstor.h:60
T min(T a, T b)
Definition: ct_utils.h:180
const InitializationVector & server_iv() const
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:47
const SymmetricKey & client_cipher_key() const
bool is_datagram_protocol() const
Definition: tls_version.cpp:34
virtual void finish(secure_vector< uint8_t > &final_block, size_t offset=0)=0
const SymmetricKey & server_cipher_key() const