1// authenc.cpp - written and placed in the public domain by Wei Dai 2 3#include "pch.h" 4 5#ifndef CRYPTOPP_IMPORTS 6 7#include "authenc.h" 8 9NAMESPACE_BEGIN(CryptoPP) 10 11void AuthenticatedSymmetricCipherBase::AuthenticateData(const byte *input, size_t len) 12{ 13 unsigned int blockSize = AuthenticationBlockSize(); 14 unsigned int &num = m_bufferedDataLength; 15 byte* data = m_buffer.begin(); 16 17 if (num != 0) // process left over data 18 { 19 if (num+len >= blockSize) 20 { 21 memcpy(data+num, input, blockSize-num); 22 AuthenticateBlocks(data, blockSize); 23 input += (blockSize-num); 24 len -= (blockSize-num); 25 num = 0; 26 // drop through and do the rest 27 } 28 else 29 { 30 memcpy(data+num, input, len); 31 num += (unsigned int)len; 32 return; 33 } 34 } 35 36 // now process the input data in blocks of blockSize bytes and save the leftovers to m_data 37 if (len >= blockSize) 38 { 39 size_t leftOver = AuthenticateBlocks(input, len); 40 input += (len - leftOver); 41 len = leftOver; 42 } 43 44 memcpy(data, input, len); 45 num = (unsigned int)len; 46} 47 48void AuthenticatedSymmetricCipherBase::SetKey(const byte *userKey, size_t keylength, const NameValuePairs ¶ms) 49{ 50 m_bufferedDataLength = 0; 51 m_state = State_Start; 52 53 SetKeyWithoutResync(userKey, keylength, params); 54 m_state = State_KeySet; 55 56 size_t length; 57 const byte *iv = GetIVAndThrowIfInvalid(params, length); 58 if (iv) 59 Resynchronize(iv, (int)length); 60} 61 62void AuthenticatedSymmetricCipherBase::Resynchronize(const byte *iv, int length) 63{ 64 if (m_state < State_KeySet) 65 throw BadState(AlgorithmName(), "Resynchronize", "key is set"); 66 67 m_bufferedDataLength = 0; 68 m_totalHeaderLength = m_totalMessageLength = m_totalFooterLength = 0; 69 m_state = State_KeySet; 70 71 Resync(iv, this->ThrowIfInvalidIVLength(length)); 72 m_state = State_IVSet; 73} 74 75void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length) 76{ 77 if (length == 0) 78 return; 79 80 switch (m_state) 81 { 82 case State_Start: 83 case State_KeySet: 84 throw BadState(AlgorithmName(), "Update", "setting key and IV"); 85 case State_IVSet: 86 AuthenticateData(input, length); 87 m_totalHeaderLength += length; 88 break; 89 case State_AuthUntransformed: 90 case State_AuthTransformed: 91 AuthenticateLastConfidentialBlock(); 92 m_bufferedDataLength = 0; 93 m_state = State_AuthFooter; 94 // fall through 95 case State_AuthFooter: 96 AuthenticateData(input, length); 97 m_totalFooterLength += length; 98 break; 99 default: 100 assert(false); 101 } 102} 103 104void AuthenticatedSymmetricCipherBase::ProcessData(byte *outString, const byte *inString, size_t length) 105{ 106 m_totalMessageLength += length; 107 if (m_state >= State_IVSet && m_totalMessageLength > MaxMessageLength()) 108 throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum"); 109 110reswitch: 111 switch (m_state) 112 { 113 case State_Start: 114 case State_KeySet: 115 throw BadState(AlgorithmName(), "ProcessData", "setting key and IV"); 116 case State_AuthFooter: 117 throw BadState(AlgorithmName(), "ProcessData was called after footer input has started"); 118 case State_IVSet: 119 AuthenticateLastHeaderBlock(); 120 m_bufferedDataLength = 0; 121 m_state = AuthenticationIsOnPlaintext()==IsForwardTransformation() ? State_AuthUntransformed : State_AuthTransformed; 122 goto reswitch; 123 case State_AuthUntransformed: 124 AuthenticateData(inString, length); 125 AccessSymmetricCipher().ProcessData(outString, inString, length); 126 break; 127 case State_AuthTransformed: 128 AccessSymmetricCipher().ProcessData(outString, inString, length); 129 AuthenticateData(outString, length); 130 break; 131 default: 132 assert(false); 133 } 134} 135 136void AuthenticatedSymmetricCipherBase::TruncatedFinal(byte *mac, size_t macSize) 137{ 138 if (m_totalHeaderLength > MaxHeaderLength()) 139 throw InvalidArgument(AlgorithmName() + ": header length of " + IntToString(m_totalHeaderLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength())); 140 141 if (m_totalFooterLength > MaxFooterLength()) 142 { 143 if (MaxFooterLength() == 0) 144 throw InvalidArgument(AlgorithmName() + ": additional authenticated data (AAD) cannot be input after data to be encrypted or decrypted"); 145 else 146 throw InvalidArgument(AlgorithmName() + ": footer length of " + IntToString(m_totalFooterLength) + " exceeds the maximum of " + IntToString(MaxFooterLength())); 147 } 148 149 switch (m_state) 150 { 151 case State_Start: 152 case State_KeySet: 153 throw BadState(AlgorithmName(), "TruncatedFinal", "setting key and IV"); 154 155 case State_IVSet: 156 AuthenticateLastHeaderBlock(); 157 m_bufferedDataLength = 0; 158 // fall through 159 160 case State_AuthUntransformed: 161 case State_AuthTransformed: 162 AuthenticateLastConfidentialBlock(); 163 m_bufferedDataLength = 0; 164 // fall through 165 166 case State_AuthFooter: 167 AuthenticateLastFooterBlock(mac, macSize); 168 m_bufferedDataLength = 0; 169 break; 170 171 default: 172 assert(false); 173 } 174 175 m_state = State_KeySet; 176} 177 178NAMESPACE_END 179 180#endif 181