- Main Page
- Namespaces
- Classes
- Files

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