diff options
author | lloyd <[email protected]> | 2013-12-25 00:46:50 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2013-12-25 00:46:50 +0000 |
commit | 0beb8efebb8a03c5a795ea03b9da7e3c87daee23 (patch) | |
tree | 3e78ccb04b8f3f9eb0cc1b485ba0636beaf7dab6 /src | |
parent | bb9ca87f6bd9383cf27de115281cc9ea54284d3a (diff) |
Provide Threefish as a block cipher, add decryption
Diffstat (limited to 'src')
-rw-r--r-- | src/block/threefish/info.txt | 2 | ||||
-rw-r--r-- | src/block/threefish/threefish.cpp | 187 | ||||
-rw-r--r-- | src/block/threefish/threefish.h | 34 | ||||
-rw-r--r-- | src/block/threefish_avx2/threefish_avx2.cpp | 22 | ||||
-rw-r--r-- | src/block/threefish_avx2/threefish_avx2.h | 3 |
5 files changed, 129 insertions, 119 deletions
diff --git a/src/block/threefish/info.txt b/src/block/threefish/info.txt index b352a49df..15843cdd3 100644 --- a/src/block/threefish/info.txt +++ b/src/block/threefish/info.txt @@ -1 +1 @@ -define THREEFISH_512 20131220 +define THREEFISH_512 20131224 diff --git a/src/block/threefish/threefish.cpp b/src/block/threefish/threefish.cpp index ef639f03a..587a76a12 100644 --- a/src/block/threefish/threefish.cpp +++ b/src/block/threefish/threefish.cpp @@ -11,22 +11,11 @@ namespace Botan { -secure_vector<byte> Threefish_512::start(const byte tweak[], size_t tweak_len) +void Threefish_512::encrypt_n(const byte in[], byte out[], size_t blocks) const { - if(!valid_nonce_length(tweak_len)) - throw Invalid_IV_Length(name(), tweak_len); - - m_T.resize(3); - - m_T[0] = load_le<u64bit>(tweak, 0); - m_T[1] = load_le<u64bit>(tweak, 1); - m_T[2] = m_T[0] ^ m_T[1]; - - return secure_vector<byte>(); - } + BOTAN_ASSERT(m_K.size() == 9, "Key was set"); + BOTAN_ASSERT(m_T.size() == 3, "Tweak was set"); -void Threefish_512::full_inplace_update(byte* buf, size_t sz) - { #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \ do { \ X0 += X4; \ @@ -55,71 +44,144 @@ void Threefish_512::full_inplace_update(byte* buf, size_t sz) X7 += m_K[(r+7) % 9] + (r); \ } while(0) -#define THREEFISH_8_ROUNDS(R1,R2) \ +#define THREEFISH_ENC_8_ROUNDS(R1,R2) \ do { \ THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 46,36,19,37); \ THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 33,27,14,42); \ THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 17,49,36,39); \ THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 44, 9,54,56); \ - \ THREEFISH_INJECT_KEY(R1); \ \ THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 39,30,34,24); \ THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 13,50,10,17); \ THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 25,29,39,43); \ THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 8,35,56,22); \ - \ THREEFISH_INJECT_KEY(R2); \ } while(0) - while(sz) + for(size_t i = 0; i != blocks; ++i) { - u64bit X0 = load_le<u64bit>(buf, 0); - u64bit X1 = load_le<u64bit>(buf, 1); - u64bit X2 = load_le<u64bit>(buf, 2); - u64bit X3 = load_le<u64bit>(buf, 3); - u64bit X4 = load_le<u64bit>(buf, 4); - u64bit X5 = load_le<u64bit>(buf, 5); - u64bit X6 = load_le<u64bit>(buf, 6); - u64bit X7 = load_le<u64bit>(buf, 7); + u64bit X0 = load_le<u64bit>(in, 0); + u64bit X1 = load_le<u64bit>(in, 1); + u64bit X2 = load_le<u64bit>(in, 2); + u64bit X3 = load_le<u64bit>(in, 3); + u64bit X4 = load_le<u64bit>(in, 4); + u64bit X5 = load_le<u64bit>(in, 5); + u64bit X6 = load_le<u64bit>(in, 6); + u64bit X7 = load_le<u64bit>(in, 7); THREEFISH_INJECT_KEY(0); - THREEFISH_8_ROUNDS(1,2); - THREEFISH_8_ROUNDS(3,4); - THREEFISH_8_ROUNDS(5,6); - THREEFISH_8_ROUNDS(7,8); - THREEFISH_8_ROUNDS(9,10); - THREEFISH_8_ROUNDS(11,12); - THREEFISH_8_ROUNDS(13,14); - THREEFISH_8_ROUNDS(15,16); - THREEFISH_8_ROUNDS(17,18); + THREEFISH_ENC_8_ROUNDS(1,2); + THREEFISH_ENC_8_ROUNDS(3,4); + THREEFISH_ENC_8_ROUNDS(5,6); + THREEFISH_ENC_8_ROUNDS(7,8); + THREEFISH_ENC_8_ROUNDS(9,10); + THREEFISH_ENC_8_ROUNDS(11,12); + THREEFISH_ENC_8_ROUNDS(13,14); + THREEFISH_ENC_8_ROUNDS(15,16); + THREEFISH_ENC_8_ROUNDS(17,18); - store_le(buf, X0, X1, X2, X3, X4, X5, X6, X7); + store_le(out, X0, X1, X2, X3, X4, X5, X6, X7); - buf += 64; - sz -= 64; + in += 64; + out += 64; } -#undef THREEFISH_8_ROUNDS +#undef THREEFISH_ENC_8_ROUNDS #undef THREEFISH_INJECT_KEY #undef THREEFISH_ROUND } -void Threefish_512::update(secure_vector<byte>& buf, size_t offset) +void Threefish_512::decrypt_n(const byte in[], byte out[], size_t blocks) const { BOTAN_ASSERT(m_K.size() == 9, "Key was set"); BOTAN_ASSERT(m_T.size() == 3, "Tweak was set"); - const size_t sz = buf.size() - offset; - BOTAN_ASSERT(sz % block_size() == 0, "Block sized input"); +#define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \ + do { \ + X4 ^= X0; \ + X5 ^= X1; \ + X6 ^= X2; \ + X7 ^= X3; \ + X4 = rotate_right(X4, ROT1); \ + X5 = rotate_right(X5, ROT2); \ + X6 = rotate_right(X6, ROT3); \ + X7 = rotate_right(X7, ROT4); \ + X0 -= X4; \ + X1 -= X5; \ + X2 -= X6; \ + X3 -= X7; \ + } while(0) + +#define THREEFISH_INJECT_KEY(r) \ + do { \ + X0 -= m_K[(r ) % 9]; \ + X1 -= m_K[(r+1) % 9]; \ + X2 -= m_K[(r+2) % 9]; \ + X3 -= m_K[(r+3) % 9]; \ + X4 -= m_K[(r+4) % 9]; \ + X5 -= m_K[(r+5) % 9] + m_T[(r ) % 3]; \ + X6 -= m_K[(r+6) % 9] + m_T[(r+1) % 3]; \ + X7 -= m_K[(r+7) % 9] + (r); \ + } while(0) + +#define THREEFISH_DEC_8_ROUNDS(R1,R2) \ + do { \ + THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 8,35,56,22); \ + THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 25,29,39,43); \ + THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 13,50,10,17); \ + THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 39,30,34,24); \ + THREEFISH_INJECT_KEY(R1); \ + \ + THREEFISH_ROUND(X6,X0,X2,X4, X1,X7,X5,X3, 44, 9,54,56); \ + THREEFISH_ROUND(X4,X6,X0,X2, X1,X3,X5,X7, 17,49,36,39); \ + THREEFISH_ROUND(X2,X4,X6,X0, X1,X7,X5,X3, 33,27,14,42); \ + THREEFISH_ROUND(X0,X2,X4,X6, X1,X3,X5,X7, 46,36,19,37); \ + THREEFISH_INJECT_KEY(R2); \ + } while(0) + + for(size_t i = 0; i != blocks; ++i) + { + u64bit X0 = load_le<u64bit>(in, 0); + u64bit X1 = load_le<u64bit>(in, 1); + u64bit X2 = load_le<u64bit>(in, 2); + u64bit X3 = load_le<u64bit>(in, 3); + u64bit X4 = load_le<u64bit>(in, 4); + u64bit X5 = load_le<u64bit>(in, 5); + u64bit X6 = load_le<u64bit>(in, 6); + u64bit X7 = load_le<u64bit>(in, 7); + + THREEFISH_INJECT_KEY(18); + + THREEFISH_DEC_8_ROUNDS(17,16); + THREEFISH_DEC_8_ROUNDS(15,14); + THREEFISH_DEC_8_ROUNDS(13,12); + THREEFISH_DEC_8_ROUNDS(11,10); + THREEFISH_DEC_8_ROUNDS(9,8); + THREEFISH_DEC_8_ROUNDS(7,6); + THREEFISH_DEC_8_ROUNDS(5,4); + THREEFISH_DEC_8_ROUNDS(3,2); + THREEFISH_DEC_8_ROUNDS(1,0); + + store_le(out, X0, X1, X2, X3, X4, X5, X6, X7); + + in += 64; + out += 64; + } - full_inplace_update(&buf[offset], sz); +#undef THREEFISH_DEC_8_ROUNDS +#undef THREEFISH_INJECT_KEY +#undef THREEFISH_ROUND } -Key_Length_Specification Threefish_512::key_spec() const +void Threefish_512::set_tweak(const byte tweak[], size_t len) { - return Key_Length_Specification(64); + if(len != 16) + throw std::runtime_error("Unsupported twofish tweak length"); + m_T[0] = load_le<u64bit>(tweak, 0); + m_T[1] = load_le<u64bit>(tweak, 1); + m_T[2] = m_T[0] ^ m_T[1]; } void Threefish_512::key_schedule(const byte key[], size_t) @@ -134,41 +196,6 @@ void Threefish_512::key_schedule(const byte key[], size_t) m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22; } -void Threefish_512::finish(secure_vector<byte>& blocks, size_t offset) - { - update(blocks, offset); - m_T.clear(); - } - -size_t Threefish_512::output_length(size_t input_length) const - { - if(input_length % update_granularity() == 0) - throw std::invalid_argument("Threefish - invalid input length " + std::to_string(input_length)); - - return input_length; - } - -size_t Threefish_512::update_granularity() const - { - return block_size(); - } - -size_t Threefish_512::minimum_final_size() const - { - return 0; - } - -size_t Threefish_512::default_nonce_length() const - { - // todo: define encoding for smaller nonces - return 16; - } - -bool Threefish_512::valid_nonce_length(size_t nonce_len) const - { - return default_nonce_length() == nonce_len; - } - void Threefish_512::clear() { zeroise(m_K); diff --git a/src/block/threefish/threefish.h b/src/block/threefish/threefish.h index 0e13221cc..327e54843 100644 --- a/src/block/threefish/threefish.h +++ b/src/block/threefish/threefish.h @@ -8,45 +8,29 @@ #ifndef BOTAN_THREEFISH_H__ #define BOTAN_THREEFISH_H__ -#include <botan/transform.h> +#include <botan/block_cipher.h> namespace Botan { /** * Threefish-512 */ -class BOTAN_DLL Threefish_512 : public Transformation +class BOTAN_DLL Threefish_512 : public Block_Cipher_Fixed_Params<64, 64> { public: - secure_vector<byte> start(const byte tweak[], size_t tweak_len) override; + void encrypt_n(const byte in[], byte out[], size_t blocks) const override; + void decrypt_n(const byte in[], byte out[], size_t blocks) const override; - void update(secure_vector<byte>& blocks, size_t offset) override; + void set_tweak(const byte tweak[], size_t len); - void finish(secure_vector<byte>& final_block, size_t offset) override; - - size_t output_length(size_t input_length) const override; - - size_t update_granularity() const override; - - size_t minimum_final_size() const override; - - size_t default_nonce_length() const override; - - bool valid_nonce_length(size_t nonce_len) const override; - - Key_Length_Specification key_spec() const override; - - std::string name() const { return "Threefish-512"; } - - void clear(); - - size_t block_size() const { return 64; } + void clear() override; + std::string name() const override { return "Threefish-512"; } + BlockCipher* clone() const override { return new Threefish_512; } + Threefish_512() : m_T(3) {} protected: const secure_vector<u64bit>& get_T() const { return m_T; } const secure_vector<u64bit>& get_K() const { return m_K; } - - virtual void full_inplace_update(byte* buf, size_t sz); private: void key_schedule(const byte key[], size_t key_len) override; diff --git a/src/block/threefish_avx2/threefish_avx2.cpp b/src/block/threefish_avx2/threefish_avx2.cpp index f77cfee47..e1e000a5d 100644 --- a/src/block/threefish_avx2/threefish_avx2.cpp +++ b/src/block/threefish_avx2/threefish_avx2.cpp @@ -35,7 +35,7 @@ inline void deinterleave_epi64(__m256i& X0, __m256i& X1) } -void Threefish_512_AVX2::full_inplace_update(byte* buf, size_t sz) +void Threefish_512_AVX2::encrypt_n(const byte in[], byte out[], size_t blocks) const { const u64bit* K = &get_K()[0]; const u64bit* T_64 = &get_T()[0]; @@ -106,14 +106,15 @@ void Threefish_512_AVX2::full_inplace_update(byte* buf, size_t sz) const __m256i ONE = _mm256_set_epi64x(1, 0, 0, 0); - while(sz >= 64) - { - __m256i* buf_mm = reinterpret_cast<__m256i*>(buf); + const __m256i* in_mm = reinterpret_cast<const __m256i*>(in); + __m256i* out_mm = reinterpret_cast<__m256i*>(out); - __m256i X0 = _mm256_loadu_si256(buf_mm); - __m256i X1 = _mm256_loadu_si256(buf_mm + 1); + for(size_t i = 0; i != blocks; ++i) + { + __m256i X0 = _mm256_loadu_si256(in_mm++); + __m256i X1 = _mm256_loadu_si256(in_mm++); - __m256i T = _mm256_set_epi64x(T_64[0], T_64[1], T_64[2], 0); + const __m256i T = _mm256_set_epi64x(T_64[0], T_64[1], T_64[2], 0); __m256i R = _mm256_set1_epi64x(0); @@ -135,11 +136,8 @@ void Threefish_512_AVX2::full_inplace_update(byte* buf, size_t sz) deinterleave_epi64(X0, X1); - _mm256_storeu_si256(buf_mm, X0); - _mm256_storeu_si256(buf_mm + 1, X1); - - buf += 64; - sz -= 64; + _mm256_storeu_si256(out_mm++, X0); + _mm256_storeu_si256(out_mm++, X1); } } diff --git a/src/block/threefish_avx2/threefish_avx2.h b/src/block/threefish_avx2/threefish_avx2.h index f9a0b666f..71d2a0b20 100644 --- a/src/block/threefish_avx2/threefish_avx2.h +++ b/src/block/threefish_avx2/threefish_avx2.h @@ -18,7 +18,8 @@ namespace Botan { class BOTAN_DLL Threefish_512_AVX2 : public Threefish_512 { private: - void full_inplace_update(byte* buf, size_t sz) override; + void encrypt_n(const byte in[], byte out[], size_t blocks) const override; + BlockCipher* clone() const override { return new Threefish_512_AVX2; } }; } |