Coverage Report

Created: 2024-11-21 07:03

/src/cryptopp/simon.cpp
Line
Count
Source (jump to first uncovered line)
1
// simon.h - written and placed in the public domain by Jeffrey Walton
2
3
#include "pch.h"
4
#include "config.h"
5
6
#include "simon.h"
7
#include "misc.h"
8
#include "cpu.h"
9
10
// Uncomment for benchmarking C++ against SSE or NEON.
11
// Do so in both simon.cpp and simon_simd.cpp.
12
// #undef CRYPTOPP_SSSE3_AVAILABLE
13
// #undef CRYPTOPP_SSE41_AVAILABLE
14
// #undef CRYPTOPP_ARM_NEON_AVAILABLE
15
16
ANONYMOUS_NAMESPACE_BEGIN
17
18
using CryptoPP::word32;
19
using CryptoPP::word64;
20
using CryptoPP::rotlConstant;
21
using CryptoPP::rotrConstant;
22
23
/// \brief Round transformation helper
24
/// \tparam W word type
25
/// \param v value
26
template <class W>
27
inline W f(const W v)
28
13.9k
{
29
13.9k
    return (rotlConstant<1>(v) & rotlConstant<8>(v)) ^ rotlConstant<2>(v);
30
13.9k
}
simon.cpp:unsigned int (anonymous namespace)::f<unsigned int>(unsigned int)
Line
Count
Source
28
13.9k
{
29
13.9k
    return (rotlConstant<1>(v) & rotlConstant<8>(v)) ^ rotlConstant<2>(v);
30
13.9k
}
simon.cpp:unsigned long (anonymous namespace)::f<unsigned long>(unsigned long)
Line
Count
Source
28
72
{
29
72
    return (rotlConstant<1>(v) & rotlConstant<8>(v)) ^ rotlConstant<2>(v);
30
72
}
31
32
/// \brief Round transformation
33
/// \tparam W word type
34
/// \param x value
35
/// \param y value
36
/// \param k value
37
/// \param l value
38
template <class W>
39
inline void R2(W& x, W& y, const W k, const W l)
40
6.98k
{
41
6.98k
    y ^= f(x); y ^= k;
42
6.98k
    x ^= f(y); x ^= l;
43
6.98k
}
simon.cpp:void (anonymous namespace)::R2<unsigned int>(unsigned int&, unsigned int&, unsigned int, unsigned int)
Line
Count
Source
40
6.95k
{
41
6.95k
    y ^= f(x); y ^= k;
42
6.95k
    x ^= f(y); x ^= l;
43
6.95k
}
simon.cpp:void (anonymous namespace)::R2<unsigned long>(unsigned long&, unsigned long&, unsigned long, unsigned long)
Line
Count
Source
40
36
{
41
36
    y ^= f(x); y ^= k;
42
36
    x ^= f(y); x ^= l;
43
36
}
44
45
/// \brief Forward transformation
46
/// \tparam W word type
47
/// \tparam R number of rounds
48
/// \param c output array
49
/// \param p input array
50
/// \param k subkey array
51
template <class W, unsigned int R>
52
inline void SIMON_Encrypt(W c[2], const W p[2], const W k[R])
53
47
{
54
47
    c[0]=p[0]; c[1]=p[1];
55
56
1.03k
    for (int i = 0; i < static_cast<int>(R-1); i += 2)
57
987
        R2(c[0], c[1], k[i], k[i + 1]);
58
59
47
    if (R & 1)
60
0
    {
61
0
        c[1] ^= f(c[0]); c[1] ^= k[R-1];
62
0
        W t = c[0]; c[0] = c[1]; c[1] = t;
63
0
    }
64
47
}
simon.cpp:void (anonymous namespace)::SIMON_Encrypt<unsigned int, 42u>(unsigned int*, unsigned int const*, unsigned int const*)
Line
Count
Source
53
47
{
54
47
    c[0]=p[0]; c[1]=p[1];
55
56
1.03k
    for (int i = 0; i < static_cast<int>(R-1); i += 2)
57
987
        R2(c[0], c[1], k[i], k[i + 1]);
58
59
47
    if (R & 1)
60
0
    {
61
0
        c[1] ^= f(c[0]); c[1] ^= k[R-1];
62
0
        W t = c[0]; c[0] = c[1]; c[1] = t;
63
0
    }
64
47
}
Unexecuted instantiation: simon.cpp:void (anonymous namespace)::SIMON_Encrypt<unsigned int, 44u>(unsigned int*, unsigned int const*, unsigned int const*)
Unexecuted instantiation: simon.cpp:void (anonymous namespace)::SIMON_Encrypt<unsigned long, 68u>(unsigned long*, unsigned long const*, unsigned long const*)
Unexecuted instantiation: simon.cpp:void (anonymous namespace)::SIMON_Encrypt<unsigned long, 69u>(unsigned long*, unsigned long const*, unsigned long const*)
Unexecuted instantiation: simon.cpp:void (anonymous namespace)::SIMON_Encrypt<unsigned long, 72u>(unsigned long*, unsigned long const*, unsigned long const*)
65
66
/// \brief Reverse transformation
67
/// \tparam W word type
68
/// \tparam R number of rounds
69
/// \param p output array
70
/// \param c input array
71
/// \param k subkey array
72
template <class W, unsigned int R>
73
inline void SIMON_Decrypt(W p[2], const W c[2], const W k[R])
74
285
{
75
285
    p[0]=c[0]; p[1]=c[1];
76
285
    unsigned int rounds = R;
77
78
285
    if (R & 1)
79
0
    {
80
0
        const W t = p[1]; p[1] = p[0]; p[0] = t;
81
0
        p[1] ^= k[R - 1]; p[1] ^= f(p[0]);
82
0
        rounds--;
83
0
    }
84
85
6.28k
    for (int i = static_cast<int>(rounds - 2); i >= 0; i -= 2)
86
6.00k
        R2(p[1], p[0], k[i + 1], k[i]);
87
285
}
simon.cpp:void (anonymous namespace)::SIMON_Decrypt<unsigned int, 42u>(unsigned int*, unsigned int const*, unsigned int const*)
Line
Count
Source
74
284
{
75
284
    p[0]=c[0]; p[1]=c[1];
76
284
    unsigned int rounds = R;
77
78
284
    if (R & 1)
79
0
    {
80
0
        const W t = p[1]; p[1] = p[0]; p[0] = t;
81
0
        p[1] ^= k[R - 1]; p[1] ^= f(p[0]);
82
0
        rounds--;
83
0
    }
84
85
6.24k
    for (int i = static_cast<int>(rounds - 2); i >= 0; i -= 2)
86
5.96k
        R2(p[1], p[0], k[i + 1], k[i]);
87
284
}
Unexecuted instantiation: simon.cpp:void (anonymous namespace)::SIMON_Decrypt<unsigned int, 44u>(unsigned int*, unsigned int const*, unsigned int const*)
Unexecuted instantiation: simon.cpp:void (anonymous namespace)::SIMON_Decrypt<unsigned long, 68u>(unsigned long*, unsigned long const*, unsigned long const*)
Unexecuted instantiation: simon.cpp:void (anonymous namespace)::SIMON_Decrypt<unsigned long, 69u>(unsigned long*, unsigned long const*, unsigned long const*)
simon.cpp:void (anonymous namespace)::SIMON_Decrypt<unsigned long, 72u>(unsigned long*, unsigned long const*, unsigned long const*)
Line
Count
Source
74
1
{
75
1
    p[0]=c[0]; p[1]=c[1];
76
1
    unsigned int rounds = R;
77
78
1
    if (R & 1)
79
0
    {
80
0
        const W t = p[1]; p[1] = p[0]; p[0] = t;
81
0
        p[1] ^= k[R - 1]; p[1] ^= f(p[0]);
82
0
        rounds--;
83
0
    }
84
85
37
    for (int i = static_cast<int>(rounds - 2); i >= 0; i -= 2)
86
36
        R2(p[1], p[0], k[i + 1], k[i]);
87
1
}
88
89
/// \brief Subkey generation function
90
/// \details Used for SIMON-64 with 96-bit key and 42 rounds. A template was
91
///   not worthwhile because all instantiations would need specialization.
92
/// \param key empty subkey array
93
/// \param k user key array
94
inline void SIMON64_ExpandKey_3W(word32 key[42], const word32 k[3])
95
5
{
96
5
    const word32 c = 0xfffffffc;
97
5
    word64 z = W64LIT(0x7369f885192c0ef5);
98
99
5
    key[0] = k[2]; key[1] = k[1]; key[2] = k[0];
100
200
    for (size_t i = 3; i<42; ++i)
101
195
    {
102
195
        key[i] = static_cast<word32>(c ^ (z & 1) ^ key[i - 3] ^
103
195
            rotrConstant<3>(key[i - 1]) ^ rotrConstant<4>(key[i - 1]));
104
195
        z >>= 1;
105
195
    }
106
5
}
107
108
/// \brief Subkey generation function
109
/// \details Used for SIMON-64 with 128-bit key and 44 rounds. A template was
110
///   not worthwhile because all instantiations would need specialization.
111
/// \param key empty subkey array
112
/// \param k user key array
113
inline void SIMON64_ExpandKey_4W(word32 key[44], const word32 k[4])
114
1
{
115
1
    const word32 c = 0xfffffffc;
116
1
    word64 z = W64LIT(0xfc2ce51207a635db);
117
118
1
    key[0] = k[3]; key[1] = k[2]; key[2] = k[1]; key[3] = k[0];
119
41
    for (size_t i = 4; i<44; ++i)
120
40
    {
121
40
        key[i] = static_cast<word32>(c ^ (z & 1) ^ key[i - 4] ^
122
40
            rotrConstant<3>(key[i - 1]) ^ key[i - 3] ^ rotrConstant<4>(key[i - 1]) ^
123
40
            rotrConstant<1>(key[i - 3]));
124
40
        z >>= 1;
125
40
    }
126
1
}
127
128
/// \brief Subkey generation function
129
/// \details Used for SIMON-128 with 128-bit key and 68 rounds. A template was
130
///   not worthwhile because all instantiations would need specialization.
131
/// \param key empty subkey array
132
/// \param k user key array
133
inline void SIMON128_ExpandKey_2W(word64 key[68], const word64 k[2])
134
4
{
135
4
    const word64 c = W64LIT(0xfffffffffffffffc);
136
4
    word64 z = W64LIT(0x7369f885192c0ef5);
137
138
4
    key[0] = k[1]; key[1] = k[0];
139
260
    for (size_t i=2; i<66; ++i)
140
256
    {
141
256
        key[i] = c ^ (z & 1) ^ key[i - 2] ^ rotrConstant<3>(key[i - 1]) ^ rotrConstant<4>(key[i - 1]);
142
256
        z>>=1;
143
256
    }
144
145
4
    key[66] = c ^ 1 ^ key[64] ^ rotrConstant<3>(key[65]) ^ rotrConstant<4>(key[65]);
146
4
    key[67] = c^key[65] ^ rotrConstant<3>(key[66]) ^ rotrConstant<4>(key[66]);
147
4
}
148
149
/// \brief Subkey generation function
150
/// \details Used for SIMON-128 with 192-bit key and 69 rounds. A template was
151
///   not worthwhile because all instantiations would need specialization.
152
/// \param key empty subkey array
153
/// \param k user key array
154
inline void SIMON128_ExpandKey_3W(word64 key[69], const word64 k[3])
155
3
{
156
3
    const word64 c = W64LIT(0xfffffffffffffffc);
157
3
    word64 z = W64LIT(0xfc2ce51207a635db);
158
159
3
    key[0]=k[2]; key[1]=k[1]; key[2]=k[0];
160
195
    for (size_t i=3; i<67; ++i)
161
192
    {
162
192
        key[i] = c ^ (z & 1) ^ key[i - 3] ^ rotrConstant<3>(key[i - 1]) ^ rotrConstant<4>(key[i - 1]);
163
192
        z>>=1;
164
192
    }
165
166
3
    key[67] = c^key[64] ^ rotrConstant<3>(key[66]) ^ rotrConstant<4>(key[66]);
167
3
    key[68] = c ^ 1 ^ key[65] ^ rotrConstant<3>(key[67]) ^ rotrConstant<4>(key[67]);
168
3
}
169
170
/// \brief Subkey generation function
171
/// \details Used for SIMON-128 with 256-bit key and 72 rounds. A template was
172
///   not worthwhile because all instantiations would need specialization.
173
/// \param key empty subkey array
174
/// \param k user key array
175
inline void SIMON128_ExpandKey_4W(word64 key[72], const word64 k[4])
176
3
{
177
3
    const word64 c = W64LIT(0xfffffffffffffffc);
178
3
    word64 z = W64LIT(0xfdc94c3a046d678b);
179
180
3
    key[0]=k[3]; key[1]=k[2]; key[2]=k[1]; key[3]=k[0];
181
195
    for (size_t i=4; i<68; ++i)
182
192
    {
183
192
        key[i] = c ^ (z & 1) ^ key[i - 4] ^ rotrConstant<3>(key[i - 1]) ^ key[i - 3] ^ rotrConstant<4>(key[i - 1]) ^ rotrConstant<1>(key[i - 3]);
184
192
        z>>=1;
185
192
    }
186
187
3
    key[68] = c^key[64] ^ rotrConstant<3>(key[67]) ^ key[65] ^ rotrConstant<4>(key[67]) ^ rotrConstant<1>(key[65]);
188
3
    key[69] = c ^ 1 ^ key[65] ^ rotrConstant<3>(key[68]) ^ key[66] ^ rotrConstant<4>(key[68]) ^ rotrConstant<1>(key[66]);
189
3
    key[70] = c^key[66] ^ rotrConstant<3>(key[69]) ^ key[67] ^ rotrConstant<4>(key[69]) ^ rotrConstant<1>(key[67]);
190
3
    key[71] = c^key[67] ^ rotrConstant<3>(key[70]) ^ key[68] ^ rotrConstant<4>(key[70]) ^ rotrConstant<1>(key[68]);
191
3
}
192
193
ANONYMOUS_NAMESPACE_END
194
195
///////////////////////////////////////////////////////////
196
197
NAMESPACE_BEGIN(CryptoPP)
198
199
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
200
extern size_t SIMON128_Enc_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds,
201
    const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
