Crypto++
idea.cpp
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 
7 NAMESPACE_BEGIN(CryptoPP)
8 
9 static 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 
14 CRYPTOPP_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
33 volatile bool IDEA::Base::tablesBuilt = false;
34 word16 IDEA::Base::log[0x10000];
35 word16 IDEA::Base::antilog[0x10000];
36 
37 void 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 
59 void 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 
75 inline 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 
81 void 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 
99 void 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 
113 static 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 
124 static inline IDEA::Word AddInv(IDEA::Word x)
125 {
126  return low16(0-x);
127 }
128 
129 void IDEA::Base::DeKey()
130 {
132  size_t 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 
158 void IDEA::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
159 {
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 
192 NAMESPACE_END
IDEA
Definition: idea.h:19
a SecBlock with fixed size, allocated statically
Definition: secblock.h:422
interface for retrieving values given their names
Definition: cryptlib.h:225