Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/cryptopp/chachapoly.cpp
2 views
1
// chachapoly.cpp - written and placed in the public domain by Jeffrey Walton
2
// RFC 8439, Section 2.8, AEAD Construction, http://tools.ietf.org/html/rfc8439
3
4
#include "pch.h"
5
#include "chachapoly.h"
6
#include "algparam.h"
7
#include "misc.h"
8
9
#if CRYPTOPP_MSC_VERSION
10
# pragma warning(disable: 4244)
11
#endif
12
13
NAMESPACE_BEGIN(CryptoPP)
14
15
////////////////////////////// IETF ChaChaTLS //////////////////////////////
16
17
// RekeyCipherAndMac is heavier-weight than we like. The Authenc framework was
18
// predicated on BlockCiphers, where the key and key schedule could be
19
// calculated independent of the IV being used. However, the ChaCha and
20
// ChaCha20Poly1305 construction combines key setup and IV. That is, both are
21
// needed to key or rekey the cipher. Even a simple Resync() requires us to
22
// regenerate the initial state for both ChaCha20 and Poly1305.
23
void ChaCha20Poly1305_Base::RekeyCipherAndMac(const byte *userKey, size_t keylength, const NameValuePairs &params)
24
{
25
// Derive MAC key
26
AlgorithmParameters block0 = MakeParameters("InitialBlock", (word64)0, true);
27
AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block0));
28
29
// Only the first 256-bits are used to key the MAC
30
SecByteBlock derived(NULLPTR, 32);
31
AccessSymmetricCipher().ProcessString(derived, derived.size());
32
33
// Key the Poly1305 MAC
34
AccessMAC().SetKey(derived, derived.size(), params);
35
36
// Key the ChaCha20 cipher
37
AlgorithmParameters block1 = MakeParameters("InitialBlock", (word64)1, true);
38
AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block1));
39
}
40
41
void ChaCha20Poly1305_Base::SetKeyWithoutResync(const byte *userKey, size_t userKeyLength, const NameValuePairs &params)
42
{
43
CRYPTOPP_ASSERT(userKey && userKeyLength == 32);
44
m_userKey.Assign(userKey, userKeyLength);
45
46
// ChaCha/Poly1305 initial state depends on both the key and IV. The
47
// IV may or may not be present during the call to SetKeyWithoutResync.
48
// If the IV is present, the framework will call SetKeyWithoutResync
49
// followed by Resynchronize which calls Resync. In this case we defer
50
// calculating the initial state until the call to Resynchronize.
51
// If the IV is not present, it avoids calling ChaCha's SetKey without
52
// an IV, which results in an exception. In this case the user will need
53
// to call Resynchronize to key ChaCha and Poly1305.
54
// RekeyCipherAndMac(userKey, userKeyLength, params);
55
CRYPTOPP_UNUSED(params);
56
}
57
58
void ChaCha20Poly1305_Base::Resync(const byte *iv, size_t len)
59
{
60
CRYPTOPP_ASSERT(iv && len == 12);
61
RekeyCipherAndMac(m_userKey, m_userKey.SizeInBytes(),
62
MakeParameters(Name::IV(), ConstByteArrayParameter(iv,len)));
63
}
64
65
size_t ChaCha20Poly1305_Base::AuthenticateBlocks(const byte *data, size_t len)
66
{
67
AccessMAC().Update(data, len);
68
return 0;
69
}
70
71
void ChaCha20Poly1305_Base::AuthenticateLastHeaderBlock()
72
{
73
// Pad to a multiple of 16 or 0
74
const byte zero[16] = {0};
75
size_t pad = (16U - (m_totalHeaderLength % 16)) % 16;
76
AccessMAC().Update(zero, pad);
77
}
78
79
void ChaCha20Poly1305_Base::AuthenticateLastConfidentialBlock()
80
{
81
// Pad to a multiple of 16 or 0
82
const byte zero[16] = {0};
83
size_t pad = (16U - (m_totalMessageLength % 16)) % 16;
84
AccessMAC().Update(zero, pad);
85
}
86
87
void ChaCha20Poly1305_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
88
{
89
CRYPTOPP_ALIGN_DATA(8) byte length[2*sizeof(word64)];
90
PutWord(true, LITTLE_ENDIAN_ORDER, length+0, m_totalHeaderLength);
91
PutWord(true, LITTLE_ENDIAN_ORDER, length+8, m_totalMessageLength);
92
AccessMAC().Update(length, sizeof(length));
93
AccessMAC().TruncatedFinal(mac, macSize);
94
m_state = State_KeySet;
95
}
96
97
void ChaCha20Poly1305_Base::EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *message, size_t messageLength)
98
{
99
Resynchronize(iv, ivLength);
100
Update(aad, aadLength);
101
ProcessString(ciphertext, message, messageLength);
102
TruncatedFinal(mac, macSize);
103
}
104
105
bool ChaCha20Poly1305_Base::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength)
106
{
107
Resynchronize(iv, ivLength);
108
Update(aad, aadLength);
109
ProcessString(message, ciphertext, ciphertextLength);
110
return TruncatedVerify(mac, macLength);
111
}
112
113
////////////////////////////// IETF XChaCha20 draft //////////////////////////////
114
115
// RekeyCipherAndMac is heavier-weight than we like. The Authenc framework was
116
// predicated on BlockCiphers, where the key and key schedule could be
117
// calculated independent of the IV being used. However, the ChaCha and
118
// ChaCha20Poly1305 construction combines key setup and IV. That is, both are
119
// needed to key or rekey the cipher. Even a simple Resync() requires us to
120
// regenerate the initial state for both ChaCha20 and Poly1305.
121
void XChaCha20Poly1305_Base::RekeyCipherAndMac(const byte *userKey, size_t keylength, const NameValuePairs &params)
122
{
123
// Derive MAC key
124
AlgorithmParameters block0 = MakeParameters("InitialBlock", (word64)0, true);
125
AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block0));
126
127
// Only the first 256-bits are used to key the MAC
128
SecByteBlock derived(NULLPTR, 32);
129
AccessSymmetricCipher().ProcessString(derived, derived.size());
130
131
// Key the Poly1305 MAC
132
AccessMAC().SetKey(derived, derived.size(), params);
133
134
// Key the ChaCha20 cipher
135
AlgorithmParameters block1 = MakeParameters("InitialBlock", (word64)1, true);
136
AccessSymmetricCipher().SetKey(userKey, keylength, CombinedNameValuePairs(params, block1));
137
}
138
139
void XChaCha20Poly1305_Base::SetKeyWithoutResync(const byte *userKey, size_t userKeyLength, const NameValuePairs &params)
140
{
141
CRYPTOPP_ASSERT(userKey && userKeyLength == 32);
142
m_userKey.Assign(userKey, userKeyLength);
143
144
// XChaCha20/Poly1305 initial state depends on both the key and IV. The
145
// IV may or may not be present during the call to SetKeyWithoutResync.
146
// If the IV is present, the framework will call SetKeyWithoutResync
147
// followed by Resynchronize which calls Resync. In this case we defer
148
// calculating the initial state until the call to Resynchronize.
149
// If the IV is not present, it avoids calling ChaCha's SetKey without
150
// an IV, which results in an exception. In this case the user will need
151
// to call Resynchronize to key ChaCha and Poly1305.
152
// RekeyCipherAndMac(userKey, userKeyLength, params);
153
CRYPTOPP_UNUSED(params);
154
}
155
156
void XChaCha20Poly1305_Base::Resync(const byte *iv, size_t len)
157
{
158
CRYPTOPP_ASSERT(iv && len == 24);
159
RekeyCipherAndMac(m_userKey, m_userKey.SizeInBytes(),
160
MakeParameters(Name::IV(), ConstByteArrayParameter(iv,len)));
161
}
162
163
size_t XChaCha20Poly1305_Base::AuthenticateBlocks(const byte *data, size_t len)
164
{
165
AccessMAC().Update(data, len);
166
return 0;
167
}
168
169
void XChaCha20Poly1305_Base::AuthenticateLastHeaderBlock()
170
{
171
// Pad to a multiple of 16 or 0
172
const byte zero[16] = {0};
173
size_t pad = (16 - (m_totalHeaderLength % 16)) % 16;
174
AccessMAC().Update(zero, pad);
175
}
176
177
void XChaCha20Poly1305_Base::AuthenticateLastConfidentialBlock()
178
{
179
// Pad to a multiple of 16 or 0
180
const byte zero[16] = {0};
181
size_t pad = (16 - (m_totalMessageLength % 16)) % 16;
182
AccessMAC().Update(zero, pad);
183
}
184
185
void XChaCha20Poly1305_Base::AuthenticateLastFooterBlock(byte *mac, size_t macSize)
186
{
187
CRYPTOPP_ALIGN_DATA(8) byte length[2*sizeof(word64)];
188
PutWord(true, LITTLE_ENDIAN_ORDER, length+0, m_totalHeaderLength);
189
PutWord(true, LITTLE_ENDIAN_ORDER, length+8, m_totalMessageLength);
190
AccessMAC().Update(length, sizeof(length));
191
AccessMAC().TruncatedFinal(mac, macSize);
192
m_state = State_KeySet;
193
}
194
195
void XChaCha20Poly1305_Base::EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *message, size_t messageLength)
196
{
197
Resynchronize(iv, ivLength);
198
Update(aad, aadLength);
199
ProcessString(ciphertext, message, messageLength);
200
TruncatedFinal(mac, macSize);
201
}
202
203
bool XChaCha20Poly1305_Base::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength)
204
{
205
Resynchronize(iv, ivLength);
206
Update(aad, aadLength);
207
ProcessString(message, ciphertext, ciphertextLength);
208
return TruncatedVerify(mac, macLength);
209
}
210
211
NAMESPACE_END
212
213