Crypto++
|
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 ¶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 // 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