- 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 CipherGetNextIV(byte *iv) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support GetNextIV()");}
    00068         virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
    00069         virtual bool IsRandomAccess() const =0;
    00070         virtual void SeekToIteration(lword iterationCount) {assert(!IsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");}
    00071 };
    00072
    00073 template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy>
    00074 struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE
    00075 {
    00076         typedef WT WordType;
    00077
    00078         unsigned int GetAlignment() const {return sizeof(WordType);}
    00079         unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
    00080         unsigned int GetIterationsToBuffer() const {return X;}
    00081         void WriteKeystream(byte *buffer, size_t iterationCount)
    00082                 {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
    00083         bool CanOperateKeystream() const {return true;}
    00084         virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0;
    00085
    00086         template <class B>
    00087         struct KeystreamOutput
    00088         {
    00089                 KeystreamOutput(KeystreamOperation operation, byte *output, const byte *input)
    00090                         : m_operation(operation), m_output(output), m_input(input) {}
    00091
    00092                 inline KeystreamOutput & operator()(WordType keystreamWord)
    00093                 {
    00094                         assert(IsAligned<WordType>(m_input));
    00095                         assert(IsAligned<WordType>(m_output));
    00096
    00097                         if (!NativeByteOrderIs(B::ToEnum()))
    00098                                 keystreamWord = ByteReverse(keystreamWord);
    00099
    00100                         if (m_operation == WRITE_KEYSTREAM)
    00101                                 *(WordType*)m_output = keystreamWord;
    00102                         else if (m_operation == XOR_KEYSTREAM)
    00103                         {
    00104                                 *(WordType*)m_output = keystreamWord ^ *(WordType*)m_input;
    00105                                 m_input += sizeof(WordType);
    00106                         }
    00107                         else if (m_operation == XOR_KEYSTREAM_INPLACE)
    00108                                 *(WordType*)m_output ^= keystreamWord;
    00109
    00110                         m_output += sizeof(WordType);
    00111
    00112                         return *this;
    00113                 }
    00114
    00115                 KeystreamOperation m_operation;
    00116                 byte *m_output;
    00117                 const byte *m_input;
    00118         };
    00119 };
    00120
    00121 template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> > >
    00122 class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE
    00123 {
    00124 public:
    00125     byte GenerateByte();
    00126     void ProcessData(byte *outString, const byte *inString, size_t length);
    00127         void GetNextIV(byte *iv) {this->AccessPolicy().CipherGetNextIV(iv);}
    00128         void Resynchronize(const byte *iv);
    00129         unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();}
    00130         unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;}
    00131         unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
    00132         bool IsSelfInverting() const {return true;}
    00133         bool IsForwardTransformation() const {return true;}
    00134         bool IsRandomAccess() const {return this->GetPolicy().IsRandomAccess();}
    00135         void Seek(lword position);
    00136
    00137         typedef typename BASE::PolicyInterface PolicyInterface;
    00138
    00139 protected:
    00140         void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
    00141
    00142         unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();}
    00143
    00144         inline byte * KeystreamBufferBegin() {return this->m_buffer.data();}
    00145         inline byte * KeystreamBufferEnd() {return (this->m_buffer.data() + this->m_buffer.size());}
    00146
    00147         SecByteBlock m_buffer;
    00148         size_t m_leftOver;
    00149 };
    00150
    00151 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy
    00152 {
    00153 public:
    00154         virtual unsigned int GetAlignment() const =0;
    00155         virtual unsigned int GetBytesPerIteration() const =0;
    00156         virtual byte * GetRegisterBegin() =0;
    00157         virtual void TransformRegister() =0;
    00158         virtual bool CanIterate() const {return false;}
    00159         virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) {assert(false);}
    00160         virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
    00161         virtual void CipherGetNextIV(byte *iv) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support GetNextIV()");}
    00162         virtual void CipherResynchronize(const byte *iv) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
    00163 };
    00164
    00165 template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy>
    00166 struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE
    00167 {
    00168         typedef WT WordType;
    00169
    00170         unsigned int GetAlignment() const {return sizeof(WordType);}
    00171         unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
    00172         bool CanIterate() const {return true;}
    00173         void TransformRegister() {this->Iterate(NULL, NULL, ENCRYPTION, 1);}
    00174
    00175         template <class B>
    00176         struct RegisterOutput
    00177         {
    00178                 RegisterOutput(byte *output, const byte *input, CipherDir dir)
    00179                         : m_output(output), m_input(input), m_dir(dir) {}
    00180
    00181                 inline RegisterOutput& operator()(WordType &registerWord)
    00182                 {
    00183                         assert(IsAligned<WordType>(m_output));
    00184                         assert(IsAligned<WordType>(m_input));
    00185
    00186                         if (!NativeByteOrderIs(B::ToEnum()))
    00187                                 registerWord = ByteReverse(registerWord);
    00188
    00189                         if (m_dir == ENCRYPTION)
    00190                         {
    00191                                 if (m_input == NULL)
    00192                                         assert(m_output == NULL);
    00193                                 else
    00194                                 {
    00195                                         WordType ct = *(const WordType *)m_input ^ registerWord;
    00196                                         registerWord = ct;
    00197                                         *(WordType*)m_output = ct;
    00198                                         m_input += sizeof(WordType);
    00199                                         m_output += sizeof(WordType);
    00200                                 }
    00201                         }
    00202                         else
    00203                         {
    00204                                 WordType ct = *(const WordType *)m_input;
    00205                                 *(WordType*)m_output = registerWord ^ ct;
    00206                                 registerWord = ct;
    00207                                 m_input += sizeof(WordType);
    00208                                 m_output += sizeof(WordType);
    00209                         }
    00210
    00211                         // registerWord is left unreversed so it can be xor-ed with further input
    00212
    00213                         return *this;
    00214                 }
    00215
    00216                 byte *m_output;
    00217                 const byte *m_input;
    00218                 CipherDir m_dir;
    00219         };
    00220 };
    00221
    00222 template <class BASE>
    00223 class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE
    00224 {
    00225 public:
    00226         void ProcessData(byte *outString, const byte *inString, size_t length);
    00227         void GetNextIV(byte *iv) {this->AccessPolicy().CipherGetNextIV(iv);}
    00228         void Resynchronize(const byte *iv);
    00229         unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();}
    00230         unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;}
    00231         unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
    00232         bool IsRandomAccess() const {return false;}
    00233         bool IsSelfInverting() const {return false;}
    00234
    00235         typedef typename BASE::PolicyInterface PolicyInterface;
    00236
    00237 protected:
    00238         virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) =0;
    00239
    00240         void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
    00241
    00242         size_t m_leftOver;
    00243 };
    00244
    00245 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
    00246 class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE>
    00247 {
    00248         bool IsForwardTransformation() const {return true;}
    00249         void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
    00250 };
    00251
    00252 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
    00253 class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE>
    00254 {
    00255         bool IsForwardTransformation() const {return false;}
    00256         void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
    00257 };
    00258
    00259 template <class BASE>
    00260 class CFB_RequireFullDataBlocks : public BASE
    00261 {
    00262 public:
    00263         unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();}
    00264 };
    00265
    00266 //! _
    00267 template <class BASE, class INFO = BASE>
    00268 class SymmetricCipherFinal : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
    00269 {
    00270 public:
    00271         SymmetricCipherFinal() {}
    00272         SymmetricCipherFinal(const byte *key)
    00273                 {this->SetKey(key, this->DEFAULT_KEYLENGTH);}
    00274         SymmetricCipherFinal(const byte *key, size_t length)
    00275                 {this->SetKey(key, length);}
    00276         SymmetricCipherFinal(const byte *key, size_t length, const byte *iv)
    00277                 {this->SetKeyWithIV(key, length, iv);}
    00278
    00279         Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinal<BASE, INFO>(*this));}
    00280 };
    00281
    00282 NAMESPACE_END
    00283
    00284 #ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
    00285 #include "strciphr.cpp"
    00286 #endif
    00287
    00288 NAMESPACE_BEGIN(CryptoPP)
    00289 CRYPTOPP_DLL_TEMPLATE_CLASS TwoBases<SymmetricCipher, RandomNumberGenerator>;
    00290 CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> >;
    00291 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> > >;
    00292 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
    00293 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
    00294 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
    00295 NAMESPACE_END
    00296
    00297 #endif