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

Generated on Sun Sep 16 18:29:53 2007 for Crypto++ by  doxygen 1.5.3