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