summaryrefslogtreecommitdiff
path: root/strciphr.h
blob: 710944fcef6a374c5102cb5285307c7a01418282 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
// strciphr.h - originally written and placed in the public domain by Wei Dai

/// \file strciphr.h
/// \brief Classes for implementing stream ciphers
/// \details This file contains helper classes for implementing stream ciphers.
///  All this infrastructure may look very complex compared to what's in Crypto++ 4.x,
///  but stream ciphers implementations now support a lot of new functionality,
///  including better performance (minimizing copying), resetting of keys and IVs, and
///  methods to query which features are supported by a cipher.
/// \details Here's an explanation of these classes. The word "policy" is used here to
///  mean a class with a set of methods that must be implemented by individual stream
///  cipher implementations. This is usually much simpler than the full stream cipher
///  API, which is implemented by either AdditiveCipherTemplate or CFB_CipherTemplate
///  using the policy. So for example, an implementation of SEAL only needs to implement
///  the AdditiveCipherAbstractPolicy interface (since it's an additive cipher, i.e., it
///  xors a keystream into the plaintext). See this line in seal.h:
/// <pre>
///     typedef SymmetricCipherFinal\<ConcretePolicyHolder\<SEAL_Policy\<B\>, AdditiveCipherTemplate\<\> \> \> Encryption;
/// </pre>
/// \details AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't
///  need to take a policy class as a template parameter (although this is allowed), so
///  that their code is not duplicated for each new cipher. Instead they each get a
///  reference to an abstract policy interface by calling AccessPolicy() on itself, so
///  AccessPolicy() must be overridden to return the actual policy reference. This is done
///  by the ConcretePolicyHolder class. Finally, SymmetricCipherFinal implements the
///  constructors and other functions that must be implemented by the most derived class.

#ifndef CRYPTOPP_STRCIPHR_H
#define CRYPTOPP_STRCIPHR_H

#include "config.h"

#if CRYPTOPP_MSC_VERSION
# pragma warning(push)
# pragma warning(disable: 4127 4189 4231 4275)
#endif

#include "cryptlib.h"
#include "seckey.h"
#include "secblock.h"
#include "argnames.h"

NAMESPACE_BEGIN(CryptoPP)

/// \brief Access a stream cipher policy object
/// \tparam POLICY_INTERFACE class implementing AbstractPolicyHolder
/// \tparam BASE class or type to use as a base class
template <class POLICY_INTERFACE, class BASE = Empty>
class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE
{
public:
	typedef POLICY_INTERFACE PolicyInterface;
	virtual ~AbstractPolicyHolder() {}

protected:
	virtual const POLICY_INTERFACE & GetPolicy() const =0;
	virtual POLICY_INTERFACE & AccessPolicy() =0;
};

/// \brief Stream cipher policy object
/// \tparam POLICY class implementing AbstractPolicyHolder
/// \tparam BASE class or type to use as a base class
template <class POLICY, class BASE, class POLICY_INTERFACE = typename BASE::PolicyInterface>
class ConcretePolicyHolder : public BASE, protected POLICY
{
public:
	virtual ~ConcretePolicyHolder() {}
protected:
	const POLICY_INTERFACE & GetPolicy() const {return *this;}
	POLICY_INTERFACE & AccessPolicy() {return *this;}
};

/// \brief Keystream operation flags
/// \sa AdditiveCipherAbstractPolicy::GetBytesPerIteration(), AdditiveCipherAbstractPolicy::GetOptimalBlockSize()
///  and AdditiveCipherAbstractPolicy::GetAlignment()
enum KeystreamOperationFlags {
	/// \brief Output buffer is aligned
	OUTPUT_ALIGNED=1,
	/// \brief Input buffer is aligned
	INPUT_ALIGNED=2,
	/// \brief Input buffer is NULL
	INPUT_NULL = 4
};

