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