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 Fri Aug 13 09:56:54 2004 for Crypto++ by doxygen 1.3.7