mirror of
https://github.com/shadps4-emu/ext-cryptopp.git
synced 2025-02-02 11:13:35 +00:00
Update StreamTransformation and ProcessLastBlock
Some authenticated encryption modes have needs that are not expressed well with MandatoryBlockSize() and MinLastBlockSize(). When IsLastBlockSpecial() returns true three things happen. First, standard block cipher padding is not applied. Second, the ProcessLastBlock() is used that provides inString and outString lengths. Third, outString is larger than inString by 2*MandatoryBlockSize(). That is, there's a reserve available when processing the last block. The return value of ProcessLastBlock() indicates how many bytes were written to outString. A filter driving data will send outString and returned length to an AttachedTransformation() for additional processing.
This commit is contained in:
parent
bebdc8b917
commit
e92eb31690
17
cryptlib.cpp
17
cryptlib.cpp
@ -213,6 +213,7 @@ unsigned int HashTransformation::OptimalDataAlignment() const
|
||||
return GetAlignmentOf<word32>();
|
||||
}
|
||||
|
||||
#if 0
|
||||
void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
|
||||
{
|
||||
CRYPTOPP_ASSERT(MinLastBlockSize() == 0); // this function should be overridden otherwise
|
||||
@ -222,6 +223,22 @@ void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inStrin
|
||||
else if (length != 0)
|
||||
throw NotImplemented(AlgorithmName() + ": this object doesn't support a special last block");
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t StreamTransformation::ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength)
|
||||
{
|
||||
// this function should be overridden otherwise
|
||||
CRYPTOPP_ASSERT(MinLastBlockSize() == 0);
|
||||
|
||||
if (inLength == MandatoryBlockSize())
|
||||
{
|
||||
ProcessData(outString, inString, inLength);
|
||||
return inLength;
|
||||
}
|
||||
else if (inLength != 0)
|
||||
throw NotImplemented(AlgorithmName() + ": this object doesn't support a special last block");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AuthenticatedSymmetricCipher::SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
|
||||
{
|
||||
|
27
cryptlib.h
27
cryptlib.h
@ -871,11 +871,16 @@ public:
|
||||
|
||||
//! \brief Encrypt or decrypt the last block of data
|
||||
//! \param outString the output byte buffer
|
||||
//! \param outLength the size of the output byte buffer, in bytes
|
||||
//! \param inString the input byte buffer
|
||||
//! \param length the size of the input and output byte buffers, in bytes
|
||||
//! ProcessLastBlock is used when the last block of data is special.
|
||||
//! Currently the only use of this function is CBC-CTS mode.
|
||||
virtual void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
|
||||
//! \param inLength the size of the input byte buffer, in bytes
|
||||
//! \returns the number of bytes used in outString
|
||||
//! ProcessLastBlock is used when the last block of data is special and the
|
||||
//! cipher text may expand larger than input data length. The current implementation provides
|
||||
//! an output buffer with a size <tt>inLength+2*MandatoryBlockSize()</tt>. This member function
|
||||
//! is used by CBC-CTS and OCB modes.
|
||||
//! \sa 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
|
||||
@ -883,6 +888,20 @@ public:
|
||||
//! block is not special.
|
||||
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(). When IsLastBlockSpecial() returns
|
||||
//! true three things happen. First, standard block cipher padding is not applied.
|
||||
//! Second, the ProcessLastBlock() is used that provides inString and outString lengths.
|
||||
//! Third, outString is larger than inString by <tt>2*MandatoryBlockSize()</tt>. That is,
|
||||
//! there's a reserve available when processing the last block.
|
||||
//! \details The return value of ProcessLastBlock() indicates how many bytes were written
|
||||
//! to outString. A filter driving data will send <tt>outString</tt> and <tt>outLength</tt>
|
||||
//! to an <tt>AttachedTransformation()</tt> for additional processing.
|
||||
//! \sa ProcessLastBlock
|
||||
virtual bool IsLastBlockSpecial() const {return false;}
|
||||
|
||||
//! \brief Encrypt or decrypt a string of bytes
|
||||
//! \param inoutString the string to process
|
||||
//! \param length the size of the inoutString, in bytes
|
||||
|
22
filters.cpp
22
filters.cpp
@ -687,6 +687,15 @@ void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
|
||||
{
|
||||
byte *space = NULLPTR;
|
||||
|
||||
if (m_cipher.IsLastBlockSpecial())
|
||||
{
|
||||
size_t reserve = 2*m_cipher.MandatoryBlockSize();
|
||||
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, length+reserve);
|
||||
length = m_cipher.ProcessLastBlock(space, length+reserve, inString, length);
|
||||
AttachedTransformation()->Put(space, length);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (m_padding)
|
||||
{
|
||||
case NO_PADDING:
|
||||
@ -694,17 +703,18 @@ void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
|
||||
if (length > 0)
|
||||
{
|
||||
size_t minLastBlockSize = m_cipher.MinLastBlockSize();
|
||||
size_t reserve = 2*m_cipher.MandatoryBlockSize();
|
||||
bool isForwardTransformation = m_cipher.IsForwardTransformation();
|
||||
|
||||
if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize))
|
||||
{
|
||||
// do padding
|
||||
size_t blockSize = STDMAX(minLastBlockSize, (size_t)m_cipher.MandatoryBlockSize());
|
||||
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize);
|
||||
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize+reserve);
|
||||
if (inString) {memcpy(space, inString, length);}
|
||||
memset(space + length, 0, blockSize - length);
|
||||
m_cipher.ProcessLastBlock(space, space, blockSize);
|
||||
AttachedTransformation()->Put(space, blockSize);
|
||||
size_t used = m_cipher.ProcessLastBlock(space, blockSize+reserve, space, blockSize);
|
||||
AttachedTransformation()->Put(space, used);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -716,9 +726,9 @@ void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
|
||||
throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
|
||||
}
|
||||
|
||||
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize);
|
||||
m_cipher.ProcessLastBlock(space, inString, length);
|
||||
AttachedTransformation()->Put(space, length);
|
||||
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize+reserve);
|
||||
size_t used = m_cipher.ProcessLastBlock(space, length+reserve, inString, length);
|
||||
AttachedTransformation()->Put(space, used);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
51
modes.cpp
51
modes.cpp
@ -174,8 +174,7 @@ void ECB_OneWay::ProcessData(byte *outString, const byte *inString, size_t lengt
|
||||
|
||||
void CBC_Encryption::ProcessData(byte *outString, const byte *inString, size_t length)
|
||||
{
|
||||
if (!length)
|
||||
return;
|
||||
if (!length) return;
|
||||
CRYPTOPP_ASSERT(length%BlockSize()==0);
|
||||
|
||||
unsigned int blockSize = BlockSize();
|
||||
@ -185,15 +184,17 @@ void CBC_Encryption::ProcessData(byte *outString, const byte *inString, size_t l
|
||||
memcpy(m_register, outString + length - blockSize, blockSize);
|
||||
}
|
||||
|
||||
void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
|
||||
size_t CBC_CTS_Encryption::ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength)
|
||||
{
|
||||
if (length <= BlockSize())
|
||||
CRYPTOPP_UNUSED(outLength);
|
||||
size_t used = inLength;
|
||||
if (inLength <= BlockSize())
|
||||
{
|
||||
if (!m_stolenIV)
|
||||
throw InvalidArgument("CBC_Encryption: message is too short for ciphertext stealing");
|
||||
|
||||
// steal from IV
|
||||
memcpy(outString, m_register, length);
|
||||
memcpy(outString, m_register, inLength);
|
||||
outString = m_stolenIV;
|
||||
}
|
||||
else
|
||||
@ -202,14 +203,16 @@ void CBC_CTS_Encryption::ProcessLastBlock(byte *outString, const byte *inString,
|
||||
xorbuf(m_register, inString, BlockSize());
|
||||
m_cipher->ProcessBlock(m_register);
|
||||
inString += BlockSize();
|
||||
length -= BlockSize();
|
||||
memcpy(outString+BlockSize(), m_register, length);
|
||||
inLength -= BlockSize();
|
||||
memcpy(outString+BlockSize(), m_register, inLength);
|
||||
}
|
||||
|
||||
// output last full ciphertext block
|
||||
xorbuf(m_register, inString, length);
|
||||
xorbuf(m_register, inString, inLength);
|
||||
m_cipher->ProcessBlock(m_register);
|
||||
memcpy(outString, m_register, BlockSize());
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
void CBC_Decryption::ResizeBuffers()
|
||||
@ -232,38 +235,44 @@ void CBC_Decryption::ProcessData(byte *outString, const byte *inString, size_t l
|
||||
m_register.swap(m_temp);
|
||||
}
|
||||
|
||||
void CBC_CTS_Decryption::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
|
||||
size_t CBC_CTS_Decryption::ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength)
|
||||
{
|
||||
const byte *pn, *pn1;
|
||||
bool stealIV = length <= BlockSize();
|
||||
CRYPTOPP_UNUSED(outLength);
|
||||
const byte *pn1, *pn2;
|
||||
bool stealIV = inLength <= BlockSize();
|
||||
size_t used = inLength;
|
||||
|
||||
if (stealIV)
|
||||
{
|
||||
pn = inString;
|
||||
pn1 = m_register;
|
||||
pn1 = inString;
|
||||
pn2 = m_register;
|
||||
}
|
||||
else
|
||||
{
|
||||
pn = inString + BlockSize();
|
||||
pn1 = inString;
|
||||
length -= BlockSize();
|
||||
pn1 = inString + BlockSize();
|
||||
pn2 = inString;
|
||||
inLength -= BlockSize();
|
||||
}
|
||||
|
||||
// decrypt last partial plaintext block
|
||||
memcpy(m_temp, pn1, BlockSize());
|
||||
memcpy(m_temp, pn2, BlockSize());
|
||||
m_cipher->ProcessBlock(m_temp);
|
||||
xorbuf(m_temp, pn, length);
|
||||
xorbuf(m_temp, pn1, inLength);
|
||||
|
||||
if (stealIV)
|
||||
memcpy(outString, m_temp, length);
|
||||
{
|
||||
memcpy(outString, m_temp, inLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(outString+BlockSize(), m_temp, length);
|
||||
memcpy(outString+BlockSize(), m_temp, inLength);
|
||||
// decrypt next to last plaintext block
|
||||
memcpy(m_temp, pn, length);
|
||||
memcpy(m_temp, pn1, inLength);
|
||||
m_cipher->ProcessBlock(m_temp);
|
||||
xorbuf(outString, m_temp, m_register, BlockSize());
|
||||
}
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
11
modes.h
11
modes.h
@ -255,7 +255,7 @@ public:
|
||||
|
||||
void SetStolenIV(byte *iv) {m_stolenIV = iv;}
|
||||
unsigned int MinLastBlockSize() const {return BlockSize()+1;}
|
||||
void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
|
||||
size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength);
|
||||
|
||||
protected:
|
||||
void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs ¶ms)
|
||||
@ -287,7 +287,7 @@ class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CBC_CTS_Decryption : public CBC_Decryption
|
||||
{
|
||||
public:
|
||||
unsigned int MinLastBlockSize() const {return BlockSize()+1;}
|
||||
void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
|
||||
size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength);
|
||||
};
|
||||
|
||||
//! \class CipherModeFinalTemplate_CipherHolder
|
||||
@ -476,13 +476,6 @@ struct CBC_CTS_Mode_ExternalCipher : public CipherModeDocumentation
|
||||
typedef CipherModeFinalTemplate_ExternalCipher<CBC_CTS_Decryption> Decryption;
|
||||
};
|
||||
|
||||
//#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
|
||||
//typedef CFB_Mode_ExternalCipher::Encryption CFBEncryption;
|
||||
//typedef CFB_Mode_ExternalCipher::Decryption CFBDecryption;
|
||||
//typedef OFB_Mode_ExternalCipher::Encryption OFB;
|
||||
//typedef CTR_Mode_ExternalCipher::Encryption CounterMode;
|
||||
//#endif
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
// Issue 340
|
||||
|
Loading…
x
Reference in New Issue
Block a user