- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# idea.cpp

    00001 // idea.cpp - written and placed in the public domain by Wei Dai
    00002
    00003 #include "pch.h"
    00004 #include "idea.h"
    00005 #include "misc.h"
    00006
    00007 NAMESPACE_BEGIN(CryptoPP)
    00008
    00009 static const int IDEA_KEYLEN=(6*IDEA::ROUNDS+4);  // key schedule length in # of word16s
    00010
    00011 #define low16(x) ((x)&0xffff)   // compiler should be able to optimize this away if word is 16 bits
    00012 #define high16(x) ((x)>>16)
    00013
    00014 CRYPTOPP_COMPILE_ASSERT(sizeof(IDEA::Word) >= 2);
    00015
    00016 // should use an inline function but macros are still faster in MSVC 4.0
    00017 #define DirectMUL(a,b)                                  \
    00018 {                                                                               \
    00019         assert(b <= 0xffff);                            \
    00020                                                                                 \
    00021         word32 p=(word32)low16(a)*b;            \
    00022                                                                                 \
    00023         if (p)                                                          \
    00024         {                                                                       \
    00025                 p = low16(p) - high16(p);               \
    00026                 a = (IDEA::Word)p - (IDEA::Word)high16(p);      \
    00027         }                                                                       \
    00028         else                                                            \
    00029                 a = 1-a-b;                                              \
    00030 }
    00031
    00032 #ifdef IDEA_LARGECACHE
    00033 bool IDEA::Base::tablesBuilt = false;
    00034 word16 IDEA::Base::log[0x10000];
    00035 word16 IDEA::Base::antilog[0x10000];
    00036
    00037 void IDEA::Base::BuildLogTables()
    00038 {
    00039         if (tablesBuilt)
    00040                 return;
    00041         else
    00042         {
    00043                 tablesBuilt = true;
    00044
    00045                 IDEA::Word x=1;
    00046                 word32 i;
    00047
    00048                 for (i=0; i<0x10000; i++)
    00049                 {
    00050                         antilog[i] = (word16)x;
    00051                         DirectMUL(x, 3);
    00052                 }
    00053
    00054                 for (i=0; i<0x10000; i++)
    00055                         log[antilog[i]] = (word16)i;
    00056         }
    00057 }
    00058
    00059 void IDEA::Base::LookupKeyLogs()
    00060 {
    00061         IDEA::Word* Z=key;
    00062         int r=ROUNDS;
    00063         do
    00064         {
    00065                 Z[0] = log[Z[0]];
    00066                 Z[3] = log[Z[3]];
    00067                 Z[4] = log[Z[4]];
    00068                 Z[5] = log[Z[5]];
    00069                 Z+=6;
    00070         } while (--r);
    00071         Z[0] = log[Z[0]];
    00072         Z[3] = log[Z[3]];
    00073 }
    00074
    00075 inline void IDEA::Base::LookupMUL(IDEA::Word &a, IDEA::Word b)
    00076 {
    00077         a = antilog[low16(log[low16(a)]+b)];
    00078 }
    00079 #endif // IDEA_LARGECACHE
    00080
    00081 void IDEA::Base::UncheckedSetKey(CipherDir direction, const byte *userKey, unsigned int length)
    00082 {
    00083         AssertValidKeyLength(length);
    00084
    00085 #ifdef IDEA_LARGECACHE
    00086         BuildLogTables();
    00087 #endif
    00088
    00089         EnKey(userKey);
    00090
    00091         if (direction==DECRYPTION)
    00092                 DeKey();
    00093
    00094 #ifdef IDEA_LARGECACHE
    00095         LookupKeyLogs();
    00096 #endif
    00097 }
    00098
    00099 void IDEA::Base::EnKey (const byte *userKey)
    00100 {
    00101         unsigned int i;
    00102
    00103         for (i=0; i<8; i++)
    00104                 m_key[i] = ((IDEA::Word)userKey[2*i]<<8) | userKey[2*i+1];
    00105
    00106         for (; i<IDEA_KEYLEN; i++)
    00107         {
    00108                 unsigned int j = RoundDownToMultipleOf(i,8U)-8;
    00109                 m_key[i] = low16((m_key[j+(i+1)%8] << 9) | (m_key[j+(i+2)%8] >> 7));
    00110         }
    00111 }
    00112
    00113 static IDEA::Word MulInv(IDEA::Word x)
    00114 {
    00115         IDEA::Word y=x;
    00116         for (unsigned i=0; i<15; i++)
    00117         {
    00118                 DirectMUL(y,low16(y));
    00119                 DirectMUL(y,x);
    00120         }
    00121         return low16(y);
    00122 }
    00123
    00124 static inline IDEA::Word AddInv(IDEA::Word x)
    00125 {
    00126         return low16(0-x);
    00127 }
    00128
    00129 void IDEA::Base::DeKey()
    00130 {
    00131         FixedSizeSecBlock<IDEA::Word, 6*ROUNDS+4> tempkey;
    00132         unsigned int i;
    00133
    00134         for (i=0; i<ROUNDS; i++)
    00135         {
    00136                 tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]);
    00137                 tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1+(i>0)]);
    00138                 tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2-(i>0)]);
    00139                 tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]);
    00140                 tempkey[i*6+4] =        m_key[(ROUNDS-1-i)*6+4];
    00141                 tempkey[i*6+5] =        m_key[(ROUNDS-1-i)*6+5];
    00142         }
    00143
    00144         tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]);
    00145         tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1]);
    00146         tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2]);
    00147         tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]);
    00148
    00149         m_key = tempkey;
    00150 }
    00151
    00152 #ifdef IDEA_LARGECACHE
    00153 #define MUL(a,b) LookupMUL(a,b)
    00154 #else
    00155 #define MUL(a,b) DirectMUL(a,b)
    00156 #endif
    00157
    00158 void IDEA::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
    00159 {
    00160         typedef BlockGetAndPut<word16, BigEndian> Block;
    00161
    00162         const IDEA::Word *key = m_key;
    00163         IDEA::Word x0,x1,x2,x3,t0,t1;
    00164         Block::Get(inBlock)(x0)(x1)(x2)(x3);
    00165
    00166         for (unsigned int i=0; i<ROUNDS; i++)
    00167         {
    00168                 MUL(x0, key[i*6+0]);
    00169                 x1 += key[i*6+1];
    00170                 x2 += key[i*6+2];
    00171                 MUL(x3, key[i*6+3]);
    00172                 t0 = x0^x2;
    00173                 MUL(t0, key[i*6+4]);
    00174                 t1 = t0 + (x1^x3);
    00175                 MUL(t1, key[i*6+5]);
    00176                 t0 += t1;
    00177                 x0 ^= t1;
    00178                 x3 ^= t0;
    00179                 t0 ^= x1;
    00180                 x1 = x2^t1;
    00181                 x2 = t0;
    00182         }
    00183
    00184         MUL(x0, key[ROUNDS*6+0]);
    00185         x2 += key[ROUNDS*6+1];
    00186         x1 += key[ROUNDS*6+2];
    00187         MUL(x3, key[ROUNDS*6+3]);
    00188
    00189         Block::Put(xorBlock, outBlock)(x0)(x2)(x1)(x3);
    00190 }
    00191
    00192 NAMESPACE_END