| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: "Jason A. Donenfeld" <Jason@zx2c4.com> |
| Date: Thu, 23 Apr 2020 15:54:04 -0600 |
| Subject: [PATCH] crypto: arch/lib - limit simd usage to 4k chunks |
| |
| commit 706024a52c614b478b63f7728d202532ce6591a9 upstream. |
| |
| The initial Zinc patchset, after some mailing list discussion, contained |
| code to ensure that kernel_fpu_enable would not be kept on for more than |
| a 4k chunk, since it disables preemption. The choice of 4k isn't totally |
| scientific, but it's not a bad guess either, and it's what's used in |
| both the x86 poly1305, blake2s, and nhpoly1305 code already (in the form |
| of PAGE_SIZE, which this commit corrects to be explicitly 4k for the |
| former two). |
| |
| Ard did some back of the envelope calculations and found that |
| at 5 cycles/byte (overestimate) on a 1ghz processor (pretty slow), 4k |
| means we have a maximum preemption disabling of 20us, which Sebastian |
| confirmed was probably a good limit. |
| |
| Unfortunately the chunking appears to have been left out of the final |
| patchset that added the glue code. So, this commit adds it back in. |
| |
| Fixes: 84e03fa39fbe ("crypto: x86/chacha - expose SIMD ChaCha routine as library function") |
| Fixes: b3aad5bad26a ("crypto: arm64/chacha - expose arm64 ChaCha routine as library function") |
| Fixes: a44a3430d71b ("crypto: arm/chacha - expose ARM ChaCha routine as library function") |
| Fixes: d7d7b8535662 ("crypto: x86/poly1305 - wire up faster implementations for kernel") |
| Fixes: f569ca164751 ("crypto: arm64/poly1305 - incorporate OpenSSL/CRYPTOGAMS NEON implementation") |
| Fixes: a6b803b3ddc7 ("crypto: arm/poly1305 - incorporate OpenSSL/CRYPTOGAMS NEON implementation") |
| Fixes: ed0356eda153 ("crypto: blake2s - x86_64 SIMD implementation") |
| Cc: Eric Biggers <ebiggers@google.com> |
| Cc: Ard Biesheuvel <ardb@kernel.org> |
| Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com> |
| Reviewed-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/arm/crypto/chacha-glue.c | 14 +++++++++++--- |
| arch/arm/crypto/poly1305-glue.c | 15 +++++++++++---- |
| arch/arm64/crypto/chacha-neon-glue.c | 14 +++++++++++--- |
| arch/arm64/crypto/poly1305-glue.c | 15 +++++++++++---- |
| arch/x86/crypto/blake2s-glue.c | 10 ++++------ |
| arch/x86/crypto/chacha_glue.c | 14 +++++++++++--- |
| arch/x86/crypto/poly1305_glue.c | 13 ++++++------- |
| 7 files changed, 65 insertions(+), 30 deletions(-) |
| |
| --- a/arch/arm/crypto/chacha-glue.c |
| +++ b/arch/arm/crypto/chacha-glue.c |
| @@ -91,9 +91,17 @@ void chacha_crypt_arch(u32 *state, u8 *d |
| return; |
| } |
| |
| - kernel_neon_begin(); |
| - chacha_doneon(state, dst, src, bytes, nrounds); |
| - kernel_neon_end(); |
| + do { |
| + unsigned int todo = min_t(unsigned int, bytes, SZ_4K); |
| + |
| + kernel_neon_begin(); |
| + chacha_doneon(state, dst, src, todo, nrounds); |
| + kernel_neon_end(); |
| + |
| + bytes -= todo; |
| + src += todo; |
| + dst += todo; |
| + } while (bytes); |
| } |
| EXPORT_SYMBOL(chacha_crypt_arch); |
| |
| --- a/arch/arm/crypto/poly1305-glue.c |
| +++ b/arch/arm/crypto/poly1305-glue.c |
| @@ -160,13 +160,20 @@ void poly1305_update_arch(struct poly130 |
| unsigned int len = round_down(nbytes, POLY1305_BLOCK_SIZE); |
| |
| if (static_branch_likely(&have_neon) && do_neon) { |
| - kernel_neon_begin(); |
| - poly1305_blocks_neon(&dctx->h, src, len, 1); |
| - kernel_neon_end(); |
| + do { |
| + unsigned int todo = min_t(unsigned int, len, SZ_4K); |
| + |
| + kernel_neon_begin(); |
| + poly1305_blocks_neon(&dctx->h, src, todo, 1); |
| + kernel_neon_end(); |
| + |
| + len -= todo; |
| + src += todo; |
| + } while (len); |
| } else { |
| poly1305_blocks_arm(&dctx->h, src, len, 1); |
| + src += len; |
| } |
| - src += len; |
| nbytes %= POLY1305_BLOCK_SIZE; |
| } |
| |
| --- a/arch/arm64/crypto/chacha-neon-glue.c |
| +++ b/arch/arm64/crypto/chacha-neon-glue.c |
| @@ -87,9 +87,17 @@ void chacha_crypt_arch(u32 *state, u8 *d |
| !crypto_simd_usable()) |
| return chacha_crypt_generic(state, dst, src, bytes, nrounds); |
| |
| - kernel_neon_begin(); |
| - chacha_doneon(state, dst, src, bytes, nrounds); |
| - kernel_neon_end(); |
| + do { |
| + unsigned int todo = min_t(unsigned int, bytes, SZ_4K); |
| + |
| + kernel_neon_begin(); |
| + chacha_doneon(state, dst, src, todo, nrounds); |
| + kernel_neon_end(); |
| + |
| + bytes -= todo; |
| + src += todo; |
| + dst += todo; |
| + } while (bytes); |
| } |
| EXPORT_SYMBOL(chacha_crypt_arch); |
| |
| --- a/arch/arm64/crypto/poly1305-glue.c |
| +++ b/arch/arm64/crypto/poly1305-glue.c |
| @@ -143,13 +143,20 @@ void poly1305_update_arch(struct poly130 |
| unsigned int len = round_down(nbytes, POLY1305_BLOCK_SIZE); |
| |
| if (static_branch_likely(&have_neon) && crypto_simd_usable()) { |
| - kernel_neon_begin(); |
| - poly1305_blocks_neon(&dctx->h, src, len, 1); |
| - kernel_neon_end(); |
| + do { |
| + unsigned int todo = min_t(unsigned int, len, SZ_4K); |
| + |
| + kernel_neon_begin(); |
| + poly1305_blocks_neon(&dctx->h, src, todo, 1); |
| + kernel_neon_end(); |
| + |
| + len -= todo; |
| + src += todo; |
| + } while (len); |
| } else { |
| poly1305_blocks(&dctx->h, src, len, 1); |
| + src += len; |
| } |
| - src += len; |
| nbytes %= POLY1305_BLOCK_SIZE; |
| } |
| |
| --- a/arch/x86/crypto/blake2s-glue.c |
| +++ b/arch/x86/crypto/blake2s-glue.c |
| @@ -32,16 +32,16 @@ void blake2s_compress_arch(struct blake2 |
| const u32 inc) |
| { |
| /* SIMD disables preemption, so relax after processing each page. */ |
| - BUILD_BUG_ON(PAGE_SIZE / BLAKE2S_BLOCK_SIZE < 8); |
| + BUILD_BUG_ON(SZ_4K / BLAKE2S_BLOCK_SIZE < 8); |
| |
| if (!static_branch_likely(&blake2s_use_ssse3) || !crypto_simd_usable()) { |
| blake2s_compress_generic(state, block, nblocks, inc); |
| return; |
| } |
| |
| - for (;;) { |
| + do { |
| const size_t blocks = min_t(size_t, nblocks, |
| - PAGE_SIZE / BLAKE2S_BLOCK_SIZE); |
| + SZ_4K / BLAKE2S_BLOCK_SIZE); |
| |
| kernel_fpu_begin(); |
| if (IS_ENABLED(CONFIG_AS_AVX512) && |
| @@ -52,10 +52,8 @@ void blake2s_compress_arch(struct blake2 |
| kernel_fpu_end(); |
| |
| nblocks -= blocks; |
| - if (!nblocks) |
| - break; |
| block += blocks * BLAKE2S_BLOCK_SIZE; |
| - } |
| + } while (nblocks); |
| } |
| EXPORT_SYMBOL(blake2s_compress_arch); |
| |
| --- a/arch/x86/crypto/chacha_glue.c |
| +++ b/arch/x86/crypto/chacha_glue.c |
| @@ -154,9 +154,17 @@ void chacha_crypt_arch(u32 *state, u8 *d |
| bytes <= CHACHA_BLOCK_SIZE) |
| return chacha_crypt_generic(state, dst, src, bytes, nrounds); |
| |
| - kernel_fpu_begin(); |
| - chacha_dosimd(state, dst, src, bytes, nrounds); |
| - kernel_fpu_end(); |
| + do { |
| + unsigned int todo = min_t(unsigned int, bytes, SZ_4K); |
| + |
| + kernel_fpu_begin(); |
| + chacha_dosimd(state, dst, src, todo, nrounds); |
| + kernel_fpu_end(); |
| + |
| + bytes -= todo; |
| + src += todo; |
| + dst += todo; |
| + } while (bytes); |
| } |
| EXPORT_SYMBOL(chacha_crypt_arch); |
| |
| --- a/arch/x86/crypto/poly1305_glue.c |
| +++ b/arch/x86/crypto/poly1305_glue.c |
| @@ -91,8 +91,8 @@ static void poly1305_simd_blocks(void *c |
| struct poly1305_arch_internal *state = ctx; |
| |
| /* SIMD disables preemption, so relax after processing each page. */ |
| - BUILD_BUG_ON(PAGE_SIZE < POLY1305_BLOCK_SIZE || |
| - PAGE_SIZE % POLY1305_BLOCK_SIZE); |
| + BUILD_BUG_ON(SZ_4K < POLY1305_BLOCK_SIZE || |
| + SZ_4K % POLY1305_BLOCK_SIZE); |
| |
| if (!IS_ENABLED(CONFIG_AS_AVX) || !static_branch_likely(&poly1305_use_avx) || |
| (len < (POLY1305_BLOCK_SIZE * 18) && !state->is_base2_26) || |
| @@ -102,8 +102,8 @@ static void poly1305_simd_blocks(void *c |
| return; |
| } |
| |
| - for (;;) { |
| - const size_t bytes = min_t(size_t, len, PAGE_SIZE); |
| + do { |
| + const size_t bytes = min_t(size_t, len, SZ_4K); |
| |
| kernel_fpu_begin(); |
| if (IS_ENABLED(CONFIG_AS_AVX512) && static_branch_likely(&poly1305_use_avx512)) |
| @@ -113,11 +113,10 @@ static void poly1305_simd_blocks(void *c |
| else |
| poly1305_blocks_avx(ctx, inp, bytes, padbit); |
| kernel_fpu_end(); |
| + |
| len -= bytes; |
| - if (!len) |
| - break; |
| inp += bytes; |
| - } |
| + } while (len); |
| } |
| |
| static void poly1305_simd_emit(void *ctx, u8 mac[POLY1305_DIGEST_SIZE], |