[PATCH v3 12/14] crypto: blake2b - sync with blake2s implementation

Ard Biesheuvel ardb at kernel.org
Wed Dec 23 04:09:36 EST 2020


On Wed, 23 Dec 2020 at 09:12, Eric Biggers <ebiggers at kernel.org> wrote:
>
> From: Eric Biggers <ebiggers at google.com>
>
> Sync the BLAKE2b code with the BLAKE2s code as much as possible:
>
> - Move a lot of code into new headers <crypto/blake2b.h> and
>   <crypto/internal/blake2b.h>, and adjust it to be like the
>   corresponding BLAKE2s code, i.e. like <crypto/blake2s.h> and
>   <crypto/internal/blake2s.h>.
>
> - Rename constants, e.g. BLAKE2B_*_DIGEST_SIZE => BLAKE2B_*_HASH_SIZE.
>
> - Use a macro BLAKE2B_ALG() to define the shash_alg structs.
>
> - Export blake2b_compress_generic() for use as a fallback.
>
> This makes it much easier to add optimized implementations of BLAKE2b,
> as optimized implementations can use the helper functions
> crypto_blake2b_{setkey,init,update,final}() and
> blake2b_compress_generic().  The ARM implementation will use these.
>
> But this change is also helpful because it eliminates unnecessary
> differences between the BLAKE2b and BLAKE2s code, so that the same
> improvements can easily be made to both.  (The two algorithms are
> basically identical, except for the word size and constants.)  It also
> makes it straightforward to add a library API for BLAKE2b in the future
> if/when it's needed.
>
> This change does make the BLAKE2b code slightly more complicated than it
> needs to be, as it doesn't actually provide a library API yet.  For
> example, __blake2b_update() doesn't really need to exist yet; it could
> just be inlined into crypto_blake2b_update().  But I believe this is
> outweighed by the benefits of keeping the code in sync.
>
> Signed-off-by: Eric Biggers <ebiggers at google.com>

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

