diff options
author | lloyd <[email protected]> | 2014-02-08 14:20:48 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2014-02-08 14:20:48 +0000 |
commit | fd9b6a6cd6ce791cf2593a23bde4174daeebb05a (patch) | |
tree | 3b96f3500d46642acc984e68759f2da047d9e9ae /src | |
parent | c2915d84b213f3bba8fc68d1d2c035289f7c8d11 (diff) |
Have Skein call Threefish, rather than duplicating the code.
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/block/threefish/threefish.cpp | 58 | ||||
-rw-r--r-- | src/lib/block/threefish/threefish.h | 10 | ||||
-rw-r--r-- | src/lib/hash/skein/info.txt | 2 | ||||
-rw-r--r-- | src/lib/hash/skein/skein_512.cpp | 240 | ||||
-rw-r--r-- | src/lib/hash/skein/skein_512.h | 23 |
5 files changed, 149 insertions, 184 deletions
diff --git a/src/lib/block/threefish/threefish.cpp b/src/lib/block/threefish/threefish.cpp index 587a76a12..aa1b1ee81 100644 --- a/src/lib/block/threefish/threefish.cpp +++ b/src/lib/block/threefish/threefish.cpp @@ -1,6 +1,6 @@ /* * Threefish-512 -* (C) 2013 Jack Lloyd +* (C) 2013,2014 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -11,11 +11,6 @@ namespace Botan { -void Threefish_512::encrypt_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"); - #define THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7,ROT1,ROT2,ROT3,ROT4) \ do { \ X0 += X4; \ @@ -59,6 +54,55 @@ void Threefish_512::encrypt_n(const byte in[], byte out[], size_t blocks) const THREEFISH_INJECT_KEY(R2); \ } while(0) +void Threefish_512::skein_feedfwd(const secure_vector<u64bit>& M, + const secure_vector<u64bit>& T) + { + BOTAN_ASSERT(m_K.size() == 9, "Key was set"); + BOTAN_ASSERT(M.size() == 8, "Single block"); + + m_T[0] = T[0]; + m_T[1] = T[1]; + m_T[2] = T[0] ^ T[1]; + + u64bit X0 = M[0]; + u64bit X1 = M[1]; + u64bit X2 = M[2]; + u64bit X3 = M[3]; + u64bit X4 = M[4]; + u64bit X5 = M[5]; + u64bit X6 = M[6]; + u64bit X7 = M[7]; + + THREEFISH_INJECT_KEY(0); + + 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); + + m_K[0] = M[0] ^ X0; + m_K[1] = M[1] ^ X1; + m_K[2] = M[2] ^ X2; + m_K[3] = M[3] ^ X3; + m_K[4] = M[4] ^ X4; + m_K[5] = M[5] ^ X5; + m_K[6] = M[6] ^ X6; + m_K[7] = M[7] ^ X7; + + m_K[8] = m_K[0] ^ m_K[1] ^ m_K[2] ^ m_K[3] ^ + m_K[4] ^ m_K[5] ^ m_K[6] ^ m_K[7] ^ 0x1BD11BDAA9FC1A22; + } + +void Threefish_512::encrypt_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"); + for(size_t i = 0; i != blocks; ++i) { u64bit X0 = load_le<u64bit>(in, 0); @@ -87,11 +131,11 @@ void Threefish_512::encrypt_n(const byte in[], byte out[], size_t blocks) const in += 64; out += 64; } + } #undef THREEFISH_ENC_8_ROUNDS #undef THREEFISH_INJECT_KEY #undef THREEFISH_ROUND - } void Threefish_512::decrypt_n(const byte in[], byte out[], size_t blocks) const { diff --git a/src/lib/block/threefish/threefish.h b/src/lib/block/threefish/threefish.h index 327e54843..0d3c6fb9d 100644 --- a/src/lib/block/threefish/threefish.h +++ b/src/lib/block/threefish/threefish.h @@ -1,6 +1,6 @@ /* * Threefish -* (C) 2013 Jack Lloyd +* (C) 2013,2014 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -28,12 +28,20 @@ class BOTAN_DLL Threefish_512 : public Block_Cipher_Fixed_Params<64, 64> 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; } private: void key_schedule(const byte key[], size_t key_len) override; + // Interface for Skein + friend class Skein_512; + + virtual void skein_feedfwd(const secure_vector<u64bit>& M, + const secure_vector<u64bit>& T); + + // Private data secure_vector<u64bit> m_T; secure_vector<u64bit> m_K; }; diff --git a/src/lib/hash/skein/info.txt b/src/lib/hash/skein/info.txt index 89443132b..82cc69bc2 100644 --- a/src/lib/hash/skein/info.txt +++ b/src/lib/hash/skein/info.txt @@ -1,5 +1,5 @@ define SKEIN_512 20131128 <requires> -alloc +threefish </requires> diff --git a/src/lib/hash/skein/skein_512.cpp b/src/lib/hash/skein/skein_512.cpp index 94c8a3063..38eb3c89f 100644 --- a/src/lib/hash/skein/skein_512.cpp +++ b/src/lib/hash/skein/skein_512.cpp @@ -1,6 +1,6 @@ /* * The Skein-512 hash function -* (C) 2009-2010 Jack Lloyd +* (C) 2009,2010,2014 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -9,124 +9,46 @@ #include <botan/loadstor.h> #include <botan/parsing.h> #include <botan/exceptn.h> -#include <botan/rotate.h> +#include <botan/internal/xor_buf.h> #include <algorithm> namespace Botan { -namespace { - -enum type_code { - SKEIN_KEY = 0, - SKEIN_CONFIG = 4, - SKEIN_PERSONALIZATION = 8, - SKEIN_PUBLIC_KEY = 12, - SKEIN_KEY_IDENTIFIER = 16, - SKEIN_NONCE = 20, - SKEIN_MSG = 48, - SKEIN_OUTPUT = 63 -}; - -void ubi_512(secure_vector<u64bit>& H, - secure_vector<u64bit>& T, - const byte msg[], size_t msg_len) +Skein_512::Skein_512(size_t arg_output_bits, + const std::string& arg_personalization) : + personalization(arg_personalization), + output_bits(arg_output_bits), + m_threefish(new Threefish_512), + T(2), buffer(64), buf_pos(0) { - do - { - const size_t to_proc = std::min<size_t>(msg_len, 64); - T[0] += to_proc; - - u64bit M[8] = { 0 }; + if(output_bits == 0 || output_bits % 8 != 0 || output_bits > 512) + throw Invalid_Argument("Bad output bits size for Skein-512"); - load_le(M, msg, to_proc / 8); + initial_block(); + } - if(to_proc % 8) - { - for(size_t j = 0; j != to_proc % 8; ++j) - M[to_proc/8] |= static_cast<u64bit>(msg[8*(to_proc/8)+j]) << (8*j); - } +std::string Skein_512::name() const + { + if(personalization != "") + return "Skein-512(" + std::to_string(output_bits) + "," + + personalization + ")"; + return "Skein-512(" + std::to_string(output_bits) + ")"; + } - H[8] = H[0] ^ H[1] ^ H[2] ^ H[3] ^ - H[4] ^ H[5] ^ H[6] ^ H[7] ^ 0x1BD11BDAA9FC1A22; - - T[2] = T[0] ^ T[1]; - - u64bit X0 = M[0] + H[0]; - u64bit X1 = M[1] + H[1]; - u64bit X2 = M[2] + H[2]; - u64bit X3 = M[3] + H[3]; - u64bit X4 = M[4] + H[4]; - u64bit X5 = M[5] + H[5] + T[0]; - u64bit X6 = M[6] + H[6] + T[1]; - u64bit X7 = M[7] + H[7]; - -#define THREEFISH_ROUND(X1,X2,X3,X4,X5,X6,X7,X8,ROT1,ROT2,ROT3,ROT4) \ - do { \ - X1 += X2; X2 = rotate_left(X2, ROT1) ^ X1; \ - X3 += X4; X4 = rotate_left(X4, ROT2) ^ X3; \ - X5 += X6; X6 = rotate_left(X6, ROT3) ^ X5; \ - X7 += X8; X8 = rotate_left(X8, ROT4) ^ X7; \ - } while(0); - -#define THREEFISH_INJECT_KEY(r) \ - do { \ - X0 += H[(r ) % 9]; \ - X1 += H[(r+1) % 9]; \ - X2 += H[(r+2) % 9]; \ - X3 += H[(r+3) % 9]; \ - X4 += H[(r+4) % 9]; \ - X5 += H[(r+5) % 9] + T[(r ) % 3]; \ - X6 += H[(r+6) % 9] + T[(r+1) % 3]; \ - X7 += H[(r+7) % 9] + (r); \ - } while(0); - -#define THREEFISH_8_ROUNDS(R1,R2) \ - do { \ - THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7, 46,36,19,37); \ - THREEFISH_ROUND(X2,X1,X4,X7,X6,X5,X0,X3, 33,27,14,42); \ - THREEFISH_ROUND(X4,X1,X6,X3,X0,X5,X2,X7, 17,49,36,39); \ - THREEFISH_ROUND(X6,X1,X0,X7,X2,X5,X4,X3, 44, 9,54,56); \ - \ - THREEFISH_INJECT_KEY(R1); \ - \ - THREEFISH_ROUND(X0,X1,X2,X3,X4,X5,X6,X7, 39,30,34,24); \ - THREEFISH_ROUND(X2,X1,X4,X7,X6,X5,X0,X3, 13,50,10,17); \ - THREEFISH_ROUND(X4,X1,X6,X3,X0,X5,X2,X7, 25,29,39,43); \ - THREEFISH_ROUND(X6,X1,X0,X7,X2,X5,X4,X3, 8,35,56,22); \ - \ - THREEFISH_INJECT_KEY(R2); \ - } while(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); - - // message feed forward - H[0] = X0 ^ M[0]; - H[1] = X1 ^ M[1]; - H[2] = X2 ^ M[2]; - H[3] = X3 ^ M[3]; - H[4] = X4 ^ M[4]; - H[5] = X5 ^ M[5]; - H[6] = X6 ^ M[6]; - H[7] = X7 ^ M[7]; +HashFunction* Skein_512::clone() const + { + return new Skein_512(output_bits, personalization); + } - // clear first flag if set - T[1] &= ~(static_cast<u64bit>(1) << 62); +void Skein_512::clear() + { + zeroise(buffer); + buf_pos = 0; - msg_len -= to_proc; - msg += to_proc; - } while(msg_len); + initial_block(); } -void reset_tweak(secure_vector<u64bit>& T, - type_code type, bool final) +void Skein_512::reset_tweak(type_code type, bool final) { T[0] = 0; @@ -135,19 +57,18 @@ void reset_tweak(secure_vector<u64bit>& T, (static_cast<u64bit>(final) << 63); } -void initial_block(secure_vector<u64bit>& H, - secure_vector<u64bit>& T, - size_t output_bits, - const std::string& personalization) +void Skein_512::initial_block() { - zeroise(H); + const byte zeros[64] = { 0 }; + + m_threefish->set_key(zeros, sizeof(zeros)); // ASCII("SHA3") followed by version (0x0001) code byte config_str[32] = { 0x53, 0x48, 0x41, 0x33, 0x01, 0x00, 0 }; store_le(u32bit(output_bits), config_str + 8); - reset_tweak(T, SKEIN_CONFIG, true); - ubi_512(H, T, config_str, sizeof(config_str)); + reset_tweak(SKEIN_CONFIG, true); + ubi_512(config_str, sizeof(config_str)); if(personalization != "") { @@ -157,50 +78,41 @@ void initial_block(secure_vector<u64bit>& H, doesn't seem worth the trouble. */ if(personalization.length() > 64) - throw Invalid_Argument("Skein personalization must be <= 64 bytes"); + throw Invalid_Argument("Skein personalization must be less than 64 bytes"); const byte* bits = reinterpret_cast<const byte*>(personalization.data()); - - reset_tweak(T, SKEIN_PERSONALIZATION, true); - ubi_512(H, T, bits, personalization.length()); + reset_tweak(SKEIN_PERSONALIZATION, true); + ubi_512(bits, personalization.length()); } - reset_tweak(T, SKEIN_MSG, false); + reset_tweak(SKEIN_MSG, false); } -} - -Skein_512::Skein_512(size_t arg_output_bits, - const std::string& arg_personalization) : - personalization(arg_personalization), - output_bits(arg_output_bits), - H(9), T(3), buffer(64), buf_pos(0) +void Skein_512::ubi_512(const byte msg[], size_t msg_len) { - if(output_bits == 0 || output_bits % 8 != 0 || output_bits > 64*1024) - throw Invalid_Argument("Bad output bits size for Skein-512"); + secure_vector<u64bit> M(8); - initial_block(H, T, output_bits, personalization); - } + do + { + const size_t to_proc = std::min<size_t>(msg_len, 64); + T[0] += to_proc; -std::string Skein_512::name() const - { - if(personalization != "") - return "Skein-512(" + std::to_string(output_bits) + "," + - personalization + ")"; - return "Skein-512(" + std::to_string(output_bits) + ")"; - } + load_le(&M[0], msg, to_proc / 8); -HashFunction* Skein_512::clone() const - { - return new Skein_512(output_bits, personalization); - } + if(to_proc % 8) + { + for(size_t j = 0; j != to_proc % 8; ++j) + M[to_proc/8] |= static_cast<u64bit>(msg[8*(to_proc/8)+j]) << (8*j); + } -void Skein_512::clear() - { - zeroise(buffer); - buf_pos = 0; + m_threefish->skein_feedfwd(M, T); + + // clear first flag if set + T[1] &= ~(static_cast<u64bit>(1) << 62); - initial_block(H, T, output_bits, personalization); + msg_len -= to_proc; + msg += to_proc; + } while(msg_len); } void Skein_512::add_data(const byte input[], size_t length) @@ -213,7 +125,7 @@ void Skein_512::add_data(const byte input[], size_t length) buffer_insert(buffer, buf_pos, input, length); if(buf_pos + length > 64) { - ubi_512(H, T, &buffer[0], buffer.size()); + ubi_512(&buffer[0], buffer.size()); input += (64 - buf_pos); length -= (64 - buf_pos); @@ -224,7 +136,7 @@ void Skein_512::add_data(const byte input[], size_t length) const size_t full_blocks = (length - 1) / 64; if(full_blocks) - ubi_512(H, T, input, 64*full_blocks); + ubi_512(input, 64*full_blocks); length -= full_blocks * 64; @@ -239,36 +151,20 @@ void Skein_512::final_result(byte out[]) for(size_t i = buf_pos; i != buffer.size(); ++i) buffer[i] = 0; - ubi_512(H, T, &buffer[0], buf_pos); - - byte counter[8] = { 0 }; - - size_t out_bytes = output_bits / 8; + ubi_512(&buffer[0], buf_pos); - secure_vector<u64bit> H_out(9); + const byte counter[8] = { 0 }; - while(out_bytes) - { - const size_t to_proc = std::min<size_t>(out_bytes, 64); - - copy_mem(&H_out[0], &H[0], 8); - - reset_tweak(T, SKEIN_OUTPUT, true); - ubi_512(H_out, T, counter, sizeof(counter)); + reset_tweak(SKEIN_OUTPUT, true); + ubi_512(counter, sizeof(counter)); - for(size_t i = 0; i != to_proc; ++i) - out[i] = get_byte(7-i%8, H_out[i/8]); + const size_t out_bytes = output_bits / 8; - out_bytes -= to_proc; - out += to_proc; - - for(size_t i = 0; i != sizeof(counter); ++i) - if(++counter[i]) - break; - } + for(size_t i = 0; i != out_bytes; ++i) + out[i] = get_byte(7-i%8, m_threefish->m_K[i/8]); buf_pos = 0; - initial_block(H, T, output_bits, personalization); + initial_block(); } } diff --git a/src/lib/hash/skein/skein_512.h b/src/lib/hash/skein/skein_512.h index e0abc06ae..1fd514cf5 100644 --- a/src/lib/hash/skein/skein_512.h +++ b/src/lib/hash/skein/skein_512.h @@ -1,6 +1,6 @@ /* * The Skein-512 hash function -* (C) 2009 Jack Lloyd +* (C) 2009,2014 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -8,9 +8,10 @@ #ifndef BOTAN_SKEIN_512_H__ #define BOTAN_SKEIN_512_H__ -#include <botan/secmem.h> #include <botan/hash.h> +#include <botan/threefish.h> #include <string> +#include <memory> namespace Botan { @@ -35,13 +36,29 @@ class BOTAN_DLL Skein_512 : public HashFunction std::string name() const; void clear(); private: + enum type_code { + SKEIN_KEY = 0, + SKEIN_CONFIG = 4, + SKEIN_PERSONALIZATION = 8, + SKEIN_PUBLIC_KEY = 12, + SKEIN_KEY_IDENTIFIER = 16, + SKEIN_NONCE = 20, + SKEIN_MSG = 48, + SKEIN_OUTPUT = 63 + }; + void add_data(const byte input[], size_t length); void final_result(byte out[]); + void ubi_512(const byte msg[], size_t msg_len); + + void initial_block(); + void reset_tweak(type_code type, bool final); + std::string personalization; size_t output_bits; - secure_vector<u64bit> H; + std::unique_ptr<Threefish_512> m_threefish; secure_vector<u64bit> T; secure_vector<byte> buffer; size_t buf_pos; |