Crypto++
|
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 ¶ms, const byte *key, size_t length); 00084 }; 00085 00086 template <class POLICY_INTERFACE> 00087 void ModePolicyCommonTemplate<POLICY_INTERFACE>::CipherSetKey(const NameValuePairs ¶ms, 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 ¶ms); 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 ¶ms = 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 ¶ms) 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