Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | 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 Wed Jul 21 19:15:27 2004 for Crypto++ by doxygen 1.3.7-20040704