| 1 | // strciphr.h - written and placed in the public domain by Wei Dai |
|---|
| 2 | |
|---|
| 3 | //! \file strciphr.h |
|---|
| 4 | //! \brief Classes for implementing stream ciphers |
|---|
| 5 | //! \details This file contains helper classes for implementing stream ciphers. |
|---|
| 6 | //! All this infrastructure may look very complex compared to what's in Crypto++ 4.x, |
|---|
| 7 | //! but stream ciphers implementations now support a lot of new functionality, |
|---|
| 8 | //! including better performance (minimizing copying), resetting of keys and IVs, and methods to |
|---|
| 9 | //! query which features are supported by a cipher. |
|---|
| 10 | //! \details Here's an explanation of these classes. The word "policy" is used here to mean a class with a |
|---|
| 11 | //! set of methods that must be implemented by individual stream cipher implementations. |
|---|
| 12 | //! This is usually much simpler than the full stream cipher API, which is implemented by |
|---|
| 13 | //! either AdditiveCipherTemplate or CFB_CipherTemplate using the policy. So for example, an |
|---|
| 14 | //! implementation of SEAL only needs to implement the AdditiveCipherAbstractPolicy interface |
|---|
| 15 | //! (since it's an additive cipher, i.e., it xors a keystream into the plaintext). |
|---|
| 16 | //! See this line in seal.h: |
|---|
| 17 | //! <pre> |
|---|
| 18 | //! typedef SymmetricCipherFinal\<ConcretePolicyHolder\<SEAL_Policy\<B\>, AdditiveCipherTemplate\<\> \> \> Encryption; |
|---|
| 19 | //! </pre> |
|---|
| 20 | //! \details AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't need |
|---|
| 21 | //! to take a policy class as a template parameter (although this is allowed), so that |
|---|
| 22 | //! their code is not duplicated for each new cipher. Instead they each |
|---|
| 23 | //! get a reference to an abstract policy interface by calling AccessPolicy() on itself, so |
|---|
| 24 | //! AccessPolicy() must be overriden to return the actual policy reference. This is done |
|---|
| 25 | //! by the ConceretePolicyHolder class. Finally, SymmetricCipherFinal implements the constructors and |
|---|
| 26 | //! other functions that must be implemented by the most derived class. |
|---|
| 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 | //! \class AbstractPolicyHolder |
|---|
| 46 | //! \brief Access a stream cipher policy object |
|---|
| 47 | //! \tparam POLICY_INTERFACE class implementing AbstractPolicyHolder |
|---|
| 48 | //! \tparam BASE class or type to use as a base class |
|---|
| 49 | template <class POLICY_INTERFACE, class BASE = Empty> |
|---|
| 50 | class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE |
|---|
| 51 | { |
|---|
| 52 | public: |
|---|
| 53 | typedef POLICY_INTERFACE PolicyInterface; |
|---|
| 54 | virtual ~AbstractPolicyHolder() {} |
|---|
| 55 | |
|---|
| 56 | protected: |
|---|
| 57 | virtual const POLICY_INTERFACE & GetPolicy() const =0; |
|---|
| 58 | virtual POLICY_INTERFACE & AccessPolicy() =0; |
|---|
| 59 | }; |
|---|
| 60 | |
|---|
| 61 | //! \class ConcretePolicyHolder |
|---|
| 62 | //! \brief Stream cipher policy object |
|---|
| 63 | //! \tparam POLICY class implementing AbstractPolicyHolder |
|---|
| 64 | //! \tparam BASE class or type to use as a base class |
|---|
| 65 | template <class POLICY, class BASE, class POLICY_INTERFACE = CPP_TYPENAME BASE::PolicyInterface> |
|---|
| 66 | class ConcretePolicyHolder : public BASE, protected POLICY |
|---|
| 67 | { |
|---|
| 68 | public: |
|---|
| 69 | #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562 |
|---|
| 70 | virtual ~ConcretePolicyHolder() {} |
|---|
| 71 | #endif |
|---|
| 72 | protected: |
|---|
| 73 | const POLICY_INTERFACE & GetPolicy() const {return *this;} |
|---|
| 74 | POLICY_INTERFACE & AccessPolicy() {return *this;} |
|---|
| 75 | }; |
|---|
| 76 | |
|---|
| 77 | //! \brief Keystream operation flags |
|---|
| 78 | //! \sa AdditiveCipherAbstractPolicy::GetBytesPerIteration(), AdditiveCipherAbstractPolicy::GetOptimalBlockSize() |
|---|
| 79 | //! and AdditiveCipherAbstractPolicy::GetAlignment() |
|---|
| 80 | enum KeystreamOperationFlags { |
|---|
| 81 | //! \brief Output buffer is aligned |
|---|
| 82 | OUTPUT_ALIGNED=1, |
|---|
| 83 | //! \brief Input buffer is aligned |
|---|
| 84 | INPUT_ALIGNED=2, |
|---|
| 85 | //! \brief Input buffer is NULL |
|---|
| 86 | INPUT_NULL = 4 |
|---|
| 87 | }; |
|---|
| 88 | |
|---|
| 89 | //! \brief Keystream operation flags |
|---|
| 90 | //! \sa AdditiveCipherAbstractPolicy::GetBytesPerIteration(), AdditiveCipherAbstractPolicy::GetOptimalBlockSize() |
|---|
| 91 | //! and AdditiveCipherAbstractPolicy::GetAlignment() |
|---|
| 92 | enum KeystreamOperation { |
|---|
| 93 | //! \brief Wirte the keystream to the output buffer, input is NULL |
|---|
| 94 | WRITE_KEYSTREAM = INPUT_NULL, |
|---|
| 95 | //! \brief Wirte the keystream to the aligned output buffer, input is NULL |
|---|
| 96 | WRITE_KEYSTREAM_ALIGNED = INPUT_NULL | OUTPUT_ALIGNED, |
|---|
| 97 | //! \brief XOR the input buffer and keystream, write to the output buffer |
|---|
| 98 | XOR_KEYSTREAM = 0, |
|---|
| 99 | //! \brief XOR the aligned input buffer and keystream, write to the output buffer |
|---|
| 100 | XOR_KEYSTREAM_INPUT_ALIGNED = INPUT_ALIGNED, |
|---|
| 101 | //! \brief XOR the input buffer and keystream, write to the aligned output buffer |
|---|
| 102 | XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED, |
|---|
| 103 | //! \brief XOR the aligned input buffer and keystream, write to the aligned output buffer |
|---|
| 104 | XOR_KEYSTREAM_BOTH_ALIGNED = OUTPUT_ALIGNED | INPUT_ALIGNED}; |
|---|
| 105 | |
|---|
| 106 | //! \class AdditiveCipherAbstractPolicy |
|---|
| 107 | //! \brief Policy object for additive stream ciphers |
|---|
| 108 | struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy |
|---|
| 109 | { |
|---|
| 110 | virtual ~AdditiveCipherAbstractPolicy() {} |
|---|
| 111 | |
|---|
| 112 | //! \brief Provides data alignment requirements |
|---|
| 113 | //! \returns data alignment requirements, in bytes |
|---|
| 114 | //! \details Internally, the default implementation returns 1. If the stream cipher is implemented |
|---|
| 115 | //! using an SSE2 ASM or intrinsics, then the value returned is usually 16. |
|---|
| 116 | virtual unsigned int GetAlignment() const {return 1;} |
|---|
| 117 | |
|---|
| 118 | //! \brief Provides number of bytes operated upon during an iteration |
|---|
| 119 | //! \returns bytes operated upon during an iteration, in bytes |
|---|
| 120 | //! \sa GetOptimalBlockSize() |
|---|
| 121 | virtual unsigned int GetBytesPerIteration() const =0; |
|---|
| 122 | |
|---|
| 123 | //! \brief Provides number of ideal bytes to process |
|---|
| 124 | //! \returns the ideal number of bytes to process |
|---|
| 125 | //! \details Internally, the default implementation returns GetBytesPerIteration() |
|---|
| 126 | //! \sa GetBytesPerIteration() |
|---|
| 127 | virtual unsigned int GetOptimalBlockSize() const {return GetBytesPerIteration();} |
|---|
| 128 | |
|---|
| 129 | //! \brief Provides buffer size based on iterations |
|---|
| 130 | //! \returns the buffer size based on iterations, in bytes |
|---|
| 131 | virtual unsigned int GetIterationsToBuffer() const =0; |
|---|
| 132 | |
|---|
| 133 | //! \brief Generate the keystream |
|---|
| 134 | //! \param keystream the key stream |
|---|
| 135 | //! \param iterationCount the number of iterations to generate the key stream |
|---|
| 136 | //! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream() |
|---|
| 137 | virtual void WriteKeystream(byte *keystream, size_t iterationCount) |
|---|
| 138 | {OperateKeystream(KeystreamOperation(INPUT_NULL | (KeystreamOperationFlags)IsAlignedOn(keystream, GetAlignment())), keystream, NULL, iterationCount);} |
|---|
| 139 | |
|---|
| 140 | //! \brief Flag indicating |
|---|
| 141 | //! \returns true if the stream can be generated independent of the transformation input, false otherwise |
|---|
| 142 | //! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream() |
|---|
| 143 | virtual bool CanOperateKeystream() const {return false;} |
|---|
| 144 | |
|---|
| 145 | //! \brief Operates the keystream |
|---|
| 146 | //! \param operation the operation with additional flags |
|---|
| 147 | //! \param output the output buffer |
|---|
| 148 | //! \param input the input buffer |
|---|
| 149 | //! \param iterationCount the number of iterations to perform on the input |
|---|
| 150 | //! \details OperateKeystream() will attempt to operate upon GetOptimalBlockSize() buffer, |
|---|
| 151 | //! which will be derived from GetBytesPerIteration(). |
|---|
| 152 | //! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream(), KeystreamOperation() |
|---|
| 153 | virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) |
|---|
| 154 | {CRYPTOPP_UNUSED(operation); CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(iterationCount); CRYPTOPP_ASSERT(false);} |
|---|
| 155 | |
|---|
| 156 | //! \brief Key the cipher |
|---|
| 157 | //! \param params set of NameValuePairs use to initialize this object |
|---|
| 158 | //! \param key a byte array used to key the cipher |
|---|
| 159 | //! \param length the size of the key array |
|---|
| 160 | virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) =0; |
|---|
| 161 | |
|---|
| 162 | //! \brief Resynchronize the cipher |
|---|
| 163 | //! \param keystreamBuffer the keystream buffer |
|---|
| 164 | //! \param iv a byte array used to resynchronize the cipher |
|---|
| 165 | //! \param length the size of the IV array |
|---|
| 166 | virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) |
|---|
| 167 | {CRYPTOPP_UNUSED(keystreamBuffer); CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(length); throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");} |
|---|
| 168 | |
|---|
| 169 | //! \brief Flag indicating random access |
|---|
| 170 | //! \returns true if the cipher is seekable, false otherwise |
|---|
| 171 | //! \sa SeekToIteration() |
|---|
| 172 | virtual bool CipherIsRandomAccess() const =0; |
|---|
| 173 | |
|---|
| 174 | //! \brief Seeks to a random position in the stream |
|---|
| 175 | //! \returns iterationCount |
|---|
| 176 | //! \sa CipherIsRandomAccess() |
|---|
| 177 | virtual void SeekToIteration(lword iterationCount) |
|---|
| 178 | {CRYPTOPP_UNUSED(iterationCount); CRYPTOPP_ASSERT(!CipherIsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");} |
|---|
| 179 | }; |
|---|
| 180 | |
|---|
| 181 | //! \class AdditiveCipherConcretePolicy |
|---|
| 182 | //! \brief Base class for additive stream ciphers |
|---|
| 183 | //! \tparam WT word type |
|---|
| 184 | //! \tparam W count of words |
|---|
| 185 | //! \tparam X bytes per iteration count |
|---|
| 186 | //! \tparam BASE AdditiveCipherAbstractPolicy derived base class |
|---|
| 187 | template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy> |
|---|
| 188 | struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE |
|---|
| 189 | { |
|---|
| 190 | typedef WT WordType; |
|---|
| 191 | CRYPTOPP_CONSTANT(BYTES_PER_ITERATION = sizeof(WordType) * W) |
|---|
| 192 | |
|---|
| 193 | #if !(CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64) |
|---|
| 194 | //! \brief Provides data alignment requirements |
|---|
| 195 | //! \returns data alignment requirements, in bytes |
|---|
| 196 | //! \details Internally, the default implementation returns 1. If the stream cipher is implemented |
|---|
| 197 | //! using an SSE2 ASM or intrinsics, then the value returned is usually 16. |
|---|
| 198 | unsigned int GetAlignment() const {return GetAlignmentOf<WordType>();} |
|---|
| 199 | #endif |
|---|
| 200 | |
|---|
| 201 | //! \brief Provides number of bytes operated upon during an iteration |
|---|
| 202 | //! \returns bytes operated upon during an iteration, in bytes |
|---|
| 203 | //! \sa GetOptimalBlockSize() |
|---|
| 204 | unsigned int GetBytesPerIteration() const {return BYTES_PER_ITERATION;} |
|---|
| 205 | |
|---|
| 206 | //! \brief Provides buffer size based on iterations |
|---|
| 207 | //! \returns the buffer size based on iterations, in bytes |
|---|
| 208 | unsigned int GetIterationsToBuffer() const {return X;} |
|---|
| 209 | |
|---|
| 210 | //! \brief Flag indicating |
|---|
| 211 | //! \returns true if the stream can be generated independent of the transformation input, false otherwise |
|---|
| 212 | //! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream() |
|---|
| 213 | bool CanOperateKeystream() const {return true;} |
|---|
| 214 | |
|---|
| 215 | //! \brief Operates the keystream |
|---|
| 216 | //! \param operation the operation with additional flags |
|---|
| 217 | //! \param output the output buffer |
|---|
| 218 | //! \param input the input buffer |
|---|
| 219 | //! \param iterationCount the number of iterations to perform on the input |
|---|
| 220 | //! \details OperateKeystream() will attempt to operate upon GetOptimalBlockSize() buffer, |
|---|
| 221 | //! which will be derived from GetBytesPerIteration(). |
|---|
| 222 | //! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream(), KeystreamOperation() |
|---|
| 223 | virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0; |
|---|
| 224 | }; |
|---|
| 225 | |
|---|
| 226 | //! \brief Helper macro to implement OperateKeystream |
|---|
| 227 | #define CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, b, i, a) \ |
|---|
| 228 | 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))); |
|---|
| 229 | |
|---|
| 230 | //! \brief Helper macro to implement OperateKeystream |
|---|
| 231 | #define CRYPTOPP_KEYSTREAM_OUTPUT_XMM(x, i, a) {\ |
|---|
| 232 | __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));\ |
|---|
| 233 | if (x & OUTPUT_ALIGNED) _mm_store_si128((__m128i *)output+i, t);\ |
|---|
| 234 | else _mm_storeu_si128((__m128i *)output+i, t);} |
|---|
| 235 | |
|---|
| 236 | //! \brief Helper macro to implement OperateKeystream |
|---|
| 237 | #define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y) \ |
|---|
| 238 | switch (operation) \ |
|---|
| 239 | { \ |
|---|
| 240 | case WRITE_KEYSTREAM: \ |
|---|
| 241 | x(WRITE_KEYSTREAM) \ |
|---|
| 242 | break; \ |
|---|
| 243 | case XOR_KEYSTREAM: \ |
|---|
| 244 | x(XOR_KEYSTREAM) \ |
|---|
| 245 | input += y; \ |
|---|
| 246 | break; \ |
|---|
| 247 | case XOR_KEYSTREAM_INPUT_ALIGNED: \ |
|---|
| 248 | x(XOR_KEYSTREAM_INPUT_ALIGNED) \ |
|---|
| 249 | input += y; \ |
|---|
| 250 | break; \ |
|---|
| 251 | case XOR_KEYSTREAM_OUTPUT_ALIGNED: \ |
|---|
| 252 | x(XOR_KEYSTREAM_OUTPUT_ALIGNED) \ |
|---|
| 253 | input += y; \ |
|---|
| 254 | break; \ |
|---|
| 255 | case WRITE_KEYSTREAM_ALIGNED: \ |
|---|
| 256 | x(WRITE_KEYSTREAM_ALIGNED) \ |
|---|
| 257 | break; \ |
|---|
| 258 | case XOR_KEYSTREAM_BOTH_ALIGNED: \ |
|---|
| 259 | x(XOR_KEYSTREAM_BOTH_ALIGNED) \ |
|---|
| 260 | input += y; \ |
|---|
| 261 | break; \ |
|---|
| 262 | } \ |
|---|
| 263 | output += y; |
|---|
| 264 | |
|---|
| 265 | //! \class AdditiveCipherTemplate |
|---|
| 266 | //! \brief Base class for additive stream ciphers with SymmetricCipher interface |
|---|
| 267 | //! \tparam BASE AbstractPolicyHolder base class |
|---|
| 268 | template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> > |
|---|
| 269 | class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE, public RandomNumberGenerator |
|---|
| 270 | { |
|---|
| 271 | public: |
|---|
| 272 | //! \brief Generate random array of bytes |
|---|
| 273 | //! \param output the byte buffer |
|---|
| 274 | //! \param size the length of the buffer, in bytes |
|---|
| 275 | //! \details All generated values are uniformly distributed over the range specified within the |
|---|
| 276 | //! the contraints of a particular generator. |
|---|
| 277 | void GenerateBlock(byte *output, size_t size); |
|---|
| 278 | |
|---|
| 279 | //! \brief Apply keystream to data |
|---|
| 280 | //! \param outString a buffer to write the transformed data |
|---|
| 281 | //! \param inString a buffer to read the data |
|---|
| 282 | //! \param length the size fo the buffers, in bytes |
|---|
| 283 | //! \details This is the primary method to operate a stream cipher. For example: |
|---|
| 284 | //! <pre> |
|---|
| 285 | //! size_t size = 30; |
|---|
| 286 | //! byte plain[size] = "Do or do not; there is no try"; |
|---|
| 287 | //! byte cipher[size]; |
|---|
| 288 | //! ... |
|---|
| 289 | //! ChaCha20 chacha(key, keySize); |
|---|
| 290 | //! chacha.ProcessData(cipher, plain, size); |
|---|
| 291 | //! </pre> |
|---|
| 292 | void ProcessData(byte *outString, const byte *inString, size_t length); |
|---|
| 293 | |
|---|
| 294 | //! \brief Resynchronize the cipher |
|---|
| 295 | //! \param iv a byte array used to resynchronize the cipher |
|---|
| 296 | //! \param length the size of the IV array |
|---|
| 297 | void Resynchronize(const byte *iv, int length=-1); |
|---|
| 298 | |
|---|
| 299 | //! \brief Provides number of ideal bytes to process |
|---|
| 300 | //! \returns the ideal number of bytes to process |
|---|
| 301 | //! \details Internally, the default implementation returns GetBytesPerIteration() |
|---|
| 302 | //! \sa GetBytesPerIteration() and GetOptimalNextBlockSize() |
|---|
| 303 | unsigned int OptimalBlockSize() const {return this->GetPolicy().GetOptimalBlockSize();} |
|---|
| 304 | |
|---|
| 305 | //! \brief Provides number of ideal bytes to process |
|---|
| 306 | //! \returns the ideal number of bytes to process |
|---|
| 307 | //! \details Internally, the default implementation returns remaining unprocessed bytes |
|---|
| 308 | //! \sa GetBytesPerIteration() and OptimalBlockSize() |
|---|
| 309 | unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;} |
|---|
| 310 | |
|---|
| 311 | //! \brief Provides number of ideal data alignment |
|---|
| 312 | //! \returns the ideal data alignment, in bytes |
|---|
| 313 | //! \sa GetAlignment() and OptimalBlockSize() |
|---|
| 314 | unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} |
|---|
| 315 | |
|---|
| 316 | //! \brief Determines if the cipher is self inverting |
|---|
| 317 | //! \returns true if the stream cipher is self inverting, false otherwise |
|---|
| 318 | bool IsSelfInverting() const {return true;} |
|---|
| 319 | |
|---|
| 320 | //! \brief Determines if the cipher is a forward transformation |
|---|
| 321 | //! \returns true if the stream cipher is a forward transformation, false otherwise |
|---|
| 322 | bool IsForwardTransformation() const {return true;} |
|---|
| 323 | |
|---|
| 324 | //! \brief Flag indicating random access |
|---|
| 325 | //! \returns true if the cipher is seekable, false otherwise |
|---|
| 326 | //! \sa Seek() |
|---|
| 327 | bool IsRandomAccess() const {return this->GetPolicy().CipherIsRandomAccess();} |
|---|
| 328 | |
|---|
| 329 | //! \brief Seeks to a random position in the stream |
|---|
| 330 | //! \param position the absolute position in the stream |
|---|
| 331 | //! \sa IsRandomAccess() |
|---|
| 332 | void Seek(lword position); |
|---|
| 333 | |
|---|
| 334 | typedef typename BASE::PolicyInterface PolicyInterface; |
|---|
| 335 | |
|---|
| 336 | protected: |
|---|
| 337 | void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); |
|---|
| 338 | |
|---|
| 339 | unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();} |
|---|
| 340 | |
|---|
| 341 | inline byte * KeystreamBufferBegin() {return this->m_buffer.data();} |
|---|
| 342 | inline byte * KeystreamBufferEnd() {return (this->m_buffer.data() + this->m_buffer.size());} |
|---|
| 343 | |
|---|
| 344 | SecByteBlock m_buffer; |
|---|
| 345 | size_t m_leftOver; |
|---|
| 346 | }; |
|---|
| 347 | |
|---|
| 348 | //! \class CFB_CipherAbstractPolicy |
|---|
| 349 | //! \brief Policy object for feeback based stream ciphers |
|---|
| 350 | class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy |
|---|
| 351 | { |
|---|
| 352 | public: |
|---|
| 353 | virtual ~CFB_CipherAbstractPolicy() {} |
|---|
| 354 | |
|---|
| 355 | //! \brief Provides data alignment requirements |
|---|
| 356 | //! \returns data alignment requirements, in bytes |
|---|
| 357 | //! \details Internally, the default implementation returns 1. If the stream cipher is implemented |
|---|
| 358 | //! using an SSE2 ASM or intrinsics, then the value returned is usually 16. |
|---|
| 359 | virtual unsigned int GetAlignment() const =0; |
|---|
| 360 | |
|---|
| 361 | //! \brief Provides number of bytes operated upon during an iteration |
|---|
| 362 | //! \returns bytes operated upon during an iteration, in bytes |
|---|
| 363 | //! \sa GetOptimalBlockSize() |
|---|
| 364 | virtual unsigned int GetBytesPerIteration() const =0; |
|---|
| 365 | |
|---|
| 366 | //! \brief Access the feedback register |
|---|
| 367 | //! \returns pointer to the first byte of the feedback register |
|---|
| 368 | virtual byte * GetRegisterBegin() =0; |
|---|
| 369 | |
|---|
| 370 | //! \brief TODO |
|---|
| 371 | virtual void TransformRegister() =0; |
|---|
| 372 | |
|---|
| 373 | //! \brief Flag indicating iteration support |
|---|
| 374 | //! \returns true if the cipher supports iteration, false otherwise |
|---|
| 375 | virtual bool CanIterate() const {return false;} |
|---|
| 376 | |
|---|
| 377 | //! \brief Iterate the cipher |
|---|
| 378 | //! \param output the output buffer |
|---|
| 379 | //! \param input the input buffer |
|---|
| 380 | //! \param dir the direction of the cipher |
|---|
| 381 | //! \param iterationCount the number of iterations to perform on the input |
|---|
| 382 | //! \sa IsSelfInverting() and IsForwardTransformation() |
|---|
| 383 | virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) |
|---|
| 384 | {CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(dir); CRYPTOPP_UNUSED(iterationCount); |
|---|
| 385 | CRYPTOPP_ASSERT(false); /*throw 0;*/ throw Exception(Exception::OTHER_ERROR, "SimpleKeyingInterface: unexpected error");} |
|---|
| 386 | |
|---|
| 387 | //! \brief Key the cipher |
|---|
| 388 | //! \param params set of NameValuePairs use to initialize this object |
|---|
| 389 | //! \param key a byte array used to key the cipher |
|---|
| 390 | //! \param length the size of the key array |
|---|
| 391 | virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) =0; |
|---|
| 392 | |
|---|
| 393 | //! \brief Resynchronize the cipher |
|---|
| 394 | //! \param iv a byte array used to resynchronize the cipher |
|---|
| 395 | //! \param length the size of the IV array |
|---|
| 396 | virtual void CipherResynchronize(const byte *iv, size_t length) |
|---|
| 397 | {CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(length); throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");} |
|---|
| 398 | }; |
|---|
| 399 | |
|---|
| 400 | //! \class CFB_CipherConcretePolicy |
|---|
| 401 | //! \brief Base class for feedback based stream ciphers |
|---|
| 402 | //! \tparam WT word type |
|---|
| 403 | //! \tparam W count of words |
|---|
| 404 | //! \tparam BASE CFB_CipherAbstractPolicy derived base class |
|---|
| 405 | template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy> |
|---|
| 406 | struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE |
|---|
| 407 | { |
|---|
| 408 | typedef WT WordType; |
|---|
| 409 | |
|---|
| 410 | //! \brief Provides data alignment requirements |
|---|
| 411 | //! \returns data alignment requirements, in bytes |
|---|
| 412 | //! \details Internally, the default implementation returns 1. If the stream cipher is implemented |
|---|
| 413 | //! using an SSE2 ASM or intrinsics, then the value returned is usually 16. |
|---|
| 414 | unsigned int GetAlignment() const {return sizeof(WordType);} |
|---|
| 415 | |
|---|
| 416 | //! \brief Provides number of bytes operated upon during an iteration |
|---|
| 417 | //! \returns bytes operated upon during an iteration, in bytes |
|---|
| 418 | //! \sa GetOptimalBlockSize() |
|---|
| 419 | unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;} |
|---|
| 420 | |
|---|
| 421 | //! \brief Flag indicating iteration support |
|---|
| 422 | //! \returns true if the cipher supports iteration, false otherwise |
|---|
| 423 | bool CanIterate() const {return true;} |
|---|
| 424 | |
|---|
| 425 | //! \brief Perform one iteration in the forward direction |
|---|
| 426 | void TransformRegister() {this->Iterate(NULL, NULL, ENCRYPTION, 1);} |
|---|
| 427 | |
|---|
| 428 | //! \brief |
|---|
| 429 | //! \tparam B enumeration indicating endianess |
|---|
| 430 | //! \details RegisterOutput() provides alternate access to the feedback register. The |
|---|
| 431 | //! enumeration B is BigEndian or LittleEndian. Repeatedly applying operator() |
|---|
| 432 | //! results in advancing in the register. |
|---|
| 433 | template <class B> |
|---|
| 434 | struct RegisterOutput |
|---|
| 435 | { |
|---|
| 436 | RegisterOutput(byte *output, const byte *input, CipherDir dir) |
|---|
| 437 | : m_output(output), m_input(input), m_dir(dir) {} |
|---|
| 438 | |
|---|
| 439 | //! \brief XOR feedback register with data |
|---|
| 440 | //! \param registerWord data represented as a word type |
|---|
| 441 | //! \returns reference to the next feedback register word |
|---|
| 442 | inline RegisterOutput& operator()(WordType ®isterWord) |
|---|
| 443 | { |
|---|
| 444 | CRYPTOPP_ASSERT(IsAligned<WordType>(m_output)); |
|---|
| 445 | CRYPTOPP_ASSERT(IsAligned<WordType>(m_input)); |
|---|
| 446 | |
|---|
| 447 | if (!NativeByteOrderIs(B::ToEnum())) |
|---|
| 448 | registerWord = ByteReverse(registerWord); |
|---|
| 449 | |
|---|
| 450 | if (m_dir == ENCRYPTION) |
|---|
| 451 | { |
|---|
| 452 | if (m_input == NULL) |
|---|
| 453 | { |
|---|
| 454 | CRYPTOPP_ASSERT(m_output == NULL); |
|---|
| 455 | } |
|---|
| 456 | else |
|---|
| 457 | { |
|---|
| 458 | WordType ct = *(const WordType *)m_input ^ registerWord; |
|---|
| 459 | registerWord = ct; |
|---|
| 460 | *(WordType*)m_output = ct; |
|---|
| 461 | m_input += sizeof(WordType); |
|---|
| 462 | m_output += sizeof(WordType); |
|---|
| 463 | } |
|---|
| 464 | } |
|---|
| 465 | else |
|---|
| 466 | { |
|---|
| 467 | WordType ct = *(const WordType *)m_input; |
|---|
| 468 | *(WordType*)m_output = registerWord ^ ct; |
|---|
| 469 | registerWord = ct; |
|---|
| 470 | m_input += sizeof(WordType); |
|---|
| 471 | m_output += sizeof(WordType); |
|---|
| 472 | } |
|---|
| 473 | |
|---|
| 474 | // registerWord is left unreversed so it can be xor-ed with further input |
|---|
| 475 | |
|---|
| 476 | return *this; |
|---|
| 477 | } |
|---|
| 478 | |
|---|
| 479 | byte *m_output; |
|---|
| 480 | const byte *m_input; |
|---|
| 481 | CipherDir m_dir; |
|---|
| 482 | }; |
|---|
| 483 | }; |
|---|
| 484 | |
|---|
| 485 | //! \class CFB_CipherTemplate |
|---|
| 486 | //! \brief Base class for feedback based stream ciphers with SymmetricCipher interface |
|---|
| 487 | //! \tparam BASE AbstractPolicyHolder base class |
|---|
| 488 | template <class BASE> |
|---|
| 489 | class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE |
|---|
| 490 | { |
|---|
| 491 | public: |
|---|
| 492 | //! \brief Apply keystream to data |
|---|
| 493 | //! \param outString a buffer to write the transformed data |
|---|
| 494 | //! \param inString a buffer to read the data |
|---|
| 495 | //! \param length the size fo the buffers, in bytes |
|---|
| 496 | //! \details This is the primary method to operate a stream cipher. For example: |
|---|
| 497 | //! <pre> |
|---|
| 498 | //! size_t size = 30; |
|---|
| 499 | //! byte plain[size] = "Do or do not; there is no try"; |
|---|
| 500 | //! byte cipher[size]; |
|---|
| 501 | //! ... |
|---|
| 502 | //! ChaCha20 chacha(key, keySize); |
|---|
| 503 | //! chacha.ProcessData(cipher, plain, size); |
|---|
| 504 | //! </pre> |
|---|
| 505 | void ProcessData(byte *outString, const byte *inString, size_t length); |
|---|
| 506 | |
|---|
| 507 | //! \brief Resynchronize the cipher |
|---|
| 508 | //! \param iv a byte array used to resynchronize the cipher |
|---|
| 509 | //! \param length the size of the IV array |
|---|
| 510 | void Resynchronize(const byte *iv, int length=-1); |
|---|
| 511 | |
|---|
| 512 | //! \brief Provides number of ideal bytes to process |
|---|
| 513 | //! \returns the ideal number of bytes to process |
|---|
| 514 | //! \details Internally, the default implementation returns GetBytesPerIteration() |
|---|
| 515 | //! \sa GetBytesPerIteration() and GetOptimalNextBlockSize() |
|---|
| 516 | unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();} |
|---|
| 517 | |
|---|
| 518 | //! \brief Provides number of ideal bytes to process |
|---|
| 519 | //! \returns the ideal number of bytes to process |
|---|
| 520 | //! \details Internally, the default implementation returns remaining unprocessed bytes |
|---|
| 521 | //! \sa GetBytesPerIteration() and OptimalBlockSize() |
|---|
| 522 | unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;} |
|---|
| 523 | |
|---|
| 524 | //! \brief Provides number of ideal data alignment |
|---|
| 525 | //! \returns the ideal data alignment, in bytes |
|---|
| 526 | //! \sa GetAlignment() and OptimalBlockSize() |
|---|
| 527 | unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} |
|---|
| 528 | |
|---|
| 529 | //! \brief Flag indicating random access |
|---|
| 530 | //! \returns true if the cipher is seekable, false otherwise |
|---|
| 531 | //! \sa Seek() |
|---|
| 532 | bool IsRandomAccess() const {return false;} |
|---|
| 533 | |
|---|
| 534 | //! \brief Determines if the cipher is self inverting |
|---|
| 535 | //! \returns true if the stream cipher is self inverting, false otherwise |
|---|
| 536 | bool IsSelfInverting() const {return false;} |
|---|
| 537 | |
|---|
| 538 | typedef typename BASE::PolicyInterface PolicyInterface; |
|---|
| 539 | |
|---|
| 540 | protected: |
|---|
| 541 | virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) =0; |
|---|
| 542 | |
|---|
| 543 | void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); |
|---|
| 544 | |
|---|
| 545 | size_t m_leftOver; |
|---|
| 546 | }; |
|---|
| 547 | |
|---|
| 548 | //! \class CFB_EncryptionTemplate |
|---|
| 549 | //! \brief Base class for feedback based stream ciphers in the forward direction with SymmetricCipher interface |
|---|
| 550 | //! \tparam BASE AbstractPolicyHolder base class |
|---|
| 551 | template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> > |
|---|
| 552 | class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE> |
|---|
| 553 | { |
|---|
| 554 | bool IsForwardTransformation() const {return true;} |
|---|
| 555 | void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length); |
|---|
| 556 | }; |
|---|
| 557 | |
|---|
| 558 | //! \class CFB_DecryptionTemplate |
|---|
| 559 | //! \brief Base class for feedback based stream ciphers in the reverse direction with SymmetricCipher interface |
|---|
| 560 | //! \tparam BASE AbstractPolicyHolder base class |
|---|
| 561 | template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> > |
|---|
| 562 | class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE> |
|---|
| 563 | { |
|---|
| 564 | bool IsForwardTransformation() const {return false;} |
|---|
| 565 | void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length); |
|---|
| 566 | }; |
|---|
| 567 | |
|---|
| 568 | //! \class CFB_RequireFullDataBlocks |
|---|
| 569 | //! \brief Base class for feedback based stream ciphers with a mandatory block size |
|---|
| 570 | //! \tparam BASE CFB_EncryptionTemplate or CFB_DecryptionTemplate base class |
|---|
| 571 | template <class BASE> |
|---|
| 572 | class CFB_RequireFullDataBlocks : public BASE |
|---|
| 573 | { |
|---|
| 574 | public: |
|---|
| 575 | unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();} |
|---|
| 576 | }; |
|---|
| 577 | |
|---|
| 578 | //! \class SymmetricCipherFinal |
|---|
| 579 | //! \brief SymmetricCipher implementation |
|---|
| 580 | //! \tparam BASE AbstractPolicyHolder derived base class |
|---|
| 581 | //! \tparam INFO AbstractPolicyHolder derived information class |
|---|
| 582 | //! \sa Weak::ARC4, ChaCha8, ChaCha12, ChaCha20, Salsa20, SEAL, Sosemanuk, WAKE |
|---|
| 583 | template <class BASE, class INFO = BASE> |
|---|
| 584 | class SymmetricCipherFinal : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO> |
|---|
| 585 | { |
|---|
| 586 | public: |
|---|
| 587 | //! \brief Construct a stream cipher |
|---|
| 588 | SymmetricCipherFinal() {} |
|---|
| 589 | |
|---|
| 590 | //! \brief Construct a stream cipher |
|---|
| 591 | //! \param key a byte array used to key the cipher |
|---|
| 592 | //! \details This overload uses DEFAULT_KEYLENGTH |
|---|
| 593 | SymmetricCipherFinal(const byte *key) |
|---|
| 594 | {this->SetKey(key, this->DEFAULT_KEYLENGTH);} |
|---|
| 595 | |
|---|
| 596 | //! \brief Construct a stream cipher |
|---|
| 597 | //! \param key a byte array used to key the cipher |
|---|
| 598 | //! \param length the size of the key array |
|---|
| 599 | SymmetricCipherFinal(const byte *key, size_t length) |
|---|
| 600 | {this->SetKey(key, length);} |
|---|
| 601 | |
|---|
| 602 | //! \brief Construct a stream cipher |
|---|
| 603 | //! \param key a byte array used to key the cipher |
|---|
| 604 | //! \param length the size of the key array |
|---|
| 605 | //! \param iv a byte array used as an initialization vector |
|---|
| 606 | SymmetricCipherFinal(const byte *key, size_t length, const byte *iv) |
|---|
| 607 | {this->SetKeyWithIV(key, length, iv);} |
|---|
| 608 | |
|---|
| 609 | //! \brief Clone a SymmetricCipher |
|---|
| 610 | //! \returns a new SymmetricCipher based on this object |
|---|
| 611 | Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinal<BASE, INFO>(*this));} |
|---|
| 612 | }; |
|---|
| 613 | |
|---|
| 614 | NAMESPACE_END |
|---|
| 615 | |
|---|
| 616 | #ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES |
|---|
| 617 | #include "strciphr.cpp" |
|---|
| 618 | #endif |
|---|
| 619 | |
|---|
| 620 | NAMESPACE_BEGIN(CryptoPP) |
|---|
| 621 | CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher>; |
|---|
| 622 | CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >; |
|---|
| 623 | CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >; |
|---|
| 624 | CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >; |
|---|
| 625 | CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >; |
|---|
| 626 | |
|---|
| 627 | NAMESPACE_END |
|---|
| 628 | |
|---|
| 629 | #if CRYPTOPP_MSC_VERSION |
|---|
| 630 | # pragma warning(pop) |
|---|
| 631 | #endif |
|---|
| 632 | |
|---|
| 633 | #endif |
|---|