~zooko/cryptopp/trunk

22 by weidai
fix whitespace problems
1
#ifndef CRYPTOPP_MODES_H
2
#define CRYPTOPP_MODES_H
1 by weidai
Initial revision
3
22 by weidai
fix whitespace problems
4
/*! \file
1 by weidai
Initial revision
5
*/
6
7
#include "cryptlib.h"
8
#include "secblock.h"
9
#include "misc.h"
10
#include "strciphr.h"
11
#include "argnames.h"
20 by weidai
add missing #include, and fix CounterMode typedef
12
#include "algparam.h"
1 by weidai
Initial revision
13
14
NAMESPACE_BEGIN(CryptoPP)
15
22 by weidai
fix whitespace problems
16
//! Cipher mode documentation. See NIST SP 800-38A for definitions of these modes.
1 by weidai
Initial revision
17
22 by weidai
fix whitespace problems
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.
1 by weidai
Initial revision
26
*/
22 by weidai
fix whitespace problems
27
struct CipherModeDocumentation : public SymmetricCipherDocumentation
1 by weidai
Initial revision
28
{
29
};
30
31
class CipherModeBase : public SymmetricCipher
32
{
33
public:
22 by weidai
fix whitespace problems
34
	unsigned int MinKeyLength() const {return m_cipher->MinKeyLength();}
35
	unsigned int MaxKeyLength() const {return m_cipher->MaxKeyLength();}
36
	unsigned int DefaultKeyLength() const {return m_cipher->DefaultKeyLength();}
37
	unsigned int GetValidKeyLength(unsigned int n) const {return m_cipher->GetValidKeyLength(n);}
38
	bool IsValidKeyLength(unsigned int n) const {return m_cipher->IsValidKeyLength(n);}
39
40
	void SetKey(const byte *key, unsigned int length, const NameValuePairs &params = g_nullNameValuePairs);
41
42
	unsigned int OptimalDataAlignment() const {return BlockSize();}
43
44
	unsigned int IVSize() const {return BlockSize();}
45
	void GetNextIV(byte *IV);
46
	virtual IV_Requirement IVRequirement() const =0;
1 by weidai
Initial revision
47
48
protected:
22 by weidai
fix whitespace problems
49
	inline unsigned int BlockSize() const {assert(m_register.size() > 0); return m_register.size();}
50
	virtual void SetFeedbackSize(unsigned int feedbackSize)
1 by weidai
Initial revision
51
	{
22 by weidai
fix whitespace problems
52
		if (!(feedbackSize == 0 || feedbackSize == BlockSize()))
53
			throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode");
1 by weidai
Initial revision
54
	}
22 by weidai
fix whitespace problems
55
	virtual void ResizeBuffers()
1 by weidai
Initial revision
56
	{
57
		m_register.New(m_cipher->BlockSize());
58
	}
42 by weidai
fix bugs in SEAL and Panama
59
	virtual void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv) =0;
1 by weidai
Initial revision
60
22 by weidai
fix whitespace problems
61
	BlockCipher *m_cipher;
1 by weidai
Initial revision
62
	SecByteBlock m_register;
63
};
64
22 by weidai
fix whitespace problems
65
template <class POLICY_INTERFACE>
66
class ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE
1 by weidai
Initial revision
67
{
22 by weidai
fix whitespace problems
68
	unsigned int GetAlignment() const {return m_cipher->BlockAlignment();}
69
	void CipherSetKey(const NameValuePairs &params, const byte *key, unsigned int length)
1 by weidai
Initial revision
70
	{
71
		m_cipher->SetKey(key, length, params);
72
		ResizeBuffers();
22 by weidai
fix whitespace problems
73
		int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0);
1 by weidai
Initial revision
74
		SetFeedbackSize(feedbackSize);
75
	}
76
};
77
78
class CFB_ModePolicy : public ModePolicyCommonTemplate<CFB_CipherAbstractPolicy>
79
{
80
public:
81
	IV_Requirement IVRequirement() const {return RANDOM_IV;}
82
83
protected:
22 by weidai
fix whitespace problems
84
	unsigned int GetBytesPerIteration() const {return m_feedbackSize;}
1 by weidai
Initial revision
85
	byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;}
86
	void TransformRegister()
