crypto: lib/sha256 - Move partial block handling out
authorHerbert Xu <herbert@gondor.apana.org.au>
Mon, 28 Apr 2025 04:56:05 +0000 (12:56 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Mon, 5 May 2025 05:32:01 +0000 (13:32 +0800)
Extract the common partial block handling into a helper macro
that can be reused by other library code.

Also delete the unused sha256_base_do_finalize function.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
include/crypto/internal/blockhash.h [new file with mode: 0644]
include/crypto/sha2.h
include/crypto/sha256_base.h

diff --git a/include/crypto/internal/blockhash.h b/include/crypto/internal/blockhash.h
new file mode 100644 (file)
index 0000000..52d9d4c
--- /dev/null
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Handle partial blocks for block hash.
+ *
+ * Copyright (c) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
+ * Copyright (c) 2025 Herbert Xu <herbert@gondor.apana.org.au>
+ */
+
+#ifndef _CRYPTO_INTERNAL_BLOCKHASH_H
+#define _CRYPTO_INTERNAL_BLOCKHASH_H
+
+#include <linux/string.h>
+#include <linux/types.h>
+
+#define BLOCK_HASH_UPDATE_BASE(block_fn, state, src, nbytes, bs, dv,   \
+                              buf, buflen)                             \
+       ({                                                              \
+               typeof(block_fn) *_block_fn = &(block_fn);              \
+               typeof(state + 0) _state = (state);                     \
+               unsigned int _buflen = (buflen);                        \
+               size_t _nbytes = (nbytes);                              \
+               unsigned int _bs = (bs);                                \
+               const u8 *_src = (src);                                 \
+               u8 *_buf = (buf);                                       \
+               while ((_buflen + _nbytes) >= _bs) {                    \
+                       const u8 *data = _src;                          \
+                       size_t len = _nbytes;                           \
+                       size_t blocks;                                  \
+                       int remain;                                     \
+                       if (_buflen) {                                  \
+                               remain = _bs - _buflen;                 \
+                               memcpy(_buf + _buflen, _src, remain);   \
+                               data = _buf;                            \
+                               len = _bs;                              \
+                       }                                               \
+                       remain = len % bs;                              \
+                       blocks = (len - remain) / (dv);                 \
+                       (*_block_fn)(_state, data, blocks);             \
+                       _src += len - remain - _buflen;                 \
+                       _nbytes -= len - remain - _buflen;              \
+                       _buflen = 0;                                    \
+               }                                                       \
+               memcpy(_buf + _buflen, _src, _nbytes);                  \
+               _buflen += _nbytes;                                     \
+       })
+
+#define BLOCK_HASH_UPDATE(block, state, src, nbytes, bs, buf, buflen) \
+       BLOCK_HASH_UPDATE_BASE(block, state, src, nbytes, bs, 1, buf, buflen)
+#define BLOCK_HASH_UPDATE_BLOCKS(block, state, src, nbytes, bs, buf, buflen) \
+       BLOCK_HASH_UPDATE_BASE(block, state, src, nbytes, bs, bs, buf, buflen)
+
+#endif /* _CRYPTO_INTERNAL_BLOCKHASH_H */
index abbd882f7849f85d930eef65c4c47154815ffdf1..f873c2207b1eaffd648a46cef478fc85972d2df7 100644 (file)
@@ -71,8 +71,13 @@ struct crypto_sha256_state {
 };
 
 struct sha256_state {
-       u32 state[SHA256_DIGEST_SIZE / 4];
-       u64 count;
+       union {
+               struct crypto_sha256_state ctx;
+               struct {
+                       u32 state[SHA256_DIGEST_SIZE / 4];
+                       u64 count;
+               };
+       };
        u8 buf[SHA256_BLOCK_SIZE];
 };
 
index 08cd5e41d4fdb5ebd60c2d8ad9e10b5a2f218c7f..9f284bed5a5110662d0dc9cc2b3d3cd594c1085b 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef _CRYPTO_SHA256_BASE_H
 #define _CRYPTO_SHA256_BASE_H
 
+#include <crypto/internal/blockhash.h>
 #include <crypto/internal/hash.h>
 #include <crypto/sha2.h>
 #include <linux/math.h>
@@ -40,35 +41,10 @@ static inline int lib_sha256_base_do_update(struct sha256_state *sctx,
                                            sha256_block_fn *block_fn)
 {
        unsigned int partial = sctx->count % SHA256_BLOCK_SIZE;
-       struct crypto_sha256_state *state = (void *)sctx;
 
        sctx->count += len;
-
-       if (unlikely((partial + len) >= SHA256_BLOCK_SIZE)) {
-               int blocks;
-
-               if (partial) {
-                       int p = SHA256_BLOCK_SIZE - partial;
-
-                       memcpy(sctx->buf + partial, data, p);
-                       data += p;
-                       len -= p;
-
-                       block_fn(state, sctx->buf, 1);
-               }
-
-               blocks = len / SHA256_BLOCK_SIZE;
-               len %= SHA256_BLOCK_SIZE;
-
-               if (blocks) {
-                       block_fn(state, data, blocks);
-                       data += blocks * SHA256_BLOCK_SIZE;
-               }
-               partial = 0;
-       }
-       if (len)
-               memcpy(sctx->buf + partial, data, len);
-
+       BLOCK_HASH_UPDATE_BLOCKS(block_fn, &sctx->ctx, data, len,
+                                SHA256_BLOCK_SIZE, sctx->buf, partial);
        return 0;
 }
 
@@ -140,14 +116,6 @@ static inline int lib_sha256_base_do_finalize(struct sha256_state *sctx,
        return lib_sha256_base_do_finup(state, sctx->buf, partial, block_fn);
 }
 
-static inline int sha256_base_do_finalize(struct shash_desc *desc,
-                                         sha256_block_fn *block_fn)
-{
-       struct sha256_state *sctx = shash_desc_ctx(desc);
-
-       return lib_sha256_base_do_finalize(sctx, block_fn);
-}
-
 static inline int __sha256_base_finish(u32 state[SHA256_DIGEST_SIZE / 4],
                                       u8 *out, unsigned int digest_size)
 {