diff options
Diffstat (limited to 'src/modes/xts/xts.cpp')
-rw-r--r-- | src/modes/xts/xts.cpp | 285 |
1 files changed, 0 insertions, 285 deletions
diff --git a/src/modes/xts/xts.cpp b/src/modes/xts/xts.cpp deleted file mode 100644 index 02da5fa5d..000000000 --- a/src/modes/xts/xts.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* -* XTS Mode -* (C) 2009,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/xts.h> -#include <botan/loadstor.h> -#include <botan/internal/xor_buf.h> -#include <botan/internal/rounding.h> - -namespace Botan { - -namespace { - -void poly_double_128(byte out[], const byte in[]) - { - u64bit X0 = load_le<u64bit>(in, 0); - u64bit X1 = load_le<u64bit>(in, 1); - - const bool carry = (X1 >> 63); - - X1 = (X1 << 1) | (X0 >> 63); - X0 = (X0 << 1); - - if(carry) - X0 ^= 0x87; - - store_le(out, X0, X1); - } - -void poly_double_64(byte out[], const byte in[]) - { - u64bit X = load_le<u64bit>(in, 0); - const bool carry = (X >> 63); - X <<= 1; - if(carry) - X ^= 0x1B; - store_le(X, out); - } - -inline void poly_double(byte out[], const byte in[], size_t size) - { - if(size == 8) - poly_double_64(out, in); - else - poly_double_128(out, in); - } - -} - -XTS_Mode::XTS_Mode(BlockCipher* cipher) : m_cipher(cipher) - { - if(m_cipher->block_size() != 8 && m_cipher->block_size() != 16) - throw std::invalid_argument("Bad cipher for XTS: " + cipher->name()); - - m_tweak_cipher.reset(m_cipher->clone()); - m_tweak.resize(update_granularity()); - } - -void XTS_Mode::clear() - { - m_cipher->clear(); - m_tweak_cipher->clear(); - zeroise(m_tweak); - } - -std::string XTS_Mode::name() const - { - return cipher().name() + "/XTS"; - } - -size_t XTS_Mode::update_granularity() const - { - return cipher().parallel_bytes(); - } - -size_t XTS_Mode::minimum_final_size() const - { - return cipher().block_size() + 1; - } - -Key_Length_Specification XTS_Mode::key_spec() const - { - return cipher().key_spec().multiple(2); - } - -size_t XTS_Mode::default_nonce_length() const - { - return cipher().block_size(); - } - -bool XTS_Mode::valid_nonce_length(size_t n) const - { - return cipher().block_size() == n; - } - -void XTS_Mode::key_schedule(const byte key[], size_t length) - { - const size_t key_half = length / 2; - - if(length % 2 == 1 || !m_cipher->valid_keylength(key_half)) - throw Invalid_Key_Length(name(), length); - - m_cipher->set_key(&key[0], key_half); - m_tweak_cipher->set_key(&key[key_half], key_half); - } - -secure_vector<byte> XTS_Mode::start(const byte nonce[], size_t nonce_len) - { - if(!valid_nonce_length(nonce_len)) - throw Invalid_IV_Length(name(), nonce_len); - - copy_mem(&m_tweak[0], nonce, nonce_len); - m_tweak_cipher->encrypt(&m_tweak[0]); - - update_tweak(0); - - return secure_vector<byte>(); - } - -void XTS_Mode::update_tweak(size_t which) - { - const size_t BS = m_tweak_cipher->block_size(); - - if(which > 0) - poly_double(&m_tweak[0], &m_tweak[(which-1)*BS], BS); - - const size_t blocks_in_tweak = update_granularity() / BS; - - for(size_t i = 1; i < blocks_in_tweak; ++i) - poly_double(&m_tweak[i*BS], &m_tweak[(i-1)*BS], BS); - } - -size_t XTS_Encryption::output_length(size_t input_length) const - { - return round_up(input_length, cipher().block_size()); - } - -void XTS_Encryption::update(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = &buffer[offset]; - - const size_t BS = cipher().block_size(); - - BOTAN_ASSERT(sz % BS == 0, "Input is full blocks"); - size_t blocks = sz / BS; - - const size_t blocks_in_tweak = update_granularity() / BS; - - while(blocks) - { - const size_t to_proc = std::min(blocks, blocks_in_tweak); - const size_t to_proc_bytes = to_proc * BS; - - xor_buf(buf, tweak(), to_proc_bytes); - cipher().encrypt_n(buf, buf, to_proc); - xor_buf(buf, tweak(), to_proc_bytes); - - buf += to_proc * BS; - blocks -= to_proc; - - update_tweak(to_proc); - } - } - -void XTS_Encryption::finish(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = &buffer[offset]; - - BOTAN_ASSERT(sz >= minimum_final_size(), "Have sufficient final input"); - - const size_t BS = cipher().block_size(); - - if(sz % BS == 0) - { - update(buffer, offset); - } - else - { - // steal ciphertext - const size_t full_blocks = ((sz / BS) - 1) * BS; - const size_t final_bytes = sz - full_blocks; - BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range"); - - secure_vector<byte> last(buf + full_blocks, buf + full_blocks + final_bytes); - buffer.resize(full_blocks + offset); - update(buffer, offset); - - xor_buf(last, tweak(), BS); - cipher().encrypt(last); - xor_buf(last, tweak(), BS); - - for(size_t i = 0; i != final_bytes - BS; ++i) - std::swap(last[i], last[i + BS]); - - xor_buf(last, tweak() + BS, BS); - cipher().encrypt(last); - xor_buf(last, tweak() + BS, BS); - - buffer += last; - } - } - -size_t XTS_Decryption::output_length(size_t input_length) const - { - // might be less - return input_length; - } - -void XTS_Decryption::update(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = &buffer[offset]; - - const size_t BS = cipher().block_size(); - - BOTAN_ASSERT(sz % BS == 0, "Input is full blocks"); - size_t blocks = sz / BS; - - const size_t blocks_in_tweak = update_granularity() / BS; - - while(blocks) - { - const size_t to_proc = std::min(blocks, blocks_in_tweak); - const size_t to_proc_bytes = to_proc * BS; - - xor_buf(buf, tweak(), to_proc_bytes); - cipher().decrypt_n(buf, buf, to_proc); - xor_buf(buf, tweak(), to_proc_bytes); - - buf += to_proc * BS; - blocks -= to_proc; - - update_tweak(to_proc); - } - } - -void XTS_Decryption::finish(secure_vector<byte>& buffer, size_t offset) - { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = &buffer[offset]; - - BOTAN_ASSERT(sz >= minimum_final_size(), "Have sufficient final input"); - - const size_t BS = cipher().block_size(); - - if(sz % BS == 0) - { - update(buffer, offset); - } - else - { - // steal ciphertext - const size_t full_blocks = ((sz / BS) - 1) * BS; - const size_t final_bytes = sz - full_blocks; - BOTAN_ASSERT(final_bytes > BS && final_bytes < 2*BS, "Left over size in expected range"); - - secure_vector<byte> last(buf + full_blocks, buf + full_blocks + final_bytes); - buffer.resize(full_blocks + offset); - update(buffer, offset); - - xor_buf(last, tweak() + BS, BS); - cipher().decrypt(last); - xor_buf(last, tweak() + BS, BS); - - for(size_t i = 0; i != final_bytes - BS; ++i) - std::swap(last[i], last[i + BS]); - - xor_buf(last, tweak(), BS); - cipher().decrypt(last); - xor_buf(last, tweak(), BS); - - buffer += last; - } - } - -} |