1/*! \file
2 	This file contains helper classes for implementing stream ciphers.
3
4	All this infrastructure may look very complex compared to what's in Crypto++ 4.x,
5	but stream ciphers implementations now support a lot of new functionality,
6	including better performance (minimizing copying), resetting of keys and IVs, and methods to
7	query which features are supported by a cipher.
8
9	Here's an explanation of these classes. The word "policy" is used here to mean a class with a
10	set of methods that must be implemented by individual stream cipher implementations.
11	This is usually much simpler than the full stream cipher API, which is implemented by
12	either AdditiveCipherTemplate or CFB_CipherTemplate using the policy. So for example, an
13	implementation of SEAL only needs to implement the AdditiveCipherAbstractPolicy interface
14	(since it's an additive cipher, i.e., it xors a keystream into the plaintext).
15	See this line in seal.h:
16
17	typedef SymmetricCipherFinal\<ConcretePolicyHolder\<SEAL_Policy\<B\>, AdditiveCipherTemplate\<\> \> \> Encryption;
18
19	AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't need
20	to take a policy class as a template parameter (although this is allowed), so that
21	their code is not duplicated for each new cipher. Instead they each
22	get a reference to an abstract policy interface by calling AccessPolicy() on itself, so
23	AccessPolicy() must be overriden to return the actual policy reference. This is done
24	by the ConceretePolicyHolder class. Finally, SymmetricCipherFinal implements the constructors and
25	other functions that must be implemented by the most derived class.
26*/
27
28#ifndef CRYPTOPP_STRCIPHR_H
29#define CRYPTOPP_STRCIPHR_H
30
31#include "seckey.h"
32#include "secblock.h"
33#include "argnames.h"
34
35NAMESPACE_BEGIN(CryptoPP)
36
37template <class POLICY_INTERFACE, class BASE = Empty>
38class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE
39{
40public:
41	typedef POLICY_INTERFACE PolicyInterface;
42	virtual ~AbstractPolicyHolder() {}
43
44protected:
45	virtual const POLICY_INTERFACE & GetPolicy() const =0;
46	virtual POLICY_INTERFACE & AccessPolicy() =0;
47};
48
49template <class POLICY, class BASE, class POLICY_INTERFACE = CPP_TYPENAME BASE::PolicyInterface>
50class ConcretePolicyHolder : public BASE, protected POLICY
51{
52protected:
53	const POLICY_INTERFACE & GetPolicy() const {return *this;}
54	POLICY_INTERFACE & AccessPolicy() {return *this;}
55};
56
57enum KeystreamOperationFlags {OUTPUT_ALIGNED=1, INPUT_ALIGNED=2, INPUT_NULL = 4};
58enum KeystreamOperation {
59	WRITE_KEYSTREAM				= INPUT_NULL,
60	WRITE_KEYSTREAM_ALIGNED		= INPUT_NULL | OUTPUT_ALIGNED,
61	XOR_KEYSTREAM				= 0,
62	XOR_KEYSTREAM_INPUT_ALIGNED = INPUT_ALIGNED,
63	XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED,
64	XOR_KEYSTREAM_BOTH_ALIGNED	= OUTPUT_ALIGNED | INPUT_ALIGNED};
65
66struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy
67{
68	virtual ~AdditiveCipherAbstractPolicy() {}
69	virtual unsigned int GetAlignment() const {return 1;}
70	virtual unsigned int GetBytesPerIteration() const =0;
71	virtual unsigned int GetOptimalBlockSize() const {return GetBytesPerIteration();}
72	virtual unsigned int GetIterationsToBuffer() const =0;
73	virtual void WriteKeystream(byte *keystream, size_t iterationCount)
74		{OperateKeystream(KeystreamOperation(INPUT_NULL | (KeystreamOperationFlags)IsAlignedOn(keystream, GetAlignment())), keystream, NULL, iterationCount);}
75	virtual bool CanOperateKeystream() const {return false;}
76	virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) {assert(false);}
77	virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
78	virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
79	virtual bool CipherIsRandomAccess() const =0;
80	virtual void SeekToIteration(lword iterationCount) {assert(!CipherIsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");}
81};
82
83template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy>
84struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE
85{
86	typedef WT WordType;
87	CRYPTOPP_CONSTANT(BYTES_PER_ITERATION = sizeof(WordType) * W)
88
89#if !(CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64)
90	unsigned int GetAlignment() const {return GetAlignmentOf<WordType>();}
91#endif
92	unsigned int GetBytesPerIteration() const {return BYTES_PER_ITERATION;}
93	unsigned int GetIterationsToBuffer() const {return X;}
94	bool CanOperateKeystream() const {return true;}
95	virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0;
96};
97
98// use these to implement OperateKeystream
99#define CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, b, i, a)	\
100	PutWord(bool(x & OUTPUT_ALIGNED), b, output+i*sizeof(WordType), (x & INPUT_NULL) ? a : a ^ GetWord<WordType>(bool(x & INPUT_ALIGNED), b, input+i*sizeof(WordType)));
101#define CRYPTOPP_KEYSTREAM_OUTPUT_XMM(x, i, a)	{\
102	__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));\
103	if (x & OUTPUT_ALIGNED) _mm_store_si128((__m128i *)output+i, t);\
104	else _mm_storeu_si128((__m128i *)output+i, t);}
105#define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y)	\
106	switch (operation)							\
107	{											\
108		case WRITE_KEYSTREAM:					\
109			x(WRITE_KEYSTREAM)					\
110			break;								\
111		case XOR_KEYSTREAM:						\
112			x(XOR_KEYSTREAM)					\
113			input += y;							\
114			break;								\
115		case XOR_KEYSTREAM_INPUT_ALIGNED:		\
116			x(XOR_KEYSTREAM_INPUT_ALIGNED)		\
117			input += y;							\
118			break;								\
119		case XOR_KEYSTREAM_OUTPUT_ALIGNED:		\
120			x(XOR_KEYSTREAM_OUTPUT_ALIGNED)		\
121			input += y;							\
122			break;								\
123		case WRITE_KEYSTREAM_ALIGNED:			\
124			x(WRITE_KEYSTREAM_ALIGNED)			\
125			break;								\
126		case XOR_KEYSTREAM_BOTH_ALIGNED:		\
127			x(XOR_KEYSTREAM_BOTH_ALIGNED)		\
128			input += y;							\
129			break;								\
130	}											\
131	output += y;
132
133template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >
134class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE, public RandomNumberGenerator
135{
136public:
137	void GenerateBlock(byte *output, size_t size);
138    void ProcessData(byte *outString, const byte *inString, size_t length);
139	void Resynchronize(const byte *iv, int length=-1);
140	unsigned int OptimalBlockSize() const {return this->GetPolicy().GetOptimalBlockSize();}
141	unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;}
142	unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
143	bool IsSelfInverting() const {return true;}
144	bool IsForwardTransformation() const {return true;}
145	bool IsRandomAccess() const {return this->GetPolicy().CipherIsRandomAccess();}
146	void Seek(lword position);
147
148	typedef typename BASE::PolicyInterface PolicyInterface;
149
150protected:
151	void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
152
153	unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();}
154
155	inline byte * KeystreamBufferBegin() {return this->m_buffer.data();}
156	inline byte * KeystreamBufferEnd() {return (this->m_buffer.data() + this->m_buffer.size());}
157
158	SecByteBlock m_buffer;
159	size_t m_leftOver;
160};
161
162class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy
163{
164public:
165	virtual ~CFB_CipherAbstractPolicy() {}
166	virtual unsigned int GetAlignment() const =0;
167	virtual unsigned int GetBytesPerIteration() const =0;
168	virtual byte * GetRegisterBegin() =0;
169	virtual void TransformRegister() =0;
170	virtual bool CanIterate() const {return false;}
171	virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) {assert(false); throw 0;}
172	virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
173	virtual void CipherResynchronize(const byte *iv, size_t length) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
174};
175
176template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy>
177struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE
178{
179	typedef WT WordType;
180
181	unsigned int GetAlignment() const {return sizeof(WordType);}
182	unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
183	bool CanIterate() const {return true;}
184	void TransformRegister() {this->Iterate(NULL, NULL, ENCRYPTION, 1);}
185
186	template <class B>
187	struct RegisterOutput
188	{
189		RegisterOutput(byte *output, const byte *input, CipherDir dir)
190			: m_output(output), m_input(input), m_dir(dir) {}
191
192		inline RegisterOutput& operator()(WordType &registerWord)
193		{
194			assert(IsAligned<WordType>(m_output));
195			assert(IsAligned<WordType>(m_input));
196
197			if (!NativeByteOrderIs(B::ToEnum()))
198				registerWord = ByteReverse(registerWord);
199
200			if (m_dir == ENCRYPTION)
201			{
202				if (m_input == NULL)
203					assert(m_output == NULL);
204				else
205				{
206					WordType ct = *(const WordType *)m_input ^ registerWord;
207					registerWord = ct;
208					*(WordType*)m_output = ct;
209					m_input += sizeof(WordType);
210					m_output += sizeof(WordType);
211				}
212			}
213			else
214			{
215				WordType ct = *(const WordType *)m_input;
216				*(WordType*)m_output = registerWord ^ ct;
217				registerWord = ct;
218				m_input += sizeof(WordType);
219				m_output += sizeof(WordType);
220			}
221
222			// registerWord is left unreversed so it can be xor-ed with further input
223
224			return *this;
225		}
226
227		byte *m_output;
228		const byte *m_input;
229		CipherDir m_dir;
230	};
231};
232
233template <class BASE>
234class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE
235{
236public:
237	void ProcessData(byte *outString, const byte *inString, size_t length);
238	void Resynchronize(const byte *iv, int length=-1);
239	unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();}
240	unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;}
241	unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
242	bool IsRandomAccess() const {return false;}
243	bool IsSelfInverting() const {return false;}
244
245	typedef typename BASE::PolicyInterface PolicyInterface;
246
247protected:
248	virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) =0;
249
250	void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
251
252	size_t m_leftOver;
253};
254
255template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
256class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE>
257{
258	bool IsForwardTransformation() const {return true;}
259	void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
260};
261
262template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
263class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE>
264{
265	bool IsForwardTransformation() const {return false;}
266	void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
267};
268
269template <class BASE>
270class CFB_RequireFullDataBlocks : public BASE
271{
272public:
273	unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();}
274};
275
276//! _
277template <class BASE, class INFO = BASE>
278class SymmetricCipherFinal : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
279{
280public:
281 	SymmetricCipherFinal() {}
282	SymmetricCipherFinal(const byte *key)
283		{this->SetKey(key, this->DEFAULT_KEYLENGTH);}
284	SymmetricCipherFinal(const byte *key, size_t length)
285		{this->SetKey(key, length);}
286	SymmetricCipherFinal(const byte *key, size_t length, const byte *iv)
287		{this->SetKeyWithIV(key, length, iv);}
288
289	Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinal<BASE, INFO>(*this));}
290};
291
292NAMESPACE_END
293
294#ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
295#include "strciphr.cpp"
296#endif
297
298NAMESPACE_BEGIN(CryptoPP)
299CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher>;
300CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >;
301CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
302CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
303CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
304NAMESPACE_END
305
306#endif
307