Coverage Report

Created: 2024-11-21 07:03

/src/cryptopp/idea.cpp
Line
Count
Source
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
8
NAMESPACE_BEGIN(CryptoPP)
9
10
static const int IDEA_KEYLEN=(6*IDEA::ROUNDS+4);  // key schedule length in # of word16s
11
12
12.2k
#define low16(x) ((x)&0xffff)  // compiler should be able to optimize this away if word is 16 bits
13
8.52k
#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
6.96k
#define DirectMUL(a,b)          \
19
6.96k
{                   \
20
6.96k
  word32 p=(word32)low16(a)*b;    \
21
6.96k
                    \
22
6.96k
  if (p)               \
23
6.96k
  {                 \
24
4.26k
    p = low16(p) - high16(p);    \
25
4.26k
    a = (IDEA::Word)p - (IDEA::Word)high16(p);  \
26
4.26k
  }                  \
27
6.96k
  else                \
28
6.96k
    a = 1-a-b;           \
29
6.96k
}
30
31
#ifdef IDEA_LARGECACHE
32
volatile bool IDEA::Base::tablesBuilt = false;
33
word16 IDEA::Base::log[0x10000];
34
word16 IDEA::Base::antilog[0x10000];
35
36
void 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
58
void 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
74
inline 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
80
void IDEA::Base::UncheckedSetKey(const byte *userKey, unsigned int length, const NameValuePairs &)
81
16
{
82
16
  AssertValidKeyLength(length);
83
84
#ifdef IDEA_LARGECACHE
85
  BuildLogTables();
86
#endif
87
88
16
  EnKey(userKey);
89
90
16
  if (!IsForwardTransformation())
91
9
    DeKey();
92
93
#ifdef IDEA_LARGECACHE
94
  LookupKeyLogs();
95
#endif
96
16
}
97
98
void IDEA::Base::EnKey (const byte *userKey)
99
16
{
100
16
  unsigned int i;
101
102
144
  for (i=0; i<8; i++)
103
128
    m_key[i] = ((IDEA::Word)userKey[2*i]<<8) | userKey[2*i+1];
104
105
720
  for (; i<IDEA_KEYLEN; i++)
106
704
  {
107
704
    unsigned int j = RoundDownToMultipleOf(i,8U)-8;
108
704
    m_key[i] = low16((m_key[j+(i+1)%8] << 9) | (m_key[j+(i+2)%8] >> 7));
109
704
  }
110
16
}
111
112
static IDEA::Word MulInv(IDEA::Word x)
113
162
{
114
162
  IDEA::Word y=x;
115
2.59k
  for (unsigned i=0; i<15; i++)
116
2.43k
  {
117
2.43k
    DirectMUL(y,low16(y));
118
2.43k
    DirectMUL(y,x);
119
2.43k
  }
120
162
  return low16(y);
121
162
}
122
123
static inline IDEA::Word AddInv(IDEA::Word x)
124
162
{
125
162
  return low16(0-x);
126
162
}
127
128
void IDEA::Base::DeKey()
129
9
{
130
9
  FixedSizeSecBlock<IDEA::Word, 6*ROUNDS+4> tempkey;
131
9
  size_t i;
132
133
81
  for (i=0; i<ROUNDS; i++)
134
72
  {
135
72
    tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]);
136
72
    tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1+(i>0)]);
137
72
    tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2-(i>0)]);
138
72
    tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]);
139
72
    tempkey[i*6+4] =        m_key[(ROUNDS-1-i)*6+4];
140
72
    tempkey[i*6+5] =        m_key[(ROUNDS-1-i)*6+5];
141
72
  }
142
143
9
  tempkey[i*6+0] = MulInv(m_key[(ROUNDS-i)*6+0]);
144
9
  tempkey[i*6+1] = AddInv(m_key[(ROUNDS-i)*6+1]);
145
9
  tempkey[i*6+2] = AddInv(m_key[(ROUNDS-i)*6+2]);
146
9
  tempkey[i*6+3] = MulInv(m_key[(ROUNDS-i)*6+3]);
147
148
9
  m_key = tempkey;
149
9
}
150
151
#ifdef IDEA_LARGECACHE
152
#define MUL(a,b) LookupMUL(a,b)
153
#else
154
2.10k
#define MUL(a,b) DirectMUL(a,b)
155
#endif
156
157
void IDEA::Base::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
158
62
{
159
62
  typedef BlockGetAndPut<word16, BigEndian> Block;
160
161
62
  const IDEA::Word *key = m_key;
162
62
  IDEA::Word x0,x1,x2,x3,t0,t1;
163
62
  Block::Get(inBlock)(x0)(x1)(x2)(x3);
164
165
558
  for (unsigned int i=0; i<ROUNDS; i++)
166
496
  {
167
496
    MUL(x0, key[i*6+0]);
168
496
    x1 += key[i*6+1];
169
496
    x2 += key[i*6+2];
170
496
    MUL(x3, key[i*6+3]);
171
496
    t0 = x0^x2;
172
496
    MUL(t0, key[i*6+4]);
173
496
    t1 = t0 + (x1^x3);
174
496
    MUL(t1, key[i*6+5]);
175
496
    t0 += t1;
176
496
    x0 ^= t1;
177
496
    x3 ^= t0;
178
496
    t0 ^= x1;
179
496
    x1 = x2^t1;
180
496
    x2 = t0;
181
496
  }
182
183
62
  MUL(x0, key[ROUNDS*6+0]);
184
62
  x2 += key[ROUNDS*6+1];
185
62
  x1 += key[ROUNDS*6+2];
186
62
  MUL(x3, key[ROUNDS*6+3]);
187
188
62
  Block::Put(xorBlock, outBlock)(x0)(x2)(x1)(x3);
189
62
}
190
191
NAMESPACE_END