Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | 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 SymmetricCipherFinalTemplate<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, SymmetricCipherFinalTemplate 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
    00034 NAMESPACE_BEGIN(CryptoPP)
    00035
    00036 template <class POLICY_INTERFACE, class BASE = Empty>
    00037 class AbstractPolicyHolder : public BASE
    00038 {
    00039 public:
    00040         typedef POLICY_INTERFACE PolicyInterface;
    00041
    00042 protected:
    00043         virtual const POLICY_INTERFACE & GetPolicy() const =0;
    00044         virtual POLICY_INTERFACE & AccessPolicy() =0;
    00045 };
    00046
    00047 template <class POLICY, class BASE, class POLICY_INTERFACE = CPP_TYPENAME BASE::PolicyInterface>
    00048 class ConcretePolicyHolder : public BASE, protected POLICY
    00049 {
    00050 protected:
    00051         const POLICY_INTERFACE & GetPolicy() const {return *this;}
    00052         POLICY_INTERFACE & AccessPolicy() {return *this;}
    00053 };
    00054
    00055 enum KeystreamOperation {WRITE_KEYSTREAM, XOR_KEYSTREAM, XOR_KEYSTREAM_INPLACE};
    00056
    00057 struct CRYPTOPP_DLL AdditiveCipherAbstractPolicy
    00058 {
    00059         virtual unsigned int GetAlignment() const =0;
    00060         virtual unsigned int GetBytesPerIteration() const =0;
    00061         virtual unsigned int GetIterationsToBuffer() const =0;
    00062         virtual void WriteKeystream(byte *keystreamBuffer, unsigned int iterationCount) =0;
    00063         virtual bool CanOperateKeystream() const {return false;}
    00064         virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount) {assert(false);}
    00065         virtual void CipherSetKey(const NameValuePairs &params, const byte *key, unsigned int length) =0;
    00066         virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv) {throw NotImplemented("StreamTransformation: this object doesn't support resynchronization");}
    00067         virtual bool IsRandomAccess() const =0;
    00068         virtual void SeekToIteration(dword iterationCount) {assert(!IsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");}
    00069 };
    00070
    00071 template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy>
    00072 struct AdditiveCipherConcretePolicy : public BASE
    00073 {
    00074         typedef WT WordType;
    00075
    00076         unsigned int GetAlignment() const {return sizeof(WordType);}
    00077         unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
    00078         unsigned int GetIterationsToBuffer() const {return X;}
    00079         void WriteKeystream(byte *buffer, unsigned int iterationCount)
    00080                 {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);}
    00081         bool CanOperateKeystream() const {return true;}
    00082         virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount) =0;
    00083
    00084         template <class B>
    00085         struct KeystreamOutput
    00086         {
    00087                 KeystreamOutput(KeystreamOperation operation, byte *output, const byte *input)
    00088                         : m_operation(operation), m_output(output), m_input(input) {}
    00089
    00090                 inline KeystreamOutput & operator()(WordType keystreamWord)
    00091                 {
    00092                         assert(IsAligned<WordType>(m_input));
    00093                         assert(IsAligned<WordType>(m_output));
    00094
    00095                         if (!NativeByteOrderIs(B::ToEnum()))
    00096                                 keystreamWord = ByteReverse(keystreamWord);
    00097
    00098                         if (m_operation == WRITE_KEYSTREAM)
    00099                                 *(WordType*)m_output = keystreamWord;
    00100                         else if (m_operation == XOR_KEYSTREAM)
    00101                         {
    00102                                 *(WordType*)m_output = keystreamWord ^ *(WordType*)m_input;
    00103                                 m_input += sizeof(WordType);
    00104                         }
    00105                         else if (m_operation == XOR_KEYSTREAM_INPLACE)
    00106                                 *(WordType*)m_output ^= keystreamWord;
    00107
    00108                         m_output += sizeof(WordType);
    00109
    00110                         return *this;
    00111                 }
    00112
    00113                 KeystreamOperation m_operation;
    00114                 byte *m_output;
    00115                 const byte *m_input;
    00116         };
    00117 };
    00118
    00119 template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> > >
    00120 class AdditiveCipherTemplate : public BASE
    00121 {
    00122 public:
    00123     byte GenerateByte();
    00124     void ProcessData(byte *outString, const byte *inString, unsigned int length);
    00125         void Resynchronize(const byte *iv);
    00126         unsigned int OptimalBlockSize() const {return GetPolicy().GetBytesPerIteration();}
    00127         unsigned int GetOptimalNextBlockSize() const {return m_leftOver;}
    00128         unsigned int OptimalDataAlignment() const {return GetPolicy().GetAlignment();}
    00129         bool IsSelfInverting() const {return true;}
    00130         bool IsForwardTransformation() const {return true;}
    00131         bool IsRandomAccess() const {return GetPolicy().IsRandomAccess();}
    00132         void Seek(dword position);
    00133
    00134         typedef typename BASE::PolicyInterface PolicyInterface;
    00135
    00136 protected:
    00137         void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length);
    00138
    00139         unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();}
    00140
    00141         inline byte * KeystreamBufferBegin() {return m_buffer.data();}
    00142         inline byte * KeystreamBufferEnd() {return (m_buffer.data() + m_buffer.size());}
    00143
    00144         SecByteBlock m_buffer;
    00145         unsigned int m_leftOver;
    00146 };
    00147
    00148 CRYPTOPP_DLL_TEMPLATE_CLASS TwoBases<SymmetricCipher, RandomNumberGenerator>;
    00149 CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> >;
    00150 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<>;
    00151
    00152 class CRYPTOPP_DLL CFB_CipherAbstractPolicy
    00153 {
    00154 public:
    00155         virtual unsigned int GetAlignment() const =0;
    00156         virtual unsigned int GetBytesPerIteration() const =0;
    00157         virtual byte * GetRegisterBegin() =0;
    00158         virtual void TransformRegister() =0;
    00159         virtual bool CanIterate() const {return false;}
    00160         virtual void Iterate(byte *output, const byte *input, CipherDir dir, unsigned int iterationCount) {assert(false);}
    00161         virtual void CipherSetKey(const NameValuePairs &params, const byte *key, unsigned int length) =0;
    00162         virtual void CipherResynchronize(const byte *iv) {throw NotImplemented("StreamTransformation: this object doesn't support resynchronization");}
    00163 };
    00164
    00165 template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy>
    00166 struct 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() {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                                 WordType ct = *(const WordType *)m_input ^ registerWord;
    00192                                 registerWord = ct;
    00193                                 *(WordType*)m_output = ct;
    00194                                 m_input += sizeof(WordType);
    00195                                 m_output += sizeof(WordType);
    00196                         }
    00197                         else
    00198                         {
    00199                                 WordType ct = *(const WordType *)m_input;
    00200                                 *(WordType*)m_output = registerWord ^ ct;
    00201                                 registerWord = ct;
    00202                                 m_input += sizeof(WordType);
    00203                                 m_output += sizeof(WordType);
    00204                         }
    00205
    00206                         // registerWord is left unreversed so it can be xor-ed with further input
    00207
    00208                         return *this;
    00209                 }
    00210
    00211                 byte *m_output;
    00212                 const byte *m_input;
    00213                 CipherDir m_dir;
    00214         };
    00215 };
    00216
    00217 template <class BASE>
    00218 class CFB_CipherTemplate : public BASE
    00219 {
    00220 public:
    00221         void ProcessData(byte *outString, const byte *inString, unsigned int length);
    00222         void Resynchronize(const byte *iv);
    00223         unsigned int OptimalBlockSize() const {return GetPolicy().GetBytesPerIteration();}
    00224         unsigned int GetOptimalNextBlockSize() const {return m_leftOver;}
    00225         unsigned int OptimalDataAlignment() const {return GetPolicy().GetAlignment();}
    00226         bool IsRandomAccess() const {return false;}
    00227         bool IsSelfInverting() const {return false;}
    00228
    00229         typedef typename BASE::PolicyInterface PolicyInterface;
    00230
    00231 protected:
    00232         virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length) =0;
    00233
    00234         void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length);
    00235
    00236         unsigned int m_leftOver;
    00237 };
    00238
    00239 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
    00240 class CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE>
    00241 {
    00242         bool IsForwardTransformation() const {return true;}
    00243         void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length);
    00244 };
    00245
    00246 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
    00247 class CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE>
    00248 {
    00249         bool IsForwardTransformation() const {return false;}
    00250         void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length);
    00251 };
    00252
    00253 CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher>;
    00254 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
    00255 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<>;
    00256 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<>;
    00257
    00258 template <class BASE, class INFO = BASE>
    00259 class SymmetricCipherFinalTemplate : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
    00260 {
    00261 public:
    00262         SymmetricCipherFinalTemplate() {}
    00263         SymmetricCipherFinalTemplate(const byte *key)
    00264                 {SetKey(key, DEFAULT_KEYLENGTH);}
    00265         SymmetricCipherFinalTemplate(const byte *key, unsigned int length)
    00266                 {SetKey(key, length);}
    00267         SymmetricCipherFinalTemplate(const byte *key, unsigned int length, const byte *iv)
    00268                 {SetKey(key, length); Resynchronize(iv);}
    00269
    00270         void SetKey(const byte *key, unsigned int length, const NameValuePairs &params = g_nullNameValuePairs)
    00271         {
    00272                 ThrowIfInvalidKeyLength(length);
    00273                 UncheckedSetKey(params, key, length);
    00274         }
    00275
    00276         Clonable * Clone() {return new SymmetricCipherFinalTemplate<BASE, INFO>(*this);}
    00277 };
    00278
    00279 template <class S>
    00280 void AdditiveCipherTemplate<S>::UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length)
    00281 {
    00282         PolicyInterface &policy = AccessPolicy();
    00283         policy.CipherSetKey(params, key, length);
    00284         m_buffer.New(GetBufferByteSize(policy));
    00285         m_leftOver = 0;
    00286 }
    00287
    00288 template <class BASE>
    00289 void CFB_CipherTemplate<BASE>::UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length)
    00290 {
    00291         PolicyInterface &policy = AccessPolicy();
    00292         policy.CipherSetKey(params, key, length);
    00293         m_leftOver = policy.GetBytesPerIteration();
    00294 }
    00295
    00296 NAMESPACE_END
    00297
    00298 #endif