| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Ard Biesheuvel <ardb@kernel.org> |
| Date: Fri, 8 Nov 2019 13:22:21 +0100 |
| Subject: [PATCH] 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>"); |