diff options
Diffstat (limited to 'target/linux/generic/backport-5.4/080-wireguard-0003-crypto-x86-chacha-depend-on-generic-chacha-library-i.patch')
-rw-r--r-- | target/linux/generic/backport-5.4/080-wireguard-0003-crypto-x86-chacha-depend-on-generic-chacha-library-i.patch | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/target/linux/generic/backport-5.4/080-wireguard-0003-crypto-x86-chacha-depend-on-generic-chacha-library-i.patch b/target/linux/generic/backport-5.4/080-wireguard-0003-crypto-x86-chacha-depend-on-generic-chacha-library-i.patch new file mode 100644 index 0000000000..b1f59cc38f --- /dev/null +++ b/target/linux/generic/backport-5.4/080-wireguard-0003-crypto-x86-chacha-depend-on-generic-chacha-library-i.patch @@ -0,0 +1,192 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ard Biesheuvel <ardb@kernel.org> +Date: Fri, 8 Nov 2019 13:22:09 +0100 +Subject: [PATCH] crypto: x86/chacha - depend on generic chacha library instead + of crypto driver + +commit 28e8d89b1ce8d2e7badfb5f69971dd635acb8863 upstream. + +In preparation of extending the x86 ChaCha driver to also expose the ChaCha +library interface, drop the dependency on the chacha_generic crypto driver +as a non-SIMD fallback, and depend on the generic ChaCha library directly. +This way, we only pull in the code we actually need, without registering +a set of ChaCha skciphers that we will never use. + +Since turning the FPU on and off is cheap these days, simplify the SIMD +routine by dropping the per-page yield, which makes for a cleaner switch +to the library API as well. This also allows use to invoke the skcipher +walk routines in non-atomic mode. + +Signed-off-by: Ard Biesheuvel <ardb@kernel.org> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> +--- + arch/x86/crypto/chacha_glue.c | 90 ++++++++++++++--------------------- + crypto/Kconfig | 2 +- + 2 files changed, 36 insertions(+), 56 deletions(-) + +--- a/arch/x86/crypto/chacha_glue.c ++++ b/arch/x86/crypto/chacha_glue.c +@@ -123,37 +123,38 @@ static void chacha_dosimd(u32 *state, u8 + } + } + +-static int chacha_simd_stream_xor(struct skcipher_walk *walk, ++static int chacha_simd_stream_xor(struct skcipher_request *req, + const struct chacha_ctx *ctx, const u8 *iv) + { + u32 *state, state_buf[16 + 2] __aligned(8); +- int next_yield = 4096; /* bytes until next FPU yield */ +- int err = 0; ++ struct skcipher_walk walk; ++ int err; ++ ++ err = skcipher_walk_virt(&walk, req, false); + + BUILD_BUG_ON(CHACHA_STATE_ALIGN != 16); + state = PTR_ALIGN(state_buf + 0, CHACHA_STATE_ALIGN); + +- crypto_chacha_init(state, ctx, iv); ++ chacha_init_generic(state, ctx->key, iv); + +- while (walk->nbytes > 0) { +- unsigned int nbytes = walk->nbytes; ++ while (walk.nbytes > 0) { ++ unsigned int nbytes = walk.nbytes; + +- if (nbytes < walk->total) { +- nbytes = round_down(nbytes, walk->stride); +- next_yield -= nbytes; +- } +- +- chacha_dosimd(state, walk->dst.virt.addr, walk->src.virt.addr, +- nbytes, ctx->nrounds); ++ if (nbytes < walk.total) ++ nbytes = round_down(nbytes, walk.stride); + +- if (next_yield <= 0) { +- /* temporarily allow preemption */ +- kernel_fpu_end(); ++ if (!crypto_simd_usable()) { ++ chacha_crypt_generic(state, walk.dst.virt.addr, ++ walk.src.virt.addr, nbytes, ++ ctx->nrounds); ++ } else { + kernel_fpu_begin(); +- next_yield = 4096; ++ chacha_dosimd(state, walk.dst.virt.addr, ++ walk.src.virt.addr, nbytes, ++ ctx->nrounds); ++ kernel_fpu_end(); + } +- +- err = skcipher_walk_done(walk, walk->nbytes - nbytes); ++ err = skcipher_walk_done(&walk, walk.nbytes - nbytes); + } + + return err; +@@ -163,55 +164,34 @@ static int chacha_simd(struct skcipher_r + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm); +- struct skcipher_walk walk; +- int err; +- +- if (req->cryptlen <= CHACHA_BLOCK_SIZE || !crypto_simd_usable()) +- return crypto_chacha_crypt(req); + +- err = skcipher_walk_virt(&walk, req, true); +- if (err) +- return err; +- +- kernel_fpu_begin(); +- err = chacha_simd_stream_xor(&walk, ctx, req->iv); +- kernel_fpu_end(); +- return err; ++ return chacha_simd_stream_xor(req, ctx, req->iv); + } + + static int xchacha_simd(struct skcipher_request *req) + { + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct chacha_ctx *ctx = crypto_skcipher_ctx(tfm); +- struct skcipher_walk walk; +- struct chacha_ctx subctx; + u32 *state, state_buf[16 + 2] __aligned(8); ++ struct chacha_ctx subctx; + u8 real_iv[16]; +- int err; +- +- if (req->cryptlen <= CHACHA_BLOCK_SIZE || !crypto_simd_usable()) +- return crypto_xchacha_crypt(req); +- +- err = skcipher_walk_virt(&walk, req, true); +- if (err) +- return err; + + BUILD_BUG_ON(CHACHA_STATE_ALIGN != 16); + state = PTR_ALIGN(state_buf + 0, CHACHA_STATE_ALIGN); +- crypto_chacha_init(state, ctx, req->iv); ++ chacha_init_generic(state, ctx->key, req->iv); + +- kernel_fpu_begin(); +- +- hchacha_block_ssse3(state, subctx.key, ctx->nrounds); ++ if (req->cryptlen > CHACHA_BLOCK_SIZE && crypto_simd_usable()) { ++ kernel_fpu_begin(); ++ hchacha_block_ssse3(state, subctx.key, ctx->nrounds); ++ kernel_fpu_end(); ++ } else { ++ hchacha_block_generic(state, subctx.key, ctx->nrounds); ++ } + subctx.nrounds = ctx->nrounds; + + memcpy(&real_iv[0], req->iv + 24, 8); + memcpy(&real_iv[8], req->iv + 16, 8); +- err = chacha_simd_stream_xor(&walk, &subctx, real_iv); +- +- kernel_fpu_end(); +- +- return err; ++ return chacha_simd_stream_xor(req, &subctx, real_iv); + } + + static struct skcipher_alg algs[] = { +@@ -227,7 +207,7 @@ static struct skcipher_alg algs[] = { + .max_keysize = CHACHA_KEY_SIZE, + .ivsize = CHACHA_IV_SIZE, + .chunksize = CHACHA_BLOCK_SIZE, +- .setkey = crypto_chacha20_setkey, ++ .setkey = chacha20_setkey, + .encrypt = chacha_simd, + .decrypt = chacha_simd, + }, { +@@ -242,7 +222,7 @@ static struct skcipher_alg algs[] = { + .max_keysize = CHACHA_KEY_SIZE, + .ivsize = XCHACHA_IV_SIZE, + .chunksize = CHACHA_BLOCK_SIZE, +- .setkey = crypto_chacha20_setkey, ++ .setkey = chacha20_setkey, + .encrypt = xchacha_simd, + .decrypt = xchacha_simd, + }, { +@@ -257,7 +237,7 @@ static struct skcipher_alg algs[] = { + .max_keysize = CHACHA_KEY_SIZE, + .ivsize = XCHACHA_IV_SIZE, + .chunksize = CHACHA_BLOCK_SIZE, +- .setkey = crypto_chacha12_setkey, ++ .setkey = chacha12_setkey, + .encrypt = xchacha_simd, + .decrypt = xchacha_simd, + }, +--- a/crypto/Kconfig ++++ b/crypto/Kconfig +@@ -1417,7 +1417,7 @@ config CRYPTO_CHACHA20_X86_64 + tristate "ChaCha stream cipher algorithms (x86_64/SSSE3/AVX2/AVX-512VL)" + depends on X86 && 64BIT + select CRYPTO_BLKCIPHER +- select CRYPTO_CHACHA20 ++ select CRYPTO_LIB_CHACHA_GENERIC + help + SSSE3, AVX2, and AVX-512VL optimized implementations of the ChaCha20, + XChaCha20, and XChaCha12 stream ciphers. |