You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
3.8 KiB
192 lines
3.8 KiB
// idea.cpp - written and placed in the public domain by Wei Dai |
|
|
|
#include "pch.h" |
|
#include "idea.h" |
|
#include "misc.h" |
|
|
|
NAMESPACE_BEGIN(CryptoPP) |
|
|
|
static const int IDEA_KEYLEN=(6*IDEA::ROUNDS+4); // key schedule length in # of word16s |
|
|
|
#define low16(x) ((x)&0xffff) // compiler should be able to optimize this away if word is 16 bits |
|
#define high16(x) ((x)>>16) |
|
|
|
CRYPTOPP_COMPILE_ASSERT(sizeof(IDEA::Word) >= 2); |
|
|
|
// should use an inline function but macros are still faster in MSVC 4.0 |
|
#define DirectMUL(a,b) \ |
|
{ \ |
|
assert(b <= 0xffff); \ |
|
\ |
|
word32 p=(word32)low16(a)*b; \ |
|
\ |
|
if (p) \ |
|
{ \ |
|
p = low16(p) - high16(p); \ |
|
a = (IDEA::Word)p - (IDEA::Word)high16(p); \ |
|
} \ |
|
else \ |
|
a = 1-a-b; \ |
|
} |
|
|
|
#ifdef IDEA_LARGECACHE |
|
volatile bool IDEA::Base::tablesBuilt = false; |
|
word16 IDEA::Base::log[0x10000]; |
|
word16 IDEA::Base::antilog[0x10000]; |
|
|
|
void IDEA::Base::BuildLogTables() |
|
{ |
|
if (tablesBuilt) |
|
return; |
|
else |
|
{ |
|
tablesBuilt = true; |
|
|
|
IDEA::Word x=1; |
|
word32 i; |
|
|
|
for (i=0; i<0x10000; i++) |
|
{ |
|
antilog[i] = (word16)x; |
|
DirectMUL(x, 3); |
|
} |
|
|
|
for (i=0; i<0x10000; i++) |
|
log[antilog[i]] = (word16)i; |
|
} |
|
} |
|
|
|
void IDEA::Base::LookupKeyLogs() |
|
{ |
|
IDEA::Word* Z=key; |
|
int r=ROUNDS; |
|
do |
|
{ |
|
Z[0] = log[Z[0]]; |
|
Z[3] = log[Z[3]]; |
|
Z[4] = log[Z[4]]; |
|
Z[5] = log[Z[5]]; |
|
Z+=6; |
|
} while (--r); |
|
Z[0] = log[Z[0]]; |
|
Z[3] = log[Z[3]]; |
|
} |
|
|
|
inline void IDEA::Base::LookupMUL(IDEA::Word &a, IDEA::Word b) |
|
{ |
|
a = antilog[low16(log[low16(a)]+b)]; |
|
} |
|
#endif // IDEA_LARGECACHE |
|
|
|
void IDEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &) |
|
{ |
|
AssertValidKeyLength(length); |
|
|
|
#ifdef IDEA_LARGECACHE |
|
BuildLogTables(); |
|
#endif |
|
|
|
EnKey(userKey); |
|
|
|
if (!IsForwardTransformation()) |
|
DeKey(); |
|
|
|
#ifdef IDEA_LARGECACHE |
|
LookupKeyLogs(); |
|
#endif |
|
} |
|
|
|
void IDEA::Base::EnKey (const byte *userKey) |
|
{ |
|
unsigned int i; |
|
|
|
for (i=0; i<8; i++) |
|
m_key[i] = ((IDEA::Word)userKey[2*i]<<8) | userKey[2*i+1]; |
|
|
|
for (; i<IDEA_KEYLEN; i++) |
|
{ |
|
unsigned int j = RoundDownToMultipleOf(i,8U)-8; |
|
m_key[i] = low16((m_key[j+(i+1)%8] << 9) | (m_key[j+(i+2)%8] >> 7)); |
|
} |
|
} |
|
|
|
static IDEA::Word MulInv(IDEA::Word x) |
|
{ |
|
IDEA::Word y=x; |
|
for (unsigned i=0; i<15; i++) |
|
{ |
|
DirectMUL(y,low16(y)); |
|
DirectMUL(y,x); |
|
} |
|
return low16(y); |
|
} |
|
|
|
static inline IDEA::Word AddInv(IDEA::Word x) |
|
{ |
|
return low16(0-x); |
|
} |
|
|
|
void IDEA::Base::DeKey() |
|
{ |
|
FixedSizeSecBlock<IDEA::Word, 6*ROUNDS+4> tempkey; |
|
size_t i; |
|
|
|
for (i=0; i<ROUNDS; i++) |
|
{ |
|
tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]); |
|
tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1+(i>0)]); |
|
tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2-(i>0)]); |
|
tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]); |
|
tempkey[i*6+4] = m_key[(ROUNDS-1-i)*6+4]; |
|
tempkey[i*6+5] = m_key[(ROUNDS-1-i)*6+5]; |
|
} |
|
|
|
tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]); |
|
tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1]); |
|
tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2]); |
|
tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]); |
|
|
|
m_key = tempkey; |
|
} |
|
|
|
#ifdef IDEA_LARGECACHE |
|
#define MUL(a,b) LookupMUL(a,b) |
|
#else |
|
#define MUL(a,b) DirectMUL(a,b) |
|
#endif |
|
|
|
void IDEA::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const |
|
{ |
|
typedef BlockGetAndPut<word16, BigEndian> Block; |
|
|
|
const IDEA::Word *key = m_key; |
|
IDEA::Word x0,x1,x2,x3,t0,t1; |
|
Block::Get(inBlock)(x0)(x1)(x2)(x3); |
|
|
|
for (unsigned int i=0; i<ROUNDS; i++) |
|
{ |
|
MUL(x0, key[i*6+0]); |
|
x1 += key[i*6+1]; |
|
x2 += key[i*6+2]; |
|
MUL(x3, key[i*6+3]); |
|
t0 = x0^x2; |
|
MUL(t0, key[i*6+4]); |
|
t1 = t0 + (x1^x3); |
|
MUL(t1, key[i*6+5]); |
|
t0 += t1; |
|
x0 ^= t1; |
|
x3 ^= t0; |
|
t0 ^= x1; |
|
x1 = x2^t1; |
|
x2 = t0; |
|
} |
|
|
|
MUL(x0, key[ROUNDS*6+0]); |
|
x2 += key[ROUNDS*6+1]; |
|
x1 += key[ROUNDS*6+2]; |
|
MUL(x3, key[ROUNDS*6+3]); |
|
|
|
Block::Put(xorBlock, outBlock)(x0)(x2)(x1)(x3); |
|
} |
|
|
|
NAMESPACE_END
|
|
|