14#if defined(__GNUC__) && (__GNUC__ < 4)
15# undef CRYPTOPP_SSE2_INTRIN_AVAILABLE
20#if (CRYPTOPP_ARM_NEON_AVAILABLE)
21extern void ChaCha_OperateKeystream_NEON(
const word32 *state,
const byte* input,
byte *output,
unsigned int rounds);
24#if (CRYPTOPP_AVX2_AVAILABLE)
25extern void ChaCha_OperateKeystream_AVX2(
const word32 *state,
const byte* input,
byte *output,
unsigned int rounds);
27#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
28extern void ChaCha_OperateKeystream_SSE2(
const word32 *state,
const byte* input,
byte *output,
unsigned int rounds);
31#if (CRYPTOPP_ALTIVEC_AVAILABLE)
32extern void ChaCha_OperateKeystream_ALTIVEC(
const word32 *state,
const byte* input,
byte *output,
unsigned int rounds);
35#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
36void ChaCha_TestInstantiations()
48#define CHACHA_QUARTER_ROUND(a,b,c,d) \
49 a += b; d ^= a; d = rotlConstant<16,word32>(d); \
50 c += d; b ^= c; b = rotlConstant<12,word32>(b); \
51 a += b; d ^= a; d = rotlConstant<8,word32>(d); \
52 c += d; b ^= c; b = rotlConstant<7,word32>(b);
54#define CHACHA_OUTPUT(x){\
55 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, x0 + state[0]);\
56 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, x1 + state[1]);\
57 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, x2 + state[2]);\
58 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, x3 + state[3]);\
59 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 4, x4 + state[4]);\
60 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 5, x5 + state[5]);\
61 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 6, x6 + state[6]);\
62 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 7, x7 + state[7]);\
63 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 8, x8 + state[8]);\
64 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 9, x9 + state[9]);\
65 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 10, x10 + state[10]);\
66 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 11, x11 + state[11]);\
67 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 12, x12 + state[12]);\
68 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 13, x13 + state[13]);\
69 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 14, x14 + state[14]);\
70 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 15, x15 + state[15]);}
72ANONYMOUS_NAMESPACE_BEGIN
78enum {BYTES_PER_ITERATION=64};
86inline bool MultiBlockSafe(
unsigned int ctrLow,
unsigned int blocks)
88 return 0xffffffff - ctrLow > blocks;
96 byte *output,
const byte *input,
size_t iterationCount)
100#if (CRYPTOPP_AVX2_AVAILABLE)
103 while (iterationCount >= 8 && MultiBlockSafe(state[12], 8))
106 ChaCha_OperateKeystream_AVX2(state, xorInput ? input : NULLPTR, output, rounds);
111 input += (!!xorInput) * 8 * BYTES_PER_ITERATION;
112 output += 8 * BYTES_PER_ITERATION;
118#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
121 while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
124 ChaCha_OperateKeystream_SSE2(state, xorInput ? input : NULLPTR, output, rounds);
129 input += (!!xorInput)*4*BYTES_PER_ITERATION;
130 output += 4*BYTES_PER_ITERATION;
136#if (CRYPTOPP_ARM_NEON_AVAILABLE)
139 while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
142 ChaCha_OperateKeystream_NEON(state, xorInput ? input : NULLPTR, output, rounds);
147 input += (!!xorInput)*4*BYTES_PER_ITERATION;
148 output += 4*BYTES_PER_ITERATION;
154#if (CRYPTOPP_ALTIVEC_AVAILABLE)
157 while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
160 ChaCha_OperateKeystream_ALTIVEC(state, xorInput ? input : NULLPTR, output, rounds);
165 input += (!!xorInput)*4*BYTES_PER_ITERATION;
166 output += 4*BYTES_PER_ITERATION;
174 word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
176 x0 = state[0]; x1 = state[1]; x2 = state[2]; x3 = state[3];
177 x4 = state[4]; x5 = state[5]; x6 = state[6]; x7 = state[7];
178 x8 = state[8]; x9 = state[9]; x10 = state[10]; x11 = state[11];
179 x12 = state[12]; x13 = state[13]; x14 = state[14]; x15 = state[15];
181 for (
int i =
static_cast<int>(rounds); i > 0; i -= 2)
183 CHACHA_QUARTER_ROUND(x0, x4, x8, x12);
184 CHACHA_QUARTER_ROUND(x1, x5, x9, x13);
185 CHACHA_QUARTER_ROUND(x2, x6, x10, x14);
186 CHACHA_QUARTER_ROUND(x3, x7, x11, x15);
188 CHACHA_QUARTER_ROUND(x0, x5, x10, x15);
189 CHACHA_QUARTER_ROUND(x1, x6, x11, x12);
190 CHACHA_QUARTER_ROUND(x2, x7, x8, x13);
191 CHACHA_QUARTER_ROUND(x3, x4, x9, x14);
203 }
while (iterationCount--);
207void HChaCha_OperateKeystream(
const word32 state[16],
word32 output[8])
209 word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
211 x0 = state[0]; x1 = state[1]; x2 = state[2]; x3 = state[3];
212 x4 = state[4]; x5 = state[5]; x6 = state[6]; x7 = state[7];
213 x8 = state[8]; x9 = state[9]; x10 = state[10]; x11 = state[11];
214 x12 = state[12]; x13 = state[13]; x14 = state[14]; x15 = state[15];
216 for (
int i = 20; i > 0; i -= 2)
218 CHACHA_QUARTER_ROUND(x0, x4, x8, x12);
219 CHACHA_QUARTER_ROUND(x1, x5, x9, x13);
220 CHACHA_QUARTER_ROUND(x2, x6, x10, x14);
221 CHACHA_QUARTER_ROUND(x3, x7, x11, x15);
223 CHACHA_QUARTER_ROUND(x0, x5, x10, x15);
224 CHACHA_QUARTER_ROUND(x1, x6, x11, x12);
225 CHACHA_QUARTER_ROUND(x2, x7, x8, x13);
226 CHACHA_QUARTER_ROUND(x3, x4, x9, x14);
229 output[0] = x0; output[1] = x1;
230 output[2] = x2; output[3] = x3;
231 output[4] = x12; output[5] = x13;
232 output[6] = x14; output[7] = x15;
235std::string ChaCha_AlgorithmProvider()
237#if (CRYPTOPP_AVX2_AVAILABLE)
242#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
247#if (CRYPTOPP_ARM_NEON_AVAILABLE)
252#if (CRYPTOPP_ALTIVEC_AVAILABLE)
260unsigned int ChaCha_GetAlignment()
262#if (CRYPTOPP_AVX2_AVAILABLE)
267#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
272#if (CRYPTOPP_ALTIVEC_AVAILABLE)
280unsigned int ChaCha_GetOptimalBlockSize()
282#if (CRYPTOPP_AVX2_AVAILABLE)
284 return 8 * BYTES_PER_ITERATION;
287#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
289 return 4*BYTES_PER_ITERATION;
292#if (CRYPTOPP_ARM_NEON_AVAILABLE)
294 return 4*BYTES_PER_ITERATION;
297#if (CRYPTOPP_ALTIVEC_AVAILABLE)
299 return 4*BYTES_PER_ITERATION;
302 return BYTES_PER_ITERATION;
305ANONYMOUS_NAMESPACE_END
311std::string ChaCha_Policy::AlgorithmName()
const
313 return std::string(
"ChaCha")+
IntToString(m_rounds);
318 return ChaCha_AlgorithmProvider();
321void ChaCha_Policy::CipherSetKey(
const NameValuePairs ¶ms,
const byte *key,
size_t length)
324 CRYPTOPP_UNUSED(key); CRYPTOPP_UNUSED(length);
328 if (rounds != 20 && rounds != 12 && rounds != 8)
335 m_state[0] = 0x61707865;
336 m_state[1] = (length == 16) ? 0x3120646e : 0x3320646e;
337 m_state[2] = (length == 16) ? 0x79622d36 : 0x79622d32;
338 m_state[3] = 0x6b206574;
340 GetBlock<word32, LittleEndian> get1(key);
341 get1(m_state[4])(m_state[5])(m_state[6])(m_state[7]);
343 GetBlock<word32, LittleEndian> get2(key + ((length == 32) ? 16 : 0));
344 get2(m_state[8])(m_state[9])(m_state[10])(m_state[11]);
347void ChaCha_Policy::CipherResynchronize(
byte *keystreamBuffer,
const byte *IV,
size_t length)
349 CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
352 GetBlock<word32, LittleEndian> get(IV);
353 m_state[12] = m_state[13] = 0;
354 get(m_state[14])(m_state[15]);
357void ChaCha_Policy::SeekToIteration(
lword iterationCount)
359 m_state[12] = (
word32)iterationCount;
365 return ChaCha_GetAlignment();
370 return ChaCha_GetOptimalBlockSize();
374 byte *output,
const byte *input,
size_t iterationCount)
376 ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
377 m_rounds, output, input, iterationCount);
382std::string ChaChaTLS_Policy::AlgorithmName()
const
384 return std::string(
"ChaChaTLS");
389 return ChaCha_AlgorithmProvider();
392void ChaChaTLS_Policy::CipherSetKey(
const NameValuePairs ¶ms,
const byte *key,
size_t length)
395 CRYPTOPP_UNUSED(length);
410 if (params.
GetValue(
"InitialBlock", block))
411 m_counter =
static_cast<word32>(block);
416 GetBlock<word32, LittleEndian> get(key);
417 get(m_state[KEY+0])(m_state[KEY+1])(m_state[KEY+2])(m_state[KEY+3])
418 (m_state[KEY+4])(m_state[KEY+5])(m_state[KEY+6])(m_state[KEY+7]);
421void ChaChaTLS_Policy::CipherResynchronize(
byte *keystreamBuffer,
const byte *IV,
size_t length)
423 CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
427 m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
428 m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
431 std::memcpy(m_state+4, m_state+KEY, 8*
sizeof(
word32));
434 GetBlock<word32, LittleEndian> get(IV);
435 m_state[12] = m_counter;
436 get(m_state[13])(m_state[14])(m_state[15]);
439void ChaChaTLS_Policy::SeekToIteration(
lword iterationCount)
445 CRYPTOPP_ASSERT(iterationCount <= (std::numeric_limits<word32>::max)());
446 m_state[12] = (
word32)iterationCount;
451 return ChaCha_GetAlignment();
456 return ChaCha_GetOptimalBlockSize();
460 byte *output,
const byte *input,
size_t iterationCount)
463 ChaCha_OperateKeystream(operation, m_state, m_state[12], discard,
464 ROUNDS, output, input, iterationCount);
478std::string XChaCha20_Policy::AlgorithmName()
const
480 return std::string(
"XChaCha20");
485 return ChaCha_AlgorithmProvider();
488void XChaCha20_Policy::CipherSetKey(
const NameValuePairs ¶ms,
const byte *key,
size_t length)
491 CRYPTOPP_UNUSED(length);
495 if (rounds != 20 && rounds != 12)
502 if (params.
GetValue(
"InitialBlock", block))
503 m_counter =
static_cast<word32>(block);
508 GetBlock<word32, LittleEndian> get(key);
509 get(m_state[KEY+0])(m_state[KEY+1])(m_state[KEY+2])(m_state[KEY+3])
510 (m_state[KEY+4])(m_state[KEY+5])(m_state[KEY+6])(m_state[KEY+7]);
513void XChaCha20_Policy::CipherResynchronize(
byte *keystreamBuffer,
const byte *iv,
size_t length)
515 CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
519 m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
520 m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
523 std::memcpy(m_state+4, m_state+KEY, 8*
sizeof(
word32));
525 GetBlock<word32, LittleEndian> get(iv);
526 get(m_state[12])(m_state[13])(m_state[14])(m_state[15]);
531 HChaCha_OperateKeystream(m_state, m_state+4);
534 m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
535 m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
538 m_state[12] = m_counter;
544void XChaCha20_Policy::SeekToIteration(
lword iterationCount)
553 return ChaCha_GetAlignment();
558 return ChaCha_GetOptimalBlockSize();
562 byte *output,
const byte *input,
size_t iterationCount)
564 ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
565 m_rounds, output, input, iterationCount);
Standard names for retrieving values by name when working with NameValuePairs.
Classes for ChaCha8, ChaCha12 and ChaCha20 stream ciphers.
Interface for retrieving values given their names.
bool GetValue(const char *name, T &value) const
Get a named value.
CRYPTOPP_DLL int GetIntValueWithDefault(const char *name, int defaultValue) const
Get a named value with type int, with default.
Library configuration file.
unsigned int word32
32-bit unsigned datatype
unsigned long long word64
64-bit unsigned datatype
word64 lword
Large word type.
Functions for CPU features and intrinsics.
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Utility functions for the Crypto++ library.
T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
Access a block of memory.
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
unsigned int GetAlignmentOf()
Returns the minimum alignment requirements of a type.
T SafeRightShift(T value)
Safely right shift values when undefined behavior could occur.
#define EnumToInt(v)
Integer value.
Crypto++ library namespace.
#define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y)
Helper macro to implement OperateKeystream.
KeystreamOperation
Keystream operation flags.
@ INPUT_NULL
Input buffer is NULL.
virtual std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
virtual unsigned int GetAlignment() const
Provides data alignment requirements.
virtual unsigned int GetOptimalBlockSize() const
Provides number of ideal bytes to process.
static const char * StaticAlgorithmName()
The algorithm name.
SymmetricCipherFinal< ConcretePolicyHolder< ChaCha_Policy, AdditiveCipherTemplate<> >, ChaCha_Info > Encryption
ChaCha Encryption.
static const char * StaticAlgorithmName()
The algorithm name.
SymmetricCipherFinal< ConcretePolicyHolder< ChaChaTLS_Policy, AdditiveCipherTemplate<> >, ChaChaTLS_Info > Encryption
ChaCha-TLS Encryption.
SymmetricCipherFinal< ConcretePolicyHolder< XChaCha20_Policy, AdditiveCipherTemplate<> >, XChaCha20_Info > Encryption
XChaCha Encryption.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.