Botan  2.15.0
Crypto and TLS for C++11
tls_cbc.cpp
Go to the documentation of this file.
1 /*
2 * TLS CBC Record Handling
3 * (C) 2012,2013,2014,2015,2016,2020 Jack Lloyd
4 * (C) 2016 Juraj Somorovsky
5 * (C) 2016 Matthias Gierlings
6 * (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
7 *
8 * Botan is released under the Simplified BSD License (see license.txt)
9 */
10 
11 #include <botan/internal/tls_cbc.h>
12 #include <botan/cbc.h>
13 
14 #include <botan/internal/rounding.h>
15 #include <botan/internal/ct_utils.h>
16 #include <botan/loadstor.h>
17 #include <botan/tls_alert.h>
18 #include <botan/tls_exceptn.h>
19 
20 namespace Botan {
21 
22 namespace TLS {
23 
24 /*
25 * TLS_CBC_HMAC_AEAD_Mode Constructor
26 */
28  std::unique_ptr<BlockCipher> cipher,
29  std::unique_ptr<MessageAuthenticationCode> mac,
30  size_t cipher_keylen,
31  size_t mac_keylen,
32  Protocol_Version version,
33  bool use_encrypt_then_mac) :
34  m_cipher_name(cipher->name()),
35  m_mac_name(mac->name()),
36  m_cipher_keylen(cipher_keylen),
37  m_mac_keylen(mac_keylen),
38  m_use_encrypt_then_mac(use_encrypt_then_mac)
39  {
40  m_tag_size = mac->output_length();
41  m_block_size = cipher->block_size();
42 
43  m_iv_size = version.supports_explicit_cbc_ivs() ? m_block_size : 0;
44 
45  m_is_datagram = version.is_datagram_protocol();
46 
47  m_mac = std::move(mac);
48 
49  if(dir == ENCRYPTION)
50  m_cbc.reset(new CBC_Encryption(cipher.release(), new Null_Padding));
51  else
52  m_cbc.reset(new CBC_Decryption(cipher.release(), new Null_Padding));
53  }
54 
56  {
57  cbc().clear();
58  mac().clear();
59  reset();
60  }
61 
63  {
64  cbc_state().clear();
65  m_ad.clear();
66  m_msg.clear();
67  }
68 
69 std::string TLS_CBC_HMAC_AEAD_Mode::name() const
70  {
71  return "TLS_CBC(" + m_cipher_name + "," + m_mac_name + ")";
72  }
73 
75  {
76  return 1; // just buffers anyway
77  }
78 
80  {
81  if(m_cbc_state.empty())
82  return nl == block_size();
83  return nl == iv_size();
84  }
85 
87  {
88  return Key_Length_Specification(m_cipher_keylen + m_mac_keylen);
89  }
90 
91 void TLS_CBC_HMAC_AEAD_Mode::key_schedule(const uint8_t key[], size_t keylen)
92  {
93  // Both keys are of fixed length specified by the ciphersuite
94 
95  if(keylen != m_cipher_keylen + m_mac_keylen)
96  throw Invalid_Key_Length(name(), keylen);
97 
98  mac().set_key(&key[0], m_mac_keylen);
99  cbc().set_key(&key[m_mac_keylen], m_cipher_keylen);
100  }
101 
102 void TLS_CBC_HMAC_AEAD_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
103  {
104  if(!valid_nonce_length(nonce_len))
105  {
106  throw Invalid_IV_Length(name(), nonce_len);
107  }
108 
109  m_msg.clear();
110 
111  if(nonce_len > 0)
112  {
113  m_cbc_state.assign(nonce, nonce + nonce_len);
114  }
115  }
116 
117 size_t TLS_CBC_HMAC_AEAD_Mode::process(uint8_t buf[], size_t sz)
118  {
119  m_msg.insert(m_msg.end(), buf, buf + sz);
120  return 0;
121  }
122 
123 std::vector<uint8_t> TLS_CBC_HMAC_AEAD_Mode::assoc_data_with_len(uint16_t len)
124  {
125  std::vector<uint8_t> ad = m_ad;
126  BOTAN_ASSERT(ad.size() == 13, "Expected AAD size");
127  ad[11] = get_byte(0, len);
128  ad[12] = get_byte(1, len);
129  return ad;
130  }
131 
132 void TLS_CBC_HMAC_AEAD_Mode::set_associated_data(const uint8_t ad[], size_t ad_len)
133  {
134  if(ad_len != 13)
135  throw Invalid_Argument("Invalid TLS AEAD associated data length");
136  m_ad.assign(ad, ad + ad_len);
137  }
138 
139 void TLS_CBC_HMAC_AEAD_Encryption::set_associated_data(const uint8_t ad[], size_t ad_len)
140  {
142 
144  {
145  // AAD hack for EtM
146  // EtM uses ciphertext size instead of plaintext size for AEAD input
147  const uint16_t pt_size = make_uint16(assoc_data()[11], assoc_data()[12]);
148  const uint16_t enc_size = static_cast<uint16_t>(round_up(iv_size() + pt_size + 1, block_size()));
149  assoc_data()[11] = get_byte<uint16_t>(0, enc_size);
150  assoc_data()[12] = get_byte<uint16_t>(1, enc_size);
151  }
152  }
153 
154 void TLS_CBC_HMAC_AEAD_Encryption::cbc_encrypt_record(
155  secure_vector<uint8_t>& buffer, size_t offset, size_t padding_length)
156  {
157  // We always do short padding:
158  BOTAN_ASSERT_NOMSG(padding_length <= 16);
159 
160  buffer.resize(buffer.size() + padding_length);
161 
162  const uint8_t padding_val = static_cast<uint8_t>(padding_length - 1);
163 
164  CT::poison(&padding_val, 1);
165  CT::poison(&padding_length, 1);
166  CT::poison(buffer.data(), buffer.size());
167 
168  const size_t last_block_starts = buffer.size() - block_size();
169  const size_t padding_starts = buffer.size() - padding_length;
170  for(size_t i = last_block_starts; i != buffer.size(); ++i)
171  {
172  auto add_padding = CT::Mask<uint8_t>(CT::Mask<size_t>::is_gte(i, padding_starts));
173  buffer[i] = add_padding.select(padding_val, buffer[i]);
174  }
175 
176  CT::unpoison(padding_val);
177  CT::unpoison(padding_length);
178  CT::unpoison(buffer.data(), buffer.size());
179 
180  cbc().start(cbc_state());
181  cbc().process(&buffer[offset], buffer.size() - offset);
182 
183  cbc_state().assign(buffer.data() + (buffer.size() - block_size()), buffer.data() + buffer.size());
184  }
185 
186 size_t TLS_CBC_HMAC_AEAD_Encryption::output_length(size_t input_length) const
187  {
188  return round_up(input_length + 1 + (use_encrypt_then_mac() ? 0 : tag_size()), block_size()) +
189  (use_encrypt_then_mac() ? tag_size() : 0);
190  }
191 
193  {
194  update(buffer, offset);
195 
196  const size_t msg_size = msg().size();
197 
198  const size_t input_size = msg_size + 1 + (use_encrypt_then_mac() ? 0 : tag_size());
199  const size_t enc_size = round_up(input_size, block_size());
200  BOTAN_DEBUG_ASSERT(enc_size % block_size() == 0);
201 
202  const uint8_t padding_val = static_cast<uint8_t>(enc_size - input_size);
203  const size_t padding_length = static_cast<size_t>(padding_val) + 1;
204 
205  buffer.reserve(offset + msg_size + padding_length + tag_size());
206  buffer.resize(offset + msg_size);
207  copy_mem(&buffer[offset], msg().data(), msg_size);
208 
209  mac().update(assoc_data());
210 
212  {
213  if(iv_size() > 0)
214  {
215  mac().update(cbc_state());
216  }
217 
218  cbc_encrypt_record(buffer, offset, padding_length);
219  mac().update(&buffer[offset], enc_size);
220  buffer.resize(buffer.size() + tag_size());
221  mac().final(&buffer[buffer.size() - tag_size()]);
222  }
223  else
224  {
225  mac().update(&buffer[offset], msg_size);
226  buffer.resize(buffer.size() + tag_size());
227  mac().final(&buffer[buffer.size() - tag_size()]);
228  cbc_encrypt_record(buffer, offset, padding_length);
229  }
230  }
231 
232 /*
233 * Checks the TLS padding. Returns 0 if the padding is invalid (we
234 * count the padding_length field as part of the padding size so a
235 * valid padding will always be at least one byte long), or the length
236 * of the padding otherwise. This is actually padding_length + 1
237 * because both the padding and padding_length fields are padding from
238 * our perspective.
239 *
240 * Returning 0 in the error case should ensure the MAC check will fail.
241 * This approach is suggested in section 6.2.3.2 of RFC 5246.
242 */
243 uint16_t check_tls_cbc_padding(const uint8_t record[], size_t record_len)
244  {
245  if(record_len == 0 || record_len > 0xFFFF)
246  return 0;
247 
248  const uint16_t rec16 = static_cast<uint16_t>(record_len);
249 
250  /*
251  * TLS v1.0 and up require all the padding bytes be the same value
252  * and allows up to 255 bytes.
253  */
254 
255  const uint16_t to_check = std::min<uint16_t>(256, static_cast<uint16_t>(record_len));
256  const uint8_t pad_byte = record[record_len-1];
257  const uint16_t pad_bytes = 1 + pad_byte;
258 
259  auto pad_invalid = CT::Mask<uint16_t>::is_lt(rec16, pad_bytes);
260 
261  for(uint16_t i = rec16 - to_check; i != rec16; ++i)
262  {
263  const uint16_t offset = rec16 - i;
264  const auto in_pad_range = CT::Mask<uint16_t>::is_lte(offset, pad_bytes);
265  const auto pad_correct = CT::Mask<uint16_t>::is_equal(record[i], pad_byte);
266  pad_invalid |= in_pad_range & ~pad_correct;
267  }
268 
269  return pad_invalid.if_not_set_return(pad_bytes);
270  }
271 
272 void TLS_CBC_HMAC_AEAD_Decryption::cbc_decrypt_record(uint8_t record_contents[], size_t record_len)
273  {
274  if(record_len == 0 || record_len % block_size() != 0)
275  throw Decoding_Error("Received TLS CBC ciphertext with invalid length");
276 
277  cbc().start(cbc_state());
278  cbc_state().assign(record_contents + record_len - block_size(),
279  record_contents + record_len);
280 
281  cbc().process(record_contents, record_len);
282  }
283 
285  {
286  /*
287  * We don't know this because the padding is arbitrary
288  */
289  return 0;
290  }
291 
292 /*
293 * This function performs additional compression calls in order
294 * to protect from the Lucky 13 attack. It adds new compression
295 * function calls over dummy data, by computing additional HMAC updates.
296 *
297 * The countermeasure was described (in a similar way) in the Lucky 13 paper.
298 *
299 * Background:
300 * - One SHA-1/SHA-256 compression is performed with 64 bytes of data.
301 * - HMAC adds 8 byte length field and padding (at least 1 byte) so that we have:
302 * - 0 - 55 bytes: 1 compression
303 * - 56 - 55+64 bytes: 2 compressions
304 * - 56+64 - 55+2*64 bytes: 3 compressions ...
305 * - For SHA-384, this works similarly, but we have 128 byte blocks and 16 byte
306 * long length field. This results in:
307 * - 0 - 111 bytes: 1 compression
308 * - 112 - 111+128 bytes: 2 compressions ...
309 *
310 * The implemented countermeasure works as follows:
311 * 1) It computes max_compressions: number of maximum compressions performed on
312 * the decrypted data
313 * 2) It computes current_compressions: number of compressions performed on the
314 * decrypted data, after padding has been removed
315 * 3) If current_compressions != max_compressions: It invokes an HMAC update
316 * over dummy data so that (max_compressions - current_compressions)
317 * compressions are performed. Otherwise, it invokes an HMAC update so that
318 * no compressions are performed.
319 *
320 * Note that the padding validation in Botan is always performed over
321 * min(plen,256) bytes, see the function check_tls_cbc_padding. This differs
322 * from the countermeasure described in the paper.
323 *
324 * Note that the padding length padlen does also count the last byte
325 * of the decrypted plaintext. This is different from the Lucky 13 paper.
326 *
327 * This countermeasure leaves a difference of about 100 clock cycles (in
328 * comparison to >1000 clock cycles observed without it).
329 *
330 * plen represents the length of the decrypted plaintext message P
331 * padlen represents the padding length
332 *
333 */
334 void TLS_CBC_HMAC_AEAD_Decryption::perform_additional_compressions(size_t plen, size_t padlen)
335  {
336  uint16_t block_size;
337  uint16_t max_bytes_in_first_block;
338  if(mac().name() == "HMAC(SHA-384)")
339  {
340  block_size = 128;
341  max_bytes_in_first_block = 111;
342  }
343  else
344  {
345  block_size = 64;
346  max_bytes_in_first_block = 55;
347  }
348  // number of maximum MACed bytes
349  const uint16_t L1 = static_cast<uint16_t>(13 + plen - tag_size());
350  // number of current MACed bytes (L1 - padlen)
351  // Here the Lucky 13 paper is different because the padlen length in the paper
352  // does not count the last message byte.
353  const uint16_t L2 = static_cast<uint16_t>(13 + plen - padlen - tag_size());
354  // From the paper, for SHA-256/SHA-1 compute: ceil((L1-55)/64) and ceil((L2-55)/64)
355  // ceil((L1-55)/64) = floor((L1+64-1-55)/64)
356  // Here we compute number of compressions for SHA-* in general
357  const uint16_t max_compresssions = ( (L1 + block_size - 1 - max_bytes_in_first_block) / block_size);
358  const uint16_t current_compressions = ((L2 + block_size - 1 - max_bytes_in_first_block) / block_size);
359  // number of additional compressions we have to perform
360  const uint16_t add_compressions = max_compresssions - current_compressions;
361  const uint16_t equal = CT::Mask<uint16_t>::is_equal(max_compresssions, current_compressions).if_set_return(1);
362  // We compute the data length we need to achieve the number of compressions.
363  // If there are no compressions, we just add 55/111 dummy bytes so that no
364  // compression is performed.
365  const uint16_t data_len = block_size * add_compressions + equal * max_bytes_in_first_block;
366  std::vector<uint8_t> data(data_len);
367  mac().update(data);
368  // we do not need to clear the MAC since the connection is broken anyway
369  }
370 
372  {
373  update(buffer, offset);
374  buffer.resize(offset);
375 
376  const size_t record_len = msg().size();
377  uint8_t* record_contents = msg().data();
378 
379  // This early exit does not leak info because all the values compared are public
380  if(record_len < tag_size() ||
381  (record_len - (use_encrypt_then_mac() ? tag_size() : 0)) % block_size() != 0)
382  {
383  throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure");
384  }
385 
387  {
388  const size_t enc_size = record_len - tag_size();
389  const size_t enc_iv_size = enc_size + iv_size();
390 
391  BOTAN_ASSERT_NOMSG(enc_iv_size <= 0xFFFF);
392 
393  mac().update(assoc_data_with_len(static_cast<uint16_t>(enc_iv_size)));
394  if(iv_size() > 0)
395  {
396  mac().update(cbc_state());
397  }
398  mac().update(record_contents, enc_size);
399 
400  std::vector<uint8_t> mac_buf(tag_size());
401  mac().final(mac_buf.data());
402 
403  const size_t mac_offset = enc_size;
404 
405  const bool mac_ok = constant_time_compare(&record_contents[mac_offset], mac_buf.data(), tag_size());
406 
407  if(!mac_ok)
408  {
409  throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure");
410  }
411 
412  cbc_decrypt_record(record_contents, enc_size);
413 
414  // 0 if padding was invalid, otherwise 1 + padding_bytes
415  const uint16_t pad_size = check_tls_cbc_padding(record_contents, enc_size);
416 
417  // No oracle here, whoever sent us this had the key since MAC check passed
418  if(pad_size == 0)
419  {
420  throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure");
421  }
422 
423  const uint8_t* plaintext_block = &record_contents[0];
424  const size_t plaintext_length = enc_size - pad_size;
425 
426  buffer.insert(buffer.end(), plaintext_block, plaintext_block + plaintext_length);
427  }
428  else
429  {
430  cbc_decrypt_record(record_contents, record_len);
431 
432  CT::poison(record_contents, record_len);
433 
434  // 0 if padding was invalid, otherwise 1 + padding_bytes
435  uint16_t pad_size = check_tls_cbc_padding(record_contents, record_len);
436 
437  /*
438  This mask is zero if there is not enough room in the packet to get a valid MAC.
439 
440  We have to accept empty packets, since otherwise we are not compatible
441  with how OpenSSL's countermeasure for fixing BEAST in TLS 1.0 CBC works
442  (sending empty records, instead of 1/(n-1) splitting)
443  */
444 
445  // We know the cast cannot overflow as pad_size <= 256 && tag_size <= 32
446  const auto size_ok_mask = CT::Mask<uint16_t>::is_lte(
447  static_cast<uint16_t>(tag_size() + pad_size),
448  static_cast<uint16_t>(record_len));
449 
450  pad_size = size_ok_mask.if_set_return(pad_size);
451 
452  CT::unpoison(record_contents, record_len);
453 
454  /*
455  This is unpoisoned sooner than it should. The pad_size leaks to plaintext_length and
456  then to the timing channel in the MAC computation described in the Lucky 13 paper.
457  */
458  CT::unpoison(pad_size);
459 
460  const uint8_t* plaintext_block = &record_contents[0];
461  const uint16_t plaintext_length = static_cast<uint16_t>(record_len - tag_size() - pad_size);
462 
463  mac().update(assoc_data_with_len(plaintext_length));
464  mac().update(plaintext_block, plaintext_length);
465 
466  std::vector<uint8_t> mac_buf(tag_size());
467  mac().final(mac_buf.data());
468 
469  const size_t mac_offset = record_len - (tag_size() + pad_size);
470 
471  const bool mac_ok = constant_time_compare(&record_contents[mac_offset], mac_buf.data(), tag_size());
472 
473  const auto ok_mask = size_ok_mask & CT::Mask<uint16_t>::expand(mac_ok) & CT::Mask<uint16_t>::expand(pad_size);
474 
475  CT::unpoison(ok_mask);
476 
477  if(ok_mask.is_set())
478  {
479  buffer.insert(buffer.end(), plaintext_block, plaintext_block + plaintext_length);
480  }
481  else
482  {
483  perform_additional_compressions(record_len, pad_size);
484 
485  /*
486  * In DTLS case we have to finish computing the MAC since we require the
487  * MAC state be reset for future packets. This extra timing channel may
488  * be exploitable in a Lucky13 variant.
489  */
491  mac().final(mac_buf);
492  throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure");
493  }
494  }
495  }
496 
497 }
498 
499 }
size_t process(uint8_t buf[], size_t sz) override final
Definition: tls_cbc.cpp:117
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: tls_cbc.cpp:192
void update(secure_vector< uint8_t > &buffer, size_t offset=0)
Definition: cipher_mode.h:112
Cipher_Mode & cbc() const
Definition: tls_cbc.h:66
constexpr uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:41
TLS_CBC_HMAC_AEAD_Mode(Cipher_Dir direction, std::unique_ptr< BlockCipher > cipher, std::unique_ptr< MessageAuthenticationCode > mac, size_t cipher_keylen, size_t mac_keylen, Protocol_Version version, bool use_encrypt_then_mac)
Definition: tls_cbc.cpp:27
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.h:82
static Mask< T > is_gte(T x, T y)
Definition: ct_utils.h:181
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:68
void poison(const T *p, size_t n)
Definition: ct_utils.h:48
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: tls_cbc.cpp:371
MessageAuthenticationCode & mac() const
Definition: tls_cbc.h:68
std::string m_cipher_name
void start(const std::vector< uint8_t, Alloc > &nonce)
Definition: cipher_mode.h:69
Key_Length_Specification key_spec() const override final
Definition: tls_cbc.cpp:86
void set_associated_data(const uint8_t ad[], size_t ad_len) override
Definition: tls_cbc.cpp:132
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
secure_vector< uint8_t > & cbc_state()
Definition: tls_cbc.h:74
void final(uint8_t out[])
Definition: buf_comp.h:83
static Mask< T > is_lte(T x, T y)
Definition: ct_utils.h:173
static Mask< T > expand(T v)
Definition: ct_utils.h:123
std::string name
void set_key(const SymmetricKey &key)
Definition: sym_algo.h:65
bool valid_nonce_length(size_t nl) const override final
Definition: tls_cbc.cpp:79
void clear() override final
Definition: tls_cbc.cpp:55
#define BOTAN_DEBUG_ASSERT(expr)
Definition: assert.h:123
std::string name() const override final
Definition: tls_cbc.cpp:69
bool supports_explicit_cbc_ivs() const
Definition: tls_version.cpp:67
T select(T x, T y) const
Definition: ct_utils.h:264
virtual void clear()=0
size_t tag_size() const override final
Definition: tls_cbc.h:40
std::vector< uint8_t > & assoc_data()
Definition: tls_cbc.h:75
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:133
Definition: alg_id.cpp:13
size_t update_granularity() const override final
Definition: tls_cbc.cpp:74
virtual size_t process(uint8_t msg[], size_t msg_len)=0
std::vector< uint8_t > assoc_data_with_len(uint16_t len)
Definition: tls_cbc.cpp:123
Cipher_Dir
Definition: cipher_mode.h:23
void update(const uint8_t in[], size_t length)
Definition: buf_comp.h:33
uint16_t check_tls_cbc_padding(const uint8_t record[], size_t record_len)
Definition: tls_cbc.cpp:243
void reset() override final
Definition: tls_cbc.cpp:62
size_t output_length(size_t input_length) const override
Definition: tls_cbc.cpp:186
void unpoison(const T *p, size_t n)
Definition: ct_utils.h:59
secure_vector< uint8_t > & msg()
Definition: tls_cbc.h:76
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)
Definition: loadstor.h:54
size_t round_up(size_t n, size_t align_to)
Definition: rounding.h:21
static Mask< T > is_equal(T x, T y)
Definition: ct_utils.h:149
virtual size_t output_length() const =0
size_t output_length(size_t input_length) const override
Definition: tls_cbc.cpp:284
void set_associated_data(const uint8_t ad[], size_t ad_len) override
Definition: tls_cbc.cpp:139
static Mask< T > is_lt(T x, T y)
Definition: ct_utils.h:157