From cc2113b5b27c7ee45711df05c49a7d05bd0a934e Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 19 Sep 2018 04:02:01 +0200 Subject: chacha20: prefer crypto_xor_cpy to avoid memmove Suggested-by: Eric Biggers Signed-off-by: Jason A. Donenfeld --- src/compat/compat.h | 28 ++++++++++++++++++++++++++++ src/crypto/zinc/chacha20/chacha20.c | 8 +++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/compat/compat.h b/src/compat/compat.h index c182234..58d16b1 100644 --- a/src/compat/compat.h +++ b/src/compat/compat.h @@ -698,6 +698,34 @@ static inline void cpu_to_le32_array(u32 *buf, unsigned int words) } #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 14, 0) +#include +static inline void crypto_xor_cpy(u8 *dst, const u8 *src1, const u8 *src2, + unsigned int size) +{ + if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && + __builtin_constant_p(size) && + (size % sizeof(unsigned long)) == 0) { + unsigned long *d = (unsigned long *)dst; + unsigned long *s1 = (unsigned long *)src1; + unsigned long *s2 = (unsigned long *)src2; + + while (size > 0) { + *d++ = *s1++ ^ *s2++; + size -= sizeof(unsigned long); + } + } else { + if (unlikely(dst != src1)) + memmove(dst, src1, size); +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) + crypto_xor(dst, src2, size); +#else + __crypto_xor(dst, src2, size); +#endif + } +} +#endif + /* https://lkml.kernel.org/r/20170624021727.17835-1-Jason@zx2c4.com */ #if IS_ENABLED(CONFIG_NF_CONNTRACK) #include diff --git a/src/crypto/zinc/chacha20/chacha20.c b/src/crypto/zinc/chacha20/chacha20.c index a7c7adc..72e24da 100644 --- a/src/crypto/zinc/chacha20/chacha20.c +++ b/src/crypto/zinc/chacha20/chacha20.c @@ -105,18 +105,16 @@ static void chacha20_generic(u8 *out, const u8 *in, u32 len, const u32 key[8], counter[0], counter[1], counter[2], counter[3] }; - if (out != in) - memmove(out, in, len); - while (len >= CHACHA20_BLOCK_SIZE) { chacha20_block_generic(buf, x); - crypto_xor(out, (u8 *)buf, CHACHA20_BLOCK_SIZE); + crypto_xor_cpy(out, in, (u8 *)buf, CHACHA20_BLOCK_SIZE); len -= CHACHA20_BLOCK_SIZE; out += CHACHA20_BLOCK_SIZE; + in += CHACHA20_BLOCK_SIZE; } if (len) { chacha20_block_generic(buf, x); - crypto_xor(out, (u8 *)buf, len); + crypto_xor_cpy(out, in, (u8 *)buf, len); } } -- cgit v1.2.3