Crypto++  5.6.3
Free C++ class library of cryptographic schemes
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 "config.h"
32 
33 #if CRYPTOPP_MSC_VERSION
34 # pragma warning(push)
35 # pragma warning(disable: 4127 4189)
36 #endif
37 
38 #include "cryptlib.h"
39 #include "seckey.h"
40 #include "secblock.h"
41 #include "argnames.h"
42 
43 NAMESPACE_BEGIN(CryptoPP)
44 
45 template <class POLICY_INTERFACE, class BASE = Empty>
46 class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE
47 {
48 public:
49  typedef POLICY_INTERFACE PolicyInterface;
50  virtual ~AbstractPolicyHolder() {}
51 
52 protected:
53  virtual const POLICY_INTERFACE & GetPolicy() const =0;
54  virtual POLICY_INTERFACE & AccessPolicy() =0;
55 };
56 
57 template <class POLICY, class BASE, class POLICY_INTERFACE = CPP_TYPENAME BASE::PolicyInterface>
58 class ConcretePolicyHolder : public BASE, protected POLICY
59 {
60 protected:
61  const POLICY_INTERFACE & GetPolicy() const {return *this;}
62  POLICY_INTERFACE & AccessPolicy() {return *this;}
63 };
64 
65 enum KeystreamOperationFlags {OUTPUT_ALIGNED=1, INPUT_ALIGNED=2, INPUT_NULL = 4};
66 enum KeystreamOperation {
67  WRITE_KEYSTREAM = INPUT_NULL,
68  WRITE_KEYSTREAM_ALIGNED = INPUT_NULL | OUTPUT_ALIGNED,
69  XOR_KEYSTREAM = 0,
70  XOR_KEYSTREAM_INPUT_ALIGNED = INPUT_ALIGNED,
71  XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED,
72  XOR_KEYSTREAM_BOTH_ALIGNED = OUTPUT_ALIGNED | INPUT_ALIGNED};
73 
74 struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy
75 {
76  virtual ~AdditiveCipherAbstractPolicy() {}
77  virtual unsigned int GetAlignment() const {return 1;}
78  virtual unsigned int GetBytesPerIteration() const =0;
79  virtual unsigned int GetOptimalBlockSize() const {return GetBytesPerIteration();}
80  virtual unsigned int GetIterationsToBuffer() const =0;
81  virtual void WriteKeystream(byte *keystream, size_t iterationCount)
82  {OperateKeystream(KeystreamOperation(INPUT_NULL | (KeystreamOperationFlags)IsAlignedOn(keystream, GetAlignment())), keystream, NULL, iterationCount);}
83  virtual bool CanOperateKeystream() const {return false;}
84  virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
85  {CRYPTOPP_UNUSED(operation); CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(iterationCount); assert(false);}
86  virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
87  virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
88  {CRYPTOPP_UNUSED(keystreamBuffer); CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(length); throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
89  virtual bool CipherIsRandomAccess() const =0;
90  virtual void SeekToIteration(lword iterationCount)
91  {CRYPTOPP_UNUSED(iterationCount); assert(!CipherIsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");}
92 };
93 
94 template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy>
95 struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE
96 {
97  typedef WT WordType;
98  CRYPTOPP_CONSTANT(BYTES_PER_ITERATION = sizeof(WordType) * W)
99 
100 #if !(CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64)
101  unsigned int GetAlignment() const {return GetAlignmentOf<WordType>();}
102 #endif
103  unsigned int GetBytesPerIteration() const {return BYTES_PER_ITERATION;}
104  unsigned int GetIterationsToBuffer() const {return X;}
105  bool CanOperateKeystream() const {return true;}
106  virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0;
107 };
108 
109 // use these to implement OperateKeystream
110 #define CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, b, i, a) \
111  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)));
112 #define CRYPTOPP_KEYSTREAM_OUTPUT_XMM(x, i, a) {\
113  __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));\
114  if (x & OUTPUT_ALIGNED) _mm_store_si128((__m128i *)output+i, t);\
115  else _mm_storeu_si128((__m128i *)output+i, t);}
116 #define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y) \
117  switch (operation) \
118  { \
119  case WRITE_KEYSTREAM: \
120  x(WRITE_KEYSTREAM) \
121  break; \
122  case XOR_KEYSTREAM: \
123  x(XOR_KEYSTREAM) \
124  input += y; \
125  break; \
126  case XOR_KEYSTREAM_INPUT_ALIGNED: \
127  x(XOR_KEYSTREAM_INPUT_ALIGNED) \
128  input += y; \
129  break; \
130  case XOR_KEYSTREAM_OUTPUT_ALIGNED: \
131  x(XOR_KEYSTREAM_OUTPUT_ALIGNED) \
132  input += y; \
133  break; \
134  case WRITE_KEYSTREAM_ALIGNED: \
135  x(WRITE_KEYSTREAM_ALIGNED) \
136  break; \
137  case XOR_KEYSTREAM_BOTH_ALIGNED: \
138  x(XOR_KEYSTREAM_BOTH_ALIGNED) \
139  input += y; \
140  break; \
141  } \
142  output += y;
143 
144 template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >
145 class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE, public RandomNumberGenerator
146 {
147 public:
148  void GenerateBlock(byte *output, size_t size);
149  void ProcessData(byte *outString, const byte *inString, size_t length);
150  void Resynchronize(const byte *iv, int length=-1);
151  unsigned int OptimalBlockSize() const {return this->GetPolicy().GetOptimalBlockSize();}
152  unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;}
153  unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
154  bool IsSelfInverting() const {return true;}
155  bool IsForwardTransformation() const {return true;}
156  bool IsRandomAccess() const {return this->GetPolicy().CipherIsRandomAccess();}
157  void Seek(lword position);
158 
159  typedef typename BASE::PolicyInterface PolicyInterface;
160 
161 protected:
162  void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
163 
164  unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();}
165 
166  inline byte * KeystreamBufferBegin() {return this->m_buffer.data();}
167  inline byte * KeystreamBufferEnd() {return (this->m_buffer.data() + this->m_buffer.size());}
168 
169  SecByteBlock m_buffer;
170  size_t m_leftOver;
171 };
172 
173 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy
174 {
175 public:
176  virtual ~CFB_CipherAbstractPolicy() {}
177  virtual unsigned int GetAlignment() const =0;
178  virtual unsigned int GetBytesPerIteration() const =0;
179  virtual byte * GetRegisterBegin() =0;
180  virtual void TransformRegister() =0;
181  virtual bool CanIterate() const {return false;}
182  virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount)
183  {CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(dir); CRYPTOPP_UNUSED(iterationCount);
184  assert(false); /*throw 0;*/ throw Exception(Exception::OTHER_ERROR, "SimpleKeyingInterface: unexpected error");}
185  virtual void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length) =0;
186  virtual void CipherResynchronize(const byte *iv, size_t length)
187  {CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(length); throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
188 };
189 
190 template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy>
191 struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE
192 {
193  typedef WT WordType;
194 
195  unsigned int GetAlignment() const {return sizeof(WordType);}
196  unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
197  bool CanIterate() const {return true;}
198  void TransformRegister() {this->Iterate(NULL, NULL, ENCRYPTION, 1);}
199 
200  template <class B>
202  {
203  RegisterOutput(byte *output, const byte *input, CipherDir dir)
204  : m_output(output), m_input(input), m_dir(dir) {}
205 
206  inline RegisterOutput& operator()(WordType &registerWord)
207  {
208  assert(IsAligned<WordType>(m_output));
209  assert(IsAligned<WordType>(m_input));
210 
211  if (!NativeByteOrderIs(B::ToEnum()))
212  registerWord = ByteReverse(registerWord);
213 
214  if (m_dir == ENCRYPTION)
215  {
216  if (m_input == NULL)
217  assert(m_output == NULL);
218  else
219  {
220  WordType ct = *(const WordType *)m_input ^ registerWord;
221  registerWord = ct;
222  *(WordType*)m_output = ct;
223  m_input += sizeof(WordType);
224  m_output += sizeof(WordType);
225  }
226  }
227  else
228  {
229  WordType ct = *(const WordType *)m_input;
230  *(WordType*)m_output = registerWord ^ ct;
231  registerWord = ct;
232  m_input += sizeof(WordType);
233  m_output += sizeof(WordType);
234  }
235 
236  // registerWord is left unreversed so it can be xor-ed with further input
237 
238  return *this;
239  }
240 
241  byte *m_output;
242  const byte *m_input;
243  CipherDir m_dir;
244  };
245 };
246 
247 template <class BASE>
248 class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE
249 {
250 public:
251  void ProcessData(byte *outString, const byte *inString, size_t length);
252  void Resynchronize(const byte *iv, int length=-1);
253  unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();}
254  unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;}
255  unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
256  bool IsRandomAccess() const {return false;}
257  bool IsSelfInverting() const {return false;}
258 
259  typedef typename BASE::PolicyInterface PolicyInterface;
260 
261 protected:
262  virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) =0;
263 
264  void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params);
265 
266  size_t m_leftOver;
267 };
268 
269 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
270 class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE>
271 {
272  bool IsForwardTransformation() const {return true;}
273  void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
274 };
275 
276 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
277 class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE>
278 {
279  bool IsForwardTransformation() const {return false;}
280  void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
281 };
282 
283 template <class BASE>
284 class CFB_RequireFullDataBlocks : public BASE
285 {
286 public:
287  unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();}
288 };
289 
290 //! _
291 template <class BASE, class INFO = BASE>
292 class SymmetricCipherFinal : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
293 {
294 public:
296  SymmetricCipherFinal(const byte *key)
297  {this->SetKey(key, this->DEFAULT_KEYLENGTH);}
298  SymmetricCipherFinal(const byte *key, size_t length)
299  {this->SetKey(key, length);}
300  SymmetricCipherFinal(const byte *key, size_t length, const byte *iv)
301  {this->SetKeyWithIV(key, length, iv);}
302 
303  Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinal<BASE, INFO>(*this));}
304 };
305 
306 NAMESPACE_END
307 
308 #ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
309 #include "strciphr.cpp"
310 #endif
311 
312 NAMESPACE_BEGIN(CryptoPP)
314 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >;
315 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
316 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
317 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >;
318 
319 NAMESPACE_END
320 
321 #if CRYPTOPP_MSC_VERSION
322 # pragma warning(pop)
323 #endif
324 
325 #endif
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:139
Standard names for retrieving values by name when working with NameValuePairs.
bool NativeByteOrderIs(ByteOrder order)
Determines whether order follows native byte ordering.
Definition: misc.h:852
virtual void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
Definition: cryptlib.cpp:329
CipherDir
Specifies a direction for a cipher to operate.
Definition: cryptlib.h:103
Abstract base classes that provide a uniform interface to this library.
Some other error occurred not belonging to other categories.
Definition: cryptlib.h:158
Library configuration file.
Interface for random number generators.
Definition: cryptlib.h:1176
SecBlock typedef.
Definition: secblock.h:723
Interface for cloning objects.
Definition: cryptlib.h:470
the cipher is performing encryption
Definition: cryptlib.h:105
Classes and functions for secure memory allocations.
bool IsAlignedOn(const void *ptr, unsigned int alignment)
Determines whether ptr is aligned to a minimum value.
Definition: misc.h:811
A method was called which was not implemented.
Definition: cryptlib.h:203
Classes and functions for implementing secret key algorithms.
Interface for one direction (encryption or decryption) of a stream cipher or cipher mode...
Definition: cryptlib.h:1089
An Empty class.
Definition: misc.h:156
Crypto++ library namespace.
byte ByteReverse(byte value)
Reverses bytes in a 8-bit value.
Definition: misc.h:1561
Interface for retrieving values given their names.
Definition: cryptlib.h:277
Base class for identifying alogorithm.
Definition: simple.h:38