aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-5.4/080-wireguard-0015-crypto-poly1305-expose-init-update-final-library-int.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/backport-5.4/080-wireguard-0015-crypto-poly1305-expose-init-update-final-library-int.patch')
-rw-r--r--target/linux/generic/backport-5.4/080-wireguard-0015-crypto-poly1305-expose-init-update-final-library-int.patch225
1 files changed, 225 insertions, 0 deletions
diff --git a/target/linux/generic/backport-5.4/080-wireguard-0015-crypto-poly1305-expose-init-update-final-library-int.patch b/target/linux/generic/backport-5.4/080-wireguard-0015-crypto-poly1305-expose-init-update-final-library-int.patch
new file mode 100644
index 0000000000..66c276267c
--- /dev/null
+++ b/target/linux/generic/backport-5.4/080-wireguard-0015-crypto-poly1305-expose-init-update-final-library-int.patch
@@ -0,0 +1,225 @@
+From fd966ddf025b8b62aab20d2e4eb242fe51ad5137 Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Fri, 8 Nov 2019 13:22:21 +0100
+Subject: [PATCH 015/124] crypto: poly1305 - expose init/update/final library
+ interface
+
+commit a1d93064094cc5e24d64e35cf093e7191d0c9344 upstream.
+
+Expose the existing generic Poly1305 code via a init/update/final
+library interface so that callers are not required to go through
+the crypto API's shash abstraction to access it. At the same time,
+make some preparations so that the library implementation can be
+superseded by an accelerated arch-specific version in the future.
+
+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>
+---
+ crypto/poly1305_generic.c | 22 +-----------
+ include/crypto/poly1305.h | 38 +++++++++++++++++++-
+ lib/crypto/Kconfig | 26 ++++++++++++++
+ lib/crypto/poly1305.c | 74 +++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 138 insertions(+), 22 deletions(-)
+
+--- a/crypto/poly1305_generic.c
++++ b/crypto/poly1305_generic.c
+@@ -85,31 +85,11 @@ EXPORT_SYMBOL_GPL(crypto_poly1305_update
+ int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
+ {
+ struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
+- __le32 digest[4];
+- u64 f = 0;
+
+ if (unlikely(!dctx->sset))
+ return -ENOKEY;
+
+- if (unlikely(dctx->buflen)) {
+- dctx->buf[dctx->buflen++] = 1;
+- memset(dctx->buf + dctx->buflen, 0,
+- POLY1305_BLOCK_SIZE - dctx->buflen);
+- poly1305_core_blocks(&dctx->h, dctx->r, dctx->buf, 1, 0);
+- }
+-
+- poly1305_core_emit(&dctx->h, digest);
+-
+- /* mac = (h + s) % (2^128) */
+- f = (f >> 32) + le32_to_cpu(digest[0]) + dctx->s[0];
+- put_unaligned_le32(f, dst + 0);
+- f = (f >> 32) + le32_to_cpu(digest[1]) + dctx->s[1];
+- put_unaligned_le32(f, dst + 4);
+- f = (f >> 32) + le32_to_cpu(digest[2]) + dctx->s[2];
+- put_unaligned_le32(f, dst + 8);
+- f = (f >> 32) + le32_to_cpu(digest[3]) + dctx->s[3];
+- put_unaligned_le32(f, dst + 12);
+-
++ poly1305_final_generic(dctx, dst);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(crypto_poly1305_final);
+--- a/include/crypto/poly1305.h
++++ b/include/crypto/poly1305.h
+@@ -35,7 +35,43 @@ struct poly1305_desc_ctx {
+ /* accumulator */
+ struct poly1305_state h;
+ /* key */
+- struct poly1305_key r[1];
++ struct poly1305_key r[CONFIG_CRYPTO_LIB_POLY1305_RSIZE];
+ };
+
++void poly1305_init_arch(struct poly1305_desc_ctx *desc, const u8 *key);
++void poly1305_init_generic(struct poly1305_desc_ctx *desc, const u8 *key);
++
++static inline void poly1305_init(struct poly1305_desc_ctx *desc, const u8 *key)
++{
++ if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305))
++ poly1305_init_arch(desc, key);
++ else
++ poly1305_init_generic(desc, key);
++}
++
++void poly1305_update_arch(struct poly1305_desc_ctx *desc, const u8 *src,
++ unsigned int nbytes);
++void poly1305_update_generic(struct poly1305_desc_ctx *desc, const u8 *src,
++ unsigned int nbytes);
++
++static inline void poly1305_update(struct poly1305_desc_ctx *desc,
++ const u8 *src, unsigned int nbytes)
++{
++ if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305))
++ poly1305_update_arch(desc, src, nbytes);
++ else
++ poly1305_update_generic(desc, src, nbytes);
++}
++
++void poly1305_final_arch(struct poly1305_desc_ctx *desc, u8 *digest);
++void poly1305_final_generic(struct poly1305_desc_ctx *desc, u8 *digest);
++
++static inline void poly1305_final(struct poly1305_desc_ctx *desc, u8 *digest)
++{
++ if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_POLY1305))
++ poly1305_final_arch(desc, digest);
++ else
++ poly1305_final_generic(desc, digest);
++}
++
+ #endif
+--- a/lib/crypto/Kconfig
++++ b/lib/crypto/Kconfig
+@@ -37,8 +37,34 @@ config CRYPTO_LIB_CHACHA
+ config CRYPTO_LIB_DES
+ tristate
+
++config CRYPTO_LIB_POLY1305_RSIZE
++ int
++ default 1
++
++config CRYPTO_ARCH_HAVE_LIB_POLY1305
++ tristate
++ help
++ Declares whether the architecture provides an arch-specific
++ accelerated implementation of the Poly1305 library interface,
++ either builtin or as a module.
++
+ config CRYPTO_LIB_POLY1305_GENERIC
+ tristate
++ help
++ This symbol can be depended upon by arch implementations of the
++ Poly1305 library interface that require the generic code as a
++ fallback, e.g., for SIMD implementations. If no arch specific
++ implementation is enabled, this implementation serves the users
++ of CRYPTO_LIB_POLY1305.
++
++config CRYPTO_LIB_POLY1305
++ tristate "Poly1305 library interface"
++ depends on CRYPTO_ARCH_HAVE_LIB_POLY1305 || !CRYPTO_ARCH_HAVE_LIB_POLY1305
++ select CRYPTO_LIB_POLY1305_GENERIC if CRYPTO_ARCH_HAVE_LIB_POLY1305=n
++ help
++ Enable the Poly1305 library interface. This interface may be fulfilled
++ by either the generic implementation or an arch-specific one, if one
++ is available and enabled.
+
+ config CRYPTO_LIB_SHA256
+ tristate
+--- a/lib/crypto/poly1305.c
++++ b/lib/crypto/poly1305.c
+@@ -154,5 +154,79 @@ void poly1305_core_emit(const struct pol
+ }
+ EXPORT_SYMBOL_GPL(poly1305_core_emit);
+
++void poly1305_init_generic(struct poly1305_desc_ctx *desc, const u8 *key)
++{
++ poly1305_core_setkey(desc->r, key);
++ desc->s[0] = get_unaligned_le32(key + 16);
++ desc->s[1] = get_unaligned_le32(key + 20);
++ desc->s[2] = get_unaligned_le32(key + 24);
++ desc->s[3] = get_unaligned_le32(key + 28);
++ poly1305_core_init(&desc->h);
++ desc->buflen = 0;
++ desc->sset = true;
++ desc->rset = 1;
++}
++EXPORT_SYMBOL_GPL(poly1305_init_generic);
++
++void poly1305_update_generic(struct poly1305_desc_ctx *desc, const u8 *src,
++ unsigned int nbytes)
++{
++ unsigned int bytes;
++
++ if (unlikely(desc->buflen)) {
++ bytes = min(nbytes, POLY1305_BLOCK_SIZE - desc->buflen);
++ memcpy(desc->buf + desc->buflen, src, bytes);
++ src += bytes;
++ nbytes -= bytes;
++ desc->buflen += bytes;
++
++ if (desc->buflen == POLY1305_BLOCK_SIZE) {
++ poly1305_core_blocks(&desc->h, desc->r, desc->buf, 1, 1);
++ desc->buflen = 0;
++ }
++ }
++
++ if (likely(nbytes >= POLY1305_BLOCK_SIZE)) {
++ poly1305_core_blocks(&desc->h, desc->r, src,
++ nbytes / POLY1305_BLOCK_SIZE, 1);
++ src += nbytes - (nbytes % POLY1305_BLOCK_SIZE);
++ nbytes %= POLY1305_BLOCK_SIZE;
++ }
++
++ if (unlikely(nbytes)) {
++ desc->buflen = nbytes;
++ memcpy(desc->buf, src, nbytes);
++ }
++}
++EXPORT_SYMBOL_GPL(poly1305_update_generic);
++
++void poly1305_final_generic(struct poly1305_desc_ctx *desc, u8 *dst)
++{
++ __le32 digest[4];
++ u64 f = 0;
++
++ if (unlikely(desc->buflen)) {
++ desc->buf[desc->buflen++] = 1;
++ memset(desc->buf + desc->buflen, 0,
++ POLY1305_BLOCK_SIZE - desc->buflen);
++ poly1305_core_blocks(&desc->h, desc->r, desc->buf, 1, 0);
++ }
++
++ poly1305_core_emit(&desc->h, digest);
++
++ /* mac = (h + s) % (2^128) */
++ f = (f >> 32) + le32_to_cpu(digest[0]) + desc->s[0];
++ put_unaligned_le32(f, dst + 0);
++ f = (f >> 32) + le32_to_cpu(digest[1]) + desc->s[1];
++ put_unaligned_le32(f, dst + 4);
++ f = (f >> 32) + le32_to_cpu(digest[2]) + desc->s[2];
++ put_unaligned_le32(f, dst + 8);
++ f = (f >> 32) + le32_to_cpu(digest[3]) + desc->s[3];
++ put_unaligned_le32(f, dst + 12);
++
++ *desc = (struct poly1305_desc_ctx){};
++}
++EXPORT_SYMBOL_GPL(poly1305_final_generic);
++
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");