Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

# modes.h

Go to the documentation of this file.

    00001 #ifndef CRYPTOPP_MODES_H
    00002 #define CRYPTOPP_MODES_H
    00003
    00004 /*! \file
    00005 */
    00006
    00007 #include "cryptlib.h"
    00008 #include "secblock.h"
    00009 #include "misc.h"
    00010 #include "strciphr.h"
    00011 #include "argnames.h"
    00012
    00013 NAMESPACE_BEGIN(CryptoPP)
    00014
    00015 //! Cipher mode documentation. See NIST SP 800-38A for definitions of these modes.
    00016
    00017 /*! Each class derived from this one defines two types, Encryption and Decryption,
    00018         both of which implement the SymmetricCipher interface.
    00019         For each mode there are two classes, one of which is a template class,
    00020         and the other one has a name that ends in "_ExternalCipher".
    00021         The "external cipher" mode objects hold a reference to the underlying block cipher,
    00022         instead of holding an instance of it. The reference must be passed in to the constructor.
    00023         For the "cipher holder" classes, the CIPHER template parameter should be a class
    00024         derived from BlockCipherDocumentation, for example DES or AES.
    00025 */
    00026 struct CipherModeDocumentation : public SymmetricCipherDocumentation
    00027 {
    00028 };
    00029
    00030 class CRYPTOPP_DLL CipherModeBase : public SymmetricCipher
    00031 {
    00032 public:
    00033         unsigned int MinKeyLength() const {return m_cipher->MinKeyLength();}
    00034         unsigned int MaxKeyLength() const {return m_cipher->MaxKeyLength();}
    00035         unsigned int DefaultKeyLength() const {return m_cipher->DefaultKeyLength();}
    00036         unsigned int GetValidKeyLength(unsigned int n) const {return m_cipher->GetValidKeyLength(n);}
    00037         bool IsValidKeyLength(unsigned int n) const {return m_cipher->IsValidKeyLength(n);}
    00038
    00039         void SetKey(const byte *key, unsigned int length, const NameValuePairs &params = g_nullNameValuePairs);
    00040
    00041         unsigned int OptimalDataAlignment() const {return BlockSize();}
    00042
    00043         unsigned int IVSize() const {return BlockSize();}
    00044         void GetNextIV(byte *IV);
    00045
    00046 protected:
    00047         inline unsigned int BlockSize() const {assert(m_register.size() > 0); return m_register.size();}
    00048         void SetIV(const byte *iv);
    00049         virtual void SetFeedbackSize(unsigned int feedbackSize)
    00050         {
    00051                 if (!(feedbackSize == 0 || feedbackSize == BlockSize()))
    00052                         throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode");
    00053         }
    00054         virtual void ResizeBuffers()
    00055         {
    00056                 m_register.New(m_cipher->BlockSize());
    00057         }
    00058         virtual void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length) =0;
    00059
    00060         BlockCipher *m_cipher;
    00061         SecByteBlock m_register;
    00062 };
    00063
    00064 template <class POLICY_INTERFACE>
    00065 class ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE
    00066 {
    00067         unsigned int GetAlignment() const {return m_cipher->BlockAlignment();}
    00068         void CipherSetKey(const NameValuePairs &params, const byte *key, unsigned int length);
    00069 };
    00070
    00071 template <class POLICY_INTERFACE>
    00072 void ModePolicyCommonTemplate<POLICY_INTERFACE>::CipherSetKey(const NameValuePairs &params, const byte *key, unsigned int length)
    00073 {
    00074         m_cipher->SetKey(key, length, params);
    00075         ResizeBuffers();
    00076         int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0);
    00077         SetFeedbackSize(feedbackSize);
    00078         const byte *iv = params.GetValueWithDefault(Name::IV(), (const byte *)NULL);
    00079         SetIV(iv);
    00080 }
    00081
    00082 CRYPTOPP_DLL_TEMPLATE_CLASS ModePolicyCommonTemplate<CFB_CipherAbstractPolicy>;
    00083 CRYPTOPP_DLL_TEMPLATE_CLASS ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>;
    00084
    00085 class CRYPTOPP_DLL CFB_ModePolicy : public ModePolicyCommonTemplate<CFB_CipherAbstractPolicy>
    00086 {
    00087 public:
    00088         IV_Requirement IVRequirement() const {return RANDOM_IV;}
    00089
    00090 protected:
    00091         unsigned int GetBytesPerIteration() const {return m_feedbackSize;}
    00092         byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;}
    00093         void TransformRegister()
    00094         {
    00095                 m_cipher->ProcessBlock(m_register, m_temp);
    00096                 memmove(m_register, m_register+m_feedbackSize, BlockSize()-m_feedbackSize);
    00097                 memcpy(m_register+BlockSize()-m_feedbackSize, m_temp, m_feedbackSize);
    00098         }
    00099         void CipherResynchronize(const byte *iv)
    00100         {
    00101                 memcpy(m_register, iv, BlockSize());
    00102                 TransformRegister();
    00103         }
    00104         void SetFeedbackSize(unsigned int feedbackSize)
    00105         {
    00106                 if (feedbackSize > BlockSize())
    00107                         throw InvalidArgument("CFB_Mode: invalid feedback size");
    00108                 m_feedbackSize = feedbackSize ? feedbackSize : BlockSize();
    00109         }
    00110         void ResizeBuffers()
    00111         {
    00112                 CipherModeBase::ResizeBuffers();
    00113                 m_temp.New(BlockSize());
    00114         }
    00115
    00116         SecByteBlock m_temp;
    00117         unsigned int m_feedbackSize;
    00118 };
    00119
    00120 class CRYPTOPP_DLL OFB_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
    00121 {
    00122 public:
    00123         bool IsRandomAccess() const {return false;}
    00124         IV_Requirement IVRequirement() const {return STRUCTURED_IV;}
    00125
    00126 private:
    00127         unsigned int GetBytesPerIteration() const {return BlockSize();}
    00128         unsigned int GetIterationsToBuffer() const {return 1;}
    00129         void WriteKeystream(byte *keystreamBuffer, unsigned int iterationCount)
    00130         {
    00131                 assert(iterationCount == 1);
    00132                 m_cipher->ProcessBlock(keystreamBuffer);
    00133                 memcpy(m_register, keystreamBuffer, BlockSize());
    00134         }
    00135         void CipherResynchronize(byte *keystreamBuffer, const byte *iv)
    00136         {
    00137                 memcpy(keystreamBuffer, iv, BlockSize());
    00138                 memcpy(m_register, keystreamBuffer, BlockSize());
    00139         }
    00140 };
    00141
    00142 class CRYPTOPP_DLL CTR_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
    00143 {
    00144 public:
    00145         bool IsRandomAccess() const {return true;}
    00146         IV_Requirement IVRequirement() const {return STRUCTURED_IV;}
    00147         void GetNextIV(byte *IV);
    00148
    00149 private:
    00150         unsigned int GetBytesPerIteration() const {return BlockSize();}
    00151         unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
    00152         void WriteKeystream(byte *buffer, unsigned int iterationCount)
    00153                 {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
    00154         bool CanOperateKeystream() const {return true;}
    00155         void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount);
    00156         void CipherResynchronize(byte *keystreamBuffer, const byte *iv);
    00157         void SeekToIteration(dword iterationCount);
    00158
    00159         static inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int s)
    00160         {
    00161                 for (int i=s-1, carry=1; i>=0 && carry; i--)
    00162                 carry = !(output[i] = input[i]+1);
    00163         }
    00164         inline void ProcessMultipleBlocks(byte *output, const byte *input, unsigned int n)
    00165         {
    00166                 unsigned int s = BlockSize(), j = 0;
    00167                 for (unsigned int i=1; i<n; i++, j+=s)
    00168                         IncrementCounterByOne(m_counterArray + j + s, m_counterArray + j, s);
    00169                 m_cipher->ProcessAndXorMultipleBlocks(m_counterArray, input, output, n);
    00170                 IncrementCounterByOne(m_counterArray, m_counterArray + s*(n-1), s);
    00171         }
    00172
    00173         SecByteBlock m_counterArray;
    00174 };
    00175
    00176 class CRYPTOPP_DLL BlockOrientedCipherModeBase : public CipherModeBase
    00177 {
    00178 public:
    00179         void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length);
    00180         unsigned int MandatoryBlockSize() const {return BlockSize();}
    00181         bool IsRandomAccess() const {return false;}
    00182         bool IsSelfInverting() const {return false;}
    00183         bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();}
    00184         void Resynchronize(const byte *iv) {memcpy(m_register, iv, BlockSize());}
    00185         void ProcessData(byte *outString, const byte *inString, unsigned int length);
    00186
    00187 protected:
    00188         bool RequireAlignedInput() const {return true;}
    00189         virtual void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks) =0;
    00190         void ResizeBuffers()
    00191         {
    00192                 CipherModeBase::ResizeBuffers();
    00193                 m_buffer.New(BlockSize());
    00194         }
    00195
    00196         SecByteBlock m_buffer;
    00197 };
    00198
    00199 class CRYPTOPP_DLL ECB_OneWay : public BlockOrientedCipherModeBase
    00200 {
    00201 public:
    00202         IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;}
    00203         unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();}
    00204         void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks)
    00205                 {m_cipher->ProcessAndXorMultipleBlocks(inString, NULL, outString, numberOfBlocks);}
    00206 };
    00207
    00208 class CRYPTOPP_DLL CBC_ModeBase : public BlockOrientedCipherModeBase
    00209 {
    00210 public:
    00211         IV_Requirement IVRequirement() const {return UNPREDICTABLE_RANDOM_IV;}
    00212         bool RequireAlignedInput() const {return false;}
    00213         unsigned int MinLastBlockSize() const {return 0;}
    00214 };
    00215
    00216 class CRYPTOPP_DLL CBC_Encryption : public CBC_ModeBase
    00217 {
    00218 public:
    00219         void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks);
    00220 };
    00221
    00222 class CRYPTOPP_DLL CBC_CTS_Encryption : public CBC_Encryption
    00223 {
    00224 public:
    00225         void SetStolenIV(byte *iv) {m_stolenIV = iv;}
    00226
    00227 protected:
    00228         void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length)
    00229         {
    00230                 CBC_Encryption::UncheckedSetKey(params, key, length);
    00231                 m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULL);
    00232         }
    00233         unsigned int MinLastBlockSize() const {return BlockSize()+1;}
    00234         void ProcessLastBlock(byte *outString, const byte *inString, unsigned int length);
    00235
    00236         byte *m_stolenIV;
    00237 };
    00238
    00239 class CRYPTOPP_DLL CBC_Decryption : public CBC_ModeBase
    00240 {
    00241 public:
    00242         void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks);
    00243
    00244 protected:
    00245         void ResizeBuffers()
    00246         {
    00247                 BlockOrientedCipherModeBase::ResizeBuffers();
    00248                 m_temp.New(BlockSize());
    00249         }
    00250         SecByteBlock m_temp;
    00251 };
    00252
    00253 class CRYPTOPP_DLL CBC_CTS_Decryption : public CBC_Decryption
    00254 {
    00255 public:
    00256         unsigned int MinLastBlockSize() const {return BlockSize()+1;}
    00257         void ProcessLastBlock(byte *outString, const byte *inString, unsigned int length);
    00258 };
    00259
    00260 //! .
    00261 template <class CIPHER, class BASE>
    00262 class CipherModeFinalTemplate_CipherHolder : public ObjectHolder<CIPHER>, public BASE
    00263 {
    00264 public:
    00265         CipherModeFinalTemplate_CipherHolder()
    00266         {
    00267                 m_cipher = &m_object;
    00268                 ResizeBuffers();
    00269         }
    00270         CipherModeFinalTemplate_CipherHolder(const byte *key, unsigned int length)
    00271         {
    00272                 m_cipher = &m_object;
    00273                 SetKey(key, length);
    00274         }
    00275         CipherModeFinalTemplate_CipherHolder(const byte *key, unsigned int length, const byte *iv, int feedbackSize = 0)
    00276         {
    00277                 m_cipher = &m_object;
    00278                 SetKey(key, length, MakeParameters("IV", iv)("FeedbackSize", feedbackSize));
    00279         }
    00280 };
    00281
    00282 //! .
    00283 template <class BASE>
    00284 class CipherModeFinalTemplate_ExternalCipher : public BASE
    00285 {
    00286 public:
    00287         CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv = NULL, int feedbackSize = 0);
    00288 };
    00289
    00290 template <class BASE> CipherModeFinalTemplate_ExternalCipher<BASE>::CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv, int feedbackSize)
    00291 {
    00292         m_cipher = &cipher;
    00293         ResizeBuffers();
    00294         SetFeedbackSize(feedbackSize);
    00295         SetIV(iv);
    00296 }
    00297
    00298 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
    00299 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
    00300 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
    00301
    00302 //! CFB mode
    00303 template <class CIPHER>
    00304 struct CFB_Mode : public CipherModeDocumentation
    00305 {
    00306         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
    00307         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
    00308 };
    00309
    00310 //! CFB mode, external cipher
    00311 struct CFB_Mode_ExternalCipher : public CipherModeDocumentation
    00312 {
    00313         typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
    00314         typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
    00315 };
    00316
    00317 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> >;
    00318
    00319 //! OFB mode
    00320 template <class CIPHER>
    00321 struct OFB_Mode : public CipherModeDocumentation
    00322 {
    00323         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
    00324         typedef Encryption Decryption;
    00325 };
    00326
    00327 //! OFB mode, external cipher
    00328 struct OFB_Mode_ExternalCipher : public CipherModeDocumentation
    00329 {
    00330         typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
    00331         typedef Encryption Decryption;
    00332 };
    00333
    00334 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> >;
    00335
    00336 //! CTR mode
    00337 template <class CIPHER>
    00338 struct CTR_Mode : public CipherModeDocumentation
    00339 {
    00340         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
    00341         typedef Encryption Decryption;
    00342 };
    00343
    00344 //! CTR mode, external cipher
    00345 struct CTR_Mode_ExternalCipher : public CipherModeDocumentation
    00346 {
    00347         typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
    00348         typedef Encryption Decryption;
    00349 };
    00350
    00351 //! ECB mode
    00352 template <class CIPHER>
    00353 struct ECB_Mode : public CipherModeDocumentation
    00354 {
    00355         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ECB_OneWay> Encryption;
    00356         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, ECB_OneWay> Decryption;
    00357 };
    00358
    00359 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<ECB_OneWay>;
    00360
    00361 //! ECB mode, external cipher
    00362 struct ECB_Mode_ExternalCipher : public CipherModeDocumentation
    00363 {
    00364         typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption;
    00365         typedef Encryption Decryption;
    00366 };
    00367
    00368 //! CBC mode
    00369 template <class CIPHER>
    00370 struct CBC_Mode : public CipherModeDocumentation
    00371 {
    00372         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_Encryption> Encryption;
    00373         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_Decryption> Decryption;
    00374 };
    00375
    00376 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Encryption>;
    00377 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Decryption>;
    00378
    00379 //! CBC mode, external cipher
    00380 struct CBC_Mode_ExternalCipher : public CipherModeDocumentation
    00381 {
    00382         typedef CipherModeFinalTemplate_ExternalCipher<CBC_Encryption> Encryption;
    00383         typedef CipherModeFinalTemplate_ExternalCipher<CBC_Decryption> Decryption;
    00384 };
    00385
    00386 //! CBC mode with ciphertext stealing
    00387 template <class CIPHER>
    00388 struct CBC_CTS_Mode : public CipherModeDocumentation
    00389 {
    00390         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_CTS_Encryption> Encryption;
    00391         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_CTS_Decryption> Decryption;
    00392 };
    00393
    00394 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption>;
    00395 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption>;
    00396
    00397 //! CBC mode with ciphertext stealing, external cipher
    00398 struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation
    00399 {
    00400         typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption> Encryption;
    00401         typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption;
    00402 };
    00403
    00404 #ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
    00405 typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption;
    00406 typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption;
    00407 typedef OFB_Mode_ExternalCipher::Encryption OFB;
    00408 typedef OFB_Mode_ExternalCipher::Encryption CounterMode;
    00409 #endif
    00410
    00411 NAMESPACE_END
    00412
    00413 #endif