/// \brief Keystream operation flags
/// \sa AdditiveCipherAbstractPolicy::GetBytesPerIteration(), AdditiveCipherAbstractPolicy::GetOptimalBlockSize()
///  and AdditiveCipherAbstractPolicy::GetAlignment()
enum KeystreamOperation {
	/// \brief Write the keystream to the output buffer, input is NULL
	WRITE_KEYSTREAM				= INPUT_NULL,
	/// \brief Write the keystream to the aligned output buffer, input is NULL
	WRITE_KEYSTREAM_ALIGNED		= INPUT_NULL | OUTPUT_ALIGNED,
	/// \brief XOR the input buffer and keystream, write to the output buffer
	XOR_KEYSTREAM				= 0,
	/// \brief XOR the aligned input buffer and keystream, write to the output buffer
	XOR_KEYSTREAM_INPUT_ALIGNED = INPUT_ALIGNED,
	/// \brief XOR the input buffer and keystream, write to the aligned output buffer
	XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED,
	/// \brief XOR the aligned input buffer and keystream, write to the aligned output buffer
	XOR_KEYSTREAM_BOTH_ALIGNED	= OUTPUT_ALIGNED | INPUT_ALIGNED
};

/// \brief Policy object for additive stream ciphers
struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy
{
	virtual ~AdditiveCipherAbstractPolicy() {}

	/// \brief Provides data alignment requirements
	/// \return data alignment requirements, in bytes
	/// \details Internally, the default implementation returns 1. If the stream cipher is implemented
	///  using an SSE2 ASM or intrinsics, then the value returned is usually 16.
	virtual unsigned int GetAlignment() const {return 1;}

	/// \brief Provides number of bytes operated upon during an iteration
	/// \return bytes operated upon during an iteration, in bytes
	/// \sa GetOptimalBlockSize()
	virtual unsigned int GetBytesPerIteration() const =0;

	/// \brief Provides number of ideal bytes to process
	/// \return the ideal number of bytes to process
	/// \details Internally, the default implementation returns GetBytesPerIteration()
	/// \sa GetBytesPerIteration()
	virtual unsigned int GetOptimalBlockSize() const {return GetBytesPerIteration();}

	/// \brief Provides buffer size based on iterations
	/// \return the buffer size based on iterations, in bytes
	virtual unsigned int GetIterationsToBuffer() const =0;

	/// \brief Generate the keystream
	/// \param keystream the key stream
	/// \param iterationCount the number of iterations to generate the key stream
	/// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream()
	virtual void WriteKeystream(byte *keystream, size_t iterationCount)
		{OperateKeystream(KeystreamOperation(INPUT_NULL | static_cast<KeystreamOperationFlags>(IsAlignedOn(keystream, GetAlignment()))), keystream, NULLPTR, iterationCount);}

	/// \brief Flag indicating
	/// \return true if the stream can be generated independent of the transformation input, false otherwise
	/// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream()
	virtual bool CanOperateKeystream() const {return false;}

	/// \brief Operates the keystream
	/// \param operation the operation with additional flags
	/// \param output the output buffer
	/// \param input the input buffer
	/// \param iterationCount the number of iterations to perform on the input
	/// \details OperateKeystream() will attempt to operate upon GetOptimalBlockSize() buffer,
	///  which will be derived from GetBytesPerIteration().
	/// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream(), KeystreamOperation()
	virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
		{CRYPTOPP_UNUSED(operation); CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(input);
		CRYPTOPP_UNUSED(iterationCount); CRYPTOPP_ASSERT(false);}

	/// \brief Key the cipher
	/// \param params set of NameValuePairs use to initialize this object
	/// \param key a byte array used to key the cipher
	/// \param length the size of the key array
	virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;

	/// \brief Resynchronize the cipher
	/// \param keystreamBuffer the keystream buffer
	/// \param iv a byte array used to resynchronize the cipher
	/// \param length the size of the IV array
	virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
		{CRYPTOPP_UNUSED(keystreamBuffer); CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(length);
		throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}

	/// \brief Flag indicating random access
	/// \return true if the cipher is seekable, false otherwise
	/// \sa SeekToIteration()
	virtual bool CipherIsRandomAccess() const =0;

	/// \brief Seeks to a random position in the stream
	/// \sa CipherIsRandomAccess()
	virtual void SeekToIteration(lword iterationCount)
		{CRYPTOPP_UNUSED(iterationCount); CRYPTOPP_ASSERT(!CipherIsRandomAccess());
		throw NotImplemented("StreamTransformation: this object doesn't support random access");}

	/// \brief Retrieve the provider of this algorithm
	/// \return the algorithm provider
	/// \details The algorithm provider can be a name like "C++", "SSE", "NEON", "AESNI",
	///  "ARMv8" and "Power8". C++ is standard C++ code. Other labels, like SSE,
	///  usually indicate a specialized implementation using instructions from a higher
	///  instruction set architecture (ISA). Future labels may include external hardware
	///  like a hardware security module (HSM).
	/// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2".
	///  Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics
	///  instead of ASM.
	/// \details Algorithms which combine different instructions or ISAs provide the
	///  dominant one. For example on x86 <tt>AES/GCM</tt> returns "AESNI" rather than
	///  "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL".
	/// \note Provider is not universally implemented yet.
	virtual std::string AlgorithmProvider() const { return "C++"; }
};

