Crypto++
modes.h
Go to the documentation of this file.
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 
14 NAMESPACE_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 */
28 {
29 };
30 
31 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CipherModeBase : public SymmetricCipher
32 {
33 public:
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 
62 protected:
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 
79 template <class POLICY_INTERFACE>
80 class 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 
86 template <class POLICY_INTERFACE>
87 void 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 
95 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_ModePolicy : public ModePolicyCommonTemplate<CFB_CipherAbstractPolicy>
96 {
97 public:
98  IV_Requirement IVRequirement() const {return RANDOM_IV;}
99  static const char * CRYPTOPP_API StaticAlgorithmName() {return "CFB";}
100 
101 protected:
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 
115 inline 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 
123 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE OFB_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
124 {
125 public:
126  bool CipherIsRandomAccess() const {return false;}
127  IV_Requirement IVRequirement() const {return UNIQUE_IV;}
128  static const char * CRYPTOPP_API StaticAlgorithmName() {return "OFB";}
129 
130 private:
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 
137 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CTR_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
138 {
139 public:
140  bool CipherIsRandomAccess() const {return true;}
141  IV_Requirement IVRequirement() const {return RANDOM_IV;}
142  static const char * CRYPTOPP_API StaticAlgorithmName() {return "CTR";}
143 
144 protected:
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 
160 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockOrientedCipherModeBase : public CipherModeBase
161 {
162 public:
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 
170 protected:
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 
181 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ECB_OneWay : public BlockOrientedCipherModeBase
182 {
183 public:
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 
192 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_ModeBase : public BlockOrientedCipherModeBase
193 {
194 public:
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 
201 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Encryption : public CBC_ModeBase
202 {
203 public:
204  void ProcessData(byte *outString, const byte *inString, size_t length);
205 };
206 
207 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Encryption : public CBC_Encryption
208 {
209 public:
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 
215 protected:
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 
225 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Decryption : public CBC_ModeBase
226 {
227 public:
228  void ProcessData(byte *outString, const byte *inString, size_t length);
229 
230 protected:
231  void ResizeBuffers()
232  {
233  BlockOrientedCipherModeBase::ResizeBuffers();
234  m_temp.New(BlockSize());
235  }
236  AlignedSecByteBlock m_temp;
237 };
238 
239 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Decryption : public CBC_Decryption
240 {
241 public:
242  unsigned int MinLastBlockSize() const {return BlockSize()+1;}
243  void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
244 };
245 
246 //! _
247 template <class CIPHER, class BASE>
248 class CipherModeFinalTemplate_CipherHolder : protected ObjectHolder<CIPHER>, public AlgorithmImpl<BASE, CipherModeFinalTemplate_CipherHolder<CIPHER, BASE> >
249 {
250 public:
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 //! _
277 template <class BASE>
279 {
280 public:
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 
294 
295 //! CFB mode
296 template <class CIPHER>
298 {
301 };
302 
303 //! CFB mode, external cipher
305 {
308 };
309 
310 //! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A
311 template <class CIPHER>
313 {
316 };
317 
318 //! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A, external cipher
320 {
323 };
324 
326 
327 //! OFB mode
328 template <class CIPHER>
330 {
332  typedef Encryption Decryption;
333 };
334 
335 //! OFB mode, external cipher
337 {
339  typedef Encryption Decryption;
340 };
341 
344 
345 //! CTR mode
346 template <class CIPHER>
348 {
350  typedef Encryption Decryption;
351 };
352 
353 //! CTR mode, external cipher
355 {
356  typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
357  typedef Encryption Decryption;
358 };
359 
360 //! ECB mode
361 template <class CIPHER>
363 {
366 };
367 
368 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<ECB_OneWay>;
369 
370 //! ECB mode, external cipher
372 {
373  typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption;
374  typedef Encryption Decryption;
375 };
376 
377 //! CBC mode
378 template <class CIPHER>
380 {
383 };
384 
387 
388 //! CBC mode, external cipher
390 {
391  typedef CipherModeFinalTemplate_ExternalCipher<CBC_Encryption> Encryption;
392  typedef CipherModeFinalTemplate_ExternalCipher<CBC_Decryption> Decryption;
393 };
394 
395 //! CBC mode with ciphertext stealing
396 template <class CIPHER>
398 {
401 };
402 
405 
406 //! CBC mode with ciphertext stealing, external cipher
408 {
409  typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption> Encryption;
410  typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption;
411 };
412 
413 #ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
414 typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption;
415 typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption;
417 typedef CTR_Mode_ExternalCipher::Encryption CounterMode;
418 #endif
419 
420 NAMESPACE_END
421 
422 #endif
bool IsSelfInverting() const
returns whether this transformation is self-inverting (e.g. xor with a keystream) ...
Definition: modes.h:166
used to pass byte array input as part of a NameValuePairs object
Definition: algparam.h:13
exception thrown when an invalid argument is detected
Definition: cryptlib.h:144
const char * FeedbackSize()
int
Definition: argnames.h:19
void Resynchronize(const byte *iv, int length=-1)
resynchronize with an IV. ivLength=-1 means use IVSize()
Definition: modes.h:168
size_t GetValidKeyLength(size_t n) const
returns the smallest valid key length in bytes that is >= min(n, GetMaxKeyLength()) ...
Definition: modes.h:37
virtual void ProcessData(byte *outString, const byte *inString, size_t length)=0
encrypt or decrypt an array of bytes of specified length
virtual void SetKey(const byte *key, size_t length, const NameValuePairs &params=g_nullNameValuePairs)
set or reset the key of this object
CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A, external cipher...
Definition: modes.h:319
IV_Requirement IVRequirement() const
returns the minimal requirement for secure IVs
Definition: modes.h:98
T GetValueWithDefault(const char *name, T defaultValue) const
get a named value, returns the default if the name doesn't exist
Definition: cryptlib.h:268
bool IsRandomAccess() const
returns whether this cipher supports random access
Definition: modes.h:165
CipherDir
used to specify a direction for a cipher to operate in (encrypt or decrypt)
Definition: cryptlib.h:92
size_t MinKeyLength() const
returns smallest valid key length in bytes */
Definition: modes.h:34
CBC mode with ciphertext stealing.
Definition: modes.h:397
CTR mode.
Definition: modes.h:347
IV_Requirement IVRequirement() const
returns the minimal requirement for secure IVs
Definition: modes.h:141
interface for one direction (encryption or decryption) of a block cipher
Definition: cryptlib.h:603
const char * StolenIV()
byte *
Definition: argnames.h:17
ECB mode.
Definition: modes.h:362
bool IsForwardTransformation() const
returns whether this is an encryption object
Definition: modes.h:167
IV_Requirement IVRequirement() const
returns the minimal requirement for secure IVs
Definition: modes.h:127
virtual IV_Requirement IVRequirement() const =0
returns the minimal requirement for secure IVs
int GetIntValueWithDefault(const char *name, int defaultValue) const
get a named value with type int, with default
Definition: cryptlib.h:285
CFB mode, external cipher.
Definition: modes.h:304
bool IsResynchronizable() const
returns whether this object can be resynchronized (i.e. supports initialization vectors) ...
Definition: cryptlib.h:385
unsigned int OptimalDataAlignment() const
returns how input should be aligned for optimal performance
Definition: modes.h:40
virtual void Resynchronize(const byte *iv, int ivLength=-1)
resynchronize with an IV. ivLength=-1 means use IVSize()
Definition: cryptlib.h:401
size_t DefaultKeyLength() const
returns default (recommended) key length in bytes */
Definition: modes.h:36
void SetKey(const byte *key, size_t length, const NameValuePairs &params=g_nullNameValuePairs)
set or reset the key of this object
Definition: modes.h:184
Cipher modes documentation. See NIST SP 800-38A for definitions of these modes. See AuthenticatedSymm...
Definition: modes.h:27
interface for one direction (encryption or decryption) of a stream cipher or cipher mode ...
Definition: cryptlib.h:610
ECB mode, external cipher.
Definition: modes.h:371
const NameValuePairs & g_nullNameValuePairs
empty set of name-value pairs
unsigned int MinLastBlockSize() const
returns the minimum size of the last block, 0 indicating the last block is not special ...
Definition: modes.h:211
unsigned int OptimalBlockSize() const
returns the input block size that is most efficient for this cipher
Definition: modes.h:187
OFB mode.
Definition: modes.h:329
size_t MaxKeyLength() const
returns largest valid key length in bytes */
Definition: modes.h:35
CBC mode, external cipher.
Definition: modes.h:389
const char * BlockSize()
int, in bytes
Definition: argnames.h:21
CFB mode.
Definition: modes.h:297
bool IsValidKeyLength(size_t n) const
returns whether n is a valid key length
Definition: modes.h:38
OFB mode, external cipher.
Definition: modes.h:336
const char * IV()
ConstByteArrayParameter, also accepts const byte * for backwards compatibility.
Definition: argnames.h:16
Each class derived from this one defines two types, Encryption and Decryption, both of which implemen...
Definition: seckey.h:201
CTR mode, external cipher.
Definition: modes.h:354
virtual void ProcessLastBlock(byte *outString, const byte *inString, size_t length)
for ciphers where the last block of data is special, encrypt or decrypt the last block of data ...
unsigned int MinLastBlockSize() const
returns the minimum size of the last block, 0 indicating the last block is not special ...
Definition: modes.h:242
IV_Requirement IVRequirement() const
returns the minimal requirement for secure IVs
Definition: modes.h:195
unsigned int MandatoryBlockSize() const
returns block size, if input must be processed in blocks, otherwise 1
Definition: modes.h:164
unsigned int MinLastBlockSize() const
returns the minimum size of the last block, 0 indicating the last block is not special ...
Definition: modes.h:197
IV_Requirement IVRequirement() const
returns the minimal requirement for secure IVs
Definition: modes.h:186
CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A.
Definition: modes.h:312
interface for retrieving values given their names
Definition: cryptlib.h:224
CBC mode.
Definition: modes.h:379
CBC mode with ciphertext stealing, external cipher.
Definition: modes.h:407