Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | 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 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 KeystreamOperation {WRITE_KEYSTREAM, XOR_KEYSTREAM, XOR_KEYSTREAM_INPLACE}; 00057 00058 struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy 00059 { 00060 virtual unsigned int GetAlignment() const =0; 00061 virtual unsigned int GetBytesPerIteration() const =0; 00062 virtual unsigned int GetIterationsToBuffer() const =0; 00063 virtual void WriteKeystream(byte *keystreamBuffer, unsigned int iterationCount) =0; 00064 virtual bool CanOperateKeystream() const {return false;} 00065 virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount) {assert(false);} 00066 virtual void CipherSetKey(const NameValuePairs &params, const byte *key, unsigned int length) =0; 00067 virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv) {throw NotImplemented("StreamTransformation: this object doesn't support resynchronization");} 00068 virtual bool IsRandomAccess() const =0; 00069 virtual void SeekToIteration(lword iterationCount) {assert(!IsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");} 00070 }; 00071 00072 template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy> 00073 struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE 00074 { 00075 typedef WT WordType; 00076 00077 unsigned int GetAlignment() const {return sizeof(WordType);} 00078 unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;} 00079 unsigned int GetIterationsToBuffer() const {return X;} 00080 void WriteKeystream(byte *buffer, unsigned int iterationCount) 00081 {OperateKeystream(WRITE_KEYSTREAM, buffer, NULL, iterationCount);} 00082 bool CanOperateKeystream() const {return true;} 00083 virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, unsigned int iterationCount) =0; 00084 00085 template <class B> 00086 struct KeystreamOutput 00087 { 00088 KeystreamOutput(KeystreamOperation operation, byte *output, const byte *input) 00089 : m_operation(operation), m_output(output), m_input(input) {} 00090 00091 inline KeystreamOutput & operator()(WordType keystreamWord) 00092 { 00093 assert(IsAligned<WordType>(m_input)); 00094 assert(IsAligned<WordType>(m_output)); 00095 00096 if (!NativeByteOrderIs(B::ToEnum())) 00097 keystreamWord = ByteReverse(keystreamWord); 00098 00099 if (m_operation == WRITE_KEYSTREAM) 00100 *(WordType*)m_output = keystreamWord; 00101 else if (m_operation == XOR_KEYSTREAM) 00102 { 00103 *(WordType*)m_output = keystreamWord ^ *(WordType*)m_input; 00104 m_input += sizeof(WordType); 00105 } 00106 else if (m_operation == XOR_KEYSTREAM_INPLACE) 00107 *(WordType*)m_output ^= keystreamWord; 00108 00109 m_output += sizeof(WordType); 00110 00111 return *this; 00112 } 00113 00114 KeystreamOperation m_operation; 00115 byte *m_output; 00116 const byte *m_input; 00117 }; 00118 }; 00119 00120 template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> > > 00121 class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE 00122 { 00123 public: 00124 byte GenerateByte(); 00125 void ProcessData(byte *outString, const byte *inString, unsigned int length); 00126 void Resynchronize(const byte *iv); 00127 unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();} 00128 unsigned int GetOptimalNextBlockSize() const {return this->m_leftOver;} 00129 unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} 00130 bool IsSelfInverting() const {return true;} 00131 bool IsForwardTransformation() const {return true;} 00132 bool IsRandomAccess() const {return this->GetPolicy().IsRandomAccess();} 00133 void Seek(lword position); 00134 00135 typedef typename BASE::PolicyInterface PolicyInterface; 00136 00137 protected: 00138 void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv); 00139 00140 unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();} 00141 00142 inline byte * KeystreamBufferBegin() {return this->m_buffer.data();} 00143 inline byte * KeystreamBufferEnd() {return (this->m_buffer.data() + this->m_buffer.size());} 00144 00145 SecByteBlock m_buffer; 00146 unsigned int m_leftOver; 00147 }; 00148 00149 CRYPTOPP_DLL_TEMPLATE_CLASS TwoBases<SymmetricCipher, RandomNumberGenerator>; 00150 CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder<AdditiveCipherAbstractPolicy, TwoBases<SymmetricCipher, RandomNumberGenerator> >; 00151 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<>; 00152 00153 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy 00154 { 00155 public: 00156 virtual unsigned int GetAlignment() const =0; 00157 virtual unsigned int GetBytesPerIteration() const =0; 00158 virtual byte * GetRegisterBegin() =0; 00159 virtual void TransformRegister() =0; 00160 virtual bool CanIterate() const {return false;} 00161 virtual void Iterate(byte *output, const byte *input, CipherDir dir, unsigned int iterationCount) {assert(false);} 00162 virtual void CipherSetKey(const NameValuePairs &params, const byte *key, unsigned int length) =0; 00163 virtual void CipherResynchronize(const byte *iv) {throw NotImplemented("StreamTransformation: this object doesn't support resynchronization");} 00164 }; 00165 00166 template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy> 00167 struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE 00168 { 00169 typedef WT WordType; 00170 00171 unsigned int GetAlignment() const {return sizeof(WordType);} 00172 unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;} 00173 bool CanIterate() const {return true;} 00174 void TransformRegister() {this->Iterate(NULL, NULL, ENCRYPTION, 1);} 00175 00176 template <class B> 00177 struct RegisterOutput 00178 { 00179 RegisterOutput(byte *output, const byte *input, CipherDir dir) 00180 : m_output(output), m_input(input), m_dir(dir) {} 00181 00182 inline RegisterOutput& operator()(WordType &registerWord) 00183 { 00184 assert(IsAligned<WordType>(m_output)); 00185 assert(IsAligned<WordType>(m_input)); 00186 00187 if (!NativeByteOrderIs(B::ToEnum())) 00188 registerWord = ByteReverse(registerWord); 00189 00190 if (m_dir == ENCRYPTION) 00191 { 00192 WordType ct = *(const WordType *)m_input ^ registerWord; 00193 registerWord = ct; 00194 *(WordType*)m_output = ct; 00195 m_input += sizeof(WordType); 00196 m_output += sizeof(WordType); 00197 } 00198 else 00199 { 00200 WordType ct = *(const WordType *)m_input; 00201 *(WordType*)m_output = registerWord ^ ct; 00202 registerWord = ct; 00203 m_input += sizeof(WordType); 00204 m_output += sizeof(WordType); 00205 } 00206 00207 // registerWord is left unreversed so it can be xor-ed with further input 00208 00209 return *this; 00210 } 00211 00212 byte *m_output; 00213 const byte *m_input; 00214 CipherDir m_dir; 00215 }; 00216 }; 00217 00218 template <class BASE> 00219 class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE 00220 { 00221 public: 00222 void ProcessData(byte *outString, const byte *inString, unsigned int length); 00223 void Resynchronize(const byte *iv); 00224 unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();} 00225 unsigned int GetOptimalNextBlockSize() const {return m_leftOver;} 00226 unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} 00227 bool IsRandomAccess() const {return false;} 00228 bool IsSelfInverting() const {return false;} 00229 00230 typedef typename BASE::PolicyInterface PolicyInterface; 00231 00232 protected: 00233 virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length) =0; 00234 00235 void UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv); 00236 00237 unsigned int m_leftOver; 00238 }; 00239 00240 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> > 00241 class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE> 00242 { 00243 bool IsForwardTransformation() const {return true;} 00244 void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length); 00245 }; 00246 00247 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> > 00248 class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE> 00249 { 00250 bool IsForwardTransformation() const {return false;} 00251 void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, unsigned int length); 00252 }; 00253 00254 template <class BASE> 00255 class CFB_RequireFullDataBlocks : public BASE 00256 { 00257 public: 00258 unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();} 00259 }; 00260 00261 // for Darwin 00262 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >; 00263 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<>; 00264 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<>; 00265 00266 //! _ 00267 template <class BASE, class INFO = BASE> 00268 class SymmetricCipherFinal : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO> 00269 { 00270 public: 00271 SymmetricCipherFinal() {} 00272 SymmetricCipherFinal(const byte *key) 00273 {SetKey(key, this->DEFAULT_KEYLENGTH);} 00274 SymmetricCipherFinal(const byte *key, unsigned int length) 00275 {SetKey(key, length);} 00276 SymmetricCipherFinal(const byte *key, unsigned int length, const byte *iv) 00277 {this->SetKeyWithIV(key, length, iv);} 00278 00279 void SetKey(const byte *key, unsigned int length, const NameValuePairs &params = g_nullNameValuePairs) 00280 { 00281 this->ThrowIfInvalidKeyLength(length); 00282 this->UncheckedSetKey(params, key, length, this->GetIVAndThrowIfInvalid(params)); 00283 } 00284 00285 Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinal<BASE, INFO>(*this));} 00286 }; 00287 00288 template <class S> 00289 void AdditiveCipherTemplate<S>::UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv) 00290 { 00291 PolicyInterface &policy = this->AccessPolicy(); 00292 policy.CipherSetKey(params, key, length); 00293 m_leftOver = 0; 00294 m_buffer.New(GetBufferByteSize(policy)); 00295 00296 if (this->IsResynchronizable()) 00297 policy.CipherResynchronize(m_buffer, iv); 00298 } 00299 00300 template <class BASE> 00301 void CFB_CipherTemplate<BASE>::UncheckedSetKey(const NameValuePairs &params, const byte *key, unsigned int length, const byte *iv) 00302 { 00303 PolicyInterface &policy = this->AccessPolicy(); 00304 policy.CipherSetKey(params, key, length); 00305 00306 if (this->IsResynchronizable()) 00307 policy.CipherResynchronize(iv); 00308 00309 m_leftOver = policy.GetBytesPerIteration(); 00310 } 00311 00312 NAMESPACE_END 00313 00314 #endif

Generated on Fri Aug 27 14:01:26 2004 for Crypto++ by doxygen 1.3.8