Crypto++  8.2
Free C++ class library of cryptographic schemes
speck.cpp
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 #ifndef CRYPTOPP_INLINE
11 # if defined(CRYPTOPP_DEBUG)
12 # define CRYPTOPP_INLINE static
13 # else
14 # define CRYPTOPP_INLINE inline
15 # endif
16 #endif
17 
18 // Uncomment for benchmarking C++ against SSE or NEON.
19 // Do so in both speck.cpp and speck-simd.cpp.
20 // #undef CRYPTOPP_SSSE3_AVAILABLE
21 // #undef CRYPTOPP_SSE41_AVAILABLE
22 // #undef CRYPTOPP_ARM_NEON_AVAILABLE
23 
24 ANONYMOUS_NAMESPACE_BEGIN
25 
26 using CryptoPP::word32;
27 using CryptoPP::word64;
30 
31 /// \brief Forward round transformation
32 /// \tparam W word type
33 /// \details TF83() is the forward round transformation using a=8 and b=3 rotations.
34 /// The initial test implementation provided template parameters, but they were
35 /// removed because SPECK32 using a=7 and b=2 was not on the road map. The
36 /// additional template parameters also made calling SPECK_Encrypt and SPECK_Decrypt
37 /// kind of messy.
38 template <class W>
39 CRYPTOPP_INLINE void TF83(W& x, W& y, const W k)
40 {
41  x = rotrConstant<8>(x);
42  x += y; x ^= k;
43  y = rotlConstant<3>(y);
44  y ^= x;
45 }
46 
47 /// \brief Reverse round transformation
48 /// \tparam W word type
49 /// \details TR83() is the reverse round transformation using a=8 and b=3 rotations.
50 /// The initial test implementation provided template parameters, but they were
51 /// removed because SPECK32 using a=7 and b=2 was not on the road map. The
52 /// additional template parameters also made calling SPECK_Encrypt and SPECK_Decrypt
53 /// kind of messy.
54 template <class W>
55 CRYPTOPP_INLINE void TR83(W& x, W& y, const W k)
56 {
57  y ^= x;
58  y = rotrConstant<3>(y);
59  x ^= k; x -= y;
60  x = rotlConstant<8>(x);
61 }
62 
63 /// \brief Forward transformation
64 /// \tparam W word type
65 /// \tparam R number of rounds
66 /// \param c output array
67 /// \param p input array
68 /// \param k subkey array
69 template <class W, unsigned int R>
70 CRYPTOPP_INLINE void SPECK_Encrypt(W c[2], const W p[2], const W k[R])
71 {
72  c[0]=p[0]; c[1]=p[1];
73 
74  // Don't unroll this loop. Things slow down.
75  for (int i = 0; i < static_cast<int>(R); ++i)
76  TF83(c[0], c[1], k[i]);
77 }
78 
79 /// \brief Reverse transformation
80 /// \tparam W word type
81 /// \tparam R number of rounds
82 /// \param p output array
83 /// \param c input array
84 /// \param k subkey array
85 template <class W, unsigned int R>
86 CRYPTOPP_INLINE void SPECK_Decrypt(W p[2], const W c[2], const W k[R])
87 {
88  p[0]=c[0]; p[1]=c[1];
89 
90  // Don't unroll this loop. Things slow down.
91  for (int i = static_cast<int>(R-1); i >= 0; --i)
92  TR83(p[0], p[1], k[i]);
93 }
94 
95 /// \brief Subkey generation function
96 /// \details Used when the user key consists of 2 words
97 /// \tparam W word type
98 /// \tparam R number of rounds
99 /// \param key empty subkey array
100 /// \param k user key array
101 template <class W, unsigned int R>
102 CRYPTOPP_INLINE void SPECK_ExpandKey_2W(W key[R], const W k[2])
103 {
104  CRYPTOPP_ASSERT(R==32);
105  W i=0, B=k[0], A=k[1];
106 
107  while (i<R-1)
108  {
109  key[i]=A; TF83(B, A, i);
110  i++;
111  }
112  key[R-1]=A;
113 }
114 
115 /// \brief Subkey generation function
116 /// \details Used when the user key consists of 3 words
117 /// \tparam W word type
118 /// \tparam R number of rounds
119 /// \param key empty subkey array
120 /// \param k user key array
121 template <class W, unsigned int R>
122 CRYPTOPP_INLINE void SPECK_ExpandKey_3W(W key[R], const W k[3])
123 {
124  CRYPTOPP_ASSERT(R==33 || R==26);
125  W i=0, C=k[0], B=k[1], A=k[2];
126 
127  unsigned int blocks = R/2;
128  while (blocks--)
129  {
130  key[i+0]=A; TF83(B, A, i+0);
131  key[i+1]=A; TF83(C, A, i+1);
132  i+=2;
133  }
134 
135  // The constexpr residue should allow the optimizer to remove unneeded statements
136  if(R%2 == 1)
137  {
138  key[R-1]=A;
139  }
140 }
141 
142 /// \brief Subkey generation function
143 /// \details Used when the user key consists of 4 words
144 /// \tparam W word type
145 /// \tparam R number of rounds
146 /// \param key empty subkey array
147 /// \param k user key array
148 template <class W, unsigned int R>
149 CRYPTOPP_INLINE void SPECK_ExpandKey_4W(W key[R], const W k[4])
150 {
151  CRYPTOPP_ASSERT(R==34 || R==27);
152  W i=0, D=k[0], C=k[1], B=k[2], A=k[3];
153 
154  unsigned int blocks = R/3;
155  while (blocks--)
156  {
157  key[i+0]=A; TF83(B, A, i+0);
158  key[i+1]=A; TF83(C, A, i+1);
159  key[i+2]=A; TF83(D, A, i+2);
160  i+=3;
161  }
162 
163  // The constexpr residue should allow the optimizer to remove unneeded statements
164  if(R%3 == 1)
165  {
166  key[R-1]=A;
167  }
168  else if(R%3 == 2)
169  {
170  key[R-2]=A; TF83(B, A, W(R-2));
171  key[R-1]=A;
172  }
173 }
174 
175 ANONYMOUS_NAMESPACE_END
176 
177 ///////////////////////////////////////////////////////////
178 
179 NAMESPACE_BEGIN(CryptoPP)
180 
181 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
182 extern size_t SPECK64_Enc_AdvancedProcessBlocks_NEON(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_NEON(const word32* subKeys, size_t rounds,
186  const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
187 
188 extern size_t SPECK128_Enc_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds,
189  const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
190 
191 extern size_t SPECK128_Dec_AdvancedProcessBlocks_NEON(const word64* subKeys, size_t rounds,
192  const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
193 #endif
194 
195 #if defined(CRYPTOPP_SSE41_AVAILABLE)
196 extern size_t SPECK64_Enc_AdvancedProcessBlocks_SSE41(const word32* subKeys, size_t rounds,
197  const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
198 
199 extern size_t SPECK64_Dec_AdvancedProcessBlocks_SSE41(const word32* subKeys, size_t rounds,
200  const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
201 #endif
202 
203 #if defined(CRYPTOPP_SSSE3_AVAILABLE)
204 extern size_t SPECK128_Enc_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds,
205  const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
206 
207 extern size_t SPECK128_Dec_AdvancedProcessBlocks_SSSE3(const word64* subKeys, size_t rounds,
208  const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
209 #endif
210 
211 #if defined(CRYPTOPP_ALTIVEC_AVAILABLE)
212 extern size_t SPECK64_Enc_AdvancedProcessBlocks_ALTIVEC(const word32* subKeys, size_t rounds,
213  const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
214 
215 extern size_t SPECK64_Dec_AdvancedProcessBlocks_ALTIVEC(const word32* subKeys, size_t rounds,
216  const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
217 #endif
218 
219 #if defined(CRYPTOPP_POWER8_AVAILABLE)
220 extern size_t SPECK128_Enc_AdvancedProcessBlocks_POWER8(const word64* subKeys, size_t rounds,
221  const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
222 
223 extern size_t SPECK128_Dec_AdvancedProcessBlocks_POWER8(const word64* subKeys, size_t rounds,
224  const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags);
225 #endif
226 
227 std::string SPECK64::Base::AlgorithmProvider() const
228 {
229 #if (CRYPTOPP_SPECK64_ADVANCED_PROCESS_BLOCKS)
230 # if (CRYPTOPP_SSE41_AVAILABLE)
231  if (HasSSE41())
232  return "SSE4.1";
233 # endif
234 # if (CRYPTOPP_ARM_NEON_AVAILABLE)
235  if (HasNEON())
236  return "NEON";
237 # endif
238 # if (CRYPTOPP_POWER8_AVAILABLE)
239  if (HasPower8())
240  return "Power8";
241 # endif
242 # if (CRYPTOPP_ALTIVEC_AVAILABLE)
243  if (HasAltivec())
244  return "Altivec";
245 # endif
246 #endif
247  return "C++";
248 }
249 
250 void SPECK64::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
251 {
252  CRYPTOPP_ASSERT(keyLength == 12 || keyLength == 16);
253  CRYPTOPP_UNUSED(params);
254 
255  // Building the key schedule table requires {3,4} words workspace.
256  // Encrypting and decrypting requires 4 words workspace.
257  m_kwords = keyLength/sizeof(word32);
258  m_wspace.New(4U);
259 
260  // Do the endian gyrations from the paper and align pointers
261  typedef GetBlock<word32, LittleEndian> KeyBlock;
262  KeyBlock kblk(userKey);
263 
264  switch (m_kwords)
265  {
266  case 3:
267  m_rkeys.New((m_rounds = 26));
268  kblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
269  SPECK_ExpandKey_3W<word32, 26>(m_rkeys, m_wspace);
270  break;
271  case 4:
272  m_rkeys.New((m_rounds = 27));
273  kblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
274  SPECK_ExpandKey_4W<word32, 27>(m_rkeys, m_wspace);
275  break;
276  default:
277  CRYPTOPP_ASSERT(0);;
278  }
279 
280  // Altivec loads the current subkey as a 16-byte vector
281  // The extra elements ensure memory backs the last subkey.
282 #if CRYPTOPP_ALTIVEC_AVAILABLE
283  m_rkeys.Grow(m_rkeys.size()+4);
284 #endif
285 }
286 
287 void SPECK64::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
288 {
289  // Do the endian gyrations from the paper and align pointers
290  typedef GetBlock<word32, LittleEndian> InBlock;
291  InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
292 
293  switch (m_rounds)
294  {
295  case 26:
296  SPECK_Encrypt<word32, 26>(m_wspace+2, m_wspace+0, m_rkeys);
297  break;
298  case 27:
299  SPECK_Encrypt<word32, 27>(m_wspace+2, m_wspace+0, m_rkeys);
300  break;
301  default:
302  CRYPTOPP_ASSERT(0);;
303  }
304 
305  // Do the endian gyrations from the paper and align pointers
306  typedef PutBlock<word32, LittleEndian> OutBlock;
307  OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
308 }
309 
310 void SPECK64::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
311 {
312  // Do the endian gyrations from the paper and align pointers
313  typedef GetBlock<word32, LittleEndian> InBlock;
314  InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
315 
316  switch (m_rounds)
317  {
318  case 26:
319  SPECK_Decrypt<word32, 26>(m_wspace+2, m_wspace+0, m_rkeys);
320  break;
321  case 27:
322  SPECK_Decrypt<word32, 27>(m_wspace+2, m_wspace+0, m_rkeys);
323  break;
324  default:
325  CRYPTOPP_ASSERT(0);;
326  }
327 
328  // Do the endian gyrations from the paper and align pointers
329  typedef PutBlock<word32, LittleEndian> OutBlock;
330  OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
331 }
332 
333 ///////////////////////////////////////////////////////////
334 
335 std::string SPECK128::Base::AlgorithmProvider() const
336 {
337 #if (CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS)
338 # if (CRYPTOPP_SSSE3_AVAILABLE)
339  if (HasSSSE3())
340  return "SSSE3";
341 # endif
342 # if (CRYPTOPP_ARM_NEON_AVAILABLE)
343  if (HasNEON())
344  return "NEON";
345 # endif
346 # if (CRYPTOPP_POWER8_AVAILABLE)
347  if (HasPower8())
348  return "Power8";
349 # endif
350 #endif
351  return "C++";
352 }
353 
354 void SPECK128::Base::UncheckedSetKey(const byte *userKey, unsigned int keyLength, const NameValuePairs &params)
355 {
356  CRYPTOPP_ASSERT(keyLength == 16 || keyLength == 24 || keyLength == 32);
357  CRYPTOPP_UNUSED(params);
358 
359  // Building the key schedule table requires {2,3,4} words workspace.
360  // Encrypting and decrypting requires 4 words workspace.
361  m_kwords = keyLength/sizeof(word64);
362  m_wspace.New(4U);
363 
364  // Do the endian gyrations from the paper and align pointers
365  typedef GetBlock<word64, LittleEndian> KeyBlock;
366  KeyBlock kblk(userKey);
367 
368  switch (m_kwords)
369  {
370  case 2:
371  m_rkeys.New((m_rounds = 32));
372  kblk(m_wspace[1])(m_wspace[0]);
373  SPECK_ExpandKey_2W<word64, 32>(m_rkeys, m_wspace);
374  break;
375  case 3:
376  m_rkeys.New((m_rounds = 33));
377  kblk(m_wspace[2])(m_wspace[1])(m_wspace[0]);
378  SPECK_ExpandKey_3W<word64, 33>(m_rkeys, m_wspace);
379  break;
380  case 4:
381  m_rkeys.New((m_rounds = 34));
382  kblk(m_wspace[3])(m_wspace[2])(m_wspace[1])(m_wspace[0]);
383  SPECK_ExpandKey_4W<word64, 34>(m_rkeys, m_wspace);
384  break;
385  default:
386  CRYPTOPP_ASSERT(0);;
387  }
388 }
389 
390 void SPECK128::Enc::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
391 {
392  // Do the endian gyrations from the paper and align pointers
393  typedef GetBlock<word64, LittleEndian> InBlock;
394  InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
395 
396  switch (m_rounds)
397  {
398  case 32:
399  SPECK_Encrypt<word64, 32>(m_wspace+2, m_wspace+0, m_rkeys);
400  break;
401  case 33:
402  SPECK_Encrypt<word64, 33>(m_wspace+2, m_wspace+0, m_rkeys);
403  break;
404  case 34:
405  SPECK_Encrypt<word64, 34>(m_wspace+2, m_wspace+0, m_rkeys);
406  break;
407  default:
408  CRYPTOPP_ASSERT(0);;
409  }
410 
411  // Do the endian gyrations from the paper and align pointers
412  typedef PutBlock<word64, LittleEndian> OutBlock;
413  OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
414 }
415 
416 void SPECK128::Dec::ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const
417 {
418  // Do the endian gyrations from the paper and align pointers
419  typedef GetBlock<word64, LittleEndian> InBlock;
420  InBlock iblk(inBlock); iblk(m_wspace[1])(m_wspace[0]);
421 
422  switch (m_rounds)
423  {
424  case 32:
425  SPECK_Decrypt<word64, 32>(m_wspace+2, m_wspace+0, m_rkeys);
426  break;
427  case 33:
428  SPECK_Decrypt<word64, 33>(m_wspace+2, m_wspace+0, m_rkeys);
429  break;
430  case 34:
431  SPECK_Decrypt<word64, 34>(m_wspace+2, m_wspace+0, m_rkeys);
432  break;
433  default:
434  CRYPTOPP_ASSERT(0);;
435  }
436 
437  // Do the endian gyrations from the paper and align pointers
438  typedef PutBlock<word64, LittleEndian> OutBlock;
439  OutBlock oblk(xorBlock, outBlock); oblk(m_wspace[3])(m_wspace[2]);
440 }
441 
442 #if defined(CRYPTOPP_SPECK64_ADVANCED_PROCESS_BLOCKS)
443 size_t SPECK64::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
444  byte *outBlocks, size_t length, word32 flags) const
445 {
446 #if defined(CRYPTOPP_SSE41_AVAILABLE)
447  if (HasSSE41())
448  return SPECK64_Enc_AdvancedProcessBlocks_SSE41(m_rkeys, (size_t)m_rounds,
449  inBlocks, xorBlocks, outBlocks, length, flags);
450 #endif
451 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
452  if (HasNEON())
453  return SPECK64_Enc_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
454  inBlocks, xorBlocks, outBlocks, length, flags);
455 #endif
456 #if (CRYPTOPP_ALTIVEC_AVAILABLE)
457  if (HasAltivec())
458  return SPECK64_Enc_AdvancedProcessBlocks_ALTIVEC(m_rkeys, (size_t)m_rounds,
459  inBlocks, xorBlocks, outBlocks, length, flags);
460 #endif
461  return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
462 }
463 
464 size_t SPECK64::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
465  byte *outBlocks, size_t length, word32 flags) const
466 {
467 #if defined(CRYPTOPP_SSE41_AVAILABLE)
468  if (HasSSE41())
469  return SPECK64_Dec_AdvancedProcessBlocks_SSE41(m_rkeys, (size_t)m_rounds,
470  inBlocks, xorBlocks, outBlocks, length, flags);
471 #endif
472 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
473  if (HasNEON())
474  return SPECK64_Dec_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
475  inBlocks, xorBlocks, outBlocks, length, flags);
476 #endif
477 #if (CRYPTOPP_ALTIVEC_AVAILABLE)
478  if (HasAltivec())
479  return SPECK64_Dec_AdvancedProcessBlocks_ALTIVEC(m_rkeys, (size_t)m_rounds,
480  inBlocks, xorBlocks, outBlocks, length, flags);
481 #endif
482  return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
483 }
484 #endif // CRYPTOPP_SPECK64_ADVANCED_PROCESS_BLOCKS
485 
486 #if defined(CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS)
487 size_t SPECK128::Enc::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
488  byte *outBlocks, size_t length, word32 flags) const
489 {
490 #if defined(CRYPTOPP_SSSE3_AVAILABLE)
491  if (HasSSSE3())
492  return SPECK128_Enc_AdvancedProcessBlocks_SSSE3(m_rkeys, (size_t)m_rounds,
493  inBlocks, xorBlocks, outBlocks, length, flags);
494 #endif
495 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
496  if (HasNEON())
497  return SPECK128_Enc_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
498  inBlocks, xorBlocks, outBlocks, length, flags);
499 #endif
500 #if (CRYPTOPP_POWER8_AVAILABLE)
501  if (HasPower8())
502  return SPECK128_Enc_AdvancedProcessBlocks_POWER8(m_rkeys, (size_t)m_rounds,
503  inBlocks, xorBlocks, outBlocks, length, flags);
504 #endif
505  return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
506 }
507 
508 size_t SPECK128::Dec::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks,
509  byte *outBlocks, size_t length, word32 flags) const
510 {
511 #if defined(CRYPTOPP_SSSE3_AVAILABLE)
512  if (HasSSSE3())
513  return SPECK128_Dec_AdvancedProcessBlocks_SSSE3(m_rkeys, (size_t)m_rounds,
514  inBlocks, xorBlocks, outBlocks, length, flags);
515 #endif
516 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
517  if (HasNEON())
518  return SPECK128_Dec_AdvancedProcessBlocks_NEON(m_rkeys, (size_t)m_rounds,
519  inBlocks, xorBlocks, outBlocks, length, flags);
520 #endif
521 #if (CRYPTOPP_POWER8_AVAILABLE)
522  if (HasPower8())
523  return SPECK128_Dec_AdvancedProcessBlocks_POWER8(m_rkeys, (size_t)m_rounds,
524  inBlocks, xorBlocks, outBlocks, length, flags);
525 #endif
526  return BlockTransformation::AdvancedProcessBlocks(inBlocks, xorBlocks, outBlocks, length, flags);
527 }
528 #endif // CRYPTOPP_SPECK128_ADVANCED_PROCESS_BLOCKS
529 
530 NAMESPACE_END
bool HasAltivec()
Determine if a PowerPC processor has Altivec available.
Definition: cpu.h:614
Utility functions for the Crypto++ library.
bool HasSSSE3()
Determines SSSE3 availability.
Definition: cpu.h:131
Library configuration file.
T rotlConstant(T x)
Performs a left rotate.
Definition: misc.h:1499
bool HasPower8()
Determine if a PowerPC processor has Power8 available.
Definition: cpu.h:640
virtual size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const
Encrypt and xor multiple blocks using additional flags.
Definition: cryptlib.cpp:141
Precompiled header file.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:69
Functions for CPU features and intrinsics.
Classes for the Speck block cipher.
T rotrConstant(T x)
Performs a right rotate.
Definition: misc.h:1525
Access a block of memory.
Definition: misc.h:2454
bool HasSSE41()
Determines SSE4.1 availability.
Definition: cpu.h:142
Access a block of memory.
Definition: misc.h:2495
Crypto++ library namespace.
bool HasNEON()
Determine if an ARM processor has Advanced SIMD available.
Definition: cpu.h:387
Interface for retrieving values given their names.
Definition: cryptlib.h:293