87
	{
88
		m_cipher->ProcessBlock(m_register, m_temp);
22 by weidai
fix whitespace problems
89
		memmove(m_register, m_register+m_feedbackSize, BlockSize()-m_feedbackSize);
1 by weidai
Initial revision
90
		memcpy(m_register+BlockSize()-m_feedbackSize, m_temp, m_feedbackSize);
91
	}
22 by weidai
fix whitespace problems
92
	void CipherResynchronize(const byte *iv)
1 by weidai
Initial revision
93
	{
94
		memcpy(m_register, iv, BlockSize());
95
		TransformRegister();
96
	}
97
	void SetFeedbackSize(unsigned int feedbackSize)
98
	{
99
		if (feedbackSize > BlockSize())
100
			throw InvalidArgument("CFB_Mode: invalid feedback size");
22 by weidai
fix whitespace problems
101
		m_feedbackSize = feedbackSize ? feedbackSize : BlockSize();
1 by weidai
Initial revision
102
	}
103
	void ResizeBuffers()
104
	{
105
		CipherModeBase::ResizeBuffers();
106
		m_temp.New(BlockSize());
107
	}
108
109
	SecByteBlock m_temp;
110
	unsigned int m_feedbackSize;
111
};
112
42 by weidai
fix bugs in SEAL and Panama
113
inline void CopyOrZero(void *dest, const void *src, size_t s)
114
{
115
	if (src)
116
		memcpy(dest, src, s);
117
	else
118
		memset(dest, 0, s);
119
}
120
1 by weidai
Initial revision
121
class OFB_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
122
{
22 by weidai
fix whitespace problems
123
	unsigned int GetBytesPerIteration() const {return BlockSize();}
1 by weidai
Initial revision
124
	unsigned int GetIterationsToBuffer() const {return 1;}
22 by weidai
fix whitespace problems
125
	void WriteKeystream(byte *keystreamBuffer, unsigned int iterationCount)
1 by weidai
Initial revision
126
	{
127
		assert(iterationCount == 1);
128
		m_cipher->ProcessBlock(keystreamBuffer);
129
	}
22 by weidai
fix whitespace problems
130
	void CipherResynchronize(byte *keystreamBuffer, const byte *iv)
1 by weidai
Initial revision
131
	{
42 by weidai
fix bugs in SEAL and Panama
132
		CopyOrZero(keystreamBuffer, iv, BlockSize());
1 by weidai
Initial revision
133
	}
22 by weidai
fix whitespace problems
134
	bool IsRandomAccess() const {return false;}
1 by weidai
Initial revision
135
	IV_Requirement IVRequirement() const {return STRUCTURED_IV;}
136
};
137
138
class CTR_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
139
{
22 by weidai
fix whitespace problems
140
	unsigned int GetBytesPerIteration() const {return BlockSize();}
1 by weidai
Initial revision
141
	unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
142
	void WriteKeystream(byte *buffer, unsigned int iterationCount)
143
		{OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
144
	bool CanOperateKeystream() const {return true;}
22 by weidai
fix whitespace problems
145
	void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount);
146
	void CipherResynchronize(byte *keystreamBuffer, const byte *iv);
147
	bool IsRandomAccess() const {return true;}
1 by weidai
Initial revision
148
	void SeekToIteration(dword iterationCount);
149
	IV_Requirement IVRequirement() const {return STRUCTURED_IV;}
150
22 by weidai
fix whitespace problems
151
	inline void ProcessMultipleBlocks(byte *output, const byte *input, unsigned int n);
1 by weidai
Initial revision
152
153
	SecByteBlock m_counterArray;
154
};
155
22 by weidai
fix whitespace problems
156
class BlockOrientedCipherModeBase : public CipherModeBase
1 by weidai
Initial revision
157
{
158
public:
42 by weidai
fix bugs in SEAL and Panama
159
	void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv);
22 by weidai
fix whitespace problems
160
	unsigned int MandatoryBlockSize() const {return BlockSize();}
161
	bool IsRandomAccess() const {return false;}
1 by weidai
Initial revision
162
	bool IsSelfInverting() const {return false;}
163
	bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();}
164
	void Resynchronize(const byte *iv) {memcpy(m_register, iv, BlockSize());}
