2013-07-29 12:13:03 +01:00
// authenc.cpp - written and placed in the public domain by Wei Dai
#include "pch.h"
#ifndef CRYPTOPP_IMPORTS
#include "authenc.h"
NAMESPACE_BEGIN ( CryptoPP )
void AuthenticatedSymmetricCipherBase :: AuthenticateData ( const byte * input , size_t len )
{
unsigned int blockSize = AuthenticationBlockSize ();
unsigned int & num = m_bufferedDataLength ;
byte * data = m_buffer . begin ();
if ( num != 0 ) // process left over data
{
if ( num + len >= blockSize )
{
memcpy ( data + num , input , blockSize - num );
AuthenticateBlocks ( data , blockSize );
input += ( blockSize - num );
len -= ( blockSize - num );
num = 0 ;
// drop through and do the rest
}
else
{
memcpy ( data + num , input , len );
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 )
{
size_t leftOver = AuthenticateBlocks ( input , len );
input += ( len - leftOver );
len = leftOver ;
}
memcpy ( data , input , len );
num = ( unsigned int ) len ;
}
void AuthenticatedSymmetricCipherBase :: SetKey ( const byte * userKey , size_t keylength , const NameValuePairs & params )
{
m_bufferedDataLength = 0 ;
m_state = State_Start ;
SetKeyWithoutResync ( userKey , keylength , params );
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 )
throw BadState ( AlgorithmName (), "Resynchronize" , "key is set" );
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 )
{
if ( length == 0 )
return ;
switch ( m_state )
{
case State_Start :
case State_KeySet :
throw BadState ( AlgorithmName (), "Update" , "setting key and IV" );
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 :
assert ( false );
}
}
void AuthenticatedSymmetricCipherBase :: ProcessData ( byte * outString , const byte * inString , size_t length )
{
m_totalMessageLength += length ;
if ( m_state >= State_IVSet && m_totalMessageLength > MaxMessageLength ())
throw InvalidArgument ( AlgorithmName () + ": message length exceeds maximum" );
reswitch :
switch ( m_state )
{
case State_Start :
case State_KeySet :
throw BadState ( AlgorithmName (), "ProcessData" , "setting key and IV" );
case State_AuthFooter :
throw BadState ( AlgorithmName (), "ProcessData was called after footer input has started" );
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 :
assert ( false );
}
}
void AuthenticatedSymmetricCipherBase :: TruncatedFinal ( byte * mac , size_t macSize )
{
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 )
throw InvalidArgument ( AlgorithmName () + ": additional authenticated data (AAD) cannot be input after data to be encrypted or decrypted" );
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 :
throw BadState ( AlgorithmName (), "TruncatedFinal" , "setting key and IV" );
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 :
assert ( false );
}
m_state = State_KeySet ;
}
NAMESPACE_END
#endif