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

Generated on Tue Aug 16 08:38:41 2005 for Crypto++ by  doxygen 1.3.9.1