diff --git a/cryptlib.cpp b/cryptlib.cpp index 41461c61..3de5c02b 100644 --- a/cryptlib.cpp +++ b/cryptlib.cpp @@ -232,8 +232,9 @@ size_t StreamTransformation::ProcessLastBlock(byte *outString, size_t outLength, if (inLength == MandatoryBlockSize()) { + outLength = inLength; // squash unused warning ProcessData(outString, inString, inLength); - return inLength; + return outLength; } else if (inLength != 0) throw NotImplemented(AlgorithmName() + ": this object doesn't support a special last block"); diff --git a/cryptlib.h b/cryptlib.h index c9336bb8..37be7fea 100644 --- a/cryptlib.h +++ b/cryptlib.h @@ -845,9 +845,17 @@ public: //! \brief Provides the mandatory block size of the cipher //! \return The block size of the cipher if input must be processed in blocks, 1 otherwise + //! \details Stream ciphers and some block ciphers modes of operation return 1. Modes that + //! return 1 must be able to process a single byte at a time, like counter mode. If a + //! mode of operation or block cipher cannot stream then it must not return 1. + //! \details When filters operate the mode or cipher, ProcessData will be called with a + //! string of bytes that is determined by MandatoryBlockSize and OptimalBlockSize. When a + //! policy is set, like 16-byte strings for a 16-byte block cipher, the filter will buffer + //! bytes until the specified number of bytes is available to the object. + //! \sa ProcessData, ProcessLastBlock, MandatoryBlockSize, MinLastBlockSize, BlockPaddingSchemeDef, IsLastBlockSpecial virtual unsigned int MandatoryBlockSize() const {return 1;} - //! \brief Provides the input block size most efficient for this cipher. + //! \brief Provides the input block size most efficient for this cipher //! \return The input block size that is most efficient for the cipher //! \details The base class implementation returns MandatoryBlockSize(). //! \note Optimal input length is @@ -858,7 +866,7 @@ public: //! \return the number of bytes used in the current block when processing at the optimal block size virtual unsigned int GetOptimalBlockSizeUsed() const {return 0;} - //! \brief Provides input and output data alignment for optimal performance. + //! \brief Provides input and output data alignment for optimal performance //! \return the input data alignment that provides optimal performance virtual unsigned int OptimalDataAlignment() const; @@ -866,7 +874,9 @@ public: //! \param outString the output byte buffer //! \param inString the input byte buffer //! \param length the size of the input and output byte buffers, in bytes - //! \details Either inString == outString, or they must not overlap. + //! \details ProcessData is called with a string of bytes whose size depends on MandatoryBlockSize. + //! Either inString == outString, or they must not overlap. + //! \sa ProcessData, ProcessLastBlock, MandatoryBlockSize, MinLastBlockSize, BlockPaddingSchemeDef, IsLastBlockSpecial virtual void ProcessData(byte *outString, const byte *inString, size_t length) =0; //! \brief Encrypt or decrypt the last block of data @@ -877,22 +887,33 @@ public: //! \returns the number of bytes used in outString //! \details ProcessLastBlock is used when the last block of data is special and requires handling //! by the cipher. The current implementation provides an output buffer with a size - //! inLength+2*MandatoryBlockSize(). The return value allows the cipher to expand cipher text - //! during encryption or shrink plain text during decryption. + //! inLength+2*MandatoryBlockSize(). The return value allows the cipher to expand cipher + //! text during encryption or shrink plain text during decryption. //! \details This member function is used by CBC-CTS and OCB modes. - //! \sa IsLastBlockSpecial + //! \sa ProcessData, ProcessLastBlock, MandatoryBlockSize, MinLastBlockSize, BlockPaddingSchemeDef, IsLastBlockSpecial virtual size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength); //! \brief Provides the size of the last block //! \returns the minimum size of the last block //! \details MinLastBlockSize() returns the minimum size of the last block. 0 indicates the last //! block is not special. + //! \details MandatoryBlockSize() enlists one of two behaviors. First, if MandatoryBlockSize() + //! returns 1, then the cipher can be streamed and ProcessData() is called with the tail bytes. + //! Second, if MandatoryBlockSize() returns non-0, then the string of bytes is padded to + //! MandatoryBlockSize() according to the padding mode. Then, ProcessData() is called with the + //! padded string of bytes. + //! \details Some authenticated encryption modes are not expressed well with MandatoryBlockSize() + //! and MinLastBlockSize(). For example, AES/OCB uses 16-byte blocks (MandatoryBlockSize = 16) + //! and the last block requires special processing (MinLastBlockSize = 0). However, 0 is a valid + //! last block size for OCB and the special processing is custom padding, and not standard PKCS + //! padding. In response an unambiguous IsLastBlockSpecial() was added. + //! \sa ProcessData, ProcessLastBlock, MandatoryBlockSize, MinLastBlockSize, BlockPaddingSchemeDef, IsLastBlockSpecial virtual unsigned int MinLastBlockSize() const {return 0;} //! \brief Determines if the last block receives special processing //! \returns true if the last block reveives special processing, false otherwise. - //! \details Some authenticated encryption modes have needs that are not expressed well - //! with MandatoryBlockSize() and MinLastBlockSize(). For example, AES/OCB uses + //! \details Some authenticated encryption modes are not expressed well with + //! MandatoryBlockSize() and MinLastBlockSize(). For example, AES/OCB uses //! 16-byte blocks (MandatoryBlockSize = 16) and the last block requires special processing //! (MinLastBlockSize = 0). However, 0 is a valid last block size for OCB and the special //! processing is custom padding, and not standard PKCS padding. In response an @@ -906,8 +927,8 @@ public: //! Fourth, the cipher is responsible for finalization like custom padding. The cipher will tell //! the library how many bytes were processed or used by returning the appropriate value from //! ProcessLastBlock(). - //! \details The return value of ProcessLastBlock() indicates how many bytes were written - //! to outString. A filter pipelining data will send outString and up to outLength + //! \details The return value of ProcessLastBlock() indicates how many bytes were written to + //! outString. A filter pipelining data will send outString and up to outLength //! to an AttachedTransformation() for additional processing. Below is an example of the code //! used in StreamTransformationFilter::LastPut. //!
  if (m_cipher.IsLastBlockSpecial())
@@ -918,7 +939,7 @@ public:
 	//!     AttachedTransformation()->Put(space, length);
 	//!     return;
 	//!   }
- //! \sa ProcessLastBlock + //! \sa ProcessData, ProcessLastBlock, MandatoryBlockSize, MinLastBlockSize, BlockPaddingSchemeDef, IsLastBlockSpecial //! \since Crypto++ 6.0 virtual bool IsLastBlockSpecial() const {return false;} diff --git a/modes.cpp b/modes.cpp index 5738b403..1dbc8fc3 100644 --- a/modes.cpp +++ b/modes.cpp @@ -177,7 +177,7 @@ void CBC_Encryption::ProcessData(byte *outString, const byte *inString, size_t l if (!length) return; CRYPTOPP_ASSERT(length%BlockSize()==0); - unsigned int blockSize = BlockSize(); + const unsigned int blockSize = BlockSize(); m_cipher->AdvancedProcessBlocks(inString, m_register, outString, blockSize, BlockTransformation::BT_XorInput); if (length > blockSize) m_cipher->AdvancedProcessBlocks(inString+blockSize, outString, outString+blockSize, length-blockSize, BlockTransformation::BT_XorInput); @@ -227,7 +227,7 @@ void CBC_Decryption::ProcessData(byte *outString, const byte *inString, size_t l return; CRYPTOPP_ASSERT(length%BlockSize()==0); - unsigned int blockSize = BlockSize(); + const unsigned int blockSize = BlockSize(); memcpy(m_temp, inString+length-blockSize, blockSize); // save copy now in case of in-place decryption if (length > blockSize) m_cipher->AdvancedProcessBlocks(inString+blockSize, inString, outString+blockSize, length-blockSize, BlockTransformation::BT_ReverseDirection|BlockTransformation::BT_AllowParallel);