/src/botan/src/lib/tls/tls_cbc/tls_cbc.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
20 | | namespace Botan { |
21 | | |
22 | | namespace TLS { |
23 | | |
24 | | /* |
25 | | * TLS_CBC_HMAC_AEAD_Mode Constructor |
26 | | */ |
27 | | TLS_CBC_HMAC_AEAD_Mode::TLS_CBC_HMAC_AEAD_Mode(Cipher_Dir dir, |
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 | 1.03k | { |
40 | 1.03k | m_tag_size = mac->output_length(); |
41 | 1.03k | m_block_size = cipher->block_size(); |
42 | 1.03k | |
43 | 1.03k | m_iv_size = version.supports_explicit_cbc_ivs() ? m_block_size : 0; |
44 | 1.03k | |
45 | 1.03k | m_is_datagram = version.is_datagram_protocol(); |
46 | 1.03k | |
47 | 1.03k | m_mac = std::move(mac); |
48 | 1.03k | |
49 | 1.03k | if(dir == ENCRYPTION) |
50 | 491 | m_cbc.reset(new CBC_Encryption(cipher.release(), new Null_Padding)); |
51 | 543 | else |
52 | 543 | m_cbc.reset(new CBC_Decryption(cipher.release(), new Null_Padding)); |
53 | 1.03k | } |
54 | | |
55 | | void TLS_CBC_HMAC_AEAD_Mode::clear() |
56 | 0 | { |
57 | 0 | cbc().clear(); |
58 | 0 | mac().clear(); |
59 | 0 | reset(); |
60 | 0 | } |
61 | | |
62 | | void TLS_CBC_HMAC_AEAD_Mode::reset() |
63 | 0 | { |
64 | 0 | cbc_state().clear(); |
65 | 0 | m_ad.clear(); |
66 | 0 | m_msg.clear(); |
67 | 0 | } |
68 | | |
69 | | std::string TLS_CBC_HMAC_AEAD_Mode::name() const |
70 | 0 | { |
71 | 0 | return "TLS_CBC(" + m_cipher_name + "," + m_mac_name + ")"; |
72 | 0 | } |
73 | | |
74 | | size_t TLS_CBC_HMAC_AEAD_Mode::update_granularity() const |
75 | 0 | { |
76 | 0 | return 1; // just buffers anyway |
77 | 0 | } |
78 | | |
79 | | bool TLS_CBC_HMAC_AEAD_Mode::valid_nonce_length(size_t nl) const |
80 | 1.08k | { |
81 | 1.08k | if(m_cbc_state.empty()) |
82 | 811 | return nl == block_size(); |
83 | 277 | return nl == iv_size(); |
84 | 277 | } |
85 | | |
86 | | Key_Length_Specification TLS_CBC_HMAC_AEAD_Mode::key_spec() const |
87 | 1.03k | { |
88 | 1.03k | return Key_Length_Specification(m_cipher_keylen + m_mac_keylen); |
89 | 1.03k | } |
90 | | |
91 | | void TLS_CBC_HMAC_AEAD_Mode::key_schedule(const uint8_t key[], size_t keylen) |
92 | 1.03k | { |
93 | 1.03k | // Both keys are of fixed length specified by the ciphersuite |
94 | 1.03k | |
95 | 1.03k | if(keylen != m_cipher_keylen + m_mac_keylen) |
96 | 0 | throw Invalid_Key_Length(name(), keylen); |
97 | 1.03k | |
98 | 1.03k | mac().set_key(&key[0], m_mac_keylen); |
99 | 1.03k | cbc().set_key(&key[m_mac_keylen], m_cipher_keylen); |
100 | 1.03k | } |
101 | | |
102 | | void TLS_CBC_HMAC_AEAD_Mode::start_msg(const uint8_t nonce[], size_t nonce_len) |
103 | 1.08k | { |
104 | 1.08k | if(!valid_nonce_length(nonce_len)) |
105 | 0 | { |
106 | 0 | throw Invalid_IV_Length(name(), nonce_len); |
107 | 0 | } |
108 | 1.08k | |
109 | 1.08k | m_msg.clear(); |
110 | 1.08k | |
111 | 1.08k | if(nonce_len > 0) |
112 | 1.08k | { |
113 | 1.08k | m_cbc_state.assign(nonce, nonce + nonce_len); |
114 | 1.08k | } |
115 | 1.08k | } |
116 | | |
117 | | size_t TLS_CBC_HMAC_AEAD_Mode::process(uint8_t buf[], size_t sz) |
118 | 1.08k | { |
119 | 1.08k | m_msg.insert(m_msg.end(), buf, buf + sz); |
120 | 1.08k | return 0; |
121 | 1.08k | } |
122 | | |
123 | | std::vector<uint8_t> TLS_CBC_HMAC_AEAD_Mode::assoc_data_with_len(uint16_t len) |
124 | 272 | { |
125 | 272 | std::vector<uint8_t> ad = m_ad; |
126 | 272 | BOTAN_ASSERT(ad.size() == 13, "Expected AAD size"); |
127 | 272 | ad[11] = get_byte(0, len); |
128 | 272 | ad[12] = get_byte(1, len); |
129 | 272 | return ad; |
130 | 272 | } |
131 | | |
132 | | void TLS_CBC_HMAC_AEAD_Mode::set_associated_data(const uint8_t ad[], size_t ad_len) |
133 | 1.08k | { |
134 | 1.08k | if(ad_len != 13) |
135 | 0 | throw Invalid_Argument("Invalid TLS AEAD associated data length"); |
136 | 1.08k | m_ad.assign(ad, ad + ad_len); |
137 | 1.08k | } |
138 | | |
139 | | void TLS_CBC_HMAC_AEAD_Encryption::set_associated_data(const uint8_t ad[], size_t ad_len) |
140 | 768 | { |
141 | 768 | TLS_CBC_HMAC_AEAD_Mode::set_associated_data(ad, ad_len); |
142 | 768 | |
143 | 768 | if(use_encrypt_then_mac()) |
144 | 52 | { |
145 | 52 | // AAD hack for EtM |
146 | 52 | // EtM uses ciphertext size instead of plaintext size for AEAD input |
147 | 52 | const uint16_t pt_size = make_uint16(assoc_data()[11], assoc_data()[12]); |
148 | 52 | const uint16_t enc_size = static_cast<uint16_t>(round_up(iv_size() + pt_size + 1, block_size())); |
149 | 52 | assoc_data()[11] = get_byte<uint16_t>(0, enc_size); |
150 | 52 | assoc_data()[12] = get_byte<uint16_t>(1, enc_size); |
151 | 52 | } |
152 | 768 | } |
153 | | |
154 | | void TLS_CBC_HMAC_AEAD_Encryption::cbc_encrypt_record( |
155 | | secure_vector<uint8_t>& buffer, size_t offset, size_t padding_length) |
156 | 768 | { |
157 | 768 | // We always do short padding: |
158 | 768 | BOTAN_ASSERT_NOMSG(padding_length <= 16); |
159 | 768 | |
160 | 768 | buffer.resize(buffer.size() + padding_length); |
161 | 768 | |
162 | 768 | const uint8_t padding_val = static_cast<uint8_t>(padding_length - 1); |
163 | 768 | |
164 | 768 | CT::poison(&padding_val, 1); |
165 | 768 | CT::poison(&padding_length, 1); |
166 | 768 | CT::poison(buffer.data(), buffer.size()); |
167 | 768 | |
168 | 768 | const size_t last_block_starts = buffer.size() - block_size(); |
169 | 768 | const size_t padding_starts = buffer.size() - padding_length; |
170 | 11.1k | for(size_t i = last_block_starts; i != buffer.size(); ++i) |
171 | 10.3k | { |
172 | 10.3k | auto add_padding = CT::Mask<uint8_t>(CT::Mask<size_t>::is_gte(i, padding_starts)); |
173 | 10.3k | buffer[i] = add_padding.select(padding_val, buffer[i]); |
174 | 10.3k | } |
175 | 768 | |
176 | 768 | CT::unpoison(padding_val); |
177 | 768 | CT::unpoison(padding_length); |
178 | 768 | CT::unpoison(buffer.data(), buffer.size()); |
179 | 768 | |
180 | 768 | cbc().start(cbc_state()); |
181 | 768 | cbc().process(&buffer[offset], buffer.size() - offset); |
182 | 768 | |
183 | 768 | cbc_state().assign(buffer.data() + (buffer.size() - block_size()), buffer.data() + buffer.size()); |
184 | 768 | } |
185 | | |
186 | | size_t TLS_CBC_HMAC_AEAD_Encryption::output_length(size_t input_length) const |
187 | 768 | { |
188 | 768 | return round_up(input_length + 1 + (use_encrypt_then_mac() ? 0 : tag_size()), block_size()) + |
189 | 768 | (use_encrypt_then_mac() ? tag_size() : 0); |
190 | 768 | } |
191 | | |
192 | | void TLS_CBC_HMAC_AEAD_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset) |
193 | 768 | { |
194 | 768 | update(buffer, offset); |
195 | 768 | |
196 | 768 | const size_t msg_size = msg().size(); |
197 | 768 | |
198 | 768 | const size_t input_size = msg_size + 1 + (use_encrypt_then_mac() ? 0 : tag_size()); |
199 | 768 | const size_t enc_size = round_up(input_size, block_size()); |
200 | 768 | BOTAN_DEBUG_ASSERT(enc_size % block_size() == 0); |
201 | 768 | |
202 | 768 | const uint8_t padding_val = static_cast<uint8_t>(enc_size - input_size); |
203 | 768 | const size_t padding_length = static_cast<size_t>(padding_val) + 1; |
204 | 768 | |
205 | 768 | buffer.reserve(offset + msg_size + padding_length + tag_size()); |
206 | 768 | buffer.resize(offset + msg_size); |
207 | 768 | copy_mem(&buffer[offset], msg().data(), msg_size); |
208 | 768 | |
209 | 768 | mac().update(assoc_data()); |
210 | 768 | |
211 | 768 | if(use_encrypt_then_mac()) |
212 | 52 | { |
213 | 52 | if(iv_size() > 0) |
214 | 52 | { |
215 | 52 | mac().update(cbc_state()); |
216 | 52 | } |
217 | 52 | |
218 | 52 | cbc_encrypt_record(buffer, offset, padding_length); |
219 | 52 | mac().update(&buffer[offset], enc_size); |
220 | 52 | buffer.resize(buffer.size() + tag_size()); |
221 | 52 | mac().final(&buffer[buffer.size() - tag_size()]); |
222 | 52 | } |
223 | 716 | else |
224 | 716 | { |
225 | 716 | mac().update(&buffer[offset], msg_size); |
226 | 716 | buffer.resize(buffer.size() + tag_size()); |
227 | 716 | mac().final(&buffer[buffer.size() - tag_size()]); |
228 | 716 | cbc_encrypt_record(buffer, offset, padding_length); |
229 | 716 | } |
230 | 768 | } |
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 | | */ |
243 | | uint16_t check_tls_cbc_padding(const uint8_t record[], size_t record_len) |
244 | 494 | { |
245 | 494 | if(record_len == 0 || record_len > 0xFFFF) |
246 | 0 | return 0; |
247 | 494 | |
248 | 494 | const uint16_t rec16 = static_cast<uint16_t>(record_len); |
249 | 494 | |
250 | 494 | /* |
251 | 494 | * TLS v1.0 and up require all the padding bytes be the same value |
252 | 494 | * and allows up to 255 bytes. |
253 | 494 | */ |
254 | 494 | |
255 | 494 | const uint16_t to_check = std::min<uint16_t>(256, static_cast<uint16_t>(record_len)); |
256 | 494 | const uint8_t pad_byte = record[record_len-1]; |
257 | 494 | const uint16_t pad_bytes = 1 + pad_byte; |
258 | 494 | |
259 | 494 | auto pad_invalid = CT::Mask<uint16_t>::is_lt(rec16, pad_bytes); |
260 | 494 | |
261 | 75.7k | for(uint16_t i = rec16 - to_check; i != rec16; ++i) |
262 | 75.2k | { |
263 | 75.2k | const uint16_t offset = rec16 - i; |
264 | 75.2k | const auto in_pad_range = CT::Mask<uint16_t>::is_lte(offset, pad_bytes); |
265 | 75.2k | const auto pad_correct = CT::Mask<uint16_t>::is_equal(record[i], pad_byte); |
266 | 75.2k | pad_invalid |= in_pad_range & ~pad_correct; |
267 | 75.2k | } |
268 | 494 | |
269 | 494 | return pad_invalid.if_not_set_return(pad_bytes); |
270 | 494 | } |
271 | | |
272 | | void TLS_CBC_HMAC_AEAD_Decryption::cbc_decrypt_record(uint8_t record_contents[], size_t record_len) |
273 | 269 | { |
274 | 269 | if(record_len == 0 || record_len % block_size() != 0) |
275 | 0 | throw Decoding_Error("Received TLS CBC ciphertext with invalid length"); |
276 | 269 | |
277 | 269 | cbc().start(cbc_state()); |
278 | 269 | cbc_state().assign(record_contents + record_len - block_size(), |
279 | 269 | record_contents + record_len); |
280 | 269 | |
281 | 269 | cbc().process(record_contents, record_len); |
282 | 269 | } |
283 | | |
284 | | size_t TLS_CBC_HMAC_AEAD_Decryption::output_length(size_t) const |
285 | 320 | { |
286 | 320 | /* |
287 | 320 | * We don't know this because the padding is arbitrary |
288 | 320 | */ |
289 | 320 | return 0; |
290 | 320 | } |
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 | | */ |
334 | | void TLS_CBC_HMAC_AEAD_Decryption::perform_additional_compressions(size_t plen, size_t padlen) |
335 | 269 | { |
336 | 269 | uint16_t block_size; |
337 | 269 | uint16_t max_bytes_in_first_block; |
338 | 269 | if(mac().name() == "HMAC(SHA-384)") |
339 | 71 | { |
340 | 71 | block_size = 128; |
341 | 71 | max_bytes_in_first_block = 111; |
342 | 71 | } |
343 | 198 | else |
344 | 198 | { |
345 | 198 | block_size = 64; |
346 | 198 | max_bytes_in_first_block = 55; |
347 | 198 | } |
348 | 269 | // number of maximum MACed bytes |
349 | 269 | const uint16_t L1 = static_cast<uint16_t>(13 + plen - tag_size()); |
350 | 269 | // number of current MACed bytes (L1 - padlen) |
351 | 269 | // Here the Lucky 13 paper is different because the padlen length in the paper |
352 | 269 | // does not count the last message byte. |
353 | 269 | const uint16_t L2 = static_cast<uint16_t>(13 + plen - padlen - tag_size()); |
354 | 269 | // From the paper, for SHA-256/SHA-1 compute: ceil((L1-55)/64) and ceil((L2-55)/64) |
355 | 269 | // ceil((L1-55)/64) = floor((L1+64-1-55)/64) |
356 | 269 | // Here we compute number of compressions for SHA-* in general |
357 | 269 | const uint16_t max_compresssions = ( (L1 + block_size - 1 - max_bytes_in_first_block) / block_size); |
358 | 269 | const uint16_t current_compressions = ((L2 + block_size - 1 - max_bytes_in_first_block) / block_size); |
359 | 269 | // number of additional compressions we have to perform |
360 | 269 | const uint16_t add_compressions = max_compresssions - current_compressions; |
361 | 269 | const uint16_t equal = CT::Mask<uint16_t>::is_equal(max_compresssions, current_compressions).if_set_return(1); |
362 | 269 | // We compute the data length we need to achieve the number of compressions. |
363 | 269 | // If there are no compressions, we just add 55/111 dummy bytes so that no |
364 | 269 | // compression is performed. |
365 | 269 | const uint16_t data_len = block_size * add_compressions + equal * max_bytes_in_first_block; |
366 | 269 | std::vector<uint8_t> data(data_len); |
367 | 269 | mac().update(data); |
368 | 269 | // we do not need to clear the MAC since the connection is broken anyway |
369 | 269 | } |
370 | | |
371 | | void TLS_CBC_HMAC_AEAD_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset) |
372 | 320 | { |
373 | 320 | update(buffer, offset); |
374 | 320 | buffer.resize(offset); |
375 | 320 | |
376 | 320 | const size_t record_len = msg().size(); |
377 | 320 | uint8_t* record_contents = msg().data(); |
378 | 320 | |
379 | 320 | // This early exit does not leak info because all the values compared are public |
380 | 320 | if(record_len < tag_size() || |
381 | 320 | (record_len - (use_encrypt_then_mac() ? tag_size() : 0)) % block_size() != 0) |
382 | 48 | { |
383 | 48 | throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure"); |
384 | 48 | } |
385 | 272 | |
386 | 272 | if(use_encrypt_then_mac()) |
387 | 3 | { |
388 | 3 | const size_t enc_size = record_len - tag_size(); |
389 | 3 | const size_t enc_iv_size = enc_size + iv_size(); |
390 | 3 | |
391 | 3 | BOTAN_ASSERT_NOMSG(enc_iv_size <= 0xFFFF); |
392 | 3 | |
393 | 3 | mac().update(assoc_data_with_len(static_cast<uint16_t>(enc_iv_size))); |
394 | 3 | if(iv_size() > 0) |
395 | 3 | { |
396 | 3 | mac().update(cbc_state()); |
397 | 3 | } |
398 | 3 | mac().update(record_contents, enc_size); |
399 | 3 | |
400 | 3 | std::vector<uint8_t> mac_buf(tag_size()); |
401 | 3 | mac().final(mac_buf.data()); |
402 | 3 | |
403 | 3 | const size_t mac_offset = enc_size; |
404 | 3 | |
405 | 3 | const bool mac_ok = constant_time_compare(&record_contents[mac_offset], mac_buf.data(), tag_size()); |
406 | 3 | |
407 | 3 | if(!mac_ok) |
408 | 3 | { |
409 | 3 | throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure"); |
410 | 3 | } |
411 | 0 | |
412 | 0 | cbc_decrypt_record(record_contents, enc_size); |
413 | 0 |
|
414 | 0 | // 0 if padding was invalid, otherwise 1 + padding_bytes |
415 | 0 | const uint16_t pad_size = check_tls_cbc_padding(record_contents, enc_size); |
416 | 0 |
|
417 | 0 | // No oracle here, whoever sent us this had the key since MAC check passed |
418 | 0 | if(pad_size == 0) |
419 | 0 | { |
420 | 0 | throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure"); |
421 | 0 | } |
422 | 0 | |
423 | 0 | const uint8_t* plaintext_block = &record_contents[0]; |
424 | 0 | const size_t plaintext_length = enc_size - pad_size; |
425 | 0 |
|
426 | 0 | buffer.insert(buffer.end(), plaintext_block, plaintext_block + plaintext_length); |
427 | 0 | } |
428 | 269 | else |
429 | 269 | { |
430 | 269 | cbc_decrypt_record(record_contents, record_len); |
431 | 269 | |
432 | 269 | CT::poison(record_contents, record_len); |
433 | 269 | |
434 | 269 | // 0 if padding was invalid, otherwise 1 + padding_bytes |
435 | 269 | uint16_t pad_size = check_tls_cbc_padding(record_contents, record_len); |
436 | 269 | |
437 | 269 | /* |
438 | 269 | This mask is zero if there is not enough room in the packet to get a valid MAC. |
439 | 269 | |
440 | 269 | We have to accept empty packets, since otherwise we are not compatible |
441 | 269 | with how OpenSSL's countermeasure for fixing BEAST in TLS 1.0 CBC works |
442 | 269 | (sending empty records, instead of 1/(n-1) splitting) |
443 | 269 | */ |
444 | 269 | |
445 | 269 | // We know the cast cannot overflow as pad_size <= 256 && tag_size <= 32 |
446 | 269 | const auto size_ok_mask = CT::Mask<uint16_t>::is_lte( |
447 | 269 | static_cast<uint16_t>(tag_size() + pad_size), |
448 | 269 | static_cast<uint16_t>(record_len)); |
449 | 269 | |
450 | 269 | pad_size = size_ok_mask.if_set_return(pad_size); |
451 | 269 | |
452 | 269 | CT::unpoison(record_contents, record_len); |
453 | 269 | |
454 | 269 | /* |
455 | 269 | This is unpoisoned sooner than it should. The pad_size leaks to plaintext_length and |
456 | 269 | then to the timing channel in the MAC computation described in the Lucky 13 paper. |
457 | 269 | */ |
458 | 269 | CT::unpoison(pad_size); |
459 | 269 | |
460 | 269 | const uint8_t* plaintext_block = &record_contents[0]; |
461 | 269 | const uint16_t plaintext_length = static_cast<uint16_t>(record_len - tag_size() - pad_size); |
462 | 269 | |
463 | 269 | mac().update(assoc_data_with_len(plaintext_length)); |
464 | 269 | mac().update(plaintext_block, plaintext_length); |
465 | 269 | |
466 | 269 | std::vector<uint8_t> mac_buf(tag_size()); |
467 | 269 | mac().final(mac_buf.data()); |
468 | 269 | |
469 | 269 | const size_t mac_offset = record_len - (tag_size() + pad_size); |
470 | 269 | |
471 | 269 | const bool mac_ok = constant_time_compare(&record_contents[mac_offset], mac_buf.data(), tag_size()); |
472 | 269 | |
473 | 269 | const auto ok_mask = size_ok_mask & CT::Mask<uint16_t>::expand(mac_ok) & CT::Mask<uint16_t>::expand(pad_size); |
474 | 269 | |
475 | 269 | CT::unpoison(ok_mask); |
476 | 269 | |
477 | 269 | if(ok_mask.is_set()) |
478 | 0 | { |
479 | 0 | buffer.insert(buffer.end(), plaintext_block, plaintext_block + plaintext_length); |
480 | 0 | } |
481 | 269 | else |
482 | 269 | { |
483 | 269 | perform_additional_compressions(record_len, pad_size); |
484 | 269 | |
485 | 269 | /* |
486 | 269 | * In DTLS case we have to finish computing the MAC since we require the |
487 | 269 | * MAC state be reset for future packets. This extra timing channel may |
488 | 269 | * be exploitable in a Lucky13 variant. |
489 | 269 | */ |
490 | 269 | if(is_datagram_protocol()) |
491 | 0 | mac().final(mac_buf); |
492 | 269 | throw TLS_Exception(Alert::BAD_RECORD_MAC, "Message authentication failure"); |
493 | 269 | } |
494 | 269 | } |
495 | 272 | } |
496 | | |
497 | | } |
498 | | |
499 | | } |