• 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 Mon Aug 9 2010 15:56:38 for Crypto++ by  doxygen 1.7.1