202
203
extern size_t SIMON128_Dec_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds,
204
    const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
205
#endif
206
207
#if (CRYPTOPP_SSSE3_AVAILABLE)
208
extern size_t SIMON128_Enc_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds,
209
    const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
210
211
extern size_t SIMON128_Dec_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds,
212
    const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
213
#endif
214
215
#if (CRYPTOPP_ALTIVEC_AVAILABLE)
216
extern size_t SIMON128_Enc_AdvancedProcessBlocks_ALTIVEC(const word64* subKeys, size_t rounds,
217
    const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
218
219
extern size_t SIMON128_Dec_AdvancedProcessBlocks_ALTIVEC(const word64* subKeys, size_t rounds,
220
    const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
221
#endif
222
223
std::string SIMON64::Base::AlgorithmProvider() const
224
0
{
225
0
    return "C++";
226
0
}
227
228
unsigned int SIMON64::Base::OptimalDataAlignment() const
229
0
{
230
0
    return GetAlignmentOf<word32>();
231
0
}
232
233
void SIMON64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
234
6
{
235
6
    CRYPTOPP_ASSERT(keyLength == 12 || keyLength == 16);
236
6
    CRYPTOPP_UNUSED(params);
237
238
    // Building the key schedule table requires {3,4} words workspace.
239
    // Encrypting and decrypting requires 4 words workspace.
240
6
    m_kwords = keyLength/sizeof(word32);
241
6
    m_wspace.New(4U);
242
243
    // Do the endian gyrations from the paper and align pointers
244
6
    typedef GetBlock<word32, LittleEndian> KeyBlock;
245
6
    KeyBlock kblk(userKey);
246
247
6
    switch (m_kwords)
248
6
    {
249
5
    case 3:
250
5
        m_rkeys.New((m_rounds = 42)+1);
251
5
        kblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
252
5
        SIMON64_ExpandKey_3W(m_rkeys, m_wspace);
253
5
        break;
254
1
    case 4:
255
1
        m_rkeys.New((m_rounds = 44)+1);
256
1
        kblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
257
1
        SIMON64_ExpandKey_4W(m_rkeys, m_wspace);
258
1
        break;
259
0
    default:
260
0
        CRYPTOPP_ASSERT(0);
261
6
    }
262
6
}
263
264
void SIMON64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
265
47
{
266
    // Do the endian gyrations from the paper and align pointers
267
47
    typedef GetBlock<word32, LittleEndian> InBlock;
268
47
    InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
269
270
47
    switch (m_rounds)
271
47
    {
272
47
    case 42:
273
47
        SIMON_Encrypt<word32, 42>(m_wspace+2, m_wspace+0, m_rkeys);
274
47
        break;
275
0
    case 44:
276
0
        SIMON_Encrypt<word32, 44>(m_wspace+2, m_wspace+0, m_rkeys);
277
0
        break;
278
0
    default:
279
0
        CRYPTOPP_ASSERT(0);
280
47
    }
281
282
    // Do the endian gyrations from the paper and align pointers
283
47
    typedef PutBlock<word32, LittleEndian> OutBlock;
284
47
    OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
285
47
}
286
287
void SIMON64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
288
284
{
289
    // Do the endian gyrations from the paper and align pointers
290
284
    typedef GetBlock<word32, LittleEndian> InBlock;
291
284
    InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
292
293
284
    switch (m_rounds)
294
284
    {
295
284
    case 42:
296
284
        SIMON_Decrypt<word32, 42>(m_wspace+2, m_wspace+0, m_rkeys);
297
284
        break;
298
0
    case 44:
299
0
        SIMON_Decrypt<word32, 44>(m_wspace+2, m_wspace+0, m_rkeys);
300
0
        break;
301
0
    default:
302
0
        CRYPTOPP_ASSERT(0);
303
284
    }
304
305
    // Do the endian gyrations from the paper and align pointers
306
284
    typedef PutBlock<word32, LittleEndian> OutBlock;
307
284
    OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
308
284
}
309
310
///////////////////////////////////////////////////////////
311
312
std::string SIMON128::Base::AlgorithmProvider() const
313
0
{
314
0
#if (CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS)
315
0
# if (CRYPTOPP_SSSE3_AVAILABLE)
316
0
    if (HasSSSE3())
317
0
        return "SSSE3";
318
0
# endif
319
# if (CRYPTOPP_ARM_NEON_AVAILABLE)
320
    if (HasNEON())
321
        return "NEON";
322
# endif
323
# if (CRYPTOPP_ALTIVEC_AVAILABLE)
324
    if (HasAltivec())
325
        return "Altivec";
326
# endif
327
0
#endif
328
0
    return "C++";
329
0
}
330
331
unsigned int SIMON128::Base::OptimalDataAlignment() const
332
0
{
333
0
#if (CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS)
334
0
# if (CRYPTOPP_SSSE3_AVAILABLE)
335
0
    if (HasSSSE3())
336
0
        return 16;  // load __m128i
337
0
# endif
338
# if (CRYPTOPP_ARM_NEON_AVAILABLE)
339
    if (HasNEON())
340
        return 8;  // load uint64x2_t
341
# endif
342
# if (CRYPTOPP_ALTIVEC_AVAILABLE)
343
    if (HasAltivec())
344
        return 16;  // load uint64x2_p
345
# endif
346
0
#endif
347
0
    return GetAlignmentOf<word64>();
348
0
}
349
350
void SIMON128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
351
10
{
352
10
    CRYPTOPP_ASSERT(keyLength == 16 || keyLength == 24 || keyLength == 32);
353
10
    CRYPTOPP_UNUSED(params);
354
355
    // Building the key schedule table requires {2,3,4} words workspace.
356
    // Encrypting and decrypting requires 4 words workspace.
357
10
    m_kwords = keyLength/sizeof(word64);
358
10
    m_wspace.New(4U);
359
360
    // Do the endian gyrations from the paper and align pointers
361
10
    typedef GetBlock<word64, LittleEndian> KeyBlock;
362
10
    KeyBlock kblk(userKey);
363
364
10
    switch (m_kwords)
365
10
    {
366
4
    case 2:
367
4
        m_rkeys.New((m_rounds = 68)+1);
368
4
        kblk(m_wspace[1])(m_wspace[0]);
369
4
        SIMON128_ExpandKey_2W(m_rkeys, m_wspace);
370
4
        break;
371
3
    case 3:
372
3
        m_rkeys.New((m_rounds = 69)+1);
373
3
        kblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
374
3
        SIMON128_ExpandKey_3W(m_rkeys, m_wspace);
375
3
        break;
376
3
    case 4:
377
3
        m_rkeys.New((m_rounds = 72)+1);
378
3
        kblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
379
3
        SIMON128_ExpandKey_4W(m_rkeys, m_wspace);
380
3
        break;
381
0
    default:
382
0
        CRYPTOPP_ASSERT(0);
383
10
    }
384
385
10
#if CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS
386
387
    // Pre-splat the round keys for Altivec forward transformation
388
#if CRYPTOPP_ALTIVEC_AVAILABLE
389
    if (IsForwardTransformation() && HasAltivec())
390
    {
391
        AlignedSecBlock presplat(m_rkeys.size()*2);
392
        for (size_t i=0, j=0; i<m_rkeys.size(); i++, j+=2)
393
            presplat[j+0] = presplat[j+1] = m_rkeys[i];
394
        m_rkeys.swap(presplat);
395
    }
396
#elif CRYPTOPP_SSSE3_AVAILABLE
397
10
    if (IsForwardTransformation() && HasSSSE3())
398
7
    {
399
7
        AlignedSecBlock presplat(m_rkeys.size()*2);
400
500
        for (size_t i=0, j=0; i<m_rkeys.size(); i++, j+=2)
401
493
            presplat[j+0] = presplat[j+1] = m_rkeys[i];
402
7
        m_rkeys.swap(presplat);
403
7
    }
404
10
#endif
405
406
10
#endif  // CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS
407
10
}
408
409
void SIMON128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
410
0
{
411
    // Do the endian gyrations from the paper and align pointers
412
0
    typedef GetBlock<word64, LittleEndian> InBlock;
413
0
    InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
414
415
0
    switch (m_rounds)
416
0
    {
417
0
    case 68:
418
0
        SIMON_Encrypt<word64, 68>(m_wspace+2, m_wspace+0, m_rkeys);
419
0
        break;
420
0
    case 69:
421
0
        SIMON_Encrypt<word64, 69>(m_wspace+2, m_wspace+0, m_rkeys);
422
0
        break;
423
0
    case 72:
424
0
        SIMON_Encrypt<word64, 72>(m_wspace+2, m_wspace+0, m_rkeys);
425
0
        break;
426
0
    default:
427
0
        CRYPTOPP_ASSERT(0);
428
0
    }
429
430
    // Do the endian gyrations from the paper and align pointers
431
0
    typedef PutBlock<word64, LittleEndian> OutBlock;
432
0
    OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
433
0
}
434
435
void SIMON128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
436
1
{
437
    // Do the endian gyrations from the paper and align pointers
438
1
    typedef GetBlock<word64, LittleEndian> InBlock;
439
1
    InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
440
441
1
    switch (m_rounds)
442
1
    {
443
0
    case 68:
444
0
        SIMON_Decrypt<word64, 68>(m_wspace+2, m_wspace+0, m_rkeys);
445
0
        break;
446
0
    case 69:
447
0
        SIMON_Decrypt<word64, 69>(m_wspace+2, m_wspace+0, m_rkeys);
448
0
        break;
449
1
    case 72:
450
1
        SIMON_Decrypt<word64, 72>(m_wspace+2, m_wspace+0, m_rkeys);
451
1
        break;
452
0
    default:
453
0
        CRYPTOPP_ASSERT(0);
454
1
    }
455
456
    // Do the endian gyrations from the paper and align pointers
457
1
    typedef PutBlock<word64, LittleEndian> OutBlock;
458
1
    OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
459
1
}
460
461
#if (CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS)
462
size_t SIMON128::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
463
        byte *outBlocks, size_t length, word32 flags) const
464
7
{
465
7
#if (CRYPTOPP_SSSE3_AVAILABLE)
466
7
    if (HasSSSE3())
467
7
        return SIMON128_Enc_AdvancedProcessBlocks_SSSE3(m_rkeys, (size_t)m_rounds,
468
7
            inBlocks, xorBlocks, outBlocks, length, flags);
469
0
#endif
470
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
471
    if (HasNEON())
472
        return SIMON128_Enc_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
473
            inBlocks, xorBlocks, outBlocks, length, flags);
474
#endif
475
#if (CRYPTOPP_ALTIVEC_AVAILABLE)
476
    if (HasAltivec())
477
        return SIMON128_Enc_AdvancedProcessBlocks_ALTIVEC(m_rkeys, (size_t)m_rounds,
478
            inBlocks, xorBlocks, outBlocks, length, flags);
479
#endif
480
0
    return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
481
7
}
482
483
size_t SIMON128::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
484
        byte *outBlocks, size_t length, word32 flags) const
485
7
{
486
7
#if (CRYPTOPP_SSSE3_AVAILABLE)
487
7
    if (HasSSSE3())
488
7
        return SIMON128_Dec_AdvancedProcessBlocks_SSSE3(m_rkeys, (size_t)m_rounds,
489
7
            inBlocks, xorBlocks, outBlocks, length, flags);
490
0
#endif
491
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
492
    if (HasNEON())
493
        return SIMON128_Dec_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
494
            inBlocks, xorBlocks, outBlocks, length, flags);
495
#endif
496
#if (CRYPTOPP_ALTIVEC_AVAILABLE)
497
    if (HasAltivec())
498
        return SIMON128_Dec_AdvancedProcessBlocks_ALTIVEC(m_rkeys, (size_t)m_rounds,
499
            inBlocks, xorBlocks, outBlocks, length, flags);
500
#endif
501
0
    return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
502
7
}
503
#endif  // CRYPTOPP_SIMON128_ADVANCED_PROCESS_BLOCKS
504
505
NAMESPACE_END