2017-01-27 12:05:45 +00:00
// authenc.cpp - originally written and placed in the public domain by Wei Dai
2009-03-02 02:39:17 +00:00
# include "pch.h"
# ifndef CRYPTOPP_IMPORTS
# include "authenc.h"
NAMESPACE_BEGIN ( CryptoPP )
void AuthenticatedSymmetricCipherBase : : AuthenticateData ( const byte * input , size_t len )
{
2019-01-30 12:28:08 +00:00
// UBsan finding with -std=c++03 using memcpy
CRYPTOPP_ASSERT ( input & & len ) ;
if ( ! input | | ! len ) return ;
2009-03-02 02:39:17 +00:00
unsigned int blockSize = AuthenticationBlockSize ( ) ;
unsigned int & num = m_bufferedDataLength ;
byte * data = m_buffer . begin ( ) ;
2019-01-30 15:00:09 +00:00
if ( data & & num ) // process left over data
2009-03-02 02:39:17 +00:00
{
if ( num + len > = blockSize )
{
2023-04-15 20:45:02 +00:00
std : : memcpy ( data + num , input , blockSize - num ) ;
2009-03-02 02:39:17 +00:00
AuthenticateBlocks ( data , blockSize ) ;
input + = ( blockSize - num ) ;
len - = ( blockSize - num ) ;
num = 0 ;
// drop through and do the rest
}
else
{
2023-04-15 20:45:02 +00:00
std : : memcpy ( data + num , input , len ) ;
2009-03-02 02:39:17 +00:00
num + = ( unsigned int ) len ;
return ;
}
}
// now process the input data in blocks of blockSize bytes and save the leftovers to m_data
if ( len > = blockSize )
{
2017-09-05 20:28:00 +00:00
size_t leftOver = AuthenticateBlocks ( input , len ) ;
2009-03-02 02:39:17 +00:00
input + = ( len - leftOver ) ;
len = leftOver ;
}
2019-01-30 15:00:09 +00:00
if ( data & & len )
2023-04-15 20:45:02 +00:00
std : : memcpy ( data , input , len ) ;
2009-03-02 02:39:17 +00:00
num = ( unsigned int ) len ;
}
void AuthenticatedSymmetricCipherBase : : SetKey ( const byte * userKey , size_t keylength , const NameValuePairs & params )
{
m_bufferedDataLength = 0 ;
m_state = State_Start ;
2017-08-17 16:33:43 +00:00
this - > SetKeyWithoutResync ( userKey , keylength , params ) ;
2009-03-02 02:39:17 +00:00
m_state = State_KeySet ;
size_t length ;
const byte * iv = GetIVAndThrowIfInvalid ( params , length ) ;
if ( iv )
Resynchronize ( iv , ( int ) length ) ;
}
void AuthenticatedSymmetricCipherBase : : Resynchronize ( const byte * iv , int length )
{
if ( m_state < State_KeySet )
2009-03-13 02:03:27 +00:00
throw BadState ( AlgorithmName ( ) , " Resynchronize " , " key is set " ) ;
2009-03-02 02:39:17 +00:00
m_bufferedDataLength = 0 ;
m_totalHeaderLength = m_totalMessageLength = m_totalFooterLength = 0 ;
m_state = State_KeySet ;
Resync ( iv , this - > ThrowIfInvalidIVLength ( length ) ) ;
m_state = State_IVSet ;
}
void AuthenticatedSymmetricCipherBase : : Update ( const byte * input , size_t length )
{
2019-01-30 15:45:12 +00:00
// Part of original authenc.cpp code. Don't remove it.
2017-09-30 10:19:28 +00:00
if ( length = = 0 ) { return ; }
2009-03-02 02:39:17 +00:00
switch ( m_state )
{
case State_Start :
case State_KeySet :
2009-03-13 02:03:27 +00:00
throw BadState ( AlgorithmName ( ) , " Update " , " setting key and IV " ) ;
2009-03-02 02:39:17 +00:00
case State_IVSet :
AuthenticateData ( input , length ) ;
m_totalHeaderLength + = length ;
break ;
case State_AuthUntransformed :
case State_AuthTransformed :
AuthenticateLastConfidentialBlock ( ) ;
m_bufferedDataLength = 0 ;
m_state = State_AuthFooter ;
// fall through
case State_AuthFooter :
AuthenticateData ( input , length ) ;
m_totalFooterLength + = length ;
break ;
default :
2016-09-16 15:27:15 +00:00
CRYPTOPP_ASSERT ( false ) ;
2009-03-02 02:39:17 +00:00
}
}
void AuthenticatedSymmetricCipherBase : : ProcessData ( byte * outString , const byte * inString , size_t length )
{
2019-01-30 15:45:12 +00:00
if ( m_state > = State_IVSet & & length > MaxMessageLength ( ) - m_totalMessageLength )
2009-03-02 02:39:17 +00:00
throw InvalidArgument ( AlgorithmName ( ) + " : message length exceeds maximum " ) ;
2019-01-30 15:45:12 +00:00
m_totalMessageLength + = length ;
2009-03-02 02:39:17 +00:00
reswitch :
switch ( m_state )
{
case State_Start :
case State_KeySet :
2009-03-13 02:03:27 +00:00
throw BadState ( AlgorithmName ( ) , " ProcessData " , " setting key and IV " ) ;
2009-03-02 02:39:17 +00:00
case State_AuthFooter :
2009-03-13 02:03:27 +00:00
throw BadState ( AlgorithmName ( ) , " ProcessData was called after footer input has started " ) ;
2009-03-02 02:39:17 +00:00
case State_IVSet :
AuthenticateLastHeaderBlock ( ) ;
m_bufferedDataLength = 0 ;
m_state = AuthenticationIsOnPlaintext ( ) = = IsForwardTransformation ( ) ? State_AuthUntransformed : State_AuthTransformed ;
goto reswitch ;
case State_AuthUntransformed :
AuthenticateData ( inString , length ) ;
AccessSymmetricCipher ( ) . ProcessData ( outString , inString , length ) ;
break ;
case State_AuthTransformed :
AccessSymmetricCipher ( ) . ProcessData ( outString , inString , length ) ;
AuthenticateData ( outString , length ) ;
break ;
default :
2016-09-16 15:27:15 +00:00
CRYPTOPP_ASSERT ( false ) ;
2009-03-02 02:39:17 +00:00
}
}
void AuthenticatedSymmetricCipherBase : : TruncatedFinal ( byte * mac , size_t macSize )
{
2020-07-07 05:15:06 +00:00
// https://github.com/weidai11/cryptopp/issues/954
this - > ThrowIfInvalidTruncatedSize ( macSize ) ;
2009-03-02 02:39:17 +00:00
if ( m_totalHeaderLength > MaxHeaderLength ( ) )
throw InvalidArgument ( AlgorithmName ( ) + " : header length of " + IntToString ( m_totalHeaderLength ) + " exceeds the maximum of " + IntToString ( MaxHeaderLength ( ) ) ) ;
if ( m_totalFooterLength > MaxFooterLength ( ) )
{
if ( MaxFooterLength ( ) = = 0 )
2009-03-13 02:03:27 +00:00
throw InvalidArgument ( AlgorithmName ( ) + " : additional authenticated data (AAD) cannot be input after data to be encrypted or decrypted " ) ;
2009-03-02 02:39:17 +00:00
else
throw InvalidArgument ( AlgorithmName ( ) + " : footer length of " + IntToString ( m_totalFooterLength ) + " exceeds the maximum of " + IntToString ( MaxFooterLength ( ) ) ) ;
}
switch ( m_state )
{
case State_Start :
case State_KeySet :
2009-03-13 02:03:27 +00:00
throw BadState ( AlgorithmName ( ) , " TruncatedFinal " , " setting key and IV " ) ;
2009-03-02 02:39:17 +00:00
case State_IVSet :
AuthenticateLastHeaderBlock ( ) ;
m_bufferedDataLength = 0 ;
// fall through
case State_AuthUntransformed :
case State_AuthTransformed :
AuthenticateLastConfidentialBlock ( ) ;
m_bufferedDataLength = 0 ;
// fall through
case State_AuthFooter :
AuthenticateLastFooterBlock ( mac , macSize ) ;
m_bufferedDataLength = 0 ;
break ;
default :
2016-09-16 15:27:15 +00:00
CRYPTOPP_ASSERT ( false ) ;
2009-03-02 02:39:17 +00:00
}
m_state = State_KeySet ;
}
NAMESPACE_END
# endif