9#include <botan/exceptn.h>
10#include <botan/loadstor.h>
11#include <botan/internal/bit_ops.h>
17 m_block_size(m_cipher->block_size()),
18 m_ctr_size(m_block_size),
19 m_ctr_blocks(m_cipher->parallel_bytes() / m_block_size),
20 m_counter(m_cipher->parallel_bytes()),
21 m_pad(m_counter.size()),
28 m_block_size(m_cipher->block_size()),
30 m_ctr_blocks(m_cipher->parallel_bytes() / m_block_size),
31 m_counter(m_cipher->parallel_bytes()),
32 m_pad(m_counter.size()),
36 "Invalid CTR-BE counter size");
55 return (iv_len <= m_block_size);
60 return m_cipher->key_spec();
65 return new CTR_BE(m_cipher->clone(), m_ctr_size);
68void CTR_BE::key_schedule(
const uint8_t key[],
size_t key_len)
70 m_cipher->set_key(key, key_len);
78 if(m_ctr_size == m_block_size)
79 return (
"CTR-BE(" + m_cipher->name() +
")");
81 return (
"CTR-BE(" + m_cipher->name() +
"," + std::to_string(m_ctr_size) +
")");
89 const uint8_t* pad_bits = &m_pad[0];
90 const size_t pad_size = m_pad.size();
94 const size_t avail = pad_size - m_pad_pos;
95 const size_t take = std::min(length, avail);
96 xor_buf(out, in, pad_bits + m_pad_pos, take);
104 add_counter(m_ctr_blocks);
105 m_cipher->encrypt_n(m_counter.data(), m_pad.data(), m_ctr_blocks);
110 while(length >= pad_size)
112 xor_buf(out, in, pad_bits, pad_size);
117 add_counter(m_ctr_blocks);
118 m_cipher->encrypt_n(m_counter.data(), m_pad.data(), m_ctr_blocks);
121 xor_buf(out, in, pad_bits, length);
130 m_iv.resize(m_block_size);
137void CTR_BE::add_counter(
const uint64_t counter)
139 const size_t ctr_size = m_ctr_size;
140 const size_t ctr_blocks = m_ctr_blocks;
141 const size_t BS = m_block_size;
145 const size_t off = (BS - 4);
146 const uint32_t low32 =
static_cast<uint32_t
>(counter +
load_be<uint32_t>(&m_counter[off], 0));
148 for(
size_t i = 0; i != ctr_blocks; ++i)
150 store_be(uint32_t(low32 + i), &m_counter[i*BS+off]);
153 else if(ctr_size == 8)
155 const size_t off = (BS - 8);
158 for(
size_t i = 0; i != ctr_blocks; ++i)
160 store_be(uint64_t(low64 + i), &m_counter[i*BS+off]);
163 else if(ctr_size == 16)
165 const size_t off = (BS - 16);
169 b0 += (b1 < counter) ? 1 : 0;
171 for(
size_t i = 0; i != ctr_blocks; ++i)
174 store_be(b1, &m_counter[i*BS+off+8]);
181 for(
size_t i = 0; i != ctr_blocks; ++i)
183 uint64_t local_counter = counter;
184 uint16_t
carry =
static_cast<uint8_t
>(local_counter);
185 for(
size_t j = 0; (
carry || local_counter) && j != ctr_size; ++j)
187 const size_t off = i*BS + (BS-1-j);
188 const uint16_t cnt =
static_cast<uint16_t
>(m_counter[off]) +
carry;
189 m_counter[off] =
static_cast<uint8_t
>(cnt);
190 local_counter = (local_counter >> 8);
191 carry = (cnt >> 8) +
static_cast<uint8_t
>(local_counter);
201 const uint64_t base_counter = m_ctr_blocks * (offset / m_counter.size());
206 const size_t BS = m_block_size;
210 if(m_ctr_size == 4 && BS >= 8)
217 while(written < m_ctr_blocks)
219 copy_mem(&m_counter[written*BS], &m_counter[0], BS*written);
225 for(
size_t i = 1; i != m_ctr_blocks; ++i)
227 copy_mem(&m_counter[i*BS], &m_counter[0], BS - 4);
231 for(
size_t i = 1; i != m_ctr_blocks; ++i)
233 const uint32_t c =
static_cast<uint32_t
>(low32 + i);
234 store_be(c, &m_counter[(BS-4)+i*BS]);
240 for(
size_t i = 1; i != m_ctr_blocks; ++i)
244 for(
size_t j = 0; j != m_ctr_size; ++j)
245 if(++m_counter[i*BS + (BS - 1 - j)])
251 add_counter(base_counter);
253 m_cipher->encrypt_n(m_counter.data(), m_pad.data(), m_ctr_blocks);
254 m_pad_pos = offset % m_counter.size();
#define BOTAN_ARG_CHECK(expr, msg)
void cipher(const uint8_t in[], uint8_t out[], size_t length) override
size_t default_iv_length() const override
Key_Length_Specification key_spec() const override
bool valid_iv_length(size_t iv_len) const override
void set_iv(const uint8_t iv[], size_t iv_len) override
void seek(uint64_t offset) override
std::string name() const override
CTR_BE(BlockCipher *cipher)
CTR_BE * clone() const override
void verify_key_set(bool cond) const
void zeroise(std::vector< T, Alloc > &vec)
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
void zap(std::vector< T, Alloc > &vec)
void store_be(uint16_t in, uint8_t out[2])
void carry(int64_t &h0, int64_t &h1)
void copy_mem(T *out, const T *in, size_t n)
uint32_t load_be< uint32_t >(const uint8_t in[], size_t off)
uint64_t load_be< uint64_t >(const uint8_t in[], size_t off)
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
constexpr bool is_power_of_2(T arg)