/// \brief Base class for additive stream ciphers
/// \tparam WT word type
/// \tparam W count of words
/// \tparam X bytes per iteration count
/// \tparam BASE AdditiveCipherAbstractPolicy derived base class
template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy>
struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE
{
	/// \brief Word type for the cipher
	typedef WT WordType;

	/// \brief Number of bytes for an iteration
	/// \details BYTES_PER_ITERATION is the product <tt>sizeof(WordType) * W</tt>.
	///  For example, ChaCha uses 16 each <tt>word32</tt>, and the value of
	///  BYTES_PER_ITERATION is 64. Each invocation of the ChaCha block function
	///  produces 64 bytes of keystream.
	CRYPTOPP_CONSTANT(BYTES_PER_ITERATION = sizeof(WordType) * W);

	virtual ~AdditiveCipherConcretePolicy() {}

	/// \brief Provides data alignment requirements
	/// \return data alignment requirements, in bytes
	/// \details Internally, the default implementation returns 1. If the stream
	///  cipher is implemented using an SSE2 ASM or intrinsics, then the value
	///  returned is usually 16.
	unsigned int GetAlignment() const {return GetAlignmentOf<WordType>();}

	/// \brief Provides number of bytes operated upon during an iteration
	/// \return bytes operated upon during an iteration, in bytes
	/// \sa GetOptimalBlockSize()
	unsigned int GetBytesPerIteration() const {return BYTES_PER_ITERATION;}

	/// \brief Provides buffer size based on iterations
	/// \return the buffer size based on iterations, in bytes
	unsigned int GetIterationsToBuffer() const {return X;}

	/// \brief Flag indicating
	/// \return true if the stream can be generated independent of the
	///  transformation input, false otherwise
	/// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream()
	bool CanOperateKeystream() const {return true;}

	/// \brief Operates the keystream
	/// \param operation the operation with additional flags
	/// \param output the output buffer
	/// \param input the input buffer
	/// \param iterationCount the number of iterations to perform on the input
	/// \details OperateKeystream() will attempt to operate upon GetOptimalBlockSize() buffer,
	///  which will be derived from GetBytesPerIteration().
	/// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream(), KeystreamOperation()
	virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0;
};

/// \brief Helper macro to implement OperateKeystream
/// \param x KeystreamOperation mask
/// \param b Endian order
/// \param i index in output buffer
/// \param a value to output
#define CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, b, i, a)	\
	PutWord(((x & OUTPUT_ALIGNED) != 0), b, output+i*sizeof(WordType), (x & INPUT_NULL) ? (a) : (a) ^ GetWord<WordType>(((x & INPUT_ALIGNED) != 0), b, input+i*sizeof(WordType)));

/// \brief Helper macro to implement OperateKeystream
/// \param x KeystreamOperation mask
/// \param i index in output buffer
/// \param a value to output
#define CRYPTOPP_KEYSTREAM_OUTPUT_XMM(x, i, a)	{\
	__m128i t = (x & INPUT_NULL) ? a : _mm_xor_si128(a, (x & INPUT_ALIGNED) ? _mm_load_si128((__m128i *)input+i) : _mm_loadu_si128((__m128i *)input+i));\
	if (x & OUTPUT_ALIGNED) _mm_store_si128((__m128i *)output+i, t);\
	else _mm_storeu_si128((__m128i *)output+i, t);}

