aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/relnotes/1_11_8.rst10
-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
6 files changed, 157 insertions, 186 deletions
diff --git a/doc/relnotes/1_11_8.rst b/doc/relnotes/1_11_8.rst
index a2928f2e5..0c670a9a9 100644
--- a/doc/relnotes/1_11_8.rst
+++ b/doc/relnotes/1_11_8.rst
@@ -3,9 +3,15 @@ Version 1.11.8, Not Yet Released
* The ChaCha20 cipher has been added
+* CMAC now supports 256 and 512 bit block ciphers, which also allows
+ the use of larger block ciphers with EAX mode. In particular this
+ allows using Threefish in EAX mode.
+
* The antique PBES1 private key encryption scheme (which only supports
DES or 64-bit RC2) has been removed.
+* Skein-512 no longer supports output lengths greater than 512 bits.
+
* Skein did not reset its internal state properly if clear() was
called, causing it to produce incorrect results for the following
message. It was reset correctly in final() so most usages should not
@@ -16,7 +22,7 @@ Version 1.11.8, Not Yet Released
EMSA4 is now called PSSR. Aliases are set which should allow all
current applications to continue to work unmodified.
-* A bug in the CFB encryption caused a few bytes past the end of the
- final block to be read, though the actual output was not affected.
+* A bug in CFB encryption caused a few bytes past the end of the final
+ block to be read. The actual output was not affected.
* Various portability fixes for Visual C++ 2013, OS X, and x86-32.
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;