• 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 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > >;
00344 
00345 //! CTR mode
00346 template <class CIPHER>
00347 struct CTR_Mode : public CipherModeDocumentation
00348 {
00349         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
00350         typedef Encryption Decryption;
00351 };
00352 
00353 //! CTR mode, external cipher
00354 struct CTR_Mode_ExternalCipher : public CipherModeDocumentation
00355 {
00356         typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
00357         typedef Encryption Decryption;
00358 };
00359 
00360 //! ECB mode
00361 template <class CIPHER>
00362 struct ECB_Mode : public CipherModeDocumentation
00363 {
00364         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ECB_OneWay> Encryption;
00365         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, ECB_OneWay> Decryption;
00366 };
00367 
00368 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<ECB_OneWay>;
00369 
00370 //! ECB mode, external cipher
00371 struct ECB_Mode_ExternalCipher : public CipherModeDocumentation
00372 {
00373         typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption;
00374         typedef Encryption Decryption;
00375 };
00376 
00377 //! CBC mode
00378 template <class CIPHER>
00379 struct CBC_Mode : public CipherModeDocumentation
00380 {
00381         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_Encryption> Encryption;
00382         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_Decryption> Decryption;
00383 };
00384 
00385 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Encryption>;
00386 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Decryption>;
00387 
00388 //! CBC mode, external cipher
00389 struct CBC_Mode_ExternalCipher : public CipherModeDocumentation
00390 {
00391         typedef CipherModeFinalTemplate_ExternalCipher<CBC_Encryption> Encryption;
00392         typedef CipherModeFinalTemplate_ExternalCipher<CBC_Decryption> Decryption;
00393 };
00394 
00395 //! CBC mode with ciphertext stealing
00396 template <class CIPHER>
00397 struct CBC_CTS_Mode : public CipherModeDocumentation
00398 {
00399         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_CTS_Encryption> Encryption;
00400         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_CTS_Decryption> Decryption;
00401 };
00402 
00403 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption>;
00404 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption>;
00405 
00406 //! CBC mode with ciphertext stealing, external cipher
00407 struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation
00408 {
00409         typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption> Encryption;
00410         typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption;
00411 };
00412 
00413 #ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
00414 typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption;
00415 typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption;
00416 typedef OFB_Mode_ExternalCipher::Encryption OFB;
00417 typedef CTR_Mode_ExternalCipher::Encryption CounterMode;
00418 #endif
00419 
00420 NAMESPACE_END
00421 
00422 #endif

Generated on Mon Aug 9 2010 15:56:35 for Crypto++ by  doxygen 1.7.1