Botan 2.19.3
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/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
20namespace Botan {
21
22namespace 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
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
91void 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
102void 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
117size_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
123std::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
132void 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
139void 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
154void 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
186size_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*/
243uint16_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
272void 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*/
334void 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}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:68
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:123
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:55
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:149
static Mask< T > expand(T v)
Definition ct_utils.h:123
static Mask< T > is_lt(T x, T y)
Definition ct_utils.h:157
static Mask< T > is_lte(T x, T y)
Definition ct_utils.h:173
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 set_key(const SymmetricKey &key)
Definition sym_algo.h:147
virtual void clear()=0
bool supports_explicit_cbc_ivs() const
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition tls_cbc.cpp:371
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
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition tls_cbc.cpp:192
size_t output_length(size_t input_length) const override
Definition tls_cbc.cpp:186
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:132
std::vector< uint8_t > assoc_data_with_len(uint16_t len)
Definition tls_cbc.cpp:123
bool valid_nonce_length(size_t nl) const override final
Definition tls_cbc.cpp:79
Key_Length_Specification key_spec() const override final
Definition tls_cbc.cpp:86
void reset() override final
Definition tls_cbc.cpp:62
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:27
size_t process(uint8_t buf[], size_t sz) override final
Definition tls_cbc.cpp:117
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:69
void clear() override final
Definition tls_cbc.cpp:55
Cipher_Mode & cbc() const
Definition tls_cbc.h:66
size_t update_granularity() const override final
Definition tls_cbc.cpp:74
std::string m_cipher_name
std::string name
int(* update)(CTX *, const void *, CC_LONG len)
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:59
uint16_t check_tls_cbc_padding(const uint8_t record[], size_t record_len)
Definition tls_cbc.cpp:243
void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:133
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition mem_ops.h:82
@ ENCRYPTION
Definition cipher_mode.h:23
constexpr uint8_t get_byte(size_t byte_num, T input)
Definition loadstor.h:41
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:54