1// idea.cpp - written and placed in the public domain by Wei Dai 2 3#include "pch.h" 4#include "idea.h" 5#include "misc.h" 6 7NAMESPACE_BEGIN(CryptoPP) 8 9static const int IDEA_KEYLEN=(6*IDEA::ROUNDS+4); // key schedule length in # of word16s 10 11#define low16(x) ((x)&0xffff) // compiler should be able to optimize this away if word is 16 bits 12#define high16(x) ((x)>>16) 13 14CRYPTOPP_COMPILE_ASSERT(sizeof(IDEA::Word) >= 2); 15 16// should use an inline function but macros are still faster in MSVC 4.0 17#define DirectMUL(a,b) \ 18{ \ 19 assert(b <= 0xffff); \ 20 \ 21 word32 p=(word32)low16(a)*b; \ 22 \ 23 if (p) \ 24 { \ 25 p = low16(p) - high16(p); \ 26 a = (IDEA::Word)p - (IDEA::Word)high16(p); \ 27 } \ 28 else \ 29 a = 1-a-b; \ 30} 31 32#ifdef IDEA_LARGECACHE 33bool IDEA::Base::tablesBuilt = false; 34word16 IDEA::Base::log[0x10000]; 35word16 IDEA::Base::antilog[0x10000]; 36 37void IDEA::Base::BuildLogTables() 38{ 39 if (tablesBuilt) 40 return; 41 else 42 { 43 tablesBuilt = true; 44 45 IDEA::Word x=1; 46 word32 i; 47 48 for (i=0; i<0x10000; i++) 49 { 50 antilog[i] = (word16)x; 51 DirectMUL(x, 3); 52 } 53 54 for (i=0; i<0x10000; i++) 55 log[antilog[i]] = (word16)i; 56 } 57} 58 59void IDEA::Base::LookupKeyLogs() 60{ 61 IDEA::Word* Z=key; 62 int r=ROUNDS; 63 do 64 { 65 Z[0] = log[Z[0]]; 66 Z[3] = log[Z[3]]; 67 Z[4] = log[Z[4]]; 68 Z[5] = log[Z[5]]; 69 Z+=6; 70 } while (--r); 71 Z[0] = log[Z[0]]; 72 Z[3] = log[Z[3]]; 73} 74 75inline void IDEA::Base::LookupMUL(IDEA::Word &a, IDEA::Word b) 76{ 77 a = antilog[low16(log[low16(a)]+b)]; 78} 79#endif // IDEA_LARGECACHE 80 81void IDEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) 82{ 83 AssertValidKeyLength(length); 84 85#ifdef IDEA_LARGECACHE 86 BuildLogTables(); 87#endif 88 89 EnKey(userKey); 90 91 if (!IsForwardTransformation()) 92 DeKey(); 93 94#ifdef IDEA_LARGECACHE 95 LookupKeyLogs(); 96#endif 97} 98 99void IDEA::Base::EnKey (const byte *userKey) 100{ 101 unsigned int i; 102 103 for (i=0; i<8; i++) 104 m_key[i] = ((IDEA::Word)userKey[2*i]<<8) | userKey[2*i+1]; 105 106 for (; i<IDEA_KEYLEN; i++) 107 { 108 unsigned int j = RoundDownToMultipleOf(i,8U)-8; 109 m_key[i] = low16((m_key[j+(i+1)%8] << 9) | (m_key[j+(i+2)%8] >> 7)); 110 } 111} 112 113static IDEA::Word MulInv(IDEA::Word x) 114{ 115 IDEA::Word y=x; 116 for (unsigned i=0; i<15; i++) 117 { 118 DirectMUL(y,low16(y)); 119 DirectMUL(y,x); 120 } 121 return low16(y); 122} 123 124static inline IDEA::Word AddInv(IDEA::Word x) 125{ 126 return low16(0-x); 127} 128 129void IDEA::Base::DeKey() 130{ 131 FixedSizeSecBlock<IDEA::Word, 6*ROUNDS+4> tempkey; 132 unsigned int i; 133 134 for (i=0; i<ROUNDS; i++) 135 { 136 tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]); 137 tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1+(i>0)]); 138 tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2-(i>0)]); 139 tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]); 140 tempkey[i*6+4] = m_key[(ROUNDS-1-i)*6+4]; 141 tempkey[i*6+5] = m_key[(ROUNDS-1-i)*6+5]; 142 } 143 144 tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]); 145 tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1]); 146 tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2]); 147 tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]); 148 149 m_key = tempkey; 150} 151 152#ifdef IDEA_LARGECACHE 153#define MUL(a,b) LookupMUL(a,b) 154#else 155#define MUL(a,b) DirectMUL(a,b) 156#endif 157 158void IDEA::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const 159{ 160 typedef BlockGetAndPut<word16, BigEndian> Block; 161 162 const IDEA::Word *key = m_key; 163 IDEA::Word x0,x1,x2,x3,t0,t1; 164 Block::Get(inBlock)(x0)(x1)(x2)(x3); 165 166 for (unsigned int i=0; i<ROUNDS; i++) 167 { 168 MUL(x0, key[i*6+0]); 169 x1 += key[i*6+1]; 170 x2 += key[i*6+2]; 171 MUL(x3, key[i*6+3]); 172 t0 = x0^x2; 173 MUL(t0, key[i*6+4]); 174 t1 = t0 + (x1^x3); 175 MUL(t1, key[i*6+5]); 176 t0 += t1; 177 x0 ^= t1; 178 x3 ^= t0; 179 t0 ^= x1; 180 x1 = x2^t1; 181 x2 = t0; 182 } 183 184 MUL(x0, key[ROUNDS*6+0]); 185 x2 += key[ROUNDS*6+1]; 186 x1 += key[ROUNDS*6+2]; 187 MUL(x3, key[ROUNDS*6+3]); 188 189 Block::Put(xorBlock, outBlock)(x0)(x2)(x1)(x3); 190} 191 192NAMESPACE_END 193