/// \brief Helper macro to implement OperateKeystream
#define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y)		\
	switch (operation)								\
	{												\
		case WRITE_KEYSTREAM:						\
			x(EnumToInt(WRITE_KEYSTREAM))	\
			break;									\
		case XOR_KEYSTREAM:							\
			x(EnumToInt(XOR_KEYSTREAM))		\
			input += y;								\
			break;									\
		case XOR_KEYSTREAM_INPUT_ALIGNED:			\
			x(EnumToInt(XOR_KEYSTREAM_INPUT_ALIGNED))		\
			input += y;								\
			break;									\
		case XOR_KEYSTREAM_OUTPUT_ALIGNED:			\
			x(EnumToInt(XOR_KEYSTREAM_OUTPUT_ALIGNED))		\
			input += y;								\
			break;									\
		case WRITE_KEYSTREAM_ALIGNED:				\
			x(EnumToInt(WRITE_KEYSTREAM_ALIGNED))			\
			break;									\
		case XOR_KEYSTREAM_BOTH_ALIGNED:			\
			x(EnumToInt(XOR_KEYSTREAM_BOTH_ALIGNED))		\
			input += y;								\
			break;									\
	}												\
	output += y;

/// \brief Base class for additive stream ciphers with SymmetricCipher interface
/// \tparam BASE AbstractPolicyHolder base class
template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >
class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE, public RandomNumberGenerator
{
public:
	virtual ~AdditiveCipherTemplate() {}
	AdditiveCipherTemplate() : m_leftOver(0) {}

	/// \brief Generate random array of bytes
	/// \param output the byte buffer
	/// \param size the length of the buffer, in bytes
	/// \details All generated values are uniformly distributed over the range specified
	///  within the constraints of a particular generator.
	void GenerateBlock(byte *output, size_t size);

	/// \brief Apply keystream to data
	/// \param outString a buffer to write the transformed data
	/// \param inString a buffer to read the data
	/// \param length the size of the buffers, in bytes
	/// \details This is the primary method to operate a stream cipher. For example:
	/// <pre>
	///     size_t size = 30;
	///     byte plain[size] = "Do or do not; there is no try";
	///     byte cipher[size];
	///     ...
	///     ChaCha20 chacha(key, keySize);
	///     chacha.ProcessData(cipher, plain, size);
	/// </pre>
	/// \details You should use distinct buffers for inString and outString. If the buffers
	///  are the same, then the data will be copied to an internal buffer to avoid GCC alias
	///  violations. The internal copy will impact performance.
	/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/1088">Issue 1088, 36% loss
	///  of performance with AES</A>, <A HREF="https://github.com/weidai11/cryptopp/issues/1010">Issue
	///  1010, HIGHT cipher troubles with FileSource</A>
	void ProcessData(byte *outString, const byte *inString, size_t length);

	/// \brief Resynchronize the cipher
	/// \param iv a byte array used to resynchronize the cipher
	/// \param length the size of the IV array
	void Resynchronize(const byte *iv, int length=-1);

	/// \brief Provides number of ideal bytes to process
	/// \return the ideal number of bytes to process
	/// \details Internally, the default implementation returns GetBytesPerIteration()
	/// \sa GetBytesPerIteration() and GetOptimalNextBlockSize()
	unsigned int OptimalBlockSize() const {return this->GetPolicy().GetOptimalBlockSize();}

	/// \brief Provides number of ideal bytes to process
	/// \return the ideal number of bytes to process
	/// \details Internally, the default implementation returns remaining unprocessed bytes
	/// \sa GetBytesPerIteration() and OptimalBlockSize()
	unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;}

	/// \brief Provides number of ideal data alignment
	/// \return the ideal data alignment, in bytes
	/// \sa GetAlignment() and OptimalBlockSize()
	unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}

	/// \brief Determines if the cipher is self inverting
	/// \return true if the stream cipher is self inverting, false otherwise
	bool IsSelfInverting() const {return true;}

	/// \brief Determines if the cipher is a forward transformation
	/// \return true if the stream cipher is a forward transformation, false otherwise
	bool IsForwardTransformation() const {return true;}

	/// \brief Flag indicating random access
	/// \return true if the cipher is seekable, false otherwise
	/// \sa Seek()
	bool IsRandomAccess() const {return this->GetPolicy().CipherIsRandomAccess();}

	/// \brief Seeks to a random position in the stream
	/// \param position the absolute position in the stream
	/// \sa IsRandomAccess()
	void Seek(lword position);

	/// \brief Retrieve the provider of this algorithm
	/// \return the algorithm provider
	/// \details The algorithm provider can be a name like "C++", "SSE", "NEON", "AESNI",
	///  "ARMv8" and "Power8". C++ is standard C++ code. Other labels, like SSE,
	///  usually indicate a specialized implementation using instructions from a higher
	///  instruction set architecture (ISA). Future labels may include external hardware
	///  like a hardware security module (HSM).
	/// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2".
	///  Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics
	///  instead of ASM.
	/// \details Algorithms which combine different instructions or ISAs provide the
	///  dominant one. For example on x86 <tt>AES/GCM</tt> returns "AESNI" rather than
	///  "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL".
	/// \note Provider is not universally implemented yet.
	std::string AlgorithmProvider() const { return this->GetPolicy().AlgorithmProvider(); }

	typedef typename BASE::PolicyInterface PolicyInterface;

