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 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
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
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
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
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
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
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
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
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
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
00371 struct ECB_Mode_ExternalCipher : public CipherModeDocumentation
00372 {
00373 typedef CipherModeFinalTemplate_ExternalCipher<ECB_OneWay> Encryption;
00374 typedef Encryption Decryption;
00375 };
00376
00377
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
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
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
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