Crypto++

- 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     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