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 Thu Jul 5 22:21:38 2007 for Crypto++ by  doxygen 1.5.2