> ---
>  crypto/blake2b_generic.c          | 226 +++++++-----------------------
>  include/crypto/blake2b.h          |  67 +++++++++
>  include/crypto/internal/blake2b.h | 115 +++++++++++++++
>  3 files changed, 230 insertions(+), 178 deletions(-)
>  create mode 100644 include/crypto/blake2b.h
>  create mode 100644 include/crypto/internal/blake2b.h
>
> diff --git a/crypto/blake2b_generic.c b/crypto/blake2b_generic.c
> index a2ffe60e06d34..963f7fe0e4ea8 100644
> --- a/crypto/blake2b_generic.c
> +++ b/crypto/blake2b_generic.c
> @@ -20,36 +20,11 @@
>
>  #include <asm/unaligned.h>
>  #include <linux/module.h>
> -#include <linux/string.h>
>  #include <linux/kernel.h>
>  #include <linux/bitops.h>
> +#include <crypto/internal/blake2b.h>
>  #include <crypto/internal/hash.h>
>
> -#define BLAKE2B_160_DIGEST_SIZE                (160 / 8)
> -#define BLAKE2B_256_DIGEST_SIZE                (256 / 8)
> -#define BLAKE2B_384_DIGEST_SIZE                (384 / 8)
> -#define BLAKE2B_512_DIGEST_SIZE                (512 / 8)
> -
> -enum blake2b_constant {
> -       BLAKE2B_BLOCKBYTES    = 128,
> -       BLAKE2B_KEYBYTES      = 64,
> -};
> -
> -struct blake2b_state {
> -       u64      h[8];
> -       u64      t[2];
> -       u64      f[2];
> -       u8       buf[BLAKE2B_BLOCKBYTES];
> -       size_t   buflen;
> -};
> -
> -static const u64 blake2b_IV[8] = {
> -       0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
> -       0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
> -       0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
> -       0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
> -};
> -
>  static const u8 blake2b_sigma[12][16] = {
>         {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 },
>         { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 },
> @@ -95,8 +70,8 @@ static void blake2b_increment_counter(struct blake2b_state *S, const u64 inc)
>                 G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
>         } while (0)
>
> -static void blake2b_compress(struct blake2b_state *S,
> -                            const u8 block[BLAKE2B_BLOCKBYTES])
> +static void blake2b_compress_one_generic(struct blake2b_state *S,
> +                                        const u8 block[BLAKE2B_BLOCK_SIZE])
>  {
>         u64 m[16];
>         u64 v[16];
> @@ -108,14 +83,14 @@ static void blake2b_compress(struct blake2b_state *S,
>         for (i = 0; i < 8; ++i)
>                 v[i] = S->h[i];
>
> -       v[ 8] = blake2b_IV[0];
> -       v[ 9] = blake2b_IV[1];
> -       v[10] = blake2b_IV[2];
> -       v[11] = blake2b_IV[3];
> -       v[12] = blake2b_IV[4] ^ S->t[0];
> -       v[13] = blake2b_IV[5] ^ S->t[1];
> -       v[14] = blake2b_IV[6] ^ S->f[0];
> -       v[15] = blake2b_IV[7] ^ S->f[1];
> +       v[ 8] = BLAKE2B_IV0;
> +       v[ 9] = BLAKE2B_IV1;
> +       v[10] = BLAKE2B_IV2;
> +       v[11] = BLAKE2B_IV3;
> +       v[12] = BLAKE2B_IV4 ^ S->t[0];
> +       v[13] = BLAKE2B_IV5 ^ S->t[1];
> +       v[14] = BLAKE2B_IV6 ^ S->f[0];
> +       v[15] = BLAKE2B_IV7 ^ S->f[1];
>
>         ROUND(0);
>         ROUND(1);
> @@ -139,159 +114,54 @@ static void blake2b_compress(struct blake2b_state *S,
>  #undef G
>  #undef ROUND
>
> -struct blake2b_tfm_ctx {
> -       u8 key[BLAKE2B_KEYBYTES];
> -       unsigned int keylen;
> -};
> -
> -static int blake2b_setkey(struct crypto_shash *tfm, const u8 *key,
> -                         unsigned int keylen)
> +void blake2b_compress_generic(struct blake2b_state *state,
> +                             const u8 *block, size_t nblocks, u32 inc)
>  {
> -       struct blake2b_tfm_ctx *tctx = crypto_shash_ctx(tfm);
> -
> -       if (keylen == 0 || keylen > BLAKE2B_KEYBYTES)
> -               return -EINVAL;
> -
> -       memcpy(tctx->key, key, keylen);
> -       tctx->keylen = keylen;
> -
> -       return 0;
> +       do {
> +               blake2b_increment_counter(state, inc);
> +               blake2b_compress_one_generic(state, block);
> +               block += BLAKE2B_BLOCK_SIZE;
> +       } while (--nblocks);
>  }
> +EXPORT_SYMBOL(blake2b_compress_generic);
>
> -static int blake2b_init(struct shash_desc *desc)
> +static int crypto_blake2b_update_generic(struct shash_desc *desc,
> +                                        const u8 *in, unsigned int inlen)
>  {
> -       struct blake2b_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
> -       struct blake2b_state *state = shash_desc_ctx(desc);
> -       const int digestsize = crypto_shash_digestsize(desc->tfm);
> -
> -       memset(state, 0, sizeof(*state));
> -       memcpy(state->h, blake2b_IV, sizeof(state->h));
> -
> -       /* Parameter block is all zeros except index 0, no xor for 1..7 */
> -       state->h[0] ^= 0x01010000 | tctx->keylen << 8 | digestsize;
> -
> -       if (tctx->keylen) {
> -               /*
> -                * Prefill the buffer with the key, next call to _update or
> -                * _final will process it
> -                */
> -               memcpy(state->buf, tctx->key, tctx->keylen);
> -               state->buflen = BLAKE2B_BLOCKBYTES;
> -       }
> -       return 0;
> +       return crypto_blake2b_update(desc, in, inlen, blake2b_compress_generic);
>  }
>
> -static int blake2b_update(struct shash_desc *desc, const u8 *in,
> -                         unsigned int inlen)
> +static int crypto_blake2b_final_generic(struct shash_desc *desc, u8 *out)
>  {
> -       struct blake2b_state *state = shash_desc_ctx(desc);
> -       const size_t left = state->buflen;
> -       const size_t fill = BLAKE2B_BLOCKBYTES - left;
> -
> -       if (!inlen)
> -               return 0;
> -
> -       if (inlen > fill) {
> -               state->buflen = 0;
> -               /* Fill buffer */
> -               memcpy(state->buf + left, in, fill);
> -               blake2b_increment_counter(state, BLAKE2B_BLOCKBYTES);
> -               /* Compress */
> -               blake2b_compress(state, state->buf);
> -               in += fill;
> -               inlen -= fill;
> -               while (inlen > BLAKE2B_BLOCKBYTES) {
> -                       blake2b_increment_counter(state, BLAKE2B_BLOCKBYTES);
> -                       blake2b_compress(state, in);
> -                       in += BLAKE2B_BLOCKBYTES;
> -                       inlen -= BLAKE2B_BLOCKBYTES;
> -               }
> -       }
> -       memcpy(state->buf + state->buflen, in, inlen);
> -       state->buflen += inlen;
> -
> -       return 0;
> +       return crypto_blake2b_final(desc, out, blake2b_compress_generic);
>  }
>
> -static int blake2b_final(struct shash_desc *desc, u8 *out)
> -{
> -       struct blake2b_state *state = shash_desc_ctx(desc);
> -       const int digestsize = crypto_shash_digestsize(desc->tfm);
> -       size_t i;
> -
> -       blake2b_increment_counter(state, state->buflen);
> -       /* Set last block */
> -       state->f[0] = (u64)-1;
> -       /* Padding */
> -       memset(state->buf + state->buflen, 0, BLAKE2B_BLOCKBYTES - state->buflen);
> -       blake2b_compress(state, state->buf);
> -
> -       /* Avoid temporary buffer and switch the internal output to LE order */
> -       for (i = 0; i < ARRAY_SIZE(state->h); i++)
> -               __cpu_to_le64s(&state->h[i]);
> -
> -       memcpy(out, state->h, digestsize);
> -       return 0;
> -}
> +#define BLAKE2B_ALG(name, driver_name, digest_size)                    \
> +       {                                                               \
> +               .base.cra_name          = name,                         \
> +               .base.cra_driver_name   = driver_name,                  \
> +               .base.cra_priority      = 100,                          \
> +               .base.cra_flags         = CRYPTO_ALG_OPTIONAL_KEY,      \
> +               .base.cra_blocksize     = BLAKE2B_BLOCK_SIZE,           \
> +               .base.cra_ctxsize       = sizeof(struct blake2b_tfm_ctx), \
> +               .base.cra_module        = THIS_MODULE,                  \
> +               .digestsize             = digest_size,                  \
> +               .setkey                 = crypto_blake2b_setkey,        \
> +               .init                   = crypto_blake2b_init,          \
> +               .update                 = crypto_blake2b_update_generic, \
> +               .final                  = crypto_blake2b_final_generic, \
> +               .descsize               = sizeof(struct blake2b_state), \
> +       }
>
>  static struct shash_alg blake2b_algs[] = {
> -       {
> -               .base.cra_name          = "blake2b-160",
> -               .base.cra_driver_name   = "blake2b-160-generic",
> -               .base.cra_priority      = 100,
> -               .base.cra_flags         = CRYPTO_ALG_OPTIONAL_KEY,
> -               .base.cra_blocksize     = BLAKE2B_BLOCKBYTES,
> -               .base.cra_ctxsize       = sizeof(struct blake2b_tfm_ctx),
> -               .base.cra_module        = THIS_MODULE,
> -               .digestsize             = BLAKE2B_160_DIGEST_SIZE,
> -               .setkey                 = blake2b_setkey,
> -               .init                   = blake2b_init,
> -               .update                 = blake2b_update,
> -               .final                  = blake2b_final,
> -               .descsize               = sizeof(struct blake2b_state),
> -       }, {
> -               .base.cra_name          = "blake2b-256",
> -               .base.cra_driver_name   = "blake2b-256-generic",
> -               .base.cra_priority      = 100,
> -               .base.cra_flags         = CRYPTO_ALG_OPTIONAL_KEY,
> -               .base.cra_blocksize     = BLAKE2B_BLOCKBYTES,
> -               .base.cra_ctxsize       = sizeof(struct blake2b_tfm_ctx),
> -               .base.cra_module        = THIS_MODULE,
> -               .digestsize             = BLAKE2B_256_DIGEST_SIZE,
> -               .setkey                 = blake2b_setkey,
> -               .init                   = blake2b_init,
> -               .update                 = blake2b_update,
> -               .final                  = blake2b_final,
> -               .descsize               = sizeof(struct blake2b_state),
> -       }, {
> -               .base.cra_name          = "blake2b-384",
> -               .base.cra_driver_name   = "blake2b-384-generic",
> -               .base.cra_priority      = 100,
> -               .base.cra_flags         = CRYPTO_ALG_OPTIONAL_KEY,
> -               .base.cra_blocksize     = BLAKE2B_BLOCKBYTES,
> -               .base.cra_ctxsize       = sizeof(struct blake2b_tfm_ctx),
> -               .base.cra_module        = THIS_MODULE,
> -               .digestsize             = BLAKE2B_384_DIGEST_SIZE,
> -               .setkey                 = blake2b_setkey,
> -               .init                   = blake2b_init,
> -               .update                 = blake2b_update,
> -               .final                  = blake2b_final,
> -               .descsize               = sizeof(struct blake2b_state),
> -       }, {
> -               .base.cra_name          = "blake2b-512",
> -               .base.cra_driver_name   = "blake2b-512-generic",
> -               .base.cra_priority      = 100,
> -               .base.cra_flags         = CRYPTO_ALG_OPTIONAL_KEY,
> -               .base.cra_blocksize     = BLAKE2B_BLOCKBYTES,
> -               .base.cra_ctxsize       = sizeof(struct blake2b_tfm_ctx),
> -               .base.cra_module        = THIS_MODULE,
> -               .digestsize             = BLAKE2B_512_DIGEST_SIZE,
> -               .setkey                 = blake2b_setkey,
> -               .init                   = blake2b_init,
> -               .update                 = blake2b_update,
> -               .final                  = blake2b_final,
> -               .descsize               = sizeof(struct blake2b_state),
> -       }
> +       BLAKE2B_ALG("blake2b-160", "blake2b-160-generic",
> +                   BLAKE2B_160_HASH_SIZE),
> +       BLAKE2B_ALG("blake2b-256", "blake2b-256-generic",
> +                   BLAKE2B_256_HASH_SIZE),
> +       BLAKE2B_ALG("blake2b-384", "blake2b-384-generic",
> +                   BLAKE2B_384_HASH_SIZE),
> +       BLAKE2B_ALG("blake2b-512", "blake2b-512-generic",
> +                   BLAKE2B_512_HASH_SIZE),
>  };
>
>  static int __init blake2b_mod_init(void)
> diff --git a/include/crypto/blake2b.h b/include/crypto/blake2b.h
> new file mode 100644
> index 0000000000000..18875f16f8cad
> --- /dev/null
> +++ b/include/crypto/blake2b.h
> @@ -0,0 +1,67 @@
> +/* SPDX-License-Identifier: GPL-2.0 OR MIT */
> +
> +#ifndef _CRYPTO_BLAKE2B_H
> +#define _CRYPTO_BLAKE2B_H
> +
> +#include <linux/bug.h>
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <linux/string.h>
> +
> +enum blake2b_lengths {
> +       BLAKE2B_BLOCK_SIZE = 128,
> +       BLAKE2B_HASH_SIZE = 64,
> +       BLAKE2B_KEY_SIZE = 64,
> +
> +       BLAKE2B_160_HASH_SIZE = 20,
> +       BLAKE2B_256_HASH_SIZE = 32,
> +       BLAKE2B_384_HASH_SIZE = 48,
> +       BLAKE2B_512_HASH_SIZE = 64,
> +};
> +
> +struct blake2b_state {
> +       /* 'h', 't', and 'f' are used in assembly code, so keep them as-is. */
> +       u64 h[8];
> +       u64 t[2];
> +       u64 f[2];
> +       u8 buf[BLAKE2B_BLOCK_SIZE];
> +       unsigned int buflen;
> +       unsigned int outlen;
> +};
> +
> +enum blake2b_iv {
> +       BLAKE2B_IV0 = 0x6A09E667F3BCC908ULL,
> +       BLAKE2B_IV1 = 0xBB67AE8584CAA73BULL,
> +       BLAKE2B_IV2 = 0x3C6EF372FE94F82BULL,
> +       BLAKE2B_IV3 = 0xA54FF53A5F1D36F1ULL,
> +       BLAKE2B_IV4 = 0x510E527FADE682D1ULL,
> +       BLAKE2B_IV5 = 0x9B05688C2B3E6C1FULL,
> +       BLAKE2B_IV6 = 0x1F83D9ABFB41BD6BULL,
> +       BLAKE2B_IV7 = 0x5BE0CD19137E2179ULL,
> +};
> +
> +static inline void __blake2b_init(struct blake2b_state *state, size_t outlen,
> +                                 const void *key, size_t keylen)
> +{
> +       state->h[0] = BLAKE2B_IV0 ^ (0x01010000 | keylen << 8 | outlen);
> +       state->h[1] = BLAKE2B_IV1;
> +       state->h[2] = BLAKE2B_IV2;
> +       state->h[3] = BLAKE2B_IV3;
> +       state->h[4] = BLAKE2B_IV4;
> +       state->h[5] = BLAKE2B_IV5;
> +       state->h[6] = BLAKE2B_IV6;
> +       state->h[7] = BLAKE2B_IV7;
> +       state->t[0] = 0;
> +       state->t[1] = 0;
> +       state->f[0] = 0;
> +       state->f[1] = 0;
> +       state->buflen = 0;
> +       state->outlen = outlen;
> +       if (keylen) {
> +               memcpy(state->buf, key, keylen);
> +               memset(&state->buf[keylen], 0, BLAKE2B_BLOCK_SIZE - keylen);
> +               state->buflen = BLAKE2B_BLOCK_SIZE;
> +       }
> +}
> +
> +#endif /* _CRYPTO_BLAKE2B_H */
> diff --git a/include/crypto/internal/blake2b.h b/include/crypto/internal/blake2b.h
> new file mode 100644
> index 0000000000000..982fe5e8471cd
> --- /dev/null
> +++ b/include/crypto/internal/blake2b.h
> @@ -0,0 +1,115 @@
> +/* SPDX-License-Identifier: GPL-2.0 OR MIT */
> +/*
> + * Helper functions for BLAKE2b implementations.
> + * Keep this in sync with the corresponding BLAKE2s header.
> + */
> +
> +#ifndef _CRYPTO_INTERNAL_BLAKE2B_H
> +#define _CRYPTO_INTERNAL_BLAKE2B_H
> +
> +#include <crypto/blake2b.h>
> +#include <crypto/internal/hash.h>
> +#include <linux/string.h>
> +
> +void blake2b_compress_generic(struct blake2b_state *state,
> +                             const u8 *block, size_t nblocks, u32 inc);
> +
> +static inline void blake2b_set_lastblock(struct blake2b_state *state)
> +{
> +       state->f[0] = -1;
> +}
> +
> +typedef void (*blake2b_compress_t)(struct blake2b_state *state,
> +                                  const u8 *block, size_t nblocks, u32 inc);
> +
> +static inline void __blake2b_update(struct blake2b_state *state,
> +                                   const u8 *in, size_t inlen,
> +                                   blake2b_compress_t compress)
> +{
> +       const size_t fill = BLAKE2B_BLOCK_SIZE - state->buflen;
> +
> +       if (unlikely(!inlen))
> +               return;
> +       if (inlen > fill) {
> +               memcpy(state->buf + state->buflen, in, fill);
> +               (*compress)(state, state->buf, 1, BLAKE2B_BLOCK_SIZE);
> +               state->buflen = 0;
> +               in += fill;
> +               inlen -= fill;
> +       }
> +       if (inlen > BLAKE2B_BLOCK_SIZE) {
> +               const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2B_BLOCK_SIZE);
> +               /* Hash one less (full) block than strictly possible */
> +               (*compress)(state, in, nblocks - 1, BLAKE2B_BLOCK_SIZE);
> +               in += BLAKE2B_BLOCK_SIZE * (nblocks - 1);
> +               inlen -= BLAKE2B_BLOCK_SIZE * (nblocks - 1);
> +       }
> +       memcpy(state->buf + state->buflen, in, inlen);
> +       state->buflen += inlen;
> +}
> +
> +static inline void __blake2b_final(struct blake2b_state *state, u8 *out,
> +                                  blake2b_compress_t compress)
> +{
> +       int i;
> +
> +       blake2b_set_lastblock(state);
> +       memset(state->buf + state->buflen, 0,
> +              BLAKE2B_BLOCK_SIZE - state->buflen); /* Padding */
> +       (*compress)(state, state->buf, 1, state->buflen);
> +       for (i = 0; i < ARRAY_SIZE(state->h); i++)
> +               __cpu_to_le64s(&state->h[i]);
> +       memcpy(out, state->h, state->outlen);
> +}
> +
> +/* Helper functions for shash implementations of BLAKE2b */
> +
> +struct blake2b_tfm_ctx {
> +       u8 key[BLAKE2B_KEY_SIZE];
> +       unsigned int keylen;
> +};
> +
> +static inline int crypto_blake2b_setkey(struct crypto_shash *tfm,
> +                                       const u8 *key, unsigned int keylen)
> +{
> +       struct blake2b_tfm_ctx *tctx = crypto_shash_ctx(tfm);
> +
> +       if (keylen == 0 || keylen > BLAKE2B_KEY_SIZE)
> +               return -EINVAL;
> +
> +       memcpy(tctx->key, key, keylen);
> +       tctx->keylen = keylen;
> +
> +       return 0;
> +}
> +
> +static inline int crypto_blake2b_init(struct shash_desc *desc)
> +{
> +       const struct blake2b_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm);
> +       struct blake2b_state *state = shash_desc_ctx(desc);
> +       unsigned int outlen = crypto_shash_digestsize(desc->tfm);
> +
> +       __blake2b_init(state, outlen, tctx->key, tctx->keylen);
> +       return 0;
> +}
> +
> +static inline int crypto_blake2b_update(struct shash_desc *desc,
> +                                       const u8 *in, unsigned int inlen,
> +                                       blake2b_compress_t compress)
> +{
> +       struct blake2b_state *state = shash_desc_ctx(desc);
> +
> +       __blake2b_update(state, in, inlen, compress);
> +       return 0;
> +}
> +
> +static inline int crypto_blake2b_final(struct shash_desc *desc, u8 *out,
> +                                      blake2b_compress_t compress)
> +{
> +       struct blake2b_state *state = shash_desc_ctx(desc);
> +
> +       __blake2b_final(state, out, compress);
> +       return 0;
> +}
> +
> +#endif /* _CRYPTO_INTERNAL_BLAKE2B_H */
> --
> 2.29.2
>



More information about the linux-arm-kernel mailing list