protected:
	void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);

	unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();}

	inline byte * KeystreamBufferBegin() {return this->m_buffer.data();}
	inline byte * KeystreamBufferEnd() {return (PtrAdd(this->m_buffer.data(), this->m_buffer.size()));}

	AlignedSecByteBlock m_buffer;
	size_t m_leftOver;
};

/// \brief Policy object for feedback based stream ciphers
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy
{
public:
	virtual ~CFB_CipherAbstractPolicy() {}

	/// \brief Provides data alignment requirements
	/// \return data alignment requirements, in bytes
	/// \details Internally, the default implementation returns 1. If the stream cipher is implemented
	///  using an SSE2 ASM or intrinsics, then the value returned is usually 16.
	virtual unsigned int GetAlignment() const =0;

	/// \brief Provides number of bytes operated upon during an iteration
	/// \return bytes operated upon during an iteration, in bytes
	/// \sa GetOptimalBlockSize()
	virtual unsigned int GetBytesPerIteration() const =0;

	/// \brief Access the feedback register
	/// \return pointer to the first byte of the feedback register
	virtual byte * GetRegisterBegin() =0;

	/// \brief TODO
	virtual void TransformRegister() =0;

	/// \brief Flag indicating iteration support
	/// \return true if the cipher supports iteration, false otherwise
	virtual bool CanIterate() const {return false;}

	/// \brief Iterate the cipher
	/// \param output the output buffer
	/// \param input the input buffer
	/// \param dir the direction of the cipher
	/// \param iterationCount the number of iterations to perform on the input
	/// \sa IsSelfInverting() and IsForwardTransformation()
	virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount)
		{CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(dir);
		CRYPTOPP_UNUSED(iterationCount); CRYPTOPP_ASSERT(false);
		throw Exception(Exception::OTHER_ERROR, "SimpleKeyingInterface: unexpected error");}

	/// \brief Key the cipher
	/// \param params set of NameValuePairs use to initialize this object
	/// \param key a byte array used to key the cipher
	/// \param length the size of the key array
	virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;

	/// \brief Resynchronize the cipher
	/// \param iv a byte array used to resynchronize the cipher
	/// \param length the size of the IV array
	virtual void CipherResynchronize(const byte *iv, size_t length)
		{CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(length);
		throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}

	/// \brief Retrieve the provider of this algorithm
	/// \return the algorithm provider
	/// \details The algorithm provider can be a name like "C++", "SSE", "NEON", "AESNI",
	///  "ARMv8" and "Power8". C++ is standard C++ code. Other labels, like SSE,
	///  usually indicate a specialized implementation using instructions from a higher
	///  instruction set architecture (ISA). Future labels may include external hardware
	///  like a hardware security module (HSM).
	/// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2".
	///  Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics
	///  instead of ASM.
	/// \details Algorithms which combine different instructions or ISAs provide the
	///  dominant one. For example on x86 <tt>AES/GCM</tt> returns "AESNI" rather than
	///  "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL".
	/// \note Provider is not universally implemented yet.
	virtual std::string AlgorithmProvider() const { return "C++"; }
};

