14 #if defined(__GNUC__) && (__GNUC__ < 4)
15 # undef CRYPTOPP_SSE2_INTRIN_AVAILABLE
20 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
21 extern void ChaCha_OperateKeystream_NEON(
const word32 *state,
const byte* input,
byte *output,
unsigned int rounds);
24 #if (CRYPTOPP_AVX2_AVAILABLE)
25 extern void ChaCha_OperateKeystream_AVX2(
const word32 *state,
const byte* input,
byte *output,
unsigned int rounds);
27 #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
28 extern void ChaCha_OperateKeystream_SSE2(
const word32 *state,
const byte* input,
byte *output,
unsigned int rounds);
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);
37 #if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
38 void ChaCha_TestInstantiations()
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);
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]);}
74 ANONYMOUS_NAMESPACE_BEGIN
79 typedef word32 WordType;
80 enum {BYTES_PER_ITERATION=64};
88 inline bool MultiBlockSafe(
unsigned int ctrLow,
unsigned int blocks)
90 return 0xffffffff - ctrLow > blocks;
97 word32 state[16], word32& ctrLow, word32& ctrHigh, word32 rounds,
98 byte *output,
const byte *input,
size_t iterationCount)
102 #if (CRYPTOPP_AVX2_AVAILABLE)
105 while (iterationCount >= 8 && MultiBlockSafe(state[12], 8))
108 ChaCha_OperateKeystream_AVX2(state, xorInput ? input : NULLPTR, output, rounds);
113 input += (!!xorInput) * 8 * BYTES_PER_ITERATION;
114 output += 8 * BYTES_PER_ITERATION;
120 #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
123 while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
126 ChaCha_OperateKeystream_SSE2(state, xorInput ? input : NULLPTR, output, rounds);
131 input += (!!xorInput)*4*BYTES_PER_ITERATION;
132 output += 4*BYTES_PER_ITERATION;
138 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
141 while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
144 ChaCha_OperateKeystream_NEON(state, xorInput ? input : NULLPTR, output, rounds);
149 input += (!!xorInput)*4*BYTES_PER_ITERATION;
150 output += 4*BYTES_PER_ITERATION;
156 #if (CRYPTOPP_POWER8_AVAILABLE)
159 while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
162 ChaCha_OperateKeystream_POWER8(state, xorInput ? input : NULLPTR, output, rounds);
167 input += (!!xorInput)*4*BYTES_PER_ITERATION;
168 output += 4*BYTES_PER_ITERATION;
172 #elif (CRYPTOPP_ALTIVEC_AVAILABLE)
175 while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
178 ChaCha_OperateKeystream_ALTIVEC(state, xorInput ? input : NULLPTR, output, rounds);
183 input += (!!xorInput)*4*BYTES_PER_ITERATION;
184 output += 4*BYTES_PER_ITERATION;
192 word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
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];
199 for (
int i =
static_cast<int>(rounds); i > 0; i -= 2)
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);
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);
221 }
while (iterationCount--);
225 void HChaCha_OperateKeystream(
const word32 state[16], word32 output[8])
227 word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
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];
234 for (
int i = 20; i > 0; i -= 2)
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);
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);
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;
253 std::string ChaCha_AlgorithmProvider()
255 #if (CRYPTOPP_AVX2_AVAILABLE)
260 #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
265 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
270 #if (CRYPTOPP_POWER8_AVAILABLE)
274 #elif (CRYPTOPP_ALTIVEC_AVAILABLE)
282 unsigned int ChaCha_GetAlignment()
284 #if (CRYPTOPP_AVX2_AVAILABLE)
289 #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
294 #if (CRYPTOPP_ALTIVEC_AVAILABLE)
299 return GetAlignmentOf<word32>();
302 unsigned int ChaCha_GetOptimalBlockSize()
304 #if (CRYPTOPP_AVX2_AVAILABLE)
306 return 8 * BYTES_PER_ITERATION;
309 #if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
311 return 4*BYTES_PER_ITERATION;
314 #if (CRYPTOPP_ARM_NEON_AVAILABLE)
316 return 4*BYTES_PER_ITERATION;
319 #if (CRYPTOPP_ALTIVEC_AVAILABLE)
321 return 4*BYTES_PER_ITERATION;
324 return BYTES_PER_ITERATION;
327 ANONYMOUS_NAMESPACE_END
333 std::string ChaCha_Policy::AlgorithmName()
const
335 return std::string(
"ChaCha")+
IntToString(m_rounds);
338 std::string ChaCha_Policy::AlgorithmProvider()
const
340 return ChaCha_AlgorithmProvider();
343 void ChaCha_Policy::CipherSetKey(
const NameValuePairs ¶ms,
const byte *key,
size_t length)
346 CRYPTOPP_UNUSED(key); CRYPTOPP_UNUSED(length);
350 if (rounds != 20 && rounds != 12 && rounds != 8)
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;
363 get1(m_state[4])(m_state[5])(m_state[6])(m_state[7]);
366 get2(m_state[8])(m_state[9])(m_state[10])(m_state[11]);
369 void ChaCha_Policy::CipherResynchronize(
byte *keystreamBuffer,
const byte *IV,
size_t length)
371 CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
375 m_state[12] = m_state[13] = 0;
376 get(m_state[14])(m_state[15]);
379 void ChaCha_Policy::SeekToIteration(lword iterationCount)
381 m_state[12] = (word32)iterationCount;
382 m_state[13] = (word32)SafeRightShift<32>(iterationCount);
385 unsigned int ChaCha_Policy::GetAlignment()
const
387 return ChaCha_GetAlignment();
390 unsigned int ChaCha_Policy::GetOptimalBlockSize()
const
392 return ChaCha_GetOptimalBlockSize();
396 byte *output,
const byte *input,
size_t iterationCount)
398 ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
399 m_rounds, output, input, iterationCount);
404 std::string ChaChaTLS_Policy::AlgorithmName()
const
406 return std::string(
"ChaChaTLS");
409 std::string ChaChaTLS_Policy::AlgorithmProvider()
const
411 return ChaCha_AlgorithmProvider();
414 void ChaChaTLS_Policy::CipherSetKey(
const NameValuePairs ¶ms,
const byte *key,
size_t length)
417 CRYPTOPP_UNUSED(length);
432 if (params.
GetValue(
"InitialBlock", block))
433 m_counter =
static_cast<word32
>(block);
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]);
443 void ChaChaTLS_Policy::CipherResynchronize(
byte *keystreamBuffer,
const byte *IV,
size_t length)
445 CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
449 m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
450 m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
453 std::memcpy(m_state+4, m_state+KEY, 8*
sizeof(word32));
457 m_state[12] = m_counter;
458 get(m_state[13])(m_state[14])(m_state[15]);
461 void ChaChaTLS_Policy::SeekToIteration(lword iterationCount)
468 m_state[12] = (word32)iterationCount;
471 unsigned int ChaChaTLS_Policy::GetAlignment()
const
473 return ChaCha_GetAlignment();
476 unsigned int ChaChaTLS_Policy::GetOptimalBlockSize()
const
478 return ChaCha_GetOptimalBlockSize();
482 byte *output,
const byte *input,
size_t iterationCount)
485 ChaCha_OperateKeystream(operation, m_state, m_state[12], discard,
486 ROUNDS, output, input, iterationCount);
500 std::string XChaCha20_Policy::AlgorithmName()
const
502 return std::string(
"XChaCha20");
505 std::string XChaCha20_Policy::AlgorithmProvider()
const
507 return ChaCha_AlgorithmProvider();
510 void XChaCha20_Policy::CipherSetKey(
const NameValuePairs ¶ms,
const byte *key,
size_t length)
513 CRYPTOPP_UNUSED(length);
517 if (rounds != 20 && rounds != 12)
524 if (params.
GetValue(
"InitialBlock", block))
525 m_counter =
static_cast<word32
>(block);
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]);
535 void XChaCha20_Policy::CipherResynchronize(
byte *keystreamBuffer,
const byte *iv,
size_t length)
537 CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
541 m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
542 m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
545 std::memcpy(m_state+4, m_state+KEY, 8*
sizeof(word32));
548 get(m_state[12])(m_state[13])(m_state[14])(m_state[15]);
553 HChaCha_OperateKeystream(m_state, m_state+4);
556 m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
557 m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
560 m_state[12] = m_counter;
566 void XChaCha20_Policy::SeekToIteration(lword iterationCount)
573 unsigned int XChaCha20_Policy::GetAlignment()
const
575 return ChaCha_GetAlignment();
578 unsigned int XChaCha20_Policy::GetOptimalBlockSize()
const
580 return ChaCha_GetOptimalBlockSize();
584 byte *output,
const byte *input,
size_t iterationCount)
586 ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
587 m_rounds, output, input, iterationCount);