diff options
Diffstat (limited to '')
-rw-r--r-- | CryptoPP/idea.cpp | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/CryptoPP/idea.cpp b/CryptoPP/idea.cpp new file mode 100644 index 000000000..793f912fb --- /dev/null +++ b/CryptoPP/idea.cpp @@ -0,0 +1,192 @@ +// idea.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "idea.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +static const int IDEA_KEYLEN=(6*IDEA::ROUNDS+4); // key schedule length in # of word16s + +#define low16(x) ((x)&0xffff) // compiler should be able to optimize this away if word is 16 bits +#define high16(x) ((x)>>16) + +CRYPTOPP_COMPILE_ASSERT(sizeof(IDEA::Word) >= 2); + +// should use an inline function but macros are still faster in MSVC 4.0 +#define DirectMUL(a,b) \ +{ \ + assert(b <= 0xffff); \ + \ + word32 p=(word32)low16(a)*b; \ + \ + if (p) \ + { \ + p = low16(p) - high16(p); \ + a = (IDEA::Word)p - (IDEA::Word)high16(p); \ + } \ + else \ + a = 1-a-b; \ +} + +#ifdef IDEA_LARGECACHE +volatile bool IDEA::Base::tablesBuilt = false; +word16 IDEA::Base::log[0x10000]; +word16 IDEA::Base::antilog[0x10000]; + +void IDEA::Base::BuildLogTables() +{ + if (tablesBuilt) + return; + else + { + tablesBuilt = true; + + IDEA::Word x=1; + word32 i; + + for (i=0; i<0x10000; i++) + { + antilog[i] = (word16)x; + DirectMUL(x, 3); + } + + for (i=0; i<0x10000; i++) + log[antilog[i]] = (word16)i; + } +} + +void IDEA::Base::LookupKeyLogs() +{ + IDEA::Word* Z=key; + int r=ROUNDS; + do + { + Z[0] = log[Z[0]]; + Z[3] = log[Z[3]]; + Z[4] = log[Z[4]]; + Z[5] = log[Z[5]]; + Z+=6; + } while (--r); + Z[0] = log[Z[0]]; + Z[3] = log[Z[3]]; +} + +inline void IDEA::Base::LookupMUL(IDEA::Word &a, IDEA::Word b) +{ + a = antilog[low16(log[low16(a)]+b)]; +} +#endif // IDEA_LARGECACHE + +void IDEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) +{ + AssertValidKeyLength(length); + +#ifdef IDEA_LARGECACHE + BuildLogTables(); +#endif + + EnKey(userKey); + + if (!IsForwardTransformation()) + DeKey(); + +#ifdef IDEA_LARGECACHE + LookupKeyLogs(); +#endif +} + +void IDEA::Base::EnKey (const byte *userKey) +{ + unsigned int i; + + for (i=0; i<8; i++) + m_key[i] = ((IDEA::Word)userKey[2*i]<<8) | userKey[2*i+1]; + + for (; i<IDEA_KEYLEN; i++) + { + unsigned int j = RoundDownToMultipleOf(i,8U)-8; + m_key[i] = low16((m_key[j+(i+1)%8] << 9) | (m_key[j+(i+2)%8] >> 7)); + } +} + +static IDEA::Word MulInv(IDEA::Word x) +{ + IDEA::Word y=x; + for (unsigned i=0; i<15; i++) + { + DirectMUL(y,low16(y)); + DirectMUL(y,x); + } + return low16(y); +} + +static inline IDEA::Word AddInv(IDEA::Word x) +{ + return low16(0-x); +} + +void IDEA::Base::DeKey() +{ + FixedSizeSecBlock<IDEA::Word, 6*ROUNDS+4> tempkey; + size_t i; + + for (i=0; i<ROUNDS; i++) + { + tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]); + tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1+(i>0)]); + tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2-(i>0)]); + tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]); + tempkey[i*6+4] = m_key[(ROUNDS-1-i)*6+4]; + tempkey[i*6+5] = m_key[(ROUNDS-1-i)*6+5]; + } + + tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]); + tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1]); + tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2]); + tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]); + + m_key = tempkey; +} + +#ifdef IDEA_LARGECACHE +#define MUL(a,b) LookupMUL(a,b) +#else +#define MUL(a,b) DirectMUL(a,b) +#endif + +void IDEA::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const +{ + typedef BlockGetAndPut<word16, BigEndian> Block; + + const IDEA::Word *key = m_key; + IDEA::Word x0,x1,x2,x3,t0,t1; + Block::Get(inBlock)(x0)(x1)(x2)(x3); + + for (unsigned int i=0; i<ROUNDS; i++) + { + MUL(x0, key[i*6+0]); + x1 += key[i*6+1]; + x2 += key[i*6+2]; + MUL(x3, key[i*6+3]); + t0 = x0^x2; + MUL(t0, key[i*6+4]); + t1 = t0 + (x1^x3); + MUL(t1, key[i*6+5]); + t0 += t1; + x0 ^= t1; + x3 ^= t0; + t0 ^= x1; + x1 = x2^t1; + x2 = t0; + } + + MUL(x0, key[ROUNDS*6+0]); + x2 += key[ROUNDS*6+1]; + x1 += key[ROUNDS*6+2]; + MUL(x3, key[ROUNDS*6+3]); + + Block::Put(xorBlock, outBlock)(x0)(x2)(x1)(x3); +} + +NAMESPACE_END |