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

Generated on Tue Aug 16 08:38:43 2005 for Crypto++ by  doxygen 1.3.9.1