Crypto++  8.8
Free C++ class library of cryptographic schemes
authenc.cpp
1 // authenc.cpp - originally 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 
9 NAMESPACE_BEGIN(CryptoPP)
10 
11 void AuthenticatedSymmetricCipherBase::AuthenticateData(const byte *input, size_t len)
12 {
13  // UBsan finding with -std=c++03 using memcpy
14  CRYPTOPP_ASSERT(input && len);
15  if(!input || !len) return;
16 
17  unsigned int blockSize = AuthenticationBlockSize();
18  unsigned int &num = m_bufferedDataLength;
19  byte* data = m_buffer.begin();
20 
21  if (data && num) // process left over data
22  {
23  if (num+len >= blockSize)
24  {
25  std::memcpy(data+num, input, blockSize-num);
26  AuthenticateBlocks(data, blockSize);
27  input += (blockSize-num);
28  len -= (blockSize-num);
29  num = 0;
30  // drop through and do the rest
31  }
32  else
33  {
34  std::memcpy(data+num, input, len);
35  num += (unsigned int)len;
36  return;
37  }
38  }
39 
40  // now process the input data in blocks of blockSize bytes and save the leftovers to m_data
41  if (len >= blockSize)
42  {
43  size_t leftOver = AuthenticateBlocks(input, len);
44  input += (len - leftOver);
45  len = leftOver;
46  }
47 
48  if (data && len)
49  std::memcpy(data, input, len);
50  num = (unsigned int)len;
51 }
52 
53 void AuthenticatedSymmetricCipherBase::SetKey(const byte *userKey, size_t keylength, const NameValuePairs &params)
54 {
55  m_bufferedDataLength = 0;
56  m_state = State_Start;
57 
58  this->SetKeyWithoutResync(userKey, keylength, params);
59  m_state = State_KeySet;
60 
61  size_t length;
62  const byte *iv = GetIVAndThrowIfInvalid(params, length);
63  if (iv)
64  Resynchronize(iv, (int)length);
65 }
66 
67 void AuthenticatedSymmetricCipherBase::Resynchronize(const byte *iv, int length)
68 {
69  if (m_state < State_KeySet)
70  throw BadState(AlgorithmName(), "Resynchronize", "key is set");
71 
72  m_bufferedDataLength = 0;
73  m_totalHeaderLength = m_totalMessageLength = m_totalFooterLength = 0;
74  m_state = State_KeySet;
75 
76  Resync(iv, this->ThrowIfInvalidIVLength(length));
77  m_state = State_IVSet;
78 }
79 
80 void AuthenticatedSymmetricCipherBase::Update(const byte *input, size_t length)
81 {
82  // Part of original authenc.cpp code. Don't remove it.
83  if (length == 0) {return;}
84 
85  switch (m_state)
86  {
87  case State_Start:
88  case State_KeySet:
89  throw BadState(AlgorithmName(), "Update", "setting key and IV");
90  case State_IVSet:
91  AuthenticateData(input, length);
92  m_totalHeaderLength += length;
93  break;
94  case State_AuthUntransformed:
95  case State_AuthTransformed:
96  AuthenticateLastConfidentialBlock();
97  m_bufferedDataLength = 0;
98  m_state = State_AuthFooter;
99  // fall through
100  case State_AuthFooter:
101  AuthenticateData(input, length);
102  m_totalFooterLength += length;
103  break;
104  default:
105  CRYPTOPP_ASSERT(false);
106  }
107 }
108 
109 void AuthenticatedSymmetricCipherBase::ProcessData(byte *outString, const byte *inString, size_t length)
110 {
111  if (m_state >= State_IVSet && length > MaxMessageLength()-m_totalMessageLength)
112  throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum");
113  m_totalMessageLength += length;
114 
115 reswitch:
116  switch (m_state)
117  {
118  case State_Start:
119  case State_KeySet:
120  throw BadState(AlgorithmName(), "ProcessData", "setting key and IV");
121  case State_AuthFooter:
122  throw BadState(AlgorithmName(), "ProcessData was called after footer input has started");
123  case State_IVSet:
124  AuthenticateLastHeaderBlock();
125  m_bufferedDataLength = 0;
126  m_state = AuthenticationIsOnPlaintext()==IsForwardTransformation() ? State_AuthUntransformed : State_AuthTransformed;
127  goto reswitch;
128  case State_AuthUntransformed:
129  AuthenticateData(inString, length);
130  AccessSymmetricCipher().ProcessData(outString, inString, length);
131  break;
132  case State_AuthTransformed:
133  AccessSymmetricCipher().ProcessData(outString, inString, length);
134  AuthenticateData(outString, length);
135  break;
136  default:
137  CRYPTOPP_ASSERT(false);
138  }
139 }
140 
141 void AuthenticatedSymmetricCipherBase::TruncatedFinal(byte *mac, size_t macSize)
142 {
143  // https://github.com/weidai11/cryptopp/issues/954
144  this->ThrowIfInvalidTruncatedSize(macSize);
145 
146  if (m_totalHeaderLength > MaxHeaderLength())
147  throw InvalidArgument(AlgorithmName() + ": header length of " + IntToString(m_totalHeaderLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
148 
149  if (m_totalFooterLength > MaxFooterLength())
150  {
151  if (MaxFooterLength() == 0)
152  throw InvalidArgument(AlgorithmName() + ": additional authenticated data (AAD) cannot be input after data to be encrypted or decrypted");
153  else
154  throw InvalidArgument(AlgorithmName() + ": footer length of " + IntToString(m_totalFooterLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
155  }
156 
157  switch (m_state)
158  {
159  case State_Start:
160  case State_KeySet:
161  throw BadState(AlgorithmName(), "TruncatedFinal", "setting key and IV");
162 
163  case State_IVSet:
164  AuthenticateLastHeaderBlock();
165  m_bufferedDataLength = 0;
166  // fall through
167 
168  case State_AuthUntransformed:
169  case State_AuthTransformed:
170  AuthenticateLastConfidentialBlock();
171  m_bufferedDataLength = 0;
172  // fall through
173 
174  case State_AuthFooter:
175  AuthenticateLastFooterBlock(mac, macSize);
176  m_bufferedDataLength = 0;
177  break;
178 
179  default:
180  CRYPTOPP_ASSERT(false);
181  }
182 
183  m_state = State_KeySet;
184 }
185 
186 NAMESPACE_END
187 
188 #endif
Classes for authenticated encryption modes of operation.
void Resynchronize(const byte *iv, int length=-1)
Resynchronize with an IV.
void ProcessData(byte *outString, const byte *inString, size_t length)
Encrypt or decrypt an array of bytes.
void Update(const byte *input, size_t length)
Updates a hash with additional input.
void TruncatedFinal(byte *mac, size_t macSize)
Computes the hash of the current message.
void SetKey(const byte *userKey, size_t keylength, const NameValuePairs &params)
Sets or reset the key of this object.
virtual lword MaxHeaderLength() const =0
Provides the maximum length of AAD that can be input.
virtual lword MaxFooterLength() const
Provides the maximum length of AAD.
Definition: cryptlib.h:1350
virtual lword MaxMessageLength() const =0
Provides the maximum length of encrypted data.
virtual std::string AlgorithmName() const
Provides the name of this algorithm.
An invalid argument was detected.
Definition: cryptlib.h:208
Interface for retrieving values given their names.
Definition: cryptlib.h:327
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition: secblock.h:836
virtual void ProcessData(byte *outString, const byte *inString, size_t length)=0
Encrypt or decrypt an array of bytes.
virtual bool IsForwardTransformation() const =0
Determines if the cipher is being operated in its forward direction.
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:929
Crypto++ library namespace.
Precompiled header file.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68