• 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

Generated on Sun Oct 17 2010 02:13:04 for Crypto++ by  doxygen 1.7.1