1#ifndef CRYPTOPP_MODES_H 2#define CRYPTOPP_MODES_H 3 4/*! \file 5*/ 6 7#include "cryptlib.h" 8#include "secblock.h" 9#include "misc.h" 10#include "strciphr.h" 11#include "argnames.h" 12#include "algparam.h" 13 14NAMESPACE_BEGIN(CryptoPP) 15 16//! Cipher modes documentation. See NIST SP 800-38A for definitions of these modes. See AuthenticatedSymmetricCipherDocumentation for authenticated encryption modes. 17 18/*! Each class derived from this one defines two types, Encryption and Decryption, 19 both of which implement the SymmetricCipher interface. 20 For each mode there are two classes, one of which is a template class, 21 and the other one has a name that ends in "_ExternalCipher". 22 The "external cipher" mode objects hold a reference to the underlying block cipher, 23 instead of holding an instance of it. The reference must be passed in to the constructor. 24 For the "cipher holder" classes, the CIPHER template parameter should be a class 25 derived from BlockCipherDocumentation, for example DES or AES. 26*/ 27struct CipherModeDocumentation : public SymmetricCipherDocumentation 28{ 29}; 30 31class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CipherModeBase : public SymmetricCipher 32{ 33public: 34 size_t MinKeyLength() const {return m_cipher->MinKeyLength();} 35 size_t MaxKeyLength() const {return m_cipher->MaxKeyLength();} 36 size_t DefaultKeyLength() const {return m_cipher->DefaultKeyLength();} 37 size_t GetValidKeyLength(size_t n) const {return m_cipher->GetValidKeyLength(n);} 38 bool IsValidKeyLength(size_t n) const {return m_cipher->IsValidKeyLength(n);} 39 40 unsigned int OptimalDataAlignment() const {return m_cipher->OptimalDataAlignment();} 41 42 unsigned int IVSize() const {return BlockSize();} 43 virtual IV_Requirement IVRequirement() const =0; 44 45 void SetCipher(BlockCipher &cipher) 46 { 47 this->ThrowIfResynchronizable(); 48 this->m_cipher = &cipher; 49 this->ResizeBuffers(); 50 } 51 52 void SetCipherWithIV(BlockCipher &cipher, const byte *iv, int feedbackSize = 0) 53 { 54 this->ThrowIfInvalidIV(iv); 55 this->m_cipher = &cipher; 56 this->ResizeBuffers(); 57 this->SetFeedbackSize(feedbackSize); 58 if (this->IsResynchronizable()) 59 this->Resynchronize(iv); 60 } 61 62protected: 63 CipherModeBase() : m_cipher(NULL) {} 64 inline unsigned int BlockSize() const {assert(m_register.size() > 0); return (unsigned int)m_register.size();} 65 virtual void SetFeedbackSize(unsigned int feedbackSize) 66 { 67 if (!(feedbackSize == 0 || feedbackSize == BlockSize())) 68 throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode"); 69 } 70 virtual void ResizeBuffers() 71 { 72 m_register.New(m_cipher->BlockSize()); 73 } 74 75 BlockCipher *m_cipher; 76 AlignedSecByteBlock m_register; 77}; 78 79template <class POLICY_INTERFACE> 80class CRYPTOPP_NO_VTABLE ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE 81{ 82 unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();} 83 void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); 84}; 85 86template <class POLICY_INTERFACE> 87void ModePolicyCommonTemplate<POLICY_INTERFACE>::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) 88{ 89 m_cipher->SetKey(key, length, params); 90 ResizeBuffers(); 91 int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0); 92 SetFeedbackSize(feedbackSize); 93} 94 95class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_ModePolicy : public ModePolicyCommonTemplate<CFB_CipherAbstractPolicy> 96{ 97public: 98 IV_Requirement IVRequirement() const {return RANDOM_IV;} 99 static const char * CRYPTOPP_API StaticAlgorithmName() {return "CFB";} 100 101protected: 102 unsigned int GetBytesPerIteration() const {return m_feedbackSize;} 103 byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;} 104 bool CanIterate() const {return m_feedbackSize == BlockSize();} 105 void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount); 106 void TransformRegister(); 107 void CipherResynchronize(const byte *iv, size_t length); 108 void SetFeedbackSize(unsigned int feedbackSize); 109 void ResizeBuffers(); 110 111 SecByteBlock m_temp; 112 unsigned int m_feedbackSize; 113}; 114 115inline void CopyOrZero(void *dest, const void *src, size_t s) 116{ 117 if (src) 118 memcpy_s(dest, s, src, s); 119 else 120 memset(dest, 0, s); 121} 122 123class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE OFB_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy> 124{ 125public: 126 bool CipherIsRandomAccess() const {return false;} 127 IV_Requirement IVRequirement() const {return UNIQUE_IV;} 128 static const char * CRYPTOPP_API StaticAlgorithmName() {return "OFB";} 129 130private: 131 unsigned int GetBytesPerIteration() const {return BlockSize();} 132 unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();} 133 void WriteKeystream(byte *keystreamBuffer, size_t iterationCount); 134 void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length); 135}; 136 137class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CTR_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy> 138{ 139public: 140 bool CipherIsRandomAccess() const {return true;} 141 IV_Requirement IVRequirement() const {return RANDOM_IV;} 142 static const char * CRYPTOPP_API StaticAlgorithmName() {return "CTR";} 143 144protected: 145 virtual void IncrementCounterBy256(); 146 147 unsigned int GetAlignment() const {return m_cipher->OptimalDataAlignment();} 148 unsigned int GetBytesPerIteration() const {return BlockSize();} 149 unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();} 150 void WriteKeystream(byte *buffer, size_t iterationCount) 151 {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);} 152 bool CanOperateKeystream() const {return true;} 153 void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); 154 void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length); 155 void SeekToIteration(lword iterationCount); 156 157 AlignedSecByteBlock m_counterArray; 158}; 159 160class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockOrientedCipherModeBase : public CipherModeBase 161{ 162public: 163 void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); 164 unsigned int MandatoryBlockSize() const {return BlockSize();} 165 bool IsRandomAccess() const {return false;} 166 bool IsSelfInverting() const {return false;} 167 bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();} 168 void Resynchronize(const byte *iv, int length=-1) {memcpy_s(m_register, m_register.size(), iv, ThrowIfInvalidIVLength(length));} 169 170protected: 171 bool RequireAlignedInput() const {return true;} 172 void ResizeBuffers() 173 { 174 CipherModeBase::ResizeBuffers(); 175 m_buffer.New(BlockSize()); 176 } 177 178 SecByteBlock m_buffer; 179}; 180 181class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ECB_OneWay : public BlockOrientedCipherModeBase 182{ 183public: 184 void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms = g_nullNameValuePairs) 185 {m_cipher->SetKey(key, length, params); BlockOrientedCipherModeBase::ResizeBuffers();} 186 IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;} 187 unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();} 188 void ProcessData(byte *outString, const byte *inString, size_t length); 189 static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECB";} 190}; 191 192class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_ModeBase : public BlockOrientedCipherModeBase 193{ 194public: 195 IV_Requirement IVRequirement() const {return UNPREDICTABLE_RANDOM_IV;} 196 bool RequireAlignedInput() const {return false;} 197 unsigned int MinLastBlockSize() const {return 0;} 198 static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC";} 199}; 200 201class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Encryption : public CBC_ModeBase 202{ 203public: 204 void ProcessData(byte *outString, const byte *inString, size_t length); 205}; 206 207class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Encryption : public CBC_Encryption 208{ 209public: 210 void SetStolenIV(byte *iv) {m_stolenIV = iv;} 211 unsigned int MinLastBlockSize() const {return BlockSize()+1;} 212 void ProcessLastBlock(byte *outString, const byte *inString, size_t length); 213 static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC/CTS";} 214 215protected: 216 void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms) 217 { 218 CBC_Encryption::UncheckedSetKey(key, length, params); 219 m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULL); 220 } 221 222 byte *m_stolenIV; 223}; 224 225class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Decryption : public CBC_ModeBase 226{ 227public: 228 void ProcessData(byte *outString, const byte *inString, size_t length); 229 230protected: 231 void ResizeBuffers() 232 { 233 BlockOrientedCipherModeBase::ResizeBuffers(); 234 m_temp.New(BlockSize()); 235 } 236 AlignedSecByteBlock m_temp; 237}; 238 239class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Decryption : public CBC_Decryption 240{ 241public: 242 unsigned int MinLastBlockSize() const {return BlockSize()+1;} 243 void ProcessLastBlock(byte *outString, const byte *inString, size_t length); 244}; 245 246//! _ 247template <class CIPHER, class BASE> 248class CipherModeFinalTemplate_CipherHolder : protected ObjectHolder<CIPHER>, public AlgorithmImpl<BASE, CipherModeFinalTemplate_CipherHolder<CIPHER, BASE> > 249{ 250public: 251 CipherModeFinalTemplate_CipherHolder() 252 { 253 this->m_cipher = &this->m_object; 254 this->ResizeBuffers(); 255 } 256 CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length) 257 { 258 this->m_cipher = &this->m_object; 259 this->SetKey(key, length); 260 } 261 CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv) 262 { 263 this->m_cipher = &this->m_object; 264 this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize()))); 265 } 266 CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv, int feedbackSize) 267 { 268 this->m_cipher = &this->m_object; 269 this->SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, this->m_cipher->BlockSize()))(Name::FeedbackSize(), feedbackSize)); 270 } 271 272 static std::string CRYPTOPP_API StaticAlgorithmName() 273 {return CIPHER::StaticAlgorithmName() + "/" + BASE::StaticAlgorithmName();} 274}; 275 276//! _ 277template <class BASE> 278class CipherModeFinalTemplate_ExternalCipher : public BASE 279{ 280public: 281 CipherModeFinalTemplate_ExternalCipher() {} 282 CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher) 283 {this->SetCipher(cipher);} 284 CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv, int feedbackSize = 0) 285 {this->SetCipherWithIV(cipher, iv, feedbackSize);} 286 287 std::string AlgorithmName() const 288 {return (this->m_cipher ? this->m_cipher->AlgorithmName() + "/" : std::string("")) + BASE::StaticAlgorithmName();} 289}; 290 291CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >; 292CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >; 293CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >; 294 295//! CFB mode 296template <class CIPHER> 297struct CFB_Mode : public CipherModeDocumentation 298{ 299 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption; 300 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption; 301}; 302 303//! CFB mode, external cipher 304struct CFB_Mode_ExternalCipher : public CipherModeDocumentation 305{ 306 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption; 307 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption; 308}; 309 310//! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A 311template <class CIPHER> 312struct CFB_FIPS_Mode : public CipherModeDocumentation 313{ 314 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Encryption; 315 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Decryption; 316}; 317 318//! CFB mode FIPS variant, requiring full block plaintext according to FIPS 800-38A, external cipher 319struct CFB_FIPS_Mode_ExternalCipher : public CipherModeDocumentation 320{ 321 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Encryption; 322 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Decryption; 323}; 324 325CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> >; 326 327//! OFB mode 328template <class CIPHER> 329struct OFB_Mode : public CipherModeDocumentation 330{ 331 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption; 332 typedef Encryption Decryption; 333}; 334 335//! OFB mode, external cipher 336struct OFB_Mode_ExternalCipher : public CipherModeDocumentation 337{ 338 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption; 339 typedef Encryption Decryption; 340}; 341 342CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> >; 343 344//! CTR mode 345template <class CIPHER> 346struct CTR_Mode : public CipherModeDocumentation 347{ 348 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption; 349 typedef Encryption Decryption; 350}; 351 352//! CTR mode, external cipher 353struct CTR_Mode_ExternalCipher : public CipherModeDocumentation 354{ 355 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption; 356 typedef Encryption Decryption; 357}; 358 359//! ECB mode 360template <class CIPHER> 361struct ECB_Mode : public CipherModeDocumentation 362{ 363 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ECB_OneWay> Encryption; 364 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, ECB_OneWay> Decryption; 365}; 366 367CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<ECB_OneWay>; 368 369//! ECB mode, external cipher 370struct ECB_Mode_ExternalCipher : public CipherModeDocumentation 371{ 372 typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption; 373 typedef Encryption Decryption; 374}; 375 376//! CBC mode 377template <class CIPHER> 378struct CBC_Mode : public CipherModeDocumentation 379{ 380 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_Encryption> Encryption; 381 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_Decryption> Decryption; 382}; 383 384CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Encryption>; 385CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Decryption>; 386 387//! CBC mode, external cipher 388struct CBC_Mode_ExternalCipher : public CipherModeDocumentation 389{ 390 typedef CipherModeFinalTemplate_ExternalCipher<CBC_Encryption> Encryption; 391 typedef CipherModeFinalTemplate_ExternalCipher<CBC_Decryption> Decryption; 392}; 393 394//! CBC mode with ciphertext stealing 395template <class CIPHER> 396struct CBC_CTS_Mode : public CipherModeDocumentation 397{ 398 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_CTS_Encryption> Encryption; 399 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_CTS_Decryption> Decryption; 400}; 401 402CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption>; 403CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption>; 404 405//! CBC mode with ciphertext stealing, external cipher 406struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation 407{ 408 typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption> Encryption; 409 typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption; 410}; 411 412#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY 413typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption; 414typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption; 415typedef OFB_Mode_ExternalCipher::Encryption OFB; 416typedef CTR_Mode_ExternalCipher::Encryption CounterMode; 417#endif 418 419NAMESPACE_END 420 421#endif 422