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