14#if defined(__GNUC__) && (__GNUC__ < 4)
15# undef CRYPTOPP_SSE2_INTRIN_AVAILABLE
18NAMESPACE_BEGIN(CryptoPP)
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
76using namespace CryptoPP;
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)
277 return GetAlignmentOf<word32>();
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
307NAMESPACE_BEGIN(CryptoPP)
311std::string ChaCha_Policy::AlgorithmName()
const
313 return std::string(
"ChaCha")+
IntToString(m_rounds);
318 return ChaCha_AlgorithmProvider();
323 CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 16 || length == 32);
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]);
349 CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
350 CRYPTOPP_ASSERT(length==8); 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]);
359 m_state[12] = (
word32)iterationCount;
360 m_state[13] = (
word32)SafeRightShift<32>(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();
394 CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32);
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]);
423 CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
424 CRYPTOPP_ASSERT(length==12);
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]);
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();
490 CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32);
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]);
515 CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
516 CRYPTOPP_ASSERT(length==24);
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;
548 CRYPTOPP_ASSERT(0); CRYPTOPP_UNUSED(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.
void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length)
Key the cipher.
void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
Resynchronize the cipher.
unsigned int GetOptimalBlockSize() const
Provides number of ideal bytes to process.
void SeekToIteration(lword iterationCount)
Seeks to a random position in the stream.
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
Operates the keystream.
unsigned int GetAlignment() const
Provides data alignment requirements.
std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
unsigned int GetOptimalBlockSize() const
Provides number of ideal bytes to process.
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
Operates the keystream.
void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
Resynchronize the cipher.
unsigned int GetAlignment() const
Provides data alignment requirements.
void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length)
Key the cipher.
void SeekToIteration(lword iterationCount)
Seeks to a random position in the stream.
Exception thrown when an invalid number of rounds is encountered.
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.
SymmetricCipher implementation.
void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
Resynchronize the cipher.
unsigned int GetOptimalBlockSize() const
Provides number of ideal bytes to process.
std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length)
Key the cipher.
unsigned int GetAlignment() const
Provides data alignment requirements.
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
Operates the keystream.
void SeekToIteration(lword iterationCount)
Seeks to a random position in the stream.
Library configuration file.
unsigned int word32
32-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.
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
#define EnumToInt(v)
Integer value.
#define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y)
Helper macro to implement OperateKeystream.
KeystreamOperation
Keystream operation flags.
@ INPUT_NULL
Input buffer is NULL.
static const char * StaticAlgorithmName()
The algorithm name.
static const char * StaticAlgorithmName()
The algorithm name.