diff options
author | weidai <weidai11@users.noreply.github.com> | 2002-10-04 17:31:41 +0000 |
---|---|---|
committer | weidai <weidai11@users.noreply.github.com> | 2002-10-04 17:31:41 +0000 |
commit | a3b6ece7ab341b5b14135baeccea7d5e4c086771 (patch) | |
tree | 8b045309c238226c32a563b1df6b9c30a2f0e0b3 /idea.cpp | |
download | cryptopp-git-a3b6ece7ab341b5b14135baeccea7d5e4c086771.tar.gz |
Initial revision
Diffstat (limited to 'idea.cpp')
-rw-r--r-- | idea.cpp | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/idea.cpp b/idea.cpp new file mode 100644 index 00000000..e8d4bb82 --- /dev/null +++ b/idea.cpp @@ -0,0 +1,190 @@ +// 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) + +// 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 = (word)p - (word)high16(p); \ + } \ + else \ + a = 1-a-b; \ +} + +#ifdef IDEA_LARGECACHE +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; + + 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() +{ + 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(word &a, word b) +{ + a = antilog[low16(log[low16(a)]+b)]; +} +#endif // IDEA_LARGECACHE + +void IDEA::Base::UncheckedSetKey(CipherDir direction, const byte *userKey, unsigned int length) +{ + AssertValidKeyLength(length); + +#ifdef IDEA_LARGECACHE + BuildLogTables(); +#endif + + EnKey(userKey); + + if (direction==DECRYPTION) + 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] = ((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 word MulInv(word x) +{ + word y=x; + for (unsigned i=0; i<15; i++) + { + DirectMUL(y,low16(y)); + DirectMUL(y,x); + } + return low16(y); +} + +static inline word AddInv(word x) +{ + return low16(0-x); +} + +void IDEA::Base::DeKey() +{ + FixedSizeSecBlock<word, 6*ROUNDS+4> tempkey; + unsigned int 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 word *key = m_key; + 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 |