xref: /OK3568_Linux_fs/kernel/lib/crypto/chacha20poly1305.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0 OR MIT
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * This is an implementation of the ChaCha20Poly1305 AEAD construction.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Information: https://tools.ietf.org/html/rfc8439
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <crypto/algapi.h>
11*4882a593Smuzhiyun #include <crypto/chacha20poly1305.h>
12*4882a593Smuzhiyun #include <crypto/chacha.h>
13*4882a593Smuzhiyun #include <crypto/poly1305.h>
14*4882a593Smuzhiyun #include <crypto/scatterwalk.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <asm/unaligned.h>
17*4882a593Smuzhiyun #include <linux/kernel.h>
18*4882a593Smuzhiyun #include <linux/init.h>
19*4882a593Smuzhiyun #include <linux/mm.h>
20*4882a593Smuzhiyun #include <linux/module.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define CHACHA_KEY_WORDS	(CHACHA_KEY_SIZE / sizeof(u32))
23*4882a593Smuzhiyun 
chacha_load_key(u32 * k,const u8 * in)24*4882a593Smuzhiyun static void chacha_load_key(u32 *k, const u8 *in)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun 	k[0] = get_unaligned_le32(in);
27*4882a593Smuzhiyun 	k[1] = get_unaligned_le32(in + 4);
28*4882a593Smuzhiyun 	k[2] = get_unaligned_le32(in + 8);
29*4882a593Smuzhiyun 	k[3] = get_unaligned_le32(in + 12);
30*4882a593Smuzhiyun 	k[4] = get_unaligned_le32(in + 16);
31*4882a593Smuzhiyun 	k[5] = get_unaligned_le32(in + 20);
32*4882a593Smuzhiyun 	k[6] = get_unaligned_le32(in + 24);
33*4882a593Smuzhiyun 	k[7] = get_unaligned_le32(in + 28);
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
xchacha_init(u32 * chacha_state,const u8 * key,const u8 * nonce)36*4882a593Smuzhiyun static void xchacha_init(u32 *chacha_state, const u8 *key, const u8 *nonce)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	u32 k[CHACHA_KEY_WORDS];
39*4882a593Smuzhiyun 	u8 iv[CHACHA_IV_SIZE];
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	memset(iv, 0, 8);
42*4882a593Smuzhiyun 	memcpy(iv + 8, nonce + 16, 8);
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	chacha_load_key(k, key);
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	/* Compute the subkey given the original key and first 128 nonce bits */
47*4882a593Smuzhiyun 	chacha_init(chacha_state, k, nonce);
48*4882a593Smuzhiyun 	hchacha_block(chacha_state, k, 20);
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	chacha_init(chacha_state, k, iv);
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	memzero_explicit(k, sizeof(k));
53*4882a593Smuzhiyun 	memzero_explicit(iv, sizeof(iv));
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun static void
__chacha20poly1305_encrypt(u8 * dst,const u8 * src,const size_t src_len,const u8 * ad,const size_t ad_len,u32 * chacha_state)57*4882a593Smuzhiyun __chacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len,
58*4882a593Smuzhiyun 			   const u8 *ad, const size_t ad_len, u32 *chacha_state)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	const u8 *pad0 = page_address(ZERO_PAGE(0));
61*4882a593Smuzhiyun 	struct poly1305_desc_ctx poly1305_state;
62*4882a593Smuzhiyun 	union {
63*4882a593Smuzhiyun 		u8 block0[POLY1305_KEY_SIZE];
64*4882a593Smuzhiyun 		__le64 lens[2];
65*4882a593Smuzhiyun 	} b;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	chacha20_crypt(chacha_state, b.block0, pad0, sizeof(b.block0));
68*4882a593Smuzhiyun 	poly1305_init(&poly1305_state, b.block0);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	poly1305_update(&poly1305_state, ad, ad_len);
71*4882a593Smuzhiyun 	if (ad_len & 0xf)
72*4882a593Smuzhiyun 		poly1305_update(&poly1305_state, pad0, 0x10 - (ad_len & 0xf));
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	chacha20_crypt(chacha_state, dst, src, src_len);
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	poly1305_update(&poly1305_state, dst, src_len);
77*4882a593Smuzhiyun 	if (src_len & 0xf)
78*4882a593Smuzhiyun 		poly1305_update(&poly1305_state, pad0, 0x10 - (src_len & 0xf));
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	b.lens[0] = cpu_to_le64(ad_len);
81*4882a593Smuzhiyun 	b.lens[1] = cpu_to_le64(src_len);
82*4882a593Smuzhiyun 	poly1305_update(&poly1305_state, (u8 *)b.lens, sizeof(b.lens));
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	poly1305_final(&poly1305_state, dst + src_len);
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	memzero_explicit(chacha_state, CHACHA_STATE_WORDS * sizeof(u32));
87*4882a593Smuzhiyun 	memzero_explicit(&b, sizeof(b));
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
chacha20poly1305_encrypt(u8 * dst,const u8 * src,const size_t src_len,const u8 * ad,const size_t ad_len,const u64 nonce,const u8 key[CHACHA20POLY1305_KEY_SIZE])90*4882a593Smuzhiyun void chacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len,
91*4882a593Smuzhiyun 			      const u8 *ad, const size_t ad_len,
92*4882a593Smuzhiyun 			      const u64 nonce,
93*4882a593Smuzhiyun 			      const u8 key[CHACHA20POLY1305_KEY_SIZE])
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun 	u32 chacha_state[CHACHA_STATE_WORDS];
96*4882a593Smuzhiyun 	u32 k[CHACHA_KEY_WORDS];
97*4882a593Smuzhiyun 	__le64 iv[2];
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	chacha_load_key(k, key);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	iv[0] = 0;
102*4882a593Smuzhiyun 	iv[1] = cpu_to_le64(nonce);
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	chacha_init(chacha_state, k, (u8 *)iv);
105*4882a593Smuzhiyun 	__chacha20poly1305_encrypt(dst, src, src_len, ad, ad_len, chacha_state);
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	memzero_explicit(iv, sizeof(iv));
108*4882a593Smuzhiyun 	memzero_explicit(k, sizeof(k));
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun EXPORT_SYMBOL(chacha20poly1305_encrypt);
111*4882a593Smuzhiyun 
xchacha20poly1305_encrypt(u8 * dst,const u8 * src,const size_t src_len,const u8 * ad,const size_t ad_len,const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE],const u8 key[CHACHA20POLY1305_KEY_SIZE])112*4882a593Smuzhiyun void xchacha20poly1305_encrypt(u8 *dst, const u8 *src, const size_t src_len,
113*4882a593Smuzhiyun 			       const u8 *ad, const size_t ad_len,
114*4882a593Smuzhiyun 			       const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE],
115*4882a593Smuzhiyun 			       const u8 key[CHACHA20POLY1305_KEY_SIZE])
116*4882a593Smuzhiyun {
117*4882a593Smuzhiyun 	u32 chacha_state[CHACHA_STATE_WORDS];
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	xchacha_init(chacha_state, key, nonce);
120*4882a593Smuzhiyun 	__chacha20poly1305_encrypt(dst, src, src_len, ad, ad_len, chacha_state);
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun EXPORT_SYMBOL(xchacha20poly1305_encrypt);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun static bool
__chacha20poly1305_decrypt(u8 * dst,const u8 * src,const size_t src_len,const u8 * ad,const size_t ad_len,u32 * chacha_state)125*4882a593Smuzhiyun __chacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len,
126*4882a593Smuzhiyun 			   const u8 *ad, const size_t ad_len, u32 *chacha_state)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun 	const u8 *pad0 = page_address(ZERO_PAGE(0));
129*4882a593Smuzhiyun 	struct poly1305_desc_ctx poly1305_state;
130*4882a593Smuzhiyun 	size_t dst_len;
131*4882a593Smuzhiyun 	int ret;
132*4882a593Smuzhiyun 	union {
133*4882a593Smuzhiyun 		u8 block0[POLY1305_KEY_SIZE];
134*4882a593Smuzhiyun 		u8 mac[POLY1305_DIGEST_SIZE];
135*4882a593Smuzhiyun 		__le64 lens[2];
136*4882a593Smuzhiyun 	} b;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	if (unlikely(src_len < POLY1305_DIGEST_SIZE))
139*4882a593Smuzhiyun 		return false;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	chacha20_crypt(chacha_state, b.block0, pad0, sizeof(b.block0));
142*4882a593Smuzhiyun 	poly1305_init(&poly1305_state, b.block0);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	poly1305_update(&poly1305_state, ad, ad_len);
145*4882a593Smuzhiyun 	if (ad_len & 0xf)
146*4882a593Smuzhiyun 		poly1305_update(&poly1305_state, pad0, 0x10 - (ad_len & 0xf));
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	dst_len = src_len - POLY1305_DIGEST_SIZE;
149*4882a593Smuzhiyun 	poly1305_update(&poly1305_state, src, dst_len);
150*4882a593Smuzhiyun 	if (dst_len & 0xf)
151*4882a593Smuzhiyun 		poly1305_update(&poly1305_state, pad0, 0x10 - (dst_len & 0xf));
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	b.lens[0] = cpu_to_le64(ad_len);
154*4882a593Smuzhiyun 	b.lens[1] = cpu_to_le64(dst_len);
155*4882a593Smuzhiyun 	poly1305_update(&poly1305_state, (u8 *)b.lens, sizeof(b.lens));
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	poly1305_final(&poly1305_state, b.mac);
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	ret = crypto_memneq(b.mac, src + dst_len, POLY1305_DIGEST_SIZE);
160*4882a593Smuzhiyun 	if (likely(!ret))
161*4882a593Smuzhiyun 		chacha20_crypt(chacha_state, dst, src, dst_len);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	memzero_explicit(&b, sizeof(b));
164*4882a593Smuzhiyun 
165*4882a593Smuzhiyun 	return !ret;
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun 
chacha20poly1305_decrypt(u8 * dst,const u8 * src,const size_t src_len,const u8 * ad,const size_t ad_len,const u64 nonce,const u8 key[CHACHA20POLY1305_KEY_SIZE])168*4882a593Smuzhiyun bool chacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len,
169*4882a593Smuzhiyun 			      const u8 *ad, const size_t ad_len,
170*4882a593Smuzhiyun 			      const u64 nonce,
171*4882a593Smuzhiyun 			      const u8 key[CHACHA20POLY1305_KEY_SIZE])
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun 	u32 chacha_state[CHACHA_STATE_WORDS];
174*4882a593Smuzhiyun 	u32 k[CHACHA_KEY_WORDS];
175*4882a593Smuzhiyun 	__le64 iv[2];
176*4882a593Smuzhiyun 	bool ret;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	chacha_load_key(k, key);
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	iv[0] = 0;
181*4882a593Smuzhiyun 	iv[1] = cpu_to_le64(nonce);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	chacha_init(chacha_state, k, (u8 *)iv);
184*4882a593Smuzhiyun 	ret = __chacha20poly1305_decrypt(dst, src, src_len, ad, ad_len,
185*4882a593Smuzhiyun 					 chacha_state);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	memzero_explicit(chacha_state, sizeof(chacha_state));
188*4882a593Smuzhiyun 	memzero_explicit(iv, sizeof(iv));
189*4882a593Smuzhiyun 	memzero_explicit(k, sizeof(k));
190*4882a593Smuzhiyun 	return ret;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun EXPORT_SYMBOL(chacha20poly1305_decrypt);
193*4882a593Smuzhiyun 
xchacha20poly1305_decrypt(u8 * dst,const u8 * src,const size_t src_len,const u8 * ad,const size_t ad_len,const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE],const u8 key[CHACHA20POLY1305_KEY_SIZE])194*4882a593Smuzhiyun bool xchacha20poly1305_decrypt(u8 *dst, const u8 *src, const size_t src_len,
195*4882a593Smuzhiyun 			       const u8 *ad, const size_t ad_len,
196*4882a593Smuzhiyun 			       const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE],
197*4882a593Smuzhiyun 			       const u8 key[CHACHA20POLY1305_KEY_SIZE])
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun 	u32 chacha_state[CHACHA_STATE_WORDS];
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	xchacha_init(chacha_state, key, nonce);
202*4882a593Smuzhiyun 	return __chacha20poly1305_decrypt(dst, src, src_len, ad, ad_len,
203*4882a593Smuzhiyun 					  chacha_state);
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun EXPORT_SYMBOL(xchacha20poly1305_decrypt);
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun static
chacha20poly1305_crypt_sg_inplace(struct scatterlist * src,const size_t src_len,const u8 * ad,const size_t ad_len,const u64 nonce,const u8 key[CHACHA20POLY1305_KEY_SIZE],int encrypt)208*4882a593Smuzhiyun bool chacha20poly1305_crypt_sg_inplace(struct scatterlist *src,
209*4882a593Smuzhiyun 				       const size_t src_len,
210*4882a593Smuzhiyun 				       const u8 *ad, const size_t ad_len,
211*4882a593Smuzhiyun 				       const u64 nonce,
212*4882a593Smuzhiyun 				       const u8 key[CHACHA20POLY1305_KEY_SIZE],
213*4882a593Smuzhiyun 				       int encrypt)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun 	const u8 *pad0 = page_address(ZERO_PAGE(0));
216*4882a593Smuzhiyun 	struct poly1305_desc_ctx poly1305_state;
217*4882a593Smuzhiyun 	u32 chacha_state[CHACHA_STATE_WORDS];
218*4882a593Smuzhiyun 	struct sg_mapping_iter miter;
219*4882a593Smuzhiyun 	size_t partial = 0;
220*4882a593Smuzhiyun 	unsigned int flags;
221*4882a593Smuzhiyun 	bool ret = true;
222*4882a593Smuzhiyun 	int sl;
223*4882a593Smuzhiyun 	union {
224*4882a593Smuzhiyun 		struct {
225*4882a593Smuzhiyun 			u32 k[CHACHA_KEY_WORDS];
226*4882a593Smuzhiyun 			__le64 iv[2];
227*4882a593Smuzhiyun 		};
228*4882a593Smuzhiyun 		u8 block0[POLY1305_KEY_SIZE];
229*4882a593Smuzhiyun 		u8 chacha_stream[CHACHA_BLOCK_SIZE];
230*4882a593Smuzhiyun 		struct {
231*4882a593Smuzhiyun 			u8 mac[2][POLY1305_DIGEST_SIZE];
232*4882a593Smuzhiyun 		};
233*4882a593Smuzhiyun 		__le64 lens[2];
234*4882a593Smuzhiyun 	} b __aligned(16);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	if (WARN_ON(src_len > INT_MAX))
237*4882a593Smuzhiyun 		return false;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	chacha_load_key(b.k, key);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	b.iv[0] = 0;
242*4882a593Smuzhiyun 	b.iv[1] = cpu_to_le64(nonce);
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	chacha_init(chacha_state, b.k, (u8 *)b.iv);
245*4882a593Smuzhiyun 	chacha20_crypt(chacha_state, b.block0, pad0, sizeof(b.block0));
246*4882a593Smuzhiyun 	poly1305_init(&poly1305_state, b.block0);
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	if (unlikely(ad_len)) {
249*4882a593Smuzhiyun 		poly1305_update(&poly1305_state, ad, ad_len);
250*4882a593Smuzhiyun 		if (ad_len & 0xf)
251*4882a593Smuzhiyun 			poly1305_update(&poly1305_state, pad0, 0x10 - (ad_len & 0xf));
252*4882a593Smuzhiyun 	}
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	flags = SG_MITER_TO_SG | SG_MITER_ATOMIC;
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	sg_miter_start(&miter, src, sg_nents(src), flags);
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	for (sl = src_len; sl > 0 && sg_miter_next(&miter); sl -= miter.length) {
259*4882a593Smuzhiyun 		u8 *addr = miter.addr;
260*4882a593Smuzhiyun 		size_t length = min_t(size_t, sl, miter.length);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 		if (!encrypt)
263*4882a593Smuzhiyun 			poly1305_update(&poly1305_state, addr, length);
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 		if (unlikely(partial)) {
266*4882a593Smuzhiyun 			size_t l = min(length, CHACHA_BLOCK_SIZE - partial);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 			crypto_xor(addr, b.chacha_stream + partial, l);
269*4882a593Smuzhiyun 			partial = (partial + l) & (CHACHA_BLOCK_SIZE - 1);
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 			addr += l;
272*4882a593Smuzhiyun 			length -= l;
273*4882a593Smuzhiyun 		}
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 		if (likely(length >= CHACHA_BLOCK_SIZE || length == sl)) {
276*4882a593Smuzhiyun 			size_t l = length;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 			if (unlikely(length < sl))
279*4882a593Smuzhiyun 				l &= ~(CHACHA_BLOCK_SIZE - 1);
280*4882a593Smuzhiyun 			chacha20_crypt(chacha_state, addr, addr, l);
281*4882a593Smuzhiyun 			addr += l;
282*4882a593Smuzhiyun 			length -= l;
283*4882a593Smuzhiyun 		}
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 		if (unlikely(length > 0)) {
286*4882a593Smuzhiyun 			chacha20_crypt(chacha_state, b.chacha_stream, pad0,
287*4882a593Smuzhiyun 				       CHACHA_BLOCK_SIZE);
288*4882a593Smuzhiyun 			crypto_xor(addr, b.chacha_stream, length);
289*4882a593Smuzhiyun 			partial = length;
290*4882a593Smuzhiyun 		}
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 		if (encrypt)
293*4882a593Smuzhiyun 			poly1305_update(&poly1305_state, miter.addr,
294*4882a593Smuzhiyun 					min_t(size_t, sl, miter.length));
295*4882a593Smuzhiyun 	}
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	if (src_len & 0xf)
298*4882a593Smuzhiyun 		poly1305_update(&poly1305_state, pad0, 0x10 - (src_len & 0xf));
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	b.lens[0] = cpu_to_le64(ad_len);
301*4882a593Smuzhiyun 	b.lens[1] = cpu_to_le64(src_len);
302*4882a593Smuzhiyun 	poly1305_update(&poly1305_state, (u8 *)b.lens, sizeof(b.lens));
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	if (likely(sl <= -POLY1305_DIGEST_SIZE)) {
305*4882a593Smuzhiyun 		if (encrypt) {
306*4882a593Smuzhiyun 			poly1305_final(&poly1305_state,
307*4882a593Smuzhiyun 				       miter.addr + miter.length + sl);
308*4882a593Smuzhiyun 			ret = true;
309*4882a593Smuzhiyun 		} else {
310*4882a593Smuzhiyun 			poly1305_final(&poly1305_state, b.mac[0]);
311*4882a593Smuzhiyun 			ret = !crypto_memneq(b.mac[0],
312*4882a593Smuzhiyun 					     miter.addr + miter.length + sl,
313*4882a593Smuzhiyun 					     POLY1305_DIGEST_SIZE);
314*4882a593Smuzhiyun 		}
315*4882a593Smuzhiyun 	}
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	sg_miter_stop(&miter);
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	if (unlikely(sl > -POLY1305_DIGEST_SIZE)) {
320*4882a593Smuzhiyun 		poly1305_final(&poly1305_state, b.mac[1]);
321*4882a593Smuzhiyun 		scatterwalk_map_and_copy(b.mac[encrypt], src, src_len,
322*4882a593Smuzhiyun 					 sizeof(b.mac[1]), encrypt);
323*4882a593Smuzhiyun 		ret = encrypt ||
324*4882a593Smuzhiyun 		      !crypto_memneq(b.mac[0], b.mac[1], POLY1305_DIGEST_SIZE);
325*4882a593Smuzhiyun 	}
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	memzero_explicit(chacha_state, sizeof(chacha_state));
328*4882a593Smuzhiyun 	memzero_explicit(&b, sizeof(b));
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	return ret;
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun 
chacha20poly1305_encrypt_sg_inplace(struct scatterlist * src,size_t src_len,const u8 * ad,const size_t ad_len,const u64 nonce,const u8 key[CHACHA20POLY1305_KEY_SIZE])333*4882a593Smuzhiyun bool chacha20poly1305_encrypt_sg_inplace(struct scatterlist *src, size_t src_len,
334*4882a593Smuzhiyun 					 const u8 *ad, const size_t ad_len,
335*4882a593Smuzhiyun 					 const u64 nonce,
336*4882a593Smuzhiyun 					 const u8 key[CHACHA20POLY1305_KEY_SIZE])
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun 	return chacha20poly1305_crypt_sg_inplace(src, src_len, ad, ad_len,
339*4882a593Smuzhiyun 						 nonce, key, 1);
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun EXPORT_SYMBOL(chacha20poly1305_encrypt_sg_inplace);
342*4882a593Smuzhiyun 
chacha20poly1305_decrypt_sg_inplace(struct scatterlist * src,size_t src_len,const u8 * ad,const size_t ad_len,const u64 nonce,const u8 key[CHACHA20POLY1305_KEY_SIZE])343*4882a593Smuzhiyun bool chacha20poly1305_decrypt_sg_inplace(struct scatterlist *src, size_t src_len,
344*4882a593Smuzhiyun 					 const u8 *ad, const size_t ad_len,
345*4882a593Smuzhiyun 					 const u64 nonce,
346*4882a593Smuzhiyun 					 const u8 key[CHACHA20POLY1305_KEY_SIZE])
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun 	if (unlikely(src_len < POLY1305_DIGEST_SIZE))
349*4882a593Smuzhiyun 		return false;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	return chacha20poly1305_crypt_sg_inplace(src,
352*4882a593Smuzhiyun 						 src_len - POLY1305_DIGEST_SIZE,
353*4882a593Smuzhiyun 						 ad, ad_len, nonce, key, 0);
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun EXPORT_SYMBOL(chacha20poly1305_decrypt_sg_inplace);
356*4882a593Smuzhiyun 
mod_init(void)357*4882a593Smuzhiyun static int __init mod_init(void)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	if (!IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) &&
360*4882a593Smuzhiyun 	    WARN_ON(!chacha20poly1305_selftest()))
361*4882a593Smuzhiyun 		return -ENODEV;
362*4882a593Smuzhiyun 	return 0;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun module_init(mod_init);
366*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
367*4882a593Smuzhiyun MODULE_DESCRIPTION("ChaCha20Poly1305 AEAD construction");
368*4882a593Smuzhiyun MODULE_AUTHOR("Jason A. Donenfeld <Jason@zx2c4.com>");
369