00001
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)
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
00027 }
00028 else
00029 {
00030 memcpy(data+num, input, len);
00031 num += (unsigned int)len;
00032 return;
00033 }
00034 }
00035
00036
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 ¶ms)
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
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
00159
00160 case State_AuthUntransformed:
00161 case State_AuthTransformed:
00162 AuthenticateLastConfidentialBlock();
00163 m_bufferedDataLength = 0;
00164
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