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