11 #include <botan/internal/tls_cbc.h>
12 #include <botan/cbc.h>
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>
28 std::unique_ptr<BlockCipher> cipher,
29 std::unique_ptr<MessageAuthenticationCode> mac,
33 bool use_encrypt_then_mac) :
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)
40 m_tag_size = mac->output_length();
41 m_block_size = cipher->block_size();
47 m_mac = std::move(mac);
71 return "TLS_CBC(" + m_cipher_name +
"," + m_mac_name +
")";
81 if(m_cbc_state.empty())
91 void TLS_CBC_HMAC_AEAD_Mode::key_schedule(
const uint8_t key[],
size_t keylen)
95 if(keylen != m_cipher_keylen + m_mac_keylen)
99 cbc().
set_key(&key[m_mac_keylen], m_cipher_keylen);
102 void TLS_CBC_HMAC_AEAD_Mode::start_msg(
const uint8_t nonce[],
size_t nonce_len)
113 m_cbc_state.assign(nonce, nonce + nonce_len);
119 m_msg.insert(m_msg.end(), buf, buf + sz);
125 std::vector<uint8_t> ad = m_ad;
136 m_ad.assign(ad, ad + ad_len);
148 assoc_data()[11] = get_byte<uint16_t>(0, enc_size);
149 assoc_data()[12] = get_byte<uint16_t>(1, enc_size);
153 void TLS_CBC_HMAC_AEAD_Encryption::cbc_encrypt_record(uint8_t buf[],
size_t buf_size)
170 buffer.resize(offset);
171 const size_t header_size = offset;
173 buffer.insert(buffer.end(),
msg().begin(),
msg().end());
177 const size_t pad_val = enc_size - input_size;
181 "Buffer is an even multiple of block size");
192 for(
size_t i = 0; i != pad_val + 1; ++i)
193 buffer.push_back(static_cast<uint8_t>(pad_val));
194 cbc_encrypt_record(&buffer[header_size], enc_size);
203 buffer.resize(buffer.size() +
tag_size());
208 for(
size_t i = 0; i != pad_val + 1; ++i)
209 buffer.push_back(static_cast<uint8_t>(pad_val));
210 cbc_encrypt_record(&buffer[header_size], buf_size);
227 if(record_len == 0 || record_len > 0xFFFF)
230 const uint16_t rec16 =
static_cast<uint16_t
>(record_len);
237 const uint16_t to_check = std::min<uint16_t>(256,
static_cast<uint16_t
>(record_len));
238 const uint8_t pad_byte = record[record_len-1];
239 const uint16_t pad_bytes = 1 + pad_byte;
243 for(uint16_t i = rec16 - to_check; i != rec16; ++i)
245 const uint16_t offset = rec16 - i;
248 pad_invalid |= in_pad_range & ~pad_correct;
251 return pad_invalid.if_not_set_return(pad_bytes);
254 void TLS_CBC_HMAC_AEAD_Decryption::cbc_decrypt_record(uint8_t record_contents[],
size_t record_len)
256 if(record_len == 0 || record_len %
block_size() != 0)
257 throw Decoding_Error(
"Received TLS CBC ciphertext with invalid length");
261 record_contents + record_len);
316 void TLS_CBC_HMAC_AEAD_Decryption::perform_additional_compressions(
size_t plen,
size_t padlen)
319 uint16_t max_bytes_in_first_block;
320 if(
mac().
name() ==
"HMAC(SHA-384)")
323 max_bytes_in_first_block = 111;
328 max_bytes_in_first_block = 55;
331 const uint16_t L1 =
static_cast<uint16_t
>(13 + plen -
tag_size());
335 const uint16_t L2 =
static_cast<uint16_t
>(13 + plen - padlen -
tag_size());
339 const uint16_t max_compresssions = ( (L1 + block_size - 1 - max_bytes_in_first_block) / block_size);
340 const uint16_t current_compressions = ((L2 + block_size - 1 - max_bytes_in_first_block) / block_size);
342 const uint16_t add_compressions = max_compresssions - current_compressions;
347 const uint16_t data_len = block_size * add_compressions + equal * max_bytes_in_first_block;
348 std::vector<uint8_t> data(data_len);
356 buffer.resize(offset);
358 const size_t record_len =
msg().size();
359 uint8_t* record_contents =
msg().data();
370 const size_t enc_size = record_len -
tag_size();
371 const size_t enc_iv_size = enc_size +
iv_size();
382 std::vector<uint8_t> mac_buf(
tag_size());
385 const size_t mac_offset = enc_size;
394 cbc_decrypt_record(record_contents, enc_size);
405 const uint8_t* plaintext_block = &record_contents[0];
406 const size_t plaintext_length = enc_size - pad_size;
408 buffer.insert(buffer.end(), plaintext_block, plaintext_block + plaintext_length);
412 cbc_decrypt_record(record_contents, record_len);
429 static_cast<uint16_t>(
tag_size() + pad_size),
430 static_cast<uint16_t>(record_len));
432 pad_size = size_ok_mask.if_set_return(pad_size);
442 const uint8_t* plaintext_block = &record_contents[0];
443 const uint16_t plaintext_length =
static_cast<uint16_t
>(record_len -
tag_size() - pad_size);
446 mac().
update(plaintext_block, plaintext_length);
448 std::vector<uint8_t> mac_buf(
tag_size());
451 const size_t mac_offset = record_len - (
tag_size() + pad_size);
461 buffer.insert(buffer.end(), plaintext_block, plaintext_block + plaintext_length);
465 perform_additional_compressions(record_len, pad_size);
size_t block_size() const
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
void clear() overridefinal
Cipher_Mode & cbc() const
void update(secure_vector< uint8_t > &buffer, size_t offset=0)
constexpr uint8_t get_byte(size_t byte_num, T input)
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)
size_t tag_size() const overridefinal
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
#define BOTAN_ASSERT_NOMSG(expr)
void poison(const T *p, size_t n)
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
MessageAuthenticationCode & mac() const
std::string m_cipher_name
void start(const std::vector< uint8_t, Alloc > &nonce)
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[])
static Mask< T > is_lte(T x, T y)
static Mask< T > expand(T v)
std::vector< T, secure_allocator< T >> secure_vector
bool supports_explicit_cbc_ivs() const
void set_key(const SymmetricKey &key)
Key_Length_Specification key_spec() const overridefinal
std::vector< uint8_t > & assoc_data()
bool use_encrypt_then_mac() const
size_t update_granularity() const overridefinal
size_t process(uint8_t buf[], size_t sz) overridefinal
virtual size_t process(uint8_t msg[], size_t msg_len)=0
std::vector< uint8_t > assoc_data_with_len(uint16_t len)
void update(const uint8_t in[], size_t length)
uint16_t check_tls_cbc_padding(const uint8_t record[], size_t record_len)
size_t output_length(size_t input_length) const override
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
bool is_datagram_protocol() const
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)
size_t round_up(size_t n, size_t align_to)
static Mask< T > is_equal(T x, T y)
bool is_datagram_protocol() const
size_t output_length(size_t input_length) const override
void set_associated_data(const uint8_t ad[], size_t ad_len) override
static Mask< T > is_lt(T x, T y)
void reset() overridefinal