Coverage Report

Created: 2024-11-21 07:03

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