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