Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class 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 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 struct CFB_CipherAbstractPolicy
00149 {
00150         virtual unsigned int GetAlignment() const =0;
00151         virtual unsigned int GetBytesPerIteration() const =0;
00152         virtual byte * GetRegisterBegin() =0;
00153         virtual void TransformRegister() =0;
00154         virtual bool CanIterate() const {return false;}
00155         virtual void Iterate(byte *output, const byte *input, CipherDir dir, unsigned int iterationCount) {assert(false);}
00156         virtual void CipherSetKey(const NameValuePairs &params, const byte *key, unsigned int length) =0;
00157         virtual void CipherResynchronize(const byte *iv) {throw NotImplemented("StreamTransformation: this object doesn't support resynchronization");}
00158 };
00159 
00160 template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy>
00161 struct CFB_CipherConcretePolicy : public BASE
00162 {
00163         typedef WT WordType;
00164 
00165         unsigned int GetAlignment() const {return sizeof(WordType);}
00166         unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
00167         bool CanIterate() const {return true;}
00168         void TransformRegister() {Iterate(NULL, NULL, ENCRYPTION, 1);}
00169 
00170         template <class B>
00171         struct RegisterOutput
00172         {
00173                 RegisterOutput(byte *output, const byte *input, CipherDir dir)
00174                         : m_output(output), m_input(input), m_dir(dir) {}
00175 
00176                 inline RegisterOutput& operator()(WordType &registerWord)
00177                 {
00178                         assert(IsAligned<WordType>(m_output));
00179                         assert(IsAligned<WordType>(m_input));
00180 
00181                         if (!NativeByteOrderIs(B::ToEnum()))
00182                                 registerWord = ByteReverse(registerWord);
00183 
00184                         if (m_dir == ENCRYPTION)
00185                         {
00186                                 WordType ct = *(const WordType *)m_input ^ registerWord;
00187                                 registerWord = ct;
00188                                 *(WordType*)m_output = ct;
00189                                 m_input += sizeof(WordType);
00190                                 m_output += sizeof(WordType);
00191                         }
00192                         else
00193                         {
00194                                 WordType ct = *(const WordType *)m_input;
00195                                 *(WordType*)m_output = registerWord ^ ct;
00196                                 registerWord = ct;
00197                                 m_input += sizeof(WordType);
00198                                 m_output += sizeof(WordType);
00199                         }
00200 
00201                         // registerWord is left unreversed so it can be xor-ed with further input
00202 
00203                         return *this;
00204                 }
00205 
00206                 byte *m_output;
00207                 const byte *m_input;
00208                 CipherDir m_dir;
00209         };
00210 };
00211 
00212 template <class BASE>
00213 class CFB_CipherTemplate : public BASE
00214 {
00215 public:
00216         void ProcessData(byte *outString, const byte *inString, unsigned int length);
00217         void Resynchronize(const byte *iv);
00218         unsigned int OptimalBlockSize() const {return GetPolicy().GetBytesPerIteration();}
00219         unsigned int GetOptimalNextBlockSize() const {return m_leftOver;}
00220         unsigned int OptimalDataAlignment() const {return GetPolicy().GetAlignment();}
00221         bool IsRandomAccess() const {return false;}
00222         bool IsSelfInverting() const {return false;}
00223 
00224         typedef typename BASE::PolicyInterface PolicyInterface;
00225 
00226 protected:
00227         virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length) =0;
00228 
00229         void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length);
00230 
00231         unsigned int m_leftOver;
00232 };
00233 
00234 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
00235 class CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE>
00236 {
00237         bool IsForwardTransformation() const {return true;}
00238         void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length);
00239 };
00240 
00241 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
00242 class CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE>
00243 {
00244         bool IsForwardTransformation() const {return false;}
00245         void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length);
00246 };
00247 
00248 template <class BASE, class INFO = BASE>
00249 class SymmetricCipherFinalTemplate : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
00250 {
00251 public:
00252         SymmetricCipherFinalTemplate() {}
00253         SymmetricCipherFinalTemplate(const byte *key)
00254                 {SetKey(key, DEFAULT_KEYLENGTH);}
00255         SymmetricCipherFinalTemplate(const byte *key, unsigned int length)
00256                 {SetKey(key, length);}
00257         SymmetricCipherFinalTemplate(const byte *key, unsigned int length, const byte *iv)
00258                 {SetKey(key, length); Resynchronize(iv);}
00259 
00260         void SetKey(const byte *key, unsigned int length, const NameValuePairs &params = g_nullNameValuePairs)
00261         {
00262                 ThrowIfInvalidKeyLength(length);
00263                 UncheckedSetKey(params, key, length);
00264         }
00265 
00266         Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinalTemplate<BASE, INFO>(*this));}
00267 };
00268 
00269 template <class S>
00270 void AdditiveCipherTemplate<S>::UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length)
00271 {
00272         PolicyInterface &policy = AccessPolicy();
00273         policy.CipherSetKey(params, key, length);
00274         m_buffer.New(GetBufferByteSize(policy));
00275         m_leftOver = 0;
00276 }
00277 
00278 template <class BASE>
00279 void CFB_CipherTemplate<BASE>::UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length)
00280 {
00281         PolicyInterface &policy = AccessPolicy();
00282         policy.CipherSetKey(params, key, length);
00283         m_leftOver = policy.GetBytesPerIteration();
00284 }
00285 
00286 NAMESPACE_END
00287 
00288 #endif

Generated on Sun Mar 14 20:44:29 2004 for Crypto++ by doxygen 1.3.6-20040222