summaryrefslogtreecommitdiffstats
path: root/CryptoPP/authenc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'CryptoPP/authenc.cpp')
-rw-r--r--CryptoPP/authenc.cpp180
1 files changed, 180 insertions, 0 deletions
diff --git a/CryptoPP/authenc.cpp b/CryptoPP/authenc.cpp
new file mode 100644
index 000000000..0ca5da60d
--- /dev/null
+++ b/CryptoPP/authenc.cpp
@@ -0,0 +1,180 @@
+// 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