22 by weidai
fix whitespace problems
165
	void ProcessData(byte *outString, const byte *inString, unsigned int length);
1 by weidai
Initial revision
166
167
protected:
168
	bool RequireAlignedInput() const {return true;}
22 by weidai
fix whitespace problems
169
	virtual void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks) =0;
1 by weidai
Initial revision
170
	void ResizeBuffers()
171
	{
172
		CipherModeBase::ResizeBuffers();
173
		m_buffer.New(BlockSize());
174
	}
175
176
	SecByteBlock m_buffer;
177
};
178
179
class ECB_OneWay : public BlockOrientedCipherModeBase
180
{
181
public:
182
	IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;}
22 by weidai
fix whitespace problems
183
	unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();}
184
	void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks)
1 by weidai
Initial revision
185
		{m_cipher->ProcessAndXorMultipleBlocks(inString, NULL, outString, numberOfBlocks);}
186
};
187
22 by weidai
fix whitespace problems
188
class CBC_ModeBase : public BlockOrientedCipherModeBase
1 by weidai
Initial revision
189
{
190
public:
191
	IV_Requirement IVRequirement() const {return UNPREDICTABLE_RANDOM_IV;}
192
	bool RequireAlignedInput() const {return false;}
22 by weidai
fix whitespace problems
193
	unsigned int MinLastBlockSize() const {return 0;}
1 by weidai
Initial revision
194
};
195
196
class CBC_Encryption : public CBC_ModeBase
197
{
198
public:
22 by weidai
fix whitespace problems
199
	void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks);
1 by weidai
Initial revision
200
};
201
202
class CBC_CTS_Encryption : public CBC_Encryption
203
{
204
public:
205
	void SetStolenIV(byte *iv) {m_stolenIV = iv;}
22 by weidai
fix whitespace problems
206
	unsigned int MinLastBlockSize() const {return BlockSize()+1;}
6 by weidai
make CTS functions public
207
	void ProcessLastBlock(byte *outString, const byte *inString, unsigned int length);
1 by weidai
Initial revision
208
209
protected:
42 by weidai
fix bugs in SEAL and Panama
210
	void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv)
1 by weidai
Initial revision
211
	{
42 by weidai
fix bugs in SEAL and Panama
212
		CBC_Encryption::UncheckedSetKey(params, key, length, iv);
22 by weidai
fix whitespace problems
213
		m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULL);
1 by weidai
Initial revision
214
	}
215
216
	byte *m_stolenIV;
217
};
218
219
class CBC_Decryption : public CBC_ModeBase
220
{
221
public:
22 by weidai
fix whitespace problems
222
	void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks);
1 by weidai
Initial revision
223
	
224
protected:
225
	void ResizeBuffers()
226
	{
227
		BlockOrientedCipherModeBase::ResizeBuffers();
228
		m_temp.New(BlockSize());
229
	}
230
	SecByteBlock m_temp;
231
};
232
233
class CBC_CTS_Decryption : public CBC_Decryption
234
{
6 by weidai
make CTS functions public
235
public:
22 by weidai
fix whitespace problems
236
	unsigned int MinLastBlockSize() const {return BlockSize()+1;}
1 by weidai
Initial revision
237
	void ProcessLastBlock(byte *outString, const byte *inString, unsigned int length);
238
};
239
22 by weidai
fix whitespace problems
240
//! .
241
template <class CIPHER, class BASE>
242
class CipherModeFinalTemplate_CipherHolder : public ObjectHolder<CIPHER>, public BASE
1 by weidai
Initial revision
243
{
244
public:
245
	CipherModeFinalTemplate_CipherHolder()
246
	{
247
		m_cipher = &m_object;
248
		ResizeBuffers();
249
	}
22 by weidai
fix whitespace problems
250
	CipherModeFinalTemplate_CipherHolder(const byte *key, unsigned int length)
1 by weidai
Initial revision
251
	{
252
		m_cipher = &m_object;
22 by weidai
fix whitespace problems
253
		SetKey(key, length);
1 by weidai
Initial revision
254
	}
22 by weidai
fix whitespace problems
255
	CipherModeFinalTemplate_CipherHolder(const byte *key, unsigned int length, const byte *iv, int feedbackSize = 0)
1 by weidai
Initial revision
256
	{
257
		m_cipher = &m_object;
42 by weidai
fix bugs in SEAL and Panama
258
		SetKey(key, length, MakeParameters(Name::IV(), iv)(Name::FeedbackSize(), feedbackSize));
1 by weidai
Initial revision
259
	}
260
};
261
22 by weidai
fix whitespace problems
262
//! .
263
template <class BASE>
1 by weidai
Initial revision
264
class CipherModeFinalTemplate_ExternalCipher : public BASE
265
{
266
public:
42 by weidai
fix bugs in SEAL and Panama
267
	CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher)
