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