summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cryptlib.cpp4
-rw-r--r--modes.cpp6
-rw-r--r--modes.h9
-rw-r--r--seckey.h145
-rw-r--r--simple.h8
5 files changed, 163 insertions, 9 deletions
diff --git a/cryptlib.cpp b/cryptlib.cpp
index 19ea1c6a..8920d356 100644
--- a/cryptlib.cpp
+++ b/cryptlib.cpp
@@ -71,7 +71,7 @@ Algorithm::Algorithm(bool checkSelfTestStatus)
void SimpleKeyingInterface::SetKey(const byte *key, size_t length, const NameValuePairs &params)
{
this->ThrowIfInvalidKeyLength(length);
- this->UncheckedSetKey(key, (unsigned int)length, params);
+ this->UncheckedSetKey(key, static_cast<unsigned int>(length), params);
}
void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, size_t length, int rounds)
@@ -127,7 +127,7 @@ const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs
{
iv = ivWithLength.begin();
ThrowIfInvalidIV(iv);
- size = ThrowIfInvalidIVLength((int)ivWithLength.size());
+ size = ThrowIfInvalidIVLength(static_cast<int>(ivWithLength.size()));
return iv;
}
else if (params.GetValue(Name::IV(), iv))
diff --git a/modes.cpp b/modes.cpp
index 6b8e81ae..0d9849ce 100644
--- a/modes.cpp
+++ b/modes.cpp
@@ -67,7 +67,7 @@ void CFB_ModePolicy::TransformRegister()
void CFB_ModePolicy::CipherResynchronize(const byte *iv, size_t length)
{
CRYPTOPP_ASSERT(length == BlockSize());
- CopyOrZero(m_register, iv, length);
+ CopyOrZero(m_register, m_register.size(), iv, length);
TransformRegister();
}
@@ -99,7 +99,7 @@ void OFB_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv,
CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
CRYPTOPP_ASSERT(length == BlockSize());
- CopyOrZero(m_register, iv, length);
+ CopyOrZero(m_register, m_register.size(), iv, length);
}
void CTR_ModePolicy::SeekToIteration(lword iterationCount)
@@ -144,7 +144,7 @@ void CTR_ModePolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv,
CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
CRYPTOPP_ASSERT(length == BlockSize());
- CopyOrZero(m_register, iv, length);
+ CopyOrZero(m_register, m_register.size(), iv, length);
m_counterArray = m_register;
}
diff --git a/modes.h b/modes.h
index 78f2cd97..0955c3bd 100644
--- a/modes.h
+++ b/modes.h
@@ -130,12 +130,15 @@ protected:
unsigned int m_feedbackSize;
};
-inline void CopyOrZero(void *dest, const void *src, size_t s)
+inline void CopyOrZero(void *dest, size_t d, const void *src, size_t s)
{
+ CRYPTOPP_ASSERT(dest);
+ CRYPTOPP_ASSERT(d >= s);
+
if (src)
- memcpy_s(dest, s, src, s);
+ memcpy_s(dest, d, src, s);
else
- memset(dest, 0, s);
+ memset(dest, 0, d);
}
//! \class OFB_ModePolicy
diff --git a/seckey.h b/seckey.h
index 0cba30e3..c8bbfc90 100644
--- a/seckey.h
+++ b/seckey.h
@@ -111,10 +111,121 @@ protected:
{
int rounds = param.GetIntValueWithDefault("Rounds", DEFAULT_ROUNDS);
ThrowIfInvalidRounds(rounds, alg);
- return (unsigned int)rounds;
+ return static_cast<unsigned int>(rounds);
}
};
+//! \class VariableBlockSize
+//! \brief Inherited by algorithms with variable blocksize
+//! \tparam D Default blocksize
+//! \tparam N Minimum blocksize
+//! \tparam M Maximum blocksize
+template <unsigned int D, unsigned int N=1, unsigned int M=INT_MAX> // use INT_MAX here because enums are treated as signed ints
+class VariableBlockSize
+{
+public:
+ //! \brief The default blocksize for the algorithm provided as a constant.
+ CRYPTOPP_CONSTANT(BLOCKSIZE = D)
+ //! \brief The default blocksize for the algorithm provided as a constant.
+ CRYPTOPP_CONSTANT(DEFAULT_BLOCKSIZE = D)
+ //! \brief The minimum blocksize for the algorithm provided as a constant.
+ CRYPTOPP_CONSTANT(MIN_BLOCKSIZE = N)
+ //! \brief The maximum blocksize for the algorithm provided as a constant.
+ CRYPTOPP_CONSTANT(MAX_BLOCKSIZE = M)
+ //! \brief The default blocksize for the algorithm based on key length
+ //! provided by a static function.
+ //! \param keylength the size of the key, in bytes
+ //! \details keylength is unused in the default implementation.
+ CRYPTOPP_STATIC_CONSTEXPR unsigned int StaticGetDefaultBlockSize(size_t keylength)
+ {
+ return (keylength >= 64) ? 64 :
+ (keylength >= 32) ? 32 : 16;
+ }
+
+protected:
+ //! \brief Validates the blocksize for an algorithm.
+ //! \param blocksize the candidate blocksize
+ //! \param alg an Algorithm object used if the blocksize is invalid
+ //! \throws InvalidBlockSize if the blocksize is invalid
+ //! \details ThrowIfInvalidBlockSize() validates the blocksize and throws if invalid.
+ inline void ThrowIfInvalidBlockSize(int blocksize, const Algorithm *alg)
+ {
+ if (M == INT_MAX) // Coverity and result_independent_of_operands
+ {
+ if (blocksize < MIN_BLOCKSIZE)
+ throw InvalidBlockSize(alg ? alg->AlgorithmName() : std::string("VariableBlockSize"), blocksize);
+ }
+ else
+ {
+ if (blocksize < MIN_BLOCKSIZE || blocksize > MAX_BLOCKSIZE)
+ throw InvalidBlockSize(alg ? alg->AlgorithmName() : std::string("VariableBlockSize"), blocksize);
+ }
+ }
+
+ //! \brief Validates the blocksize for an algorithm
+ //! \param param the candidate blocksize
+ //! \param alg an Algorithm object used if the blocksize is invalid
+ //! \returns the blocksize for the algorithm
+ //! \throws InvalidBlockSize if the blocksize is invalid
+ //! \details GetBlockSizeAndThrowIfInvalid() validates the blocksize and throws if invalid.
+ inline unsigned int GetBlockSizeAndThrowIfInvalid(const NameValuePairs &param, const Algorithm *alg)
+ {
+ int keylength = param.GetIntValueWithDefault("KeySize", 0);
+ int blocksize = param.GetIntValueWithDefault("BlockSize", DEFAULT_BLOCKSIZE);
+ if (keylength > 0)
+ ThrowIfInvalidBlockSize(keylength, blocksize, alg);
+ else
+ ThrowIfInvalidBlockSize(blocksize, alg);
+ return static_cast<unsigned int>(blocksize);
+ }
+
+ //! Provides the block size of the cipher
+ //! \return the block size, in bytes
+ //! \details The sematics of BlockSize() is return DEFAULT_BLOCKSIZE if the default blocksize
+ //! is in effect. If the blocksize has changed, then the value returned is the BlockSize()
+ //! parameter used during SetKey().
+ //! \details DEFAULT_BLOCKSIZE should be paired with DEFAULT_KEYLENGTH, and it is the same as
+ //! BLOCKSIZE in a FixedBlockSize cipher.
+ virtual unsigned int BlockSize() const =0;
+
+ //! Provides the minimum block size of the cipher
+ //! \return the minimum block size, in bytes
+ //! \details MinBlockSize() returns the smallest blocksize a cipher can use. The size can
+ //! be affected by the key length. For example, Threefish has key sizes of 256, 512 and 1024 bits,
+ //! and the blocksize follows the key length. If a 512-bit key is used, then the block size is 512
+ //! bits. Once keyed, the minimum block size of 256 is not accurate, nor is a block size of 1024 bit.
+ virtual unsigned int MinBlockSize() const
+ { return MIN_BLOCKSIZE; }
+
+ //! Provides the maximum block size of the cipher
+ //! \return the maximum block size, in bytes
+ //! \details MaxBlockSize() returns the largest blocksize a cipher can use. The size can
+ //! be affected by the key length. For example, Threefish has key sizes of 256, 512 and 1024 bits,
+ //! and the blocksize follows the key length. If a 512-bit key is used, then the block size is 512
+ //! bits. Once keyed, the minimum block size of 256 is not accurate, nor is a block size of 1024 bit.
+ virtual unsigned int MaxBlockSize() const
+ { return MAX_BLOCKSIZE; }
+
+ //! Provides the initialization vector length of the cipher
+ //! \return the initialization vector length, in bytes
+ //! \details The sematics of IVSize() is return IV_LENGTH if the default blocksize is
+ //! in effect. If the blocksize has changed, then the default implentation returns the value of
+ //! the BlockSize() parameter used during SetKey().
+ //! \details Derived classes may override the behavior such that a different value is returned.
+ //! This may happen with a cipher that requires an IV that is twice the block size.
+ virtual unsigned int IVSize() const =0;
+
+ //! \brief Provides the minimum size of an IV
+ //! \return minimal length of IVs accepted by this cipher, in bytes
+ virtual unsigned int MinIVLength() const
+ { return MIN_BLOCKSIZE; }
+
+ //! \brief Provides the maximum size of an IV
+ //! \return maximal length of IVs accepted by this cipher, in bytes
+ virtual unsigned int MaxIVLength() const
+ { return MAX_BLOCKSIZE; }
+};
+
// ************** key length ***************
//! \class FixedKeyLength
@@ -316,6 +427,38 @@ public:
unsigned int BlockSize() const {return this->BLOCKSIZE;}
};
+//! \class VariableBlockCipherImpl
+//! \brief Provides a base implementation of Algorithm and SimpleKeyingInterface for block ciphers with varibale block sizes
+//! \tparam INFO a SimpleKeyingInterface derived class
+//! \tparam BASE a SimpleKeyingInterface derived class
+//! \details VariableBlockCipherImpl() provides a default implementation for block ciphers with varibale block sizes using AlgorithmImpl()
+//! and SimpleKeyingInterfaceImpl().
+//! \sa Algorithm(), SimpleKeyingInterface(), AlgorithmImpl(), SimpleKeyingInterfaceImpl()
+template <class INFO, class BASE = BlockCipher>
+class CRYPTOPP_NO_VTABLE VariableBlockCipherImpl : public AlgorithmImpl<SimpleKeyingInterfaceImpl<TwoBases<BASE, INFO> > >
+{
+public:
+ VariableBlockCipherImpl() : m_blocksize(0) {}
+ VariableBlockCipherImpl(unsigned int blocksize) : m_blocksize(blocksize) {}
+
+ //! Provides the block size of the algorithm
+ //! \returns the block size, in bytes
+ unsigned int BlockSize() const {
+ return m_blocksize ? m_blocksize : this->BLOCKSIZE;
+ }
+
+ //! Provides the initialization vector length of the algorithm
+ //! \returns the initialization vector length, in bytes
+ unsigned int IVSize() const {
+ if (!this->IsResynchronizable())
+ throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");
+ return m_blocksize ? m_blocksize : this->IV_LENGTH;
+ }
+
+protected:
+ unsigned int m_blocksize;
+};
+
//! \class BlockCipherFinal
//! \brief Provides class member functions to key a block cipher
//! \tparam DIR a CipherDir
diff --git a/simple.h b/simple.h
index 2b92d343..8be4d422 100644
--- a/simple.h
+++ b/simple.h
@@ -58,6 +58,14 @@ public:
explicit InvalidRounds(const std::string &algorithm, unsigned int rounds) : InvalidArgument(algorithm + ": " + IntToString(rounds) + " is not a valid number of rounds") {}
};
+//! \class InvalidBlockSize
+//! \brief Exception thrown when an invalid block size is encountered
+class CRYPTOPP_DLL InvalidBlockSize : public InvalidArgument
+{
+public:
+ explicit InvalidBlockSize(const std::string &algorithm, size_t length) : InvalidArgument(algorithm + ": " + IntToString(length) + " is not a valid block size") {}
+};
+
//! \class InvalidPersonalizationLength
//! \brief Exception thrown when an invalid personalization string length is encountered
class CRYPTOPP_DLL InvalidPersonalizationLength : public InvalidArgument