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