Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/cryptopp/chacha.cpp
2 views
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_ALTIVEC_AVAILABLE)
32
extern void ChaCha_OperateKeystream_ALTIVEC(const word32 *state, const byte* input, byte *output, unsigned int rounds);
33
#endif
34
35
#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
36
void ChaCha_TestInstantiations()
37
{
38
ChaCha::Encryption x;
39
ChaChaTLS::Encryption y;
40
XChaCha20::Encryption z;
41
}
42
#endif
43
44
NAMESPACE_END // CryptoPP
45
46
////////////////////////////// ChaCha Core //////////////////////////////
47
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);
53
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]);}
71
72
ANONYMOUS_NAMESPACE_BEGIN
73
74
// Hacks... Bring in all symbols, and supply
75
// the stuff the templates normally provide.
76
using namespace CryptoPP;
77
typedef word32 WordType;
78
enum {BYTES_PER_ITERATION=64};
79
80
// MultiBlockSafe detects a condition that can arise in the SIMD
81
// implementations where we overflow one of the 32-bit state words during
82
// addition in an intermediate result. Preconditions for the issue include
83
// a user seeks to around 2^32 blocks (256 GB of data) for ChaCha; or a
84
// user specifies an arbitrarily large initial counter block for ChaChaTLS.
85
// Also see https://github.com/weidai11/cryptopp/issues/732.
86
inline bool MultiBlockSafe(unsigned int ctrLow, unsigned int blocks)
87
{
88
return 0xffffffff - ctrLow > blocks;
89
}
90
91
// OperateKeystream always produces a key stream. The key stream is written
92
// to output. Optionally a message may be supplied to xor with the key stream.
93
// The message is input, and output = output ^ input.
94
void ChaCha_OperateKeystream(KeystreamOperation operation,
95
word32 state[16], word32& ctrLow, word32& ctrHigh, word32 rounds,
96
byte *output, const byte *input, size_t iterationCount)
97
{
98
do
99
{
100
#if (CRYPTOPP_AVX2_AVAILABLE)
101
if (HasAVX2())
102
{
103
while (iterationCount >= 8 && MultiBlockSafe(state[12], 8))
104
{
105
const bool xorInput = (operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL);
106
ChaCha_OperateKeystream_AVX2(state, xorInput ? input : NULLPTR, output, rounds);
107
108
// MultiBlockSafe avoids overflow on the counter words
109
state[12] += 8;
110
111
input += (!!xorInput) * 8 * BYTES_PER_ITERATION;
112
output += 8 * BYTES_PER_ITERATION;
113
iterationCount -= 8;
114
}
115
}
116
#endif
117
118
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
119
if (HasSSE2())
120
{
121
while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
122
{
123
const bool xorInput = (operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL);
124
ChaCha_OperateKeystream_SSE2(state, xorInput ? input : NULLPTR, output, rounds);
125
126
// MultiBlockSafe avoids overflow on the counter words
127
state[12] += 4;
128
129
input += (!!xorInput)*4*BYTES_PER_ITERATION;
130
output += 4*BYTES_PER_ITERATION;
131
iterationCount -= 4;
132
}
133
}
134
#endif
135
136
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
137
if (HasNEON())
138
{
139
while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
140
{
141
const bool xorInput = (operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL);
142
ChaCha_OperateKeystream_NEON(state, xorInput ? input : NULLPTR, output, rounds);
143
144
// MultiBlockSafe avoids overflow on the counter words
145
state[12] += 4;
146
147
input += (!!xorInput)*4*BYTES_PER_ITERATION;
148
output += 4*BYTES_PER_ITERATION;
149
iterationCount -= 4;
150
}
151
}
152
#endif
153
154
#if (CRYPTOPP_ALTIVEC_AVAILABLE)
155
if (HasAltivec())
156
{
157
while (iterationCount >= 4 && MultiBlockSafe(state[12], 4))
158
{
159
const bool xorInput = (operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL);
160
ChaCha_OperateKeystream_ALTIVEC(state, xorInput ? input : NULLPTR, output, rounds);
161
162
// MultiBlockSafe avoids overflow on the counter words
163
state[12] += 4;
164
165
input += (!!xorInput)*4*BYTES_PER_ITERATION;
166
output += 4*BYTES_PER_ITERATION;
167
iterationCount -= 4;
168
}
169
}
170
#endif
171
172
if (iterationCount)
173
{
174
word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
175
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];
180
181
for (int i = static_cast<int>(rounds); i > 0; i -= 2)
182
{
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);
187
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);
192
}
193
194
CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(CHACHA_OUTPUT, BYTES_PER_ITERATION);
195
196
// This is state[12] and state[13] from ChaCha. In the case of
197
// ChaChaTLS ctrHigh is a reference to a discard value.
198
if (++ctrLow == 0)
199
ctrHigh++;
200
}
201
202
// We may re-enter a SIMD keystream operation from here.
203
} while (iterationCount--);
204
}
205
206
// XChaCha key derivation
207
void HChaCha_OperateKeystream(const word32 state[16], word32 output[8])
208
{
209
word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
210
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];
215
216
for (int i = 20; i > 0; i -= 2)
217
{
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);
222
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);
227
}
228
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;
233
}
234
235
std::string ChaCha_AlgorithmProvider()
236
{
237
#if (CRYPTOPP_AVX2_AVAILABLE)
238
if (HasAVX2())
239
return "AVX2";
240
else
241
#endif
242
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
243
if (HasSSE2())
244
return "SSE2";
245
else
246
#endif
247
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
248
if (HasNEON())
249
return "NEON";
250
else
251
#endif
252
#if (CRYPTOPP_ALTIVEC_AVAILABLE)
253
if (HasAltivec())
254
return "Altivec";
255
else
256
#endif
257
return "C++";
258
}
259
260
unsigned int ChaCha_GetAlignment()
261
{
262
#if (CRYPTOPP_AVX2_AVAILABLE)
263
if (HasAVX2())
264
return 16;
265
else
266
#endif
267
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
268
if (HasSSE2())
269
return 16;
270
else
271
#endif
272
#if (CRYPTOPP_ALTIVEC_AVAILABLE)
273
if (HasAltivec())
274
return 16;
275
else
276
#endif
277
return GetAlignmentOf<word32>();
278
}
279
280
unsigned int ChaCha_GetOptimalBlockSize()
281
{
282
#if (CRYPTOPP_AVX2_AVAILABLE)
283
if (HasAVX2())
284
return 8 * BYTES_PER_ITERATION;
285
else
286
#endif
287
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
288
if (HasSSE2())
289
return 4*BYTES_PER_ITERATION;
290
else
291
#endif
292
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
293
if (HasNEON())
294
return 4*BYTES_PER_ITERATION;
295
else
296
#endif
297
#if (CRYPTOPP_ALTIVEC_AVAILABLE)
298
if (HasAltivec())
299
return 4*BYTES_PER_ITERATION;
300
else
301
#endif
302
return BYTES_PER_ITERATION;
303
}
304
305
ANONYMOUS_NAMESPACE_END
306
307
NAMESPACE_BEGIN(CryptoPP)
308
309
////////////////////////////// Bernstein ChaCha //////////////////////////////
310
311
std::string ChaCha_Policy::AlgorithmName() const
312
{
313
return std::string("ChaCha")+IntToString(m_rounds);
314
}
315
316
std::string ChaCha_Policy::AlgorithmProvider() const
317
{
318
return ChaCha_AlgorithmProvider();
319
}
320
321
void ChaCha_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
322
{
323
CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 16 || length == 32);
324
CRYPTOPP_UNUSED(key); CRYPTOPP_UNUSED(length);
325
326
// Use previous rounds as the default value
327
int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
328
if (rounds != 20 && rounds != 12 && rounds != 8)
329
throw InvalidRounds(ChaCha::StaticAlgorithmName(), rounds);
330
331
// Latch a good value
332
m_rounds = rounds;
333
334
// "expand 16-byte k" or "expand 32-byte k"
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;
339
340
GetBlock<word32, LittleEndian> get1(key);
341
get1(m_state[4])(m_state[5])(m_state[6])(m_state[7]);
342
343
GetBlock<word32, LittleEndian> get2(key + ((length == 32) ? 16 : 0));
344
get2(m_state[8])(m_state[9])(m_state[10])(m_state[11]);
345
}
346
347
void ChaCha_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
348
{
349
CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
350
CRYPTOPP_ASSERT(length==8); CRYPTOPP_UNUSED(length);
351
352
GetBlock<word32, LittleEndian> get(IV);
353
m_state[12] = m_state[13] = 0;
354
get(m_state[14])(m_state[15]);
355
}
356
357
void ChaCha_Policy::SeekToIteration(lword iterationCount)
358
{
359
m_state[12] = (word32)iterationCount; // low word
360
m_state[13] = (word32)SafeRightShift<32>(iterationCount);
361
}
362
363
unsigned int ChaCha_Policy::GetAlignment() const
364
{
365
return ChaCha_GetAlignment();
366
}
367
368
unsigned int ChaCha_Policy::GetOptimalBlockSize() const
369
{
370
return ChaCha_GetOptimalBlockSize();
371
}
372
373
void ChaCha_Policy::OperateKeystream(KeystreamOperation operation,
374
byte *output, const byte *input, size_t iterationCount)
375
{
376
ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
377
m_rounds, output, input, iterationCount);
378
}
379
380
////////////////////////////// IETF ChaChaTLS //////////////////////////////
381
382
std::string ChaChaTLS_Policy::AlgorithmName() const
383
{
384
return std::string("ChaChaTLS");
385
}
386
387
std::string ChaChaTLS_Policy::AlgorithmProvider() const
388
{
389
return ChaCha_AlgorithmProvider();
390
}
391
392
void ChaChaTLS_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
393
{
394
CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32);
395
CRYPTOPP_UNUSED(length);
396
397
// ChaChaTLS is always 20 rounds. Fetch Rounds() to avoid a spurious failure.
398
int rounds = params.GetIntValueWithDefault(Name::Rounds(), ROUNDS);
399
if (rounds != 20)
400
throw InvalidRounds(ChaChaTLS::StaticAlgorithmName(), rounds);
401
402
// RFC 8439 test vectors use an initial block counter. However, the counter
403
// can be an arbitrary value per RFC 8439 Section 2.4. We stash the counter
404
// away in state[16] and use it for a Resynchronize() operation. I think
405
// the initial counter is used more like a Tweak when non-0, and it should
406
// be provided in Resynchronize() (light-weight re-keying). However,
407
// Resynchronize() does not have an overload that allows us to pass it into
408
// the function, so we have to use the heavier-weight SetKey to change it.
409
word64 block;
410
if (params.GetValue("InitialBlock", block))
411
m_counter = static_cast<word32>(block);
412
else
413
m_counter = 0;
414
415
// State words are defined in RFC 8439, Section 2.3. Key is 32-bytes.
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]);
419
}
420
421
void ChaChaTLS_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
422
{
423
CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
424
CRYPTOPP_ASSERT(length==12);
425
426
// State words are defined in RFC 8439, Section 2.3.
427
m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
428
m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
429
430
// Copy saved key into state
431
std::memcpy(m_state+4, m_state+KEY, 8*sizeof(word32));
432
433
// State words are defined in RFC 8439, Section 2.3
434
GetBlock<word32, LittleEndian> get(IV);
435
m_state[12] = m_counter;
436
get(m_state[13])(m_state[14])(m_state[15]);
437
}
438
439
void ChaChaTLS_Policy::SeekToIteration(lword iterationCount)
440
{
441
// Should we throw here??? If the initial block counter is
442
// large then we can wrap and process more data as long as
443
// data processed in the security context does not exceed
444
// 2^32 blocks or approximately 256 GB of data.
445
CRYPTOPP_ASSERT(iterationCount <= (std::numeric_limits<word32>::max)());
446
m_state[12] = (word32)iterationCount; // low word
447
}
448
449
unsigned int ChaChaTLS_Policy::GetAlignment() const
450
{
451
return ChaCha_GetAlignment();
452
}
453
454
unsigned int ChaChaTLS_Policy::GetOptimalBlockSize() const
455
{
456
return ChaCha_GetOptimalBlockSize();
457
}
458
459
void ChaChaTLS_Policy::OperateKeystream(KeystreamOperation operation,
460
byte *output, const byte *input, size_t iterationCount)
461
{
462
word32 discard=0;
463
ChaCha_OperateKeystream(operation, m_state, m_state[12], discard,
464
ROUNDS, output, input, iterationCount);
465
466
// If this fires it means ChaCha_OperateKeystream generated a counter
467
// block carry that was discarded. The problem is, the RFC does not
468
// specify what should happen when the counter block wraps. All we can
469
// do is inform the user that something bad may happen because we don't
470
// know what we should do.
471
// Also see https://github.com/weidai11/cryptopp/issues/790 and
472
// https://mailarchive.ietf.org/arch/msg/cfrg/gsOnTJzcbgG6OqD8Sc0GO5aR_tU
473
// CRYPTOPP_ASSERT(discard==0);
474
}
475
476
////////////////////////////// IETF XChaCha20 //////////////////////////////
477
478
std::string XChaCha20_Policy::AlgorithmName() const
479
{
480
return std::string("XChaCha20");
481
}
482
483
std::string XChaCha20_Policy::AlgorithmProvider() const
484
{
485
return ChaCha_AlgorithmProvider();
486
}
487
488
void XChaCha20_Policy::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
489
{
490
CRYPTOPP_ASSERT(key); CRYPTOPP_ASSERT(length == 32);
491
CRYPTOPP_UNUSED(length);
492
493
// Use previous rounds as the default value
494
int rounds = params.GetIntValueWithDefault(Name::Rounds(), m_rounds);
495
if (rounds != 20 && rounds != 12)
496
throw InvalidRounds(ChaCha::StaticAlgorithmName(), rounds);
497
498
// Latch a good value
499
m_rounds = rounds;
500
501
word64 block;
502
if (params.GetValue("InitialBlock", block))
503
m_counter = static_cast<word32>(block);
504
else
505
m_counter = 1;
506
507
// Stash key away for use in CipherResynchronize
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]);
511
}
512
513
void XChaCha20_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
514
{
515
CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
516
CRYPTOPP_ASSERT(length==24);
517
518
// HChaCha derivation
519
m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
520
m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
521
522
// Copy saved key into state
523
std::memcpy(m_state+4, m_state+KEY, 8*sizeof(word32));
524
525
GetBlock<word32, LittleEndian> get(iv);
526
get(m_state[12])(m_state[13])(m_state[14])(m_state[15]);
527
528
// Operate the keystream without adding state back in.
529
// This function also gathers the key words into a
530
// contiguous 8-word block.
531
HChaCha_OperateKeystream(m_state, m_state+4);
532
533
// XChaCha state
534
m_state[0] = 0x61707865; m_state[1] = 0x3320646e;
535
m_state[2] = 0x79622d32; m_state[3] = 0x6b206574;
536
537
// Setup new IV
538
m_state[12] = m_counter;
539
m_state[13] = 0;
540
m_state[14] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, iv+16);
541
m_state[15] = GetWord<word32>(false, LITTLE_ENDIAN_ORDER, iv+20);
542
}
543
544
void XChaCha20_Policy::SeekToIteration(lword iterationCount)
545
{
546
// Should we throw here??? XChaCha does not have a block
547
// counter, so I'm not sure how to seek on it.
548
CRYPTOPP_ASSERT(0); CRYPTOPP_UNUSED(iterationCount);
549
}
550
551
unsigned int XChaCha20_Policy::GetAlignment() const
552
{
553
return ChaCha_GetAlignment();
554
}
555
556
unsigned int XChaCha20_Policy::GetOptimalBlockSize() const
557
{
558
return ChaCha_GetOptimalBlockSize();
559
}
560
561
void XChaCha20_Policy::OperateKeystream(KeystreamOperation operation,
562
byte *output, const byte *input, size_t iterationCount)
563
{
564
ChaCha_OperateKeystream(operation, m_state, m_state[12], m_state[13],
565
m_rounds, output, input, iterationCount);
566
}
567
568
NAMESPACE_END
569
570