Crypto++
|
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 ¶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 // 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 ¶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 // 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 ¶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