/// \brief Base class for feedback based stream ciphers
/// \tparam WT word type
/// \tparam W count of words
/// \tparam BASE CFB_CipherAbstractPolicy derived base class
template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy>
struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE
{
	typedef WT WordType;

	virtual ~CFB_CipherConcretePolicy() {}

	/// \brief Provides data alignment requirements
	/// \return data alignment requirements, in bytes
	/// \details Internally, the default implementation returns 1. If the stream cipher is implemented
	///   using an SSE2 ASM or intrinsics, then the value returned is usually 16.
	unsigned int GetAlignment() const {return sizeof(WordType);}

	/// \brief Provides number of bytes operated upon during an iteration
	/// \return bytes operated upon during an iteration, in bytes
	/// \sa GetOptimalBlockSize()
	unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}

	/// \brief Flag indicating iteration support
	/// \return true if the cipher supports iteration, false otherwise
	bool CanIterate() const {return true;}

	/// \brief Perform one iteration in the forward direction
	void TransformRegister() {this->Iterate(NULLPTR, NULLPTR, ENCRYPTION, 1);}

	/// \brief Provides alternate access to a feedback register
	/// \tparam B enumeration indicating endianness
	/// \details RegisterOutput() provides alternate access to the feedback register. The
	///   enumeration B is BigEndian or LittleEndian. Repeatedly applying operator()
	///   results in advancing in the register.
	template <class B>
	struct RegisterOutput
	{
		RegisterOutput(byte *output, const byte *input, CipherDir dir)
			: m_output(output), m_input(input), m_dir(dir) {}

		/// \brief XOR feedback register with data
		/// \param registerWord data represented as a word type
		/// \return reference to the next feedback register word
		inline RegisterOutput& operator()(WordType &registerWord)
		{
			//CRYPTOPP_ASSERT(IsAligned<WordType>(m_output));
			//CRYPTOPP_ASSERT(IsAligned<WordType>(m_input));

			if (!NativeByteOrderIs(B::ToEnum()))
				registerWord = ByteReverse(registerWord);

			if (m_dir == ENCRYPTION)
			{
				if (m_input == NULLPTR)
				{
					CRYPTOPP_ASSERT(m_output == NULLPTR);
				}
				else
				{
					// WordType ct = *(const WordType *)m_input ^ registerWord;
					WordType ct = GetWord<WordType>(false, NativeByteOrder::ToEnum(), m_input) ^ registerWord;
					registerWord = ct;

					// *(WordType*)m_output = ct;
					PutWord<WordType>(false, NativeByteOrder::ToEnum(), m_output, ct);

					m_input += sizeof(WordType);
					m_output += sizeof(WordType);
				}
			}
			else
			{
				// WordType ct = *(const WordType *)m_input;
				WordType ct = GetWord<WordType>(false, NativeByteOrder::ToEnum(), m_input);

				// *(WordType*)m_output = registerWord ^ ct;
				PutWord<WordType>(false, NativeByteOrder::ToEnum(), m_output, registerWord ^ ct);
				registerWord = ct;

				m_input += sizeof(WordType);
				m_output += sizeof(WordType);
			}

			// registerWord is left unreversed so it can be xor-ed with further input

			return *this;
		}

		byte *m_output;
		const byte *m_input;
		CipherDir m_dir;
	};
};

/// \brief Base class for feedback based stream ciphers with SymmetricCipher interface
/// \tparam BASE AbstractPolicyHolder base class
template <class BASE>
class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE
{
public:
	virtual ~CFB_CipherTemplate() {}
	CFB_CipherTemplate() : m_leftOver(0) {}

	/// \brief Apply keystream to data
	/// \param outString a buffer to write the transformed data
	/// \param inString a buffer to read the data
	/// \param length the size of the buffers, in bytes
	/// \details This is the primary method to operate a stream cipher. For example:
	/// <pre>
	///     size_t size = 30;
	///     byte plain[size] = "Do or do not; there is no try";
	///     byte cipher[size];
	///     ...
	///     ChaCha20 chacha(key, keySize);
	///     chacha.ProcessData(cipher, plain, size);
	/// </pre>
	/// \details You should use distinct buffers for inString and outString. If the buffers
	///  are the same, then the data will be copied to an internal buffer to avoid GCC alias
	///  violations. The internal copy will impact performance.
	/// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/1088">Issue 1088, 36% loss
	///  of performance with AES</A>, <A HREF="https://github.com/weidai11/cryptopp/issues/1010">Issue
	///  1010, HIGHT cipher troubles with FileSource</A>
	void ProcessData(byte *outString, const byte *inString, size_t length);

	/// \brief Resynchronize the cipher
	/// \param iv a byte array used to resynchronize the cipher
	/// \param length the size of the IV array
	void Resynchronize(const byte *iv, int length=-1);

