- Main Page
- Namespaces
- Classes
- Files

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