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