Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/cryptopp/cham.cpp
2 views
1
// cham.cpp - written and placed in the public domain by Kim Sung Hee and Jeffrey Walton
2
// Based on "CHAM: A Family of Lightweight Block Ciphers for
3
// Resource-Constrained Devices" by Bonwook Koo, Dongyoung Roh,
4
// Hyeonjin Kim, Younghoon Jung, Dong-Geon Lee, and Daesung Kwon
5
6
#include "pch.h"
7
#include "config.h"
8
9
#include "cham.h"
10
#include "misc.h"
11
#include "cpu.h"
12
13
// CHAM table of parameters
14
// +-------------------------------------------------
15
// +cipher n k r w k/w
16
// +-------------------------------------------------
17
// +CHAM-64/128 64 128 80 16 8
18
// +CHAM-128/128 128 128 80 32 4
19
// +CHAM-128/256 128 256 96 32 8
20
// +-------------------------------------------------
21
22
ANONYMOUS_NAMESPACE_BEGIN
23
24
using CryptoPP::rotlConstant;
25
using CryptoPP::rotrConstant;
26
27
/// \brief CHAM encryption round
28
/// \tparam RR the round number residue
29
/// \tparam KW the number of key words
30
/// \tparam T words type
31
/// \param x the state array
32
/// \param k the subkey table
33
/// \param i the round number
34
/// \details CHAM_EncRound applies the encryption round to the plain text.
35
/// RR is the "round residue" and it is used modulo 4. ProcessAndXorBlock
36
/// may provide a fully unrolled encryption transformation, or provide
37
/// a transformation that loops using multiples of 4 encryption rounds.
38
/// \details CHAM_EncRound calculates indexes into the x[] array based
39
/// on the round number residue. There is no need for the assignments
40
/// that shift values in preparations for the next round.
41
/// \details CHAM_EncRound depends on the round number. The actual round
42
/// being executed is passed through the parameter <tt>i</tt>. If
43
/// ProcessAndXorBlock fully unrolled the loop then the parameter
44
/// <tt>i</tt> would be unnecessary.
45
template <unsigned int RR, unsigned int KW, class T>
46
inline void CHAM_EncRound(T x[4], const T k[KW], unsigned int i)
47
{
48
CRYPTOPP_CONSTANT(IDX0 = (RR+0) % 4);
49
CRYPTOPP_CONSTANT(IDX1 = (RR+1) % 4);
50
CRYPTOPP_CONSTANT(IDX3 = (RR+3+1) % 4);
51
CRYPTOPP_CONSTANT(R1 = (RR % 2 == 0) ? 1 : 8);
52
CRYPTOPP_CONSTANT(R2 = (RR % 2 == 0) ? 8 : 1);
53
54
// Follows conventions in the ref impl
55
const T kk = k[i % KW];
56
const T aa = x[IDX0] ^ static_cast<T>(i);
57
const T bb = rotlConstant<R1>(x[IDX1]) ^ kk;
58
x[IDX3] = rotlConstant<R2>(static_cast<T>(aa + bb));
59
}
60
61
/// \brief CHAM decryption round
62
/// \tparam RR the round number residue
63
/// \tparam KW the number of key words
64
/// \tparam T words type
65
/// \param x the state array
66
/// \param k the subkey table
67
/// \param i the round number
68
/// \details CHAM_DecRound applies the decryption round to the cipher text.
69
/// RR is the "round residue" and it is used modulo 4. ProcessAndXorBlock
70
/// may provide a fully unrolled decryption transformation, or provide
71
/// a transformation that loops using multiples of 4 decryption rounds.
72
/// \details CHAM_DecRound calculates indexes into the x[] array based
73
/// on the round number residue. There is no need for the assignments
74
/// that shift values in preparations for the next round.
75
/// \details CHAM_DecRound depends on the round number. The actual round
76
/// being executed is passed through the parameter <tt>i</tt>. If
77
/// ProcessAndXorBlock fully unrolled the loop then the parameter
78
/// <tt>i</tt> would be unnecessary.
79
template <unsigned int RR, unsigned int KW, class T>
80
inline void CHAM_DecRound(T x[4], const T k[KW], unsigned int i)
81
{
82
CRYPTOPP_CONSTANT(IDX0 = (RR+0) % 4);
83
CRYPTOPP_CONSTANT(IDX1 = (RR+1) % 4);
84
CRYPTOPP_CONSTANT(IDX3 = (RR+3+1) % 4);
85
CRYPTOPP_CONSTANT(R1 = (RR % 2 == 0) ? 8 : 1);
86
CRYPTOPP_CONSTANT(R2 = (RR % 2 == 0) ? 1 : 8);
87
88
// Follows conventions in the ref impl
89
const T kk = k[i % KW];
90
const T aa = rotrConstant<R1>(x[IDX3]);
91
const T bb = rotlConstant<R2>(x[IDX1]) ^ kk;
92
x[IDX0] = static_cast<T>(aa - bb) ^ static_cast<T>(i);
93
}
94
95
ANONYMOUS_NAMESPACE_END
96
97
NAMESPACE_BEGIN(CryptoPP)
98
99
#if CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS
100
# if (CRYPTOPP_SSSE3_AVAILABLE)
101
extern size_t CHAM64_Enc_AdvancedProcessBlocks_SSSE3(const word16* subKeys, size_t rounds,
102
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
103
104
extern size_t CHAM64_Dec_AdvancedProcessBlocks_SSSE3(const word16* subKeys, size_t rounds,
105
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
106
107
extern size_t CHAM128_Enc_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds,
108
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
109
110
extern size_t CHAM128_Dec_AdvancedProcessBlocks_SSSE3(const word32* subKeys, size_t rounds,
111
const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
112
# endif // CRYPTOPP_SSSE3_AVAILABLE
113
#endif // CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS
114
115
void CHAM64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
116
{
117
CRYPTOPP_UNUSED(params);
118
m_kw = keyLength/sizeof(word16);
119
m_rk.New(2*m_kw);
120
121
for (size_t i = 0; i < m_kw; userKey += sizeof(word32))
122
{
123
// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
124
const word32 rk = GetWord<word32>(false, BIG_ENDIAN_ORDER, userKey);
125
126
const word16 rk1 = static_cast<word16>(rk >> 16);
127
m_rk[i] = rk1 ^ rotlConstant<1>(rk1) ^ rotlConstant<8>(rk1);
128
m_rk[(i + m_kw) ^ 1] = rk1 ^ rotlConstant<1>(rk1) ^ rotlConstant<11>(rk1);
129
i++;
130
131
const word16 rk2 = static_cast<word16>(rk & 0xffff);
132
m_rk[i] = rk2 ^ rotlConstant<1>(rk2) ^ rotlConstant<8>(rk2);
133
m_rk[(i + m_kw) ^ 1] = rk2 ^ rotlConstant<1>(rk2) ^ rotlConstant<11>(rk2);
134
i++;
135
}
136
}
137
138
void CHAM64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
139
{
140
// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
141
GetBlock<word16, BigEndian> iblock(inBlock);
142
iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
143
144
const int R = 80;
145
for (int i = 0; i < R; i+=16)
146
{
147
CHAM_EncRound< 0, 16>(m_x.begin(), m_rk.begin(), i+0);
148
CHAM_EncRound< 1, 16>(m_x.begin(), m_rk.begin(), i+1);
149
CHAM_EncRound< 2, 16>(m_x.begin(), m_rk.begin(), i+2);
150
CHAM_EncRound< 3, 16>(m_x.begin(), m_rk.begin(), i+3);
151
CHAM_EncRound< 4, 16>(m_x.begin(), m_rk.begin(), i+4);
152
CHAM_EncRound< 5, 16>(m_x.begin(), m_rk.begin(), i+5);
153
CHAM_EncRound< 6, 16>(m_x.begin(), m_rk.begin(), i+6);
154
CHAM_EncRound< 7, 16>(m_x.begin(), m_rk.begin(), i+7);
155
CHAM_EncRound< 8, 16>(m_x.begin(), m_rk.begin(), i+8);
156
CHAM_EncRound< 9, 16>(m_x.begin(), m_rk.begin(), i+9);
157
CHAM_EncRound<10, 16>(m_x.begin(), m_rk.begin(), i+10);
158
CHAM_EncRound<11, 16>(m_x.begin(), m_rk.begin(), i+11);
159
CHAM_EncRound<12, 16>(m_x.begin(), m_rk.begin(), i+12);
160
CHAM_EncRound<13, 16>(m_x.begin(), m_rk.begin(), i+13);
161
CHAM_EncRound<14, 16>(m_x.begin(), m_rk.begin(), i+14);
162
CHAM_EncRound<15, 16>(m_x.begin(), m_rk.begin(), i+15);
163
}
164
165
PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);
166
oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
167
}
168
169
void CHAM64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
170
{
171
// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
172
GetBlock<word16, BigEndian> iblock(inBlock);
173
iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
174
175
const int R = 80;
176
for (int i = R-1; i >=0 ; i-=16)
177
{
178
CHAM_DecRound<15, 16>(m_x.begin(), m_rk.begin(), i-0);
179
CHAM_DecRound<14, 16>(m_x.begin(), m_rk.begin(), i-1);
180
CHAM_DecRound<13, 16>(m_x.begin(), m_rk.begin(), i-2);
181
CHAM_DecRound<12, 16>(m_x.begin(), m_rk.begin(), i-3);
182
CHAM_DecRound<11, 16>(m_x.begin(), m_rk.begin(), i-4);
183
CHAM_DecRound<10, 16>(m_x.begin(), m_rk.begin(), i-5);
184
CHAM_DecRound< 9, 16>(m_x.begin(), m_rk.begin(), i-6);
185
CHAM_DecRound< 8, 16>(m_x.begin(), m_rk.begin(), i-7);
186
CHAM_DecRound< 7, 16>(m_x.begin(), m_rk.begin(), i-8);
187
CHAM_DecRound< 6, 16>(m_x.begin(), m_rk.begin(), i-9);
188
CHAM_DecRound< 5, 16>(m_x.begin(), m_rk.begin(), i-10);
189
CHAM_DecRound< 4, 16>(m_x.begin(), m_rk.begin(), i-11);
190
CHAM_DecRound< 3, 16>(m_x.begin(), m_rk.begin(), i-12);
191
CHAM_DecRound< 2, 16>(m_x.begin(), m_rk.begin(), i-13);
192
CHAM_DecRound< 1, 16>(m_x.begin(), m_rk.begin(), i-14);
193
CHAM_DecRound< 0, 16>(m_x.begin(), m_rk.begin(), i-15);
194
}
195
196
PutBlock<word16, BigEndian> oblock(xorBlock, outBlock);
197
oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
198
}
199
200
std::string CHAM128::Base::AlgorithmProvider() const
201
{
202
#if defined(CRYPTOPP_SSSE3_AVAILABLE)
203
if (HasSSSE3())
204
return "SSSE3";
205
#endif
206
return "C++";
207
}
208
209
void CHAM128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
210
{
211
CRYPTOPP_UNUSED(params);
212
m_kw = keyLength/sizeof(word32);
213
m_rk.New(2*m_kw);
214
215
for (size_t i = 0; i < m_kw; userKey += sizeof(word32))
216
{
217
// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
218
const word32 rk = GetWord<word32>(false, BIG_ENDIAN_ORDER, userKey);
219
m_rk[i] = rk ^ rotlConstant<1>(rk) ^ rotlConstant<8>(rk);
220
m_rk[(i + m_kw) ^ 1] = rk ^ rotlConstant<1>(rk) ^ rotlConstant<11>(rk);
221
i++;
222
}
223
}
224
225
void CHAM128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
226
{
227
// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
228
GetBlock<word32, BigEndian> iblock(inBlock);
229
iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
230
231
switch (m_kw)
232
{
233
case 4: // 128-bit key
234
{
235
const int R = 80;
236
for (int i = 0; i < R; i+=8)
237
{
238
CHAM_EncRound<0, 8>(m_x.begin(), m_rk.begin(), i+0);
239
CHAM_EncRound<1, 8>(m_x.begin(), m_rk.begin(), i+1);
240
CHAM_EncRound<2, 8>(m_x.begin(), m_rk.begin(), i+2);
241
CHAM_EncRound<3, 8>(m_x.begin(), m_rk.begin(), i+3);
242
CHAM_EncRound<4, 8>(m_x.begin(), m_rk.begin(), i+4);
243
CHAM_EncRound<5, 8>(m_x.begin(), m_rk.begin(), i+5);
244
CHAM_EncRound<6, 8>(m_x.begin(), m_rk.begin(), i+6);
245
CHAM_EncRound<7, 8>(m_x.begin(), m_rk.begin(), i+7);
246
}
247
break;
248
}
249
case 8: // 256-bit key
250
{
251
const int R = 96;
252
for (int i = 0; i < R; i+=16)
253
{
254
CHAM_EncRound< 0, 16>(m_x.begin(), m_rk.begin(), i+0);
255
CHAM_EncRound< 1, 16>(m_x.begin(), m_rk.begin(), i+1);
256
CHAM_EncRound< 2, 16>(m_x.begin(), m_rk.begin(), i+2);
257
CHAM_EncRound< 3, 16>(m_x.begin(), m_rk.begin(), i+3);
258
CHAM_EncRound< 4, 16>(m_x.begin(), m_rk.begin(), i+4);
259
CHAM_EncRound< 5, 16>(m_x.begin(), m_rk.begin(), i+5);
260
CHAM_EncRound< 6, 16>(m_x.begin(), m_rk.begin(), i+6);
261
CHAM_EncRound< 7, 16>(m_x.begin(), m_rk.begin(), i+7);
262
CHAM_EncRound< 8, 16>(m_x.begin(), m_rk.begin(), i+8);
263
CHAM_EncRound< 9, 16>(m_x.begin(), m_rk.begin(), i+9);
264
CHAM_EncRound<10, 16>(m_x.begin(), m_rk.begin(), i+10);
265
CHAM_EncRound<11, 16>(m_x.begin(), m_rk.begin(), i+11);
266
CHAM_EncRound<12, 16>(m_x.begin(), m_rk.begin(), i+12);
267
CHAM_EncRound<13, 16>(m_x.begin(), m_rk.begin(), i+13);
268
CHAM_EncRound<14, 16>(m_x.begin(), m_rk.begin(), i+14);
269
CHAM_EncRound<15, 16>(m_x.begin(), m_rk.begin(), i+15);
270
}
271
break;
272
}
273
default:
274
CRYPTOPP_ASSERT(0);
275
}
276
277
PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);
278
oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
279
}
280
281
void CHAM128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
282
{
283
// Do not cast the buffer. It will SIGBUS on some ARM and SPARC.
284
GetBlock<word32, BigEndian> iblock(inBlock);
285
iblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
286
287
switch (m_kw)
288
{
289
case 4: // 128-bit key
290
{
291
const int R = 80;
292
for (int i = R-1; i >= 0; i-=8)
293
{
294
CHAM_DecRound<7, 8>(m_x.begin(), m_rk.begin(), i-0);
295
CHAM_DecRound<6, 8>(m_x.begin(), m_rk.begin(), i-1);
296
CHAM_DecRound<5, 8>(m_x.begin(), m_rk.begin(), i-2);
297
CHAM_DecRound<4, 8>(m_x.begin(), m_rk.begin(), i-3);
298
CHAM_DecRound<3, 8>(m_x.begin(), m_rk.begin(), i-4);
299
CHAM_DecRound<2, 8>(m_x.begin(), m_rk.begin(), i-5);
300
CHAM_DecRound<1, 8>(m_x.begin(), m_rk.begin(), i-6);
301
CHAM_DecRound<0, 8>(m_x.begin(), m_rk.begin(), i-7);
302
}
303
break;
304
}
305
case 8: // 256-bit key
306
{
307
const int R = 96;
308
for (int i = R-1; i >= 0; i-=16)
309
{
310
CHAM_DecRound<15, 16>(m_x.begin(), m_rk.begin(), i-0);
311
CHAM_DecRound<14, 16>(m_x.begin(), m_rk.begin(), i-1);
312
CHAM_DecRound<13, 16>(m_x.begin(), m_rk.begin(), i-2);
313
CHAM_DecRound<12, 16>(m_x.begin(), m_rk.begin(), i-3);
314
CHAM_DecRound<11, 16>(m_x.begin(), m_rk.begin(), i-4);
315
CHAM_DecRound<10, 16>(m_x.begin(), m_rk.begin(), i-5);
316
CHAM_DecRound< 9, 16>(m_x.begin(), m_rk.begin(), i-6);
317
CHAM_DecRound< 8, 16>(m_x.begin(), m_rk.begin(), i-7);
318
CHAM_DecRound< 7, 16>(m_x.begin(), m_rk.begin(), i-8);
319
CHAM_DecRound< 6, 16>(m_x.begin(), m_rk.begin(), i-9);
320
CHAM_DecRound< 5, 16>(m_x.begin(), m_rk.begin(), i-10);
321
CHAM_DecRound< 4, 16>(m_x.begin(), m_rk.begin(), i-11);
322
CHAM_DecRound< 3, 16>(m_x.begin(), m_rk.begin(), i-12);
323
CHAM_DecRound< 2, 16>(m_x.begin(), m_rk.begin(), i-13);
324
CHAM_DecRound< 1, 16>(m_x.begin(), m_rk.begin(), i-14);
325
CHAM_DecRound< 0, 16>(m_x.begin(), m_rk.begin(), i-15);
326
}
327
break;
328
}
329
default:
330
CRYPTOPP_ASSERT(0);
331
}
332
333
PutBlock<word32, BigEndian> oblock(xorBlock, outBlock);
334
oblock(m_x[0])(m_x[1])(m_x[2])(m_x[3]);
335
}
336
337
#if CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS
338
size_t CHAM128::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
339
byte *outBlocks, size_t length, word32 flags) const
340
{
341
# if (CRYPTOPP_SSSE3_AVAILABLE)
342
if (HasSSSE3()) {
343
const size_t rounds = (m_kw == 4 ? 80 : 96);
344
return CHAM128_Enc_AdvancedProcessBlocks_SSSE3(m_rk, rounds,
345
inBlocks, xorBlocks, outBlocks, length, flags);
346
}
347
# endif // CRYPTOPP_SSSE3_AVAILABLE
348
return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
349
}
350
351
size_t CHAM128::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
352
byte *outBlocks, size_t length, word32 flags) const
353
{
354
# if (CRYPTOPP_SSSE3_AVAILABLE)
355
if (HasSSSE3()) {
356
const size_t rounds = (m_kw == 4 ? 80 : 96);
357
return CHAM128_Dec_AdvancedProcessBlocks_SSSE3(m_rk, rounds,
358
inBlocks, xorBlocks, outBlocks, length, flags);
359
}
360
# endif // CRYPTOPP_SSSE3_AVAILABLE
361
return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
362
}
363
#endif // CRYPTOPP_CHAM128_ADVANCED_PROCESS_BLOCKS
364
365
NAMESPACE_END
366
367