[PATCH v3 05/14] crypto: blake2s - share the "shash" API boilerplate code

Ard Biesheuvel ardb at kernel.org
Wed Dec 23 04:06:03 EST 2020


On Wed, 23 Dec 2020 at 09:12, Eric Biggers <ebiggers at kernel.org> wrote:
>
> From: Eric Biggers <ebiggers at google.com>
>
> Add helper functions for shash implementations of BLAKE2s to
> include/crypto/internal/blake2s.h, taking advantage of
> __blake2s_update() and __blake2s_final() that were added by the previous
> patch to share more code between the library and shash implementations.
>
> crypto_blake2s_setkey() and crypto_blake2s_init() are usable as
> shash_alg::setkey and shash_alg::init directly, while
> crypto_blake2s_update() and crypto_blake2s_final() take an extra
> 'blake2s_compress_t' function pointer parameter.  This allows the
> implementation of the compression function to be overridden, which is
> the only part that optimized implementations really care about.
>
> The new functions are inline functions (similar to those in sha1_base.h,
> sha256_base.h, and sm3_base.h) because this avoids needing to add a new
> module blake2s_helpers.ko, they aren't *too* long, and this avoids
> indirect calls which are expensive these days.  Note that they can't go
> in blake2s_generic.ko, as that would require selecting CRYPTO_BLAKE2S
> from CRYPTO_BLAKE2S_X86, which would cause a recursive dependency.
>
> Finally, use these new helper functions in the x86 implementation of
> BLAKE2s.  (This part should be a separate patch, but unfortunately the
> x86 implementation used the exact same function names like
> "crypto_blake2s_update()", so it had to be updated at the same time.)
>
> Signed-off-by: Eric Biggers <ebiggers at google.com>

Acked-by: Ard Biesheuvel <ardb at kernel.org>

