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