1#ifndef CRYPTOPP_MODES_H
2#define CRYPTOPP_MODES_H
3
4/*! \file
5*/
6
7#include "cryptlib.h"
8#include "secblock.h"
9#include "misc.h"
10#include "strciphr.h"
11#include "argnames.h"
12#include "algparam.h"
13
14NAMESPACE_BEGIN(CryptoPP)
15
16//! Cipher modes documentation. See NIST SP 800-38A for definitions of these modes. See AuthenticatedSymmetricCipherDocumentation for authenticated encryption modes.
17
18/*! Each class derived from this one defines two types, Encryption and Decryption,
19	both of which implement the SymmetricCipher interface.
20	For each mode there are two classes, one of which is a template class,
21	and the other one has a name that ends in "_ExternalCipher".
22	The "external cipher" mode objects hold a reference to the underlying block cipher,
23	instead of holding an instance of it. The reference must be passed in to the constructor.
24	For the "cipher holder" classes, the CIPHER template parameter should be a class
25	derived from BlockCipherDocumentation, for example DES or AES.
26*/
27struct CipherModeDocumentation : public SymmetricCipherDocumentation
28{
29};
30
31class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CipherModeBase : public SymmetricCipher
32{
33public:
34	size_t MinKeyLength() const {return m_cipher->MinKeyLength();}
35	size_t MaxKeyLength() const {return m_cipher->MaxKeyLength();}
36	size_t DefaultKeyLength() const {return m_cipher->DefaultKeyLength();}
37	size_t GetValidKeyLength(size_t n) const {return m_cipher->GetValidKeyLength(n);}
38	bool IsValidKeyLength(size_t n) const {return m_cipher->IsValidKeyLength(n);}
39
40	unsigned int OptimalDataAlignment() const {return m_cipher->OptimalDataAlignment();}
41
42	unsigned int IVSize() const {return BlockSize();}
43	virtual IV_Requirement IVRequirement() const =0;
44
45	void SetCipher(BlockCipher &cipher)
46	{
47		this->ThrowIfResynchronizable();
48		this->m_cipher = &cipher;
49		this->ResizeBuffers();
50	}
51
52	void SetCipherWithIV(BlockCipher &cipher, const byte *iv, int feedbackSize = 0)
53	{
54		this->ThrowIfInvalidIV(iv);
55		this->m_cipher = &cipher;
56		this->ResizeBuffers();
57		this->SetFeedbackSize(feedbackSize);
58		if (this->IsResynchronizable())
59			this->Resynchronize(iv);
60	}
61
62protected:
63	CipherModeBase() : m_cipher(NULL) {}
64	inline unsigned int BlockSize() const {assert(m_register.size() > 0); return (unsigned int)m_register.size();}
65	virtual void SetFeedbackSize(unsigned int feedbackSize)
66	{
67		if (!(feedbackSize == 0 || feedbackSize == BlockSize()))
68			throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode");
69	}
70	virtual void ResizeBuffers()
71	{
72		m_register.New(m_cipher->BlockSize());
73	}
74
75	BlockCipher *m_cipher;
76	AlignedSecByteBlock m_register;
77};
78
79template <class POLICY_INTERFACE>
80class CRYPTOPP_NO_VTABLE ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE
81{
82	unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();}
83	void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length);
84};
85
86template <class POLICY_INTERFACE>
87void ModePolicyCommonTemplate<POLICY_INTERFACE>::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
88{
89	m_cipher->SetKey(key, length, params);
90	ResizeBuffers();
91	int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0);
92	SetFeedbackSize(feedbackSize);
93}
94
95class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_ModePolicy : public ModePolicyCommonTemplate<CFB_CipherAbstractPolicy>
96{
97public:
98	IV_Requirement IVRequirement() const {return RANDOM_IV;}
99	static const char * CRYPTOPP_API StaticAlgorithmName() {return "CFB";}
100
101protected:
102	unsigned int GetBytesPerIteration() const {return m_feedbackSize;}
103	byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;}
104	bool CanIterate() const {return m_feedbackSize == BlockSize();}
105	void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount);
106	void TransformRegister();
107	void CipherResynchronize(const byte *iv, size_t length);
108	void SetFeedbackSize(unsigned int feedbackSize);
109	void ResizeBuffers();
110
111	SecByteBlock m_temp;
112	unsigned int m_feedbackSize;
113};
114
115inline void CopyOrZero(void *dest, const void *src, size_t s)
116{
117	if (src)
118		memcpy_s(dest, s, src, s);
119	else
120		memset(dest, 0, s);
121}
122
123class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE OFB_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
124{
125public:
126	bool CipherIsRandomAccess() const {return false;}
127	IV_Requirement IVRequirement() const {return UNIQUE_IV;}
128	static const char * CRYPTOPP_API StaticAlgorithmName() {return "OFB";}
129
130private:
131	unsigned int GetBytesPerIteration() const {return BlockSize();}
132	unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
133	void WriteKeystream(byte *keystreamBuffer, size_t iterationCount);
134	void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
135};
136
137class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CTR_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
138{
139public:
140	bool CipherIsRandomAccess() const {return true;}
141	IV_Requirement IVRequirement() const {return RANDOM_IV;}
142	static const char * CRYPTOPP_API StaticAlgorithmName() {return "CTR";}
143
144protected:
145	virtual void IncrementCounterBy256();
146
147	unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();}
148	unsigned int GetBytesPerIteration() const {return BlockSize();}
149	unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
150	void WriteKeystream(byte *buffer, size_t iterationCount)
151		{OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
152	bool CanOperateKeystream() const {return true;}
153	void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
154	void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length);
155	void SeekToIteration(lword iterationCount);
156
157	AlignedSecByteBlock m_counterArray;
158};
159
160class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockOrientedCipherModeBase : public CipherModeBase
161{
162public:
163	void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
164	unsigned int MandatoryBlockSize() const {return BlockSize();}
165	bool IsRandomAccess() const {return false;}
166	bool IsSelfInverting() const {return false;}
167	bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();}
168	void Resynchronize(const byte *iv, int length=-1) {memcpy_s(m_register, m_register.size(), iv, ThrowIfInvalidIVLength(length));}
169
170protected:
171	bool RequireAlignedInput() const {return true;}
172	void ResizeBuffers()
173	{
174		CipherModeBase::ResizeBuffers();
175		m_buffer.New(BlockSize());
176	}
177
178	SecByteBlock m_buffer;
179};
180
181class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ECB_OneWay : public BlockOrientedCipherModeBase
182{
183public:
184	void SetKey(const byte *key, size_t length, const NameValuePairs &params = g_nullNameValuePairs)
185		{m_cipher->SetKey(key, length, params); BlockOrientedCipherModeBase::ResizeBuffers();}
186	IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;}
187	unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();}
188	void ProcessData(byte *outString, const byte *inString, size_t length);
189	static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECB";}
190};
191
192class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_ModeBase : public BlockOrientedCipherModeBase
193{
194public:
195	IV_Requirement IVRequirement() const {return UNPREDICTABLE_RANDOM_IV;}
196	bool RequireAlignedInput() const {return false;}
197	unsigned int MinLastBlockSize() const {return 0;}
198	static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC";}
199};
200
201class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Encryption : public CBC_ModeBase
202{
203public:
204	void ProcessData(byte *outString, const byte *inString, size_t length);
205};
206
207class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Encryption : public CBC_Encryption
208{
209public:
210	void SetStolenIV(byte *iv) {m_stolenIV = iv;}
211	unsigned int MinLastBlockSize() const {return BlockSize()+1;}
212	void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
213	static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC/CTS";}
214
215protected:
216	void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params)
217	{
218		CBC_Encryption::UncheckedSetKey(key, length, params);
219		m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULL);
220	}
221
222	byte *m_stolenIV;
223};
224
225class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Decryption : public CBC_ModeBase
226{
227public:
228	void ProcessData(byte *outString, const byte *inString, size_t length);
229
230protected:
231	void ResizeBuffers()
232	{
233		BlockOrientedCipherModeBase::ResizeBuffers();
234		m_temp.New(BlockSize());
235	}
236	AlignedSecByteBlock m_temp;
237};
238
239class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Decryption : public CBC_Decryption
240{
241public:
242	unsigned int MinLastBlockSize() const {return BlockSize()+1;}
243	void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
244};
245
246//! _
247template <class CIPHER, class BASE>
248class CipherModeFinalTemplate_CipherHolder : protected ObjectHolder<CIPHER>, public AlgorithmImpl<BASE, CipherModeFinalTemplate_CipherHolder<CIPHER, BASE> >
249{
250public:
251	CipherModeFinalTemplate_CipherHolder()
252	{
253		this->m_cipher = &this->m_object;
254		this->ResizeBuffers();
255	}
256	CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length)
257	{
258		this->m_cipher = &this->m_object;
259		this->SetKey(key, length);
260	}
261	CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv)
262	{
263		this->m_cipher = &this->m_object;
264		this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize())));
265	}
266	CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv, int feedbackSize)
267	{
268		this->m_cipher = &this->m_object;
269		this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize()))(Name::FeedbackSize(), feedbackSize));
270	}
271
272	static std::string CRYPTOPP_API StaticAlgorithmName()
273		{return CIPHER::StaticAlgorithmName() + "/" + BASE::StaticAlgorithmName();}
274};
275
276//! _
277template <class BASE>
278class CipherModeFinalTemplate_ExternalCipher : public BASE
279{
280public:
281	CipherModeFinalTemplate_ExternalCipher() {}
282	CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher)
283		{this->SetCipher(cipher);}
284	CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv, int feedbackSize = 0)
285		{this->SetCipherWithIV(cipher, iv, feedbackSize);}
286
287	std::string AlgorithmName() const
288		{return (this->m_cipher ? this->m_cipher->AlgorithmName() + "/" : std::string("")) + BASE::StaticAlgorithmName();}
289};
290
291CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
292CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
293CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
294
295//! CFB mode
296template <class CIPHER>
297struct CFB_Mode : public CipherModeDocumentation
298{
299	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
300	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
301};
302
303//! CFB mode, external cipher
304struct CFB_Mode_ExternalCipher : public CipherModeDocumentation
305{
306	typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
307	typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
308};
309
310//! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A
311template <class CIPHER>
312struct CFB_FIPS_Mode : public CipherModeDocumentation
313{
314	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Encryption;
315	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Decryption;
316};
317
318//! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A, external cipher
319struct CFB_FIPS_Mode_ExternalCipher : public CipherModeDocumentation
320{
321	typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Encryption;
322	typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Decryption;
323};
324
325CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> >;
326
327//! OFB mode
328template <class CIPHER>
329struct OFB_Mode : public CipherModeDocumentation
330{
331	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
332	typedef Encryption Decryption;
333};
334
335//! OFB mode, external cipher
336struct OFB_Mode_ExternalCipher : public CipherModeDocumentation
337{
338	typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
339	typedef Encryption Decryption;
340};
341
342CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> >;
343
344//! CTR mode
345template <class CIPHER>
346struct CTR_Mode : public CipherModeDocumentation
347{
348	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
349	typedef Encryption Decryption;
350};
351
352//! CTR mode, external cipher
353struct CTR_Mode_ExternalCipher : public CipherModeDocumentation
354{
355	typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
356	typedef Encryption Decryption;
357};
358
359//! ECB mode
360template <class CIPHER>
361struct ECB_Mode : public CipherModeDocumentation
362{
363	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ECB_OneWay> Encryption;
364	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, ECB_OneWay> Decryption;
365};
366
367CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<ECB_OneWay>;
368
369//! ECB mode, external cipher
370struct ECB_Mode_ExternalCipher : public CipherModeDocumentation
371{
372	typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption;
373	typedef Encryption Decryption;
374};
375
376//! CBC mode
377template <class CIPHER>
378struct CBC_Mode : public CipherModeDocumentation
379{
380	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_Encryption> Encryption;
381	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_Decryption> Decryption;
382};
383
384CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Encryption>;
385CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Decryption>;
386
387//! CBC mode, external cipher
388struct CBC_Mode_ExternalCipher : public CipherModeDocumentation
389{
390	typedef CipherModeFinalTemplate_ExternalCipher<CBC_Encryption> Encryption;
391	typedef CipherModeFinalTemplate_ExternalCipher<CBC_Decryption> Decryption;
392};
393
394//! CBC mode with ciphertext stealing
395template <class CIPHER>
396struct CBC_CTS_Mode : public CipherModeDocumentation
397{
398	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_CTS_Encryption> Encryption;
399	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_CTS_Decryption> Decryption;
400};
401
402CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption>;
403CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption>;
404
405//! CBC mode with ciphertext stealing, external cipher
406struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation
407{
408	typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption> Encryption;
409	typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption;
410};
411
412#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
413typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption;
414typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption;
415typedef OFB_Mode_ExternalCipher::Encryption OFB;
416typedef CTR_Mode_ExternalCipher::Encryption CounterMode;
417#endif
418
419NAMESPACE_END
420
421#endif
422