Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

306 lines
12 KiB

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