1 // chachapoly.h - 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 /// \file chachapoly.h
5 /// \brief IETF ChaCha20/Poly1305 AEAD scheme
6 /// \details ChaCha20Poly1305 is an authenticated encryption scheme that combines
7 ///  ChaCha20TLS and Poly1305TLS. The scheme is defined in RFC 8439, section 2.8,
8 ///  AEAD_CHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha20
9 ///  and Poly1305.
10 /// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
11 ///  for IETF Protocols</A>.
12 /// \since Crypto++ 8.1
13 
14 #ifndef CRYPTOPP_CHACHA_POLY1305_H
15 #define CRYPTOPP_CHACHA_POLY1305_H
16 
17 #include "cryptlib.h"
18 #include "authenc.h"
19 #include "chacha.h"
20 #include "poly1305.h"
21 
NAMESPACE_BEGIN(CryptoPP)22 NAMESPACE_BEGIN(CryptoPP)
23 
24 ////////////////////////////// IETF ChaChaTLS //////////////////////////////
25 
26 /// \brief IETF ChaCha20Poly1305 cipher base implementation
27 /// \details Base implementation of the AuthenticatedSymmetricCipher interface
28 /// \since Crypto++ 8.1
29 class ChaCha20Poly1305_Base : public AuthenticatedSymmetricCipherBase
30 {
31 public:
32 	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName()
33 		{return "ChaCha20/Poly1305";}
34 
35 	virtual ~ChaCha20Poly1305_Base() {}
36 
37 	// AuthenticatedSymmetricCipher
38 	std::string AlgorithmName() const
39 		{return std::string("ChaCha20/Poly1305");}
40 	std::string AlgorithmProvider() const
41 		{return GetSymmetricCipher().AlgorithmProvider();}
42 	size_t MinKeyLength() const
43 		{return 32;}
44 	size_t MaxKeyLength() const
45 		{return 32;}
46 	size_t DefaultKeyLength() const
47 		{return 32;}
48 	size_t GetValidKeyLength(size_t n) const
49 		{CRYPTOPP_UNUSED(n); return 32;}
50 	bool IsValidKeyLength(size_t n) const
51 		{return n==32;}
52 	unsigned int OptimalDataAlignment() const
53 		{return GetSymmetricCipher().OptimalDataAlignment();}
54 	IV_Requirement IVRequirement() const
55 		{return UNIQUE_IV;}
56 	unsigned int IVSize() const
57 		{return 12;}
58 	unsigned int MinIVLength() const
59 		{return 12;}
60 	unsigned int MaxIVLength() const
61 		{return 12;}
62 	unsigned int DigestSize() const
63 		{return 16;}
64 	lword MaxHeaderLength() const
65 		{return LWORD_MAX;}  // 2^64-1 bytes
66 	lword MaxMessageLength() const
67 		{return W64LIT(274877906880);}  // 2^38-1 blocks
68 	lword MaxFooterLength() const
69 		{return 0;}
70 
71 	/// \brief Encrypts and calculates a MAC in one call
72 	/// \param ciphertext the encryption buffer
73 	/// \param mac the mac buffer
74 	/// \param macSize the size of the MAC buffer, in bytes
75 	/// \param iv the iv buffer
76 	/// \param ivLength the size of the IV buffer, in bytes
77 	/// \param aad the AAD buffer
78 	/// \param aadLength the size of the AAD buffer, in bytes
79 	/// \param message the message buffer
80 	/// \param messageLength the size of the messagetext buffer, in bytes
81 	/// \details EncryptAndAuthenticate() encrypts and generates the MAC in one call. The function
82 	///   truncates the MAC if <tt>macSize < TagSize()</tt>.
83 	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);
84 
85 	/// \brief Decrypts and verifies a MAC in one call
86 	/// \param message the decryption buffer
87 	/// \param mac the mac buffer
88 	/// \param macSize the size of the MAC buffer, in bytes
89 	/// \param iv the iv buffer
90 	/// \param ivLength the size of the IV buffer, in bytes
91 	/// \param aad the AAD buffer
92 	/// \param aadLength the size of the AAD buffer, in bytes
93 	/// \param ciphertext the cipher buffer
94 	/// \param ciphertextLength the size of the ciphertext buffer, in bytes
95 	/// \return true if the MAC is valid and the decoding succeeded, false otherwise
96 	/// \details DecryptAndVerify() decrypts and verifies the MAC in one call.
97 	/// <tt>message</tt> is a decryption buffer and should be at least as large as the ciphertext buffer.
98 	/// \details The function returns true iff MAC is valid. DecryptAndVerify() assumes the MAC
99 	///  is truncated if <tt>macLength < TagSize()</tt>.
100 	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);
101 
102 protected:
103 	// AuthenticatedSymmetricCipherBase
104 	bool AuthenticationIsOnPlaintext() const {return false;}
105 	unsigned int AuthenticationBlockSize() const {return 1;}
106 	void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
107 	void Resync(const byte *iv, size_t len);
108 	size_t AuthenticateBlocks(const byte *data, size_t len);
109 	void AuthenticateLastHeaderBlock();
110 	void AuthenticateLastConfidentialBlock();
111 	void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
112 
113 	// See comments in chachapoly.cpp
114 	void RekeyCipherAndMac(const byte *userKey, size_t userKeyLength, const NameValuePairs &params);
115 
116 	virtual const MessageAuthenticationCode & GetMAC() const = 0;
117 	virtual MessageAuthenticationCode & AccessMAC() = 0;
118 
119 private:
120 	SecByteBlock m_userKey;
121 };
122 
123 /// \brief IETF ChaCha20Poly1305 cipher final implementation
124 /// \tparam T_IsEncryption flag indicating cipher direction
125 /// \details ChaCha20Poly1305 is an authenticated encryption scheme that combines
126 ///  ChaCha20TLS and Poly1305TLS. The scheme is defined in RFC 8439, section 2.8,
127 ///  AEAD_CHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha20
128 ///  and Poly1305.
129 /// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
130 ///  for IETF Protocols</A>.
131 /// \since Crypto++ 8.1
132 template <bool T_IsEncryption>
133 class ChaCha20Poly1305_Final : public ChaCha20Poly1305_Base
134 {
135 public:
~ChaCha20Poly1305_Final()136 	virtual ~ChaCha20Poly1305_Final() {}
137 
138 protected:
GetSymmetricCipher()139 	const SymmetricCipher & GetSymmetricCipher()
140 		{return const_cast<ChaCha20Poly1305_Final *>(this)->AccessSymmetricCipher();}
AccessSymmetricCipher()141 	SymmetricCipher & AccessSymmetricCipher()
142 		{return m_cipher;}
IsForwardTransformation()143 	bool IsForwardTransformation() const
144 		{return T_IsEncryption;}
145 
GetMAC()146 	const MessageAuthenticationCode & GetMAC() const
147 		{return const_cast<ChaCha20Poly1305_Final *>(this)->AccessMAC();}
AccessMAC()148 	MessageAuthenticationCode & AccessMAC()
149 		{return m_mac;}
150 
151 private:
152 	ChaChaTLS::Encryption m_cipher;
153 	Poly1305TLS m_mac;
154 };
155 
156 /// \brief IETF ChaCha20/Poly1305 AEAD scheme
157 /// \details ChaCha20Poly1305 is an authenticated encryption scheme that combines
158 ///  ChaCha20TLS and Poly1305TLS. The scheme is defined in RFC 8439, section 2.8,
159 ///  AEAD_CHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha20
160 ///  and Poly1305.
161 /// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
162 ///  for IETF Protocols</A>.
163 /// \since Crypto++ 8.1
164 struct ChaCha20Poly1305 : public AuthenticatedSymmetricCipherDocumentation
165 {
166 	/// \brief ChaCha20Poly1305 encryption
167 	typedef ChaCha20Poly1305_Final<true> Encryption;
168 	/// \brief ChaCha20Poly1305 decryption
169 	typedef ChaCha20Poly1305_Final<false> Decryption;
170 };
171 
172 ////////////////////////////// IETF XChaCha20 draft //////////////////////////////
173 
174 /// \brief IETF XChaCha20Poly1305 cipher base implementation
175 /// \details Base implementation of the AuthenticatedSymmetricCipher interface
176 /// \since Crypto++ 8.1
177 class XChaCha20Poly1305_Base : public AuthenticatedSymmetricCipherBase
178 {
179 public:
StaticAlgorithmName()180 	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName()
181 		{return "XChaCha20/Poly1305";}
182 
~XChaCha20Poly1305_Base()183 	virtual ~XChaCha20Poly1305_Base() {}
184 
185 	// AuthenticatedSymmetricCipher
AlgorithmName()186 	std::string AlgorithmName() const
187 		{return std::string("XChaCha20/Poly1305");}
AlgorithmProvider()188 	std::string AlgorithmProvider() const
189 		{return GetSymmetricCipher().AlgorithmProvider();}
MinKeyLength()190 	size_t MinKeyLength() const
191 		{return 32;}
MaxKeyLength()192 	size_t MaxKeyLength() const
193 		{return 32;}
DefaultKeyLength()194 	size_t DefaultKeyLength() const
195 		{return 32;}
GetValidKeyLength(size_t n)196 	size_t GetValidKeyLength(size_t n) const
197 		{CRYPTOPP_UNUSED(n); return 32;}
IsValidKeyLength(size_t n)198 	bool IsValidKeyLength(size_t n) const
199 		{return n==32;}
OptimalDataAlignment()200 	unsigned int OptimalDataAlignment() const
201 		{return GetSymmetricCipher().OptimalDataAlignment();}
IVRequirement()202 	IV_Requirement IVRequirement() const
203 		{return UNIQUE_IV;}
IVSize()204 	unsigned int IVSize() const
205 		{return 24;}
MinIVLength()206 	unsigned int MinIVLength() const
207 		{return 24;}
MaxIVLength()208 	unsigned int MaxIVLength() const
209 		{return 24;}
DigestSize()210 	unsigned int DigestSize() const
211 		{return 16;}
MaxHeaderLength()212 	lword MaxHeaderLength() const
213 		{return LWORD_MAX;}  // 2^64-1 bytes
MaxMessageLength()214 	lword MaxMessageLength() const
215 		{return W64LIT(274877906880);}  // 2^38-1 blocks
MaxFooterLength()216 	lword MaxFooterLength() const
217 		{return 0;}
218 
219 	/// \brief Encrypts and calculates a MAC in one call
220 	/// \param ciphertext the encryption buffer
221 	/// \param mac the mac buffer
222 	/// \param macSize the size of the MAC buffer, in bytes
223 	/// \param iv the iv buffer
224 	/// \param ivLength the size of the IV buffer, in bytes
225 	/// \param aad the AAD buffer
226 	/// \param aadLength the size of the AAD buffer, in bytes
227 	/// \param message the message buffer
228 	/// \param messageLength the size of the messagetext buffer, in bytes
229 	/// \details EncryptAndAuthenticate() encrypts and generates the MAC in one call. The function
230 	///   truncates the MAC if <tt>macSize < TagSize()</tt>.
231 	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);
232 
233 	/// \brief Decrypts and verifies a MAC in one call
234 	/// \param message the decryption buffer
235 	/// \param mac the mac buffer
236 	/// \param macSize the size of the MAC buffer, in bytes
237 	/// \param iv the iv buffer
238 	/// \param ivLength the size of the IV buffer, in bytes
239 	/// \param aad the AAD buffer
240 	/// \param aadLength the size of the AAD buffer, in bytes
241 	/// \param ciphertext the cipher buffer
242 	/// \param ciphertextLength the size of the ciphertext buffer, in bytes
243 	/// \return true if the MAC is valid and the decoding succeeded, false otherwise
244 	/// \details DecryptAndVerify() decrypts and verifies the MAC in one call.
245 	/// <tt>message</tt> is a decryption buffer and should be at least as large as the ciphertext buffer.
246 	/// \details The function returns true iff MAC is valid. DecryptAndVerify() assumes the MAC
247 	///  is truncated if <tt>macLength < TagSize()</tt>.
248 	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);
249 
250 protected:
251 	// AuthenticatedSymmetricCipherBase
AuthenticationIsOnPlaintext()252 	bool AuthenticationIsOnPlaintext() const {return false;}
AuthenticationBlockSize()253 	unsigned int AuthenticationBlockSize() const {return 1;}
254 	void SetKeyWithoutResync(const byte *userKey, size_t keylength, const NameValuePairs &params);
255 	void Resync(const byte *iv, size_t len);
256 	size_t AuthenticateBlocks(const byte *data, size_t len);
257 	void AuthenticateLastHeaderBlock();
258 	void AuthenticateLastConfidentialBlock();
259 	void AuthenticateLastFooterBlock(byte *mac, size_t macSize);
260 
261 	// See comments in chachapoly.cpp
262 	void RekeyCipherAndMac(const byte *userKey, size_t userKeyLength, const NameValuePairs &params);
263 
264 	virtual const MessageAuthenticationCode & GetMAC() const = 0;
265 	virtual MessageAuthenticationCode & AccessMAC() = 0;
266 
267 private:
268 	SecByteBlock m_userKey;
269 };
270 
271 /// \brief IETF XChaCha20Poly1305 cipher final implementation
272 /// \tparam T_IsEncryption flag indicating cipher direction
273 /// \details XChaCha20Poly1305 is an authenticated encryption scheme that combines
274 ///  XChaCha20 and Poly1305-TLS. The scheme is defined in RFC 8439, section 2.8,
275 ///  AEAD_CHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha20
276 ///  and Poly1305.
277 /// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
278 ///  for IETF Protocols</A>.
279 /// \since Crypto++ 8.1
280 template <bool T_IsEncryption>
281 class XChaCha20Poly1305_Final : public XChaCha20Poly1305_Base
282 {
283 public:
~XChaCha20Poly1305_Final()284 	virtual ~XChaCha20Poly1305_Final() {}
285 
286 protected:
GetSymmetricCipher()287 	const SymmetricCipher & GetSymmetricCipher()
288 		{return const_cast<XChaCha20Poly1305_Final *>(this)->AccessSymmetricCipher();}
AccessSymmetricCipher()289 	SymmetricCipher & AccessSymmetricCipher()
290 		{return m_cipher;}
IsForwardTransformation()291 	bool IsForwardTransformation() const
292 		{return T_IsEncryption;}
293 
GetMAC()294 	const MessageAuthenticationCode & GetMAC() const
295 		{return const_cast<XChaCha20Poly1305_Final *>(this)->AccessMAC();}
AccessMAC()296 	MessageAuthenticationCode & AccessMAC()
297 		{return m_mac;}
298 
299 private:
300 	XChaCha20::Encryption m_cipher;
301 	Poly1305TLS m_mac;
302 };
303 
304 /// \brief IETF XChaCha20/Poly1305 AEAD scheme
305 /// \details XChaCha20Poly1305 is an authenticated encryption scheme that combines
306 ///  XChaCha20 and Poly1305-TLS. The scheme is defined in RFC 8439, section 2.8,
307 ///  AEAD_XCHACHA20_POLY1305 construction, and uses the IETF versions of ChaCha20
308 ///  and Poly1305.
309 /// \sa <A HREF="http://tools.ietf.org/html/rfc8439">RFC 8439, ChaCha20 and Poly1305
310 ///  for IETF Protocols</A>.
311 /// \since Crypto++ 8.1
312 struct XChaCha20Poly1305 : public AuthenticatedSymmetricCipherDocumentation
313 {
314 	/// \brief XChaCha20Poly1305 encryption
315 	typedef XChaCha20Poly1305_Final<true> Encryption;
316 	/// \brief XChaCha20Poly1305 decryption
317 	typedef XChaCha20Poly1305_Final<false> Decryption;
318 };
319 
320 NAMESPACE_END
321 
322 #endif  // CRYPTOPP_CHACHA_POLY1305_H
323