- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# strciphr.h

Go to the documentation of this file.

    00001 /*! \file
    00002         This file contains helper classes for implementing stream ciphers.
    00003
    00004         All this infrastructure may look very complex compared to what's in Crypto++ 4.x,
    00005         but stream ciphers implementations now support a lot of new functionality,
    00006         including better performance (minimizing copying), resetting of keys and IVs, and methods to
    00007         query which features are supported by a cipher.
    00008
    00009         Here's an explanation of these classes. The word "policy" is used here to mean a class with a
    00010         set of methods that must be implemented by individual stream cipher implementations.
    00011         This is usually much simpler than the full stream cipher API, which is implemented by
    00012         either AdditiveCipherTemplate or CFB_CipherTemplate using the policy. So for example, an
    00013         implementation of SEAL only needs to implement the AdditiveCipherAbstractPolicy interface
    00014         (since it's an additive cipher, i.e., it xors a keystream into the plaintext).
    00015         See this line in seal.h:
    00016
    00017         typedef SymmetricCipherFinal<ConcretePolicyHolder<SEAL_Policy<B>, AdditiveCipherTemplate<> > > Encryption;
    00018
    00019         AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't need
    00020         to take a policy class as a template parameter (although this is allowed), so that
    00021         their code is not duplicated for each new cipher. Instead they each
    00022         get a reference to an abstract policy interface by calling AccessPolicy() on itself, so
    00023         AccessPolicy() must be overriden to return the actual policy reference. This is done
    00024         by the ConceretePolicyHolder class. Finally, SymmetricCipherFinal implements the constructors and
    00025         other functions that must be implemented by the most derived class.
    00026 */
    00027
    00028 #ifndef CRYPTOPP_STRCIPHR_H
    00029 #define CRYPTOPP_STRCIPHR_H
    00030
    00031 #include "seckey.h"
    00032 #include "secblock.h"
    00033 #include "argnames.h"
    00034
    00035 NAMESPACE_BEGIN(CryptoPP)
    00036
    00037 template <class POLICY_INTERFACE, class BASE = Empty>
    00038 class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE
    00039 {
    00040 public:
    00041         typedef POLICY_INTERFACE PolicyInterface;
    00042
    00043 protected:
    00044         virtual const POLICY_INTERFACE & GetPolicy() const =0;
    00045         virtual POLICY_INTERFACE & AccessPolicy() =0;
    00046 };
    00047
    00048 template <class POLICY, class BASE, class POLICY_INTERFACE = CPP_TYPENAME BASE::PolicyInterface>
    00049 class ConcretePolicyHolder : public BASE, protected POLICY
    00050 {
    00051 protected:
    00052         const POLICY_INTERFACE & GetPolicy() const {return *this;}
    00053         POLICY_INTERFACE & AccessPolicy() {return *this;}
    00054 };
    00055
    00056 enum KeystreamOperation {WRITE_KEYSTREAM, XOR_KEYSTREAM, XOR_KEYSTREAM_INPLACE};
    00057
    00058 struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy
    00059 {
    00060         virtual unsigned int GetAlignment() const =0;
    00061         virtual unsigned int GetBytesPerIteration() const =0;
    00062         virtual unsigned int GetIterationsToBuffer() const =0;
    00063         virtual void WriteKeystream(byte *keystreamBuffer, size_t iterationCount) =0;
    00064         virtual bool CanOperateKeystream() const {return false;}
    00065         virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) {assert(false);}
    00066         virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
    00067         virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv) {throw NotImplemented("StreamTransformation: this object doesn't support resynchronization");}
    00068         virtual bool IsRandomAccess() const =0;
    00069         virtual void SeekToIteration(lword iterationCount) {assert(!IsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");}
    00070 };
    00071
    00072 template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy>
    00073 struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE
    00074 {
    00075         typedef WT WordType;
    00076
    00077         unsigned int GetAlignment() const {return sizeof(WordType);}
    00078         unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
    00079         unsigned int GetIterationsToBuffer() const {return X;}
    00080         void WriteKeystream(byte *buffer, size_t iterationCount)
    00081                 {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
    00082         bool CanOperateKeystream() const {return true;}
    00083         virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0;
    00084
    00085         template <class B>
    00086         struct KeystreamOutput
    00087         {
    00088                 KeystreamOutput(KeystreamOperation operation, byte *output, const byte *input)
    00089                         : m_operation(operation), m_output(output), m_input(input) {}
    00090
    00091                 inline KeystreamOutput & operator()(WordType keystreamWord)
    00092                 {
    00093                         assert(IsAligned<WordType>(m_input));
    00094                         assert(IsAligned<WordType>(m_output));
    00095
    00096                         if (!NativeByteOrderIs(B::ToEnum()))
    00097                                 keystreamWord = ByteReverse(keystreamWord);
    00098
    00099                         if (m_operation == WRITE_KEYSTREAM)
    00100                                 *(WordType*)m_output = keystreamWord;
    00101                         else if (m_operation == XOR_KEYSTREAM)
    00102                         {
    00103                                 *(WordType*)m_output = keystreamWord ^ *(WordType*)m_input;
    00104                                 m_input += sizeof(WordType);
    00105                         }
    00106                         else if (m_operation == XOR_KEYSTREAM_INPLACE)
    00107                                 *(WordType*)m_output ^= keystreamWord;
    00108
    00109                         m_output += sizeof(WordType);
    00110
    00111                         return *this;
    00112                 }
    00113
    00114                 KeystreamOperation m_operation;
    00115                 byte *m_output;
    00116                 const byte *m_input;
    00117         };
    00118 };
    00119
    00120 template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> > >
    00121 class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE
    00122 {
    00123 public:
    00124     byte GenerateByte();
    00125     void ProcessData(byte *outString, const byte *inString, size_t length);
    00126         void Resynchronize(const byte *iv);
    00127         unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();}
    00128         unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;}
    00129         unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
    00130         bool IsSelfInverting() const {return true;}
    00131         bool IsForwardTransformation() const {return true;}
    00132         bool IsRandomAccess() const {return this->GetPolicy().IsRandomAccess();}
    00133         void Seek(lword position);
    00134
    00135         typedef typename BASE::PolicyInterface PolicyInterface;
    00136
    00137 protected:
    00138         void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv);
    00139
    00140         unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();}
    00141
    00142         inline byte * KeystreamBufferBegin() {return this->m_buffer.data();}
    00143         inline byte * KeystreamBufferEnd() {return (this->m_buffer.data() + this->m_buffer.size());}
    00144
    00145         SecByteBlock m_buffer;
    00146         size_t m_leftOver;
    00147 };
    00148
    00149 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy
    00150 {
    00151 public:
    00152         virtual unsigned int GetAlignment() const =0;
    00153         virtual unsigned int GetBytesPerIteration() const =0;
    00154         virtual byte * GetRegisterBegin() =0;
    00155         virtual void TransformRegister() =0;
    00156         virtual bool CanIterate() const {return false;}
    00157         virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) {assert(false);}
    00158         virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
    00159         virtual void CipherResynchronize(const byte *iv) {throw NotImplemented("StreamTransformation: this object doesn't support resynchronization");}
    00160 };
    00161
    00162 template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy>
    00163 struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE
    00164 {
    00165         typedef WT WordType;
    00166
    00167         unsigned int GetAlignment() const {return sizeof(WordType);}
    00168         unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
    00169         bool CanIterate() const {return true;}
    00170         void TransformRegister() {this->Iterate(NULL, NULL, ENCRYPTION, 1);}
    00171
    00172         template <class B>
    00173         struct RegisterOutput
    00174         {
    00175                 RegisterOutput(byte *output, const byte *input, CipherDir dir)
    00176                         : m_output(output), m_input(input), m_dir(dir) {}
    00177
    00178                 inline RegisterOutput& operator()(WordType &registerWord)
    00179                 {
    00180                         assert(IsAligned<WordType>(m_output));
    00181                         assert(IsAligned<WordType>(m_input));
    00182
    00183                         if (!NativeByteOrderIs(B::ToEnum()))
    00184                                 registerWord = ByteReverse(registerWord);
    00185
    00186                         if (m_dir == ENCRYPTION)
    00187                         {
    00188                                 if (m_input == NULL)
    00189                                         assert(m_output == NULL);
    00190                                 else
    00191                                 {
    00192                                         WordType ct = *(const WordType *)m_input ^ registerWord;
    00193                                         registerWord = ct;
    00194                                         *(WordType*)m_output = ct;
    00195                                         m_input += sizeof(WordType);
    00196                                         m_output += sizeof(WordType);
    00197                                 }
    00198                         }
    00199                         else
    00200                         {
    00201                                 WordType ct = *(const WordType *)m_input;
    00202                                 *(WordType*)m_output = registerWord ^ ct;
    00203                                 registerWord = ct;
    00204                                 m_input += sizeof(WordType);
    00205                                 m_output += sizeof(WordType);
    00206                         }
    00207
    00208                         // registerWord is left unreversed so it can be xor-ed with further input
    00209
    00210                         return *this;
    00211                 }
    00212
    00213                 byte *m_output;
    00214                 const byte *m_input;
    00215                 CipherDir m_dir;
    00216         };
    00217 };
    00218
    00219 template <class BASE>
    00220 class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE
    00221 {
    00222 public:
    00223         void ProcessData(byte *outString, const byte *inString, size_t length);
    00224         void Resynchronize(const byte *iv);
    00225         unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();}
    00226         unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;}
    00227         unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
    00228         bool IsRandomAccess() const {return false;}
    00229         bool IsSelfInverting() const {return false;}
    00230
    00231         typedef typename BASE::PolicyInterface PolicyInterface;
    00232
    00233 protected:
    00234         virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) =0;
    00235
    00236         void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv);
    00237
    00238         size_t m_leftOver;
    00239 };
    00240
    00241 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
    00242 class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE>
    00243 {
    00244         bool IsForwardTransformation() const {return true;}
    00245         void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
    00246 };
    00247
    00248 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
    00249 class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE>
    00250 {
    00251         bool IsForwardTransformation() const {return false;}
    00252         void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
    00253 };
    00254
    00255 template <class BASE>
    00256 class CFB_RequireFullDataBlocks : public BASE
    00257 {
    00258 public:
    00259         unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();}
    00260 };
    00261
    00262 //! _
    00263 template <class BASE, class INFO = BASE>
    00264 class SymmetricCipherFinal : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
    00265 {
    00266 public:
    00267         SymmetricCipherFinal() {}
    00268         SymmetricCipherFinal(const byte *key)
    00269                 {SetKey(key, this->DEFAULT_KEYLENGTH);}
    00270         SymmetricCipherFinal(const byte *key, size_t length)
    00271                 {SetKey(key, length);}
    00272         SymmetricCipherFinal(const byte *key, size_t length, const byte *iv)
    00273                 {this->SetKeyWithIV(key, length, iv);}
    00274
    00275         void SetKey(const byte *key, size_t length, const NameValuePairs &params = g_nullNameValuePairs)
    00276         {
    00277                 this->ThrowIfInvalidKeyLength(length);
    00278                 this->UncheckedSetKey(params, key, (unsigned int)length, this->GetIVAndThrowIfInvalid(params));
    00279         }
    00280
    00281         Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinal<BASE, INFO>(*this));}
    00282 };
    00283
    00284 template <class S>
    00285 void AdditiveCipherTemplate<S>::UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv)
    00286 {
    00287         PolicyInterface &policy = this->AccessPolicy();
    00288         policy.CipherSetKey(params, key, length);
    00289         m_leftOver = 0;
    00290         m_buffer.New(GetBufferByteSize(policy));
    00291
    00292         if (this->IsResynchronizable())
    00293                 policy.CipherResynchronize(m_buffer, iv);
    00294 }
    00295
    00296 template <class BASE>
    00297 void CFB_CipherTemplate<BASE>::UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv)
    00298 {
    00299         PolicyInterface &policy = this->AccessPolicy();
    00300         policy.CipherSetKey(params, key, length);
    00301
    00302         if (this->IsResynchronizable())
    00303                 policy.CipherResynchronize(iv);
    00304
    00305         m_leftOver = policy.GetBytesPerIteration();
    00306 }
    00307
    00308 NAMESPACE_END
    00309
    00310 #ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
    00311 #include "strciphr.cpp"
    00312 #endif
    00313
    00314 NAMESPACE_BEGIN(CryptoPP)
    00315 CRYPTOPP_DLL_TEMPLATE_CLASS TwoBases<SymmetricCipher, RandomNumberGenerator>;
    00316 CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> >;
    00317 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<>;
    00318 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
    00319 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<>;
    00320 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<>;
    00321 NAMESPACE_END
    00322
    00323 #endif