11#include <botan/internal/tls_cbc.h>
13#include <botan/block_cipher.h>
15#include <botan/tls_alert.h>
16#include <botan/tls_exceptn.h>
17#include <botan/tls_version.h>
18#include <botan/internal/cbc.h>
19#include <botan/internal/ct_utils.h>
20#include <botan/internal/loadstor.h>
21#include <botan/internal/rounding.h>
31 std::unique_ptr<BlockCipher> cipher,
32 std::unique_ptr<MessageAuthenticationCode>
mac,
37 m_mac(std::move(
mac)),
38 m_cipher_name(cipher->
name()),
39 m_mac_name(m_mac->
name()),
42 m_iv_size(m_block_size),
50 auto null_padding = std::make_unique<Null_Padding>();
52 m_cbc = std::make_unique<CBC_Encryption>(std::move(cipher), std::move(null_padding));
54 m_cbc = std::make_unique<CBC_Decryption>(std::move(cipher), std::move(null_padding));
71 return "TLS_CBC(" + m_cipher_name +
"," + m_mac_name +
")";
83 if(m_cbc_state.empty()) {
97void TLS_CBC_HMAC_AEAD_Mode::key_schedule(std::span<const uint8_t> key) {
100 if(key.size() != m_cipher_keylen + m_mac_keylen) {
105 cbc().
set_key(key.subspan(m_mac_keylen, m_cipher_keylen));
108void TLS_CBC_HMAC_AEAD_Mode::start_msg(
const uint8_t nonce[],
size_t nonce_len) {
110 throw Invalid_IV_Length(
name(), nonce_len);
116 m_cbc_state.assign(nonce, nonce + nonce_len);
120size_t TLS_CBC_HMAC_AEAD_Mode::process_msg(uint8_t buf[],
size_t sz) {
121 m_msg.insert(m_msg.end(), buf, buf + sz);
126 std::vector<uint8_t> ad = m_ad;
134 BOTAN_ARG_CHECK(idx == 0,
"TLS 1.2 CBC/HMAC: cannot handle non-zero index in set_associated_data_n");
135 if(ad.size() != 13) {
138 m_ad.assign(ad.begin(), ad.end());
142 std::unique_ptr<MessageAuthenticationCode>
mac,
170 size_t padding_length) {
174 buffer.resize(buffer.size() + padding_length);
176 const uint8_t padding_val =
static_cast<uint8_t
>(padding_length - 1);
182 const size_t last_block_starts = buffer.size() -
block_size();
183 const size_t padding_starts = buffer.size() - padding_length;
184 for(
size_t i = last_block_starts; i != buffer.size(); ++i) {
186 buffer[i] = add_padding.select(padding_val, buffer[i]);
194 cbc().
process(&buffer[offset], buffer.size() - offset);
196 cbc_state().assign(buffer.data() + (buffer.size() -
block_size()), buffer.data() + buffer.size());
207 const size_t msg_size =
msg().size();
213 const uint8_t padding_val =
static_cast<uint8_t
>(enc_size - input_size);
214 const size_t padding_length =
static_cast<size_t>(padding_val) + 1;
216 buffer.reserve(offset + msg_size + padding_length +
tag_size());
217 buffer.resize(offset + msg_size);
229 cbc_encrypt_record(buffer, offset, padding_length);
231 buffer.resize(buffer.size() +
tag_size());
237 buffer.resize(buffer.size() +
tag_size());
239 cbc_encrypt_record(buffer, offset, padding_length);
255 if(record_len == 0 || record_len > 0xFFFF) {
259 const uint16_t rec16 =
static_cast<uint16_t
>(record_len);
266 const uint16_t to_check = std::min<uint16_t>(256,
static_cast<uint16_t
>(record_len));
267 const uint8_t pad_byte = record[record_len - 1];
268 const uint16_t pad_bytes = 1 + pad_byte;
272 for(uint16_t i = rec16 - to_check; i != rec16; ++i) {
273 const uint16_t offset = rec16 - i;
276 pad_invalid |= in_pad_range & ~pad_correct;
279 return pad_invalid.if_not_set_return(pad_bytes);
283 std::unique_ptr<MessageAuthenticationCode>
mac,
296void TLS_CBC_HMAC_AEAD_Decryption::cbc_decrypt_record(uint8_t record_contents[],
size_t record_len) {
297 if(record_len == 0 || record_len %
block_size() != 0) {
298 throw Decoding_Error(
"Received TLS CBC ciphertext with invalid length");
302 cbc_state().assign(record_contents + record_len -
block_size(), record_contents + record_len);
356void TLS_CBC_HMAC_AEAD_Decryption::perform_additional_compressions(
size_t plen,
size_t padlen) {
357 const bool is_sha384 =
mac().
name() ==
"HMAC(SHA-384)";
358 const uint16_t
block_size = is_sha384 ? 128 : 64;
359 const uint16_t max_bytes_in_first_block = is_sha384 ? 111 : 55;
362 const uint16_t L1 =
static_cast<uint16_t
>(13 + plen -
tag_size());
366 const uint16_t L2 =
static_cast<uint16_t
>(13 + plen - padlen -
tag_size());
370 const uint16_t max_compresssions = ((L1 +
block_size - 1 - max_bytes_in_first_block) /
block_size);
371 const uint16_t current_compressions = ((L2 +
block_size - 1 - max_bytes_in_first_block) /
block_size);
373 const uint16_t add_compressions = max_compresssions - current_compressions;
378 const uint16_t data_len =
block_size * add_compressions + equal * max_bytes_in_first_block;
379 std::vector<uint8_t> data(data_len);
386 buffer.resize(offset);
388 const size_t record_len =
msg().size();
389 uint8_t* record_contents =
msg().data();
393 throw TLS_Exception(Alert::BadRecordMac,
"Message authentication failure");
397 const size_t enc_size = record_len -
tag_size();
398 const size_t enc_iv_size = enc_size +
iv_size();
408 std::vector<uint8_t> mac_buf(
tag_size());
411 const size_t mac_offset = enc_size;
415 if(!mac_ok.as_bool()) {
416 throw TLS_Exception(Alert::BadRecordMac,
"Message authentication failure");
419 cbc_decrypt_record(record_contents, enc_size);
426 throw TLS_Exception(Alert::BadRecordMac,
"Message authentication failure");
429 const uint8_t* plaintext_block = &record_contents[0];
430 const size_t plaintext_length = enc_size - pad_size;
432 buffer.insert(buffer.end(), plaintext_block, plaintext_block + plaintext_length);
434 cbc_decrypt_record(record_contents, record_len);
450 const auto size_ok_mask =
453 pad_size = size_ok_mask.if_set_return(pad_size);
463 const uint8_t* plaintext_block = &record_contents[0];
464 const uint16_t plaintext_length =
static_cast<uint16_t
>(record_len -
tag_size() - pad_size);
467 mac().
update(plaintext_block, plaintext_length);
469 std::vector<uint8_t> mac_buf(
tag_size());
472 const size_t mac_offset = record_len - (
tag_size() + pad_size);
480 if(ok_mask.as_bool()) {
481 buffer.insert(buffer.end(), plaintext_block, plaintext_block + plaintext_length);
483 perform_additional_compressions(record_len, pad_size);
493 throw TLS_Exception(Alert::BadRecordMac,
"Message authentication failure");
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_DEBUG_ASSERT(expr)
#define BOTAN_ARG_CHECK(expr, msg)
#define BOTAN_ASSERT(expr, assertion_made)
void update(const uint8_t in[], size_t length)
void final(uint8_t out[])
static constexpr Mask< T > is_lte(T x, T y)
static constexpr Mask< T > is_gte(T x, T y)
static constexpr Mask< T > expand(T v)
static constexpr Mask< T > is_equal(T x, T y)
static constexpr Mask< T > is_lt(T x, T y)
void start(std::span< const uint8_t > nonce)
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
void set_key(const OctetString &key)
TLS_CBC_HMAC_AEAD_Decryption(std::unique_ptr< BlockCipher > cipher, std::unique_ptr< MessageAuthenticationCode > mac, size_t cipher_keylen, size_t mac_keylen, const Protocol_Version &version, bool use_encrypt_then_mac)
size_t output_length(size_t input_length) const override
void set_associated_data_n(size_t idx, std::span< const uint8_t > ad) override
size_t output_length(size_t input_length) const override
TLS_CBC_HMAC_AEAD_Encryption(std::unique_ptr< BlockCipher > cipher, std::unique_ptr< MessageAuthenticationCode > mac, size_t cipher_keylen, size_t mac_keylen, const Protocol_Version &version, bool use_encrypt_then_mac)
size_t update_granularity() const final
void set_associated_data_n(size_t idx, std::span< const uint8_t > ad) override
size_t block_size() const
secure_vector< uint8_t > & cbc_state()
size_t mac_keylen() const
Key_Length_Specification key_spec() const final
bool has_keying_material() const final
size_t ideal_granularity() const final
std::vector< uint8_t > assoc_data_with_len(uint16_t len)
std::string name() const final
bool use_encrypt_then_mac() const
bool is_datagram_protocol() const
std::vector< uint8_t > & assoc_data()
secure_vector< uint8_t > & msg()
size_t cipher_keylen() const
TLS_CBC_HMAC_AEAD_Mode(const TLS_CBC_HMAC_AEAD_Mode &other)=delete
MessageAuthenticationCode & mac() const
~TLS_CBC_HMAC_AEAD_Mode() override
Cipher_Mode & cbc() const
size_t tag_size() const final
bool valid_nonce_length(size_t nl) const final
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
constexpr void unpoison(const T *p, size_t n)
constexpr void poison(const T *p, size_t n)
uint16_t check_tls_cbc_padding(const uint8_t record[], size_t record_len)
constexpr uint8_t get_byte(T input)
constexpr void copy_mem(T *out, const T *in, size_t n)
constexpr size_t round_up(size_t n, size_t align_to)
std::vector< T, secure_allocator< T > > secure_vector
constexpr uint16_t make_uint16(uint8_t i0, uint8_t i1)