aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2014-02-08 14:20:48 +0000
committerlloyd <[email protected]>2014-02-08 14:20:48 +0000
commitfd9b6a6cd6ce791cf2593a23bde4174daeebb05a (patch)
tree3b96f3500d46642acc984e68759f2da047d9e9ae /src
parentc2915d84b213f3bba8fc68d1d2c035289f7c8d11 (diff)
Have Skein call Threefish, rather than duplicating the code.
Diffstat (limited to 'src')
-rw-r--r--src/lib/block/threefish/threefish.cpp58
-rw-r--r--src/lib/block/threefish/threefish.h10
-rw-r--r--src/lib/hash/skein/info.txt2
-rw-r--r--src/lib/hash/skein/skein_512.cpp240
-rw-r--r--src/lib/hash/skein/skein_512.h23
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;