9#include <botan/internal/xts.h>
11#include <botan/exceptn.h>
12#include <botan/mem_ops.h>
13#include <botan/internal/fmt.h>
14#include <botan/internal/poly_dbl.h>
16#if defined(BOTAN_HAS_MODE_XTS_AVX512_CLMUL)
17 #include <botan/internal/cpuid.h>
23 m_cipher(std::move(
cipher)),
24 m_cipher_block_size(m_cipher->block_size()),
25 m_cipher_parallelism(m_cipher->parallel_bytes()),
26 m_tweak_blocks(m_cipher_parallelism / m_cipher_block_size) {
31 m_tweak_cipher = m_cipher->new_object();
36 m_tweak_cipher->clear();
41 return m_cipher_block_size;
45 return m_cipher_parallelism;
73 return m_cipher->has_keying_material() && m_tweak_cipher->has_keying_material();
76void XTS_Mode::key_schedule(std::span<const uint8_t> key) {
77 const size_t key_half = key.size() / 2;
79 if(key.size() % 2 == 1 || !m_cipher->valid_keylength(key_half)) {
83 m_cipher->set_key(key.first(key_half));
84 m_tweak_cipher->set_key(key.last(key_half));
87void XTS_Mode::start_msg(
const uint8_t nonce[],
size_t nonce_len) {
89 throw Invalid_IV_Length(
name(), nonce_len);
92 m_tweak.resize(m_cipher_parallelism);
93 clear_mem(m_tweak.data(), m_tweak.size());
94 copy_mem(m_tweak.data(), nonce, nonce_len);
95 m_tweak_cipher->encrypt(m_tweak.data());
102void XTS_Mode::update_tweak_block(uint8_t tweak[],
size_t BS,
size_t blocks_in_tweak) {
103#if defined(BOTAN_HAS_MODE_XTS_AVX512_CLMUL)
105 return update_tweak_block_avx512_clmul(
tweak, BS, blocks_in_tweak);
119 const size_t BS = m_tweak_cipher->block_size();
124 if(consumed == blocks_in_tweak) {
126 update_tweak_block(m_tweak.data(), BS, blocks_in_tweak);
134 copy_mem(m_tweak.data(), &m_tweak[(consumed * BS)], BS);
143size_t XTS_Encryption::process_msg(uint8_t buf[],
size_t sz) {
148 size_t blocks = sz / BS;
153 const size_t to_proc = std::min(blocks, blocks_in_tweak);
154 const size_t proc_bytes = to_proc * BS;
171 const size_t sz = buffer.size() - offset;
172 uint8_t* buf = buffer.data() + offset;
182 const size_t full_blocks = ((sz / BS) - 1) * BS;
183 const size_t final_bytes = sz - full_blocks;
184 BOTAN_ASSERT(final_bytes > BS && final_bytes < 2 * BS,
"Left over size in expected range");
187 buffer.resize(full_blocks + offset);
194 for(
size_t i = 0; i != final_bytes - BS; ++i) {
195 last[i] ^= last[i + BS];
196 last[i + BS] ^= last[i];
197 last[i] ^= last[i + BS];
212size_t XTS_Decryption::process_msg(uint8_t buf[],
size_t sz) {
217 size_t blocks = sz / BS;
222 const size_t to_proc = std::min(blocks, blocks_in_tweak);
223 const size_t proc_bytes = to_proc * BS;
240 const size_t sz = buffer.size() - offset;
241 uint8_t* buf = buffer.data() + offset;
251 const size_t full_blocks = ((sz / BS) - 1) * BS;
252 const size_t final_bytes = sz - full_blocks;
253 BOTAN_ASSERT(final_bytes > BS && final_bytes < 2 * BS,
"Left over size in expected range");
256 buffer.resize(full_blocks + offset);
263 for(
size_t i = 0; i != final_bytes - BS; ++i) {
264 last[i] ^= last[i + BS];
265 last[i + BS] ^= last[i];
266 last[i] ^= last[i + BS];
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_STATE_CHECK(expr)
#define BOTAN_ARG_CHECK(expr, msg)
#define BOTAN_ASSERT(expr, assertion_made)
void encrypt(const uint8_t in[], uint8_t out[]) const
void decrypt(const uint8_t in[], uint8_t out[]) const
virtual void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const =0
virtual void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const =0
static bool has(CPUID::Feature feat)
void update(T &buffer, size_t offset=0)
Key_Length_Specification multiple(size_t n) const
virtual std::string name() const =0
virtual Key_Length_Specification key_spec() const =0
size_t output_length(size_t input_length) const override
size_t output_length(size_t input_length) const override
const uint8_t * tweak() const
size_t ideal_granularity() const final
std::string name() const final
void update_tweak(size_t consumed)
size_t default_nonce_length() const final
size_t cipher_block_size() const
size_t update_granularity() const final
bool has_keying_material() const final
XTS_Mode(std::unique_ptr< BlockCipher > cipher)
const BlockCipher & cipher() const
size_t tweak_blocks() const
Key_Length_Specification key_spec() const final
bool valid_nonce_length(size_t n) const final
size_t minimum_final_size() const final
constexpr void copy_mem(T *out, const T *in, size_t n)
std::string fmt(std::string_view format, const T &... args)
void poly_double_n_le(uint8_t out[], const uint8_t in[], size_t n)
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
std::vector< T, secure_allocator< T > > secure_vector
void xts_compute_tweak_block(uint8_t tweak[], size_t BS, size_t blocks_in_tweak)
bool poly_double_supported_size(size_t n)
constexpr void clear_mem(T *ptr, size_t n)