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