From b21162cf8e06f40baa1f58be6a8c17435cebc34d Mon Sep 17 00:00:00 2001 From: weidai Date: Fri, 4 Oct 2002 17:31:41 +0000 Subject: Initial revision git-svn-id: svn://svn.code.sf.net/p/cryptopp/code/trunk/c5@2 57ff6487-cd31-0410-9ec3-f628ee90f5f0 --- twofish.cpp | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 twofish.cpp (limited to 'twofish.cpp') diff --git a/twofish.cpp b/twofish.cpp new file mode 100644 index 0000000..2371002 --- /dev/null +++ b/twofish.cpp @@ -0,0 +1,168 @@ +// twofish.cpp - modified by Wei Dai from Matthew Skala's twofish.c +// The original code and all modifications are in the public domain. + +#include "pch.h" +#include "twofish.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +// compute (c * x^4) mod (x^4 + (a + 1/a) * x^3 + a * x^2 + (a + 1/a) * x + 1) +// over GF(256) +static inline unsigned int Mod(unsigned int c) +{ + static const unsigned int modulus = 0x14d; + unsigned int c2 = (c<<1) ^ ((c & 0x80) ? modulus : 0); + unsigned int c1 = c2 ^ (c>>1) ^ ((c & 1) ? (modulus>>1) : 0); + return c | (c1 << 8) | (c2 << 16) | (c1 << 24); +} + +// compute RS(12,8) code with the above polynomial as generator +// this is equivalent to multiplying by the RS matrix +static word32 ReedSolomon(word32 high, word32 low) +{ + for (unsigned int i=0; i<8; i++) + { + high = Mod(high>>24) ^ (high<<8) ^ (low>>24); + low <<= 8; + } + return high; +} + +inline word32 Twofish::Base::h0(word32 x, const word32 *key, unsigned int kLen) +{ + x = x | (x<<8) | (x<<16) | (x<<24); + switch(kLen) + { +#define Q(a, b, c, d, t) q[a][GETBYTE(t,0)] ^ (q[b][GETBYTE(t,1)] << 8) ^ (q[c][GETBYTE(t,2)] << 16) ^ (q[d][GETBYTE(t,3)] << 24) + case 4: x = Q(1, 0, 0, 1, x) ^ key[6]; + case 3: x = Q(1, 1, 0, 0, x) ^ key[4]; + case 2: x = Q(0, 1, 0, 1, x) ^ key[2]; + x = Q(0, 0, 1, 1, x) ^ key[0]; + } + return x; +} + +inline word32 Twofish::Base::h(word32 x, const word32 *key, unsigned int kLen) +{ + x = h0(x, key, kLen); + return mds[0][GETBYTE(x,0)] ^ mds[1][GETBYTE(x,1)] ^ mds[2][GETBYTE(x,2)] ^ mds[3][GETBYTE(x,3)]; +} + +void Twofish::Base::UncheckedSetKey(CipherDir dir, const byte *userKey, unsigned int keylength) +{ + AssertValidKeyLength(keylength); + + unsigned int len = (keylength <= 16 ? 2 : (keylength <= 24 ? 3 : 4)); + SecBlock key(len*2); + GetUserKey(LITTLE_ENDIAN_ORDER, key.begin(), len*2, userKey, keylength); + + unsigned int i; + for (i=0; i<40; i+=2) + { + word32 a = h(i, key, len); + word32 b = rotlFixed(h(i+1, key+1, len), 8); + m_k[i] = a+b; + m_k[i+1] = rotlFixed(a+2*b, 9); + } + + SecBlock svec(2*len); + for (i=0; i Block; + +void Twofish::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 x, y, a, b, c, d; + + Block::Get(inBlock)(a)(b)(c)(d); + + a ^= m_k[0]; + b ^= m_k[1]; + c ^= m_k[2]; + d ^= m_k[3]; + + const word32 *k = m_k+8; + ENCCYCLE (0); + ENCCYCLE (1); + ENCCYCLE (2); + ENCCYCLE (3); + ENCCYCLE (4); + ENCCYCLE (5); + ENCCYCLE (6); + ENCCYCLE (7); + + c ^= m_k[4]; + d ^= m_k[5]; + a ^= m_k[6]; + b ^= m_k[7]; + + Block::Put(xorBlock, outBlock)(c)(d)(a)(b); +} + +void Twofish::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + word32 x, y, a, b, c, d; + + Block::Get(inBlock)(c)(d)(a)(b); + + c ^= m_k[4]; + d ^= m_k[5]; + a ^= m_k[6]; + b ^= m_k[7]; + + const word32 *k = m_k+8; + DECCYCLE (7); + DECCYCLE (6); + DECCYCLE (5); + DECCYCLE (4); + DECCYCLE (3); + DECCYCLE (2); + DECCYCLE (1); + DECCYCLE (0); + + a ^= m_k[0]; + b ^= m_k[1]; + c ^= m_k[2]; + d ^= m_k[3]; + + Block::Put(xorBlock, outBlock)(a)(b)(c)(d); +} + +NAMESPACE_END -- cgit v1.2.1