> ---
>  arch/x86/crypto/blake2s-glue.c    | 74 +++---------------------------
>  crypto/blake2s_generic.c          | 76 ++++---------------------------
>  include/crypto/internal/blake2s.h | 65 ++++++++++++++++++++++++--
>  3 files changed, 76 insertions(+), 139 deletions(-)
>
> diff --git a/arch/x86/crypto/blake2s-glue.c b/arch/x86/crypto/blake2s-glue.c
> index 4dcb2ee89efc9..a40365ab301ee 100644
> --- a/arch/x86/crypto/blake2s-glue.c
> +++ b/arch/x86/crypto/blake2s-glue.c
> @@ -58,75 +58,15 @@ void blake2s_compress_arch(struct blake2s_state *state,
>  }
>  EXPORT_SYMBOL(blake2s_compress_arch);
>
> -static int crypto_blake2s_setkey(struct crypto_shash *tfm, const u8 *key,
> -                                unsigned int keylen)
> +static int crypto_blake2s_update_x86(struct shash_desc *desc,
> +                                    const u8 *in, unsigned int inlen)
>  {
> -       struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(tfm);
> -
> -       if (keylen == 0 || keylen > BLAKE2S_KEY_SIZE)
> -               return -EINVAL;
> -
> -       memcpy(tctx->key, key, keylen);
> -       tctx->keylen = keylen;
> -
> -       return 0;
> -}
> -
> -static int crypto_blake2s_init(struct shash_desc *desc)
> -{
> -       struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
> -       struct blake2s_state *state = shash_desc_ctx(desc);
> -       const int outlen = crypto_shash_digestsize(desc->tfm);
> -
> -       if (tctx->keylen)
> -               blake2s_init_key(state, outlen, tctx->key, tctx->keylen);
> -       else
> -               blake2s_init(state, outlen);
> -
> -       return 0;
> -}
> -
> -static int crypto_blake2s_update(struct shash_desc *desc, const u8 *in,
> -                                unsigned int inlen)
> -{
> -       struct blake2s_state *state = shash_desc_ctx(desc);
> -       const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen;
> -
> -       if (unlikely(!inlen))
> -               return 0;
> -       if (inlen > fill) {
> -               memcpy(state->buf + state->buflen, in, fill);
> -               blake2s_compress_arch(state, state->buf, 1, BLAKE2S_BLOCK_SIZE);
> -               state->buflen = 0;
> -               in += fill;
> -               inlen -= fill;
> -       }
> -       if (inlen > BLAKE2S_BLOCK_SIZE) {
> -               const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE);
> -               /* Hash one less (full) block than strictly possible */
> -               blake2s_compress_arch(state, in, nblocks - 1, BLAKE2S_BLOCK_SIZE);
> -               in += BLAKE2S_BLOCK_SIZE * (nblocks - 1);
> -               inlen -= BLAKE2S_BLOCK_SIZE * (nblocks - 1);
> -       }
> -       memcpy(state->buf + state->buflen, in, inlen);
> -       state->buflen += inlen;
> -
> -       return 0;
> +       return crypto_blake2s_update(desc, in, inlen, blake2s_compress_arch);
>  }
>
> -static int crypto_blake2s_final(struct shash_desc *desc, u8 *out)
> +static int crypto_blake2s_final_x86(struct shash_desc *desc, u8 *out)
>  {
> -       struct blake2s_state *state = shash_desc_ctx(desc);
> -
> -       blake2s_set_lastblock(state);
> -       memset(state->buf + state->buflen, 0,
> -              BLAKE2S_BLOCK_SIZE - state->buflen); /* Padding */
> -       blake2s_compress_arch(state, state->buf, 1, state->buflen);
> -       cpu_to_le32_array(state->h, ARRAY_SIZE(state->h));
> -       memcpy(out, state->h, state->outlen);
> -       memzero_explicit(state, sizeof(*state));
> -
> -       return 0;
> +       return crypto_blake2s_final(desc, out, blake2s_compress_arch);
>  }
>
>  #define BLAKE2S_ALG(name, driver_name, digest_size)                    \
> @@ -141,8 +81,8 @@ static int crypto_blake2s_final(struct shash_desc *desc, u8 *out)
>                 .digestsize             = digest_size,                  \
>                 .setkey                 = crypto_blake2s_setkey,        \
>                 .init                   = crypto_blake2s_init,          \
> -               .update                 = crypto_blake2s_update,        \
> -               .final                  = crypto_blake2s_final,         \
> +               .update                 = crypto_blake2s_update_x86,    \
> +               .final                  = crypto_blake2s_final_x86,     \
>                 .descsize               = sizeof(struct blake2s_state), \
>         }
>
> diff --git a/crypto/blake2s_generic.c b/crypto/blake2s_generic.c
> index b89536c3671cf..72fe480f9bd67 100644
> --- a/crypto/blake2s_generic.c
> +++ b/crypto/blake2s_generic.c
> @@ -1,5 +1,7 @@
>  // SPDX-License-Identifier: GPL-2.0 OR MIT
>  /*
> + * shash interface to the generic implementation of BLAKE2s
> + *
>   * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason at zx2c4.com>. All Rights Reserved.
>   */
>
> @@ -10,75 +12,15 @@
>  #include <linux/kernel.h>
>  #include <linux/module.h>
>
> -static int crypto_blake2s_setkey(struct crypto_shash *tfm, const u8 *key,
> -                                unsigned int keylen)
> +static int crypto_blake2s_update_generic(struct shash_desc *desc,
> +                                        const u8 *in, unsigned int inlen)
>  {
> -       struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(tfm);
> -
> -       if (keylen == 0 || keylen > BLAKE2S_KEY_SIZE)
> -               return -EINVAL;
> -
> -       memcpy(tctx->key, key, keylen);
> -       tctx->keylen = keylen;
> -
> -       return 0;
> +       return crypto_blake2s_update(desc, in, inlen, blake2s_compress_generic);
>  }
>
> -static int crypto_blake2s_init(struct shash_desc *desc)
> +static int crypto_blake2s_final_generic(struct shash_desc *desc, u8 *out)
>  {
> -       struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
> -       struct blake2s_state *state = shash_desc_ctx(desc);
> -       const int outlen = crypto_shash_digestsize(desc->tfm);
> -
> -       if (tctx->keylen)
> -               blake2s_init_key(state, outlen, tctx->key, tctx->keylen);
> -       else
> -               blake2s_init(state, outlen);
> -
> -       return 0;
> -}
> -
> -static int crypto_blake2s_update(struct shash_desc *desc, const u8 *in,
> -                                unsigned int inlen)
> -{
> -       struct blake2s_state *state = shash_desc_ctx(desc);
> -       const size_t fill = BLAKE2S_BLOCK_SIZE - state->buflen;
> -
> -       if (unlikely(!inlen))
> -               return 0;
> -       if (inlen > fill) {
> -               memcpy(state->buf + state->buflen, in, fill);
> -               blake2s_compress_generic(state, state->buf, 1, BLAKE2S_BLOCK_SIZE);
> -               state->buflen = 0;
> -               in += fill;
> -               inlen -= fill;
> -       }
> -       if (inlen > BLAKE2S_BLOCK_SIZE) {
> -               const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2S_BLOCK_SIZE);
> -               /* Hash one less (full) block than strictly possible */
> -               blake2s_compress_generic(state, in, nblocks - 1, BLAKE2S_BLOCK_SIZE);
> -               in += BLAKE2S_BLOCK_SIZE * (nblocks - 1);
> -               inlen -= BLAKE2S_BLOCK_SIZE * (nblocks - 1);
> -       }
> -       memcpy(state->buf + state->buflen, in, inlen);
> -       state->buflen += inlen;
> -
> -       return 0;
> -}
> -
> -static int crypto_blake2s_final(struct shash_desc *desc, u8 *out)
> -{
> -       struct blake2s_state *state = shash_desc_ctx(desc);
> -
> -       blake2s_set_lastblock(state);
> -       memset(state->buf + state->buflen, 0,
> -              BLAKE2S_BLOCK_SIZE - state->buflen); /* Padding */
> -       blake2s_compress_generic(state, state->buf, 1, state->buflen);
> -       cpu_to_le32_array(state->h, ARRAY_SIZE(state->h));
> -       memcpy(out, state->h, state->outlen);
> -       memzero_explicit(state, sizeof(*state));
> -
> -       return 0;
> +       return crypto_blake2s_final(desc, out, blake2s_compress_generic);
>  }
>
>  #define BLAKE2S_ALG(name, driver_name, digest_size)                    \
> @@ -93,8 +35,8 @@ static int crypto_blake2s_final(struct shash_desc *desc, u8 *out)
>                 .digestsize             = digest_size,                  \
>                 .setkey                 = crypto_blake2s_setkey,        \
>                 .init                   = crypto_blake2s_init,          \
> -               .update                 = crypto_blake2s_update,        \
> -               .final                  = crypto_blake2s_final,         \
> +               .update                 = crypto_blake2s_update_generic, \
> +               .final                  = crypto_blake2s_final_generic, \
>                 .descsize               = sizeof(struct blake2s_state), \
>         }
>
> diff --git a/include/crypto/internal/blake2s.h b/include/crypto/internal/blake2s.h
> index 42deba4b8ceef..2ea0a8f5e7f41 100644
> --- a/include/crypto/internal/blake2s.h
> +++ b/include/crypto/internal/blake2s.h
> @@ -1,16 +1,16 @@
>  /* SPDX-License-Identifier: GPL-2.0 OR MIT */
> +/*
> + * Helper functions for BLAKE2s implementations.
> + * Keep this in sync with the corresponding BLAKE2b header.
> + */
>
>  #ifndef BLAKE2S_INTERNAL_H
>  #define BLAKE2S_INTERNAL_H
>
>  #include <crypto/blake2s.h>
> +#include <crypto/internal/hash.h>
>  #include <linux/string.h>
>
> -struct blake2s_tfm_ctx {
> -       u8 key[BLAKE2S_KEY_SIZE];
> -       unsigned int keylen;
> -};
> -
>  void blake2s_compress_generic(struct blake2s_state *state,const u8 *block,
>                               size_t nblocks, const u32 inc);
>
> @@ -27,6 +27,8 @@ static inline void blake2s_set_lastblock(struct blake2s_state *state)
>  typedef void (*blake2s_compress_t)(struct blake2s_state *state,
>                                    const u8 *block, size_t nblocks, u32 inc);
>
> +/* Helper functions for BLAKE2s shared by the library and shash APIs */
> +
>  static inline void __blake2s_update(struct blake2s_state *state,
>                                     const u8 *in, size_t inlen,
>                                     blake2s_compress_t compress)
> @@ -64,4 +66,57 @@ static inline void __blake2s_final(struct blake2s_state *state, u8 *out,
>         memcpy(out, state->h, state->outlen);
>  }
>
> +/* Helper functions for shash implementations of BLAKE2s */
> +
> +struct blake2s_tfm_ctx {
> +       u8 key[BLAKE2S_KEY_SIZE];
> +       unsigned int keylen;
> +};
> +
> +static inline int crypto_blake2s_setkey(struct crypto_shash *tfm,
> +                                       const u8 *key, unsigned int keylen)
> +{
> +       struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(tfm);
> +
> +       if (keylen == 0 || keylen > BLAKE2S_KEY_SIZE)
> +               return -EINVAL;
> +
> +       memcpy(tctx->key, key, keylen);
> +       tctx->keylen = keylen;
> +
> +       return 0;
> +}
> +
> +static inline int crypto_blake2s_init(struct shash_desc *desc)
> +{
> +       const struct blake2s_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
> +       struct blake2s_state *state = shash_desc_ctx(desc);
> +       unsigned int outlen = crypto_shash_digestsize(desc->tfm);
> +
> +       if (tctx->keylen)
> +               blake2s_init_key(state, outlen, tctx->key, tctx->keylen);
> +       else
> +               blake2s_init(state, outlen);
> +       return 0;
> +}
> +
> +static inline int crypto_blake2s_update(struct shash_desc *desc,
> +                                       const u8 *in, unsigned int inlen,
> +                                       blake2s_compress_t compress)
> +{
> +       struct blake2s_state *state = shash_desc_ctx(desc);
> +
> +       __blake2s_update(state, in, inlen, compress);
> +       return 0;
> +}
> +
> +static inline int crypto_blake2s_final(struct shash_desc *desc, u8 *out,
> +                                      blake2s_compress_t compress)
> +{
> +       struct blake2s_state *state = shash_desc_ctx(desc);
> +
> +       __blake2s_final(state, out, compress);
> +       return 0;
> +}
> +
>  #endif /* BLAKE2S_INTERNAL_H */
> --
> 2.29.2
>



More information about the linux-arm-kernel mailing list