	/// \brief Provides number of ideal bytes to process
	/// \return the ideal number of bytes to process
	/// \details Internally, the default implementation returns GetBytesPerIteration()
	/// \sa GetBytesPerIteration() and GetOptimalNextBlockSize()
	unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();}

	/// \brief Provides number of ideal bytes to process
	/// \return the ideal number of bytes to process
	/// \details Internally, the default implementation returns remaining unprocessed bytes
	/// \sa GetBytesPerIteration() and OptimalBlockSize()
	unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;}

	/// \brief Provides number of ideal data alignment
	/// \return the ideal data alignment, in bytes
	/// \sa GetAlignment() and OptimalBlockSize()
	unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}

	/// \brief Flag indicating random access
	/// \return true if the cipher is seekable, false otherwise
	/// \sa Seek()
	bool IsRandomAccess() const {return false;}

	/// \brief Determines if the cipher is self inverting
	/// \return true if the stream cipher is self inverting, false otherwise
	bool IsSelfInverting() const {return false;}

	/// \brief Retrieve the provider of this algorithm
	/// \return the algorithm provider
	/// \details The algorithm provider can be a name like "C++", "SSE", "NEON", "AESNI",
	///  "ARMv8" and "Power8". C++ is standard C++ code. Other labels, like SSE,
	///  usually indicate a specialized implementation using instructions from a higher
	///  instruction set architecture (ISA). Future labels may include external hardware
	///  like a hardware security module (HSM).
	/// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2".
	///  Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics
	///  instead of ASM.
	/// \details Algorithms which combine different instructions or ISAs provide the
	///  dominant one. For example on x86 <tt>AES/GCM</tt> returns "AESNI" rather than
	///  "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL".
	/// \note Provider is not universally implemented yet.
	std::string AlgorithmProvider() const { return this->GetPolicy().AlgorithmProvider(); }

	typedef typename BASE::PolicyInterface PolicyInterface;

protected:
	virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) =0;

	void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);

	size_t m_leftOver;
};

/// \brief Base class for feedback based stream ciphers in the forward direction with SymmetricCipher interface
/// \tparam BASE AbstractPolicyHolder base class
template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE>
{
	bool IsForwardTransformation() const {return true;}
	void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
};

/// \brief Base class for feedback based stream ciphers in the reverse direction with SymmetricCipher interface
/// \tparam BASE AbstractPolicyHolder base class
template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE>
{
	bool IsForwardTransformation() const {return false;}
	void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
};

/// \brief Base class for feedback based stream ciphers with a mandatory block size
/// \tparam BASE CFB_EncryptionTemplate or CFB_DecryptionTemplate base class
template <class BASE>
class CFB_RequireFullDataBlocks : public BASE
{
public:
	unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();}
};

/// \brief SymmetricCipher implementation
/// \tparam BASE AbstractPolicyHolder derived base class
/// \tparam INFO AbstractPolicyHolder derived information class
/// \sa Weak::ARC4, ChaCha8, ChaCha12, ChaCha20, Salsa20, SEAL, Sosemanuk, WAKE
template <class BASE, class INFO = BASE>
class SymmetricCipherFinal : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
{
public:
	virtual ~SymmetricCipherFinal() {}

	/// \brief Construct a stream cipher
 	SymmetricCipherFinal() {}

	/// \brief Construct a stream cipher
	/// \param key a byte array used to key the cipher
	/// \details This overload uses DEFAULT_KEYLENGTH
	SymmetricCipherFinal(const byte *key)
		{this->SetKey(key, this->DEFAULT_KEYLENGTH);}

	/// \brief Construct a stream cipher
	/// \param key a byte array used to key the cipher
	/// \param length the size of the key array
	SymmetricCipherFinal(const byte *key, size_t length)
		{this->SetKey(key, length);}

	/// \brief Construct a stream cipher
	/// \param key a byte array used to key the cipher
	/// \param length the size of the key array
	/// \param iv a byte array used as an initialization vector
	SymmetricCipherFinal(const byte *key, size_t length, const byte *iv)
		{this->SetKeyWithIV(key, length, iv);}

	/// \brief Clone a SymmetricCipher
	/// \return a new SymmetricCipher based on this object
	Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinal<BASE, INFO>(*this));}
};

NAMESPACE_END

// Used by dll.cpp to ensure objects are in dll.o, and not strciphr.o.
#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
# include "strciphr.cpp"
#endif

NAMESPACE_BEGIN(CryptoPP)

CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher>;
CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >;

CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;

NAMESPACE_END

#if CRYPTOPP_MSC_VERSION
# pragma warning(pop)
#endif

#endif