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 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 ¶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 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, unsigned int length);
00070 };
00071
00072 template <class POLICY_INTERFACE>
00073 void ModePolicyCommonTemplate<POLICY_INTERFACE>::CipherSetKey(const NameValuePairs ¶ms, const byte *key, unsigned int 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 *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 *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, unsigned int 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 *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, unsigned int iterationCount)
00159 {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
00160 bool CanOperateKeystream() const {return true;}
00161 void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount);
00162 void CipherResynchronize(byte *keystreamBuffer, const byte *iv);
00163 void SeekToIteration(lword iterationCount);
00164
00165 inline void ProcessMultipleBlocks(byte *output, const byte *input, unsigned int 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, unsigned int length);
00180
00181 protected:
00182 bool RequireAlignedInput() const {return true;}
00183 virtual void ProcessBlocks(byte *outString, const byte *inString, unsigned int 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, unsigned int numberOfBlocks)
00199 {m_cipher->ProcessAndXorMultipleBlocks(inString, NULL, outString, numberOfBlocks);}
00200 static const char *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 *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, unsigned int 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, unsigned int length);
00224 static const char *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, unsigned int 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, unsigned int 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, unsigned int length)
00268 {
00269 this->m_cipher = &this->m_object;
00270 this->SetKey(key, length);
00271 }
00272 CipherModeFinalTemplate_CipherHolder(const byte *key, unsigned int 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, unsigned int 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 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 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
00322 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
00323 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> >;
00324
00325
00326 template <class CIPHER>
00327 struct CFB_Mode : public CipherModeDocumentation
00328 {
00329 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
00330 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
00331 };
00332
00333
00334 struct CFB_Mode_ExternalCipher : public CipherModeDocumentation
00335 {
00336 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Encryption;
00337 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > Decryption;
00338 };
00339
00340
00341 template <class CIPHER>
00342 struct CFB_FIPS_Mode : public CipherModeDocumentation
00343 {
00344 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Encryption;
00345 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Decryption;
00346 };
00347
00348
00349 struct CFB_FIPS_Mode_ExternalCipher : public CipherModeDocumentation
00350 {
00351 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Encryption;
00352 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, CFB_RequireFullDataBlocks<CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, CFB_ModePolicy> > > > > Decryption;
00353 };
00354
00355 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> >;
00356
00357
00358 template <class CIPHER>
00359 struct OFB_Mode : public CipherModeDocumentation
00360 {
00361 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
00362 typedef Encryption Decryption;
00363 };
00364
00365
00366 struct OFB_Mode_ExternalCipher : public CipherModeDocumentation
00367 {
00368 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, OFB_ModePolicy> > > > Encryption;
00369 typedef Encryption Decryption;
00370 };
00371
00372 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> >;
00373
00374
00375 template <class CIPHER>
00376 struct CTR_Mode : public CipherModeDocumentation
00377 {
00378 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
00379 typedef Encryption Decryption;
00380 };
00381
00382
00383 struct CTR_Mode_ExternalCipher : public CipherModeDocumentation
00384 {
00385 typedef CipherModeFinalTemplate_ExternalCipher<ConcretePolicyHolder<Empty, AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, CTR_ModePolicy> > > > Encryption;
00386 typedef Encryption Decryption;
00387 };
00388
00389
00390 template <class CIPHER>
00391 struct ECB_Mode : public CipherModeDocumentation
00392 {
00393 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, ECB_OneWay> Encryption;
00394 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, ECB_OneWay> Decryption;
00395 };
00396
00397 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<ECB_OneWay>;
00398
00399
00400 struct ECB_Mode_ExternalCipher : public CipherModeDocumentation
00401 {
00402 typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption;
00403 typedef Encryption Decryption;
00404 };
00405
00406
00407 template <class CIPHER>
00408 struct CBC_Mode : public CipherModeDocumentation
00409 {
00410 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_Encryption> Encryption;
00411 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_Decryption> Decryption;
00412 };
00413
00414 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Encryption>;
00415 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_Decryption>;
00416
00417
00418 struct CBC_Mode_ExternalCipher : public CipherModeDocumentation
00419 {
00420 typedef CipherModeFinalTemplate_ExternalCipher<CBC_Encryption> Encryption;
00421 typedef CipherModeFinalTemplate_ExternalCipher<CBC_Decryption> Decryption;
00422 };
00423
00424
00425 template <class CIPHER>
00426 struct CBC_CTS_Mode : public CipherModeDocumentation
00427 {
00428 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Encryption, CBC_CTS_Encryption> Encryption;
00429 typedef CipherModeFinalTemplate_CipherHolder<CPP_TYPENAME CIPHER::Decryption, CBC_CTS_Decryption> Decryption;
00430 };
00431
00432 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption>;
00433 CRYPTOPP_DLL_TEMPLATE_CLASS CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption>;
00434
00435
00436 struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation
00437 {
00438 typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Encryption> Encryption;
00439 typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption;
00440 };
00441
00442 #ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
00443 typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption;
00444 typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption;
00445 typedef OFB_Mode_ExternalCipher::Encryption OFB;
00446 typedef CTR_Mode_ExternalCipher::Encryption CounterMode;
00447 #endif
00448
00449 NAMESPACE_END
00450
00451 #endif