268
	{
269
		ThrowIfResynchronizable();
270
		m_cipher = &cipher;
271
		ResizeBuffers();
272
	}
273
274
	CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv, int feedbackSize = 0)
275
	{
276
		ThrowIfInvalidIV(iv);
1 by weidai
Initial revision
277
		m_cipher = &cipher;
278
		ResizeBuffers();
279
		SetFeedbackSize(feedbackSize);
42 by weidai
fix bugs in SEAL and Panama
280
		if (IsResynchronizable())
281
			Resynchronize(iv);
1 by weidai
Initial revision
282
	}
283
};
284
22 by weidai
fix whitespace problems
285
//! CFB mode
286
template <class CIPHER>
287
struct CFB_Mode : public CipherModeDocumentation
288
{
289
	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
290
	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
291
};
292
293
//! CFB mode, external cipher
294
struct CFB_Mode_ExternalCipher : public CipherModeDocumentation
295
{
296
	typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
297
	typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
298
};
299
300
//! OFB mode
301
template <class CIPHER>
302
struct OFB_Mode : public CipherModeDocumentation
303
{
304
	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
305
	typedef Encryption Decryption;
306
};
307
308
//! OFB mode, external cipher
309
struct OFB_Mode_ExternalCipher : public CipherModeDocumentation
310
{
311
	typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
312
	typedef Encryption Decryption;
313
};
314
315
//! CTR mode
316
template <class CIPHER>
317
struct CTR_Mode : public CipherModeDocumentation
318
{
319
	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
320
	typedef Encryption Decryption;
321
};
322
323
//! CTR mode, external cipher
324
struct CTR_Mode_ExternalCipher : public CipherModeDocumentation
325
{
326
	typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
327
	typedef Encryption Decryption;
328
};
329
330
//! ECB mode
331
template <class CIPHER>
332
struct ECB_Mode : public CipherModeDocumentation
333
{
334
	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ECB_OneWay> Encryption;
335
	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, ECB_OneWay> Decryption;
336
};
337
338
//! ECB mode, external cipher
339
struct ECB_Mode_ExternalCipher : public CipherModeDocumentation
340
{
341
	typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption;
342
	typedef Encryption Decryption;
343
};
344
345
//! CBC mode
346
template <class CIPHER>
347
struct CBC_Mode : public CipherModeDocumentation
348
{
349
	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_Encryption> Encryption;
350
	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_Decryption> Decryption;
351
};
352
353
//! CBC mode, external cipher
354
struct CBC_Mode_ExternalCipher : public CipherModeDocumentation
355
{
356
	typedef CipherModeFinalTemplate_ExternalCipher<CBC_Encryption> Encryption;
357
	typedef CipherModeFinalTemplate_ExternalCipher<CBC_Decryption> Decryption;
358
};
359
360
//! CBC mode with ciphertext stealing
361
template <class CIPHER>
362
struct CBC_CTS_Mode : public CipherModeDocumentation
363
{
364
	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_CTS_Encryption> Encryption;
365
	typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_CTS_Decryption> Decryption;
366
};
367
368
//! CBC mode with ciphertext stealing, external cipher
369
struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation
370
{
371
	typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption> Encryption;
372
	typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption;
1 by weidai
Initial revision
373
};
374
375
#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
22 by weidai
fix whitespace problems
376
typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption;
377
typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption;
378
typedef OFB_Mode_ExternalCipher::Encryption OFB;
379
typedef CTR_Mode_ExternalCipher::Encryption CounterMode;
1 by weidai
Initial revision
380
#endif
381
382
NAMESPACE_END
383
384
#endif