11 #include <botan/internal/tls_cbc.h>
12 #include <botan/internal/rounding.h>
13 #include <botan/internal/ct_utils.h>
14 #include <botan/tls_alert.h>
15 #include <botan/tls_magic.h>
16 #include <botan/tls_exceptn.h>
27 const std::string& mac_name,
30 bool use_encrypt_then_mac) :
33 m_cipher_keylen(cipher_keylen),
34 m_mac_keylen(mac_keylen),
35 m_use_encrypt_then_mac(use_encrypt_then_mac)
40 m_tag_size = m_mac->output_length();
41 m_block_size = m_cipher->block_size();
43 m_iv_size = use_explicit_iv ? m_block_size : 0;
62 return "TLS_CBC(" + m_cipher_name +
"," + m_mac_name +
")";
72 if(m_cbc_state.empty())
82 void TLS_CBC_HMAC_AEAD_Mode::key_schedule(
const uint8_t key[],
size_t keylen)
86 if(keylen != m_cipher_keylen + m_mac_keylen)
90 mac().
set_key(&key[m_cipher_keylen], m_mac_keylen);
93 void TLS_CBC_HMAC_AEAD_Mode::start_msg(
const uint8_t nonce[],
size_t nonce_len)
104 m_cbc_state.assign(nonce, nonce + nonce_len);
110 m_msg.insert(m_msg.end(), buf, buf + sz);
116 std::vector<uint8_t> ad = m_ad;
126 throw Exception(
"Invalid TLS AEAD associated data length");
127 m_ad.assign(ad, ad + ad_len);
139 assoc_data()[11] = get_byte<uint16_t>(0, enc_size);
140 assoc_data()[12] = get_byte<uint16_t>(1, enc_size);
144 void TLS_CBC_HMAC_AEAD_Encryption::cbc_encrypt_record(uint8_t buf[],
size_t buf_size)
146 const size_t blocks = buf_size /
block_size();
152 for(
size_t i = 1; i < blocks; ++i)
171 buffer.resize(offset);
172 const size_t header_size = offset;
174 buffer.insert(buffer.end(),
msg().begin(),
msg().end());
178 const size_t pad_val = enc_size - input_size;
182 "Buffer is an even multiple of block size");
193 for(
size_t i = 0; i != pad_val + 1; ++i)
194 buffer.push_back(static_cast<uint8_t>(pad_val));
195 cbc_encrypt_record(&buffer[header_size], enc_size);
204 buffer.resize(buffer.size() +
tag_size());
209 for(
size_t i = 0; i != pad_val + 1; ++i)
210 buffer.push_back(static_cast<uint8_t>(pad_val));
211 cbc_encrypt_record(&buffer[header_size], buf_size);
229 uint16_t check_tls_padding(
const uint8_t record[],
size_t record_len)
236 const uint8_t pad_byte = record[(record_len-1)];
238 uint8_t pad_invalid = 0;
239 for(
size_t i = 0; i != record_len; ++i)
241 const size_t left = record_len - i - 2;
242 const uint8_t delim_mask = CT::is_less<uint16_t>(
static_cast<uint16_t
>(left), pad_byte) & 0xFF;
243 pad_invalid |= (delim_mask & (record[i] ^ pad_byte));
246 uint16_t pad_invalid_mask = CT::expand_mask<uint16_t>(pad_invalid);
247 return CT::select<uint16_t>(pad_invalid_mask, 0, pad_byte + 1);
252 void TLS_CBC_HMAC_AEAD_Decryption::cbc_decrypt_record(uint8_t record_contents[],
size_t record_len)
255 "Buffer is an even multiple of block size");
257 const size_t blocks = record_len /
block_size();
259 BOTAN_ASSERT(blocks >= 1,
"At least one ciphertext block");
261 uint8_t* buf = record_contents;
263 secure_vector<uint8_t> last_ciphertext(
block_size());
269 secure_vector<uint8_t> last_ciphertext2;
271 for(
size_t i = 1; i < blocks; ++i)
276 std::swap(last_ciphertext, last_ciphertext2);
279 cbc_state().assign(last_ciphertext.begin(), last_ciphertext.end());
332 void TLS_CBC_HMAC_AEAD_Decryption::perform_additional_compressions(
size_t plen,
size_t padlen)
335 uint16_t max_bytes_in_first_block;
336 if(
mac().
name() ==
"HMAC(SHA-384)")
339 max_bytes_in_first_block = 111;
344 max_bytes_in_first_block = 55;
347 const uint16_t L1 = 13 + plen -
tag_size();
351 const uint16_t L2 = 13 + plen - padlen -
tag_size();
355 const uint16_t max_compresssions = ( (L1 + block_size - 1 - max_bytes_in_first_block) / block_size);
356 const uint16_t current_compressions = ((L2 + block_size - 1 - max_bytes_in_first_block) / block_size);
358 const uint16_t add_compressions = max_compresssions - current_compressions;
359 const uint8_t equal =
CT::is_equal(max_compresssions, current_compressions) & 0x01;
363 const uint16_t data_len = block_size * add_compressions + equal * max_bytes_in_first_block;
364 secure_vector<uint8_t> data(data_len);
372 buffer.resize(offset);
374 const size_t record_len =
msg().size();
375 uint8_t* record_contents =
msg().data();
386 const size_t enc_size = record_len -
tag_size();
395 std::vector<uint8_t> mac_buf(
tag_size());
398 const size_t mac_offset = enc_size;
400 const bool mac_ok =
same_mem(&record_contents[mac_offset], mac_buf.data(),
tag_size());
407 cbc_decrypt_record(record_contents, enc_size);
410 uint16_t pad_size = check_tls_padding(record_contents, enc_size);
418 const uint8_t* plaintext_block = &record_contents[0];
419 const uint16_t plaintext_length = enc_size - pad_size;
421 buffer.insert(buffer.end(), plaintext_block, plaintext_block + plaintext_length);
427 cbc_decrypt_record(record_contents, record_len);
430 uint16_t pad_size = check_tls_padding(record_contents, record_len);
440 const uint16_t size_ok_mask = CT::is_lte<uint16_t>(
static_cast<uint16_t
>(
tag_size() + pad_size), static_cast<uint16_t>(record_len + 1));
441 pad_size &= size_ok_mask;
451 const uint8_t* plaintext_block = &record_contents[0];
452 const uint16_t plaintext_length =
static_cast<uint16_t
>(record_len -
tag_size() - pad_size);
455 mac().
update(plaintext_block, plaintext_length);
457 std::vector<uint8_t> mac_buf(
tag_size());
460 const size_t mac_offset = record_len - (
tag_size() + pad_size);
462 const bool mac_ok =
same_mem(&record_contents[mac_offset], mac_buf.data(),
tag_size());
464 const uint16_t ok_mask = size_ok_mask & CT::expand_mask<uint16_t>(mac_ok) & CT::expand_mask<uint16_t>(pad_size);
470 buffer.insert(buffer.end(), plaintext_block, plaintext_block + plaintext_length);
474 perform_additional_compressions(record_len, pad_size);
void xor_buf(T out[], const T in[], size_t length)
void encrypt(const uint8_t in[], uint8_t out[]) const
void decrypt(const uint8_t in[], uint8_t out[]) const
BlockCipher & cipher() const
TLS_CBC_HMAC_AEAD_Mode(const std::string &cipher_name, size_t cipher_keylen, const std::string &mac_name, size_t mac_keylen, bool use_explicit_iv, bool use_encrypt_then_mac)
bool same_mem(const T *p1, const T *p2, size_t n)
std::string m_cipher_name
size_t block_size() const
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
void clear() overridefinal
void update(secure_vector< uint8_t > &buffer, size_t offset=0)
size_t tag_size() const overridefinal
void poison(const T *p, size_t n)
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
MessageAuthenticationCode & mac() const
void set_associated_data(const uint8_t ad[], size_t ad_len) override
#define BOTAN_ASSERT(expr, assertion_made)
secure_vector< uint8_t > & cbc_state()
void final(uint8_t out[])
std::vector< T, secure_allocator< T >> secure_vector
void set_key(const SymmetricKey &key)
Key_Length_Specification key_spec() const overridefinal
std::vector< uint8_t > & assoc_data()
void copy_mem(T *out, const T *in, size_t n)
bool use_encrypt_then_mac() const
static std::unique_ptr< BlockCipher > create_or_throw(const std::string &algo_spec, const std::string &provider="")
size_t update_granularity() const overridefinal
size_t process(uint8_t buf[], size_t sz) overridefinal
std::vector< T > unlock(const secure_vector< T > &in)
std::vector< uint8_t > assoc_data_with_len(uint16_t len)
void update(const uint8_t in[], size_t length)
uint16_t make_uint16(uint8_t i0, uint8_t i1)
static std::unique_ptr< MessageAuthenticationCode > create_or_throw(const std::string &algo_spec, const std::string &provider="")
size_t output_length(size_t input_length) const override
uint8_t get_byte(size_t byte_num, T input)
void unpoison(const T *p, size_t n)
secure_vector< uint8_t > & msg()
std::string name() const overridefinal
bool valid_nonce_length(size_t nl) const overridefinal
size_t round_up(size_t n, size_t align_to)
size_t output_length(size_t input_length) const override
void set_associated_data(const uint8_t ad[], size_t ad_len) override
void reset() overridefinal