Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class 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 #include "algparam.h"
00013 
00014 NAMESPACE_BEGIN(CryptoPP)
00015 
00016 //! Cipher mode documentation. See NIST SP 800-38A for definitions of these 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 CipherModeBase : public SymmetricCipher
00032 {
00033 public:
00034         unsigned int MinKeyLength() const {return m_cipher->MinKeyLength();}
00035         unsigned int MaxKeyLength() const {return m_cipher->MaxKeyLength();}
00036         unsigned int DefaultKeyLength() const {return m_cipher->DefaultKeyLength();}
00037         unsigned int GetValidKeyLength(unsigned int n) const {return m_cipher->GetValidKeyLength(n);}
00038         bool IsValidKeyLength(unsigned int n) const {return m_cipher->IsValidKeyLength(n);}
00039 
00040         void SetKey(const byte *key, unsigned int length, const NameValuePairs &params = g_nullNameValuePairs);
00041 
00042         unsigned int OptimalDataAlignment() const {return BlockSize();}
00043 
00044         unsigned int IVSize() const {return BlockSize();}
00045         void GetNextIV(byte *IV);
00046         virtual IV_Requirement IVRequirement() const =0;
00047 
00048 protected:
00049         inline unsigned int BlockSize() const {assert(m_register.size() > 0); return m_register.size();}
00050         void SetIV(const byte *iv);
00051         virtual void SetFeedbackSize(unsigned int feedbackSize)
00052         {
00053                 if (!(feedbackSize == 0 || feedbackSize == BlockSize()))
00054                         throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode");
00055         }
00056         virtual void ResizeBuffers()
00057         {
00058                 m_register.New(m_cipher->BlockSize());
00059         }
00060         virtual void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length) =0;
00061 
00062         BlockCipher *m_cipher;
00063         SecByteBlock m_register;
00064 };
00065 
00066 template <class POLICY_INTERFACE>
00067 class ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE
00068 {
00069         unsigned int GetAlignment() const {return m_cipher->BlockAlignment();}
00070         void CipherSetKey(const NameValuePairs &params, const byte *key, unsigned int length)
00071         {
00072                 m_cipher->SetKey(key, length, params);
00073                 ResizeBuffers();
00074                 int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0);
00075                 SetFeedbackSize(feedbackSize);
00076                 const byte *iv = params.GetValueWithDefault(Name::IV(), (const byte *)NULL);
00077                 SetIV(iv);
00078         }
00079 };
00080 
00081 class CFB_ModePolicy : public ModePolicyCommonTemplate<CFB_CipherAbstractPolicy>
00082 {
00083 public:
00084         IV_Requirement IVRequirement() const {return RANDOM_IV;}
00085 
00086 protected:
00087         unsigned int GetBytesPerIteration() const {return m_feedbackSize;}
00088         byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;}
00089         void TransformRegister()
00090         {
00091                 m_cipher->ProcessBlock(m_register, m_temp);
00092                 memmove(m_register, m_register+m_feedbackSize, BlockSize()-m_feedbackSize);
00093                 memcpy(m_register+BlockSize()-m_feedbackSize, m_temp, m_feedbackSize);
00094         }
00095         void CipherResynchronize(const byte *iv)
00096         {
00097                 memcpy(m_register, iv, BlockSize());
00098                 TransformRegister();
00099         }
00100         void SetFeedbackSize(unsigned int feedbackSize)
00101         {
00102                 if (feedbackSize > BlockSize())
00103                         throw InvalidArgument("CFB_Mode: invalid feedback size");
00104                 m_feedbackSize = feedbackSize ? feedbackSize : BlockSize();
00105         }
00106         void ResizeBuffers()
00107         {
00108                 CipherModeBase::ResizeBuffers();
00109                 m_temp.New(BlockSize());
00110         }
00111 
00112         SecByteBlock m_temp;
00113         unsigned int m_feedbackSize;
00114 };
00115 
00116 class OFB_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
00117 {
00118         unsigned int GetBytesPerIteration() const {return BlockSize();}
00119         unsigned int GetIterationsToBuffer() const {return 1;}
00120         void WriteKeystream(byte *keystreamBuffer, unsigned int iterationCount)
00121         {
00122                 assert(iterationCount == 1);
00123                 m_cipher->ProcessBlock(keystreamBuffer);
00124         }
00125         void CipherResynchronize(byte *keystreamBuffer, const byte *iv)
00126         {
00127                 memcpy(keystreamBuffer, iv, BlockSize());
00128         }
00129         bool IsRandomAccess() const {return false;}
00130         IV_Requirement IVRequirement() const {return STRUCTURED_IV;}
00131 };
00132 
00133 class CTR_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
00134 {
00135         unsigned int GetBytesPerIteration() const {return BlockSize();}
00136         unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
00137         void WriteKeystream(byte *buffer, unsigned int iterationCount)
00138                 {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
00139         bool CanOperateKeystream() const {return true;}
00140         void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount);
00141         void CipherResynchronize(byte *keystreamBuffer, const byte *iv);
00142         bool IsRandomAccess() const {return true;}
00143         void SeekToIteration(dword iterationCount);
00144         IV_Requirement IVRequirement() const {return STRUCTURED_IV;}
00145 
00146         inline void ProcessMultipleBlocks(byte *output, const byte *input, unsigned int n);
00147 
00148         SecByteBlock m_counterArray;
00149 };
00150 
00151 class BlockOrientedCipherModeBase : public CipherModeBase
00152 {
00153 public:
00154         void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length);
00155         unsigned int MandatoryBlockSize() const {return BlockSize();}
00156         bool IsRandomAccess() const {return false;}
00157         bool IsSelfInverting() const {return false;}
00158         bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();}
00159         void Resynchronize(const byte *iv) {memcpy(m_register, iv, BlockSize());}
00160         void ProcessData(byte *outString, const byte *inString, unsigned int length);
00161 
00162 protected:
00163         bool RequireAlignedInput() const {return true;}
00164         virtual void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks) =0;
00165         void ResizeBuffers()
00166         {
00167                 CipherModeBase::ResizeBuffers();
00168                 m_buffer.New(BlockSize());
00169         }
00170 
00171         SecByteBlock m_buffer;
00172 };
00173 
00174 class ECB_OneWay : public BlockOrientedCipherModeBase
00175 {
00176 public:
00177         IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;}
00178         unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();}
00179         void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks)
00180                 {m_cipher->ProcessAndXorMultipleBlocks(inString, NULL, outString, numberOfBlocks);}
00181 };
00182 
00183 class CBC_ModeBase : public BlockOrientedCipherModeBase
00184 {
00185 public:
00186         IV_Requirement IVRequirement() const {return UNPREDICTABLE_RANDOM_IV;}
00187         bool RequireAlignedInput() const {return false;}
00188         unsigned int MinLastBlockSize() const {return 0;}
00189 };
00190 
00191 class CBC_Encryption : public CBC_ModeBase
00192 {
00193 public:
00194         void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks);
00195 };
00196 
00197 class CBC_CTS_Encryption : public CBC_Encryption
00198 {
00199 public:
00200         void SetStolenIV(byte *iv) {m_stolenIV = iv;}
00201         unsigned int MinLastBlockSize() const {return BlockSize()+1;}
00202         void ProcessLastBlock(byte *outString, const byte *inString, unsigned int length);
00203 
00204 protected:
00205         void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length)
00206         {
00207                 CBC_Encryption::UncheckedSetKey(params, key, length);
00208                 m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULL);
00209         }
00210 
00211         byte *m_stolenIV;
00212 };
00213 
00214 class CBC_Decryption : public CBC_ModeBase
00215 {
00216 public:
00217         void ProcessBlocks(byte *outString, const byte *inString, unsigned int numberOfBlocks);
00218         
00219 protected:
00220         void ResizeBuffers()
00221         {
00222                 BlockOrientedCipherModeBase::ResizeBuffers();
00223                 m_temp.New(BlockSize());
00224         }
00225         SecByteBlock m_temp;
00226 };
00227 
00228 class CBC_CTS_Decryption : public CBC_Decryption
00229 {
00230 public:
00231         unsigned int MinLastBlockSize() const {return BlockSize()+1;}
00232         void ProcessLastBlock(byte *outString, const byte *inString, unsigned int length);
00233 };
00234 
00235 //! .
00236 template <class CIPHER, class BASE>
00237 class CipherModeFinalTemplate_CipherHolder : public ObjectHolder<CIPHER>, public BASE
00238 {
00239 public:
00240         CipherModeFinalTemplate_CipherHolder()
00241         {
00242                 m_cipher = &m_object;
00243                 ResizeBuffers();
00244         }
00245         CipherModeFinalTemplate_CipherHolder(const byte *key, unsigned int length)
00246         {
00247                 m_cipher = &m_object;
00248                 SetKey(key, length);
00249         }
00250         CipherModeFinalTemplate_CipherHolder(const byte *key, unsigned int length, const byte *iv, int feedbackSize = 0)
00251         {
00252                 m_cipher = &m_object;
00253                 SetKey(key, length, MakeParameters("IV", iv)("FeedbackSize", feedbackSize));
00254         }
00255 };
00256 
00257 //! .
00258 template <class BASE>
00259 class CipherModeFinalTemplate_ExternalCipher : public BASE
00260 {
00261 public:
00262         CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv = NULL, int feedbackSize = 0)
00263         {
00264                 m_cipher = &cipher;
00265                 ResizeBuffers();
00266                 SetFeedbackSize(feedbackSize);
00267                 SetIV(iv);
00268         }
00269 };
00270 
00271 //! CFB mode
00272 template <class CIPHER>
00273 struct CFB_Mode : public CipherModeDocumentation
00274 {
00275         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
00276         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
00277 };
00278 
00279 //! CFB mode, external cipher
00280 struct CFB_Mode_ExternalCipher : public CipherModeDocumentation
00281 {
00282         typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
00283         typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
00284 };
00285 
00286 //! OFB mode
00287 template <class CIPHER>
00288 struct OFB_Mode : public CipherModeDocumentation
00289 {
00290         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
00291         typedef Encryption Decryption;
00292 };
00293 
00294 //! OFB mode, external cipher
00295 struct OFB_Mode_ExternalCipher : public CipherModeDocumentation
00296 {
00297         typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
00298         typedef Encryption Decryption;
00299 };
00300 
00301 //! CTR mode
00302 template <class CIPHER>
00303 struct CTR_Mode : public CipherModeDocumentation
00304 {
00305         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
00306         typedef Encryption Decryption;
00307 };
00308 
00309 //! CTR mode, external cipher
00310 struct CTR_Mode_ExternalCipher : public CipherModeDocumentation
00311 {
00312         typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
00313         typedef Encryption Decryption;
00314 };
00315 
00316 //! ECB mode
00317 template <class CIPHER>
00318 struct ECB_Mode : public CipherModeDocumentation
00319 {
00320         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ECB_OneWay> Encryption;
00321         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, ECB_OneWay> Decryption;
00322 };
00323 
00324 //! ECB mode, external cipher
00325 struct ECB_Mode_ExternalCipher : public CipherModeDocumentation
00326 {
00327         typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption;
00328         typedef Encryption Decryption;
00329 };
00330 
00331 //! CBC mode
00332 template <class CIPHER>
00333 struct CBC_Mode : public CipherModeDocumentation
00334 {
00335         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_Encryption> Encryption;
00336         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_Decryption> Decryption;
00337 };
00338 
00339 //! CBC mode, external cipher
00340 struct CBC_Mode_ExternalCipher : public CipherModeDocumentation
00341 {
00342         typedef CipherModeFinalTemplate_ExternalCipher<CBC_Encryption> Encryption;
00343         typedef CipherModeFinalTemplate_ExternalCipher<CBC_Decryption> Decryption;
00344 };
00345 
00346 //! CBC mode with ciphertext stealing
00347 template <class CIPHER>
00348 struct CBC_CTS_Mode : public CipherModeDocumentation
00349 {
00350         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_CTS_Encryption> Encryption;
00351         typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_CTS_Decryption> Decryption;
00352 };
00353 
00354 //! CBC mode with ciphertext stealing, external cipher
00355 struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation
00356 {
00357         typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption> Encryption;
00358         typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption;
00359 };
00360 
00361 #ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
00362 typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption;
00363 typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption;
00364 typedef OFB_Mode_ExternalCipher::Encryption OFB;
00365 typedef CTR_Mode_ExternalCipher::Encryption CounterMode;
00366 #endif
00367 
00368 NAMESPACE_END
00369 
00370 #endif

Generated on Mon Apr 19 18:12:31 2004 for Crypto++ by doxygen 1.3.6-20040222