- Main Page
- Namespaces
- Classes
- Files

# authenc.cpp

    00001 // authenc.cpp - written and placed in the public domain by Wei Dai
    00002
    00003 #include "pch.h"
    00004
    00005 #ifndef CRYPTOPP_IMPORTS
    00006
    00007 #include "authenc.h"
    00008
    00009 NAMESPACE_BEGIN(CryptoPP)
    00010
    00011 void AuthenticatedSymmetricCipherBase::AuthenticateData(const byte *input, size_t len)
    00012 {
    00013         unsigned int blockSize = AuthenticationBlockSize();
    00014         unsigned int &num = m_bufferedDataLength;
    00015         byte* data = m_buffer.begin();
    00016
    00017         if (num != 0)   // process left over data
    00018         {
    00019                 if (num+len >= blockSize)
    00020                 {
    00021                         memcpy(data+num, input, blockSize-num);
    00022                         AuthenticateBlocks(data, blockSize);
    00023                         input += (blockSize-num);
    00024                         len -= (blockSize-num);
    00025                         num = 0;
    00026                         // drop through and do the rest
    00027                 }
    00028                 else
    00029                 {
    00030                         memcpy(data+num, input, len);
    00031                         num += (unsigned int)len;
    00032                         return;
    00033                 }
    00034         }
    00035
    00036         // now process the input data in blocks of blockSize bytes and save the leftovers to m_data
    00037         if (len >= blockSize)
    00038         {
    00039                 size_t leftOver = AuthenticateBlocks(input, len);
    00040                 input += (len - leftOver);
    00041                 len = leftOver;
    00042         }
    00043
    00044         memcpy(data, input, len);
    00045         num = (unsigned int)len;
    00046 }
    00047
    00048 void AuthenticatedSymmetricCipherBase::SetKey(const byte *userKey, size_t keylength, const NameValuePairs &params)
    00049 {
    00050         m_bufferedDataLength = 0;
    00051         m_state = State_Start;
    00052
    00053         SetKeyWithoutResync(userKey, keylength, params);
    00054         m_state = State_KeySet;
    00055
    00056         size_t length;
    00057         const byte *iv = GetIVAndThrowIfInvalid(params, length);
    00058         if (iv)
    00059                 Resynchronize(iv, (int)length);
    00060 }
    00061
    00062 void AuthenticatedSymmetricCipherBase::Resynchronize(const byte *iv, int length)
    00063 {
    00064         if (m_state < State_KeySet)
    00065                 throw BadState(AlgorithmName(), "Resynchronize", "key is set");
    00066
    00067         m_bufferedDataLength = 0;
    00068         m_totalHeaderLength = m_totalMessageLength = m_totalFooterLength = 0;
    00069         m_state = State_KeySet;
    00070
    00071         Resync(iv, this->ThrowIfInvalidIVLength(length));
    00072         m_state = State_IVSet;
    00073 }
    00074
    00075 void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length)
    00076 {
    00077         if (length == 0)
    00078                 return;
    00079
    00080         switch (m_state)
    00081         {
    00082         case State_Start:
    00083         case State_KeySet:
    00084                 throw BadState(AlgorithmName(), "Update", "setting key and IV");
    00085         case State_IVSet:
    00086                 AuthenticateData(input, length);
    00087                 m_totalHeaderLength += length;
    00088                 break;
    00089         case State_AuthUntransformed:
    00090         case State_AuthTransformed:
    00091                 AuthenticateLastConfidentialBlock();
    00092                 m_bufferedDataLength = 0;
    00093                 m_state = State_AuthFooter;
    00094                 // fall through
    00095         case State_AuthFooter:
    00096                 AuthenticateData(input, length);
    00097                 m_totalFooterLength += length;
    00098                 break;
    00099         default:
    00100                 assert(false);
    00101         }
    00102 }
    00103
    00104 void AuthenticatedSymmetricCipherBase::ProcessData(byte *outString, const byte *inString, size_t length)
    00105 {
    00106         m_totalMessageLength += length;
    00107         if (m_state >= State_IVSet && m_totalMessageLength > MaxMessageLength())
    00108                 throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum");
    00109
    00110 reswitch:
    00111         switch (m_state)
    00112         {
    00113         case State_Start:
    00114         case State_KeySet:
    00115                 throw BadState(AlgorithmName(), "ProcessData", "setting key and IV");
    00116         case State_AuthFooter:
    00117                 throw BadState(AlgorithmName(), "ProcessData was called after footer input has started");
    00118         case State_IVSet:
    00119                 AuthenticateLastHeaderBlock();
    00120                 m_bufferedDataLength = 0;
    00121                 m_state = AuthenticationIsOnPlaintext()==IsForwardTransformation() ? State_AuthUntransformed : State_AuthTransformed;
    00122                 goto reswitch;
    00123         case State_AuthUntransformed:
    00124                 AuthenticateData(inString, length);
    00125                 AccessSymmetricCipher().ProcessData(outString, inString, length);
    00126                 break;
    00127         case State_AuthTransformed:
    00128                 AccessSymmetricCipher().ProcessData(outString, inString, length);
    00129                 AuthenticateData(outString, length);
    00130                 break;
    00131         default:
    00132                 assert(false);
    00133         }
    00134 }
    00135
    00136 void AuthenticatedSymmetricCipherBase::TruncatedFinal(byte *mac, size_t macSize)
    00137 {
    00138         if (m_totalHeaderLength > MaxHeaderLength())
    00139                 throw InvalidArgument(AlgorithmName() + ": header length of " + IntToString(m_totalHeaderLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
    00140
    00141         if (m_totalFooterLength > MaxFooterLength())
    00142         {
    00143                 if (MaxFooterLength() == 0)
    00144                         throw InvalidArgument(AlgorithmName() + ": additional authenticated data (AAD) cannot be input after data to be encrypted or decrypted");
    00145                 else
    00146                         throw InvalidArgument(AlgorithmName() + ": footer length of " + IntToString(m_totalFooterLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
    00147         }
    00148
    00149         switch (m_state)
    00150         {
    00151         case State_Start:
    00152         case State_KeySet:
    00153                 throw BadState(AlgorithmName(), "TruncatedFinal", "setting key and IV");
    00154
    00155         case State_IVSet:
    00156                 AuthenticateLastHeaderBlock();
    00157                 m_bufferedDataLength = 0;
    00158                 // fall through
    00159
    00160         case State_AuthUntransformed:
    00161         case State_AuthTransformed:
    00162                 AuthenticateLastConfidentialBlock();
    00163                 m_bufferedDataLength = 0;
    00164                 // fall through
    00165
    00166         case State_AuthFooter:
    00167                 AuthenticateLastFooterBlock(mac, macSize);
    00168                 m_bufferedDataLength = 0;
    00169                 break;
    00170
    00171         default:
    00172                 assert(false);
    00173         }
    00174
    00175         m_state = State_KeySet;
    00176 }
    00177
    00178 NAMESPACE_END
    00179
    00180 #endif