2017-01-27 12:05:45 +00:00
// strciphr.h - originally written and placed in the public domain by Wei Dai
2016-04-22 03:06:26 +00:00
//! \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
2016-12-27 17:34:57 +00:00
//! AccessPolicy() must be overridden to return the actual policy reference. This is done
2016-04-22 03:06:26 +00:00
//! by the ConceretePolicyHolder class. Finally, SymmetricCipherFinal implements the constructors and
//! other functions that must be implemented by the most derived class.
2015-11-05 06:59:46 +00:00
# ifndef CRYPTOPP_STRCIPHR_H
# define CRYPTOPP_STRCIPHR_H
# include "config.h"
# if CRYPTOPP_MSC_VERSION
# pragma warning(push)
2017-06-02 09:18:52 +00:00
# pragma warning(disable: 4127 4189 4231 4275)
2015-11-05 06:59:46 +00:00
# endif
# include "cryptlib.h"
# include "seckey.h"
# include "secblock.h"
# include "argnames.h"
NAMESPACE_BEGIN ( CryptoPP )
2016-04-22 03:06:26 +00:00
//! \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
2015-11-05 06:59:46 +00:00
template < class POLICY_INTERFACE , class BASE = Empty >
class CRYPTOPP_NO_VTABLE AbstractPolicyHolder : public BASE
{
public :
typedef POLICY_INTERFACE PolicyInterface ;
virtual ~ AbstractPolicyHolder ( ) { }
protected :
virtual const POLICY_INTERFACE & GetPolicy ( ) const = 0 ;
virtual POLICY_INTERFACE & AccessPolicy ( ) = 0 ;
} ;
2016-04-22 03:06:26 +00:00
//! \class ConcretePolicyHolder
//! \brief Stream cipher policy object
//! \tparam POLICY class implementing AbstractPolicyHolder
//! \tparam BASE class or type to use as a base class
2016-12-03 10:05:56 +00:00
template < class POLICY , class BASE , class POLICY_INTERFACE = typename BASE : : PolicyInterface >
2015-11-05 06:59:46 +00:00
class ConcretePolicyHolder : public BASE , protected POLICY
{
2016-04-22 03:06:26 +00:00
public :
virtual ~ ConcretePolicyHolder ( ) { }
2015-11-05 06:59:46 +00:00
protected :
const POLICY_INTERFACE & GetPolicy ( ) const { return * this ; }
POLICY_INTERFACE & AccessPolicy ( ) { return * this ; }
} ;
2016-04-22 03:06:26 +00:00
//! \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()
2015-11-05 06:59:46 +00:00
enum KeystreamOperation {
2016-04-22 03:06:26 +00:00
//! \brief Wirte the keystream to the output buffer, input is NULL
2016-09-10 08:57:48 +00:00
WRITE_KEYSTREAM = INPUT_NULL ,
2016-04-22 03:06:26 +00:00
//! \brief Wirte the keystream to the aligned output buffer, input is NULL
2016-09-10 08:57:48 +00:00
WRITE_KEYSTREAM_ALIGNED = INPUT_NULL | OUTPUT_ALIGNED ,
2016-04-22 03:06:26 +00:00
//! \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
2015-11-05 06:59:46 +00:00
XOR_KEYSTREAM_BOTH_ALIGNED = OUTPUT_ALIGNED | INPUT_ALIGNED } ;
2016-04-22 03:06:26 +00:00
//! \class AdditiveCipherAbstractPolicy
//! \brief Policy object for additive stream ciphers
2015-11-05 06:59:46 +00:00
struct CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AdditiveCipherAbstractPolicy
{
virtual ~ AdditiveCipherAbstractPolicy ( ) { }
2016-04-22 03:06:26 +00:00
//! \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.
2015-11-05 06:59:46 +00:00
virtual unsigned int GetAlignment ( ) const { return 1 ; }
2016-04-22 03:06:26 +00:00
//! \brief Provides number of bytes operated upon during an iteration
//! \returns bytes operated upon during an iteration, in bytes
//! \sa GetOptimalBlockSize()
2015-11-05 06:59:46 +00:00
virtual unsigned int GetBytesPerIteration ( ) const = 0 ;
2016-04-22 03:06:26 +00:00
//! \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()
2015-11-05 06:59:46 +00:00
virtual unsigned int GetOptimalBlockSize ( ) const { return GetBytesPerIteration ( ) ; }
2016-04-22 03:06:26 +00:00
//! \brief Provides buffer size based on iterations
//! \returns the buffer size based on iterations, in bytes
2015-11-05 06:59:46 +00:00
virtual unsigned int GetIterationsToBuffer ( ) const = 0 ;
2016-04-22 03:06:26 +00:00
//! \brief Generate the keystream
//! \param keystream the key stream
//! \param iterationCount the number of iterations to generate the key stream
//! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream()
2015-11-05 06:59:46 +00:00
virtual void WriteKeystream ( byte * keystream , size_t iterationCount )
2017-03-01 11:10:06 +00:00
{ OperateKeystream ( KeystreamOperation ( INPUT_NULL | ( KeystreamOperationFlags ) IsAlignedOn ( keystream , GetAlignment ( ) ) ) , keystream , NULLPTR , iterationCount ) ; }
2016-04-22 03:06:26 +00:00
//! \brief Flag indicating
//! \returns true if the stream can be generated independent of the transformation input, false otherwise
//! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream()
2015-11-05 06:59:46 +00:00
virtual bool CanOperateKeystream ( ) const { return false ; }
2016-04-22 03:06:26 +00:00
//! \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()
2015-11-05 06:59:46 +00:00
virtual void OperateKeystream ( KeystreamOperation operation , byte * output , const byte * input , size_t iterationCount )
2016-09-16 15:27:15 +00:00
{ CRYPTOPP_UNUSED ( operation ) ; CRYPTOPP_UNUSED ( output ) ; CRYPTOPP_UNUSED ( input ) ; CRYPTOPP_UNUSED ( iterationCount ) ; CRYPTOPP_ASSERT ( false ) ; }
2016-04-22 03:06:26 +00:00
//! \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
2015-11-05 06:59:46 +00:00
virtual void CipherSetKey ( const NameValuePairs & params , const byte * key , size_t length ) = 0 ;
2016-04-22 03:06:26 +00:00
//! \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
2015-11-05 06:59:46 +00:00
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 " ) ; }
2016-04-22 03:06:26 +00:00
//! \brief Flag indicating random access
//! \returns true if the cipher is seekable, false otherwise
//! \sa SeekToIteration()
2015-11-05 06:59:46 +00:00
virtual bool CipherIsRandomAccess ( ) const = 0 ;
2016-04-22 03:06:26 +00:00
//! \brief Seeks to a random position in the stream
//! \sa CipherIsRandomAccess()
2015-11-05 06:59:46 +00:00
virtual void SeekToIteration ( lword iterationCount )
2016-09-16 15:27:15 +00:00
{ CRYPTOPP_UNUSED ( iterationCount ) ; CRYPTOPP_ASSERT ( ! CipherIsRandomAccess ( ) ) ; throw NotImplemented ( " StreamTransformation: this object doesn't support random access " ) ; }
2015-11-05 06:59:46 +00:00
} ;
2016-04-22 03:06:26 +00:00
//! \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
2015-11-05 06:59:46 +00:00
template < typename WT , unsigned int W , unsigned int X = 1 , class BASE = AdditiveCipherAbstractPolicy >
struct CRYPTOPP_NO_VTABLE AdditiveCipherConcretePolicy : public BASE
{
typedef WT WordType ;
CRYPTOPP_CONSTANT ( BYTES_PER_ITERATION = sizeof ( WordType ) * W )
# if !(CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X64)
2016-04-22 03:06:26 +00:00
//! \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.
2015-11-05 06:59:46 +00:00
unsigned int GetAlignment ( ) const { return GetAlignmentOf < WordType > ( ) ; }
# endif
2016-04-22 03:06:26 +00:00
//! \brief Provides number of bytes operated upon during an iteration
//! \returns bytes operated upon during an iteration, in bytes
//! \sa GetOptimalBlockSize()
2015-11-05 06:59:46 +00:00
unsigned int GetBytesPerIteration ( ) const { return BYTES_PER_ITERATION ; }
2016-04-22 03:06:26 +00:00
//! \brief Provides buffer size based on iterations
//! \returns the buffer size based on iterations, in bytes
2015-11-05 06:59:46 +00:00
unsigned int GetIterationsToBuffer ( ) const { return X ; }
2016-04-22 03:06:26 +00:00
//! \brief Flag indicating
//! \returns true if the stream can be generated independent of the transformation input, false otherwise
//! \sa CanOperateKeystream(), OperateKeystream(), WriteKeystream()
2015-11-05 06:59:46 +00:00
bool CanOperateKeystream ( ) const { return true ; }
2016-04-22 03:06:26 +00:00
//! \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()
2015-11-05 06:59:46 +00:00
virtual void OperateKeystream ( KeystreamOperation operation , byte * output , const byte * input , size_t iterationCount ) = 0 ;
} ;
2016-04-22 03:06:26 +00:00
//! \brief Helper macro to implement OperateKeystream
2015-11-05 06:59:46 +00:00
# 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 ) ) ) ;
2016-04-22 03:06:26 +00:00
//! \brief Helper macro to implement OperateKeystream
2015-11-05 06:59:46 +00:00
# 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 ) ; }
2016-04-22 03:06:26 +00:00
//! \brief Helper macro to implement OperateKeystream
2015-11-05 06:59:46 +00:00
# define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y) \
switch ( operation ) \
{ \
case WRITE_KEYSTREAM : \
x ( WRITE_KEYSTREAM ) \
break ; \
case XOR_KEYSTREAM : \
x ( XOR_KEYSTREAM ) \
input + = y ; \
break ; \
case XOR_KEYSTREAM_INPUT_ALIGNED : \
x ( XOR_KEYSTREAM_INPUT_ALIGNED ) \
input + = y ; \
break ; \
case XOR_KEYSTREAM_OUTPUT_ALIGNED : \
x ( XOR_KEYSTREAM_OUTPUT_ALIGNED ) \
input + = y ; \
break ; \
case WRITE_KEYSTREAM_ALIGNED : \
x ( WRITE_KEYSTREAM_ALIGNED ) \
break ; \
case XOR_KEYSTREAM_BOTH_ALIGNED : \
x ( XOR_KEYSTREAM_BOTH_ALIGNED ) \
input + = y ; \
break ; \
} \
output + = y ;
2016-04-22 03:06:26 +00:00
//! \class AdditiveCipherTemplate
//! \brief Base class for additive stream ciphers with SymmetricCipher interface
//! \tparam BASE AbstractPolicyHolder base class
2015-11-05 06:59:46 +00:00
template < class BASE = AbstractPolicyHolder < AdditiveCipherAbstractPolicy , SymmetricCipher > >
class CRYPTOPP_NO_VTABLE AdditiveCipherTemplate : public BASE , public RandomNumberGenerator
{
public :
2016-12-03 05:32:07 +00:00
virtual ~ AdditiveCipherTemplate ( ) { }
2016-04-22 03:06:26 +00:00
//! \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
2016-12-27 17:34:57 +00:00
//! the constraints of a particular generator.
2015-11-05 06:59:46 +00:00
void GenerateBlock ( byte * output , size_t size ) ;
2016-04-22 03:06:26 +00:00
//! \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>
2015-11-05 06:59:46 +00:00
void ProcessData ( byte * outString , const byte * inString , size_t length ) ;
2016-04-22 03:06:26 +00:00
//! \brief Resynchronize the cipher
//! \param iv a byte array used to resynchronize the cipher
//! \param length the size of the IV array
2015-11-05 06:59:46 +00:00
void Resynchronize ( const byte * iv , int length = - 1 ) ;
2016-04-22 03:06:26 +00:00
//! \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()
2015-11-05 06:59:46 +00:00
unsigned int OptimalBlockSize ( ) const { return this - > GetPolicy ( ) . GetOptimalBlockSize ( ) ; }
2016-04-22 03:06:26 +00:00
//! \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()
2015-11-05 06:59:46 +00:00
unsigned int GetOptimalNextBlockSize ( ) const { return ( unsigned int ) this - > m_leftOver ; }
2016-04-22 03:06:26 +00:00
//! \brief Provides number of ideal data alignment
//! \returns the ideal data alignment, in bytes
//! \sa GetAlignment() and OptimalBlockSize()
2015-11-05 06:59:46 +00:00
unsigned int OptimalDataAlignment ( ) const { return this - > GetPolicy ( ) . GetAlignment ( ) ; }
2016-04-22 03:06:26 +00:00
//! \brief Determines if the cipher is self inverting
//! \returns true if the stream cipher is self inverting, false otherwise
2015-11-05 06:59:46 +00:00
bool IsSelfInverting ( ) const { return true ; }
2016-04-22 03:06:26 +00:00
//! \brief Determines if the cipher is a forward transformation
//! \returns true if the stream cipher is a forward transformation, false otherwise
2015-11-05 06:59:46 +00:00
bool IsForwardTransformation ( ) const { return true ; }
2016-04-22 03:06:26 +00:00
//! \brief Flag indicating random access
//! \returns true if the cipher is seekable, false otherwise
//! \sa Seek()
2015-11-05 06:59:46 +00:00
bool IsRandomAccess ( ) const { return this - > GetPolicy ( ) . CipherIsRandomAccess ( ) ; }
2016-04-22 03:06:26 +00:00
//! \brief Seeks to a random position in the stream
//! \param position the absolute position in the stream
//! \sa IsRandomAccess()
2015-11-05 06:59:46 +00:00
void Seek ( lword position ) ;
typedef typename BASE : : PolicyInterface PolicyInterface ;
protected :
void UncheckedSetKey ( const byte * key , unsigned int length , const NameValuePairs & params ) ;
unsigned int GetBufferByteSize ( const PolicyInterface & policy ) const { return policy . GetBytesPerIteration ( ) * policy . GetIterationsToBuffer ( ) ; }
inline byte * KeystreamBufferBegin ( ) { return this - > m_buffer . data ( ) ; }
inline byte * KeystreamBufferEnd ( ) { return ( this - > m_buffer . data ( ) + this - > m_buffer . size ( ) ) ; }
SecByteBlock m_buffer ;
size_t m_leftOver ;
} ;
2016-04-22 03:06:26 +00:00
//! \class CFB_CipherAbstractPolicy
//! \brief Policy object for feeback based stream ciphers
2015-11-05 06:59:46 +00:00
class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CFB_CipherAbstractPolicy
{
public :
virtual ~ CFB_CipherAbstractPolicy ( ) { }
2016-04-22 03:06:26 +00:00
//! \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.
2015-11-05 06:59:46 +00:00
virtual unsigned int GetAlignment ( ) const = 0 ;
2016-04-22 03:06:26 +00:00
//! \brief Provides number of bytes operated upon during an iteration
//! \returns bytes operated upon during an iteration, in bytes
//! \sa GetOptimalBlockSize()
2015-11-05 06:59:46 +00:00
virtual unsigned int GetBytesPerIteration ( ) const = 0 ;
2016-04-22 03:06:26 +00:00
//! \brief Access the feedback register
//! \returns pointer to the first byte of the feedback register
2015-11-05 06:59:46 +00:00
virtual byte * GetRegisterBegin ( ) = 0 ;
2016-04-22 03:06:26 +00:00
//! \brief TODO
2015-11-05 06:59:46 +00:00
virtual void TransformRegister ( ) = 0 ;
2016-04-22 03:06:26 +00:00
//! \brief Flag indicating iteration support
//! \returns true if the cipher supports iteration, false otherwise
2015-11-05 06:59:46 +00:00
virtual bool CanIterate ( ) const { return false ; }
2016-04-22 03:06:26 +00:00
//! \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()
2015-11-05 06:59:46 +00:00
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 ) ;
2016-09-16 15:27:15 +00:00
CRYPTOPP_ASSERT ( false ) ; /*throw 0;*/ throw Exception ( Exception : : OTHER_ERROR , " SimpleKeyingInterface: unexpected error " ) ; }
2016-04-22 03:06:26 +00:00
//! \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
2015-11-05 06:59:46 +00:00
virtual void CipherSetKey ( const NameValuePairs & params , const byte * key , size_t length ) = 0 ;
2016-04-22 03:06:26 +00:00
//! \brief Resynchronize the cipher
//! \param iv a byte array used to resynchronize the cipher
//! \param length the size of the IV array
2015-11-05 06:59:46 +00:00
virtual void CipherResynchronize ( const byte * iv , size_t length )
{ CRYPTOPP_UNUSED ( iv ) ; CRYPTOPP_UNUSED ( length ) ; throw NotImplemented ( " SimpleKeyingInterface: this object doesn't support resynchronization " ) ; }
} ;
2016-04-22 03:06:26 +00:00
//! \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
2015-11-05 06:59:46 +00:00
template < typename WT , unsigned int W , class BASE = CFB_CipherAbstractPolicy >
struct CRYPTOPP_NO_VTABLE CFB_CipherConcretePolicy : public BASE
{
typedef WT WordType ;
2016-04-22 03:06:26 +00:00
//! \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.
2015-11-05 06:59:46 +00:00
unsigned int GetAlignment ( ) const { return sizeof ( WordType ) ; }
2016-04-22 03:06:26 +00:00
//! \brief Provides number of bytes operated upon during an iteration
//! \returns bytes operated upon during an iteration, in bytes
//! \sa GetOptimalBlockSize()
2015-11-05 06:59:46 +00:00
unsigned int GetBytesPerIteration ( ) const { return sizeof ( WordType ) * W ; }
2016-04-22 03:06:26 +00:00
//! \brief Flag indicating iteration support
//! \returns true if the cipher supports iteration, false otherwise
2015-11-05 06:59:46 +00:00
bool CanIterate ( ) const { return true ; }
2016-04-22 03:06:26 +00:00
//! \brief Perform one iteration in the forward direction
2017-03-01 11:10:06 +00:00
void TransformRegister ( ) { this - > Iterate ( NULLPTR , NULLPTR , ENCRYPTION , 1 ) ; }
2015-11-05 06:59:46 +00:00
2017-07-27 23:15:21 +00:00
//! \brief Provides alternate access to a feedback register
2016-12-27 17:34:57 +00:00
//! \tparam B enumeration indicating endianness
2016-04-22 03:06:26 +00:00
//! \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.
2015-11-05 06:59:46 +00:00
template < class B >
struct RegisterOutput
{
RegisterOutput ( byte * output , const byte * input , CipherDir dir )
: m_output ( output ) , m_input ( input ) , m_dir ( dir ) { }
2016-04-22 03:06:26 +00:00
//! \brief XOR feedback register with data
//! \param registerWord data represented as a word type
//! \returns reference to the next feedback register word
2015-11-05 06:59:46 +00:00
inline RegisterOutput & operator ( ) ( WordType & registerWord )
{
2016-09-16 15:27:15 +00:00
CRYPTOPP_ASSERT ( IsAligned < WordType > ( m_output ) ) ;
CRYPTOPP_ASSERT ( IsAligned < WordType > ( m_input ) ) ;
2015-11-05 06:59:46 +00:00
if ( ! NativeByteOrderIs ( B : : ToEnum ( ) ) )
registerWord = ByteReverse ( registerWord ) ;
if ( m_dir = = ENCRYPTION )
{
2017-03-01 11:10:06 +00:00
if ( m_input = = NULLPTR )
2016-09-16 15:27:15 +00:00
{
2017-03-01 11:10:06 +00:00
CRYPTOPP_ASSERT ( m_output = = NULLPTR ) ;
2016-09-16 15:27:15 +00:00
}
2015-11-05 06:59:46 +00:00
else
{
WordType ct = * ( const WordType * ) m_input ^ registerWord ;
registerWord = ct ;
* ( WordType * ) m_output = ct ;
m_input + = sizeof ( WordType ) ;
m_output + = sizeof ( WordType ) ;
}
}
else
{
WordType ct = * ( const WordType * ) m_input ;
* ( WordType * ) m_output = registerWord ^ ct ;
registerWord = ct ;
m_input + = sizeof ( WordType ) ;
m_output + = sizeof ( WordType ) ;
}
// registerWord is left unreversed so it can be xor-ed with further input
return * this ;
}
byte * m_output ;
const byte * m_input ;
CipherDir m_dir ;
} ;
} ;
2016-04-22 04:03:03 +00:00
//! \class CFB_CipherTemplate
//! \brief Base class for feedback based stream ciphers with SymmetricCipher interface
2016-04-22 03:06:26 +00:00
//! \tparam BASE AbstractPolicyHolder base class
2015-11-05 06:59:46 +00:00
template < class BASE >
class CRYPTOPP_NO_VTABLE CFB_CipherTemplate : public BASE
{
public :
2016-04-22 03:06:26 +00:00
//! \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>
2015-11-05 06:59:46 +00:00
void ProcessData ( byte * outString , const byte * inString , size_t length ) ;
2016-04-22 03:06:26 +00:00
//! \brief Resynchronize the cipher
//! \param iv a byte array used to resynchronize the cipher
//! \param length the size of the IV array
2015-11-05 06:59:46 +00:00
void Resynchronize ( const byte * iv , int length = - 1 ) ;
2016-04-22 03:06:26 +00:00
//! \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()
2015-11-05 06:59:46 +00:00
unsigned int OptimalBlockSize ( ) const { return this - > GetPolicy ( ) . GetBytesPerIteration ( ) ; }
2016-04-22 03:06:26 +00:00
//! \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()
2015-11-05 06:59:46 +00:00
unsigned int GetOptimalNextBlockSize ( ) const { return ( unsigned int ) m_leftOver ; }
2016-04-22 03:06:26 +00:00
//! \brief Provides number of ideal data alignment
//! \returns the ideal data alignment, in bytes
//! \sa GetAlignment() and OptimalBlockSize()
2015-11-05 06:59:46 +00:00
unsigned int OptimalDataAlignment ( ) const { return this - > GetPolicy ( ) . GetAlignment ( ) ; }
2016-04-22 03:06:26 +00:00
//! \brief Flag indicating random access
//! \returns true if the cipher is seekable, false otherwise
//! \sa Seek()
2015-11-05 06:59:46 +00:00
bool IsRandomAccess ( ) const { return false ; }
2016-04-22 03:06:26 +00:00
//! \brief Determines if the cipher is self inverting
//! \returns true if the stream cipher is self inverting, false otherwise
2015-11-05 06:59:46 +00:00
bool IsSelfInverting ( ) const { return false ; }
typedef typename BASE : : PolicyInterface PolicyInterface ;
protected :
virtual void CombineMessageAndShiftRegister ( byte * output , byte * reg , const byte * message , size_t length ) = 0 ;
void UncheckedSetKey ( const byte * key , unsigned int length , const NameValuePairs & params ) ;
size_t m_leftOver ;
} ;
2016-04-22 03:06:26 +00:00
//! \class CFB_EncryptionTemplate
//! \brief Base class for feedback based stream ciphers in the forward direction with SymmetricCipher interface
//! \tparam BASE AbstractPolicyHolder base class
2015-11-05 06:59:46 +00:00
template < class BASE = AbstractPolicyHolder < CFB_CipherAbstractPolicy , SymmetricCipher > >
class CRYPTOPP_NO_VTABLE CFB_EncryptionTemplate : public CFB_CipherTemplate < BASE >
{
bool IsForwardTransformation ( ) const { return true ; }
void CombineMessageAndShiftRegister ( byte * output , byte * reg , const byte * message , size_t length ) ;
} ;
2016-04-22 03:06:26 +00:00
//! \class CFB_DecryptionTemplate
//! \brief Base class for feedback based stream ciphers in the reverse direction with SymmetricCipher interface
//! \tparam BASE AbstractPolicyHolder base class
2015-11-05 06:59:46 +00:00
template < class BASE = AbstractPolicyHolder < CFB_CipherAbstractPolicy , SymmetricCipher > >
class CRYPTOPP_NO_VTABLE CFB_DecryptionTemplate : public CFB_CipherTemplate < BASE >
{
bool IsForwardTransformation ( ) const { return false ; }
void CombineMessageAndShiftRegister ( byte * output , byte * reg , const byte * message , size_t length ) ;
} ;
2016-04-22 03:06:26 +00:00
//! \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
2015-11-05 06:59:46 +00:00
template < class BASE >
class CFB_RequireFullDataBlocks : public BASE
{
public :
unsigned int MandatoryBlockSize ( ) const { return this - > OptimalBlockSize ( ) ; }
} ;
2016-04-22 03:06:26 +00:00
//! \class SymmetricCipherFinal
2016-09-10 08:57:48 +00:00
//! \brief SymmetricCipher implementation
2016-04-22 03:06:26 +00:00
//! \tparam BASE AbstractPolicyHolder derived base class
//! \tparam INFO AbstractPolicyHolder derived information class
//! \sa Weak::ARC4, ChaCha8, ChaCha12, ChaCha20, Salsa20, SEAL, Sosemanuk, WAKE
2015-11-05 06:59:46 +00:00
template < class BASE , class INFO = BASE >
class SymmetricCipherFinal : public AlgorithmImpl < SimpleKeyingInterfaceImpl < BASE , INFO > , INFO >
{
public :
2016-12-03 05:32:07 +00:00
virtual ~ SymmetricCipherFinal ( ) { }
2016-04-22 03:06:26 +00:00
//! \brief Construct a stream cipher
2015-11-05 06:59:46 +00:00
SymmetricCipherFinal ( ) { }
2016-04-22 03:06:26 +00:00
//! \brief Construct a stream cipher
//! \param key a byte array used to key the cipher
//! \details This overload uses DEFAULT_KEYLENGTH
2015-11-05 06:59:46 +00:00
SymmetricCipherFinal ( const byte * key )
{ this - > SetKey ( key , this - > DEFAULT_KEYLENGTH ) ; }
2016-04-22 03:06:26 +00:00
//! \brief Construct a stream cipher
//! \param key a byte array used to key the cipher
//! \param length the size of the key array
2015-11-05 06:59:46 +00:00
SymmetricCipherFinal ( const byte * key , size_t length )
{ this - > SetKey ( key , length ) ; }
2016-04-22 03:06:26 +00:00
//! \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
2015-11-05 06:59:46 +00:00
SymmetricCipherFinal ( const byte * key , size_t length , const byte * iv )
{ this - > SetKeyWithIV ( key , length , iv ) ; }
2016-04-22 03:06:26 +00:00
//! \brief Clone a SymmetricCipher
//! \returns a new SymmetricCipher based on this object
2015-11-05 06:59:46 +00:00
Clonable * Clone ( ) const { return static_cast < SymmetricCipher * > ( new SymmetricCipherFinal < BASE , INFO > ( * this ) ) ; }
} ;
NAMESPACE_END
# ifdef CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
# include "strciphr.cpp"
# endif
NAMESPACE_BEGIN ( CryptoPP )
CRYPTOPP_DLL_TEMPLATE_CLASS AbstractPolicyHolder < AdditiveCipherAbstractPolicy , SymmetricCipher > ;
CRYPTOPP_DLL_TEMPLATE_CLASS AdditiveCipherTemplate < AbstractPolicyHolder < AdditiveCipherAbstractPolicy , SymmetricCipher > > ;
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_CipherTemplate < AbstractPolicyHolder < CFB_CipherAbstractPolicy , SymmetricCipher > > ;
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_EncryptionTemplate < AbstractPolicyHolder < CFB_CipherAbstractPolicy , SymmetricCipher > > ;
CRYPTOPP_DLL_TEMPLATE_CLASS CFB_DecryptionTemplate < AbstractPolicyHolder < CFB_CipherAbstractPolicy , SymmetricCipher > > ;
NAMESPACE_END
# if CRYPTOPP_MSC_VERSION
# pragma warning(pop)
# endif
# endif