diff options
-rw-r--r-- | camellia.cpp | 313 | ||||
-rw-r--r-- | camellia.h | 55 | ||||
-rw-r--r-- | shacal2.cpp | 144 | ||||
-rw-r--r-- | shacal2.h | 53 | ||||
-rw-r--r-- | ttmac.cpp | 338 | ||||
-rw-r--r-- | ttmac.h | 38 | ||||
-rw-r--r-- | whrlpool.cpp | 882 | ||||
-rw-r--r-- | whrlpool.h | 31 |
8 files changed, 1854 insertions, 0 deletions
diff --git a/camellia.cpp b/camellia.cpp new file mode 100644 index 0000000..3d8d5e3 --- /dev/null +++ b/camellia.cpp @@ -0,0 +1,313 @@ +// camellia.cpp - by Kevin Springle, 2003 +// This code is hereby placed in the public domain. + +#include "pch.h" + +#ifdef WORD64_AVAILABLE + +#include "camellia.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +// Define internal Camellia function macros + +inline word64 Camellia::Base::F(word64 X) +{ + word32 t1 = (word32)(X >> 32); + word32 t2 = (word32)(X & 0xFFFFFFFFL); + t2= (s2[GETBYTE(t2, 3)] << 24) | + (s3[GETBYTE(t2, 2)] << 16) | + (s4[GETBYTE(t2, 1)] << 8) | + (s1[GETBYTE(t2, 0)]); + t1= (s1[GETBYTE(t1, 3)] << 24) | + (s2[GETBYTE(t1, 2)] << 16) | + (s3[GETBYTE(t1, 1)] << 8) | + (s4[GETBYTE(t1, 0)]); + t1 ^= rotlFixed(t2, 8); + t2 ^= rotlFixed(t1, 16); + t1 ^= rotlFixed(t2, 24); + t2 ^= rotlFixed(t1, 24); + return ((word64)t2 << 32) | (word64)t1; +} + +#define ROUND2(Xp, K1, K2) \ + { (Xp)[1] ^= F((Xp)[0] ^ K1); (Xp)[0] ^= F((Xp)[1] ^ K2); } + +inline void Camellia::Base::FLlayer(word64 *x, word64 K1, word64 K2) +{ + word32 Xl = (word32)(x[0] >> 32); + word32 Xr = (word32)(x[0] & 0xFFFFFFFFL); + Xr ^= rotlFixed(Xl & (word32)(K1 >> 32), 1); + Xl ^= (Xr | (word32)(K1 & 0xFFFFFFFFL)); + x[0] = ((word64)Xl << 32) | (word64)Xr; + + Xl = (word32)(x[1] >> 32); + Xr = (word32)(x[1] & 0xFFFFFFFFL); + Xl ^= (Xr | (word32)(K2 & 0xFFFFFFFFL)); + Xr ^= rotlFixed(Xl & (word32)(K2 >> 32), 1); + x[1] = ((word64)Xl << 32) | (word64)Xr; +} + +inline void rotl128(word64 *x, unsigned int bits) +{ + word64 temp = x[0] >> (64 - bits); + x[0] = (x[0] << bits) | (x[1] >> (64 - bits)); + x[1] = (x[1] << bits) | temp; +} + +void Camellia::Base::UncheckedSetKey(CipherDir dir, const byte *key, unsigned int keylen) +{ + AssertValidKeyLength(keylen); + + m_rounds = (keylen >= 24) ? 4 : 3; + unsigned int kslen = (8 * m_rounds + 2); + m_key.New(8 * kslen); + word64 *ks = m_key; + + FixedSizeSecBlock<word64, 32> keyword; + word64 *kw = keyword; + +#define KL (kw+0) +#define KR (kw+2) +#define KA (kw+4) +#define KB (kw+6) + +//??? GetBlock<word64, BigEndian> keyblock(key); +//??? keyblock(KL[0])(KL[1]); + if (keylen == 16) + { + GetUserKey(BIG_ENDIAN_ORDER, kw, 2, key, keylen); + KA[0] = KL[0]; + KA[1] = KL[1]; + } + else + { + if (keylen == 24) + { + GetUserKey(BIG_ENDIAN_ORDER, kw, 3, key, keylen); + KR[1] = ~KR[0]; + } + else + { + GetUserKey(BIG_ENDIAN_ORDER, kw, 4, key, keylen); + } +//??? keyblock(KR[0]); +//??? if (keylen == 32) +//??? { +//??? keyblock(KR[1]); +//??? } +//??? else +//??? { +//??? KR[1] = ~KR[0]; +//??? } + KA[0] = KL[0] ^ KR[0]; + KA[1] = KL[1] ^ KR[1]; + } + ROUND2(KA, W64LIT(0xA09E667F3BCC908B), W64LIT(0xB67AE8584CAA73B2)); + KA[0] ^= KL[0]; + KA[1] ^= KL[1]; + ROUND2(KA, W64LIT(0xC6EF372FE94F82BE), W64LIT(0x54FF53A5F1D36F1C)); + + if (keylen == 16) + { + ks[0] = KL[0]; ks[1] = KL[1]; + rotl128(KL, 15); + ks[4] = KL[0]; ks[5] = KL[1]; + rotl128(KL, 30); + ks[10] = KL[0]; ks[11] = KL[1]; + rotl128(KL, 15); + ks[13] = KL[1]; + rotl128(KL, 17); + ks[16] = KL[0]; ks[17] = KL[1]; + rotl128(KL, 17); + ks[18] = KL[0]; ks[19] = KL[1]; + rotl128(KL, 17); + ks[22] = KL[0]; ks[23] = KL[1]; + + ks[2] = KA[0]; ks[3] = KA[1]; + rotl128(KA, 15); + ks[6] = KA[0]; ks[7] = KA[1]; + rotl128(KA, 15); + ks[8] = KA[0]; ks[9] = KA[1]; + rotl128(KA, 15); + ks[12] = KA[0]; + rotl128(KA, 15); + ks[14] = KA[0]; ks[15] = KA[1]; + rotl128(KA, 34); + ks[20] = KA[0]; ks[21] = KA[1]; + rotl128(KA, 17); + ks[24] = KA[0]; ks[25] = KA[1]; + } + else + { + KB[0] = KA[0] ^ KR[0]; + KB[1] = KA[1] ^ KR[1]; + ROUND2(KB, W64LIT(0x10E527FADE682D1D), W64LIT(0xB05688C2B3E6C1FD)); + + ks[0] = KL[0]; ks[1] = KL[1]; + rotl128(KL, 45); + ks[12] = KL[0]; ks[13] = KL[1]; + rotl128(KL, 15); + ks[16] = KL[0]; ks[17] = KL[1]; + rotl128(KL, 17); + ks[22] = KL[0]; ks[23] = KL[1]; + rotl128(KL, 34); + ks[30] = KL[0]; ks[31] = KL[1]; + + rotl128(KR, 15); + ks[4] = KR[0]; ks[5] = KR[1]; + rotl128(KR, 15); + ks[8] = KR[0]; ks[9] = KR[1]; + rotl128(KR, 30); + ks[18] = KR[0]; ks[19] = KR[1]; + rotl128(KR, 34); + ks[26] = KR[0]; ks[27] = KR[1]; + + rotl128(KA, 15); + ks[6] = KA[0]; ks[7] = KA[1]; + rotl128(KA, 30); + ks[14] = KA[0]; ks[15] = KA[1]; + rotl128(KA, 32); + ks[24] = KA[0]; ks[25] = KA[1]; + rotl128(KA, 17); + ks[28] = KA[0]; ks[29] = KA[1]; + + ks[2] = KB[0]; ks[3] = KB[1]; + rotl128(KB, 30); + ks[10] = KB[0]; ks[11] = KB[1]; + rotl128(KB, 30); + ks[20] = KB[0]; ks[21] = KB[1]; + rotl128(KB, 51); + ks[32] = KB[0]; ks[33] = KB[1]; + } + + if (dir == DECRYPTION) // reverse key schedule order + { + std::swap(ks[0], ks[kslen-2]); + std::swap(ks[1], ks[kslen-1]); + for (unsigned int i=2; i<kslen/2; i++) + { + std::swap(ks[i], ks[kslen-1-i]); + } + } +} + +typedef BlockGetAndPut<word64, BigEndian> Block; + +void Camellia::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + FixedSizeSecBlock<word64, 16> mb; + word64 *m = mb; + const word64 *ks = m_key; + + Block::Get(inBlock)(m[0])(m[1]); + + m[0] ^= ks[0]; + m[1] ^= ks[1]; + ks += 2; + for (unsigned int i = m_rounds; i > 0; --i) + { + ROUND2(m, ks[0], ks[1]); + ROUND2(m, ks[2], ks[3]); + ROUND2(m, ks[4], ks[5]); + if (i != 1) + { + FLlayer(m, ks[6], ks[7]); + ks += 8; + } + else + { + m[0] ^= ks[7]; + m[1] ^= ks[6]; + } + } + + Block::Put(xorBlock, outBlock)(m[1])(m[0]); +} + +// The Camellia s-boxes + +const byte Camellia::Base::s1[256] = +{ + 112,130,44,236,179,39,192,229,228,133,87,53,234,12,174,65, + 35,239,107,147,69,25,165,33,237,14,79,78,29,101,146,189, + 134,184,175,143,124,235,31,206,62,48,220,95,94,197,11,26, + 166,225,57,202,213,71,93,61,217,1,90,214,81,86,108,77, + 139,13,154,102,251,204,176,45,116,18,43,32,240,177,132,153, + 223,76,203,194,52,126,118,5,109,183,169,49,209,23,4,215, + 20,88,58,97,222,27,17,28,50,15,156,22,83,24,242,34, + 254,68,207,178,195,181,122,145,36,8,232,168,96,252,105,80, + 170,208,160,125,161,137,98,151,84,91,30,149,224,255,100,210, + 16,196,0,72,163,247,117,219,138,3,230,218,9,63,221,148, + 135,92,131,2,205,74,144,51,115,103,246,243,157,127,191,226, + 82,155,216,38,200,55,198,59,129,150,111,75,19,190,99,46, + 233,121,167,140,159,110,188,142,41,245,249,182,47,253,180,89, + 120,152,6,106,231,70,113,186,212,37,171,66,136,162,141,250, + 114,7,185,85,248,238,172,10,54,73,42,104,60,56,241,164, + 64,40,211,123,187,201,67,193,21,227,173,244,119,199,128,158 +}; + +const byte Camellia::Base::s2[256] = +{ + 224,5,88,217,103,78,129,203,201,11,174,106,213,24,93,130, + 70,223,214,39,138,50,75,66,219,28,158,156,58,202,37,123, + 13,113,95,31,248,215,62,157,124,96,185,190,188,139,22,52, + 77,195,114,149,171,142,186,122,179,2,180,173,162,172,216,154, + 23,26,53,204,247,153,97,90,232,36,86,64,225,99,9,51, + 191,152,151,133,104,252,236,10,218,111,83,98,163,46,8,175, + 40,176,116,194,189,54,34,56,100,30,57,44,166,48,229,68, + 253,136,159,101,135,107,244,35,72,16,209,81,192,249,210,160, + 85,161,65,250,67,19,196,47,168,182,60,43,193,255,200,165, + 32,137,0,144,71,239,234,183,21,6,205,181,18,126,187,41, + 15,184,7,4,155,148,33,102,230,206,237,231,59,254,127,197, + 164,55,177,76,145,110,141,118,3,45,222,150,38,125,198,92, + 211,242,79,25,63,220,121,29,82,235,243,109,94,251,105,178, + 240,49,12,212,207,140,226,117,169,74,87,132,17,69,27,245, + 228,14,115,170,241,221,89,20,108,146,84,208,120,112,227,73, + 128,80,167,246,119,147,134,131,42,199,91,233,238,143,1,61 +}; + +const byte Camellia::Base::s3[256] = +{ + 56,65,22,118,217,147,96,242,114,194,171,154,117,6,87,160, + 145,247,181,201,162,140,210,144,246,7,167,39,142,178,73,222, + 67,92,215,199,62,245,143,103,31,24,110,175,47,226,133,13, + 83,240,156,101,234,163,174,158,236,128,45,107,168,43,54,166, + 197,134,77,51,253,102,88,150,58,9,149,16,120,216,66,204, + 239,38,229,97,26,63,59,130,182,219,212,152,232,139,2,235, + 10,44,29,176,111,141,136,14,25,135,78,11,169,12,121,17, + 127,34,231,89,225,218,61,200,18,4,116,84,48,126,180,40, + 85,104,80,190,208,196,49,203,42,173,15,202,112,255,50,105, + 8,98,0,36,209,251,186,237,69,129,115,109,132,159,238,74, + 195,46,193,1,230,37,72,153,185,179,123,249,206,191,223,113, + 41,205,108,19,100,155,99,157,192,75,183,165,137,95,177,23, + 244,188,211,70,207,55,94,71,148,250,252,91,151,254,90,172, + 60,76,3,53,243,35,184,93,106,146,213,33,68,81,198,125, + 57,131,220,170,124,119,86,5,27,164,21,52,30,28,248,82, + 32,20,233,189,221,228,161,224,138,241,214,122,187,227,64,79 +}; + +const byte Camellia::Base::s4[256] = +{ + 112,44,179,192,228,87,234,174,35,107,69,165,237,79,29,146, + 134,175,124,31,62,220,94,11,166,57,213,93,217,90,81,108, + 139,154,251,176,116,43,240,132,223,203,52,118,109,169,209,4, + 20,58,222,17,50,156,83,242,254,207,195,122,36,232,96,105, + 170,160,161,98,84,30,224,100,16,0,163,117,138,230,9,221, + 135,131,205,144,115,246,157,191,82,216,200,198,129,111,19,99, + 233,167,159,188,41,249,47,180,120,6,231,113,212,171,136,141, + 114,185,248,172,54,42,60,241,64,211,187,67,21,173,119,128, + 130,236,39,229,133,53,12,65,239,147,25,33,14,78,101,189, + 184,143,235,206,48,95,197,26,225,202,71,61,1,214,86,77, + 13,102,204,45,18,32,177,153,76,194,126,5,183,49,23,215, + 88,97,27,28,15,22,24,34,68,178,181,145,8,168,252,80, + 208,125,137,151,91,149,255,210,196,72,247,219,3,218,63,148, + 92,2,74,51,103,243,127,226,155,38,55,59,150,75,190,46, + 121,140,110,142,245,182,253,89,152,106,70,186,37,66,162,250, + 7,85,238,10,73,104,56,164,40,123,201,193,227,244,199,158 +}; + +NAMESPACE_END + +#endif // WORD64_AVAILABLE diff --git a/camellia.h b/camellia.h new file mode 100644 index 0000000..8e15c11 --- /dev/null +++ b/camellia.h @@ -0,0 +1,55 @@ +#ifndef CRYPTOPP_CAMELLIA_H +#define CRYPTOPP_CAMELLIA_H + +#include "config.h" + +#ifdef WORD64_AVAILABLE + +/** \file +*/ + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +struct Camellia_Info : public FixedBlockSize<16>, public VariableKeyLength<16, 16, 32, 8> +{ + static const char *StaticAlgorithmName() {return "Camellia";} +}; + +/// <a href="http://www.weidai.com/scan-mirror/cs.html#Camellia">Camellia</a> +class Camellia : public Camellia_Info, public BlockCipherDocumentation +{ + class Base : public BlockCipherBaseTemplate<Camellia_Info> + { + public: + void UncheckedSetKey(CipherDir dir, const byte *key, unsigned int keylen); + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + + protected: + static word64 F(word64 X); + static void FLlayer(word64 *x, word64 K1, word64 K2); + + static const byte s1[256]; + static const byte s2[256]; + static const byte s3[256]; + static const byte s4[256]; + + unsigned int m_rounds; + SecBlock<word64> m_key; + }; + +public: + typedef BlockCipherTemplate<ENCRYPTION, Base> Encryption; + typedef BlockCipherTemplate<DECRYPTION, Base> Decryption; +}; + +typedef Camellia::Encryption CamelliaEncryption; +typedef Camellia::Decryption CamelliaDecryption; + +NAMESPACE_END + +#endif + +#endif diff --git a/shacal2.cpp b/shacal2.cpp new file mode 100644 index 0000000..971aec0 --- /dev/null +++ b/shacal2.cpp @@ -0,0 +1,144 @@ +// shacal2.cpp - by Kevin Springle, 2003 +// +// Portions of this code were derived from +// Wei Dai's implementation of SHA-2 +// +// The original code and all modifications are in the public domain. + +#include "pch.h" +#include "shacal2.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +// SHACAL-2 function and round definitions + +#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22)) +#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25)) +#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3)) +#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10)) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) ((x&y)|(z&(x|y))) + +/* R is the SHA-256 round function. */ +/* This macro increments the k argument as a side effect. */ +#define R(a,b,c,d,e,f,g,h,k) \ + h+=S1(e)+Ch(e,f,g)+*k++;d+=h;h+=S0(a)+Maj(a,b,c); + +/* P is the inverse of the SHA-256 round function. */ +/* This macro decrements the k argument as a side effect. */ +#define P(a,b,c,d,e,f,g,h,k) \ + h-=S0(a)+Maj(a,b,c);d-=h;h-=S1(e)+Ch(e,f,g)+*--k; + +void SHACAL2::Base::UncheckedSetKey(CipherDir dir, const byte *userKey, unsigned int keylen) +{ + AssertValidKeyLength(keylen); + + word32 *rk = m_key; + unsigned int i; + + GetUserKey(BIG_ENDIAN_ORDER, rk, keylen/4, userKey, keylen); + if (keylen != MAX_KEYLENGTH) + { + memset(rk + keylen/4, 0, MAX_KEYLENGTH - keylen); + } + for (i = 0; i < 48; i++, rk++) + { + rk[16] = rk[0] + s0(rk[1]) + rk[9] + s1(rk[14]); + rk[0] += K[i]; + } + for (i = 48; i < 64; i++, rk++) + { + rk[0] += K[i]; + } +} + +typedef BlockGetAndPut<word32, BigEndian> Block; + +void SHACAL2::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 a, b, c, d, e, f, g, h; + const word32 *rk = m_key; + + /* + * map byte array block to cipher state: + */ + Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h); + + // Perform SHA-256 transformation. + + /* 64 operations, partially loop unrolled */ + for (unsigned int j=0; j<64; j+=8) + { + R(a,b,c,d,e,f,g,h,rk); + R(h,a,b,c,d,e,f,g,rk); + R(g,h,a,b,c,d,e,f,rk); + R(f,g,h,a,b,c,d,e,rk); + R(e,f,g,h,a,b,c,d,rk); + R(d,e,f,g,h,a,b,c,rk); + R(c,d,e,f,g,h,a,b,rk); + R(b,c,d,e,f,g,h,a,rk); + } + + /* + * map cipher state to byte array block: + */ + + Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h); +} + +void SHACAL2::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 a, b, c, d, e, f, g, h; + const word32 *rk = m_key + 64; + + /* + * map byte array block to cipher state: + */ + Block::Get(inBlock)(a)(b)(c)(d)(e)(f)(g)(h); + + // Perform inverse SHA-256 transformation. + + /* 64 operations, partially loop unrolled */ + for (unsigned int j=0; j<64; j+=8) + { + P(b,c,d,e,f,g,h,a,rk); + P(c,d,e,f,g,h,a,b,rk); + P(d,e,f,g,h,a,b,c,rk); + P(e,f,g,h,a,b,c,d,rk); + P(f,g,h,a,b,c,d,e,rk); + P(g,h,a,b,c,d,e,f,rk); + P(h,a,b,c,d,e,f,g,rk); + P(a,b,c,d,e,f,g,h,rk); + } + + /* + * map cipher state to byte array block: + */ + + Block::Put(xorBlock, outBlock)(a)(b)(c)(d)(e)(f)(g)(h); +} + +// The SHACAL-2 round constants are identical to the SHA-256 round constants. +const word32 SHACAL2::Base::K[64] = +{ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +NAMESPACE_END diff --git a/shacal2.h b/shacal2.h new file mode 100644 index 0000000..8208760 --- /dev/null +++ b/shacal2.h @@ -0,0 +1,53 @@ +#ifndef CRYPTOPP_SHACAL2_H +#define CRYPTOPP_SHACAL2_H + +/** \file +*/ + +#include "seckey.h" +#include "secblock.h" + +NAMESPACE_BEGIN(CryptoPP) + +struct SHACAL2_Info : public FixedBlockSize<32>, public VariableKeyLength<16, 16, 64> +{ + static const char *StaticAlgorithmName() {return "SHACAL-2";} +}; + +/// <a href="http://www.weidai.com/scan-mirror/cs.html#SHACAL-2">SHACAL-2</a> +class SHACAL2 : public SHACAL2_Info, public BlockCipherDocumentation +{ + class Base : public BlockCipherBaseTemplate<SHACAL2_Info> + { + public: + void UncheckedSetKey(CipherDir direction, const byte *userKey, unsigned int length); + + protected: + FixedSizeSecBlock<word32, 64> m_key; + + static const word32 K[64]; + }; + + class Enc : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + + class Dec : public Base + { + public: + void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const; + }; + +public: + typedef BlockCipherTemplate<ENCRYPTION, Enc> Encryption; + typedef BlockCipherTemplate<DECRYPTION, Dec> Decryption; +}; + +typedef SHACAL2::Encryption SHACAL2Encryption; +typedef SHACAL2::Decryption SHACAL2Decryption; + +NAMESPACE_END + +#endif diff --git a/ttmac.cpp b/ttmac.cpp new file mode 100644 index 0000000..208528d --- /dev/null +++ b/ttmac.cpp @@ -0,0 +1,338 @@ +// ttmac.cpp - written and placed in the public domain by Kevin Springle + +#include "pch.h" +#include "ttmac.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +void TTMAC_Base::UncheckedSetKey(const byte *userKey, unsigned int keylength) +{ + AssertValidKeyLength(keylength); + + memcpy(m_key, userKey, KEYLENGTH); + CorrectEndianess(m_key, m_key, KEYLENGTH); + + Init(); +} + +void TTMAC_Base::Init() +{ + m_digest[0] = m_digest[5] = m_key[0]; + m_digest[1] = m_digest[6] = m_key[1]; + m_digest[2] = m_digest[7] = m_key[2]; + m_digest[3] = m_digest[8] = m_key[3]; + m_digest[4] = m_digest[9] = m_key[4]; +} + +void TTMAC_Base::TruncatedFinal(byte *hash, unsigned int size) +{ + PadLastBlock(BlockSize() - 2*sizeof(HashWordType)); + CorrectEndianess(m_data, m_data, BlockSize() - 2*sizeof(HashWordType)); + + m_data[m_data.size()-2] = GetBitCountLo(); + m_data[m_data.size()-1] = GetBitCountHi(); + + Transform(m_digest, m_data, true); + + word32 t2 = m_digest[2]; + word32 t3 = m_digest[3]; + if (size != DIGESTSIZE) + { + switch (size) + { + case 16: + m_digest[3] += m_digest[1] + m_digest[4]; + + case 12: + m_digest[2] += m_digest[0] + t3; + + case 8: + m_digest[0] += m_digest[1] + t3; + m_digest[1] += m_digest[4] + t2; + break; + + case 4: + m_digest[0] += + m_digest[1] + + m_digest[2] + + m_digest[3] + + m_digest[4]; + break; + + case 0: + // Used by HashTransformation::Restart() + break; + + default: + throw InvalidArgument("TTMAC_Base: can't truncate a Two-Track-MAC 20 byte digest to " + IntToString(size) + " bytes"); + break; + } + } + + CorrectEndianess(m_digest, m_digest, size); + memcpy(hash, m_digest, size); + + Restart(); // reinit for next use +} + +// RIPEMD-160 definitions used by Two-Track-MAC + +#define F(x, y, z) (x ^ y ^ z) +#define G(x, y, z) (z ^ (x & (y^z))) +#define H(x, y, z) (z ^ (x | ~y)) +#define I(x, y, z) (y ^ (z & (x^y))) +#define J(x, y, z) (x ^ (y | ~z)) + +#define k0 0 +#define k1 0x5a827999UL +#define k2 0x6ed9eba1UL +#define k3 0x8f1bbcdcUL +#define k4 0xa953fd4eUL +#define k5 0x50a28be6UL +#define k6 0x5c4dd124UL +#define k7 0x6d703ef3UL +#define k8 0x7a6d76e9UL +#define k9 0 + +void TTMAC_Base::Transform(word32 *digest, const word32 *X, bool last) +{ +#define Subround(f, a, b, c, d, e, x, s, k) \ + a += f(b, c, d) + x + k;\ + a = rotlFixed((word32)a, s) + e;\ + c = rotlFixed((word32)c, 10U) + + word32 a1, b1, c1, d1, e1, a2, b2, c2, d2, e2; + word32 *trackA, *trackB; + + if (!last) + { + trackA = digest; + trackB = digest+5; + } + else + { + trackB = digest; + trackA = digest+5; + } + a1 = trackA[0]; + b1 = trackA[1]; + c1 = trackA[2]; + d1 = trackA[3]; + e1 = trackA[4]; + a2 = trackB[0]; + b2 = trackB[1]; + c2 = trackB[2]; + d2 = trackB[3]; + e2 = trackB[4]; + + Subround(F, a1, b1, c1, d1, e1, X[ 0], 11, k0); + Subround(F, e1, a1, b1, c1, d1, X[ 1], 14, k0); + Subround(F, d1, e1, a1, b1, c1, X[ 2], 15, k0); + Subround(F, c1, d1, e1, a1, b1, X[ 3], 12, k0); + Subround(F, b1, c1, d1, e1, a1, X[ 4], 5, k0); + Subround(F, a1, b1, c1, d1, e1, X[ 5], 8, k0); + Subround(F, e1, a1, b1, c1, d1, X[ 6], 7, k0); + Subround(F, d1, e1, a1, b1, c1, X[ 7], 9, k0); + Subround(F, c1, d1, e1, a1, b1, X[ 8], 11, k0); + Subround(F, b1, c1, d1, e1, a1, X[ 9], 13, k0); + Subround(F, a1, b1, c1, d1, e1, X[10], 14, k0); + Subround(F, e1, a1, b1, c1, d1, X[11], 15, k0); + Subround(F, d1, e1, a1, b1, c1, X[12], 6, k0); + Subround(F, c1, d1, e1, a1, b1, X[13], 7, k0); + Subround(F, b1, c1, d1, e1, a1, X[14], 9, k0); + Subround(F, a1, b1, c1, d1, e1, X[15], 8, k0); + + Subround(G, e1, a1, b1, c1, d1, X[ 7], 7, k1); + Subround(G, d1, e1, a1, b1, c1, X[ 4], 6, k1); + Subround(G, c1, d1, e1, a1, b1, X[13], 8, k1); + Subround(G, b1, c1, d1, e1, a1, X[ 1], 13, k1); + Subround(G, a1, b1, c1, d1, e1, X[10], 11, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 6], 9, k1); + Subround(G, d1, e1, a1, b1, c1, X[15], 7, k1); + Subround(G, c1, d1, e1, a1, b1, X[ 3], 15, k1); + Subround(G, b1, c1, d1, e1, a1, X[12], 7, k1); + Subround(G, a1, b1, c1, d1, e1, X[ 0], 12, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 9], 15, k1); + Subround(G, d1, e1, a1, b1, c1, X[ 5], 9, k1); + Subround(G, c1, d1, e1, a1, b1, X[ 2], 11, k1); + Subround(G, b1, c1, d1, e1, a1, X[14], 7, k1); + Subround(G, a1, b1, c1, d1, e1, X[11], 13, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 8], 12, k1); + + Subround(H, d1, e1, a1, b1, c1, X[ 3], 11, k2); + Subround(H, c1, d1, e1, a1, b1, X[10], 13, k2); + Subround(H, b1, c1, d1, e1, a1, X[14], 6, k2); + Subround(H, a1, b1, c1, d1, e1, X[ 4], 7, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 9], 14, k2); + Subround(H, d1, e1, a1, b1, c1, X[15], 9, k2); + Subround(H, c1, d1, e1, a1, b1, X[ 8], 13, k2); + Subround(H, b1, c1, d1, e1, a1, X[ 1], 15, k2); + Subround(H, a1, b1, c1, d1, e1, X[ 2], 14, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 7], 8, k2); + Subround(H, d1, e1, a1, b1, c1, X[ 0], 13, k2); + Subround(H, c1, d1, e1, a1, b1, X[ 6], 6, k2); + Subround(H, b1, c1, d1, e1, a1, X[13], 5, k2); + Subround(H, a1, b1, c1, d1, e1, X[11], 12, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 5], 7, k2); + Subround(H, d1, e1, a1, b1, c1, X[12], 5, k2); + + Subround(I, c1, d1, e1, a1, b1, X[ 1], 11, k3); + Subround(I, b1, c1, d1, e1, a1, X[ 9], 12, k3); + Subround(I, a1, b1, c1, d1, e1, X[11], 14, k3); + Subround(I, e1, a1, b1, c1, d1, X[10], 15, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 0], 14, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 8], 15, k3); + Subround(I, b1, c1, d1, e1, a1, X[12], 9, k3); + Subround(I, a1, b1, c1, d1, e1, X[ 4], 8, k3); + Subround(I, e1, a1, b1, c1, d1, X[13], 9, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 3], 14, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 7], 5, k3); + Subround(I, b1, c1, d1, e1, a1, X[15], 6, k3); + Subround(I, a1, b1, c1, d1, e1, X[14], 8, k3); + Subround(I, e1, a1, b1, c1, d1, X[ 5], 6, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 6], 5, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 2], 12, k3); + + Subround(J, b1, c1, d1, e1, a1, X[ 4], 9, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 0], 15, k4); + Subround(J, e1, a1, b1, c1, d1, X[ 5], 5, k4); + Subround(J, d1, e1, a1, b1, c1, X[ 9], 11, k4); + Subround(J, c1, d1, e1, a1, b1, X[ 7], 6, k4); + Subround(J, b1, c1, d1, e1, a1, X[12], 8, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 2], 13, k4); + Subround(J, e1, a1, b1, c1, d1, X[10], 12, k4); + Subround(J, d1, e1, a1, b1, c1, X[14], 5, k4); + Subround(J, c1, d1, e1, a1, b1, X[ 1], 12, k4); + Subround(J, b1, c1, d1, e1, a1, X[ 3], 13, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 8], 14, k4); + Subround(J, e1, a1, b1, c1, d1, X[11], 11, k4); + Subround(J, d1, e1, a1, b1, c1, X[ 6], 8, k4); + Subround(J, c1, d1, e1, a1, b1, X[15], 5, k4); + Subround(J, b1, c1, d1, e1, a1, X[13], 6, k4); + + Subround(J, a2, b2, c2, d2, e2, X[ 5], 8, k5); + Subround(J, e2, a2, b2, c2, d2, X[14], 9, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 7], 9, k5); + Subround(J, c2, d2, e2, a2, b2, X[ 0], 11, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 9], 13, k5); + Subround(J, a2, b2, c2, d2, e2, X[ 2], 15, k5); + Subround(J, e2, a2, b2, c2, d2, X[11], 15, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 4], 5, k5); + Subround(J, c2, d2, e2, a2, b2, X[13], 7, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 6], 7, k5); + Subround(J, a2, b2, c2, d2, e2, X[15], 8, k5); + Subround(J, e2, a2, b2, c2, d2, X[ 8], 11, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 1], 14, k5); + Subround(J, c2, d2, e2, a2, b2, X[10], 14, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 3], 12, k5); + Subround(J, a2, b2, c2, d2, e2, X[12], 6, k5); + + Subround(I, e2, a2, b2, c2, d2, X[ 6], 9, k6); + Subround(I, d2, e2, a2, b2, c2, X[11], 13, k6); + Subround(I, c2, d2, e2, a2, b2, X[ 3], 15, k6); + Subround(I, b2, c2, d2, e2, a2, X[ 7], 7, k6); + Subround(I, a2, b2, c2, d2, e2, X[ 0], 12, k6); + Subround(I, e2, a2, b2, c2, d2, X[13], 8, k6); + Subround(I, d2, e2, a2, b2, c2, X[ 5], 9, k6); + Subround(I, c2, d2, e2, a2, b2, X[10], 11, k6); + Subround(I, b2, c2, d2, e2, a2, X[14], 7, k6); + Subround(I, a2, b2, c2, d2, e2, X[15], 7, k6); + Subround(I, e2, a2, b2, c2, d2, X[ 8], 12, k6); + Subround(I, d2, e2, a2, b2, c2, X[12], 7, k6); + Subround(I, c2, d2, e2, a2, b2, X[ 4], 6, k6); + Subround(I, b2, c2, d2, e2, a2, X[ 9], 15, k6); + Subround(I, a2, b2, c2, d2, e2, X[ 1], 13, k6); + Subround(I, e2, a2, b2, c2, d2, X[ 2], 11, k6); + + Subround(H, d2, e2, a2, b2, c2, X[15], 9, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 5], 7, k7); + Subround(H, b2, c2, d2, e2, a2, X[ 1], 15, k7); + Subround(H, a2, b2, c2, d2, e2, X[ 3], 11, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 7], 8, k7); + Subround(H, d2, e2, a2, b2, c2, X[14], 6, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 6], 6, k7); + Subround(H, b2, c2, d2, e2, a2, X[ 9], 14, k7); + Subround(H, a2, b2, c2, d2, e2, X[11], 12, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 8], 13, k7); + Subround(H, d2, e2, a2, b2, c2, X[12], 5, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 2], 14, k7); + Subround(H, b2, c2, d2, e2, a2, X[10], 13, k7); + Subround(H, a2, b2, c2, d2, e2, X[ 0], 13, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 4], 7, k7); + Subround(H, d2, e2, a2, b2, c2, X[13], 5, k7); + + Subround(G, c2, d2, e2, a2, b2, X[ 8], 15, k8); + Subround(G, b2, c2, d2, e2, a2, X[ 6], 5, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 4], 8, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 1], 11, k8); + Subround(G, d2, e2, a2, b2, c2, X[ 3], 14, k8); + Subround(G, c2, d2, e2, a2, b2, X[11], 14, k8); + Subround(G, b2, c2, d2, e2, a2, X[15], 6, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 0], 14, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 5], 6, k8); + Subround(G, d2, e2, a2, b2, c2, X[12], 9, k8); + Subround(G, c2, d2, e2, a2, b2, X[ 2], 12, k8); + Subround(G, b2, c2, d2, e2, a2, X[13], 9, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 9], 12, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 7], 5, k8); + Subround(G, d2, e2, a2, b2, c2, X[10], 15, k8); + Subround(G, c2, d2, e2, a2, b2, X[14], 8, k8); + + Subround(F, b2, c2, d2, e2, a2, X[12], 8, k9); + Subround(F, a2, b2, c2, d2, e2, X[15], 5, k9); + Subround(F, e2, a2, b2, c2, d2, X[10], 12, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 4], 9, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 1], 12, k9); + Subround(F, b2, c2, d2, e2, a2, X[ 5], 5, k9); + Subround(F, a2, b2, c2, d2, e2, X[ 8], 14, k9); + Subround(F, e2, a2, b2, c2, d2, X[ 7], 6, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 6], 8, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 2], 13, k9); + Subround(F, b2, c2, d2, e2, a2, X[13], 6, k9); + Subround(F, a2, b2, c2, d2, e2, X[14], 5, k9); + Subround(F, e2, a2, b2, c2, d2, X[ 0], 15, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 3], 13, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 9], 11, k9); + Subround(F, b2, c2, d2, e2, a2, X[11], 11, k9); + + a1 -= trackA[0]; + b1 -= trackA[1]; + c1 -= trackA[2]; + d1 -= trackA[3]; + e1 -= trackA[4]; + a2 -= trackB[0]; + b2 -= trackB[1]; + c2 -= trackB[2]; + d2 -= trackB[3]; + e2 -= trackB[4]; + + if (!last) + { + trackA[0] = (b1 + e1) - d2; + trackA[1] = c1 - e2; + trackA[2] = d1 - a2; + trackA[3] = e1 - b2; + trackA[4] = a1 - c2; + trackB[0] = d1 - e2; + trackB[1] = (e1 + c1) - a2; + trackB[2] = a1 - b2; + trackB[3] = b1 - c2; + trackB[4] = c1 - d2; + } + else + { + trackB[0] = a2 - a1; + trackB[1] = b2 - b1; + trackB[2] = c2 - c1; + trackB[3] = d2 - d1; + trackB[4] = e2 - e1; + trackA[0] = 0; + trackA[1] = 0; + trackA[2] = 0; + trackA[3] = 0; + trackA[4] = 0; + } +} + +NAMESPACE_END @@ -0,0 +1,38 @@ +// ttmac.h - written and placed in the public domain by Kevin Springle + +#ifndef CRYPTOPP_TTMAC_H +#define CRYPTOPP_TTMAC_H + +#include "seckey.h" +#include "iterhash.h" + +NAMESPACE_BEGIN(CryptoPP) +//! <a href="http://www.eskimo.com/~weidai/scan-mirror/mac.html#Two-Track-MAC">Two-Track-MAC</a> +/*! 160 Bit MAC with 160 Bit Key */ + +class TTMAC_Base : public FixedKeyLength<20>, public IteratedHash<word32, LittleEndian, 64, MessageAuthenticationCode> +{ +public: + static std::string StaticAlgorithmName() {return std::string("Two-Track-MAC");} + enum {DIGESTSIZE=20}; + + TTMAC_Base() : IteratedHash<word32, LittleEndian, 64, MessageAuthenticationCode>(DIGESTSIZE*2) {} + + unsigned int DigestSize() const {return DIGESTSIZE;}; + void UncheckedSetKey(const byte *userKey, unsigned int keylength); + void TruncatedFinal(byte *mac, unsigned int size); + +protected: + static void Transform (word32 *digest, const word32 *X, bool last); + void vTransform(const word32 *data) {Transform(m_digest, data, false);} + void Init(); + + FixedSizeSecBlock<word32, DIGESTSIZE> m_key; +}; + +//! <a href="http://www.weidai.com/scan-mirror/mac.html#TTMAC">Two-Track-MAC</a> +typedef MessageAuthenticationCodeTemplate<TTMAC_Base> TTMAC; + +NAMESPACE_END + +#endif diff --git a/whrlpool.cpp b/whrlpool.cpp new file mode 100644 index 0000000..6f483ef --- /dev/null +++ b/whrlpool.cpp @@ -0,0 +1,882 @@ +// Whrlpool.cpp - modified by Kevin Springle from +// Paulo Barreto and Vincent Rijmen's public domain code, whirlpool.c. +// Any modifications are placed in the public domain + +// This is the original introductory comment: + +/** + * The Whirlpool hashing function. + * + * <P> + * <b>References</b> + * + * <P> + * The Whirlpool algorithm was developed by + * <a href="mailto:pbarreto@scopus.com.br">Paulo S. L. M. Barreto</a> and + * <a href="mailto:vincent.rijmen@cryptomathic.com">Vincent Rijmen</a>. + * + * See + * P.S.L.M. Barreto, V. Rijmen, + * ``The Whirlpool hashing function,'' + * NESSIE submission, 2000 (tweaked version, 2001), + * <https://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/whirlpool.zip> + * + * @author Paulo S.L.M. Barreto + * @author Vincent Rijmen. + * + * @version 2.1 (2001.09.01) + * + * ============================================================================= + * + * Differences from version 1.0: + * + * - Original S-box replaced by the tweaked, hardware-efficient version. + * + * ============================================================================= + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "pch.h" + +#ifdef WORD64_AVAILABLE + +#include "whrlpool.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +void Whirlpool_TestInstantiations() +{ + Whirlpool x; +} + +void Whirlpool::Init() +{ + m_digest[0] = m_digest[1] = m_digest[2] = m_digest[3] = + m_digest[4] = m_digest[5] = m_digest[6] = m_digest[7] = 0; +} + +void Whirlpool::TruncatedFinal(byte *hash, unsigned int size) +{ + ThrowIfInvalidTruncatedSize(size); + + PadLastBlock(32); + CorrectEndianess(m_data, m_data, 32); + + m_data[m_data.size()-4] = 0; + m_data[m_data.size()-3] = 0; + m_data[m_data.size()-2] = GetBitCountHi(); + m_data[m_data.size()-1] = GetBitCountLo(); + + Transform(m_digest, m_data); + CorrectEndianess(m_digest, m_digest, DigestSize()); + memcpy(hash, m_digest, size); + + Restart(); // reinit for next use +} + +/* + * The number of rounds of the internal dedicated block cipher. + */ +#define R 10 + +/* + * Though Whirlpool is endianness-neutral, the encryption tables are listed + * in BIG-ENDIAN format, which is adopted throughout this implementation + * (but little-endian notation would be equally suitable if consistently + * employed). + */ + +static const word64 C0[256] = { + W64LIT(0x1818281878c0d878), W64LIT(0x23236523af0526af), + W64LIT(0xc6c657c6f97eb8f9), W64LIT(0xe8e825e86f13fb6f), + W64LIT(0x87879487a14ccba1), W64LIT(0xb8b8d5b862a91162), + W64LIT(0x0101030105080905), W64LIT(0x4f4fd14f6e420d6e), + W64LIT(0x36365a36eead9bee), W64LIT(0xa6a6f7a60459ff04), + W64LIT(0xd2d26bd2bdde0cbd), W64LIT(0xf5f502f506fb0e06), + W64LIT(0x79798b7980ef9680), W64LIT(0x6f6fb16fce5f30ce), + W64LIT(0x9191ae91effc6def), W64LIT(0x5252f65207aaf807), + W64LIT(0x6060a060fd2747fd), W64LIT(0xbcbcd9bc76893576), + W64LIT(0x9b9bb09bcdac37cd), W64LIT(0x8e8e8f8e8c048a8c), + W64LIT(0xa3a3f8a31571d215), W64LIT(0x0c0c140c3c606c3c), + W64LIT(0x7b7b8d7b8aff848a), W64LIT(0x35355f35e1b580e1), + W64LIT(0x1d1d271d69e8f569), W64LIT(0xe0e03de04753b347), + W64LIT(0xd7d764d7acf621ac), W64LIT(0xc2c25bc2ed5e9ced), + W64LIT(0x2e2e722e966d4396), W64LIT(0x4b4bdd4b7a62297a), + W64LIT(0xfefe1ffe21a35d21), W64LIT(0x5757f9571682d516), + W64LIT(0x15153f1541a8bd41), W64LIT(0x77779977b69fe8b6), + W64LIT(0x37375937eba592eb), W64LIT(0xe5e532e5567b9e56), + W64LIT(0x9f9fbc9fd98c13d9), W64LIT(0xf0f00df017d32317), + W64LIT(0x4a4ade4a7f6a207f), W64LIT(0xdada73da959e4495), + W64LIT(0x5858e85825faa225), W64LIT(0xc9c946c9ca06cfca), + W64LIT(0x29297b298d557c8d), W64LIT(0x0a0a1e0a22505a22), + W64LIT(0xb1b1ceb14fe1504f), W64LIT(0xa0a0fda01a69c91a), + W64LIT(0x6b6bbd6bda7f14da), W64LIT(0x85859285ab5cd9ab), + W64LIT(0xbdbddabd73813c73), W64LIT(0x5d5de75d34d28f34), + W64LIT(0x1010301050809050), W64LIT(0xf4f401f403f30703), + W64LIT(0xcbcb40cbc016ddc0), W64LIT(0x3e3e423ec6edd3c6), + W64LIT(0x05050f0511282d11), W64LIT(0x6767a967e61f78e6), + W64LIT(0xe4e431e453739753), W64LIT(0x27276927bb2502bb), + W64LIT(0x4141c34158327358), W64LIT(0x8b8b808b9d2ca79d), + W64LIT(0xa7a7f4a70151f601), W64LIT(0x7d7d877d94cfb294), + W64LIT(0x9595a295fbdc49fb), W64LIT(0xd8d875d89f8e569f), + W64LIT(0xfbfb10fb308b7030), W64LIT(0xeeee2fee7123cd71), + W64LIT(0x7c7c847c91c7bb91), W64LIT(0x6666aa66e31771e3), + W64LIT(0xdddd7add8ea67b8e), W64LIT(0x171739174bb8af4b), + W64LIT(0x4747c94746024546), W64LIT(0x9e9ebf9edc841adc), + W64LIT(0xcaca43cac51ed4c5), W64LIT(0x2d2d772d99755899), + W64LIT(0xbfbfdcbf79912e79), W64LIT(0x070709071b383f1b), + W64LIT(0xadadeaad2301ac23), W64LIT(0x5a5aee5a2feab02f), + W64LIT(0x83839883b56cefb5), W64LIT(0x33335533ff85b6ff), + W64LIT(0x6363a563f23f5cf2), W64LIT(0x020206020a10120a), + W64LIT(0xaaaae3aa38399338), W64LIT(0x71719371a8afdea8), + W64LIT(0xc8c845c8cf0ec6cf), W64LIT(0x19192b197dc8d17d), + W64LIT(0x4949db4970723b70), W64LIT(0xd9d976d99a865f9a), + W64LIT(0xf2f20bf21dc3311d), W64LIT(0xe3e338e3484ba848), + W64LIT(0x5b5bed5b2ae2b92a), W64LIT(0x888885889234bc92), + W64LIT(0x9a9ab39ac8a43ec8), W64LIT(0x26266a26be2d0bbe), + W64LIT(0x32325632fa8dbffa), W64LIT(0xb0b0cdb04ae9594a), + W64LIT(0xe9e926e96a1bf26a), W64LIT(0x0f0f110f33787733), + W64LIT(0xd5d562d5a6e633a6), W64LIT(0x80809d80ba74f4ba), + W64LIT(0xbebedfbe7c99277c), W64LIT(0xcdcd4acdde26ebde), + W64LIT(0x34345c34e4bd89e4), W64LIT(0x4848d848757a3275), + W64LIT(0xffff1cff24ab5424), W64LIT(0x7a7a8e7a8ff78d8f), + W64LIT(0x9090ad90eaf464ea), W64LIT(0x5f5fe15f3ec29d3e), + W64LIT(0x20206020a01d3da0), W64LIT(0x6868b868d5670fd5), + W64LIT(0x1a1a2e1a72d0ca72), W64LIT(0xaeaeefae2c19b72c), + W64LIT(0xb4b4c1b45ec97d5e), W64LIT(0x5454fc54199ace19), + W64LIT(0x9393a893e5ec7fe5), W64LIT(0x22226622aa0d2faa), + W64LIT(0x6464ac64e90763e9), W64LIT(0xf1f10ef112db2a12), + W64LIT(0x73739573a2bfcca2), W64LIT(0x121236125a90825a), + W64LIT(0x4040c0405d3a7a5d), W64LIT(0x0808180828404828), + W64LIT(0xc3c358c3e85695e8), W64LIT(0xecec29ec7b33df7b), + W64LIT(0xdbdb70db90964d90), W64LIT(0xa1a1fea11f61c01f), + W64LIT(0x8d8d8a8d831c9183), W64LIT(0x3d3d473dc9f5c8c9), + W64LIT(0x9797a497f1cc5bf1), W64LIT(0x0000000000000000), + W64LIT(0xcfcf4ccfd436f9d4), W64LIT(0x2b2b7d2b87456e87), + W64LIT(0x76769a76b397e1b3), W64LIT(0x82829b82b064e6b0), + W64LIT(0xd6d667d6a9fe28a9), W64LIT(0x1b1b2d1b77d8c377), + W64LIT(0xb5b5c2b55bc1745b), W64LIT(0xafafecaf2911be29), + W64LIT(0x6a6abe6adf771ddf), W64LIT(0x5050f0500dbaea0d), + W64LIT(0x4545cf454c12574c), W64LIT(0xf3f308f318cb3818), + W64LIT(0x30305030f09dadf0), W64LIT(0xefef2cef742bc474), + W64LIT(0x3f3f413fc3e5dac3), W64LIT(0x5555ff551c92c71c), + W64LIT(0xa2a2fba21079db10), W64LIT(0xeaea23ea6503e965), + W64LIT(0x6565af65ec0f6aec), W64LIT(0xbabad3ba68b90368), + W64LIT(0x2f2f712f93654a93), W64LIT(0xc0c05dc0e74e8ee7), + W64LIT(0xdede7fde81be6081), W64LIT(0x1c1c241c6ce0fc6c), + W64LIT(0xfdfd1afd2ebb462e), W64LIT(0x4d4dd74d64521f64), + W64LIT(0x9292ab92e0e476e0), W64LIT(0x75759f75bc8ffabc), + W64LIT(0x06060a061e30361e), W64LIT(0x8a8a838a9824ae98), + W64LIT(0xb2b2cbb240f94b40), W64LIT(0xe6e637e659638559), + W64LIT(0x0e0e120e36707e36), W64LIT(0x1f1f211f63f8e763), + W64LIT(0x6262a662f73755f7), W64LIT(0xd4d461d4a3ee3aa3), + W64LIT(0xa8a8e5a832298132), W64LIT(0x9696a796f4c452f4), + W64LIT(0xf9f916f93a9b623a), W64LIT(0xc5c552c5f666a3f6), + W64LIT(0x25256f25b13510b1), W64LIT(0x5959eb5920f2ab20), + W64LIT(0x84849184ae54d0ae), W64LIT(0x72729672a7b7c5a7), + W64LIT(0x39394b39ddd5ecdd), W64LIT(0x4c4cd44c615a1661), + W64LIT(0x5e5ee25e3bca943b), W64LIT(0x7878887885e79f85), + W64LIT(0x38384838d8dde5d8), W64LIT(0x8c8c898c86149886), + W64LIT(0xd1d16ed1b2c617b2), W64LIT(0xa5a5f2a50b41e40b), + W64LIT(0xe2e23be24d43a14d), W64LIT(0x6161a361f82f4ef8), + W64LIT(0xb3b3c8b345f14245), W64LIT(0x21216321a51534a5), + W64LIT(0x9c9cb99cd69408d6), W64LIT(0x1e1e221e66f0ee66), + W64LIT(0x4343c54352226152), W64LIT(0xc7c754c7fc76b1fc), + W64LIT(0xfcfc19fc2bb34f2b), W64LIT(0x04040c0414202414), + W64LIT(0x5151f35108b2e308), W64LIT(0x9999b699c7bc25c7), + W64LIT(0x6d6db76dc44f22c4), W64LIT(0x0d0d170d39686539), + W64LIT(0xfafa13fa35837935), W64LIT(0xdfdf7cdf84b66984), + W64LIT(0x7e7e827e9bd7a99b), W64LIT(0x24246c24b43d19b4), + W64LIT(0x3b3b4d3bd7c5fed7), W64LIT(0xababe0ab3d319a3d), + W64LIT(0xcece4fced13ef0d1), W64LIT(0x1111331155889955), + W64LIT(0x8f8f8c8f890c8389), W64LIT(0x4e4ed24e6b4a046b), + W64LIT(0xb7b7c4b751d16651), W64LIT(0xebeb20eb600be060), + W64LIT(0x3c3c443cccfdc1cc), W64LIT(0x81819e81bf7cfdbf), + W64LIT(0x9494a194fed440fe), W64LIT(0xf7f704f70ceb1c0c), + W64LIT(0xb9b9d6b967a11867), W64LIT(0x131335135f988b5f), + W64LIT(0x2c2c742c9c7d519c), W64LIT(0xd3d368d3b8d605b8), + W64LIT(0xe7e734e75c6b8c5c), W64LIT(0x6e6eb26ecb5739cb), + W64LIT(0xc4c451c4f36eaaf3), W64LIT(0x030305030f181b0f), + W64LIT(0x5656fa56138adc13), W64LIT(0x4444cc44491a5e49), + W64LIT(0x7f7f817f9edfa09e), W64LIT(0xa9a9e6a937218837), + W64LIT(0x2a2a7e2a824d6782), W64LIT(0xbbbbd0bb6db10a6d), + W64LIT(0xc1c15ec1e24687e2), W64LIT(0x5353f55302a2f102), + W64LIT(0xdcdc79dc8bae728b), W64LIT(0x0b0b1d0b27585327), + W64LIT(0x9d9dba9dd39c01d3), W64LIT(0x6c6cb46cc1472bc1), + W64LIT(0x31315331f595a4f5), W64LIT(0x74749c74b987f3b9), + W64LIT(0xf6f607f609e31509), W64LIT(0x4646ca46430a4c43), + W64LIT(0xacace9ac2609a526), W64LIT(0x89898689973cb597), + W64LIT(0x14143c1444a0b444), W64LIT(0xe1e13ee1425bba42), + W64LIT(0x16163a164eb0a64e), W64LIT(0x3a3a4e3ad2cdf7d2), + W64LIT(0x6969bb69d06f06d0), W64LIT(0x09091b092d48412d), + W64LIT(0x70709070ada7d7ad), W64LIT(0xb6b6c7b654d96f54), + W64LIT(0xd0d06dd0b7ce1eb7), W64LIT(0xeded2aed7e3bd67e), + W64LIT(0xcccc49ccdb2ee2db), W64LIT(0x4242c642572a6857), + W64LIT(0x9898b598c2b42cc2), W64LIT(0xa4a4f1a40e49ed0e), + W64LIT(0x28287828885d7588), W64LIT(0x5c5ce45c31da8631), + W64LIT(0xf8f815f83f936b3f), W64LIT(0x86869786a444c2a4), +}; + +static const word64 C1[256] = { + W64LIT(0x781818281878c0d8), W64LIT(0xaf23236523af0526), + W64LIT(0xf9c6c657c6f97eb8), W64LIT(0x6fe8e825e86f13fb), + W64LIT(0xa187879487a14ccb), W64LIT(0x62b8b8d5b862a911), + W64LIT(0x0501010301050809), W64LIT(0x6e4f4fd14f6e420d), + W64LIT(0xee36365a36eead9b), W64LIT(0x04a6a6f7a60459ff), + W64LIT(0xbdd2d26bd2bdde0c), W64LIT(0x06f5f502f506fb0e), + W64LIT(0x8079798b7980ef96), W64LIT(0xce6f6fb16fce5f30), + W64LIT(0xef9191ae91effc6d), W64LIT(0x075252f65207aaf8), + W64LIT(0xfd6060a060fd2747), W64LIT(0x76bcbcd9bc768935), + W64LIT(0xcd9b9bb09bcdac37), W64LIT(0x8c8e8e8f8e8c048a), + W64LIT(0x15a3a3f8a31571d2), W64LIT(0x3c0c0c140c3c606c), + W64LIT(0x8a7b7b8d7b8aff84), W64LIT(0xe135355f35e1b580), + W64LIT(0x691d1d271d69e8f5), W64LIT(0x47e0e03de04753b3), + W64LIT(0xacd7d764d7acf621), W64LIT(0xedc2c25bc2ed5e9c), + W64LIT(0x962e2e722e966d43), W64LIT(0x7a4b4bdd4b7a6229), + W64LIT(0x21fefe1ffe21a35d), W64LIT(0x165757f9571682d5), + W64LIT(0x4115153f1541a8bd), W64LIT(0xb677779977b69fe8), + W64LIT(0xeb37375937eba592), W64LIT(0x56e5e532e5567b9e), + W64LIT(0xd99f9fbc9fd98c13), W64LIT(0x17f0f00df017d323), + W64LIT(0x7f4a4ade4a7f6a20), W64LIT(0x95dada73da959e44), + W64LIT(0x255858e85825faa2), W64LIT(0xcac9c946c9ca06cf), + W64LIT(0x8d29297b298d557c), W64LIT(0x220a0a1e0a22505a), + W64LIT(0x4fb1b1ceb14fe150), W64LIT(0x1aa0a0fda01a69c9), + W64LIT(0xda6b6bbd6bda7f14), W64LIT(0xab85859285ab5cd9), + W64LIT(0x73bdbddabd73813c), W64LIT(0x345d5de75d34d28f), + W64LIT(0x5010103010508090), W64LIT(0x03f4f401f403f307), + W64LIT(0xc0cbcb40cbc016dd), W64LIT(0xc63e3e423ec6edd3), + W64LIT(0x1105050f0511282d), W64LIT(0xe66767a967e61f78), + W64LIT(0x53e4e431e4537397), W64LIT(0xbb27276927bb2502), + W64LIT(0x584141c341583273), W64LIT(0x9d8b8b808b9d2ca7), + W64LIT(0x01a7a7f4a70151f6), W64LIT(0x947d7d877d94cfb2), + W64LIT(0xfb9595a295fbdc49), W64LIT(0x9fd8d875d89f8e56), + W64LIT(0x30fbfb10fb308b70), W64LIT(0x71eeee2fee7123cd), + W64LIT(0x917c7c847c91c7bb), W64LIT(0xe36666aa66e31771), + W64LIT(0x8edddd7add8ea67b), W64LIT(0x4b171739174bb8af), + W64LIT(0x464747c947460245), W64LIT(0xdc9e9ebf9edc841a), + W64LIT(0xc5caca43cac51ed4), W64LIT(0x992d2d772d997558), + W64LIT(0x79bfbfdcbf79912e), W64LIT(0x1b070709071b383f), + W64LIT(0x23adadeaad2301ac), W64LIT(0x2f5a5aee5a2feab0), + W64LIT(0xb583839883b56cef), W64LIT(0xff33335533ff85b6), + W64LIT(0xf26363a563f23f5c), W64LIT(0x0a020206020a1012), + W64LIT(0x38aaaae3aa383993), W64LIT(0xa871719371a8afde), + W64LIT(0xcfc8c845c8cf0ec6), W64LIT(0x7d19192b197dc8d1), + W64LIT(0x704949db4970723b), W64LIT(0x9ad9d976d99a865f), + W64LIT(0x1df2f20bf21dc331), W64LIT(0x48e3e338e3484ba8), + W64LIT(0x2a5b5bed5b2ae2b9), W64LIT(0x92888885889234bc), + W64LIT(0xc89a9ab39ac8a43e), W64LIT(0xbe26266a26be2d0b), + W64LIT(0xfa32325632fa8dbf), W64LIT(0x4ab0b0cdb04ae959), + W64LIT(0x6ae9e926e96a1bf2), W64LIT(0x330f0f110f337877), + W64LIT(0xa6d5d562d5a6e633), W64LIT(0xba80809d80ba74f4), + W64LIT(0x7cbebedfbe7c9927), W64LIT(0xdecdcd4acdde26eb), + W64LIT(0xe434345c34e4bd89), W64LIT(0x754848d848757a32), + W64LIT(0x24ffff1cff24ab54), W64LIT(0x8f7a7a8e7a8ff78d), + W64LIT(0xea9090ad90eaf464), W64LIT(0x3e5f5fe15f3ec29d), + W64LIT(0xa020206020a01d3d), W64LIT(0xd56868b868d5670f), + W64LIT(0x721a1a2e1a72d0ca), W64LIT(0x2caeaeefae2c19b7), + W64LIT(0x5eb4b4c1b45ec97d), W64LIT(0x195454fc54199ace), + W64LIT(0xe59393a893e5ec7f), W64LIT(0xaa22226622aa0d2f), + W64LIT(0xe96464ac64e90763), W64LIT(0x12f1f10ef112db2a), + W64LIT(0xa273739573a2bfcc), W64LIT(0x5a121236125a9082), + W64LIT(0x5d4040c0405d3a7a), W64LIT(0x2808081808284048), + W64LIT(0xe8c3c358c3e85695), W64LIT(0x7becec29ec7b33df), + W64LIT(0x90dbdb70db90964d), W64LIT(0x1fa1a1fea11f61c0), + W64LIT(0x838d8d8a8d831c91), W64LIT(0xc93d3d473dc9f5c8), + W64LIT(0xf19797a497f1cc5b), W64LIT(0x0000000000000000), + W64LIT(0xd4cfcf4ccfd436f9), W64LIT(0x872b2b7d2b87456e), + W64LIT(0xb376769a76b397e1), W64LIT(0xb082829b82b064e6), + W64LIT(0xa9d6d667d6a9fe28), W64LIT(0x771b1b2d1b77d8c3), + W64LIT(0x5bb5b5c2b55bc174), W64LIT(0x29afafecaf2911be), + W64LIT(0xdf6a6abe6adf771d), W64LIT(0x0d5050f0500dbaea), + W64LIT(0x4c4545cf454c1257), W64LIT(0x18f3f308f318cb38), + W64LIT(0xf030305030f09dad), W64LIT(0x74efef2cef742bc4), + W64LIT(0xc33f3f413fc3e5da), W64LIT(0x1c5555ff551c92c7), + W64LIT(0x10a2a2fba21079db), W64LIT(0x65eaea23ea6503e9), + W64LIT(0xec6565af65ec0f6a), W64LIT(0x68babad3ba68b903), + W64LIT(0x932f2f712f93654a), W64LIT(0xe7c0c05dc0e74e8e), + W64LIT(0x81dede7fde81be60), W64LIT(0x6c1c1c241c6ce0fc), + W64LIT(0x2efdfd1afd2ebb46), W64LIT(0x644d4dd74d64521f), + W64LIT(0xe09292ab92e0e476), W64LIT(0xbc75759f75bc8ffa), + W64LIT(0x1e06060a061e3036), W64LIT(0x988a8a838a9824ae), + W64LIT(0x40b2b2cbb240f94b), W64LIT(0x59e6e637e6596385), + W64LIT(0x360e0e120e36707e), W64LIT(0x631f1f211f63f8e7), + W64LIT(0xf76262a662f73755), W64LIT(0xa3d4d461d4a3ee3a), + W64LIT(0x32a8a8e5a8322981), W64LIT(0xf49696a796f4c452), + W64LIT(0x3af9f916f93a9b62), W64LIT(0xf6c5c552c5f666a3), + W64LIT(0xb125256f25b13510), W64LIT(0x205959eb5920f2ab), + W64LIT(0xae84849184ae54d0), W64LIT(0xa772729672a7b7c5), + W64LIT(0xdd39394b39ddd5ec), W64LIT(0x614c4cd44c615a16), + W64LIT(0x3b5e5ee25e3bca94), W64LIT(0x857878887885e79f), + W64LIT(0xd838384838d8dde5), W64LIT(0x868c8c898c861498), + W64LIT(0xb2d1d16ed1b2c617), W64LIT(0x0ba5a5f2a50b41e4), + W64LIT(0x4de2e23be24d43a1), W64LIT(0xf86161a361f82f4e), + W64LIT(0x45b3b3c8b345f142), W64LIT(0xa521216321a51534), + W64LIT(0xd69c9cb99cd69408), W64LIT(0x661e1e221e66f0ee), + W64LIT(0x524343c543522261), W64LIT(0xfcc7c754c7fc76b1), + W64LIT(0x2bfcfc19fc2bb34f), W64LIT(0x1404040c04142024), + W64LIT(0x085151f35108b2e3), W64LIT(0xc79999b699c7bc25), + W64LIT(0xc46d6db76dc44f22), W64LIT(0x390d0d170d396865), + W64LIT(0x35fafa13fa358379), W64LIT(0x84dfdf7cdf84b669), + W64LIT(0x9b7e7e827e9bd7a9), W64LIT(0xb424246c24b43d19), + W64LIT(0xd73b3b4d3bd7c5fe), W64LIT(0x3dababe0ab3d319a), + W64LIT(0xd1cece4fced13ef0), W64LIT(0x5511113311558899), + W64LIT(0x898f8f8c8f890c83), W64LIT(0x6b4e4ed24e6b4a04), + W64LIT(0x51b7b7c4b751d166), W64LIT(0x60ebeb20eb600be0), + W64LIT(0xcc3c3c443cccfdc1), W64LIT(0xbf81819e81bf7cfd), + W64LIT(0xfe9494a194fed440), W64LIT(0x0cf7f704f70ceb1c), + W64LIT(0x67b9b9d6b967a118), W64LIT(0x5f131335135f988b), + W64LIT(0x9c2c2c742c9c7d51), W64LIT(0xb8d3d368d3b8d605), + W64LIT(0x5ce7e734e75c6b8c), W64LIT(0xcb6e6eb26ecb5739), + W64LIT(0xf3c4c451c4f36eaa), W64LIT(0x0f030305030f181b), + W64LIT(0x135656fa56138adc), W64LIT(0x494444cc44491a5e), + W64LIT(0x9e7f7f817f9edfa0), W64LIT(0x37a9a9e6a9372188), + W64LIT(0x822a2a7e2a824d67), W64LIT(0x6dbbbbd0bb6db10a), + W64LIT(0xe2c1c15ec1e24687), W64LIT(0x025353f55302a2f1), + W64LIT(0x8bdcdc79dc8bae72), W64LIT(0x270b0b1d0b275853), + W64LIT(0xd39d9dba9dd39c01), W64LIT(0xc16c6cb46cc1472b), + W64LIT(0xf531315331f595a4), W64LIT(0xb974749c74b987f3), + W64LIT(0x09f6f607f609e315), W64LIT(0x434646ca46430a4c), + W64LIT(0x26acace9ac2609a5), W64LIT(0x9789898689973cb5), + W64LIT(0x4414143c1444a0b4), W64LIT(0x42e1e13ee1425bba), + W64LIT(0x4e16163a164eb0a6), W64LIT(0xd23a3a4e3ad2cdf7), + W64LIT(0xd06969bb69d06f06), W64LIT(0x2d09091b092d4841), + W64LIT(0xad70709070ada7d7), W64LIT(0x54b6b6c7b654d96f), + W64LIT(0xb7d0d06dd0b7ce1e), W64LIT(0x7eeded2aed7e3bd6), + W64LIT(0xdbcccc49ccdb2ee2), W64LIT(0x574242c642572a68), + W64LIT(0xc29898b598c2b42c), W64LIT(0x0ea4a4f1a40e49ed), + W64LIT(0x8828287828885d75), W64LIT(0x315c5ce45c31da86), + W64LIT(0x3ff8f815f83f936b), W64LIT(0xa486869786a444c2), +}; + +static const word64 C2[256] = { + W64LIT(0xd8781818281878c0), W64LIT(0x26af23236523af05), + W64LIT(0xb8f9c6c657c6f97e), W64LIT(0xfb6fe8e825e86f13), + W64LIT(0xcba187879487a14c), W64LIT(0x1162b8b8d5b862a9), + W64LIT(0x0905010103010508), W64LIT(0x0d6e4f4fd14f6e42), + W64LIT(0x9bee36365a36eead), W64LIT(0xff04a6a6f7a60459), + W64LIT(0x0cbdd2d26bd2bdde), W64LIT(0x0e06f5f502f506fb), + W64LIT(0x968079798b7980ef), W64LIT(0x30ce6f6fb16fce5f), + W64LIT(0x6def9191ae91effc), W64LIT(0xf8075252f65207aa), + W64LIT(0x47fd6060a060fd27), W64LIT(0x3576bcbcd9bc7689), + W64LIT(0x37cd9b9bb09bcdac), W64LIT(0x8a8c8e8e8f8e8c04), + W64LIT(0xd215a3a3f8a31571), W64LIT(0x6c3c0c0c140c3c60), + W64LIT(0x848a7b7b8d7b8aff), W64LIT(0x80e135355f35e1b5), + W64LIT(0xf5691d1d271d69e8), W64LIT(0xb347e0e03de04753), + W64LIT(0x21acd7d764d7acf6), W64LIT(0x9cedc2c25bc2ed5e), + W64LIT(0x43962e2e722e966d), W64LIT(0x297a4b4bdd4b7a62), + W64LIT(0x5d21fefe1ffe21a3), W64LIT(0xd5165757f9571682), + W64LIT(0xbd4115153f1541a8), W64LIT(0xe8b677779977b69f), + W64LIT(0x92eb37375937eba5), W64LIT(0x9e56e5e532e5567b), + W64LIT(0x13d99f9fbc9fd98c), W64LIT(0x2317f0f00df017d3), + W64LIT(0x207f4a4ade4a7f6a), W64LIT(0x4495dada73da959e), + W64LIT(0xa2255858e85825fa), W64LIT(0xcfcac9c946c9ca06), + W64LIT(0x7c8d29297b298d55), W64LIT(0x5a220a0a1e0a2250), + W64LIT(0x504fb1b1ceb14fe1), W64LIT(0xc91aa0a0fda01a69), + W64LIT(0x14da6b6bbd6bda7f), W64LIT(0xd9ab85859285ab5c), + W64LIT(0x3c73bdbddabd7381), W64LIT(0x8f345d5de75d34d2), + W64LIT(0x9050101030105080), W64LIT(0x0703f4f401f403f3), + W64LIT(0xddc0cbcb40cbc016), W64LIT(0xd3c63e3e423ec6ed), + W64LIT(0x2d1105050f051128), W64LIT(0x78e66767a967e61f), + W64LIT(0x9753e4e431e45373), W64LIT(0x02bb27276927bb25), + W64LIT(0x73584141c3415832), W64LIT(0xa79d8b8b808b9d2c), + W64LIT(0xf601a7a7f4a70151), W64LIT(0xb2947d7d877d94cf), + W64LIT(0x49fb9595a295fbdc), W64LIT(0x569fd8d875d89f8e), + W64LIT(0x7030fbfb10fb308b), W64LIT(0xcd71eeee2fee7123), + W64LIT(0xbb917c7c847c91c7), W64LIT(0x71e36666aa66e317), + W64LIT(0x7b8edddd7add8ea6), W64LIT(0xaf4b171739174bb8), + W64LIT(0x45464747c9474602), W64LIT(0x1adc9e9ebf9edc84), + W64LIT(0xd4c5caca43cac51e), W64LIT(0x58992d2d772d9975), + W64LIT(0x2e79bfbfdcbf7991), W64LIT(0x3f1b070709071b38), + W64LIT(0xac23adadeaad2301), W64LIT(0xb02f5a5aee5a2fea), + W64LIT(0xefb583839883b56c), W64LIT(0xb6ff33335533ff85), + W64LIT(0x5cf26363a563f23f), W64LIT(0x120a020206020a10), + W64LIT(0x9338aaaae3aa3839), W64LIT(0xdea871719371a8af), + W64LIT(0xc6cfc8c845c8cf0e), W64LIT(0xd17d19192b197dc8), + W64LIT(0x3b704949db497072), W64LIT(0x5f9ad9d976d99a86), + W64LIT(0x311df2f20bf21dc3), W64LIT(0xa848e3e338e3484b), + W64LIT(0xb92a5b5bed5b2ae2), W64LIT(0xbc92888885889234), + W64LIT(0x3ec89a9ab39ac8a4), W64LIT(0x0bbe26266a26be2d), + W64LIT(0xbffa32325632fa8d), W64LIT(0x594ab0b0cdb04ae9), + W64LIT(0xf26ae9e926e96a1b), W64LIT(0x77330f0f110f3378), + W64LIT(0x33a6d5d562d5a6e6), W64LIT(0xf4ba80809d80ba74), + W64LIT(0x277cbebedfbe7c99), W64LIT(0xebdecdcd4acdde26), + W64LIT(0x89e434345c34e4bd), W64LIT(0x32754848d848757a), + W64LIT(0x5424ffff1cff24ab), W64LIT(0x8d8f7a7a8e7a8ff7), + W64LIT(0x64ea9090ad90eaf4), W64LIT(0x9d3e5f5fe15f3ec2), + W64LIT(0x3da020206020a01d), W64LIT(0x0fd56868b868d567), + W64LIT(0xca721a1a2e1a72d0), W64LIT(0xb72caeaeefae2c19), + W64LIT(0x7d5eb4b4c1b45ec9), W64LIT(0xce195454fc54199a), + W64LIT(0x7fe59393a893e5ec), W64LIT(0x2faa22226622aa0d), + W64LIT(0x63e96464ac64e907), W64LIT(0x2a12f1f10ef112db), + W64LIT(0xcca273739573a2bf), W64LIT(0x825a121236125a90), + W64LIT(0x7a5d4040c0405d3a), W64LIT(0x4828080818082840), + W64LIT(0x95e8c3c358c3e856), W64LIT(0xdf7becec29ec7b33), + W64LIT(0x4d90dbdb70db9096), W64LIT(0xc01fa1a1fea11f61), + W64LIT(0x91838d8d8a8d831c), W64LIT(0xc8c93d3d473dc9f5), + W64LIT(0x5bf19797a497f1cc), W64LIT(0x0000000000000000), + W64LIT(0xf9d4cfcf4ccfd436), W64LIT(0x6e872b2b7d2b8745), + W64LIT(0xe1b376769a76b397), W64LIT(0xe6b082829b82b064), + W64LIT(0x28a9d6d667d6a9fe), W64LIT(0xc3771b1b2d1b77d8), + W64LIT(0x745bb5b5c2b55bc1), W64LIT(0xbe29afafecaf2911), + W64LIT(0x1ddf6a6abe6adf77), W64LIT(0xea0d5050f0500dba), + W64LIT(0x574c4545cf454c12), W64LIT(0x3818f3f308f318cb), + W64LIT(0xadf030305030f09d), W64LIT(0xc474efef2cef742b), + W64LIT(0xdac33f3f413fc3e5), W64LIT(0xc71c5555ff551c92), + W64LIT(0xdb10a2a2fba21079), W64LIT(0xe965eaea23ea6503), + W64LIT(0x6aec6565af65ec0f), W64LIT(0x0368babad3ba68b9), + W64LIT(0x4a932f2f712f9365), W64LIT(0x8ee7c0c05dc0e74e), + W64LIT(0x6081dede7fde81be), W64LIT(0xfc6c1c1c241c6ce0), + W64LIT(0x462efdfd1afd2ebb), W64LIT(0x1f644d4dd74d6452), + W64LIT(0x76e09292ab92e0e4), W64LIT(0xfabc75759f75bc8f), + W64LIT(0x361e06060a061e30), W64LIT(0xae988a8a838a9824), + W64LIT(0x4b40b2b2cbb240f9), W64LIT(0x8559e6e637e65963), + W64LIT(0x7e360e0e120e3670), W64LIT(0xe7631f1f211f63f8), + W64LIT(0x55f76262a662f737), W64LIT(0x3aa3d4d461d4a3ee), + W64LIT(0x8132a8a8e5a83229), W64LIT(0x52f49696a796f4c4), + W64LIT(0x623af9f916f93a9b), W64LIT(0xa3f6c5c552c5f666), + W64LIT(0x10b125256f25b135), W64LIT(0xab205959eb5920f2), + W64LIT(0xd0ae84849184ae54), W64LIT(0xc5a772729672a7b7), + W64LIT(0xecdd39394b39ddd5), W64LIT(0x16614c4cd44c615a), + W64LIT(0x943b5e5ee25e3bca), W64LIT(0x9f857878887885e7), + W64LIT(0xe5d838384838d8dd), W64LIT(0x98868c8c898c8614), + W64LIT(0x17b2d1d16ed1b2c6), W64LIT(0xe40ba5a5f2a50b41), + W64LIT(0xa14de2e23be24d43), W64LIT(0x4ef86161a361f82f), + W64LIT(0x4245b3b3c8b345f1), W64LIT(0x34a521216321a515), + W64LIT(0x08d69c9cb99cd694), W64LIT(0xee661e1e221e66f0), + W64LIT(0x61524343c5435222), W64LIT(0xb1fcc7c754c7fc76), + W64LIT(0x4f2bfcfc19fc2bb3), W64LIT(0x241404040c041420), + W64LIT(0xe3085151f35108b2), W64LIT(0x25c79999b699c7bc), + W64LIT(0x22c46d6db76dc44f), W64LIT(0x65390d0d170d3968), + W64LIT(0x7935fafa13fa3583), W64LIT(0x6984dfdf7cdf84b6), + W64LIT(0xa99b7e7e827e9bd7), W64LIT(0x19b424246c24b43d), + W64LIT(0xfed73b3b4d3bd7c5), W64LIT(0x9a3dababe0ab3d31), + W64LIT(0xf0d1cece4fced13e), W64LIT(0x9955111133115588), + W64LIT(0x83898f8f8c8f890c), W64LIT(0x046b4e4ed24e6b4a), + W64LIT(0x6651b7b7c4b751d1), W64LIT(0xe060ebeb20eb600b), + W64LIT(0xc1cc3c3c443cccfd), W64LIT(0xfdbf81819e81bf7c), + W64LIT(0x40fe9494a194fed4), W64LIT(0x1c0cf7f704f70ceb), + W64LIT(0x1867b9b9d6b967a1), W64LIT(0x8b5f131335135f98), + W64LIT(0x519c2c2c742c9c7d), W64LIT(0x05b8d3d368d3b8d6), + W64LIT(0x8c5ce7e734e75c6b), W64LIT(0x39cb6e6eb26ecb57), + W64LIT(0xaaf3c4c451c4f36e), W64LIT(0x1b0f030305030f18), + W64LIT(0xdc135656fa56138a), W64LIT(0x5e494444cc44491a), + W64LIT(0xa09e7f7f817f9edf), W64LIT(0x8837a9a9e6a93721), + W64LIT(0x67822a2a7e2a824d), W64LIT(0x0a6dbbbbd0bb6db1), + W64LIT(0x87e2c1c15ec1e246), W64LIT(0xf1025353f55302a2), + W64LIT(0x728bdcdc79dc8bae), W64LIT(0x53270b0b1d0b2758), + W64LIT(0x01d39d9dba9dd39c), W64LIT(0x2bc16c6cb46cc147), + W64LIT(0xa4f531315331f595), W64LIT(0xf3b974749c74b987), + W64LIT(0x1509f6f607f609e3), W64LIT(0x4c434646ca46430a), + W64LIT(0xa526acace9ac2609), W64LIT(0xb59789898689973c), + W64LIT(0xb44414143c1444a0), W64LIT(0xba42e1e13ee1425b), + W64LIT(0xa64e16163a164eb0), W64LIT(0xf7d23a3a4e3ad2cd), + W64LIT(0x06d06969bb69d06f), W64LIT(0x412d09091b092d48), + W64LIT(0xd7ad70709070ada7), W64LIT(0x6f54b6b6c7b654d9), + W64LIT(0x1eb7d0d06dd0b7ce), W64LIT(0xd67eeded2aed7e3b), + W64LIT(0xe2dbcccc49ccdb2e), W64LIT(0x68574242c642572a), + W64LIT(0x2cc29898b598c2b4), W64LIT(0xed0ea4a4f1a40e49), + W64LIT(0x758828287828885d), W64LIT(0x86315c5ce45c31da), + W64LIT(0x6b3ff8f815f83f93), W64LIT(0xc2a486869786a444), +}; + +static const word64 C3[256] = { + W64LIT(0xc0d8781818281878), W64LIT(0x0526af23236523af), + W64LIT(0x7eb8f9c6c657c6f9), W64LIT(0x13fb6fe8e825e86f), + W64LIT(0x4ccba187879487a1), W64LIT(0xa91162b8b8d5b862), + W64LIT(0x0809050101030105), W64LIT(0x420d6e4f4fd14f6e), + W64LIT(0xad9bee36365a36ee), W64LIT(0x59ff04a6a6f7a604), + W64LIT(0xde0cbdd2d26bd2bd), W64LIT(0xfb0e06f5f502f506), + W64LIT(0xef968079798b7980), W64LIT(0x5f30ce6f6fb16fce), + W64LIT(0xfc6def9191ae91ef), W64LIT(0xaaf8075252f65207), + W64LIT(0x2747fd6060a060fd), W64LIT(0x893576bcbcd9bc76), + W64LIT(0xac37cd9b9bb09bcd), W64LIT(0x048a8c8e8e8f8e8c), + W64LIT(0x71d215a3a3f8a315), W64LIT(0x606c3c0c0c140c3c), + W64LIT(0xff848a7b7b8d7b8a), W64LIT(0xb580e135355f35e1), + W64LIT(0xe8f5691d1d271d69), W64LIT(0x53b347e0e03de047), + W64LIT(0xf621acd7d764d7ac), W64LIT(0x5e9cedc2c25bc2ed), + W64LIT(0x6d43962e2e722e96), W64LIT(0x62297a4b4bdd4b7a), + W64LIT(0xa35d21fefe1ffe21), W64LIT(0x82d5165757f95716), + W64LIT(0xa8bd4115153f1541), W64LIT(0x9fe8b677779977b6), + W64LIT(0xa592eb37375937eb), W64LIT(0x7b9e56e5e532e556), + W64LIT(0x8c13d99f9fbc9fd9), W64LIT(0xd32317f0f00df017), + W64LIT(0x6a207f4a4ade4a7f), W64LIT(0x9e4495dada73da95), + W64LIT(0xfaa2255858e85825), W64LIT(0x06cfcac9c946c9ca), + W64LIT(0x557c8d29297b298d), W64LIT(0x505a220a0a1e0a22), + W64LIT(0xe1504fb1b1ceb14f), W64LIT(0x69c91aa0a0fda01a), + W64LIT(0x7f14da6b6bbd6bda), W64LIT(0x5cd9ab85859285ab), + W64LIT(0x813c73bdbddabd73), W64LIT(0xd28f345d5de75d34), + W64LIT(0x8090501010301050), W64LIT(0xf30703f4f401f403), + W64LIT(0x16ddc0cbcb40cbc0), W64LIT(0xedd3c63e3e423ec6), + W64LIT(0x282d1105050f0511), W64LIT(0x1f78e66767a967e6), + W64LIT(0x739753e4e431e453), W64LIT(0x2502bb27276927bb), + W64LIT(0x3273584141c34158), W64LIT(0x2ca79d8b8b808b9d), + W64LIT(0x51f601a7a7f4a701), W64LIT(0xcfb2947d7d877d94), + W64LIT(0xdc49fb9595a295fb), W64LIT(0x8e569fd8d875d89f), + W64LIT(0x8b7030fbfb10fb30), W64LIT(0x23cd71eeee2fee71), + W64LIT(0xc7bb917c7c847c91), W64LIT(0x1771e36666aa66e3), + W64LIT(0xa67b8edddd7add8e), W64LIT(0xb8af4b171739174b), + W64LIT(0x0245464747c94746), W64LIT(0x841adc9e9ebf9edc), + W64LIT(0x1ed4c5caca43cac5), W64LIT(0x7558992d2d772d99), + W64LIT(0x912e79bfbfdcbf79), W64LIT(0x383f1b070709071b), + W64LIT(0x01ac23adadeaad23), W64LIT(0xeab02f5a5aee5a2f), + W64LIT(0x6cefb583839883b5), W64LIT(0x85b6ff33335533ff), + W64LIT(0x3f5cf26363a563f2), W64LIT(0x10120a020206020a), + W64LIT(0x399338aaaae3aa38), W64LIT(0xafdea871719371a8), + W64LIT(0x0ec6cfc8c845c8cf), W64LIT(0xc8d17d19192b197d), + W64LIT(0x723b704949db4970), W64LIT(0x865f9ad9d976d99a), + W64LIT(0xc3311df2f20bf21d), W64LIT(0x4ba848e3e338e348), + W64LIT(0xe2b92a5b5bed5b2a), W64LIT(0x34bc928888858892), + W64LIT(0xa43ec89a9ab39ac8), W64LIT(0x2d0bbe26266a26be), + W64LIT(0x8dbffa32325632fa), W64LIT(0xe9594ab0b0cdb04a), + W64LIT(0x1bf26ae9e926e96a), W64LIT(0x7877330f0f110f33), + W64LIT(0xe633a6d5d562d5a6), W64LIT(0x74f4ba80809d80ba), + W64LIT(0x99277cbebedfbe7c), W64LIT(0x26ebdecdcd4acdde), + W64LIT(0xbd89e434345c34e4), W64LIT(0x7a32754848d84875), + W64LIT(0xab5424ffff1cff24), W64LIT(0xf78d8f7a7a8e7a8f), + W64LIT(0xf464ea9090ad90ea), W64LIT(0xc29d3e5f5fe15f3e), + W64LIT(0x1d3da020206020a0), W64LIT(0x670fd56868b868d5), + W64LIT(0xd0ca721a1a2e1a72), W64LIT(0x19b72caeaeefae2c), + W64LIT(0xc97d5eb4b4c1b45e), W64LIT(0x9ace195454fc5419), + W64LIT(0xec7fe59393a893e5), W64LIT(0x0d2faa22226622aa), + W64LIT(0x0763e96464ac64e9), W64LIT(0xdb2a12f1f10ef112), + W64LIT(0xbfcca273739573a2), W64LIT(0x90825a121236125a), + W64LIT(0x3a7a5d4040c0405d), W64LIT(0x4048280808180828), + W64LIT(0x5695e8c3c358c3e8), W64LIT(0x33df7becec29ec7b), + W64LIT(0x964d90dbdb70db90), W64LIT(0x61c01fa1a1fea11f), + W64LIT(0x1c91838d8d8a8d83), W64LIT(0xf5c8c93d3d473dc9), + W64LIT(0xcc5bf19797a497f1), W64LIT(0x0000000000000000), + W64LIT(0x36f9d4cfcf4ccfd4), W64LIT(0x456e872b2b7d2b87), + W64LIT(0x97e1b376769a76b3), W64LIT(0x64e6b082829b82b0), + W64LIT(0xfe28a9d6d667d6a9), W64LIT(0xd8c3771b1b2d1b77), + W64LIT(0xc1745bb5b5c2b55b), W64LIT(0x11be29afafecaf29), + W64LIT(0x771ddf6a6abe6adf), W64LIT(0xbaea0d5050f0500d), + W64LIT(0x12574c4545cf454c), W64LIT(0xcb3818f3f308f318), + W64LIT(0x9dadf030305030f0), W64LIT(0x2bc474efef2cef74), + W64LIT(0xe5dac33f3f413fc3), W64LIT(0x92c71c5555ff551c), + W64LIT(0x79db10a2a2fba210), W64LIT(0x03e965eaea23ea65), + W64LIT(0x0f6aec6565af65ec), W64LIT(0xb90368babad3ba68), + W64LIT(0x654a932f2f712f93), W64LIT(0x4e8ee7c0c05dc0e7), + W64LIT(0xbe6081dede7fde81), W64LIT(0xe0fc6c1c1c241c6c), + W64LIT(0xbb462efdfd1afd2e), W64LIT(0x521f644d4dd74d64), + W64LIT(0xe476e09292ab92e0), W64LIT(0x8ffabc75759f75bc), + W64LIT(0x30361e06060a061e), W64LIT(0x24ae988a8a838a98), + W64LIT(0xf94b40b2b2cbb240), W64LIT(0x638559e6e637e659), + W64LIT(0x707e360e0e120e36), W64LIT(0xf8e7631f1f211f63), + W64LIT(0x3755f76262a662f7), W64LIT(0xee3aa3d4d461d4a3), + W64LIT(0x298132a8a8e5a832), W64LIT(0xc452f49696a796f4), + W64LIT(0x9b623af9f916f93a), W64LIT(0x66a3f6c5c552c5f6), + W64LIT(0x3510b125256f25b1), W64LIT(0xf2ab205959eb5920), + W64LIT(0x54d0ae84849184ae), W64LIT(0xb7c5a772729672a7), + W64LIT(0xd5ecdd39394b39dd), W64LIT(0x5a16614c4cd44c61), + W64LIT(0xca943b5e5ee25e3b), W64LIT(0xe79f857878887885), + W64LIT(0xdde5d838384838d8), W64LIT(0x1498868c8c898c86), + W64LIT(0xc617b2d1d16ed1b2), W64LIT(0x41e40ba5a5f2a50b), + W64LIT(0x43a14de2e23be24d), W64LIT(0x2f4ef86161a361f8), + W64LIT(0xf14245b3b3c8b345), W64LIT(0x1534a521216321a5), + W64LIT(0x9408d69c9cb99cd6), W64LIT(0xf0ee661e1e221e66), + W64LIT(0x2261524343c54352), W64LIT(0x76b1fcc7c754c7fc), + W64LIT(0xb34f2bfcfc19fc2b), W64LIT(0x20241404040c0414), + W64LIT(0xb2e3085151f35108), W64LIT(0xbc25c79999b699c7), + W64LIT(0x4f22c46d6db76dc4), W64LIT(0x6865390d0d170d39), + W64LIT(0x837935fafa13fa35), W64LIT(0xb66984dfdf7cdf84), + W64LIT(0xd7a99b7e7e827e9b), W64LIT(0x3d19b424246c24b4), + W64LIT(0xc5fed73b3b4d3bd7), W64LIT(0x319a3dababe0ab3d), + W64LIT(0x3ef0d1cece4fced1), W64LIT(0x8899551111331155), + W64LIT(0x0c83898f8f8c8f89), W64LIT(0x4a046b4e4ed24e6b), + W64LIT(0xd16651b7b7c4b751), W64LIT(0x0be060ebeb20eb60), + W64LIT(0xfdc1cc3c3c443ccc), W64LIT(0x7cfdbf81819e81bf), + W64LIT(0xd440fe9494a194fe), W64LIT(0xeb1c0cf7f704f70c), + W64LIT(0xa11867b9b9d6b967), W64LIT(0x988b5f131335135f), + W64LIT(0x7d519c2c2c742c9c), W64LIT(0xd605b8d3d368d3b8), + W64LIT(0x6b8c5ce7e734e75c), W64LIT(0x5739cb6e6eb26ecb), + W64LIT(0x6eaaf3c4c451c4f3), W64LIT(0x181b0f030305030f), + W64LIT(0x8adc135656fa5613), W64LIT(0x1a5e494444cc4449), + W64LIT(0xdfa09e7f7f817f9e), W64LIT(0x218837a9a9e6a937), + W64LIT(0x4d67822a2a7e2a82), W64LIT(0xb10a6dbbbbd0bb6d), + W64LIT(0x4687e2c1c15ec1e2), W64LIT(0xa2f1025353f55302), + W64LIT(0xae728bdcdc79dc8b), W64LIT(0x5853270b0b1d0b27), + W64LIT(0x9c01d39d9dba9dd3), W64LIT(0x472bc16c6cb46cc1), + W64LIT(0x95a4f531315331f5), W64LIT(0x87f3b974749c74b9), + W64LIT(0xe31509f6f607f609), W64LIT(0x0a4c434646ca4643), + W64LIT(0x09a526acace9ac26), W64LIT(0x3cb5978989868997), + W64LIT(0xa0b44414143c1444), W64LIT(0x5bba42e1e13ee142), + W64LIT(0xb0a64e16163a164e), W64LIT(0xcdf7d23a3a4e3ad2), + W64LIT(0x6f06d06969bb69d0), W64LIT(0x48412d09091b092d), + W64LIT(0xa7d7ad70709070ad), W64LIT(0xd96f54b6b6c7b654), + W64LIT(0xce1eb7d0d06dd0b7), W64LIT(0x3bd67eeded2aed7e), + W64LIT(0x2ee2dbcccc49ccdb), W64LIT(0x2a68574242c64257), + W64LIT(0xb42cc29898b598c2), W64LIT(0x49ed0ea4a4f1a40e), + W64LIT(0x5d75882828782888), W64LIT(0xda86315c5ce45c31), + W64LIT(0x936b3ff8f815f83f), W64LIT(0x44c2a486869786a4), +}; + +static const word64 rc[R + 1] = { + W64LIT(0x0000000000000000), + W64LIT(0x1823c6e887b8014f), + W64LIT(0x36a6d2f5796f9152), + W64LIT(0x60bc9b8ea30c7b35), + W64LIT(0x1de0d7c22e4bfe57), + W64LIT(0x157737e59ff04ada), + W64LIT(0x58c9290ab1a06b85), + W64LIT(0xbd5d10f4cb3e0567), + W64LIT(0xe427418ba77d95d8), + W64LIT(0xfbee7c66dd17479e), + W64LIT(0xca2dbf07ad5a8333) +}; + + +// Whirlpool basic transformation. Transforms state based on block. +void Whirlpool::Transform(word64 *digest, const word64 *block) +{ + int r; + word64 L[8]; // temporary storage + word64 state[8]; // the cipher state + word64 K[8]; // the round key + + // Compute and apply K^0 to the cipher state + // Also apply part of the Miyaguchi-Preneel compression function + digest[0] = state[0] = block[0] ^ (K[0] = digest[0]); + digest[1] = state[1] = block[1] ^ (K[1] = digest[1]); + digest[2] = state[2] = block[2] ^ (K[2] = digest[2]); + digest[3] = state[3] = block[3] ^ (K[3] = digest[3]); + digest[4] = state[4] = block[4] ^ (K[4] = digest[4]); + digest[5] = state[5] = block[5] ^ (K[5] = digest[5]); + digest[6] = state[6] = block[6] ^ (K[6] = digest[6]); + digest[7] = state[7] = block[7] ^ (K[7] = digest[7]); + + // Iterate over all rounds: + for (r = 1; r <= R; r++) { + + // Compute K^r from K^{r-1}: + L[0] = + C0[GETBYTE(K[4], 3)] ^ + C1[GETBYTE(K[3], 2)] ^ + C2[GETBYTE(K[2], 1)] ^ + C3[GETBYTE(K[1], 0)]; + L[0] = (L[0] >> 32) | (L[0] << 32); + L[0] ^= + C0[GETBYTE(K[0], 7)] ^ + C1[GETBYTE(K[7], 6)] ^ + C2[GETBYTE(K[6], 5)] ^ + C3[GETBYTE(K[5], 4)] ^ + rc[r]; + L[1] = + C0[GETBYTE(K[5], 3)] ^ + C1[GETBYTE(K[4], 2)] ^ + C2[GETBYTE(K[3], 1)] ^ + C3[GETBYTE(K[2], 0)]; + L[1] = (L[1] >> 32) | (L[1] << 32); + L[1] ^= + C0[GETBYTE(K[1], 7)] ^ + C1[GETBYTE(K[0], 6)] ^ + C2[GETBYTE(K[7], 5)] ^ + C3[GETBYTE(K[6], 4)]; + L[2] = + C0[GETBYTE(K[6], 3)] ^ + C1[GETBYTE(K[5], 2)] ^ + C2[GETBYTE(K[4], 1)] ^ + C3[GETBYTE(K[3], 0)]; + L[2] = (L[2] >> 32) | (L[2] << 32); + L[2] ^= + C0[GETBYTE(K[2], 7)] ^ + C1[GETBYTE(K[1], 6)] ^ + C2[GETBYTE(K[0], 5)] ^ + C3[GETBYTE(K[7], 4)]; + L[3] = + C0[GETBYTE(K[7], 3)] ^ + C1[GETBYTE(K[6], 2)] ^ + C2[GETBYTE(K[5], 1)] ^ + C3[GETBYTE(K[4], 0)]; + L[3] = (L[3] >> 32) | (L[3] << 32); + L[3] ^= + C0[GETBYTE(K[3], 7)] ^ + C1[GETBYTE(K[2], 6)] ^ + C2[GETBYTE(K[1], 5)] ^ + C3[GETBYTE(K[0], 4)]; + L[4] = + C0[GETBYTE(K[0], 3)] ^ + C1[GETBYTE(K[7], 2)] ^ + C2[GETBYTE(K[6], 1)] ^ + C3[GETBYTE(K[5], 0)]; + L[4] = (L[4] >> 32) | (L[4] << 32); + L[4] ^= + C0[GETBYTE(K[4], 7)] ^ + C1[GETBYTE(K[3], 6)] ^ + C2[GETBYTE(K[2], 5)] ^ + C3[GETBYTE(K[1], 4)]; + L[5] = + C0[GETBYTE(K[1], 3)] ^ + C1[GETBYTE(K[0], 2)] ^ + C2[GETBYTE(K[7], 1)] ^ + C3[GETBYTE(K[6], 0)]; + L[5] = (L[5] >> 32) | (L[5] << 32); + L[5] ^= + C0[GETBYTE(K[5], 7)] ^ + C1[GETBYTE(K[4], 6)] ^ + C2[GETBYTE(K[3], 5)] ^ + C3[GETBYTE(K[2], 4)]; + L[6] = + C0[GETBYTE(K[2], 3)] ^ + C1[GETBYTE(K[1], 2)] ^ + C2[GETBYTE(K[0], 1)] ^ + C3[GETBYTE(K[7], 0)]; + L[6] = (L[6] >> 32) | (L[6] << 32); + L[6] ^= + C0[GETBYTE(K[6], 7)] ^ + C1[GETBYTE(K[5], 6)] ^ + C2[GETBYTE(K[4], 5)] ^ + C3[GETBYTE(K[3], 4)]; + L[7] = + C0[GETBYTE(K[3], 3)] ^ + C1[GETBYTE(K[2], 2)] ^ + C2[GETBYTE(K[1], 1)] ^ + C3[GETBYTE(K[0], 0)]; + L[7] = (L[7] >> 32) | (L[7] << 32); + L[7] ^= + C0[GETBYTE(K[7], 7)] ^ + C1[GETBYTE(K[6], 6)] ^ + C2[GETBYTE(K[5], 5)] ^ + C3[GETBYTE(K[4], 4)]; + K[0] = L[0]; + K[1] = L[1]; + K[2] = L[2]; + K[3] = L[3]; + K[4] = L[4]; + K[5] = L[5]; + K[6] = L[6]; + K[7] = L[7]; + + // Apply the r-th round transformation: + L[0] = + C0[GETBYTE(state[4], 3)] ^ + C1[GETBYTE(state[3], 2)] ^ + C2[GETBYTE(state[2], 1)] ^ + C3[GETBYTE(state[1], 0)]; + L[0] = (L[0] >> 32) | (L[0] << 32); + L[0] ^= + C0[GETBYTE(state[0], 7)] ^ + C1[GETBYTE(state[7], 6)] ^ + C2[GETBYTE(state[6], 5)] ^ + C3[GETBYTE(state[5], 4)] ^ + K[0]; + L[1] = + C0[GETBYTE(state[5], 3)] ^ + C1[GETBYTE(state[4], 2)] ^ + C2[GETBYTE(state[3], 1)] ^ + C3[GETBYTE(state[2], 0)]; + L[1] = (L[1] >> 32) | (L[1] << 32); + L[1] ^= + C0[GETBYTE(state[1], 7)] ^ + C1[GETBYTE(state[0], 6)] ^ + C2[GETBYTE(state[7], 5)] ^ + C3[GETBYTE(state[6], 4)] ^ + K[1]; + L[2] = + C0[GETBYTE(state[6], 3)] ^ + C1[GETBYTE(state[5], 2)] ^ + C2[GETBYTE(state[4], 1)] ^ + C3[GETBYTE(state[3], 0)]; + L[2] = (L[2] >> 32) | (L[2] << 32); + L[2] ^= + C0[GETBYTE(state[2], 7)] ^ + C1[GETBYTE(state[1], 6)] ^ + C2[GETBYTE(state[0], 5)] ^ + C3[GETBYTE(state[7], 4)] ^ + K[2]; + L[3] = + C0[GETBYTE(state[7], 3)] ^ + C1[GETBYTE(state[6], 2)] ^ + C2[GETBYTE(state[5], 1)] ^ + C3[GETBYTE(state[4], 0)]; + L[3] = (L[3] >> 32) | (L[3] << 32); + L[3] ^= + C0[GETBYTE(state[3], 7)] ^ + C1[GETBYTE(state[2], 6)] ^ + C2[GETBYTE(state[1], 5)] ^ + C3[GETBYTE(state[0], 4)] ^ + K[3]; + L[4] = + C0[GETBYTE(state[0], 3)] ^ + C1[GETBYTE(state[7], 2)] ^ + C2[GETBYTE(state[6], 1)] ^ + C3[GETBYTE(state[5], 0)]; + L[4] = (L[4] >> 32) | (L[4] << 32); + L[4] ^= + C0[GETBYTE(state[4], 7)] ^ + C1[GETBYTE(state[3], 6)] ^ + C2[GETBYTE(state[2], 5)] ^ + C3[GETBYTE(state[1], 4)] ^ + K[4]; + L[5] = + C0[GETBYTE(state[1], 3)] ^ + C1[GETBYTE(state[0], 2)] ^ + C2[GETBYTE(state[7], 1)] ^ + C3[GETBYTE(state[6], 0)]; + L[5] = (L[5] >> 32) | (L[5] << 32); + L[5] ^= + C0[GETBYTE(state[5], 7)] ^ + C1[GETBYTE(state[4], 6)] ^ + C2[GETBYTE(state[3], 5)] ^ + C3[GETBYTE(state[2], 4)] ^ + K[5]; + L[6] = + C0[GETBYTE(state[2], 3)] ^ + C1[GETBYTE(state[1], 2)] ^ + C2[GETBYTE(state[0], 1)] ^ + C3[GETBYTE(state[7], 0)]; + L[6] = (L[6] >> 32) | (L[6] << 32); + L[6] ^= + C0[GETBYTE(state[6], 7)] ^ + C1[GETBYTE(state[5], 6)] ^ + C2[GETBYTE(state[4], 5)] ^ + C3[GETBYTE(state[3], 4)] ^ + K[6]; + L[7] = + C0[GETBYTE(state[3], 3)] ^ + C1[GETBYTE(state[2], 2)] ^ + C2[GETBYTE(state[1], 1)] ^ + C3[GETBYTE(state[0], 0)]; + L[7] = (L[7] >> 32) | (L[7] << 32); + L[7] ^= + C0[GETBYTE(state[7], 7)] ^ + C1[GETBYTE(state[6], 6)] ^ + C2[GETBYTE(state[5], 5)] ^ + C3[GETBYTE(state[4], 4)] ^ + K[7]; + state[0] = L[0]; + state[1] = L[1]; + state[2] = L[2]; + state[3] = L[3]; + state[4] = L[4]; + state[5] = L[5]; + state[6] = L[6]; + state[7] = L[7]; + } + + // Apply the rest of the Miyaguchi-Preneel compression function: + digest[0] ^= state[0]; + digest[1] ^= state[1]; + digest[2] ^= state[2]; + digest[3] ^= state[3]; + digest[4] ^= state[4]; + digest[5] ^= state[5]; + digest[6] ^= state[6]; + digest[7] ^= state[7]; +} + +NAMESPACE_END + +#endif // WORD64_AVAILABLE diff --git a/whrlpool.h b/whrlpool.h new file mode 100644 index 0000000..4e3911d --- /dev/null +++ b/whrlpool.h @@ -0,0 +1,31 @@ +#ifndef CRYPTOPP_WHIRLPOOL_H +#define CRYPTOPP_WHIRLPOOL_H + +#include "config.h" + +#ifdef WORD64_AVAILABLE + +#include "iterhash.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! <a href="http://www.eskimo.com/~weidai/scan-mirror/md.html#Whirlpool">Whirlpool</a> +/*! 512 Bit Hash */ +class Whirlpool : public IteratedHashWithStaticTransform<word64, BigEndian, 64, Whirlpool> +{ +public: + enum {DIGESTSIZE = 64}; + Whirlpool() : IteratedHashWithStaticTransform<word64, BigEndian, 64, Whirlpool>(DIGESTSIZE) {Init();} + static void Transform(word64 *digest, const word64 *data); + void TruncatedFinal(byte *hash, unsigned int size); + static const char * StaticAlgorithmName() {return "Whirlpool";} + +protected: + void Init(); +}; + +NAMESPACE_END + +#endif + +#endif |