Crypto++  8.2
Free C++ class library of cryptographic schemes
chacha.cpp
1 // chacha.cpp - written and placed in the public domain by Jeffrey Walton.
2 // Based on Wei Dai's Salsa20, Botan's SSE2 implementation,
3 // and Bernstein's reference ChaCha family implementation at
4 // http://cr.yp.to/chacha.html.
5 
6 #include "pch.h"
7 #include "config.h"
8 #include "chacha.h"
9 #include "argnames.h"
10 #include "misc.h"
11 #include "cpu.h"
12 
13 // Internal compiler error in GCC 3.3 and below
14 #if defined(__GNUC__) && (__GNUC__ < 4)
15 # undef CRYPTOPP_SSE2_INTRIN_AVAILABLE
16 #endif
17 
18 NAMESPACE_BEGIN(CryptoPP)
19 
20 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
21 extern void ChaCha_OperateKeystream_NEON(const word32 *state, const byte* input, byte *output, unsigned int rounds);
22 #endif
23 
24 #if (CRYPTOPP_AVX2_AVAILABLE)
25 extern void ChaCha_OperateKeystream_AVX2(const word32 *state, const byte* input, byte *output, unsigned int rounds);
26 #endif
27 #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
28 extern void ChaCha_OperateKeystream_SSE2(const word32 *state, const byte* input, byte *output, unsigned int rounds);
29 #endif
30 
31 #if (CRYPTOPP_POWER8_AVAILABLE)
32 extern void ChaCha_OperateKeystream_POWER8(const word32 *state, const byte* input, byte *output, unsigned int rounds);
33 #elif (CRYPTOPP_ALTIVEC_AVAILABLE)
34 extern void ChaCha_OperateKeystream_ALTIVEC(const word32 *state, const byte* input, byte *output, unsigned int rounds);
35 #endif
36 
37 #if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
38 void ChaCha_TestInstantiations()
39 {
43 }
44 #endif
45 
46 NAMESPACE_END // CryptoPP
47 
48 ////////////////////////////// ChaCha Core //////////////////////////////
49 
50 #define CHACHA_QUARTER_ROUND(a,b,c,d) \
51  a += b; d ^= a; d = rotlConstant<16,word32>(d); \
52  c += d; b ^= c; b = rotlConstant<12,word32>(b); \
53  a += b; d ^= a; d = rotlConstant<8,word32>(d); \
54  c += d; b ^= c; b = rotlConstant<7,word32>(b);
55 
56 #define CHACHA_OUTPUT(x){\
57  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, x0 + state[0]);\
58  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, x1 + state[1]);\
59  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, x2 + state[2]);\
60  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, x3 + state[3]);\
61  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 4, x4 + state[4]);\
62  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 5, x5 + state[5]);\
63  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 6, x6 + state[6]);\
64  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 7, x7 + state[7]);\
65  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 8, x8 + state[8]);\
66  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 9, x9 + state[9]);\
67  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 10, x10 + state[10]);\
68  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 11, x11 + state[11]);\
69  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 12, x12 + state[12]);\
70  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 13, x13 + state[13]);\
71  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 14, x14 + state[14]);\
72  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 15, x15 + state[15]);}
73 
74 ANONYMOUS_NAMESPACE_BEGIN
75 
76 // Hacks... Bring in all symbols, and supply
77 // the stuff the templates normally provide.
78 using namespace CryptoPP;
79 typedef word32 WordType;
80 enum {BYTES_PER_ITERATION=64};
81 
82 // MultiBlockSafe detects a condition that can arise in the SIMD
83 // implementations where we overflow one of the 32-bit state words during
84 // addition in an intermediate result. Preconditions for the issue include
85 // a user seeks to around 2^32 blocks (256 GB of data) for ChaCha; or a
86 // user specifies an arbitrarily large initial counter block for ChaChaTLS.
87 // Also see https://github.com/weidai11/cryptopp/issues/732.
88 inline bool MultiBlockSafe(unsigned int ctrLow, unsigned int blocks)
89 {
90  return 0xffffffff - ctrLow > blocks;
91 }
92 
93 // OperateKeystream always produces a key stream. The key stream is written
94 // to output. Optionally a message may be supplied to xor with the key stream.
95 // The message is input, and output = output ^ input.
96 void ChaCha_OperateKeystream(KeystreamOperation operation,
97  word32 state[16], word32& ctrLow, word32& ctrHigh, word32 rounds,
98  byte *output, const byte *input, size_t iterationCount)
99 {
100  do
101  {
102 #if (CRYPTOPP_AVX2_AVAILABLE)
103  if (HasAVX2())
104  {
105  while (iterationCount >= 8 && MultiBlockSafe(state[12], 8))
106  {
107  const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
108  ChaCha_OperateKeystream_AVX2(state, xorInput ? input : NULLPTR, output, rounds);
109 
110  // MultiBlockSafe avoids overflow on the counter words
111  state[12] += 8;
112 
113  input += (!!xorInput) * 8 * BYTES_PER_ITERATION;
114  output += 8 * BYTES_PER_ITERATION;
115  iterationCount -= 8;
116  }
117  }
118 #endif
119 
120 #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
121  if (HasSSE2())
122  {
123  while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
124  {
125  const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
126  ChaCha_OperateKeystream_SSE2(state, xorInput ? input : NULLPTR, output, rounds);
127 
128  // MultiBlockSafe avoids overflow on the counter words
129  state[12] += 4;
130 
131  input += (!!xorInput)*4*BYTES_PER_ITERATION;
132  output += 4*BYTES_PER_ITERATION;
133  iterationCount -= 4;
134  }
135  }
136 #endif
137 
138 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
139  if (HasNEON())
140  {
141  while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
142  {
143  const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
144  ChaCha_OperateKeystream_NEON(state, xorInput ? input : NULLPTR, output, rounds);
145 
146  // MultiBlockSafe avoids overflow on the counter words
147  state[12] += 4;
148 
149  input += (!!xorInput)*4*BYTES_PER_ITERATION;
150  output += 4*BYTES_PER_ITERATION;
151  iterationCount -= 4;
152  }
153  }
154 #endif
155 
156 #if (CRYPTOPP_POWER8_AVAILABLE)
157  if (HasPower8())
158  {
159  while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
160  {
161  const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
162  ChaCha_OperateKeystream_POWER8(state, xorInput ? input : NULLPTR, output, rounds);
163 
164  // MultiBlockSafe avoids overflow on the counter words
165  state[12] += 4;
166 
167  input += (!!xorInput)*4*BYTES_PER_ITERATION;
168  output += 4*BYTES_PER_ITERATION;
169  iterationCount -= 4;
170  }
171  }
172 #elif (CRYPTOPP_ALTIVEC_AVAILABLE)
173  if (HasAltivec())
174  {
175  while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
176  {
177  const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
178  ChaCha_OperateKeystream_ALTIVEC(state, xorInput ? input : NULLPTR, output, rounds);
179 
180  // MultiBlockSafe avoids overflow on the counter words
181  state[12] += 4;
182 
183  input += (!!xorInput)*4*BYTES_PER_ITERATION;
184  output += 4*BYTES_PER_ITERATION;
185  iterationCount -= 4;
186  }
187  }
188 #endif
189 
190  if (iterationCount)
191  {
192  word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
193 
194  x0 = state[0]; x1 = state[1]; x2 = state[2]; x3 = state[3];
195  x4 = state[4]; x5 = state[5]; x6 = state[6]; x7 = state[7];
196  x8 = state[8]; x9 = state[9]; x10 = state[10]; x11 = state[11];
197  x12 = state[12]; x13 = state[13]; x14 = state[14]; x15 = state[15];
198 
199  for (int i = static_cast<int>(rounds); i > 0; i -= 2)
200  {
201  CHACHA_QUARTER_ROUND(x0, x4, x8, x12);
202  CHACHA_QUARTER_ROUND(x1, x5, x9, x13);
203  CHACHA_QUARTER_ROUND(x2, x6, x10, x14);
204  CHACHA_QUARTER_ROUND(x3, x7, x11, x15);
205 
206  CHACHA_QUARTER_ROUND(x0, x5, x10, x15);
207  CHACHA_QUARTER_ROUND(x1, x6, x11, x12);
208  CHACHA_QUARTER_ROUND(x2, x7, x8, x13);
209  CHACHA_QUARTER_ROUND(x3, x4, x9, x14);
210  }
211 
212  CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(CHACHA_OUTPUT, BYTES_PER_ITERATION);
213 
214  // This is state[12] and state[13] from ChaCha. In the case of
215  // ChaChaTLS ctrHigh is a reference to a discard value.
216  if (++ctrLow == 0)
217  ctrHigh++;
218  }
219 
220  // We may re-enter a SIMD keystream operation from here.
221  } while (iterationCount--);
222 }
223 
224 // XChaCha key derivation
225 void HChaCha_OperateKeystream(const word32 state[16], word32 output[8])
226 {
227  word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
228 
229  x0 = state[0]; x1 = state[1]; x2 = state[2]; x3 = state[3];
230  x4 = state[4]; x5 = state[5]; x6 = state[6]; x7 = state[7];
231  x8 = state[8]; x9 = state[9]; x10 = state[10]; x11 = state[11];
232  x12 = state[12]; x13 = state[13]; x14 = state[14]; x15 = state[15];
233 
234  for (int i = 20; i > 0; i -= 2)
235  {
236  CHACHA_QUARTER_ROUND(x0, x4, x8, x12);
237  CHACHA_QUARTER_ROUND(x1, x5, x9, x13);
238  CHACHA_QUARTER_ROUND(x2, x6, x10, x14);
239  CHACHA_QUARTER_ROUND(x3, x7, x11, x15);
240 
241  CHACHA_QUARTER_ROUND(x0, x5, x10, x15);
242  CHACHA_QUARTER_ROUND(x1, x6, x11, x12);
243  CHACHA_QUARTER_ROUND(x2, x7, x8, x13);
244  CHACHA_QUARTER_ROUND(x3, x4, x9, x14);
245  }
246 
247  output[0] = x0; output[1] = x1;
248  output[2] = x2; output[3] = x3;
249  output[4] = x12; output[5] = x13;
250  output[6] = x14; output[7] = x15;
251 }
252 
253 std::string ChaCha_AlgorithmProvider()
254 {
255 #if (CRYPTOPP_AVX2_AVAILABLE)
256  if (HasAVX2())
257  return "AVX2";
258  else
259 #endif
260 #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
261  if (HasSSE2())
262  return "SSE2";
263  else
264 #endif
265 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
266  if (HasNEON())
267  return "NEON";
268  else
269 #endif
270 #if (CRYPTOPP_POWER8_AVAILABLE)
271  if (HasPower8())
272  return "Power8";
273  else
274 #elif (CRYPTOPP_ALTIVEC_AVAILABLE)
275  if (HasAltivec())
276  return "Altivec";
277  else
278 #endif
279  return "C++";
280 }
281 
282 unsigned int ChaCha_GetAlignment()
283 {
284 #if (CRYPTOPP_AVX2_AVAILABLE)
285  if (HasAVX2())
286  return 16;
287  else
288 #endif
289 #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
290  if (HasSSE2())
291  return 16;
292  else
293 #endif
294 #if (CRYPTOPP_ALTIVEC_AVAILABLE)
295  if (HasAltivec())
296  return 16;
297  else
298 #endif
299  return GetAlignmentOf<word32>();
300 }
301 
302 unsigned int ChaCha_GetOptimalBlockSize()
303 {
304 #if (CRYPTOPP_AVX2_AVAILABLE)
305  if (HasAVX2())
306  return 8 * BYTES_PER_ITERATION;
307  else
308 #endif
309 #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
310  if (HasSSE2())
311  return 4*BYTES_PER_ITERATION;
312  else
313 #endif
314 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
315  if (HasNEON())
316  return 4*BYTES_PER_ITERATION;
317  else
318 #endif
319 #if (CRYPTOPP_ALTIVEC_AVAILABLE)
320  if (HasAltivec())
321  return 4*BYTES_PER_ITERATION;
322  else
323 #endif
324  return BYTES_PER_ITERATION;
325 }
326 
327 ANONYMOUS_NAMESPACE_END
328 
329 NAMESPACE_BEGIN(CryptoPP)
330 
331 ////////////////////////////// Bernstein ChaCha //////////////////////////////
332 
333 std::string ChaCha_Policy::AlgorithmName() const
334 {
335  return std::string("ChaCha")+IntToString(m_rounds);
336 }
337 
338 std::string ChaCha_Policy::AlgorithmProvider() const
339 {
340  return ChaCha_AlgorithmProvider();
341 }
342 
343 void ChaCha_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
344 {
345  CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 16 || length == 32);
346  CRYPTOPP_UNUSED(key); CRYPTOPP_UNUSED(length);
347 
348  // Use previous rounds as the default value
349  int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
350  if (rounds != 20 && rounds != 12 && rounds != 8)
352 
353  // Latch a good value
354  m_rounds = rounds;
355 
356  // "expand 16-byte k" or "expand 32-byte k"
357  m_state[0] = 0x61707865;
358  m_state[1] = (length == 16) ? 0x3120646e : 0x3320646e;
359  m_state[2] = (length == 16) ? 0x79622d36 : 0x79622d32;
360  m_state[3] = 0x6b206574;
361 
363  get1(m_state[4])(m_state[5])(m_state[6])(m_state[7]);
364 
365  GetBlock<word32, LittleEndian> get2(key + ((length == 32) ? 16 : 0));
366  get2(m_state[8])(m_state[9])(m_state[10])(m_state[11]);
367 }
368 
369 void ChaCha_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
370 {
371  CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
372  CRYPTOPP_ASSERT(length==8); CRYPTOPP_UNUSED(length);
373 
375  m_state[12] = m_state[13] = 0;
376  get(m_state[14])(m_state[15]);
377 }
378 
379 void ChaCha_Policy::SeekToIteration(lword iterationCount)
380 {
381  m_state[12] = (word32)iterationCount; // low word
382  m_state[13] = (word32)SafeRightShift<32>(iterationCount);
383 }
384 
385 unsigned int ChaCha_Policy::GetAlignment() const
386 {
387  return ChaCha_GetAlignment();
388 }
389 
390 unsigned int ChaCha_Policy::GetOptimalBlockSize() const
391 {
392  return ChaCha_GetOptimalBlockSize();
393 }
394 
395 void ChaCha_Policy::OperateKeystream(KeystreamOperation operation,
396  byte *output, const byte *input, size_t iterationCount)
397 {
398  ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
399  m_rounds, output, input, iterationCount);
400 }
401 
402 ////////////////////////////// IETF ChaChaTLS //////////////////////////////
403 
404 std::string ChaChaTLS_Policy::AlgorithmName() const
405 {
406  return std::string("ChaChaTLS");
407 }
408 
409 std::string ChaChaTLS_Policy::AlgorithmProvider() const
410 {
411  return ChaCha_AlgorithmProvider();
412 }
413 
414 void ChaChaTLS_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
415 {
416  CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32);
417  CRYPTOPP_UNUSED(length);
418 
419  // ChaChaTLS is always 20 rounds. Fetch Rounds() to avoid a spurious failure.
420  int rounds = params.GetIntValueWithDefault(Name::Rounds(), ROUNDS);
421  if (rounds != 20)
423 
424  // RFC 8439 test vectors use an initial block counter. However, the counter
425  // can be an arbitrary value per RFC 8439 Section 2.4. We stash the counter
426  // away in state[16] and use it for a Resynchronize() operation. I think
427  // the initial counter is used more like a Tweak when non-0, and it should
428  // be provided in Resynchronize() (light-weight re-keying). However,
429  // Resynchronize() does not have an overload that allows us to pass it into
430  // the function, so we have to use the heavier-weight SetKey to change it.
431  word64 block;
432  if (params.GetValue("InitialBlock", block))
433  m_counter = static_cast<word32>(block);
434  else
435  m_counter = 0;
436 
437  // State words are defined in RFC 8439, Section 2.3. Key is 32-bytes.
439  get(m_state[KEY+0])(m_state[KEY+1])(m_state[KEY+2])(m_state[KEY+3])
440  (m_state[KEY+4])(m_state[KEY+5])(m_state[KEY+6])(m_state[KEY+7]);
441 }
442 
443 void ChaChaTLS_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
444 {
445  CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
446  CRYPTOPP_ASSERT(length==12);
447 
448  // State words are defined in RFC 8439, Section 2.3.
449  m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
450  m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
451 
452  // Copy saved key into state
453  std::memcpy(m_state+4, m_state+KEY, 8*sizeof(word32));
454 
455  // State words are defined in RFC 8439, Section 2.3
457  m_state[12] = m_counter;
458  get(m_state[13])(m_state[14])(m_state[15]);
459 }
460 
461 void ChaChaTLS_Policy::SeekToIteration(lword iterationCount)
462 {
463  // Should we throw here??? If the initial block counter is
464  // large then we can wrap and process more data as long as
465  // data processed in the security context does not exceed
466  // 2^32 blocks or approximately 256 GB of data.
467  CRYPTOPP_ASSERT(iterationCount <= std::numeric_limits<word32>::max());
468  m_state[12] = (word32)iterationCount; // low word
469 }
470 
471 unsigned int ChaChaTLS_Policy::GetAlignment() const
472 {
473  return ChaCha_GetAlignment();
474 }
475 
476 unsigned int ChaChaTLS_Policy::GetOptimalBlockSize() const
477 {
478  return ChaCha_GetOptimalBlockSize();
479 }
480 
481 void ChaChaTLS_Policy::OperateKeystream(KeystreamOperation operation,
482  byte *output, const byte *input, size_t iterationCount)
483 {
484  word32 discard=0;
485  ChaCha_OperateKeystream(operation, m_state, m_state[12], discard,
486  ROUNDS, output, input, iterationCount);
487 
488  // If this fires it means ChaCha_OperateKeystream generated a counter
489  // block carry that was discarded. The problem is, the RFC does not
490  // specify what should happen when the counter block wraps. All we can
491  // do is inform the user that something bad may happen because we don't
492  // know what we should do.
493  // Also see https://github.com/weidai11/cryptopp/issues/790 and
494  // https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU
495  // CRYPTOPP_ASSERT(discard==0);
496 }
497 
498 ////////////////////////////// IETF XChaCha20 //////////////////////////////
499 
500 std::string XChaCha20_Policy::AlgorithmName() const
501 {
502  return std::string("XChaCha20");
503 }
504 
505 std::string XChaCha20_Policy::AlgorithmProvider() const
506 {
507  return ChaCha_AlgorithmProvider();
508 }
509 
510 void XChaCha20_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
511 {
512  CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32);
513  CRYPTOPP_UNUSED(length);
514 
515  // Use previous rounds as the default value
516  int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
517  if (rounds != 20 && rounds != 12)
519 
520  // Latch a good value
521  m_rounds = rounds;
522 
523  word64 block;
524  if (params.GetValue("InitialBlock", block))
525  m_counter = static_cast<word32>(block);
526  else
527  m_counter = 1;
528 
529  // Stash key away for use in CipherResynchronize
531  get(m_state[KEY+0])(m_state[KEY+1])(m_state[KEY+2])(m_state[KEY+3])
532  (m_state[KEY+4])(m_state[KEY+5])(m_state[KEY+6])(m_state[KEY+7]);
533 }
534 
535 void XChaCha20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
536 {
537  CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
538  CRYPTOPP_ASSERT(length==24);
539 
540  // HChaCha derivation
541  m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
542  m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
543 
544  // Copy saved key into state
545  std::memcpy(m_state+4, m_state+KEY, 8*sizeof(word32));
546 
548  get(m_state[12])(m_state[13])(m_state[14])(m_state[15]);
549 
550  // Operate the keystream without adding state back in.
551  // This function also gathers the key words into a
552  // contiguous 8-word block.
553  HChaCha_OperateKeystream(m_state, m_state+4);
554 
555  // XChaCha state
556  m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
557  m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
558 
559  // Setup new IV
560  m_state[12] = m_counter;
561  m_state[13] = 0;
562  m_state[14] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, iv+16);
563  m_state[15] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, iv+20);
564 }
565 
566 void XChaCha20_Policy::SeekToIteration(lword iterationCount)
567 {
568  // Should we throw here??? XChaCha does not have a block
569  // counter, so I'm not sure how to seek on it.
570  CRYPTOPP_ASSERT(0); CRYPTOPP_UNUSED(iterationCount);
571 }
572 
573 unsigned int XChaCha20_Policy::GetAlignment() const
574 {
575  return ChaCha_GetAlignment();
576 }
577 
578 unsigned int XChaCha20_Policy::GetOptimalBlockSize() const
579 {
580  return ChaCha_GetOptimalBlockSize();
581 }
582 
583 void XChaCha20_Policy::OperateKeystream(KeystreamOperation operation,
584  byte *output, const byte *input, size_t iterationCount)
585 {
586  ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
587  m_rounds, output, input, iterationCount);
588 }
589 
590 NAMESPACE_END
static const char * StaticAlgorithmName()
The algorithm name.
Definition: chacha.h:50
int GetIntValueWithDefault(const char *name, int defaultValue) const
Get a named value with type int, with default.
Definition: cryptlib.h:395
Standard names for retrieving values by name when working with NameValuePairs.
static const char * StaticAlgorithmName()
The algorithm name.
Definition: chacha.h:107
bool HasAltivec()
Determine if a PowerPC processor has Altivec available.
Definition: cpu.h:614
Utility functions for the Crypto++ library.
const char * Rounds()
int
Definition: argnames.h:24
bool HasAVX2()
Determines AVX2 availability.
Definition: cpu.h:225
Library configuration file.
#define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y)
Helper macro to implement OperateKeystream.
Definition: strciphr.h:268
byte order is little-endian
Definition: cryptlib.h:145
Input buffer is NULL.
Definition: strciphr.h:82
Exception thrown when an invalid number of rounds is encountered.
Definition: simple.h:59
bool HasPower8()
Determine if a PowerPC processor has Power8 available.
Definition: cpu.h:640
Precompiled header file.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:69
Functions for CPU features and intrinsics.
const char * IV()
ConstByteArrayParameter, also accepts const byte * for backwards compatibility.
Definition: argnames.h:21
bool HasSSE2()
Determines SSE2 availability.
Definition: cpu.h:116
Access a block of memory.
Definition: misc.h:2454
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:636
KeystreamOperation
Keystream operation flags.
Definition: strciphr.h:88
Crypto++ library namespace.
bool GetValue(const char *name, T &value) const
Get a named value.
Definition: cryptlib.h:350
SymmetricCipher implementation.
Definition: strciphr.h:673
Classes for ChaCha8, ChaCha12 and ChaCha20 stream ciphers.
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