Updated documentation
parent
433f2d6566
commit
746b618c3e
368
strciphr.h
368
strciphr.h
|
|
@ -1,29 +1,29 @@
|
|||
/*! \file
|
||||
This file contains helper classes for implementing stream ciphers.
|
||||
// strciphr.h - written and placed in the public domain by Wei Dai
|
||||
|
||||
All this infrastructure may look very complex compared to what's in Crypto++ 4.x,
|
||||
but stream ciphers implementations now support a lot of new functionality,
|
||||
including better performance (minimizing copying), resetting of keys and IVs, and methods to
|
||||
query which features are supported by a cipher.
|
||||
|
||||
Here's an explanation of these classes. The word "policy" is used here to mean a class with a
|
||||
set of methods that must be implemented by individual stream cipher implementations.
|
||||
This is usually much simpler than the full stream cipher API, which is implemented by
|
||||
either AdditiveCipherTemplate or CFB_CipherTemplate using the policy. So for example, an
|
||||
implementation of SEAL only needs to implement the AdditiveCipherAbstractPolicy interface
|
||||
(since it's an additive cipher, i.e., it xors a keystream into the plaintext).
|
||||
See this line in seal.h:
|
||||
|
||||
typedef SymmetricCipherFinal\<ConcretePolicyHolder\<SEAL_Policy\<B\>, AdditiveCipherTemplate\<\> \> \> Encryption;
|
||||
|
||||
AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't need
|
||||
to take a policy class as a template parameter (although this is allowed), so that
|
||||
their code is not duplicated for each new cipher. Instead they each
|
||||
get a reference to an abstract policy interface by calling AccessPolicy() on itself, so
|
||||
AccessPolicy() must be overriden to return the actual policy reference. This is done
|
||||
by the ConceretePolicyHolder class. Finally, SymmetricCipherFinal implements the constructors and
|
||||
other functions that must be implemented by the most derived class.
|
||||
*/
|
||||
//! \file strciphr.h
|
||||
//! \brief Classes for implementing stream ciphers
|
||||
//! \details This file contains helper classes for implementing stream ciphers.
|
||||
//! All this infrastructure may look very complex compared to what's in Crypto++ 4.x,
|
||||
//! but stream ciphers implementations now support a lot of new functionality,
|
||||
//! including better performance (minimizing copying), resetting of keys and IVs, and methods to
|
||||
//! query which features are supported by a cipher.
|
||||
//! \details Here's an explanation of these classes. The word "policy" is used here to mean a class with a
|
||||
//! set of methods that must be implemented by individual stream cipher implementations.
|
||||
//! This is usually much simpler than the full stream cipher API, which is implemented by
|
||||
//! either AdditiveCipherTemplate or CFB_CipherTemplate using the policy. So for example, an
|
||||
//! implementation of SEAL only needs to implement the AdditiveCipherAbstractPolicy interface
|
||||
//! (since it's an additive cipher, i.e., it xors a keystream into the plaintext).
|
||||
//! See this line in seal.h:
|
||||
//! <pre>
|
||||
//! typedef SymmetricCipherFinal\<ConcretePolicyHolder\<SEAL_Policy\<B\>, AdditiveCipherTemplate\<\> \> \> Encryption;
|
||||
//! </pre>
|
||||
//! \details AdditiveCipherTemplate and CFB_CipherTemplate are designed so that they don't need
|
||||
//! to take a policy class as a template parameter (although this is allowed), so that
|
||||
//! their code is not duplicated for each new cipher. Instead they each
|
||||
//! get a reference to an abstract policy interface by calling AccessPolicy() on itself, so
|
||||
//! AccessPolicy() must be overriden to return the actual policy reference. This is done
|
||||
//! by the ConceretePolicyHolder class. Finally, SymmetricCipherFinal implements the constructors and
|
||||
//! other functions that must be implemented by the most derived class.
|
||||
|
||||
#ifndef CRYPTOPP_STRCIPHR_H
|
||||
#define CRYPTOPP_STRCIPHR_H
|
||||
|
|
@ -42,6 +42,10 @@
|
|||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! \class AbstractPolicyHolder
|
||||
//! \brief Access a stream cipher policy object
|
||||
//! \tparam POLICY_INTERFACE class implementing AbstractPolicyHolder
|
||||
//! \tparam BASE class or type to use as a base class
|
||||
template <class POLICY_INTERFACE, class BASE = Empty>
|
||||
class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE
|
||||
{
|
||||
|
|
@ -54,43 +58,132 @@ protected:
|
|||
virtual POLICY_INTERFACE & AccessPolicy() =0;
|
||||
};
|
||||
|
||||
//! \class ConcretePolicyHolder
|
||||
//! \brief Stream cipher policy object
|
||||
//! \tparam POLICY class implementing AbstractPolicyHolder
|
||||
//! \tparam BASE class or type to use as a base class
|
||||
template <class POLICY, class BASE, class POLICY_INTERFACE = CPP_TYPENAME BASE::PolicyInterface>
|
||||
class ConcretePolicyHolder : public BASE, protected POLICY
|
||||
{
|
||||
public:
|
||||
#ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
|
||||
virtual ~ConcretePolicyHolder() {}
|
||||
#endif
|
||||
protected:
|
||||
const POLICY_INTERFACE & GetPolicy() const {return *this;}
|
||||
POLICY_INTERFACE & AccessPolicy() {return *this;}
|
||||
};
|
||||
|
||||
enum KeystreamOperationFlags {OUTPUT_ALIGNED=1, INPUT_ALIGNED=2, INPUT_NULL = 4};
|
||||
//! \brief Keystream operation flags
|
||||
//! \sa AdditiveCipherAbstractPolicy::GetBytesPerIteration(), AdditiveCipherAbstractPolicy::GetOptimalBlockSize()
|
||||
//! and AdditiveCipherAbstractPolicy::GetAlignment()
|
||||
enum KeystreamOperationFlags {
|
||||
//! \brief Output buffer is aligned
|
||||
OUTPUT_ALIGNED=1,
|
||||
//! \brief Input buffer is aligned
|
||||
INPUT_ALIGNED=2,
|
||||
//! \brief Input buffer is NULL
|
||||
INPUT_NULL = 4
|
||||
};
|
||||
|
||||
//! \brief Keystream operation flags
|
||||
//! \sa AdditiveCipherAbstractPolicy::GetBytesPerIteration(), AdditiveCipherAbstractPolicy::GetOptimalBlockSize()
|
||||
//! and AdditiveCipherAbstractPolicy::GetAlignment()
|
||||
enum KeystreamOperation {
|
||||
//! \brief Wirte the keystream to the output buffer, input is NULL
|
||||
WRITE_KEYSTREAM = INPUT_NULL,
|
||||
//! \brief Wirte the keystream to the aligned output buffer, input is NULL
|
||||
WRITE_KEYSTREAM_ALIGNED = INPUT_NULL | OUTPUT_ALIGNED,
|
||||
XOR_KEYSTREAM = 0,
|
||||
XOR_KEYSTREAM_INPUT_ALIGNED = INPUT_ALIGNED,
|
||||
XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED,
|
||||
//! \brief XOR the input buffer and keystream, write to the output buffer
|
||||
XOR_KEYSTREAM = 0,
|
||||
//! \brief XOR the aligned input buffer and keystream, write to the output buffer
|
||||
XOR_KEYSTREAM_INPUT_ALIGNED = INPUT_ALIGNED,
|
||||
//! \brief XOR the input buffer and keystream, write to the aligned output buffer
|
||||
XOR_KEYSTREAM_OUTPUT_ALIGNED= OUTPUT_ALIGNED,
|
||||
//! \brief XOR the aligned input buffer and keystream, write to the aligned output buffer
|
||||
XOR_KEYSTREAM_BOTH_ALIGNED = OUTPUT_ALIGNED | INPUT_ALIGNED};
|
||||
|
||||
//! \class AdditiveCipherAbstractPolicy
|
||||
//! \brief Policy object for additive stream ciphers
|
||||
struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy
|
||||
{
|
||||
virtual ~AdditiveCipherAbstractPolicy() {}
|
||||
|
||||
//! \brief Provides data alignment requirements
|
||||
//! \returns data alignment requirements, in bytes
|
||||
//! \details Internally, the default implementation returns 1. If the stream cipher is implemented
|
||||
//! using an SSE2 ASM or intrinsics, then the value returned is usually 16.
|
||||
virtual unsigned int GetAlignment() const {return 1;}
|
||||
|
||||
//! \brief Provides number of bytes operated upon during an iteration
|
||||
//! \returns bytes operated upon during an iteration, in bytes
|
||||
//! \sa GetOptimalBlockSize()
|
||||
virtual unsigned int GetBytesPerIteration() const =0;
|
||||
|
||||
//! \brief Provides number of ideal bytes to process
|
||||
//! \returns the ideal number of bytes to process
|
||||
//! \details Internally, the default implementation returns GetBytesPerIteration()
|
||||
//! \sa GetBytesPerIteration()
|
||||
virtual unsigned int GetOptimalBlockSize() const {return GetBytesPerIteration();}
|
||||
|
||||
//! \brief Provides buffer size based on iterations
|
||||
//! \returns the buffer size based on iterations, in bytes
|
||||
virtual unsigned int GetIterationsToBuffer() const =0;
|
||||
|
||||
//! \brief Generate the keystream
|
||||
//! \param keystream the key stream
|
||||
//! \param iterationCount the number of iterations to generate the key stream
|
||||
//! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream()
|
||||
virtual void WriteKeystream(byte *keystream, size_t iterationCount)
|
||||
{OperateKeystream(KeystreamOperation(INPUT_NULL | (KeystreamOperationFlags)IsAlignedOn(keystream, GetAlignment())), keystream, NULL, iterationCount);}
|
||||
|
||||
//! \brief Flag indicating
|
||||
//! \returns true if the stream can be generated independent of the transformation input, false otherwise
|
||||
//! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream()
|
||||
virtual bool CanOperateKeystream() const {return false;}
|
||||
|
||||
//! \brief Operates the keystream
|
||||
//! \param operation the operation with additional flags
|
||||
//! \param output the output buffer
|
||||
//! \param input the input buffer
|
||||
//! \param iterationCount the number of iterations to perform on the input
|
||||
//! \details OperateKeystream() will attempt to operate upon GetOptimalBlockSize() buffer,
|
||||
//! which will be derived from GetBytesPerIteration().
|
||||
//! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream(), KeystreamOperation()
|
||||
virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
|
||||
{CRYPTOPP_UNUSED(operation); CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(iterationCount); assert(false);}
|
||||
|
||||
//! \brief Key the cipher
|
||||
//! \param params set of NameValuePairs use to initialize this object
|
||||
//! \param key a byte array used to key the cipher
|
||||
//! \param length the size of the key array
|
||||
virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) =0;
|
||||
|
||||
//! \brief Resynchronize the cipher
|
||||
//! \param keystreamBuffer the keystream buffer
|
||||
//! \param iv a byte array used to resynchronize the cipher
|
||||
//! \param length the size of the IV array
|
||||
virtual void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
|
||||
{CRYPTOPP_UNUSED(keystreamBuffer); CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(length); throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
|
||||
|
||||
//! \brief Flag indicating random access
|
||||
//! \returns true if the cipher is seekable, false otherwise
|
||||
//! \sa SeekToIteration()
|
||||
virtual bool CipherIsRandomAccess() const =0;
|
||||
|
||||
//! \brief Seeks to a random position in the stream
|
||||
//! \returns iterationCount
|
||||
//! \sa CipherIsRandomAccess()
|
||||
virtual void SeekToIteration(lword iterationCount)
|
||||
{CRYPTOPP_UNUSED(iterationCount); assert(!CipherIsRandomAccess()); throw NotImplemented("StreamTransformation: this object doesn't support random access");}
|
||||
};
|
||||
|
||||
//! \class AdditiveCipherConcretePolicy
|
||||
//! \brief Base class for additive stream ciphers
|
||||
//! \tparam WT word type
|
||||
//! \tparam W count of words
|
||||
//! \tparam X bytes per iteration count
|
||||
//! \tparam BASE AdditiveCipherAbstractPolicy derived base class
|
||||
template <typename WT, unsigned int W, unsigned int X = 1, class BASE = AdditiveCipherAbstractPolicy>
|
||||
struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE
|
||||
{
|
||||
|
|
@ -98,21 +191,49 @@ struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE
|
|||
CRYPTOPP_CONSTANT(BYTES_PER_ITERATION = sizeof(WordType) * W)
|
||||
|
||||
#if !(CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64)
|
||||
//! \brief Provides data alignment requirements
|
||||
//! \returns data alignment requirements, in bytes
|
||||
//! \details Internally, the default implementation returns 1. If the stream cipher is implemented
|
||||
//! using an SSE2 ASM or intrinsics, then the value returned is usually 16.
|
||||
unsigned int GetAlignment() const {return GetAlignmentOf<WordType>();}
|
||||
#endif
|
||||
|
||||
//! \brief Provides number of bytes operated upon during an iteration
|
||||
//! \returns bytes operated upon during an iteration, in bytes
|
||||
//! \sa GetOptimalBlockSize()
|
||||
unsigned int GetBytesPerIteration() const {return BYTES_PER_ITERATION;}
|
||||
|
||||
//! \brief Provides buffer size based on iterations
|
||||
//! \returns the buffer size based on iterations, in bytes
|
||||
unsigned int GetIterationsToBuffer() const {return X;}
|
||||
|
||||
//! \brief Flag indicating
|
||||
//! \returns true if the stream can be generated independent of the transformation input, false otherwise
|
||||
//! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream()
|
||||
bool CanOperateKeystream() const {return true;}
|
||||
|
||||
//! \brief Operates the keystream
|
||||
//! \param operation the operation with additional flags
|
||||
//! \param output the output buffer
|
||||
//! \param input the input buffer
|
||||
//! \param iterationCount the number of iterations to perform on the input
|
||||
//! \details OperateKeystream() will attempt to operate upon GetOptimalBlockSize() buffer,
|
||||
//! which will be derived from GetBytesPerIteration().
|
||||
//! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream(), KeystreamOperation()
|
||||
virtual void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) =0;
|
||||
};
|
||||
|
||||
// use these to implement OperateKeystream
|
||||
//! \brief Helper macro to implement OperateKeystream
|
||||
#define CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, b, i, a) \
|
||||
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)));
|
||||
|
||||
//! \brief Helper macro to implement OperateKeystream
|
||||
#define CRYPTOPP_KEYSTREAM_OUTPUT_XMM(x, i, a) {\
|
||||
__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));\
|
||||
if (x & OUTPUT_ALIGNED) _mm_store_si128((__m128i *)output+i, t);\
|
||||
else _mm_storeu_si128((__m128i *)output+i, t);}
|
||||
|
||||
//! \brief Helper macro to implement OperateKeystream
|
||||
#define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y) \
|
||||
switch (operation) \
|
||||
{ \
|
||||
|
|
@ -141,19 +262,73 @@ struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE
|
|||
} \
|
||||
output += y;
|
||||
|
||||
//! \class AdditiveCipherTemplate
|
||||
//! \brief Base class for additive stream ciphers with SymmetricCipher interface
|
||||
//! \tparam BASE AbstractPolicyHolder base class
|
||||
template <class BASE = AbstractPolicyHolder<AdditiveCipherAbstractPolicy, SymmetricCipher> >
|
||||
class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE, public RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
//! \brief Generate random array of bytes
|
||||
//! \param output the byte buffer
|
||||
//! \param size the length of the buffer, in bytes
|
||||
//! \details All generated values are uniformly distributed over the range specified within the
|
||||
//! the contraints of a particular generator.
|
||||
void GenerateBlock(byte *output, size_t size);
|
||||
|
||||
//! \brief Apply keystream to data
|
||||
//! \param outString a buffer to write the transformed data
|
||||
//! \param inString a buffer to read the data
|
||||
//! \param length the size fo the buffers, in bytes
|
||||
//! \details This is the primary method to operate a stream cipher. For example:
|
||||
//! <pre>
|
||||
//! size_t size = 30;
|
||||
//! byte plain[size] = "Do or do not; there is no try";
|
||||
//! byte cipher[size];
|
||||
//! ...
|
||||
//! ChaCha20 chacha(key, keySize);
|
||||
//! chacha.ProcessData(cipher, plain, size);
|
||||
//! </pre>
|
||||
void ProcessData(byte *outString, const byte *inString, size_t length);
|
||||
|
||||
//! \brief Resynchronize the cipher
|
||||
//! \param iv a byte array used to resynchronize the cipher
|
||||
//! \param length the size of the IV array
|
||||
void Resynchronize(const byte *iv, int length=-1);
|
||||
|
||||
//! \brief Provides number of ideal bytes to process
|
||||
//! \returns the ideal number of bytes to process
|
||||
//! \details Internally, the default implementation returns GetBytesPerIteration()
|
||||
//! \sa GetBytesPerIteration() and GetOptimalNextBlockSize()
|
||||
unsigned int OptimalBlockSize() const {return this->GetPolicy().GetOptimalBlockSize();}
|
||||
|
||||
//! \brief Provides number of ideal bytes to process
|
||||
//! \returns the ideal number of bytes to process
|
||||
//! \details Internally, the default implementation returns remaining unprocessed bytes
|
||||
//! \sa GetBytesPerIteration() and OptimalBlockSize()
|
||||
unsigned int GetOptimalNextBlockSize() const {return (unsigned int)this->m_leftOver;}
|
||||
|
||||
//! \brief Provides number of ideal data alignment
|
||||
//! \returns the ideal data alignment, in bytes
|
||||
//! \sa GetAlignment() and OptimalBlockSize()
|
||||
unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
|
||||
|
||||
//! \brief Determines if the cipher is self inverting
|
||||
//! \returns true if the stream cipher is self inverting, false otherwise
|
||||
bool IsSelfInverting() const {return true;}
|
||||
|
||||
//! \brief Determines if the cipher is a forward transformation
|
||||
//! \returns true if the stream cipher is a forward transformation, false otherwise
|
||||
bool IsForwardTransformation() const {return true;}
|
||||
|
||||
//! \brief Flag indicating random access
|
||||
//! \returns true if the cipher is seekable, false otherwise
|
||||
//! \sa Seek()
|
||||
bool IsRandomAccess() const {return this->GetPolicy().CipherIsRandomAccess();}
|
||||
|
||||
//! \brief Seeks to a random position in the stream
|
||||
//! \param position the absolute position in the stream
|
||||
//! \sa IsRandomAccess()
|
||||
void Seek(lword position);
|
||||
|
||||
typedef typename BASE::PolicyInterface PolicyInterface;
|
||||
|
|
@ -170,39 +345,100 @@ protected:
|
|||
size_t m_leftOver;
|
||||
};
|
||||
|
||||
//! \class CFB_CipherAbstractPolicy
|
||||
//! \brief Policy object for feeback based stream ciphers
|
||||
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy
|
||||
{
|
||||
public:
|
||||
virtual ~CFB_CipherAbstractPolicy() {}
|
||||
|
||||
//! \brief Provides data alignment requirements
|
||||
//! \returns data alignment requirements, in bytes
|
||||
//! \details Internally, the default implementation returns 1. If the stream cipher is implemented
|
||||
//! using an SSE2 ASM or intrinsics, then the value returned is usually 16.
|
||||
virtual unsigned int GetAlignment() const =0;
|
||||
|
||||
//! \brief Provides number of bytes operated upon during an iteration
|
||||
//! \returns bytes operated upon during an iteration, in bytes
|
||||
//! \sa GetOptimalBlockSize()
|
||||
virtual unsigned int GetBytesPerIteration() const =0;
|
||||
|
||||
//! \brief Access the feedback register
|
||||
//! \returns pointer to the first byte of the feedback register
|
||||
virtual byte * GetRegisterBegin() =0;
|
||||
|
||||
//! \brief TODO
|
||||
virtual void TransformRegister() =0;
|
||||
|
||||
//! \brief Flag indicating iteration support
|
||||
//! \returns true if the cipher supports iteration, false otherwise
|
||||
virtual bool CanIterate() const {return false;}
|
||||
|
||||
//! \brief Iterate the cipher
|
||||
//! \param output the output buffer
|
||||
//! \param input the input buffer
|
||||
//! \param dir the direction of the cipher
|
||||
//! \param iterationCount the number of iterations to perform on the input
|
||||
//! \sa IsSelfInverting() and IsForwardTransformation()
|
||||
virtual void Iterate(byte *output, const byte *input, CipherDir dir, size_t iterationCount)
|
||||
{CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(dir); CRYPTOPP_UNUSED(iterationCount);
|
||||
assert(false); /*throw 0;*/ throw Exception(Exception::OTHER_ERROR, "SimpleKeyingInterface: unexpected error");}
|
||||
|
||||
//! \brief Key the cipher
|
||||
//! \param params set of NameValuePairs use to initialize this object
|
||||
//! \param key a byte array used to key the cipher
|
||||
//! \param length the size of the key array
|
||||
virtual void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) =0;
|
||||
|
||||
//! \brief Resynchronize the cipher
|
||||
//! \param iv a byte array used to resynchronize the cipher
|
||||
//! \param length the size of the IV array
|
||||
virtual void CipherResynchronize(const byte *iv, size_t length)
|
||||
{CRYPTOPP_UNUSED(iv); CRYPTOPP_UNUSED(length); throw NotImplemented("SimpleKeyingInterface: this object doesn't support resynchronization");}
|
||||
};
|
||||
|
||||
//! \class CFB_CipherConcretePolicy
|
||||
//! \brief Base class for feedback based stream ciphers
|
||||
//! \tparam WT word type
|
||||
//! \tparam W count of words
|
||||
//! \tparam BASE CFB_CipherAbstractPolicy derived base class
|
||||
template <typename WT, unsigned int W, class BASE = CFB_CipherAbstractPolicy>
|
||||
struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE
|
||||
{
|
||||
typedef WT WordType;
|
||||
|
||||
//! \brief Provides data alignment requirements
|
||||
//! \returns data alignment requirements, in bytes
|
||||
//! \details Internally, the default implementation returns 1. If the stream cipher is implemented
|
||||
//! using an SSE2 ASM or intrinsics, then the value returned is usually 16.
|
||||
unsigned int GetAlignment() const {return sizeof(WordType);}
|
||||
|
||||
//! \brief Provides number of bytes operated upon during an iteration
|
||||
//! \returns bytes operated upon during an iteration, in bytes
|
||||
//! \sa GetOptimalBlockSize()
|
||||
unsigned int GetBytesPerIteration() const {return sizeof(WordType) * W;}
|
||||
|
||||
//! \brief Flag indicating iteration support
|
||||
//! \returns true if the cipher supports iteration, false otherwise
|
||||
bool CanIterate() const {return true;}
|
||||
|
||||
//! \brief Perform one iteration in the forward direction
|
||||
void TransformRegister() {this->Iterate(NULL, NULL, ENCRYPTION, 1);}
|
||||
|
||||
//! \brief
|
||||
//! \tparam B enumeration indicating endianess
|
||||
//! \details RegisterOutput() provides alternate access to the feedback register. The
|
||||
//! enumeration B is BigEndian or LittleEndian. Repeatedly applying operator()
|
||||
//! results in advancing in the register.
|
||||
template <class B>
|
||||
struct RegisterOutput
|
||||
{
|
||||
RegisterOutput(byte *output, const byte *input, CipherDir dir)
|
||||
: m_output(output), m_input(input), m_dir(dir) {}
|
||||
|
||||
//! \brief XOR feedback register with data
|
||||
//! \param registerWord data represented as a word type
|
||||
//! \returns reference to the next feedback register word
|
||||
inline RegisterOutput& operator()(WordType ®isterWord)
|
||||
{
|
||||
assert(IsAligned<WordType>(m_output));
|
||||
|
|
@ -244,16 +480,57 @@ struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE
|
|||
};
|
||||
};
|
||||
|
||||
//! \class AdditiveCipherTemplate
|
||||
//! \brief Base class for stream ciphers with SymmetricCipher interface
|
||||
//! \tparam BASE AbstractPolicyHolder base class
|
||||
template <class BASE>
|
||||
class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE
|
||||
{
|
||||
public:
|
||||
//! \brief Apply keystream to data
|
||||
//! \param outString a buffer to write the transformed data
|
||||
//! \param inString a buffer to read the data
|
||||
//! \param length the size fo the buffers, in bytes
|
||||
//! \details This is the primary method to operate a stream cipher. For example:
|
||||
//! <pre>
|
||||
//! size_t size = 30;
|
||||
//! byte plain[size] = "Do or do not; there is no try";
|
||||
//! byte cipher[size];
|
||||
//! ...
|
||||
//! ChaCha20 chacha(key, keySize);
|
||||
//! chacha.ProcessData(cipher, plain, size);
|
||||
//! </pre>
|
||||
void ProcessData(byte *outString, const byte *inString, size_t length);
|
||||
|
||||
//! \brief Resynchronize the cipher
|
||||
//! \param iv a byte array used to resynchronize the cipher
|
||||
//! \param length the size of the IV array
|
||||
void Resynchronize(const byte *iv, int length=-1);
|
||||
|
||||
//! \brief Provides number of ideal bytes to process
|
||||
//! \returns the ideal number of bytes to process
|
||||
//! \details Internally, the default implementation returns GetBytesPerIteration()
|
||||
//! \sa GetBytesPerIteration() and GetOptimalNextBlockSize()
|
||||
unsigned int OptimalBlockSize() const {return this->GetPolicy().GetBytesPerIteration();}
|
||||
|
||||
//! \brief Provides number of ideal bytes to process
|
||||
//! \returns the ideal number of bytes to process
|
||||
//! \details Internally, the default implementation returns remaining unprocessed bytes
|
||||
//! \sa GetBytesPerIteration() and OptimalBlockSize()
|
||||
unsigned int GetOptimalNextBlockSize() const {return (unsigned int)m_leftOver;}
|
||||
|
||||
//! \brief Provides number of ideal data alignment
|
||||
//! \returns the ideal data alignment, in bytes
|
||||
//! \sa GetAlignment() and OptimalBlockSize()
|
||||
unsigned int OptimalDataAlignment() const {return this->GetPolicy().GetAlignment();}
|
||||
|
||||
//! \brief Flag indicating random access
|
||||
//! \returns true if the cipher is seekable, false otherwise
|
||||
//! \sa Seek()
|
||||
bool IsRandomAccess() const {return false;}
|
||||
|
||||
//! \brief Determines if the cipher is self inverting
|
||||
//! \returns true if the stream cipher is self inverting, false otherwise
|
||||
bool IsSelfInverting() const {return false;}
|
||||
|
||||
typedef typename BASE::PolicyInterface PolicyInterface;
|
||||
|
|
@ -266,6 +543,9 @@ protected:
|
|||
size_t m_leftOver;
|
||||
};
|
||||
|
||||
//! \class CFB_EncryptionTemplate
|
||||
//! \brief Base class for feedback based stream ciphers in the forward direction with SymmetricCipher interface
|
||||
//! \tparam BASE AbstractPolicyHolder base class
|
||||
template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
|
||||
class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE>
|
||||
{
|
||||
|
|
@ -273,6 +553,9 @@ class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate<BASE
|
|||
void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
|
||||
};
|
||||
|
||||
//! \class CFB_DecryptionTemplate
|
||||
//! \brief Base class for feedback based stream ciphers in the reverse direction with SymmetricCipher interface
|
||||
//! \tparam BASE AbstractPolicyHolder base class
|
||||
template <class BASE = AbstractPolicyHolder<CFB_CipherAbstractPolicy, SymmetricCipher> >
|
||||
class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE>
|
||||
{
|
||||
|
|
@ -280,6 +563,9 @@ class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate<BASE
|
|||
void CombineMessageAndShiftRegister(byte *output, byte *reg, const byte *message, size_t length);
|
||||
};
|
||||
|
||||
//! \class CFB_RequireFullDataBlocks
|
||||
//! \brief Base class for feedback based stream ciphers with a mandatory block size
|
||||
//! \tparam BASE CFB_EncryptionTemplate or CFB_DecryptionTemplate base class
|
||||
template <class BASE>
|
||||
class CFB_RequireFullDataBlocks : public BASE
|
||||
{
|
||||
|
|
@ -287,19 +573,39 @@ public:
|
|||
unsigned int MandatoryBlockSize() const {return this->OptimalBlockSize();}
|
||||
};
|
||||
|
||||
//! _
|
||||
//! \class SymmetricCipherFinal
|
||||
//! \brief SymmetricCipher implementation
|
||||
//! \tparam BASE AbstractPolicyHolder derived base class
|
||||
//! \tparam INFO AbstractPolicyHolder derived information class
|
||||
//! \sa Weak::ARC4, ChaCha8, ChaCha12, ChaCha20, Salsa20, SEAL, Sosemanuk, WAKE
|
||||
template <class BASE, class INFO = BASE>
|
||||
class SymmetricCipherFinal : public AlgorithmImpl<SimpleKeyingInterfaceImpl<BASE, INFO>, INFO>
|
||||
{
|
||||
public:
|
||||
//! \brief Construct a stream cipher
|
||||
SymmetricCipherFinal() {}
|
||||
|
||||
//! \brief Construct a stream cipher
|
||||
//! \param key a byte array used to key the cipher
|
||||
//! \details This overload uses DEFAULT_KEYLENGTH
|
||||
SymmetricCipherFinal(const byte *key)
|
||||
{this->SetKey(key, this->DEFAULT_KEYLENGTH);}
|
||||
|
||||
//! \brief Construct a stream cipher
|
||||
//! \param key a byte array used to key the cipher
|
||||
//! \param length the size of the key array
|
||||
SymmetricCipherFinal(const byte *key, size_t length)
|
||||
{this->SetKey(key, length);}
|
||||
|
||||
//! \brief Construct a stream cipher
|
||||
//! \param key a byte array used to key the cipher
|
||||
//! \param length the size of the key array
|
||||
//! \param iv a byte array used as an initialization vector
|
||||
SymmetricCipherFinal(const byte *key, size_t length, const byte *iv)
|
||||
{this->SetKeyWithIV(key, length, iv);}
|
||||
|
||||
//! \brief Clone a SymmetricCipher
|
||||
//! \returns a new SymmetricCipher based on this object
|
||||
Clonable * Clone() const {return static_cast<SymmetricCipher *>(new SymmetricCipherFinal<BASE, INFO>(*this));}
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue