Crypto++ 8.9 Free C++ class library of cryptographic schemes

chachapoly.cpp
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
algparam.h
Classes for working with NameValuePairs.
MakeParameters
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed=true)
Create an object that implements NameValuePairs.
Definition: algparam.h:508
chachapoly.h
IETF ChaCha20/Poly1305 AEAD scheme.
AlgorithmParameters
An object that implements NameValuePairs.
Definition: algparam.h:426
AuthenticatedSymmetricCipherBase::Resynchronize
void Resynchronize(const byte *iv, int length=-1)
Resynchronize with an IV.
AuthenticatedSymmetricCipherBase::Update
void Update(const byte *input, size_t length)
Updates a hash with additional input.
AuthenticatedSymmetricCipherBase::TruncatedFinal
void TruncatedFinal(byte *mac, size_t macSize)
Computes the hash of the current message.
ChaCha20Poly1305_Base
IETF ChaCha20Poly1305 cipher base implementation.
Definition: chachapoly.h:30
ChaCha20Poly1305_Base::EncryptAndAuthenticate
virtual void 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)
Encrypts and calculates a MAC in one call.
Definition: chachapoly.cpp:97
ChaCha20Poly1305_Base::DecryptAndVerify
virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength)
Decrypts and verifies a MAC in one call.
Definition: chachapoly.cpp:105
CombinedNameValuePairs
Combines two sets of NameValuePairs.
Definition: algparam.h:129
ConstByteArrayParameter
Used to pass byte array input as part of a NameValuePairs object.
Definition: algparam.h:25
HashTransformation::Update
virtual void Update(const byte *input, size_t length)=0
Updates a hash with additional input.
HashTransformation::TruncatedVerify
virtual bool TruncatedVerify(const byte *digest, size_t digestLength)
Verifies the hash of the current message.
NameValuePairs
Interface for retrieving values given their names.
Definition: cryptlib.h:327
SecBlock::SizeInBytes
size_type SizeInBytes() const
Provides the number of bytes in the SecBlock.
Definition: secblock.h:885
SecBlock::Assign
void Assign(const T *ptr, size_type len)
Set contents and size from an array.
Definition: secblock.h:898
SecByteBlock
SecBlock<byte> typedef.
Definition: secblock.h:1226
SimpleKeyingInterface::SetKey
virtual void SetKey(const byte *key, size_t length, const NameValuePairs &params=g_nullNameValuePairs)
Sets or reset the key of this object.
StreamTransformation::ProcessString
void ProcessString(byte *inoutString, size_t length)
Encrypt or decrypt a string of bytes.
Definition: cryptlib.h:1065
XChaCha20Poly1305_Base
IETF XChaCha20Poly1305 cipher base implementation.
Definition: chachapoly.h:178
XChaCha20Poly1305_Base::DecryptAndVerify
virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *aad, size_t aadLength, const byte *ciphertext, size_t ciphertextLength)
Decrypts and verifies a MAC in one call.
Definition: chachapoly.cpp:203
byte
unsigned char byte
8-bit unsigned datatype
Definition: config_int.h:66
word64
unsigned long long word64
64-bit unsigned datatype
Definition: config_int.h:101
LITTLE_ENDIAN_ORDER
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Definition: cryptlib.h:150
misc.h
Utility functions for the Crypto++ library.
PutWord
void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock=NULL)
Access a block of memory.
Definition: misc.h:2948
CryptoPP
Crypto++ library namespace.
Name::IV
const char * IV()
ConstByteArrayParameter, also accepts const byte * for backwards compatibility.
Definition: argnames.h:21
pch.h
Precompiled header file.
CRYPTOPP_ASSERT
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68