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

Generated on Tue Jul 8 23:34:26 2003 for Crypto++ by doxygen 1.3.2