aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2013-12-25 00:46:50 +0000
committerlloyd <[email protected]>2013-12-25 00:46:50 +0000
commit0beb8efebb8a03c5a795ea03b9da7e3c87daee23 (patch)
tree3e78ccb04b8f3f9eb0cc1b485ba0636beaf7dab6
parentbb9ca87f6bd9383cf27de115281cc9ea54284d3a (diff)
Provide Threefish as a block cipher, add decryption
-rw-r--r--checks/transform.cpp8
-rw-r--r--checks/validate.dat6
-rw-r--r--src/block/threefish/info.txt2
-rw-r--r--src/block/threefish/threefish.cpp187
-rw-r--r--src/block/threefish/threefish.h34
-rw-r--r--src/block/threefish_avx2/threefish_avx2.cpp22
-rw-r--r--src/block/threefish_avx2/threefish_avx2.h3
7 files changed, 138 insertions, 124 deletions
diff --git a/checks/transform.cpp b/checks/transform.cpp
index cfcc5bb51..ddad62a72 100644
--- a/checks/transform.cpp
+++ b/checks/transform.cpp
@@ -3,7 +3,7 @@
#include <botan/libstate.h>
#include <botan/botan.h>
-#include <botan/threefish.h>
+#include <botan/transform.h>
#include <botan/benchmark.h>
#include <botan/hex.h>
#include <iostream>
@@ -15,10 +15,6 @@ namespace {
Transformation* get_transform(const std::string& algo)
{
-#if defined(BOTAN_HAS_THREEFISH_512)
- if(algo == "Threefish-512")
- return new Threefish_512;
-#endif
throw std::runtime_error("Unknown transform " + algo);
}
@@ -43,6 +39,8 @@ secure_vector<byte> transform_test(const std::string& algo,
void test_transform()
{
+ return;
+
std::ifstream vec("checks/transform.vec");
run_tests(vec, "Transform", "Output", true,
diff --git a/checks/validate.dat b/checks/validate.dat
index 677890d4c..5e220e50f 100644
--- a/checks/validate.dat
+++ b/checks/validate.dat
@@ -23554,6 +23554,12 @@ D2DED73E59319A8138E0331F0EA149EAA443EA1B2C5747CE7EC5F21D4FE0C147
00000000000000000000000000000001:23D1247EFF4CA8CBB378DF118369821E:\
0000000000000000000000000000000000000000000000000000000000000000
+[Threefish-512]
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:\
+B1A2BBC6EF6025BC40EB3822161F36E375D1BB0AEE3186FBD19E47C5D479947B7BC2F8586E35F0CFF7E7F03084B0B7B1F1AB3961A580A3E97EB41EA14A6D7BBE:\
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:\
+00000000000000000000000000000000
+
[XTEA]
FEFEFEFEFEFEFEFE:36552E889D6A41CF:00112233445566778899AABBCCDDEEFF
0123456789ABCDEF:B8BF2821622B5B30:00112233445566778899AABBCCDDEEFF
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; }
};
}