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 ¶ms) |
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 ¶ms) |
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 |