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(const byte *userKey, unsigned int length, const NameValuePairs &)
00082 {
00083         AssertValidKeyLength(length);
00084         
00085 #ifdef IDEA_LARGECACHE
00086         BuildLogTables();
00087 #endif
00088         
00089         EnKey(userKey);
00090         
00091         if (!IsForwardTransformation())
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

Generated on Sat Dec 23 02:07:08 2006 for Crypto++ by  doxygen 1.5.1-p1