00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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 ¶ms, 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
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 ¶ms);
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 ¶ms, 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 ®isterWord)
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
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 ¶ms);
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