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