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

Generated on Tue Jun 30 2015 19:07:05 for Crypto++ by  doxygen 1.7.1