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