|
||||
File indexing completed on 2025-01-18 09:55:09
0001 // strciphr.h - originally written and placed in the public domain by Wei Dai 0002 0003 /// \file strciphr.h 0004 /// \brief Classes for implementing stream ciphers 0005 /// \details This file contains helper classes for implementing stream ciphers. 0006 /// All this infrastructure may look very complex compared to what's in Crypto++ 4.x, 0007 /// but stream ciphers implementations now support a lot of new functionality, 0008 /// including better performance (minimizing copying), resetting of keys and IVs, and 0009 /// methods to query which features are supported by a cipher. 0010 /// \details Here's an explanation of these classes. The word "policy" is used here to 0011 /// mean a class with a set of methods that must be implemented by individual stream 0012 /// cipher implementations. This is usually much simpler than the full stream cipher 0013 /// API, which is implemented by either AdditiveCipherTemplate or CFB_CipherTemplate 0014 /// using the policy. So for example, an implementation of SEAL only needs to implement 0015 /// the AdditiveCipherAbstractPolicy interface (since it's an additive cipher, i.e., it 0016 /// xors a keystream into the plaintext). See this line in seal.h: 0017 /// <pre> 0018 /// typedef SymmetricCipherFinal\<ConcretePolicyHolder\<SEAL_Policy\<B\>, AdditiveCipherTemplate\<\> \> \> Encryption; 0019 /// </pre> 0020 /// \details AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't 0021 /// need to take a policy class as a template parameter (although this is allowed), so 0022 /// that their code is not duplicated for each new cipher. Instead they each get a 0023 /// reference to an abstract policy interface by calling AccessPolicy() on itself, so 0024 /// AccessPolicy() must be overridden to return the actual policy reference. This is done 0025 /// by the ConcretePolicyHolder class. Finally, SymmetricCipherFinal implements the 0026 /// constructors and other functions that must be implemented by the most derived class. 0027 0028 #ifndef CRYPTOPP_STRCIPHR_H 0029 #define CRYPTOPP_STRCIPHR_H 0030 0031 #include "config.h" 0032 0033 #if CRYPTOPP_MSC_VERSION 0034 # pragma warning(push) 0035 # pragma warning(disable: 4127 4189 4231 4275) 0036 #endif 0037 0038 #include "cryptlib.h" 0039 #include "seckey.h" 0040 #include "secblock.h" 0041 #include "argnames.h" 0042 0043 NAMESPACE_BEGIN(CryptoPP) 0044 0045 /// \brief Access a stream cipher policy object 0046 /// \tparam POLICY_INTERFACE class implementing AbstractPolicyHolder 0047 /// \tparam BASE class or type to use as a base class 0048 template <class POLICY_INTERFACE, class BASE = Empty> 0049 class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE 0050 { 0051 public: 0052 typedef POLICY_INTERFACE PolicyInterface; 0053 virtual ~AbstractPolicyHolder() {} 0054 0055 protected: 0056 virtual const POLICY_INTERFACE & GetPolicy() const =0; 0057 virtual POLICY_INTERFACE & AccessPolicy() =0; 0058 }; 0059 0060 /// \brief Stream cipher policy object 0061 /// \tparam POLICY class implementing AbstractPolicyHolder 0062 /// \tparam BASE class or type to use as a base class 0063 template <class POLICY, class BASE, class POLICY_INTERFACE = typename BASE::PolicyInterface> 0064 class ConcretePolicyHolder : public BASE, protected POLICY 0065 { 0066 public: 0067 virtual ~ConcretePolicyHolder() {} 0068 protected: 0069 const POLICY_INTERFACE & GetPolicy() const {return *this;} 0070 POLICY_INTERFACE & AccessPolicy() {return *this;} 0071 }; 0072 0073 /// \brief Keystream operation flags 0074 /// \sa AdditiveCipherAbstractPolicy::GetBytesPerIteration(), AdditiveCipherAbstractPolicy::GetOptimalBlockSize() 0075 /// and AdditiveCipherAbstractPolicy::GetAlignment() 0076 enum KeystreamOperationFlags { 0077 /// \brief Output buffer is aligned 0078 OUTPUT_ALIGNED=1, 0079 /// \brief Input buffer is aligned 0080 INPUT_ALIGNED=2, 0081 /// \brief Input buffer is NULL 0082 INPUT_NULL = 4 0083 }; 0084 0085 /// \brief Keystream operation flags 0086 /// \sa AdditiveCipherAbstractPolicy::GetBytesPerIteration(), AdditiveCipherAbstractPolicy::GetOptimalBlockSize() 0087 /// and AdditiveCipherAbstractPolicy::GetAlignment() 0088 enum KeystreamOperation { 0089 /// \brief Write the keystream to the output buffer, input is NULL 0090 WRITE_KEYSTREAM = INPUT_NULL, 0091 /// \brief Write the keystream to the aligned output buffer, input is NULL 0092 WRITE_KEYSTREAM_ALIGNED = INPUT_NULL | OUTPUT_ALIGNED, 0093 /// \brief XOR the input buffer and keystream, write to the output buffer 0094 XOR_KEYSTREAM = 0, 0095 /// \brief XOR the aligned input buffer and keystream, write to the output buffer 0096 XOR_KEYSTREAM_INPUT_ALIGNED = INPUT_ALIGNED, 0097 /// \brief XOR the input buffer and keystream, write to the aligned output buffer 0098 XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED, 0099 /// \brief XOR the aligned input buffer and keystream, write to the aligned output buffer 0100 XOR_KEYSTREAM_BOTH_ALIGNED = OUTPUT_ALIGNED | INPUT_ALIGNED 0101 }; 0102 0103 /// \brief Policy object for additive stream ciphers 0104 struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy 0105 { 0106 virtual ~AdditiveCipherAbstractPolicy() {} 0107 0108 /// \brief Provides data alignment requirements 0109 /// \return data alignment requirements, in bytes 0110 /// \details Internally, the default implementation returns 1. If the stream cipher is implemented 0111 /// using an SSE2 ASM or intrinsics, then the value returned is usually 16. 0112 virtual unsigned int GetAlignment() const {return 1;} 0113 0114 /// \brief Provides number of bytes operated upon during an iteration 0115 /// \return bytes operated upon during an iteration, in bytes 0116 /// \sa GetOptimalBlockSize() 0117 virtual unsigned int GetBytesPerIteration() const =0; 0118 0119 /// \brief Provides number of ideal bytes to process 0120 /// \return the ideal number of bytes to process 0121 /// \details Internally, the default implementation returns GetBytesPerIteration() 0122 /// \sa GetBytesPerIteration() 0123 virtual unsigned int GetOptimalBlockSize() const {return GetBytesPerIteration();} 0124 0125 /// \brief Provides buffer size based on iterations 0126 /// \return the buffer size based on iterations, in bytes 0127 virtual unsigned int GetIterationsToBuffer() const =0; 0128 0129 /// \brief Generate the keystream 0130 /// \param keystream the key stream 0131 /// \param iterationCount the number of iterations to generate the key stream 0132 /// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream() 0133 virtual void WriteKeystream(byte *keystream, size_t iterationCount) 0134 {OperateKeystream(KeystreamOperation(INPUT_NULL | static_cast<KeystreamOperationFlags>(IsAlignedOn(keystream, GetAlignment()))), keystream, NULLPTR, iterationCount);} 0135 0136 /// \brief Flag indicating 0137 /// \return true if the stream can be generated independent of the transformation input, false otherwise 0138 /// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream() 0139 virtual bool CanOperateKeystream() const {return false;} 0140 0141 /// \brief Operates the keystream 0142 /// \param operation the operation with additional flags 0143 /// \param output the output buffer 0144 /// \param input the input buffer 0145 /// \param iterationCount the number of iterations to perform on the input 0146 /// \details OperateKeystream() will attempt to operate upon GetOptimalBlockSize() buffer, 0147 /// which will be derived from GetBytesPerIteration(). 0148 /// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream(), KeystreamOperation() 0149 virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) 0150 {CRYPTOPP_UNUSED(operation); CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(input); 0151 CRYPTOPP_UNUSED(iterationCount); CRYPTOPP_ASSERT(false);} 0152 0153 /// \brief Key the cipher 0154 /// \param params set of NameValuePairs use to initialize this object 0155 /// \param key a byte array used to key the cipher 0156 /// \param length the size of the key array 0157 virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) =0; 0158 0159 /// \brief Resynchronize the cipher 0160 /// \param keystreamBuffer the keystream buffer 0161 /// \param iv a byte array used to resynchronize the cipher 0162 /// \param length the size of the IV array 0163 virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length) 0164 {CRYPTOPP_UNUSED(keystreamBuffer); CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(length); 0165 throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");} 0166 0167 /// \brief Flag indicating random access 0168 /// \return true if the cipher is seekable, false otherwise 0169 /// \sa SeekToIteration() 0170 virtual bool CipherIsRandomAccess() const =0; 0171 0172 /// \brief Seeks to a random position in the stream 0173 /// \sa CipherIsRandomAccess() 0174 virtual void SeekToIteration(lword iterationCount) 0175 {CRYPTOPP_UNUSED(iterationCount); CRYPTOPP_ASSERT(!CipherIsRandomAccess()); 0176 throw NotImplemented("StreamTransformation: this object doesn't support random access");} 0177 0178 /// \brief Retrieve the provider of this algorithm 0179 /// \return the algorithm provider 0180 /// \details The algorithm provider can be a name like "C++", "SSE", "NEON", "AESNI", 0181 /// "ARMv8" and "Power8". C++ is standard C++ code. Other labels, like SSE, 0182 /// usually indicate a specialized implementation using instructions from a higher 0183 /// instruction set architecture (ISA). Future labels may include external hardware 0184 /// like a hardware security module (HSM). 0185 /// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2". 0186 /// Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics 0187 /// instead of ASM. 0188 /// \details Algorithms which combine different instructions or ISAs provide the 0189 /// dominant one. For example on x86 <tt>AES/GCM</tt> returns "AESNI" rather than 0190 /// "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL". 0191 /// \note Provider is not universally implemented yet. 0192 virtual std::string AlgorithmProvider() const { return "C++"; } 0193 }; 0194 0195 /// \brief Base class for additive stream ciphers 0196 /// \tparam WT word type 0197 /// \tparam W count of words 0198 /// \tparam X bytes per iteration count 0199 /// \tparam BASE AdditiveCipherAbstractPolicy derived base class 0200 template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy> 0201 struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE 0202 { 0203 /// \brief Word type for the cipher 0204 typedef WT WordType; 0205 0206 /// \brief Number of bytes for an iteration 0207 /// \details BYTES_PER_ITERATION is the product <tt>sizeof(WordType) * W</tt>. 0208 /// For example, ChaCha uses 16 each <tt>word32</tt>, and the value of 0209 /// BYTES_PER_ITERATION is 64. Each invocation of the ChaCha block function 0210 /// produces 64 bytes of keystream. 0211 CRYPTOPP_CONSTANT(BYTES_PER_ITERATION = sizeof(WordType) * W); 0212 0213 virtual ~AdditiveCipherConcretePolicy() {} 0214 0215 /// \brief Provides data alignment requirements 0216 /// \return data alignment requirements, in bytes 0217 /// \details Internally, the default implementation returns 1. If the stream 0218 /// cipher is implemented using an SSE2 ASM or intrinsics, then the value 0219 /// returned is usually 16. 0220 unsigned int GetAlignment() const {return GetAlignmentOf<WordType>();} 0221 0222 /// \brief Provides number of bytes operated upon during an iteration 0223 /// \return bytes operated upon during an iteration, in bytes 0224 /// \sa GetOptimalBlockSize() 0225 unsigned int GetBytesPerIteration() const {return BYTES_PER_ITERATION;} 0226 0227 /// \brief Provides buffer size based on iterations 0228 /// \return the buffer size based on iterations, in bytes 0229 unsigned int GetIterationsToBuffer() const {return X;} 0230 0231 /// \brief Flag indicating 0232 /// \return true if the stream can be generated independent of the 0233 /// transformation input, false otherwise 0234 /// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream() 0235 bool CanOperateKeystream() const {return true;} 0236 0237 /// \brief Operates the keystream 0238 /// \param operation the operation with additional flags 0239 /// \param output the output buffer 0240 /// \param input the input buffer 0241 /// \param iterationCount the number of iterations to perform on the input 0242 /// \details OperateKeystream() will attempt to operate upon GetOptimalBlockSize() buffer, 0243 /// which will be derived from GetBytesPerIteration(). 0244 /// \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream(), KeystreamOperation() 0245 virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0; 0246 }; 0247 0248 /// \brief Helper macro to implement OperateKeystream 0249 /// \param x KeystreamOperation mask 0250 /// \param b Endian order 0251 /// \param i index in output buffer 0252 /// \param a value to output 0253 #define CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, b, i, a) \ 0254 PutWord(((x & OUTPUT_ALIGNED) != 0), b, output+i*sizeof(WordType), (x & INPUT_NULL) ? (a) : (a) ^ GetWord<WordType>(((x & INPUT_ALIGNED) != 0), b, input+i*sizeof(WordType))); 0255 0256 /// \brief Helper macro to implement OperateKeystream 0257 /// \param x KeystreamOperation mask 0258 /// \param i index in output buffer 0259 /// \param a value to output 0260 #define CRYPTOPP_KEYSTREAM_OUTPUT_XMM(x, i, a) {\ 0261 __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));\ 0262 if (x & OUTPUT_ALIGNED) _mm_store_si128((__m128i *)output+i, t);\ 0263 else _mm_storeu_si128((__m128i *)output+i, t);} 0264 0265 /// \brief Helper macro to implement OperateKeystream 0266 #define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y) \ 0267 switch (operation) \ 0268 { \ 0269 case WRITE_KEYSTREAM: \ 0270 x(EnumToInt(WRITE_KEYSTREAM)) \ 0271 break; \ 0272 case XOR_KEYSTREAM: \ 0273 x(EnumToInt(XOR_KEYSTREAM)) \ 0274 input += y; \ 0275 break; \ 0276 case XOR_KEYSTREAM_INPUT_ALIGNED: \ 0277 x(EnumToInt(XOR_KEYSTREAM_INPUT_ALIGNED)) \ 0278 input += y; \ 0279 break; \ 0280 case XOR_KEYSTREAM_OUTPUT_ALIGNED: \ 0281 x(EnumToInt(XOR_KEYSTREAM_OUTPUT_ALIGNED)) \ 0282 input += y; \ 0283 break; \ 0284 case WRITE_KEYSTREAM_ALIGNED: \ 0285 x(EnumToInt(WRITE_KEYSTREAM_ALIGNED)) \ 0286 break; \ 0287 case XOR_KEYSTREAM_BOTH_ALIGNED: \ 0288 x(EnumToInt(XOR_KEYSTREAM_BOTH_ALIGNED)) \ 0289 input += y; \ 0290 break; \ 0291 } \ 0292 output += y; 0293 0294 /// \brief Base class for additive stream ciphers with SymmetricCipher interface 0295 /// \tparam BASE AbstractPolicyHolder base class 0296 template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> > 0297 class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE, public RandomNumberGenerator 0298 { 0299 public: 0300 virtual ~AdditiveCipherTemplate() {} 0301 AdditiveCipherTemplate() : m_leftOver(0) {} 0302 0303 /// \brief Generate random array of bytes 0304 /// \param output the byte buffer 0305 /// \param size the length of the buffer, in bytes 0306 /// \details All generated values are uniformly distributed over the range specified 0307 /// within the constraints of a particular generator. 0308 void GenerateBlock(byte *output, size_t size); 0309 0310 /// \brief Apply keystream to data 0311 /// \param outString a buffer to write the transformed data 0312 /// \param inString a buffer to read the data 0313 /// \param length the size of the buffers, in bytes 0314 /// \details This is the primary method to operate a stream cipher. For example: 0315 /// <pre> 0316 /// size_t size = 30; 0317 /// byte plain[size] = "Do or do not; there is no try"; 0318 /// byte cipher[size]; 0319 /// ... 0320 /// ChaCha20 chacha(key, keySize); 0321 /// chacha.ProcessData(cipher, plain, size); 0322 /// </pre> 0323 /// \details You should use distinct buffers for inString and outString. If the buffers 0324 /// are the same, then the data will be copied to an internal buffer to avoid GCC alias 0325 /// violations. The internal copy will impact performance. 0326 /// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/1088">Issue 1088, 36% loss 0327 /// of performance with AES</A>, <A HREF="https://github.com/weidai11/cryptopp/issues/1010">Issue 0328 /// 1010, HIGHT cipher troubles with FileSource</A> 0329 void ProcessData(byte *outString, const byte *inString, size_t length); 0330 0331 /// \brief Resynchronize the cipher 0332 /// \param iv a byte array used to resynchronize the cipher 0333 /// \param length the size of the IV array 0334 void Resynchronize(const byte *iv, int length=-1); 0335 0336 /// \brief Provides number of ideal bytes to process 0337 /// \return the ideal number of bytes to process 0338 /// \details Internally, the default implementation returns GetBytesPerIteration() 0339 /// \sa GetBytesPerIteration() and GetOptimalNextBlockSize() 0340 unsigned int OptimalBlockSize() const {return this->GetPolicy().GetOptimalBlockSize();} 0341 0342 /// \brief Provides number of ideal bytes to process 0343 /// \return the ideal number of bytes to process 0344 /// \details Internally, the default implementation returns remaining unprocessed bytes 0345 /// \sa GetBytesPerIteration() and OptimalBlockSize() 0346 unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;} 0347 0348 /// \brief Provides number of ideal data alignment 0349 /// \return the ideal data alignment, in bytes 0350 /// \sa GetAlignment() and OptimalBlockSize() 0351 unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} 0352 0353 /// \brief Determines if the cipher is self inverting 0354 /// \return true if the stream cipher is self inverting, false otherwise 0355 bool IsSelfInverting() const {return true;} 0356 0357 /// \brief Determines if the cipher is a forward transformation 0358 /// \return true if the stream cipher is a forward transformation, false otherwise 0359 bool IsForwardTransformation() const {return true;} 0360 0361 /// \brief Flag indicating random access 0362 /// \return true if the cipher is seekable, false otherwise 0363 /// \sa Seek() 0364 bool IsRandomAccess() const {return this->GetPolicy().CipherIsRandomAccess();} 0365 0366 /// \brief Seeks to a random position in the stream 0367 /// \param position the absolute position in the stream 0368 /// \sa IsRandomAccess() 0369 void Seek(lword position); 0370 0371 /// \brief Retrieve the provider of this algorithm 0372 /// \return the algorithm provider 0373 /// \details The algorithm provider can be a name like "C++", "SSE", "NEON", "AESNI", 0374 /// "ARMv8" and "Power8". C++ is standard C++ code. Other labels, like SSE, 0375 /// usually indicate a specialized implementation using instructions from a higher 0376 /// instruction set architecture (ISA). Future labels may include external hardware 0377 /// like a hardware security module (HSM). 0378 /// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2". 0379 /// Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics 0380 /// instead of ASM. 0381 /// \details Algorithms which combine different instructions or ISAs provide the 0382 /// dominant one. For example on x86 <tt>AES/GCM</tt> returns "AESNI" rather than 0383 /// "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL". 0384 /// \note Provider is not universally implemented yet. 0385 std::string AlgorithmProvider() const { return this->GetPolicy().AlgorithmProvider(); } 0386 0387 typedef typename BASE::PolicyInterface PolicyInterface; 0388 0389 protected: 0390 void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); 0391 0392 unsigned int GetBufferByteSize(const PolicyInterface &policy) const {return policy.GetBytesPerIteration() * policy.GetIterationsToBuffer();} 0393 0394 inline byte * KeystreamBufferBegin() {return this->m_buffer.data();} 0395 inline byte * KeystreamBufferEnd() {return (PtrAdd(this->m_buffer.data(), this->m_buffer.size()));} 0396 0397 AlignedSecByteBlock m_buffer; 0398 size_t m_leftOver; 0399 }; 0400 0401 /// \brief Policy object for feedback based stream ciphers 0402 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy 0403 { 0404 public: 0405 virtual ~CFB_CipherAbstractPolicy() {} 0406 0407 /// \brief Provides data alignment requirements 0408 /// \return data alignment requirements, in bytes 0409 /// \details Internally, the default implementation returns 1. If the stream cipher is implemented 0410 /// using an SSE2 ASM or intrinsics, then the value returned is usually 16. 0411 virtual unsigned int GetAlignment() const =0; 0412 0413 /// \brief Provides number of bytes operated upon during an iteration 0414 /// \return bytes operated upon during an iteration, in bytes 0415 /// \sa GetOptimalBlockSize() 0416 virtual unsigned int GetBytesPerIteration() const =0; 0417 0418 /// \brief Access the feedback register 0419 /// \return pointer to the first byte of the feedback register 0420 virtual byte * GetRegisterBegin() =0; 0421 0422 /// \brief TODO 0423 virtual void TransformRegister() =0; 0424 0425 /// \brief Flag indicating iteration support 0426 /// \return true if the cipher supports iteration, false otherwise 0427 virtual bool CanIterate() const {return false;} 0428 0429 /// \brief Iterate the cipher 0430 /// \param output the output buffer 0431 /// \param input the input buffer 0432 /// \param dir the direction of the cipher 0433 /// \param iterationCount the number of iterations to perform on the input 0434 /// \sa IsSelfInverting() and IsForwardTransformation() 0435 virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount) 0436 {CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(dir); 0437 CRYPTOPP_UNUSED(iterationCount); CRYPTOPP_ASSERT(false); 0438 throw Exception(Exception::OTHER_ERROR, "SimpleKeyingInterface: unexpected error");} 0439 0440 /// \brief Key the cipher 0441 /// \param params set of NameValuePairs use to initialize this object 0442 /// \param key a byte array used to key the cipher 0443 /// \param length the size of the key array 0444 virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) =0; 0445 0446 /// \brief Resynchronize the cipher 0447 /// \param iv a byte array used to resynchronize the cipher 0448 /// \param length the size of the IV array 0449 virtual void CipherResynchronize(const byte *iv, size_t length) 0450 {CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(length); 0451 throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");} 0452 0453 /// \brief Retrieve the provider of this algorithm 0454 /// \return the algorithm provider 0455 /// \details The algorithm provider can be a name like "C++", "SSE", "NEON", "AESNI", 0456 /// "ARMv8" and "Power8". C++ is standard C++ code. Other labels, like SSE, 0457 /// usually indicate a specialized implementation using instructions from a higher 0458 /// instruction set architecture (ISA). Future labels may include external hardware 0459 /// like a hardware security module (HSM). 0460 /// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2". 0461 /// Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics 0462 /// instead of ASM. 0463 /// \details Algorithms which combine different instructions or ISAs provide the 0464 /// dominant one. For example on x86 <tt>AES/GCM</tt> returns "AESNI" rather than 0465 /// "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL". 0466 /// \note Provider is not universally implemented yet. 0467 virtual std::string AlgorithmProvider() const { return "C++"; } 0468 }; 0469 0470 /// \brief Base class for feedback based stream ciphers 0471 /// \tparam WT word type 0472 /// \tparam W count of words 0473 /// \tparam BASE CFB_CipherAbstractPolicy derived base class 0474 template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy> 0475 struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE 0476 { 0477 typedef WT WordType; 0478 0479 virtual ~CFB_CipherConcretePolicy() {} 0480 0481 /// \brief Provides data alignment requirements 0482 /// \return data alignment requirements, in bytes 0483 /// \details Internally, the default implementation returns 1. If the stream cipher is implemented 0484 /// using an SSE2 ASM or intrinsics, then the value returned is usually 16. 0485 unsigned int GetAlignment() const {return sizeof(WordType);} 0486 0487 /// \brief Provides number of bytes operated upon during an iteration 0488 /// \return bytes operated upon during an iteration, in bytes 0489 /// \sa GetOptimalBlockSize() 0490 unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;} 0491 0492 /// \brief Flag indicating iteration support 0493 /// \return true if the cipher supports iteration, false otherwise 0494 bool CanIterate() const {return true;} 0495 0496 /// \brief Perform one iteration in the forward direction 0497 void TransformRegister() {this->Iterate(NULLPTR, NULLPTR, ENCRYPTION, 1);} 0498 0499 /// \brief Provides alternate access to a feedback register 0500 /// \tparam B enumeration indicating endianness 0501 /// \details RegisterOutput() provides alternate access to the feedback register. The 0502 /// enumeration B is BigEndian or LittleEndian. Repeatedly applying operator() 0503 /// results in advancing in the register. 0504 template <class B> 0505 struct RegisterOutput 0506 { 0507 RegisterOutput(byte *output, const byte *input, CipherDir dir) 0508 : m_output(output), m_input(input), m_dir(dir) {} 0509 0510 /// \brief XOR feedback register with data 0511 /// \param registerWord data represented as a word type 0512 /// \return reference to the next feedback register word 0513 inline RegisterOutput& operator()(WordType ®isterWord) 0514 { 0515 //CRYPTOPP_ASSERT(IsAligned<WordType>(m_output)); 0516 //CRYPTOPP_ASSERT(IsAligned<WordType>(m_input)); 0517 0518 if (!NativeByteOrderIs(B::ToEnum())) 0519 registerWord = ByteReverse(registerWord); 0520 0521 if (m_dir == ENCRYPTION) 0522 { 0523 if (m_input == NULLPTR) 0524 { 0525 CRYPTOPP_ASSERT(m_output == NULLPTR); 0526 } 0527 else 0528 { 0529 // WordType ct = *(const WordType *)m_input ^ registerWord; 0530 WordType ct = GetWord<WordType>(false, NativeByteOrder::ToEnum(), m_input) ^ registerWord; 0531 registerWord = ct; 0532 0533 // *(WordType*)m_output = ct; 0534 PutWord<WordType>(false, NativeByteOrder::ToEnum(), m_output, ct); 0535 0536 m_input += sizeof(WordType); 0537 m_output += sizeof(WordType); 0538 } 0539 } 0540 else 0541 { 0542 // WordType ct = *(const WordType *)m_input; 0543 WordType ct = GetWord<WordType>(false, NativeByteOrder::ToEnum(), m_input); 0544 0545 // *(WordType*)m_output = registerWord ^ ct; 0546 PutWord<WordType>(false, NativeByteOrder::ToEnum(), m_output, registerWord ^ ct); 0547 registerWord = ct; 0548 0549 m_input += sizeof(WordType); 0550 m_output += sizeof(WordType); 0551 } 0552 0553 // registerWord is left unreversed so it can be xor-ed with further input 0554 0555 return *this; 0556 } 0557 0558 byte *m_output; 0559 const byte *m_input; 0560 CipherDir m_dir; 0561 }; 0562 }; 0563 0564 /// \brief Base class for feedback based stream ciphers with SymmetricCipher interface 0565 /// \tparam BASE AbstractPolicyHolder base class 0566 template <class BASE> 0567 class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE 0568 { 0569 public: 0570 virtual ~CFB_CipherTemplate() {} 0571 CFB_CipherTemplate() : m_leftOver(0) {} 0572 0573 /// \brief Apply keystream to data 0574 /// \param outString a buffer to write the transformed data 0575 /// \param inString a buffer to read the data 0576 /// \param length the size of the buffers, in bytes 0577 /// \details This is the primary method to operate a stream cipher. For example: 0578 /// <pre> 0579 /// size_t size = 30; 0580 /// byte plain[size] = "Do or do not; there is no try"; 0581 /// byte cipher[size]; 0582 /// ... 0583 /// ChaCha20 chacha(key, keySize); 0584 /// chacha.ProcessData(cipher, plain, size); 0585 /// </pre> 0586 /// \details You should use distinct buffers for inString and outString. If the buffers 0587 /// are the same, then the data will be copied to an internal buffer to avoid GCC alias 0588 /// violations. The internal copy will impact performance. 0589 /// \sa <A HREF="https://github.com/weidai11/cryptopp/issues/1088">Issue 1088, 36% loss 0590 /// of performance with AES</A>, <A HREF="https://github.com/weidai11/cryptopp/issues/1010">Issue 0591 /// 1010, HIGHT cipher troubles with FileSource</A> 0592 void ProcessData(byte *outString, const byte *inString, size_t length); 0593 0594 /// \brief Resynchronize the cipher 0595 /// \param iv a byte array used to resynchronize the cipher 0596 /// \param length the size of the IV array 0597 void Resynchronize(const byte *iv, int length=-1); 0598 0599 /// \brief Provides number of ideal bytes to process 0600 /// \return the ideal number of bytes to process 0601 /// \details Internally, the default implementation returns GetBytesPerIteration() 0602 /// \sa GetBytesPerIteration() and GetOptimalNextBlockSize() 0603 unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();} 0604 0605 /// \brief Provides number of ideal bytes to process 0606 /// \return the ideal number of bytes to process 0607 /// \details Internally, the default implementation returns remaining unprocessed bytes 0608 /// \sa GetBytesPerIteration() and OptimalBlockSize() 0609 unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;} 0610 0611 /// \brief Provides number of ideal data alignment 0612 /// \return the ideal data alignment, in bytes 0613 /// \sa GetAlignment() and OptimalBlockSize() 0614 unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();} 0615 0616 /// \brief Flag indicating random access 0617 /// \return true if the cipher is seekable, false otherwise 0618 /// \sa Seek() 0619 bool IsRandomAccess() const {return false;} 0620 0621 /// \brief Determines if the cipher is self inverting 0622 /// \return true if the stream cipher is self inverting, false otherwise 0623 bool IsSelfInverting() const {return false;} 0624 0625 /// \brief Retrieve the provider of this algorithm 0626 /// \return the algorithm provider 0627 /// \details The algorithm provider can be a name like "C++", "SSE", "NEON", "AESNI", 0628 /// "ARMv8" and "Power8". C++ is standard C++ code. Other labels, like SSE, 0629 /// usually indicate a specialized implementation using instructions from a higher 0630 /// instruction set architecture (ISA). Future labels may include external hardware 0631 /// like a hardware security module (HSM). 0632 /// \details Generally speaking Wei Dai's original IA-32 ASM code falls under "SSE2". 0633 /// Labels like "SSSE3" and "SSE4.1" follow after Wei's code and use intrinsics 0634 /// instead of ASM. 0635 /// \details Algorithms which combine different instructions or ISAs provide the 0636 /// dominant one. For example on x86 <tt>AES/GCM</tt> returns "AESNI" rather than 0637 /// "CLMUL" or "AES+SSE4.1" or "AES+CLMUL" or "AES+SSE4.1+CLMUL". 0638 /// \note Provider is not universally implemented yet. 0639 std::string AlgorithmProvider() const { return this->GetPolicy().AlgorithmProvider(); } 0640 0641 typedef typename BASE::PolicyInterface PolicyInterface; 0642 0643 protected: 0644 virtual void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length) =0; 0645 0646 void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms); 0647 0648 size_t m_leftOver; 0649 }; 0650 0651 /// \brief Base class for feedback based stream ciphers in the forward direction with SymmetricCipher interface 0652 /// \tparam BASE AbstractPolicyHolder base class 0653 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> > 0654 class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE> 0655 { 0656 bool IsForwardTransformation() const {return true;} 0657 void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length); 0658 }; 0659 0660 /// \brief Base class for feedback based stream ciphers in the reverse direction with SymmetricCipher interface 0661 /// \tparam BASE AbstractPolicyHolder base class 0662 template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> > 0663 class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE> 0664 { 0665 bool IsForwardTransformation() const {return false;} 0666 void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length); 0667 }; 0668 0669 /// \brief Base class for feedback based stream ciphers with a mandatory block size 0670 /// \tparam BASE CFB_EncryptionTemplate or CFB_DecryptionTemplate base class 0671 template <class BASE> 0672 class CFB_RequireFullDataBlocks : public BASE 0673 { 0674 public: 0675 unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();} 0676 }; 0677 0678 /// \brief SymmetricCipher implementation 0679 /// \tparam BASE AbstractPolicyHolder derived base class 0680 /// \tparam INFO AbstractPolicyHolder derived information class 0681 /// \sa Weak::ARC4, ChaCha8, ChaCha12, ChaCha20, Salsa20, SEAL, Sosemanuk, WAKE 0682 template <class BASE, class INFO = BASE> 0683 class SymmetricCipherFinal : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO> 0684 { 0685 public: 0686 virtual ~SymmetricCipherFinal() {} 0687 0688 /// \brief Construct a stream cipher 0689 SymmetricCipherFinal() {} 0690 0691 /// \brief Construct a stream cipher 0692 /// \param key a byte array used to key the cipher 0693 /// \details This overload uses DEFAULT_KEYLENGTH 0694 SymmetricCipherFinal(const byte *key) 0695 {this->SetKey(key, this->DEFAULT_KEYLENGTH);} 0696 0697 /// \brief Construct a stream cipher 0698 /// \param key a byte array used to key the cipher 0699 /// \param length the size of the key array 0700 SymmetricCipherFinal(const byte *key, size_t length) 0701 {this->SetKey(key, length);} 0702 0703 /// \brief Construct a stream cipher 0704 /// \param key a byte array used to key the cipher 0705 /// \param length the size of the key array 0706 /// \param iv a byte array used as an initialization vector 0707 SymmetricCipherFinal(const byte *key, size_t length, const byte *iv) 0708 {this->SetKeyWithIV(key, length, iv);} 0709 0710 /// \brief Clone a SymmetricCipher 0711 /// \return a new SymmetricCipher based on this object 0712 Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinal<BASE, INFO>(*this));} 0713 }; 0714 0715 NAMESPACE_END 0716 0717 // Used by dll.cpp to ensure objects are in dll.o, and not strciphr.o. 0718 #ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES 0719 # include "strciphr.cpp" 0720 #endif 0721 0722 NAMESPACE_BEGIN(CryptoPP) 0723 0724 CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher>; 0725 CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate<AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >; 0726 0727 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >; 0728 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >; 0729 CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate<AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >; 0730 0731 NAMESPACE_END 0732 0733 #if CRYPTOPP_MSC_VERSION 0734 # pragma warning(pop) 0735 #endif 0736 0737 #endif
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |