Crypto++
strciphr.h
Go to the documentation of this file.
1 /*! \file
2  This file contains helper classes for implementing stream ciphers.
3 
4  All this infrastructure may look very complex compared to what's in Crypto++ 4.x,
5  but stream ciphers implementations now support a lot of new functionality,
6  including better performance (minimizing copying), resetting of keys and IVs, and methods to
7  query which features are supported by a cipher.
8 
9  Here's an explanation of these classes. The word "policy" is used here to mean a class with a
10  set of methods that must be implemented by individual stream cipher implementations.
11  This is usually much simpler than the full stream cipher API, which is implemented by
12  either AdditiveCipherTemplate or CFB_CipherTemplate using the policy. So for example, an
13  implementation of SEAL only needs to implement the AdditiveCipherAbstractPolicy interface
14  (since it's an additive cipher, i.e., it xors a keystream into the plaintext).
15  See this line in seal.h:
16 
17  typedef SymmetricCipherFinal<ConcretePolicyHolder<SEAL_Policy<B>, AdditiveCipherTemplate<> > > Encryption;
18 
19  AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't need
20  to take a policy class as a template parameter (although this is allowed), so that
21  their code is not duplicated for each new cipher. Instead they each
22  get a reference to an abstract policy interface by calling AccessPolicy() on itself, so
23  AccessPolicy() must be overriden to return the actual policy reference. This is done
24  by the ConceretePolicyHolder class. Finally, SymmetricCipherFinal implements the constructors and
25  other functions that must be implemented by the most derived class.
26 */
27 
28 #ifndef CRYPTOPP_STRCIPHR_H
29 #define CRYPTOPP_STRCIPHR_H
30 
31 #include "seckey.h"
32 #include "secblock.h"
33 #include "argnames.h"
34 
35 NAMESPACE_BEGIN(CryptoPP)
36 
37 template <class POLICY_INTERFACE, class BASE = Empty>
38 class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE
39 {
40 public:
41  typedef POLICY_INTERFACE PolicyInterface;
42  virtual ~AbstractPolicyHolder() {}
43 
44 protected:
45  virtual const POLICY_INTERFACE & GetPolicy() const =0;
46  virtual POLICY_INTERFACE & AccessPolicy() =0;
47 };
48 
49 template <class POLICY, class BASE, class POLICY_INTERFACE = CPP_TYPENAME BASE::PolicyInterface>
50 class ConcretePolicyHolder : public BASE, protected POLICY
51 {
52 protected:
53  const POLICY_INTERFACE & GetPolicy() const {return *this;}
54  POLICY_INTERFACE & AccessPolicy() {return *this;}
55 };
56 
57 enum KeystreamOperationFlags {OUTPUT_ALIGNED=1, INPUT_ALIGNED=2, INPUT_NULL = 4};
58 enum KeystreamOperation {
59  WRITE_KEYSTREAM = INPUT_NULL,
60  WRITE_KEYSTREAM_ALIGNED = INPUT_NULL | OUTPUT_ALIGNED,
61  XOR_KEYSTREAM = 0,
62  XOR_KEYSTREAM_INPUT_ALIGNED = INPUT_ALIGNED,
63  XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED,
64  XOR_KEYSTREAM_BOTH_ALIGNED = OUTPUT_ALIGNED | INPUT_ALIGNED};
65 
66 struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy
67 {
68  virtual ~AdditiveCipherAbstractPolicy() {}
69  virtual unsigned int GetAlignment() const {return 1;}
70  virtual unsigned int GetBytesPerIteration() const =0;
71  virtual unsigned int GetOptimalBlockSize() const {return GetBytesPerIteration();}
72  virtual unsigned int GetIterationsToBuffer() const =0;
73  virtual void WriteKeystream(byte *keystream, size_t iterationCount)
74  {OperateKeystream(KeystreamOperation(INPUT_NULL | (KeystreamOperationFlags)IsAlignedOn(keystream, GetAlignment())), keystream, NULL, iterationCount);}
75  virtual bool CanOperateKeystream() const {return false;}
76  virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) {assert(false);}
77  virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
78  virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
79  virtual bool CipherIsRandomAccess() const =0;
80  virtual void SeekToIteration(lword iterationCount) {assert(!CipherIsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");}
81 };
82 
83 template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy>
84 struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE
85 {
86  typedef WT WordType;
87  CRYPTOPP_CONSTANT(BYTES_PER_ITERATION = sizeof(WordType) * W)
88 
89 #if !(CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64)
90  unsigned int GetAlignment() const {return GetAlignmentOf<WordType>();}
91 #endif
92  unsigned int GetBytesPerIteration() const {return BYTES_PER_ITERATION;}
93  unsigned int GetIterationsToBuffer() const {return X;}
94  bool CanOperateKeystream() const {return true;}
95  virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0;
96 };
97 
98 // use these to implement OperateKeystream
99 #define CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, b, i, a) \
100  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)));
101 #define CRYPTOPP_KEYSTREAM_OUTPUT_XMM(x, i, a) {\
102  __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));\
103  if (x & OUTPUT_ALIGNED) _mm_store_si128((__m128i *)output+i, t);\
104  else _mm_storeu_si128((__m128i *)output+i, t);}
105 #define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y) \
106  switch (operation) \
107  { \
108  case WRITE_KEYSTREAM: \
109  x(WRITE_KEYSTREAM) \
110  break; \
111  case XOR_KEYSTREAM: \
112  x(XOR_KEYSTREAM) \
113  input += y; \
114  break; \
115  case XOR_KEYSTREAM_INPUT_ALIGNED: \
116  x(XOR_KEYSTREAM_INPUT_ALIGNED) \
117  input += y; \
118  break; \
119  case XOR_KEYSTREAM_OUTPUT_ALIGNED: \
120  x(XOR_KEYSTREAM_OUTPUT_ALIGNED) \
121  input += y; \
122  break; \
123  case WRITE_KEYSTREAM_ALIGNED: \
124  x(WRITE_KEYSTREAM_ALIGNED) \
125  break; \
126  case XOR_KEYSTREAM_BOTH_ALIGNED: \
127  x(XOR_KEYSTREAM_BOTH_ALIGNED) \
128  input += y; \
129  break; \
130  } \
131  output += y;
132 
133 template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >
134 class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE, public RandomNumberGenerator
135 {
136 public:
137  void GenerateBlock(byte *output, size_t size);
138  void ProcessData(byte *outString, const byte *inString, size_t length);
139  void Resynchronize(const byte *iv, int length=-1);
140  unsigned int OptimalBlockSize() const {return this->GetPolicy().GetOptimalBlockSize();}
141  unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;}
142  unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
143  bool IsSelfInverting() const {return true;}
144  bool IsForwardTransformation() const {return true;}
145  bool IsRandomAccess() const {return this->GetPolicy().CipherIsRandomAccess();}
146  void Seek(lword position);
147 
148  typedef typename BASE::PolicyInterface PolicyInterface;
149 
150 protected:
151  void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
152 
153  unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();}
154 
155  inline byte * KeystreamBufferBegin() {return this->m_buffer.data();}
156  inline byte * KeystreamBufferEnd() {return (this->m_buffer.data() + this->m_buffer.size());}
157 
158  SecByteBlock m_buffer;
159  size_t m_leftOver;
160 };
161 
162 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy
163 {
164 public:
165  virtual ~CFB_CipherAbstractPolicy() {}
166  virtual unsigned int GetAlignment() const =0;
167  virtual unsigned int GetBytesPerIteration() const =0;
168  virtual byte * GetRegisterBegin() =0;
169  virtual void TransformRegister() =0;
170  virtual bool CanIterate() const {return false;}
171  virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) {assert(false); throw 0;}
172  virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
173  virtual void CipherResynchronize(const byte *iv, size_t length) {throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
174 };
175 
176 template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy>
177 struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE
178 {
179  typedef WT WordType;
180 
181  unsigned int GetAlignment() const {return sizeof(WordType);}
182  unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
183  bool CanIterate() const {return true;}
184  void TransformRegister() {this->Iterate(NULL, NULL, ENCRYPTION, 1);}
185 
186  template <class B>
188  {
189  RegisterOutput(byte *output, const byte *input, CipherDir dir)
190  : m_output(output), m_input(input), m_dir(dir) {}
191 
192  inline RegisterOutput& operator()(WordType &registerWord)
193  {
194  assert(IsAligned<WordType>(m_output));
195  assert(IsAligned<WordType>(m_input));
196 
197  if (!NativeByteOrderIs(B::ToEnum()))
198  registerWord = ByteReverse(registerWord);
199 
200  if (m_dir == ENCRYPTION)
201  {
202  if (m_input == NULL)
203  assert(m_output == NULL);
204  else
205  {
206  WordType ct = *(const WordType *)m_input ^ registerWord;
207  registerWord = ct;
208  *(WordType*)m_output = ct;
209  m_input += sizeof(WordType);
210  m_output += sizeof(WordType);
211  }
212  }
213  else
214  {
215  WordType ct = *(const WordType *)m_input;
216  *(WordType*)m_output = registerWord ^ ct;
217  registerWord = ct;
218  m_input += sizeof(WordType);
219  m_output += sizeof(WordType);
220  }
221 
222  // registerWord is left unreversed so it can be xor-ed with further input
223 
224  return *this;
225  }
226 
227  byte *m_output;
228  const byte *m_input;
229  CipherDir m_dir;
230  };
231 };
232 
233 template <class BASE>
234 class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE
235 {
236 public:
237  void ProcessData(byte *outString, const byte *inString, size_t length);
238  void Resynchronize(const byte *iv, int length=-1);
239  unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();}
240  unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;}
241  unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
242  bool IsRandomAccess() const {return false;}
243  bool IsSelfInverting() const {return false;}
244 
245  typedef typename BASE::PolicyInterface PolicyInterface;
246 
247 protected:
248  virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) =0;
249 
250  void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
251 
252  size_t m_leftOver;
253 };
254 
255 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
256 class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE>
257 {
258  bool IsForwardTransformation() const {return true;}
259  void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
260 };
261 
262 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
263 class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE>
264 {
265  bool IsForwardTransformation() const {return false;}
266  void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
267 };
268 
269 template <class BASE>
270 class CFB_RequireFullDataBlocks : public BASE
271 {
272 public:
273  unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();}
274 };
275 
276 //! _
277 template <class BASE, class INFO = BASE>
278 class SymmetricCipherFinal : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
279 {
280 public:
282  SymmetricCipherFinal(const byte *key)
283  {this->SetKey(key, this->DEFAULT_KEYLENGTH);}
284  SymmetricCipherFinal(const byte *key, size_t length)
285  {this->SetKey(key, length);}
286  SymmetricCipherFinal(const byte *key, size_t length, const byte *iv)
287  {this->SetKeyWithIV(key, length, iv);}
288 
289  Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinal<BASE, INFO>(*this));}
290 };
291 
292 NAMESPACE_END
293 
294 #ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
295 #include "strciphr.cpp"
296 #endif
297 
298 NAMESPACE_BEGIN(CryptoPP)
300 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >;
301 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
302 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
303 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
304 NAMESPACE_END
305 
306 #endif
CipherDir
used to specify a direction for a cipher to operate in (encrypt or decrypt)
Definition: cryptlib.h:92
interface for random number generators
Definition: cryptlib.h:668
interface for cloning objects, this is not implemented by most classes yet
Definition: cryptlib.h:325
exception thrown by a class if a non-implemented method is called
Definition: cryptlib.h:165
interface for one direction (encryption or decryption) of a stream cipher or cipher mode ...
Definition: cryptlib.h:610
virtual void GenerateBlock(byte *output, size_t size)
generate random array of bytes
Definition: misc.h:66
interface for retrieving values given their names
Definition: cryptlib.h:224