xref: /openbmc/linux/arch/arm/crypto/chacha-glue.c (revision 8394bfec51e0e565556101bcc4e2fe7551104cd8)
1b36d8c09SArd Biesheuvel // SPDX-License-Identifier: GPL-2.0
2b36d8c09SArd Biesheuvel /*
3b36d8c09SArd Biesheuvel  * ARM NEON accelerated ChaCha and XChaCha stream ciphers,
4b36d8c09SArd Biesheuvel  * including ChaCha20 (RFC7539)
5b36d8c09SArd Biesheuvel  *
6b36d8c09SArd Biesheuvel  * Copyright (C) 2016-2019 Linaro, Ltd. <ard.biesheuvel@linaro.org>
7b36d8c09SArd Biesheuvel  * Copyright (C) 2015 Martin Willi
8b36d8c09SArd Biesheuvel  */
9b36d8c09SArd Biesheuvel 
10b36d8c09SArd Biesheuvel #include <crypto/algapi.h>
11b36d8c09SArd Biesheuvel #include <crypto/internal/chacha.h>
12b36d8c09SArd Biesheuvel #include <crypto/internal/simd.h>
13b36d8c09SArd Biesheuvel #include <crypto/internal/skcipher.h>
14a44a3430SArd Biesheuvel #include <linux/jump_label.h>
15b36d8c09SArd Biesheuvel #include <linux/kernel.h>
16b36d8c09SArd Biesheuvel #include <linux/module.h>
17b36d8c09SArd Biesheuvel 
18b36d8c09SArd Biesheuvel #include <asm/cputype.h>
19b36d8c09SArd Biesheuvel #include <asm/hwcap.h>
20b36d8c09SArd Biesheuvel #include <asm/neon.h>
21b36d8c09SArd Biesheuvel #include <asm/simd.h>
22b36d8c09SArd Biesheuvel 
23b36d8c09SArd Biesheuvel asmlinkage void chacha_block_xor_neon(const u32 *state, u8 *dst, const u8 *src,
24b36d8c09SArd Biesheuvel 				      int nrounds);
25b36d8c09SArd Biesheuvel asmlinkage void chacha_4block_xor_neon(const u32 *state, u8 *dst, const u8 *src,
26b36d8c09SArd Biesheuvel 				       int nrounds);
27b36d8c09SArd Biesheuvel asmlinkage void hchacha_block_arm(const u32 *state, u32 *out, int nrounds);
28b36d8c09SArd Biesheuvel asmlinkage void hchacha_block_neon(const u32 *state, u32 *out, int nrounds);
29b36d8c09SArd Biesheuvel 
30b36d8c09SArd Biesheuvel asmlinkage void chacha_doarm(u8 *dst, const u8 *src, unsigned int bytes,
31b36d8c09SArd Biesheuvel 			     const u32 *state, int nrounds);
32b36d8c09SArd Biesheuvel 
33a44a3430SArd Biesheuvel static __ro_after_init DEFINE_STATIC_KEY_FALSE(use_neon);
34a44a3430SArd Biesheuvel 
35b36d8c09SArd Biesheuvel static inline bool neon_usable(void)
36b36d8c09SArd Biesheuvel {
37a44a3430SArd Biesheuvel 	return static_branch_likely(&use_neon) && crypto_simd_usable();
38b36d8c09SArd Biesheuvel }
39b36d8c09SArd Biesheuvel 
40b36d8c09SArd Biesheuvel static void chacha_doneon(u32 *state, u8 *dst, const u8 *src,
41b36d8c09SArd Biesheuvel 			  unsigned int bytes, int nrounds)
42b36d8c09SArd Biesheuvel {
43b36d8c09SArd Biesheuvel 	u8 buf[CHACHA_BLOCK_SIZE];
44b36d8c09SArd Biesheuvel 
45b36d8c09SArd Biesheuvel 	while (bytes >= CHACHA_BLOCK_SIZE * 4) {
46b36d8c09SArd Biesheuvel 		chacha_4block_xor_neon(state, dst, src, nrounds);
47b36d8c09SArd Biesheuvel 		bytes -= CHACHA_BLOCK_SIZE * 4;
48b36d8c09SArd Biesheuvel 		src += CHACHA_BLOCK_SIZE * 4;
49b36d8c09SArd Biesheuvel 		dst += CHACHA_BLOCK_SIZE * 4;
50b36d8c09SArd Biesheuvel 		state[12] += 4;
51b36d8c09SArd Biesheuvel 	}
52b36d8c09SArd Biesheuvel 	while (bytes >= CHACHA_BLOCK_SIZE) {
53b36d8c09SArd Biesheuvel 		chacha_block_xor_neon(state, dst, src, nrounds);
54b36d8c09SArd Biesheuvel 		bytes -= CHACHA_BLOCK_SIZE;
55b36d8c09SArd Biesheuvel 		src += CHACHA_BLOCK_SIZE;
56b36d8c09SArd Biesheuvel 		dst += CHACHA_BLOCK_SIZE;
57b36d8c09SArd Biesheuvel 		state[12]++;
58b36d8c09SArd Biesheuvel 	}
59b36d8c09SArd Biesheuvel 	if (bytes) {
60b36d8c09SArd Biesheuvel 		memcpy(buf, src, bytes);
61b36d8c09SArd Biesheuvel 		chacha_block_xor_neon(state, buf, buf, nrounds);
62b36d8c09SArd Biesheuvel 		memcpy(dst, buf, bytes);
63b36d8c09SArd Biesheuvel 	}
64b36d8c09SArd Biesheuvel }
65b36d8c09SArd Biesheuvel 
66a44a3430SArd Biesheuvel void hchacha_block_arch(const u32 *state, u32 *stream, int nrounds)
67a44a3430SArd Biesheuvel {
68a44a3430SArd Biesheuvel 	if (!IS_ENABLED(CONFIG_KERNEL_MODE_NEON) || !neon_usable()) {
69a44a3430SArd Biesheuvel 		hchacha_block_arm(state, stream, nrounds);
70a44a3430SArd Biesheuvel 	} else {
71a44a3430SArd Biesheuvel 		kernel_neon_begin();
72a44a3430SArd Biesheuvel 		hchacha_block_neon(state, stream, nrounds);
73a44a3430SArd Biesheuvel 		kernel_neon_end();
74a44a3430SArd Biesheuvel 	}
75a44a3430SArd Biesheuvel }
76a44a3430SArd Biesheuvel EXPORT_SYMBOL(hchacha_block_arch);
77a44a3430SArd Biesheuvel 
78a44a3430SArd Biesheuvel void chacha_init_arch(u32 *state, const u32 *key, const u8 *iv)
79a44a3430SArd Biesheuvel {
80a44a3430SArd Biesheuvel 	chacha_init_generic(state, key, iv);
81a44a3430SArd Biesheuvel }
82a44a3430SArd Biesheuvel EXPORT_SYMBOL(chacha_init_arch);
83a44a3430SArd Biesheuvel 
84a44a3430SArd Biesheuvel void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, unsigned int bytes,
85a44a3430SArd Biesheuvel 		       int nrounds)
86a44a3430SArd Biesheuvel {
87a44a3430SArd Biesheuvel 	if (!IS_ENABLED(CONFIG_KERNEL_MODE_NEON) || !neon_usable() ||
88a44a3430SArd Biesheuvel 	    bytes <= CHACHA_BLOCK_SIZE) {
89a44a3430SArd Biesheuvel 		chacha_doarm(dst, src, bytes, state, nrounds);
90a44a3430SArd Biesheuvel 		state[12] += DIV_ROUND_UP(bytes, CHACHA_BLOCK_SIZE);
91a44a3430SArd Biesheuvel 		return;
92a44a3430SArd Biesheuvel 	}
93a44a3430SArd Biesheuvel 
94a44a3430SArd Biesheuvel 	kernel_neon_begin();
95a44a3430SArd Biesheuvel 	chacha_doneon(state, dst, src, bytes, nrounds);
96a44a3430SArd Biesheuvel 	kernel_neon_end();
97a44a3430SArd Biesheuvel }
98a44a3430SArd Biesheuvel EXPORT_SYMBOL(chacha_crypt_arch);
99a44a3430SArd Biesheuvel 
100b36d8c09SArd Biesheuvel static int chacha_stream_xor(struct skcipher_request *req,
101b36d8c09SArd Biesheuvel 			     const struct chacha_ctx *ctx, const u8 *iv,
102b36d8c09SArd Biesheuvel 			     bool neon)
103b36d8c09SArd Biesheuvel {
104b36d8c09SArd Biesheuvel 	struct skcipher_walk walk;
105b36d8c09SArd Biesheuvel 	u32 state[16];
106b36d8c09SArd Biesheuvel 	int err;
107b36d8c09SArd Biesheuvel 
108b36d8c09SArd Biesheuvel 	err = skcipher_walk_virt(&walk, req, false);
109b36d8c09SArd Biesheuvel 
110b36d8c09SArd Biesheuvel 	chacha_init_generic(state, ctx->key, iv);
111b36d8c09SArd Biesheuvel 
112b36d8c09SArd Biesheuvel 	while (walk.nbytes > 0) {
113b36d8c09SArd Biesheuvel 		unsigned int nbytes = walk.nbytes;
114b36d8c09SArd Biesheuvel 
115b36d8c09SArd Biesheuvel 		if (nbytes < walk.total)
116b36d8c09SArd Biesheuvel 			nbytes = round_down(nbytes, walk.stride);
117b36d8c09SArd Biesheuvel 
118b36d8c09SArd Biesheuvel 		if (!neon) {
119b36d8c09SArd Biesheuvel 			chacha_doarm(walk.dst.virt.addr, walk.src.virt.addr,
120b36d8c09SArd Biesheuvel 				     nbytes, state, ctx->nrounds);
121b36d8c09SArd Biesheuvel 			state[12] += DIV_ROUND_UP(nbytes, CHACHA_BLOCK_SIZE);
122b36d8c09SArd Biesheuvel 		} else {
123b36d8c09SArd Biesheuvel 			kernel_neon_begin();
124b36d8c09SArd Biesheuvel 			chacha_doneon(state, walk.dst.virt.addr,
125b36d8c09SArd Biesheuvel 				      walk.src.virt.addr, nbytes, ctx->nrounds);
126b36d8c09SArd Biesheuvel 			kernel_neon_end();
127b36d8c09SArd Biesheuvel 		}
128b36d8c09SArd Biesheuvel 		err = skcipher_walk_done(&walk, walk.nbytes - nbytes);
129b36d8c09SArd Biesheuvel 	}
130b36d8c09SArd Biesheuvel 
131b36d8c09SArd Biesheuvel 	return err;
132b36d8c09SArd Biesheuvel }
133b36d8c09SArd Biesheuvel 
134b36d8c09SArd Biesheuvel static int do_chacha(struct skcipher_request *req, bool neon)
135b36d8c09SArd Biesheuvel {
136b36d8c09SArd Biesheuvel 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
137b36d8c09SArd Biesheuvel 	struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
138b36d8c09SArd Biesheuvel 
139b36d8c09SArd Biesheuvel 	return chacha_stream_xor(req, ctx, req->iv, neon);
140b36d8c09SArd Biesheuvel }
141b36d8c09SArd Biesheuvel 
142b36d8c09SArd Biesheuvel static int chacha_arm(struct skcipher_request *req)
143b36d8c09SArd Biesheuvel {
144b36d8c09SArd Biesheuvel 	return do_chacha(req, false);
145b36d8c09SArd Biesheuvel }
146b36d8c09SArd Biesheuvel 
147b36d8c09SArd Biesheuvel static int chacha_neon(struct skcipher_request *req)
148b36d8c09SArd Biesheuvel {
149b36d8c09SArd Biesheuvel 	return do_chacha(req, neon_usable());
150b36d8c09SArd Biesheuvel }
151b36d8c09SArd Biesheuvel 
152b36d8c09SArd Biesheuvel static int do_xchacha(struct skcipher_request *req, bool neon)
153b36d8c09SArd Biesheuvel {
154b36d8c09SArd Biesheuvel 	struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
155b36d8c09SArd Biesheuvel 	struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm);
156b36d8c09SArd Biesheuvel 	struct chacha_ctx subctx;
157b36d8c09SArd Biesheuvel 	u32 state[16];
158b36d8c09SArd Biesheuvel 	u8 real_iv[16];
159b36d8c09SArd Biesheuvel 
160b36d8c09SArd Biesheuvel 	chacha_init_generic(state, ctx->key, req->iv);
161b36d8c09SArd Biesheuvel 
162b36d8c09SArd Biesheuvel 	if (!neon) {
163b36d8c09SArd Biesheuvel 		hchacha_block_arm(state, subctx.key, ctx->nrounds);
164b36d8c09SArd Biesheuvel 	} else {
165b36d8c09SArd Biesheuvel 		kernel_neon_begin();
166b36d8c09SArd Biesheuvel 		hchacha_block_neon(state, subctx.key, ctx->nrounds);
167b36d8c09SArd Biesheuvel 		kernel_neon_end();
168b36d8c09SArd Biesheuvel 	}
169b36d8c09SArd Biesheuvel 	subctx.nrounds = ctx->nrounds;
170b36d8c09SArd Biesheuvel 
171b36d8c09SArd Biesheuvel 	memcpy(&real_iv[0], req->iv + 24, 8);
172b36d8c09SArd Biesheuvel 	memcpy(&real_iv[8], req->iv + 16, 8);
173b36d8c09SArd Biesheuvel 	return chacha_stream_xor(req, &subctx, real_iv, neon);
174b36d8c09SArd Biesheuvel }
175b36d8c09SArd Biesheuvel 
176b36d8c09SArd Biesheuvel static int xchacha_arm(struct skcipher_request *req)
177b36d8c09SArd Biesheuvel {
178b36d8c09SArd Biesheuvel 	return do_xchacha(req, false);
179b36d8c09SArd Biesheuvel }
180b36d8c09SArd Biesheuvel 
181b36d8c09SArd Biesheuvel static int xchacha_neon(struct skcipher_request *req)
182b36d8c09SArd Biesheuvel {
183b36d8c09SArd Biesheuvel 	return do_xchacha(req, neon_usable());
184b36d8c09SArd Biesheuvel }
185b36d8c09SArd Biesheuvel 
186b36d8c09SArd Biesheuvel static struct skcipher_alg arm_algs[] = {
187b36d8c09SArd Biesheuvel 	{
188b36d8c09SArd Biesheuvel 		.base.cra_name		= "chacha20",
189b36d8c09SArd Biesheuvel 		.base.cra_driver_name	= "chacha20-arm",
190b36d8c09SArd Biesheuvel 		.base.cra_priority	= 200,
191b36d8c09SArd Biesheuvel 		.base.cra_blocksize	= 1,
192b36d8c09SArd Biesheuvel 		.base.cra_ctxsize	= sizeof(struct chacha_ctx),
193b36d8c09SArd Biesheuvel 		.base.cra_module	= THIS_MODULE,
194b36d8c09SArd Biesheuvel 
195b36d8c09SArd Biesheuvel 		.min_keysize		= CHACHA_KEY_SIZE,
196b36d8c09SArd Biesheuvel 		.max_keysize		= CHACHA_KEY_SIZE,
197b36d8c09SArd Biesheuvel 		.ivsize			= CHACHA_IV_SIZE,
198b36d8c09SArd Biesheuvel 		.chunksize		= CHACHA_BLOCK_SIZE,
199b36d8c09SArd Biesheuvel 		.setkey			= chacha20_setkey,
200b36d8c09SArd Biesheuvel 		.encrypt		= chacha_arm,
201b36d8c09SArd Biesheuvel 		.decrypt		= chacha_arm,
202b36d8c09SArd Biesheuvel 	}, {
203b36d8c09SArd Biesheuvel 		.base.cra_name		= "xchacha20",
204b36d8c09SArd Biesheuvel 		.base.cra_driver_name	= "xchacha20-arm",
205b36d8c09SArd Biesheuvel 		.base.cra_priority	= 200,
206b36d8c09SArd Biesheuvel 		.base.cra_blocksize	= 1,
207b36d8c09SArd Biesheuvel 		.base.cra_ctxsize	= sizeof(struct chacha_ctx),
208b36d8c09SArd Biesheuvel 		.base.cra_module	= THIS_MODULE,
209b36d8c09SArd Biesheuvel 
210b36d8c09SArd Biesheuvel 		.min_keysize		= CHACHA_KEY_SIZE,
211b36d8c09SArd Biesheuvel 		.max_keysize		= CHACHA_KEY_SIZE,
212b36d8c09SArd Biesheuvel 		.ivsize			= XCHACHA_IV_SIZE,
213b36d8c09SArd Biesheuvel 		.chunksize		= CHACHA_BLOCK_SIZE,
214b36d8c09SArd Biesheuvel 		.setkey			= chacha20_setkey,
215b36d8c09SArd Biesheuvel 		.encrypt		= xchacha_arm,
216b36d8c09SArd Biesheuvel 		.decrypt		= xchacha_arm,
217b36d8c09SArd Biesheuvel 	}, {
218b36d8c09SArd Biesheuvel 		.base.cra_name		= "xchacha12",
219b36d8c09SArd Biesheuvel 		.base.cra_driver_name	= "xchacha12-arm",
220b36d8c09SArd Biesheuvel 		.base.cra_priority	= 200,
221b36d8c09SArd Biesheuvel 		.base.cra_blocksize	= 1,
222b36d8c09SArd Biesheuvel 		.base.cra_ctxsize	= sizeof(struct chacha_ctx),
223b36d8c09SArd Biesheuvel 		.base.cra_module	= THIS_MODULE,
224b36d8c09SArd Biesheuvel 
225b36d8c09SArd Biesheuvel 		.min_keysize		= CHACHA_KEY_SIZE,
226b36d8c09SArd Biesheuvel 		.max_keysize		= CHACHA_KEY_SIZE,
227b36d8c09SArd Biesheuvel 		.ivsize			= XCHACHA_IV_SIZE,
228b36d8c09SArd Biesheuvel 		.chunksize		= CHACHA_BLOCK_SIZE,
229b36d8c09SArd Biesheuvel 		.setkey			= chacha12_setkey,
230b36d8c09SArd Biesheuvel 		.encrypt		= xchacha_arm,
231b36d8c09SArd Biesheuvel 		.decrypt		= xchacha_arm,
232b36d8c09SArd Biesheuvel 	},
233b36d8c09SArd Biesheuvel };
234b36d8c09SArd Biesheuvel 
235b36d8c09SArd Biesheuvel static struct skcipher_alg neon_algs[] = {
236b36d8c09SArd Biesheuvel 	{
237b36d8c09SArd Biesheuvel 		.base.cra_name		= "chacha20",
238b36d8c09SArd Biesheuvel 		.base.cra_driver_name	= "chacha20-neon",
239b36d8c09SArd Biesheuvel 		.base.cra_priority	= 300,
240b36d8c09SArd Biesheuvel 		.base.cra_blocksize	= 1,
241b36d8c09SArd Biesheuvel 		.base.cra_ctxsize	= sizeof(struct chacha_ctx),
242b36d8c09SArd Biesheuvel 		.base.cra_module	= THIS_MODULE,
243b36d8c09SArd Biesheuvel 
244b36d8c09SArd Biesheuvel 		.min_keysize		= CHACHA_KEY_SIZE,
245b36d8c09SArd Biesheuvel 		.max_keysize		= CHACHA_KEY_SIZE,
246b36d8c09SArd Biesheuvel 		.ivsize			= CHACHA_IV_SIZE,
247b36d8c09SArd Biesheuvel 		.chunksize		= CHACHA_BLOCK_SIZE,
248b36d8c09SArd Biesheuvel 		.walksize		= 4 * CHACHA_BLOCK_SIZE,
249b36d8c09SArd Biesheuvel 		.setkey			= chacha20_setkey,
250b36d8c09SArd Biesheuvel 		.encrypt		= chacha_neon,
251b36d8c09SArd Biesheuvel 		.decrypt		= chacha_neon,
252b36d8c09SArd Biesheuvel 	}, {
253b36d8c09SArd Biesheuvel 		.base.cra_name		= "xchacha20",
254b36d8c09SArd Biesheuvel 		.base.cra_driver_name	= "xchacha20-neon",
255b36d8c09SArd Biesheuvel 		.base.cra_priority	= 300,
256b36d8c09SArd Biesheuvel 		.base.cra_blocksize	= 1,
257b36d8c09SArd Biesheuvel 		.base.cra_ctxsize	= sizeof(struct chacha_ctx),
258b36d8c09SArd Biesheuvel 		.base.cra_module	= THIS_MODULE,
259b36d8c09SArd Biesheuvel 
260b36d8c09SArd Biesheuvel 		.min_keysize		= CHACHA_KEY_SIZE,
261b36d8c09SArd Biesheuvel 		.max_keysize		= CHACHA_KEY_SIZE,
262b36d8c09SArd Biesheuvel 		.ivsize			= XCHACHA_IV_SIZE,
263b36d8c09SArd Biesheuvel 		.chunksize		= CHACHA_BLOCK_SIZE,
264b36d8c09SArd Biesheuvel 		.walksize		= 4 * CHACHA_BLOCK_SIZE,
265b36d8c09SArd Biesheuvel 		.setkey			= chacha20_setkey,
266b36d8c09SArd Biesheuvel 		.encrypt		= xchacha_neon,
267b36d8c09SArd Biesheuvel 		.decrypt		= xchacha_neon,
268b36d8c09SArd Biesheuvel 	}, {
269b36d8c09SArd Biesheuvel 		.base.cra_name		= "xchacha12",
270b36d8c09SArd Biesheuvel 		.base.cra_driver_name	= "xchacha12-neon",
271b36d8c09SArd Biesheuvel 		.base.cra_priority	= 300,
272b36d8c09SArd Biesheuvel 		.base.cra_blocksize	= 1,
273b36d8c09SArd Biesheuvel 		.base.cra_ctxsize	= sizeof(struct chacha_ctx),
274b36d8c09SArd Biesheuvel 		.base.cra_module	= THIS_MODULE,
275b36d8c09SArd Biesheuvel 
276b36d8c09SArd Biesheuvel 		.min_keysize		= CHACHA_KEY_SIZE,
277b36d8c09SArd Biesheuvel 		.max_keysize		= CHACHA_KEY_SIZE,
278b36d8c09SArd Biesheuvel 		.ivsize			= XCHACHA_IV_SIZE,
279b36d8c09SArd Biesheuvel 		.chunksize		= CHACHA_BLOCK_SIZE,
280b36d8c09SArd Biesheuvel 		.walksize		= 4 * CHACHA_BLOCK_SIZE,
281b36d8c09SArd Biesheuvel 		.setkey			= chacha12_setkey,
282b36d8c09SArd Biesheuvel 		.encrypt		= xchacha_neon,
283b36d8c09SArd Biesheuvel 		.decrypt		= xchacha_neon,
284b36d8c09SArd Biesheuvel 	}
285b36d8c09SArd Biesheuvel };
286b36d8c09SArd Biesheuvel 
287b36d8c09SArd Biesheuvel static int __init chacha_simd_mod_init(void)
288b36d8c09SArd Biesheuvel {
289*8394bfecSJason A. Donenfeld 	int err = 0;
290b36d8c09SArd Biesheuvel 
291*8394bfecSJason A. Donenfeld 	if (IS_REACHABLE(CONFIG_CRYPTO_SKCIPHER)) {
292b36d8c09SArd Biesheuvel 		err = crypto_register_skciphers(arm_algs, ARRAY_SIZE(arm_algs));
293b36d8c09SArd Biesheuvel 		if (err)
294b36d8c09SArd Biesheuvel 			return err;
295*8394bfecSJason A. Donenfeld 	}
296b36d8c09SArd Biesheuvel 
297b36d8c09SArd Biesheuvel 	if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && (elf_hwcap & HWCAP_NEON)) {
298b36d8c09SArd Biesheuvel 		int i;
299b36d8c09SArd Biesheuvel 
300b36d8c09SArd Biesheuvel 		switch (read_cpuid_part()) {
301b36d8c09SArd Biesheuvel 		case ARM_CPU_PART_CORTEX_A7:
302b36d8c09SArd Biesheuvel 		case ARM_CPU_PART_CORTEX_A5:
303b36d8c09SArd Biesheuvel 			/*
304b36d8c09SArd Biesheuvel 			 * The Cortex-A7 and Cortex-A5 do not perform well with
305b36d8c09SArd Biesheuvel 			 * the NEON implementation but do incredibly with the
306b36d8c09SArd Biesheuvel 			 * scalar one and use less power.
307b36d8c09SArd Biesheuvel 			 */
308b36d8c09SArd Biesheuvel 			for (i = 0; i < ARRAY_SIZE(neon_algs); i++)
309b36d8c09SArd Biesheuvel 				neon_algs[i].base.cra_priority = 0;
310b36d8c09SArd Biesheuvel 			break;
311a44a3430SArd Biesheuvel 		default:
312a44a3430SArd Biesheuvel 			static_branch_enable(&use_neon);
313b36d8c09SArd Biesheuvel 		}
314b36d8c09SArd Biesheuvel 
315*8394bfecSJason A. Donenfeld 		if (IS_REACHABLE(CONFIG_CRYPTO_SKCIPHER)) {
316b36d8c09SArd Biesheuvel 			err = crypto_register_skciphers(neon_algs, ARRAY_SIZE(neon_algs));
317b36d8c09SArd Biesheuvel 			if (err)
318b36d8c09SArd Biesheuvel 				crypto_unregister_skciphers(arm_algs, ARRAY_SIZE(arm_algs));
319b36d8c09SArd Biesheuvel 		}
320*8394bfecSJason A. Donenfeld 	}
321b36d8c09SArd Biesheuvel 	return err;
322b36d8c09SArd Biesheuvel }
323b36d8c09SArd Biesheuvel 
324b36d8c09SArd Biesheuvel static void __exit chacha_simd_mod_fini(void)
325b36d8c09SArd Biesheuvel {
326*8394bfecSJason A. Donenfeld 	if (IS_REACHABLE(CONFIG_CRYPTO_SKCIPHER)) {
327b36d8c09SArd Biesheuvel 		crypto_unregister_skciphers(arm_algs, ARRAY_SIZE(arm_algs));
328b36d8c09SArd Biesheuvel 		if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && (elf_hwcap & HWCAP_NEON))
329b36d8c09SArd Biesheuvel 			crypto_unregister_skciphers(neon_algs, ARRAY_SIZE(neon_algs));
330b36d8c09SArd Biesheuvel 	}
331*8394bfecSJason A. Donenfeld }
332b36d8c09SArd Biesheuvel 
333b36d8c09SArd Biesheuvel module_init(chacha_simd_mod_init);
334b36d8c09SArd Biesheuvel module_exit(chacha_simd_mod_fini);
335b36d8c09SArd Biesheuvel 
336b36d8c09SArd Biesheuvel MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (scalar and NEON accelerated)");
337b36d8c09SArd Biesheuvel MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
338b36d8c09SArd Biesheuvel MODULE_LICENSE("GPL v2");
339b36d8c09SArd Biesheuvel MODULE_ALIAS_CRYPTO("chacha20");
340b36d8c09SArd Biesheuvel MODULE_ALIAS_CRYPTO("chacha20-arm");
341b36d8c09SArd Biesheuvel MODULE_ALIAS_CRYPTO("xchacha20");
342b36d8c09SArd Biesheuvel MODULE_ALIAS_CRYPTO("xchacha20-arm");
343b36d8c09SArd Biesheuvel MODULE_ALIAS_CRYPTO("xchacha12");
344b36d8c09SArd Biesheuvel MODULE_ALIAS_CRYPTO("xchacha12-arm");
345b36d8c09SArd Biesheuvel #ifdef CONFIG_KERNEL_MODE_NEON
346b36d8c09SArd Biesheuvel MODULE_ALIAS_CRYPTO("chacha20-neon");
347b36d8c09SArd Biesheuvel MODULE_ALIAS_CRYPTO("xchacha20-neon");
348b36d8c09SArd Biesheuvel MODULE_ALIAS_CRYPTO("xchacha12-neon");
349b36d8c09SArd Biesheuvel #endif
350