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

Generated on Wed Jul 28 08:07:09 2004 for Crypto++ by doxygen 1.3.7