summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-09-19 04:02:01 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2018-09-20 00:57:59 +0200
commitcc2113b5b27c7ee45711df05c49a7d05bd0a934e (patch)
tree8aae932419bbc43aabbcb39fda208fe37c19c9cf /src
parentafdd509ad206e0a3858118ac4c26fbc709af3562 (diff)
chacha20: prefer crypto_xor_cpy to avoid memmove
Suggested-by: Eric Biggers <ebiggers@kernel.org> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'src')
-rw-r--r--src/compat/compat.h28
-rw-r--r--src/crypto/zinc/chacha20/chacha20.c8
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 <crypto/algapi.h>
+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 <linux/ip.h>
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);
}
}