Crypto++ 8.7
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
9NAMESPACE_BEGIN(CryptoPP)
10
11void 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 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 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 memcpy(data, input, len);
50 num = (unsigned int)len;
51}
52
53void 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
67void 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
80void 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
109void 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
115reswitch:
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
141void 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
186NAMESPACE_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:1345
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:203
Interface for retrieving values given their names.
Definition: cryptlib.h:322
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:724
Crypto++ library namespace.
Precompiled header file.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68