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