00001
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);
00010
00011 #define low16(x) ((x)&0xffff)
00012 #define high16(x) ((x)>>16)
00013
00014
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