Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

lib/crypto: blake2b: Add BLAKE2b library functions

Add a library API for BLAKE2b, closely modeled after the BLAKE2s API.

This will allow in-kernel users such as btrfs to use BLAKE2b without
going through the generic crypto layer. In addition, as usual the
BLAKE2b crypto_shash algorithms will be reimplemented on top of this.

Note: to create lib/crypto/blake2b.c I made a copy of
lib/crypto/blake2s.c and made the updates from BLAKE2s => BLAKE2b. This
way, the BLAKE2s and BLAKE2b code is kept consistent. Therefore, it
borrows the SPDX-License-Identifier and Copyright from
lib/crypto/blake2s.c rather than crypto/blake2b_generic.c.

The library API uses 'struct blake2b_ctx', consistent with other
lib/crypto/ APIs. The existing 'struct blake2b_state' will be removed
once the blake2b crypto_shash algorithms are updated to stop using it.

Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20251018043106.375964-7-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>

+330 -13
+121 -12
include/crypto/blake2b.h
··· 28 28 BLAKE2B_512_HASH_SIZE = 64, 29 29 }; 30 30 31 + /** 32 + * struct blake2b_ctx - Context for hashing a message with BLAKE2b 33 + * @h: compression function state 34 + * @t: block counter 35 + * @f: finalization indicator 36 + * @buf: partial block buffer; 'buflen' bytes are valid 37 + * @buflen: number of bytes buffered in @buf 38 + * @outlen: length of output hash value in bytes, at most BLAKE2B_HASH_SIZE 39 + */ 40 + struct blake2b_ctx { 41 + /* 'h', 't', and 'f' are used in assembly code, so keep them as-is. */ 42 + u64 h[8]; 43 + u64 t[2]; 44 + u64 f[2]; 45 + u8 buf[BLAKE2B_BLOCK_SIZE]; 46 + unsigned int buflen; 47 + unsigned int outlen; 48 + }; 49 + 31 50 enum blake2b_iv { 32 51 BLAKE2B_IV0 = 0x6A09E667F3BCC908ULL, 33 52 BLAKE2B_IV1 = 0xBB67AE8584CAA73BULL, ··· 58 39 BLAKE2B_IV7 = 0x5BE0CD19137E2179ULL, 59 40 }; 60 41 61 - static inline void __blake2b_init(struct blake2b_state *state, size_t outlen, 62 - size_t keylen) 42 + static inline void __blake2b_init(struct blake2b_ctx *ctx, size_t outlen, 43 + const void *key, size_t keylen) 63 44 { 64 - state->h[0] = BLAKE2B_IV0 ^ (0x01010000 | keylen << 8 | outlen); 65 - state->h[1] = BLAKE2B_IV1; 66 - state->h[2] = BLAKE2B_IV2; 67 - state->h[3] = BLAKE2B_IV3; 68 - state->h[4] = BLAKE2B_IV4; 69 - state->h[5] = BLAKE2B_IV5; 70 - state->h[6] = BLAKE2B_IV6; 71 - state->h[7] = BLAKE2B_IV7; 72 - state->t[0] = 0; 73 - state->t[1] = 0; 45 + ctx->h[0] = BLAKE2B_IV0 ^ (0x01010000 | keylen << 8 | outlen); 46 + ctx->h[1] = BLAKE2B_IV1; 47 + ctx->h[2] = BLAKE2B_IV2; 48 + ctx->h[3] = BLAKE2B_IV3; 49 + ctx->h[4] = BLAKE2B_IV4; 50 + ctx->h[5] = BLAKE2B_IV5; 51 + ctx->h[6] = BLAKE2B_IV6; 52 + ctx->h[7] = BLAKE2B_IV7; 53 + ctx->t[0] = 0; 54 + ctx->t[1] = 0; 55 + ctx->f[0] = 0; 56 + ctx->f[1] = 0; 57 + ctx->buflen = 0; 58 + ctx->outlen = outlen; 59 + if (keylen) { 60 + memcpy(ctx->buf, key, keylen); 61 + memset(&ctx->buf[keylen], 0, BLAKE2B_BLOCK_SIZE - keylen); 62 + ctx->buflen = BLAKE2B_BLOCK_SIZE; 63 + } 64 + } 65 + 66 + /** 67 + * blake2b_init() - Initialize a BLAKE2b context for a new message (unkeyed) 68 + * @ctx: the context to initialize 69 + * @outlen: length of output hash value in bytes, at most BLAKE2B_HASH_SIZE 70 + * 71 + * Context: Any context. 72 + */ 73 + static inline void blake2b_init(struct blake2b_ctx *ctx, size_t outlen) 74 + { 75 + __blake2b_init(ctx, outlen, NULL, 0); 76 + } 77 + 78 + /** 79 + * blake2b_init_key() - Initialize a BLAKE2b context for a new message (keyed) 80 + * @ctx: the context to initialize 81 + * @outlen: length of output hash value in bytes, at most BLAKE2B_HASH_SIZE 82 + * @key: the key 83 + * @keylen: the key length in bytes, at most BLAKE2B_KEY_SIZE 84 + * 85 + * Context: Any context. 86 + */ 87 + static inline void blake2b_init_key(struct blake2b_ctx *ctx, size_t outlen, 88 + const void *key, size_t keylen) 89 + { 90 + WARN_ON(IS_ENABLED(DEBUG) && (!outlen || outlen > BLAKE2B_HASH_SIZE || 91 + !key || !keylen || keylen > BLAKE2B_KEY_SIZE)); 92 + 93 + __blake2b_init(ctx, outlen, key, keylen); 94 + } 95 + 96 + /** 97 + * blake2b_update() - Update a BLAKE2b context with message data 98 + * @ctx: the context to update; must have been initialized 99 + * @in: the message data 100 + * @inlen: the data length in bytes 101 + * 102 + * This can be called any number of times. 103 + * 104 + * Context: Any context. 105 + */ 106 + void blake2b_update(struct blake2b_ctx *ctx, const u8 *in, size_t inlen); 107 + 108 + /** 109 + * blake2b_final() - Finish computing a BLAKE2b hash 110 + * @ctx: the context to finalize; must have been initialized 111 + * @out: (output) the resulting BLAKE2b hash. Its length will be equal to the 112 + * @outlen that was passed to blake2b_init() or blake2b_init_key(). 113 + * 114 + * After finishing, this zeroizes @ctx. So the caller does not need to do it. 115 + * 116 + * Context: Any context. 117 + */ 118 + void blake2b_final(struct blake2b_ctx *ctx, u8 *out); 119 + 120 + /** 121 + * blake2b() - Compute BLAKE2b hash in one shot 122 + * @key: the key, or NULL for an unkeyed hash 123 + * @keylen: the key length in bytes (at most BLAKE2B_KEY_SIZE), or 0 for an 124 + * unkeyed hash 125 + * @in: the message data 126 + * @inlen: the data length in bytes 127 + * @out: (output) the resulting BLAKE2b hash, with length @outlen 128 + * @outlen: length of output hash value in bytes, at most BLAKE2B_HASH_SIZE 129 + * 130 + * Context: Any context. 131 + */ 132 + static inline void blake2b(const u8 *key, size_t keylen, 133 + const u8 *in, size_t inlen, 134 + u8 *out, size_t outlen) 135 + { 136 + struct blake2b_ctx ctx; 137 + 138 + WARN_ON(IS_ENABLED(DEBUG) && ((!in && inlen > 0) || !out || !outlen || 139 + outlen > BLAKE2B_HASH_SIZE || keylen > BLAKE2B_KEY_SIZE || 140 + (!key && keylen))); 141 + 142 + __blake2b_init(&ctx, outlen, key, keylen); 143 + blake2b_update(&ctx, in, inlen); 144 + blake2b_final(&ctx, out); 74 145 } 75 146 76 147 #endif /* _CRYPTO_BLAKE2B_H */
+16 -1
include/crypto/internal/blake2b.h
··· 57 57 return 0; 58 58 } 59 59 60 + static inline void __crypto_blake2b_init(struct blake2b_state *state, 61 + size_t outlen, size_t keylen) 62 + { 63 + state->h[0] = BLAKE2B_IV0 ^ (0x01010000 | keylen << 8 | outlen); 64 + state->h[1] = BLAKE2B_IV1; 65 + state->h[2] = BLAKE2B_IV2; 66 + state->h[3] = BLAKE2B_IV3; 67 + state->h[4] = BLAKE2B_IV4; 68 + state->h[5] = BLAKE2B_IV5; 69 + state->h[6] = BLAKE2B_IV6; 70 + state->h[7] = BLAKE2B_IV7; 71 + state->t[0] = 0; 72 + state->t[1] = 0; 73 + } 74 + 60 75 static inline int crypto_blake2b_init(struct shash_desc *desc) 61 76 { 62 77 const struct blake2b_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); 63 78 struct blake2b_state *state = shash_desc_ctx(desc); 64 79 unsigned int outlen = crypto_shash_digestsize(desc->tfm); 65 80 66 - __blake2b_init(state, outlen, tctx->keylen); 81 + __crypto_blake2b_init(state, outlen, tctx->keylen); 67 82 return tctx->keylen ? 68 83 crypto_shash_update(desc, tctx->key, BLAKE2B_BLOCK_SIZE) : 0; 69 84 }
+10
lib/crypto/Kconfig
··· 28 28 config CRYPTO_LIB_GF128MUL 29 29 tristate 30 30 31 + config CRYPTO_LIB_BLAKE2B 32 + tristate 33 + help 34 + The BLAKE2b library functions. Select this if your module uses any of 35 + the functions from <crypto/blake2b.h>. 36 + 37 + config CRYPTO_LIB_BLAKE2B_ARCH 38 + bool 39 + depends on CRYPTO_LIB_BLAKE2B && !UML 40 + 31 41 # BLAKE2s support is always built-in, so there's no CRYPTO_LIB_BLAKE2S option. 32 42 33 43 config CRYPTO_LIB_BLAKE2S_ARCH
+9
lib/crypto/Makefile
··· 31 31 32 32 ################################################################################ 33 33 34 + obj-$(CONFIG_CRYPTO_LIB_BLAKE2B) += libblake2b.o 35 + libblake2b-y := blake2b.o 36 + CFLAGS_blake2b.o := -Wframe-larger-than=4096 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105930 37 + ifeq ($(CONFIG_CRYPTO_LIB_BLAKE2B_ARCH),y) 38 + CFLAGS_blake2b.o += -I$(src)/$(SRCARCH) 39 + endif # CONFIG_CRYPTO_LIB_BLAKE2B_ARCH 40 + 41 + ################################################################################ 42 + 34 43 # blake2s is used by the /dev/random driver which is always builtin 35 44 obj-y += blake2s.o 36 45 ifeq ($(CONFIG_CRYPTO_LIB_BLAKE2S_ARCH),y)
+174
lib/crypto/blake2b.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 OR MIT 2 + /* 3 + * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 4 + * Copyright 2025 Google LLC 5 + * 6 + * This is an implementation of the BLAKE2b hash and PRF functions. 7 + * 8 + * Information: https://blake2.net/ 9 + */ 10 + 11 + #include <crypto/blake2b.h> 12 + #include <linux/bug.h> 13 + #include <linux/export.h> 14 + #include <linux/kernel.h> 15 + #include <linux/module.h> 16 + #include <linux/string.h> 17 + #include <linux/types.h> 18 + 19 + static const u8 blake2b_sigma[12][16] = { 20 + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, 21 + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, 22 + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, 23 + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, 24 + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, 25 + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, 26 + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, 27 + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, 28 + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, 29 + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, 30 + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, 31 + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } 32 + }; 33 + 34 + static inline void blake2b_increment_counter(struct blake2b_ctx *ctx, u32 inc) 35 + { 36 + ctx->t[0] += inc; 37 + ctx->t[1] += (ctx->t[0] < inc); 38 + } 39 + 40 + static void __maybe_unused 41 + blake2b_compress_generic(struct blake2b_ctx *ctx, 42 + const u8 *data, size_t nblocks, u32 inc) 43 + { 44 + u64 m[16]; 45 + u64 v[16]; 46 + int i; 47 + 48 + WARN_ON(IS_ENABLED(DEBUG) && 49 + (nblocks > 1 && inc != BLAKE2B_BLOCK_SIZE)); 50 + 51 + while (nblocks > 0) { 52 + blake2b_increment_counter(ctx, inc); 53 + memcpy(m, data, BLAKE2B_BLOCK_SIZE); 54 + le64_to_cpu_array(m, ARRAY_SIZE(m)); 55 + memcpy(v, ctx->h, 64); 56 + v[ 8] = BLAKE2B_IV0; 57 + v[ 9] = BLAKE2B_IV1; 58 + v[10] = BLAKE2B_IV2; 59 + v[11] = BLAKE2B_IV3; 60 + v[12] = BLAKE2B_IV4 ^ ctx->t[0]; 61 + v[13] = BLAKE2B_IV5 ^ ctx->t[1]; 62 + v[14] = BLAKE2B_IV6 ^ ctx->f[0]; 63 + v[15] = BLAKE2B_IV7 ^ ctx->f[1]; 64 + 65 + #define G(r, i, a, b, c, d) do { \ 66 + a += b + m[blake2b_sigma[r][2 * i + 0]]; \ 67 + d = ror64(d ^ a, 32); \ 68 + c += d; \ 69 + b = ror64(b ^ c, 24); \ 70 + a += b + m[blake2b_sigma[r][2 * i + 1]]; \ 71 + d = ror64(d ^ a, 16); \ 72 + c += d; \ 73 + b = ror64(b ^ c, 63); \ 74 + } while (0) 75 + 76 + #define ROUND(r) do { \ 77 + G(r, 0, v[0], v[ 4], v[ 8], v[12]); \ 78 + G(r, 1, v[1], v[ 5], v[ 9], v[13]); \ 79 + G(r, 2, v[2], v[ 6], v[10], v[14]); \ 80 + G(r, 3, v[3], v[ 7], v[11], v[15]); \ 81 + G(r, 4, v[0], v[ 5], v[10], v[15]); \ 82 + G(r, 5, v[1], v[ 6], v[11], v[12]); \ 83 + G(r, 6, v[2], v[ 7], v[ 8], v[13]); \ 84 + G(r, 7, v[3], v[ 4], v[ 9], v[14]); \ 85 + } while (0) 86 + ROUND(0); 87 + ROUND(1); 88 + ROUND(2); 89 + ROUND(3); 90 + ROUND(4); 91 + ROUND(5); 92 + ROUND(6); 93 + ROUND(7); 94 + ROUND(8); 95 + ROUND(9); 96 + ROUND(10); 97 + ROUND(11); 98 + 99 + #undef G 100 + #undef ROUND 101 + 102 + for (i = 0; i < 8; ++i) 103 + ctx->h[i] ^= v[i] ^ v[i + 8]; 104 + 105 + data += BLAKE2B_BLOCK_SIZE; 106 + --nblocks; 107 + } 108 + } 109 + 110 + #ifdef CONFIG_CRYPTO_LIB_BLAKE2B_ARCH 111 + #include "blake2b.h" /* $(SRCARCH)/blake2b.h */ 112 + #else 113 + #define blake2b_compress blake2b_compress_generic 114 + #endif 115 + 116 + static inline void blake2b_set_lastblock(struct blake2b_ctx *ctx) 117 + { 118 + ctx->f[0] = -1; 119 + } 120 + 121 + void blake2b_update(struct blake2b_ctx *ctx, const u8 *in, size_t inlen) 122 + { 123 + const size_t fill = BLAKE2B_BLOCK_SIZE - ctx->buflen; 124 + 125 + if (unlikely(!inlen)) 126 + return; 127 + if (inlen > fill) { 128 + memcpy(ctx->buf + ctx->buflen, in, fill); 129 + blake2b_compress(ctx, ctx->buf, 1, BLAKE2B_BLOCK_SIZE); 130 + ctx->buflen = 0; 131 + in += fill; 132 + inlen -= fill; 133 + } 134 + if (inlen > BLAKE2B_BLOCK_SIZE) { 135 + const size_t nblocks = DIV_ROUND_UP(inlen, BLAKE2B_BLOCK_SIZE); 136 + 137 + blake2b_compress(ctx, in, nblocks - 1, BLAKE2B_BLOCK_SIZE); 138 + in += BLAKE2B_BLOCK_SIZE * (nblocks - 1); 139 + inlen -= BLAKE2B_BLOCK_SIZE * (nblocks - 1); 140 + } 141 + memcpy(ctx->buf + ctx->buflen, in, inlen); 142 + ctx->buflen += inlen; 143 + } 144 + EXPORT_SYMBOL(blake2b_update); 145 + 146 + void blake2b_final(struct blake2b_ctx *ctx, u8 *out) 147 + { 148 + WARN_ON(IS_ENABLED(DEBUG) && !out); 149 + blake2b_set_lastblock(ctx); 150 + memset(ctx->buf + ctx->buflen, 0, 151 + BLAKE2B_BLOCK_SIZE - ctx->buflen); /* Padding */ 152 + blake2b_compress(ctx, ctx->buf, 1, ctx->buflen); 153 + cpu_to_le64_array(ctx->h, ARRAY_SIZE(ctx->h)); 154 + memcpy(out, ctx->h, ctx->outlen); 155 + memzero_explicit(ctx, sizeof(*ctx)); 156 + } 157 + EXPORT_SYMBOL(blake2b_final); 158 + 159 + #ifdef blake2b_mod_init_arch 160 + static int __init blake2b_mod_init(void) 161 + { 162 + blake2b_mod_init_arch(); 163 + return 0; 164 + } 165 + subsys_initcall(blake2b_mod_init); 166 + 167 + static void __exit blake2b_mod_exit(void) 168 + { 169 + } 170 + module_exit(blake2b_mod_exit); 171 + #endif 172 + 173 + MODULE_DESCRIPTION("BLAKE2b hash function"); 174 + MODULE_LICENSE("GPL");