00001 #ifndef CRYPTOPP_MODES_H
00002 #define CRYPTOPP_MODES_H
00003
00004
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
00017
00018
00019
00020
00021
00022
00023
00024
00025
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 void SetKey(const byte *key, size_t length, const NameValuePairs ¶ms = 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 (unsigned int)m_register.size();}
00050 virtual void SetFeedbackSize(unsigned int feedbackSize)
00051 {
00052 if (!(feedbackSize == 0 || feedbackSize == BlockSize()))
00053 throw InvalidArgument("CipherModeBase: feedback size cannot be specified for this cipher mode");
00054 }
00055 virtual void ResizeBuffers()
00056 {
00057 m_register.New(m_cipher->BlockSize());
00058 }
00059 virtual void UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length, const byte *iv) =0;
00060
00061 BlockCipher *m_cipher;
00062 SecByteBlock m_register;
00063 };
00064
00065 template <class POLICY_INTERFACE>
00066 class CRYPTOPP_NO_VTABLE ModePolicyCommonTemplate : public CipherModeBase, public POLICY_INTERFACE
00067 {
00068 unsigned int GetAlignment() const {return m_cipher->BlockAlignment();}
00069 void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length);
00070 };
00071
00072 template <class POLICY_INTERFACE>
00073 void ModePolicyCommonTemplate<POLICY_INTERFACE>::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length)
00074 {
00075 m_cipher->SetKey(key, length, params);
00076 ResizeBuffers();
00077 int feedbackSize = params.GetIntValueWithDefault(Name::FeedbackSize(), 0);
00078 SetFeedbackSize(feedbackSize);
00079 }
00080
00081 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_ModePolicy : public ModePolicyCommonTemplate<CFB_CipherAbstractPolicy>
00082 {
00083 public:
00084 IV_Requirement IVRequirement() const {return RANDOM_IV;}
00085 static const char * CRYPTOPP_API StaticAlgorithmName() {return "CFB";}
00086
00087 protected:
00088 unsigned int GetBytesPerIteration() const {return m_feedbackSize;}
00089 byte * GetRegisterBegin() {return m_register + BlockSize() - m_feedbackSize;}
00090 void TransformRegister()
00091 {
00092 m_cipher->ProcessBlock(m_register, m_temp);
00093 unsigned int updateSize = BlockSize()-m_feedbackSize;
00094 memmove_s(m_register, m_register.size(), m_register+m_feedbackSize, updateSize);
00095 memcpy_s(m_register+updateSize, m_register.size()-updateSize, m_temp, m_feedbackSize);
00096 }
00097 void CipherResynchronize(const byte *iv)
00098 {
00099 memcpy_s(m_register, m_register.size(), iv, BlockSize());
00100 TransformRegister();
00101 }
00102 void SetFeedbackSize(unsigned int feedbackSize)
00103 {
00104 if (feedbackSize > BlockSize())
00105 throw InvalidArgument("CFB_Mode: invalid feedback size");
00106 m_feedbackSize = feedbackSize ? feedbackSize : BlockSize();
00107 }
00108 void ResizeBuffers()
00109 {
00110 CipherModeBase::ResizeBuffers();
00111 m_temp.New(BlockSize());
00112 }
00113
00114 SecByteBlock m_temp;
00115 unsigned int m_feedbackSize;
00116 };
00117
00118 inline void CopyOrZero(void *dest, const void *src, size_t s)
00119 {
00120 if (src)
00121 memcpy_s(dest, s, src, s);
00122 else
00123 memset(dest, 0, s);
00124 }
00125
00126 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE OFB_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
00127 {
00128 public:
00129 bool IsRandomAccess() const {return false;}
00130 IV_Requirement IVRequirement() const {return STRUCTURED_IV;}
00131 static const char * CRYPTOPP_API StaticAlgorithmName() {return "OFB";}
00132
00133 private:
00134 unsigned int GetBytesPerIteration() const {return BlockSize();}
00135 unsigned int GetIterationsToBuffer() const {return 1;}
00136 void WriteKeystream(byte *keystreamBuffer, size_t iterationCount)
00137 {
00138 assert(iterationCount == 1);
00139 m_cipher->ProcessBlock(keystreamBuffer);
00140 memcpy_s(m_register, m_register.size(), keystreamBuffer, BlockSize());
00141 }
00142 void CipherResynchronize(byte *keystreamBuffer, const byte *iv)
00143 {
00144 CopyOrZero(keystreamBuffer, iv, BlockSize());
00145 }
00146 };
00147
00148 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CTR_ModePolicy : public ModePolicyCommonTemplate<AdditiveCipherAbstractPolicy>
00149 {
00150 public:
00151 bool IsRandomAccess() const {return true;}
00152 IV_Requirement IVRequirement() const {return STRUCTURED_IV;}
00153 void GetNextIV(byte *IV);
00154 static const char * CRYPTOPP_API StaticAlgorithmName() {return "CTR";}
00155
00156 private:
00157 unsigned int GetBytesPerIteration() const {return BlockSize();}
00158 unsigned int GetIterationsToBuffer() const {return m_cipher->OptimalNumberOfParallelBlocks();}
00159 void WriteKeystream(byte *buffer, size_t iterationCount)
00160 {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
00161 bool CanOperateKeystream() const {return true;}
00162 void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount);
00163 void CipherResynchronize(byte *keystreamBuffer, const byte *iv);
00164 void SeekToIteration(lword iterationCount);
00165
00166 inline void ProcessMultipleBlocks(byte *output, const byte *input, size_t n);
00167
00168 SecByteBlock m_counterArray;
00169 };
00170
00171 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockOrientedCipherModeBase : public CipherModeBase
00172 {
00173 public:
00174 void UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length, const byte *iv);
00175 unsigned int MandatoryBlockSize() const {return BlockSize();}
00176 bool IsRandomAccess() const {return false;}
00177 bool IsSelfInverting() const {return false;}
00178 bool IsForwardTransformation() const {return m_cipher->IsForwardTransformation();}
00179 void Resynchronize(const byte *iv) {memcpy_s(m_register, m_register.size(), iv, BlockSize());}
00180 void ProcessData(byte *outString, const byte *inString, size_t length);
00181
00182 protected:
00183 bool RequireAlignedInput() const {return true;}
00184 virtual void ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks) =0;
00185 void ResizeBuffers()
00186 {
00187 CipherModeBase::ResizeBuffers();
00188 m_buffer.New(BlockSize());
00189 }
00190
00191 SecByteBlock m_buffer;
00192 };
00193
00194 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ECB_OneWay : public BlockOrientedCipherModeBase
00195 {
00196 public:
00197 IV_Requirement IVRequirement() const {return NOT_RESYNCHRONIZABLE;}
00198 unsigned int OptimalBlockSize() const {return BlockSize() * m_cipher->OptimalNumberOfParallelBlocks();}
00199 void ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks)
00200 {m_cipher->ProcessAndXorMultipleBlocks(inString, NULL, outString, numberOfBlocks);}
00201 static const char * CRYPTOPP_API StaticAlgorithmName() {return "ECB";}
00202 };
00203
00204 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_ModeBase : public BlockOrientedCipherModeBase
00205 {
00206 public:
00207 IV_Requirement IVRequirement() const {return UNPREDICTABLE_RANDOM_IV;}
00208 bool RequireAlignedInput() const {return false;}
00209 unsigned int MinLastBlockSize() const {return 0;}
00210 static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC";}
00211 };
00212
00213 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Encryption : public CBC_ModeBase
00214 {
00215 public:
00216 void ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks);
00217 };
00218
00219 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Encryption : public CBC_Encryption
00220 {
00221 public:
00222 void SetStolenIV(byte *iv) {m_stolenIV = iv;}
00223 unsigned int MinLastBlockSize() const {return BlockSize()+1;}
00224 void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
00225 static const char * CRYPTOPP_API StaticAlgorithmName() {return "CBC/CTS";}
00226
00227 protected:
00228 void UncheckedSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int length, const byte *iv)
00229 {
00230 CBC_Encryption::UncheckedSetKey(params, key, length, iv);
00231 m_stolenIV = params.GetValueWithDefault(Name::StolenIV(), (byte *)NULL);
00232 }
00233
00234 byte *m_stolenIV;
00235 };
00236
00237 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_Decryption : public CBC_ModeBase
00238 {
00239 public:
00240 void ProcessBlocks(byte *outString, const byte *inString, size_t numberOfBlocks);
00241
00242 protected:
00243 void ResizeBuffers()
00244 {
00245 BlockOrientedCipherModeBase::ResizeBuffers();
00246 m_temp.New(BlockSize());
00247 }
00248 SecByteBlock m_temp;
00249 };
00250
00251 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Decryption : public CBC_Decryption
00252 {
00253 public:
00254 unsigned int MinLastBlockSize() const {return BlockSize()+1;}
00255 void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
00256 };
00257
00258
00259 template <class CIPHER, class BASE>
00260 class CipherModeFinalTemplate_CipherHolder : protected ObjectHolder<CIPHER>, public AlgorithmImpl<BASE, CipherModeFinalTemplate_CipherHolder<CIPHER, BASE> >
00261 {
00262 public:
00263 CipherModeFinalTemplate_CipherHolder()
00264 {
00265 this->m_cipher = &this->m_object;
00266 this->ResizeBuffers();
00267 }
00268 CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length)
00269 {
00270 this->m_cipher = &this->m_object;
00271 this->SetKey(key, length);
00272 }
00273 CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv)
00274 {
00275 this->m_cipher = &this->m_object;
00276 this->SetKey(key, length, MakeParameters(Name::IV(), iv));
00277 }
00278 CipherModeFinalTemplate_CipherHolder(const byte *key, size_t length, const byte *iv, int feedbackSize)
00279 {
00280 this->m_cipher = &this->m_object;
00281 this->SetKey(key, length, MakeParameters(Name::IV(), iv)(Name::FeedbackSize(), feedbackSize));
00282 }
00283
00284 static std::string CRYPTOPP_API StaticAlgorithmName()
00285 {return CIPHER::StaticAlgorithmName() + "/" + BASE::StaticAlgorithmName();}
00286 };
00287
00288
00289 template <class BASE>
00290 class CipherModeFinalTemplate_ExternalCipher : public BASE
00291 {
00292 public:
00293 CipherModeFinalTemplate_ExternalCipher() {}
00294 CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher)
00295 {SetCipher(cipher);}
00296 CipherModeFinalTemplate_ExternalCipher(BlockCipher &cipher, const byte *iv, int feedbackSize = 0)
00297 {SetCipherWithIV(cipher, iv, feedbackSize);}
00298
00299 void SetCipher(BlockCipher &cipher);
00300 void SetCipherWithIV(BlockCipher &cipher, const byte *iv, int feedbackSize = 0);
00301 };
00302
00303 template <class BASE>
00304 void CipherModeFinalTemplate_ExternalCipher<BASE>::SetCipher(BlockCipher &cipher)
00305 {
00306 this->ThrowIfResynchronizable();
00307 this->m_cipher = &cipher;
00308 this->ResizeBuffers();
00309 }
00310
00311 template <class BASE>
00312 void CipherModeFinalTemplate_ExternalCipher<BASE>::SetCipherWithIV(BlockCipher &cipher, const byte *iv, int feedbackSize)
00313 {
00314 this->ThrowIfInvalidIV(iv);
00315 this->m_cipher = &cipher;
00316 this->ResizeBuffers();
00317 this->SetFeedbackSize(feedbackSize);
00318 if (this->IsResynchronizable())
00319 this->Resynchronize(iv);
00320 }
00321
00322 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
00323 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
00324 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
00325
00326
00327 template <class CIPHER>
00328 struct CFB_Mode : public CipherModeDocumentation
00329 {
00330 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
00331 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
00332 };
00333
00334
00335 struct CFB_Mode_ExternalCipher : public CipherModeDocumentation
00336 {
00337 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
00338 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
00339 };
00340
00341
00342 template <class CIPHER>
00343 struct CFB_FIPS_Mode : public CipherModeDocumentation
00344 {
00345 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Encryption;
00346 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Decryption;
00347 };
00348
00349
00350 struct CFB_FIPS_Mode_ExternalCipher : public CipherModeDocumentation
00351 {
00352 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Encryption;
00353 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Decryption;
00354 };
00355
00356 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> >;
00357
00358
00359 template <class CIPHER>
00360 struct OFB_Mode : public CipherModeDocumentation
00361 {
00362 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
00363 typedef Encryption Decryption;
00364 };
00365
00366
00367 struct OFB_Mode_ExternalCipher : public CipherModeDocumentation
00368 {
00369 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
00370 typedef Encryption Decryption;
00371 };
00372
00373 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> >;
00374
00375
00376 template <class CIPHER>
00377 struct CTR_Mode : public CipherModeDocumentation
00378 {
00379 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
00380 typedef Encryption Decryption;
00381 };
00382
00383
00384 struct CTR_Mode_ExternalCipher : public CipherModeDocumentation
00385 {
00386 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
00387 typedef Encryption Decryption;
00388 };
00389
00390
00391 template <class CIPHER>
00392 struct ECB_Mode : public CipherModeDocumentation
00393 {
00394 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ECB_OneWay> Encryption;
00395 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, ECB_OneWay> Decryption;
00396 };
00397
00398 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<ECB_OneWay>;
00399
00400
00401 struct ECB_Mode_ExternalCipher : public CipherModeDocumentation
00402 {
00403 typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption;
00404 typedef Encryption Decryption;
00405 };
00406
00407
00408 template <class CIPHER>
00409 struct CBC_Mode : public CipherModeDocumentation
00410 {
00411 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_Encryption> Encryption;
00412 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_Decryption> Decryption;
00413 };
00414
00415 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Encryption>;
00416 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Decryption>;
00417
00418
00419 struct CBC_Mode_ExternalCipher : public CipherModeDocumentation
00420 {
00421 typedef CipherModeFinalTemplate_ExternalCipher<CBC_Encryption> Encryption;
00422 typedef CipherModeFinalTemplate_ExternalCipher<CBC_Decryption> Decryption;
00423 };
00424
00425
00426 template <class CIPHER>
00427 struct CBC_CTS_Mode : public CipherModeDocumentation
00428 {
00429 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_CTS_Encryption> Encryption;
00430 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_CTS_Decryption> Decryption;
00431 };
00432
00433 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption>;
00434 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption>;
00435
00436
00437 struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation
00438 {
00439 typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption> Encryption;
00440 typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption;
00441 };
00442
00443 #ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
00444 typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption;
00445 typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption;
00446 typedef OFB_Mode_ExternalCipher::Encryption OFB;
00447 typedef CTR_Mode_ExternalCipher::Encryption CounterMode;
00448 #endif
00449
00450 NAMESPACE_END
00451
00452 #endif