* [PATCH v2 01/14] libceph: Rename hmac_sha256() to ceph_hmac_sha256()
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 02/14] cxl/test: Simplify fw_buf_checksum_show() Eric Biggers
` (14 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
Rename hmac_sha256() to ceph_hmac_sha256(), to avoid a naming conflict
with the upcoming hmac_sha256() library function.
This code will be able to use the HMAC-SHA256 library, but that's left
for a later commit.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
net/ceph/messenger_v2.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c
index bd608ffa06279..5483b4eed94e1 100644
--- a/net/ceph/messenger_v2.c
+++ b/net/ceph/messenger_v2.c
@@ -791,12 +791,12 @@ static int setup_crypto(struct ceph_connection *con,
con_secret + CEPH_GCM_KEY_LEN + CEPH_GCM_IV_LEN,
CEPH_GCM_IV_LEN);
return 0; /* auth_x, secure mode */
}
-static int hmac_sha256(struct ceph_connection *con, const struct kvec *kvecs,
- int kvec_cnt, u8 *hmac)
+static int ceph_hmac_sha256(struct ceph_connection *con,
+ const struct kvec *kvecs, int kvec_cnt, u8 *hmac)
{
SHASH_DESC_ON_STACK(desc, con->v2.hmac_tfm); /* tfm arg is ignored */
int ret;
int i;
@@ -1460,12 +1460,12 @@ static int prepare_auth_signature(struct ceph_connection *con)
buf = alloc_conn_buf(con, head_onwire_len(SHA256_DIGEST_SIZE,
con_secure(con)));
if (!buf)
return -ENOMEM;
- ret = hmac_sha256(con, con->v2.in_sign_kvecs, con->v2.in_sign_kvec_cnt,
- CTRL_BODY(buf));
+ ret = ceph_hmac_sha256(con, con->v2.in_sign_kvecs,
+ con->v2.in_sign_kvec_cnt, CTRL_BODY(buf));
if (ret)
return ret;
return prepare_control(con, FRAME_TAG_AUTH_SIGNATURE, buf,
SHA256_DIGEST_SIZE);
@@ -2458,12 +2458,12 @@ static int process_auth_signature(struct ceph_connection *con,
if (con->state != CEPH_CON_S_V2_AUTH_SIGNATURE) {
con->error_msg = "protocol error, unexpected auth_signature";
return -EINVAL;
}
- ret = hmac_sha256(con, con->v2.out_sign_kvecs,
- con->v2.out_sign_kvec_cnt, hmac);
+ ret = ceph_hmac_sha256(con, con->v2.out_sign_kvecs,
+ con->v2.out_sign_kvec_cnt, hmac);
if (ret)
return ret;
ceph_decode_need(&p, end, SHA256_DIGEST_SIZE, bad);
if (crypto_memneq(p, hmac, SHA256_DIGEST_SIZE)) {
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 02/14] cxl/test: Simplify fw_buf_checksum_show()
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
2025-06-30 16:06 ` [PATCH v2 01/14] libceph: Rename hmac_sha256() to ceph_hmac_sha256() Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 03/14] lib/crypto: sha256: Reorder some code Eric Biggers
` (13 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
First, just use sha256() instead of a sequence of sha256_init(),
sha256_update(), and sha256_final(). The result is the same.
Second, use *phN instead of open-coding the conversion of bytes to hex.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
tools/testing/cxl/test/mem.c | 21 ++-------------------
1 file changed, 2 insertions(+), 19 deletions(-)
diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index 0f1d91f57ba34..d533481672b78 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -1826,31 +1826,14 @@ static DEVICE_ATTR_RW(security_lock);
static ssize_t fw_buf_checksum_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct cxl_mockmem_data *mdata = dev_get_drvdata(dev);
u8 hash[SHA256_DIGEST_SIZE];
- unsigned char *hstr, *hptr;
- struct sha256_state sctx;
- ssize_t written = 0;
- int i;
-
- sha256_init(&sctx);
- sha256_update(&sctx, mdata->fw, mdata->fw_size);
- sha256_final(&sctx, hash);
-
- hstr = kzalloc((SHA256_DIGEST_SIZE * 2) + 1, GFP_KERNEL);
- if (!hstr)
- return -ENOMEM;
-
- hptr = hstr;
- for (i = 0; i < SHA256_DIGEST_SIZE; i++)
- hptr += sprintf(hptr, "%02x", hash[i]);
- written = sysfs_emit(buf, "%s\n", hstr);
+ sha256(mdata->fw, mdata->fw_size, hash);
- kfree(hstr);
- return written;
+ return sysfs_emit(buf, "%*phN\n", SHA256_DIGEST_SIZE, hash);
}
static DEVICE_ATTR_RO(fw_buf_checksum);
static ssize_t sanitize_timeout_show(struct device *dev,
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 03/14] lib/crypto: sha256: Reorder some code
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
2025-06-30 16:06 ` [PATCH v2 01/14] libceph: Rename hmac_sha256() to ceph_hmac_sha256() Eric Biggers
2025-06-30 16:06 ` [PATCH v2 02/14] cxl/test: Simplify fw_buf_checksum_show() Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 04/14] lib/crypto: sha256: Remove sha256_blocks_simd() Eric Biggers
` (12 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
First, move the declarations of sha224_init/update/final to be just
above the corresponding SHA-256 code, matching the order that I used for
SHA-384 and SHA-512. In sha2.h, the end result is that SHA-224,
SHA-256, SHA-384, and SHA-512 are all in the logical order.
Second, move sha224_block_init() and sha256_block_init() to be just
below crypto_sha256_state. In later changes, these functions as well as
struct crypto_sha256_state will no longer be used by the library
functions. They'll remain just for some legacy offload drivers. This
gets them into a logical place in the file for that.
No code changes other than reordering.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
include/crypto/sha2.h | 60 +++++++++++++++++++++----------------------
lib/crypto/sha256.c | 12 ++++-----
2 files changed, 36 insertions(+), 36 deletions(-)
diff --git a/include/crypto/sha2.h b/include/crypto/sha2.h
index 296ce9d468bfc..bb181b7996cdc 100644
--- a/include/crypto/sha2.h
+++ b/include/crypto/sha2.h
@@ -69,10 +69,36 @@ extern const u8 sha512_zero_message_hash[SHA512_DIGEST_SIZE];
struct crypto_sha256_state {
u32 state[SHA256_STATE_WORDS];
u64 count;
};
+static inline void sha224_block_init(struct crypto_sha256_state *sctx)
+{
+ sctx->state[0] = SHA224_H0;
+ sctx->state[1] = SHA224_H1;
+ sctx->state[2] = SHA224_H2;
+ sctx->state[3] = SHA224_H3;
+ sctx->state[4] = SHA224_H4;
+ sctx->state[5] = SHA224_H5;
+ sctx->state[6] = SHA224_H6;
+ sctx->state[7] = SHA224_H7;
+ sctx->count = 0;
+}
+
+static inline void sha256_block_init(struct crypto_sha256_state *sctx)
+{
+ sctx->state[0] = SHA256_H0;
+ sctx->state[1] = SHA256_H1;
+ sctx->state[2] = SHA256_H2;
+ sctx->state[3] = SHA256_H3;
+ sctx->state[4] = SHA256_H4;
+ sctx->state[5] = SHA256_H5;
+ sctx->state[6] = SHA256_H6;
+ sctx->state[7] = SHA256_H7;
+ sctx->count = 0;
+}
+
struct sha256_state {
union {
struct crypto_sha256_state ctx;
struct {
u32 state[SHA256_STATE_WORDS];
@@ -86,51 +112,25 @@ struct sha512_state {
u64 state[SHA512_DIGEST_SIZE / 8];
u64 count[2];
u8 buf[SHA512_BLOCK_SIZE];
};
-static inline void sha256_block_init(struct crypto_sha256_state *sctx)
+static inline void sha224_init(struct sha256_state *sctx)
{
- sctx->state[0] = SHA256_H0;
- sctx->state[1] = SHA256_H1;
- sctx->state[2] = SHA256_H2;
- sctx->state[3] = SHA256_H3;
- sctx->state[4] = SHA256_H4;
- sctx->state[5] = SHA256_H5;
- sctx->state[6] = SHA256_H6;
- sctx->state[7] = SHA256_H7;
- sctx->count = 0;
+ sha224_block_init(&sctx->ctx);
}
+/* Simply use sha256_update as it is equivalent to sha224_update. */
+void sha224_final(struct sha256_state *sctx, u8 out[SHA224_DIGEST_SIZE]);
static inline void sha256_init(struct sha256_state *sctx)
{
sha256_block_init(&sctx->ctx);
}
void sha256_update(struct sha256_state *sctx, const u8 *data, size_t len);
void sha256_final(struct sha256_state *sctx, u8 out[SHA256_DIGEST_SIZE]);
void sha256(const u8 *data, size_t len, u8 out[SHA256_DIGEST_SIZE]);
-static inline void sha224_block_init(struct crypto_sha256_state *sctx)
-{
- sctx->state[0] = SHA224_H0;
- sctx->state[1] = SHA224_H1;
- sctx->state[2] = SHA224_H2;
- sctx->state[3] = SHA224_H3;
- sctx->state[4] = SHA224_H4;
- sctx->state[5] = SHA224_H5;
- sctx->state[6] = SHA224_H6;
- sctx->state[7] = SHA224_H7;
- sctx->count = 0;
-}
-
-static inline void sha224_init(struct sha256_state *sctx)
-{
- sha224_block_init(&sctx->ctx);
-}
-/* Simply use sha256_update as it is equivalent to sha224_update. */
-void sha224_final(struct sha256_state *sctx, u8 out[SHA224_DIGEST_SIZE]);
-
/* State for the SHA-512 (and SHA-384) compression function */
struct sha512_block_state {
u64 h[8];
};
diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
index 6bfa4ae8dfb59..573ccecbf48bf 100644
--- a/lib/crypto/sha256.c
+++ b/lib/crypto/sha256.c
@@ -56,22 +56,22 @@ static inline void __sha256_final(struct sha256_state *sctx, u8 *out,
sha256_finup(&sctx->ctx, sctx->buf, partial, out, digest_size,
sha256_purgatory(), false);
memzero_explicit(sctx, sizeof(*sctx));
}
-void sha256_final(struct sha256_state *sctx, u8 out[SHA256_DIGEST_SIZE])
-{
- __sha256_final(sctx, out, SHA256_DIGEST_SIZE);
-}
-EXPORT_SYMBOL(sha256_final);
-
void sha224_final(struct sha256_state *sctx, u8 out[SHA224_DIGEST_SIZE])
{
__sha256_final(sctx, out, SHA224_DIGEST_SIZE);
}
EXPORT_SYMBOL(sha224_final);
+void sha256_final(struct sha256_state *sctx, u8 out[SHA256_DIGEST_SIZE])
+{
+ __sha256_final(sctx, out, SHA256_DIGEST_SIZE);
+}
+EXPORT_SYMBOL(sha256_final);
+
void sha256(const u8 *data, size_t len, u8 out[SHA256_DIGEST_SIZE])
{
struct sha256_state sctx;
sha256_init(&sctx);
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 04/14] lib/crypto: sha256: Remove sha256_blocks_simd()
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (2 preceding siblings ...)
2025-06-30 16:06 ` [PATCH v2 03/14] lib/crypto: sha256: Reorder some code Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 05/14] lib/crypto: sha256: Add sha224() and sha224_update() Eric Biggers
` (11 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
Instead of having both sha256_blocks_arch() and sha256_blocks_simd(),
instead have just sha256_blocks_arch() which uses the most efficient
implementation that is available in the calling context.
This is simpler, as it reduces the API surface. It's also safer, since
sha256_blocks_arch() just works in all contexts, including contexts
where the FPU/SIMD/vector registers cannot be used. This doesn't mean
that SHA-256 computations *should* be done in such contexts, but rather
we should just do the right thing instead of corrupting a random task's
registers. Eliminating this footgun and simplifying the code is well
worth the very small performance cost of doing the check.
Note: in the case of arm and arm64, what used to be sha256_blocks_arch()
is renamed back to its original name of sha256_block_data_order().
sha256_blocks_arch() is now used for the higher-level dispatch function.
This renaming also required an update to lib/crypto/arm64/sha512.h,
since sha2-armv8.pl is shared by both SHA-256 and SHA-512.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
include/crypto/internal/sha2.h | 6 ------
lib/crypto/Kconfig | 8 --------
lib/crypto/arm/Kconfig | 1 -
lib/crypto/arm/sha256-armv4.pl | 20 ++++++++++----------
lib/crypto/arm/sha256.c | 14 +++++++-------
lib/crypto/arm64/Kconfig | 1 -
lib/crypto/arm64/sha2-armv8.pl | 2 +-
lib/crypto/arm64/sha256.c | 14 +++++++-------
lib/crypto/arm64/sha512.h | 6 +++---
lib/crypto/riscv/Kconfig | 1 -
lib/crypto/riscv/sha256.c | 12 +++---------
lib/crypto/x86/Kconfig | 1 -
lib/crypto/x86/sha256.c | 12 +++---------
13 files changed, 34 insertions(+), 64 deletions(-)
diff --git a/include/crypto/internal/sha2.h b/include/crypto/internal/sha2.h
index 21a27fd5e198f..5a25ccc493886 100644
--- a/include/crypto/internal/sha2.h
+++ b/include/crypto/internal/sha2.h
@@ -1,11 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _CRYPTO_INTERNAL_SHA2_H
#define _CRYPTO_INTERNAL_SHA2_H
-#include <crypto/internal/simd.h>
#include <crypto/sha2.h>
#include <linux/compiler_attributes.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/unaligned.h>
@@ -20,22 +19,17 @@ static inline bool sha256_is_arch_optimized(void)
#endif
void sha256_blocks_generic(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks);
void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks);
-void sha256_blocks_simd(u32 state[SHA256_STATE_WORDS],
- const u8 *data, size_t nblocks);
static __always_inline void sha256_choose_blocks(
u32 state[SHA256_STATE_WORDS], const u8 *data, size_t nblocks,
bool force_generic, bool force_simd)
{
if (!IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_SHA256) || force_generic)
sha256_blocks_generic(state, data, nblocks);
- else if (IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_SHA256_SIMD) &&
- (force_simd || crypto_simd_usable()))
- sha256_blocks_simd(state, data, nblocks);
else
sha256_blocks_arch(state, data, nblocks);
}
static __always_inline void sha256_finup(
diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig
index 2460ddff967fc..9bd740475a898 100644
--- a/lib/crypto/Kconfig
+++ b/lib/crypto/Kconfig
@@ -148,18 +148,10 @@ config CRYPTO_ARCH_HAVE_LIB_SHA256
bool
help
Declares whether the architecture provides an arch-specific
accelerated implementation of the SHA-256 library interface.
-config CRYPTO_ARCH_HAVE_LIB_SHA256_SIMD
- bool
- help
- Declares whether the architecture provides an arch-specific
- accelerated implementation of the SHA-256 library interface
- that is SIMD-based and therefore not usable in hardirq
- context.
-
config CRYPTO_LIB_SHA256_GENERIC
tristate
default CRYPTO_LIB_SHA256 if !CRYPTO_ARCH_HAVE_LIB_SHA256
help
This symbol can be selected by arch implementations of the SHA-256
diff --git a/lib/crypto/arm/Kconfig b/lib/crypto/arm/Kconfig
index d1ad664f0c674..9f3ff30f40328 100644
--- a/lib/crypto/arm/Kconfig
+++ b/lib/crypto/arm/Kconfig
@@ -26,6 +26,5 @@ config CRYPTO_POLY1305_ARM
config CRYPTO_SHA256_ARM
tristate
depends on !CPU_V7M
default CRYPTO_LIB_SHA256
select CRYPTO_ARCH_HAVE_LIB_SHA256
- select CRYPTO_ARCH_HAVE_LIB_SHA256_SIMD
diff --git a/lib/crypto/arm/sha256-armv4.pl b/lib/crypto/arm/sha256-armv4.pl
index 8122db7fd5990..f3a2b54efd4ee 100644
--- a/lib/crypto/arm/sha256-armv4.pl
+++ b/lib/crypto/arm/sha256-armv4.pl
@@ -202,22 +202,22 @@ K256:
.word 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
.size K256,.-K256
.word 0 @ terminator
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
.LOPENSSL_armcap:
-.word OPENSSL_armcap_P-sha256_blocks_arch
+.word OPENSSL_armcap_P-sha256_block_data_order
#endif
.align 5
-.global sha256_blocks_arch
-.type sha256_blocks_arch,%function
-sha256_blocks_arch:
-.Lsha256_blocks_arch:
+.global sha256_block_data_order
+.type sha256_block_data_order,%function
+sha256_block_data_order:
+.Lsha256_block_data_order:
#if __ARM_ARCH__<7
- sub r3,pc,#8 @ sha256_blocks_arch
+ sub r3,pc,#8 @ sha256_block_data_order
#else
- adr r3,.Lsha256_blocks_arch
+ adr r3,.Lsha256_block_data_order
#endif
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
ldr r12,.LOPENSSL_armcap
ldr r12,[r3,r12] @ OPENSSL_armcap_P
tst r12,#ARMV8_SHA256
@@ -280,11 +280,11 @@ $code.=<<___;
ldmia sp!,{r4-r11,lr}
tst lr,#1
moveq pc,lr @ be binary compatible with V4, yet
bx lr @ interoperable with Thumb ISA:-)
#endif
-.size sha256_blocks_arch,.-sha256_blocks_arch
+.size sha256_block_data_order,.-sha256_block_data_order
___
######################################################################
# NEON stuff
#
{{{
@@ -468,12 +468,12 @@ $code.=<<___;
sha256_block_data_order_neon:
.LNEON:
stmdb sp!,{r4-r12,lr}
sub $H,sp,#16*4+16
- adr $Ktbl,.Lsha256_blocks_arch
- sub $Ktbl,$Ktbl,#.Lsha256_blocks_arch-K256
+ adr $Ktbl,.Lsha256_block_data_order
+ sub $Ktbl,$Ktbl,#.Lsha256_block_data_order-K256
bic $H,$H,#15 @ align for 128-bit stores
mov $t2,sp
mov sp,$H @ alloca
add $len,$inp,$len,lsl#6 @ len to point at the end of inp
diff --git a/lib/crypto/arm/sha256.c b/lib/crypto/arm/sha256.c
index 109192e54b0f0..2c9cfdaaa0691 100644
--- a/lib/crypto/arm/sha256.c
+++ b/lib/crypto/arm/sha256.c
@@ -4,40 +4,40 @@
*
* Copyright 2025 Google LLC
*/
#include <asm/neon.h>
#include <crypto/internal/sha2.h>
+#include <crypto/internal/simd.h>
#include <linux/kernel.h>
#include <linux/module.h>
-asmlinkage void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
- const u8 *data, size_t nblocks);
-EXPORT_SYMBOL_GPL(sha256_blocks_arch);
+asmlinkage void sha256_block_data_order(u32 state[SHA256_STATE_WORDS],
+ const u8 *data, size_t nblocks);
asmlinkage void sha256_block_data_order_neon(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks);
asmlinkage void sha256_ce_transform(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_ce);
-void sha256_blocks_simd(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
- static_branch_likely(&have_neon)) {
+ static_branch_likely(&have_neon) && crypto_simd_usable()) {
kernel_neon_begin();
if (static_branch_likely(&have_ce))
sha256_ce_transform(state, data, nblocks);
else
sha256_block_data_order_neon(state, data, nblocks);
kernel_neon_end();
} else {
- sha256_blocks_arch(state, data, nblocks);
+ sha256_block_data_order(state, data, nblocks);
}
}
-EXPORT_SYMBOL_GPL(sha256_blocks_simd);
+EXPORT_SYMBOL_GPL(sha256_blocks_arch);
bool sha256_is_arch_optimized(void)
{
/* We always can use at least the ARM scalar implementation. */
return true;
diff --git a/lib/crypto/arm64/Kconfig b/lib/crypto/arm64/Kconfig
index 129a7685cb4c1..49e57bfdb5b52 100644
--- a/lib/crypto/arm64/Kconfig
+++ b/lib/crypto/arm64/Kconfig
@@ -15,6 +15,5 @@ config CRYPTO_POLY1305_NEON
config CRYPTO_SHA256_ARM64
tristate
default CRYPTO_LIB_SHA256
select CRYPTO_ARCH_HAVE_LIB_SHA256
- select CRYPTO_ARCH_HAVE_LIB_SHA256_SIMD
diff --git a/lib/crypto/arm64/sha2-armv8.pl b/lib/crypto/arm64/sha2-armv8.pl
index 4aebd20c498bc..35ec9ae99fe16 100644
--- a/lib/crypto/arm64/sha2-armv8.pl
+++ b/lib/crypto/arm64/sha2-armv8.pl
@@ -93,11 +93,11 @@ if ($output =~ /512/) {
@sigma1=(17,19,10);
$rounds=64;
$reg_t="w";
}
-$func="sha${BITS}_blocks_arch";
+$func="sha${BITS}_block_data_order";
($ctx,$inp,$num,$Ktbl)=map("x$_",(0..2,30));
@X=map("$reg_t$_",(3..15,0..2));
@V=($A,$B,$C,$D,$E,$F,$G,$H)=map("$reg_t$_",(20..27));
diff --git a/lib/crypto/arm64/sha256.c b/lib/crypto/arm64/sha256.c
index bcf7a3adc0c46..fb9bff40357be 100644
--- a/lib/crypto/arm64/sha256.c
+++ b/lib/crypto/arm64/sha256.c
@@ -4,29 +4,29 @@
*
* Copyright 2025 Google LLC
*/
#include <asm/neon.h>
#include <crypto/internal/sha2.h>
+#include <crypto/internal/simd.h>
#include <linux/kernel.h>
#include <linux/module.h>
-asmlinkage void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
- const u8 *data, size_t nblocks);
-EXPORT_SYMBOL_GPL(sha256_blocks_arch);
+asmlinkage void sha256_block_data_order(u32 state[SHA256_STATE_WORDS],
+ const u8 *data, size_t nblocks);
asmlinkage void sha256_block_neon(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks);
asmlinkage size_t __sha256_ce_transform(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_ce);
-void sha256_blocks_simd(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
- static_branch_likely(&have_neon)) {
+ static_branch_likely(&have_neon) && crypto_simd_usable()) {
if (static_branch_likely(&have_ce)) {
do {
size_t rem;
kernel_neon_begin();
@@ -40,14 +40,14 @@ void sha256_blocks_simd(u32 state[SHA256_STATE_WORDS],
kernel_neon_begin();
sha256_block_neon(state, data, nblocks);
kernel_neon_end();
}
} else {
- sha256_blocks_arch(state, data, nblocks);
+ sha256_block_data_order(state, data, nblocks);
}
}
-EXPORT_SYMBOL_GPL(sha256_blocks_simd);
+EXPORT_SYMBOL_GPL(sha256_blocks_arch);
bool sha256_is_arch_optimized(void)
{
/* We always can use at least the ARM64 scalar implementation. */
return true;
diff --git a/lib/crypto/arm64/sha512.h b/lib/crypto/arm64/sha512.h
index eae14f9752e0b..6abb40b467f2e 100644
--- a/lib/crypto/arm64/sha512.h
+++ b/lib/crypto/arm64/sha512.h
@@ -9,12 +9,12 @@
#include <crypto/internal/simd.h>
#include <linux/cpufeature.h>
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_sha512_insns);
-asmlinkage void sha512_blocks_arch(struct sha512_block_state *state,
- const u8 *data, size_t nblocks);
+asmlinkage void sha512_block_data_order(struct sha512_block_state *state,
+ const u8 *data, size_t nblocks);
asmlinkage size_t __sha512_ce_transform(struct sha512_block_state *state,
const u8 *data, size_t nblocks);
static void sha512_blocks(struct sha512_block_state *state,
const u8 *data, size_t nblocks)
@@ -30,11 +30,11 @@ static void sha512_blocks(struct sha512_block_state *state,
kernel_neon_end();
data += (nblocks - rem) * SHA512_BLOCK_SIZE;
nblocks = rem;
} while (nblocks);
} else {
- sha512_blocks_arch(state, data, nblocks);
+ sha512_block_data_order(state, data, nblocks);
}
}
#ifdef CONFIG_KERNEL_MODE_NEON
#define sha512_mod_init_arch sha512_mod_init_arch
diff --git a/lib/crypto/riscv/Kconfig b/lib/crypto/riscv/Kconfig
index 47c99ea97ce2c..c100571feb7e8 100644
--- a/lib/crypto/riscv/Kconfig
+++ b/lib/crypto/riscv/Kconfig
@@ -10,7 +10,6 @@ config CRYPTO_CHACHA_RISCV64
config CRYPTO_SHA256_RISCV64
tristate
depends on 64BIT && RISCV_ISA_V && TOOLCHAIN_HAS_VECTOR_CRYPTO
default CRYPTO_LIB_SHA256
select CRYPTO_ARCH_HAVE_LIB_SHA256
- select CRYPTO_ARCH_HAVE_LIB_SHA256_SIMD
select CRYPTO_LIB_SHA256_GENERIC
diff --git a/lib/crypto/riscv/sha256.c b/lib/crypto/riscv/sha256.c
index 71808397dff4c..aa77349d08f30 100644
--- a/lib/crypto/riscv/sha256.c
+++ b/lib/crypto/riscv/sha256.c
@@ -9,36 +9,30 @@
* Author: Jerry Shih <jerry.shih@sifive.com>
*/
#include <asm/vector.h>
#include <crypto/internal/sha2.h>
+#include <crypto/internal/simd.h>
#include <linux/kernel.h>
#include <linux/module.h>
asmlinkage void sha256_transform_zvknha_or_zvknhb_zvkb(
u32 state[SHA256_STATE_WORDS], const u8 *data, size_t nblocks);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_extensions);
-void sha256_blocks_simd(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks)
{
- if (static_branch_likely(&have_extensions)) {
+ if (static_branch_likely(&have_extensions) && crypto_simd_usable()) {
kernel_vector_begin();
sha256_transform_zvknha_or_zvknhb_zvkb(state, data, nblocks);
kernel_vector_end();
} else {
sha256_blocks_generic(state, data, nblocks);
}
}
-EXPORT_SYMBOL_GPL(sha256_blocks_simd);
-
-void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
- const u8 *data, size_t nblocks)
-{
- sha256_blocks_generic(state, data, nblocks);
-}
EXPORT_SYMBOL_GPL(sha256_blocks_arch);
bool sha256_is_arch_optimized(void)
{
return static_key_enabled(&have_extensions);
diff --git a/lib/crypto/x86/Kconfig b/lib/crypto/x86/Kconfig
index 5e94cdee492c2..e344579db3d85 100644
--- a/lib/crypto/x86/Kconfig
+++ b/lib/crypto/x86/Kconfig
@@ -28,7 +28,6 @@ config CRYPTO_POLY1305_X86_64
config CRYPTO_SHA256_X86_64
tristate
depends on 64BIT
default CRYPTO_LIB_SHA256
select CRYPTO_ARCH_HAVE_LIB_SHA256
- select CRYPTO_ARCH_HAVE_LIB_SHA256_SIMD
select CRYPTO_LIB_SHA256_GENERIC
diff --git a/lib/crypto/x86/sha256.c b/lib/crypto/x86/sha256.c
index 80380f8fdcee4..baba74d7d26f2 100644
--- a/lib/crypto/x86/sha256.c
+++ b/lib/crypto/x86/sha256.c
@@ -4,10 +4,11 @@
*
* Copyright 2025 Google LLC
*/
#include <asm/fpu/api.h>
#include <crypto/internal/sha2.h>
+#include <crypto/internal/simd.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/static_call.h>
asmlinkage void sha256_transform_ssse3(u32 state[SHA256_STATE_WORDS],
@@ -21,28 +22,21 @@ asmlinkage void sha256_ni_transform(u32 state[SHA256_STATE_WORDS],
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_sha256_x86);
DEFINE_STATIC_CALL(sha256_blocks_x86, sha256_transform_ssse3);
-void sha256_blocks_simd(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
const u8 *data, size_t nblocks)
{
- if (static_branch_likely(&have_sha256_x86)) {
+ if (static_branch_likely(&have_sha256_x86) && crypto_simd_usable()) {
kernel_fpu_begin();
static_call(sha256_blocks_x86)(state, data, nblocks);
kernel_fpu_end();
} else {
sha256_blocks_generic(state, data, nblocks);
}
}
-EXPORT_SYMBOL_GPL(sha256_blocks_simd);
-
-void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
- const u8 *data, size_t nblocks)
-{
- sha256_blocks_generic(state, data, nblocks);
-}
EXPORT_SYMBOL_GPL(sha256_blocks_arch);
bool sha256_is_arch_optimized(void)
{
return static_key_enabled(&have_sha256_x86);
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 05/14] lib/crypto: sha256: Add sha224() and sha224_update()
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (3 preceding siblings ...)
2025-06-30 16:06 ` [PATCH v2 04/14] lib/crypto: sha256: Remove sha256_blocks_simd() Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 06/14] lib/crypto: sha256: Make library API use strongly-typed contexts Eric Biggers
` (10 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
Add a one-shot SHA-224 computation function sha224(), for consistency
with sha256(), sha384(), and sha512() which all already exist.
Similarly, add sha224_update(). While for now it's identical to
sha256_update(), omitting it makes the API harder to use since users
have to "know" which functions are the same between SHA-224 and SHA-256.
Also, this is a prerequisite for using different context types for each.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
include/crypto/sha2.h | 10 ++++++++--
lib/crypto/sha256.c | 10 ++++++++++
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git a/include/crypto/sha2.h b/include/crypto/sha2.h
index bb181b7996cdc..e31da0743a522 100644
--- a/include/crypto/sha2.h
+++ b/include/crypto/sha2.h
@@ -112,22 +112,28 @@ struct sha512_state {
u64 state[SHA512_DIGEST_SIZE / 8];
u64 count[2];
u8 buf[SHA512_BLOCK_SIZE];
};
+void sha256_update(struct sha256_state *sctx, const u8 *data, size_t len);
+
static inline void sha224_init(struct sha256_state *sctx)
{
sha224_block_init(&sctx->ctx);
}
-/* Simply use sha256_update as it is equivalent to sha224_update. */
+static inline void sha224_update(struct sha256_state *sctx,
+ const u8 *data, size_t len)
+{
+ sha256_update(sctx, data, len);
+}
void sha224_final(struct sha256_state *sctx, u8 out[SHA224_DIGEST_SIZE]);
+void sha224(const u8 *data, size_t len, u8 out[SHA224_DIGEST_SIZE]);
static inline void sha256_init(struct sha256_state *sctx)
{
sha256_block_init(&sctx->ctx);
}
-void sha256_update(struct sha256_state *sctx, const u8 *data, size_t len);
void sha256_final(struct sha256_state *sctx, u8 out[SHA256_DIGEST_SIZE]);
void sha256(const u8 *data, size_t len, u8 out[SHA256_DIGEST_SIZE]);
/* State for the SHA-512 (and SHA-384) compression function */
struct sha512_block_state {
diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
index 573ccecbf48bf..ccaae70880166 100644
--- a/lib/crypto/sha256.c
+++ b/lib/crypto/sha256.c
@@ -68,10 +68,20 @@ void sha256_final(struct sha256_state *sctx, u8 out[SHA256_DIGEST_SIZE])
{
__sha256_final(sctx, out, SHA256_DIGEST_SIZE);
}
EXPORT_SYMBOL(sha256_final);
+void sha224(const u8 *data, size_t len, u8 out[SHA224_DIGEST_SIZE])
+{
+ struct sha256_state sctx;
+
+ sha224_init(&sctx);
+ sha224_update(&sctx, data, len);
+ sha224_final(&sctx, out);
+}
+EXPORT_SYMBOL(sha224);
+
void sha256(const u8 *data, size_t len, u8 out[SHA256_DIGEST_SIZE])
{
struct sha256_state sctx;
sha256_init(&sctx);
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 06/14] lib/crypto: sha256: Make library API use strongly-typed contexts
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (4 preceding siblings ...)
2025-06-30 16:06 ` [PATCH v2 05/14] lib/crypto: sha256: Add sha224() and sha224_update() Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 07/14] lib/crypto: sha256: Propagate sha256_block_state type to implementations Eric Biggers
` (9 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
Currently the SHA-224 and SHA-256 library functions can be mixed
arbitrarily, even in ways that are incorrect, for example using
sha224_init() and sha256_final(). This is because they operate on the
same structure, sha256_state.
Introduce stronger typing, as I did for SHA-384 and SHA-512.
Also as I did for SHA-384 and SHA-512, use the names *_ctx instead of
*_state. The *_ctx names have the following small benefits:
- They're shorter.
- They avoid an ambiguity with the compression function state.
- They're consistent with the well-known OpenSSL API.
- Users usually name the variable 'sctx' anyway, which suggests that
*_ctx would be the more natural name for the actual struct.
Therefore: update the SHA-224 and SHA-256 APIs, implementation, and
calling code accordingly.
In the new structs, also strongly-type the compression function state.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
arch/riscv/purgatory/purgatory.c | 8 +--
arch/s390/purgatory/purgatory.c | 2 +-
arch/x86/purgatory/purgatory.c | 2 +-
crypto/sha256.c | 16 ++---
drivers/char/tpm/tpm2-sessions.c | 12 ++--
include/crypto/sha2.h | 52 ++++++++++++----
kernel/kexec_file.c | 10 ++--
lib/crypto/sha256.c | 100 ++++++++++++++++++++++---------
8 files changed, 139 insertions(+), 63 deletions(-)
diff --git a/arch/riscv/purgatory/purgatory.c b/arch/riscv/purgatory/purgatory.c
index 80596ab5fb622..bbd5cfa4d7412 100644
--- a/arch/riscv/purgatory/purgatory.c
+++ b/arch/riscv/purgatory/purgatory.c
@@ -18,18 +18,18 @@ u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE] __section(".kexec-purgatory");
struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX] __section(".kexec-purgatory");
static int verify_sha256_digest(void)
{
struct kexec_sha_region *ptr, *end;
- struct sha256_state ss;
+ struct sha256_ctx sctx;
u8 digest[SHA256_DIGEST_SIZE];
- sha256_init(&ss);
+ sha256_init(&sctx);
end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions);
for (ptr = purgatory_sha_regions; ptr < end; ptr++)
- sha256_update(&ss, (uint8_t *)(ptr->start), ptr->len);
- sha256_final(&ss, digest);
+ sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len);
+ sha256_final(&sctx, digest);
if (memcmp(digest, purgatory_sha256_digest, sizeof(digest)) != 0)
return 1;
return 0;
}
diff --git a/arch/s390/purgatory/purgatory.c b/arch/s390/purgatory/purgatory.c
index 030efda05dbe5..ecb38102187c2 100644
--- a/arch/s390/purgatory/purgatory.c
+++ b/arch/s390/purgatory/purgatory.c
@@ -14,11 +14,11 @@
int verify_sha256_digest(void)
{
struct kexec_sha_region *ptr, *end;
u8 digest[SHA256_DIGEST_SIZE];
- struct sha256_state sctx;
+ struct sha256_ctx sctx;
sha256_init(&sctx);
end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions);
for (ptr = purgatory_sha_regions; ptr < end; ptr++)
diff --git a/arch/x86/purgatory/purgatory.c b/arch/x86/purgatory/purgatory.c
index aea47e7939637..655139dd05325 100644
--- a/arch/x86/purgatory/purgatory.c
+++ b/arch/x86/purgatory/purgatory.c
@@ -23,11 +23,11 @@ struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX] __section(".kex
static int verify_sha256_digest(void)
{
struct kexec_sha_region *ptr, *end;
u8 digest[SHA256_DIGEST_SIZE];
- struct sha256_state sctx;
+ struct sha256_ctx sctx;
sha256_init(&sctx);
end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions);
for (ptr = purgatory_sha_regions; ptr < end; ptr++)
diff --git a/crypto/sha256.c b/crypto/sha256.c
index 4aeb213bab117..15c57fba256b7 100644
--- a/crypto/sha256.c
+++ b/crypto/sha256.c
@@ -135,28 +135,28 @@ static int crypto_sha224_final_lib(struct shash_desc *desc, u8 *out)
return 0;
}
static int crypto_sha256_import_lib(struct shash_desc *desc, const void *in)
{
- struct sha256_state *sctx = shash_desc_ctx(desc);
+ struct __sha256_ctx *sctx = shash_desc_ctx(desc);
const u8 *p = in;
memcpy(sctx, p, sizeof(*sctx));
p += sizeof(*sctx);
- sctx->count += *p;
+ sctx->bytecount += *p;
return 0;
}
static int crypto_sha256_export_lib(struct shash_desc *desc, void *out)
{
- struct sha256_state *sctx0 = shash_desc_ctx(desc);
- struct sha256_state sctx = *sctx0;
+ struct __sha256_ctx *sctx0 = shash_desc_ctx(desc);
+ struct __sha256_ctx sctx = *sctx0;
unsigned int partial;
u8 *p = out;
- partial = sctx.count % SHA256_BLOCK_SIZE;
- sctx.count -= partial;
+ partial = sctx.bytecount % SHA256_BLOCK_SIZE;
+ sctx.bytecount -= partial;
memcpy(p, &sctx, sizeof(sctx));
p += sizeof(sctx);
*p = partial;
return 0;
}
@@ -199,11 +199,11 @@ static struct shash_alg algs[] = {
.digestsize = SHA256_DIGEST_SIZE,
.init = crypto_sha256_init,
.update = crypto_sha256_update_lib,
.final = crypto_sha256_final_lib,
.digest = crypto_sha256_digest_lib,
- .descsize = sizeof(struct sha256_state),
+ .descsize = sizeof(struct sha256_ctx),
.statesize = sizeof(struct crypto_sha256_state) +
SHA256_BLOCK_SIZE + 1,
.import = crypto_sha256_import_lib,
.export = crypto_sha256_export_lib,
},
@@ -214,11 +214,11 @@ static struct shash_alg algs[] = {
.base.cra_module = THIS_MODULE,
.digestsize = SHA224_DIGEST_SIZE,
.init = crypto_sha224_init,
.update = crypto_sha256_update_lib,
.final = crypto_sha224_final_lib,
- .descsize = sizeof(struct sha256_state),
+ .descsize = sizeof(struct sha224_ctx),
.statesize = sizeof(struct crypto_sha256_state) +
SHA256_BLOCK_SIZE + 1,
.import = crypto_sha256_import_lib,
.export = crypto_sha256_export_lib,
},
diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
index 7b5049b3d476e..bdb119453dfbe 100644
--- a/drivers/char/tpm/tpm2-sessions.c
+++ b/drivers/char/tpm/tpm2-sessions.c
@@ -388,11 +388,11 @@ static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy,
* It turns out the crypto hmac(sha256) is hard for us to consume
* because it assumes a fixed key and the TPM seems to change the key
* on every operation, so we weld the hmac init and final functions in
* here to give it the same usage characteristics as a regular hash
*/
-static void tpm2_hmac_init(struct sha256_state *sctx, u8 *key, u32 key_len)
+static void tpm2_hmac_init(struct sha256_ctx *sctx, u8 *key, u32 key_len)
{
u8 pad[SHA256_BLOCK_SIZE];
int i;
sha256_init(sctx);
@@ -404,11 +404,11 @@ static void tpm2_hmac_init(struct sha256_state *sctx, u8 *key, u32 key_len)
pad[i] ^= HMAC_IPAD_VALUE;
}
sha256_update(sctx, pad, sizeof(pad));
}
-static void tpm2_hmac_final(struct sha256_state *sctx, u8 *key, u32 key_len,
+static void tpm2_hmac_final(struct sha256_ctx *sctx, u8 *key, u32 key_len,
u8 *out)
{
u8 pad[SHA256_BLOCK_SIZE];
int i;
@@ -438,11 +438,11 @@ static void tpm2_KDFa(u8 *key, u32 key_len, const char *label, u8 *u,
{
u32 counter = 1;
const __be32 bits = cpu_to_be32(bytes * 8);
while (bytes > 0) {
- struct sha256_state sctx;
+ struct sha256_ctx sctx;
__be32 c = cpu_to_be32(counter);
tpm2_hmac_init(&sctx, key, key_len);
sha256_update(&sctx, (u8 *)&c, sizeof(c));
sha256_update(&sctx, label, strlen(label)+1);
@@ -465,11 +465,11 @@ static void tpm2_KDFa(u8 *key, u32 key_len, const char *label, u8 *u,
* in this KDF.
*/
static void tpm2_KDFe(u8 z[EC_PT_SZ], const char *str, u8 *pt_u, u8 *pt_v,
u8 *out)
{
- struct sha256_state sctx;
+ struct sha256_ctx sctx;
/*
* this should be an iterative counter, but because we know
* we're only taking 32 bytes for the point using a sha256
* hash which is also 32 bytes, there's only one loop
*/
@@ -590,11 +590,11 @@ void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
struct tpm_header *head = (struct tpm_header *)buf->data;
off_t offset_s = TPM_HEADER_SIZE, offset_p;
u8 *hmac = NULL;
u32 attrs;
u8 cphash[SHA256_DIGEST_SIZE];
- struct sha256_state sctx;
+ struct sha256_ctx sctx;
if (!auth)
return;
/* save the command code in BE format */
@@ -748,11 +748,11 @@ int tpm_buf_check_hmac_response(struct tpm_chip *chip, struct tpm_buf *buf,
struct tpm_header *head = (struct tpm_header *)buf->data;
struct tpm2_auth *auth = chip->auth;
off_t offset_s, offset_p;
u8 rphash[SHA256_DIGEST_SIZE];
u32 attrs, cc;
- struct sha256_state sctx;
+ struct sha256_ctx sctx;
u16 tag = be16_to_cpu(head->tag);
int parm_len, len, i, handles;
if (!auth)
return rc;
diff --git a/include/crypto/sha2.h b/include/crypto/sha2.h
index e31da0743a522..18e1eec841b71 100644
--- a/include/crypto/sha2.h
+++ b/include/crypto/sha2.h
@@ -112,29 +112,59 @@ struct sha512_state {
u64 state[SHA512_DIGEST_SIZE / 8];
u64 count[2];
u8 buf[SHA512_BLOCK_SIZE];
};
-void sha256_update(struct sha256_state *sctx, const u8 *data, size_t len);
+/* State for the SHA-256 (and SHA-224) compression function */
+struct sha256_block_state {
+ u32 h[SHA256_STATE_WORDS];
+};
-static inline void sha224_init(struct sha256_state *sctx)
-{
- sha224_block_init(&sctx->ctx);
-}
-static inline void sha224_update(struct sha256_state *sctx,
+/*
+ * Context structure, shared by SHA-224 and SHA-256. The sha224_ctx and
+ * sha256_ctx structs wrap this one so that the API has proper typing and
+ * doesn't allow mixing the SHA-224 and SHA-256 functions arbitrarily.
+ */
+struct __sha256_ctx {
+ struct sha256_block_state state;
+ u64 bytecount;
+ u8 buf[SHA256_BLOCK_SIZE] __aligned(__alignof__(__be64));
+};
+void __sha256_update(struct __sha256_ctx *ctx, const u8 *data, size_t len);
+
+/**
+ * struct sha224_ctx - Context for hashing a message with SHA-224
+ * @ctx: private
+ */
+struct sha224_ctx {
+ struct __sha256_ctx ctx;
+};
+
+void sha224_init(struct sha224_ctx *ctx);
+static inline void sha224_update(struct sha224_ctx *ctx,
const u8 *data, size_t len)
{
- sha256_update(sctx, data, len);
+ __sha256_update(&ctx->ctx, data, len);
}
-void sha224_final(struct sha256_state *sctx, u8 out[SHA224_DIGEST_SIZE]);
+void sha224_final(struct sha224_ctx *ctx, u8 out[SHA224_DIGEST_SIZE]);
void sha224(const u8 *data, size_t len, u8 out[SHA224_DIGEST_SIZE]);
-static inline void sha256_init(struct sha256_state *sctx)
+/**
+ * struct sha256_ctx - Context for hashing a message with SHA-256
+ * @ctx: private
+ */
+struct sha256_ctx {
+ struct __sha256_ctx ctx;
+};
+
+void sha256_init(struct sha256_ctx *ctx);
+static inline void sha256_update(struct sha256_ctx *ctx,
+ const u8 *data, size_t len)
{
- sha256_block_init(&sctx->ctx);
+ __sha256_update(&ctx->ctx, data, len);
}
-void sha256_final(struct sha256_state *sctx, u8 out[SHA256_DIGEST_SIZE]);
+void sha256_final(struct sha256_ctx *ctx, u8 out[SHA256_DIGEST_SIZE]);
void sha256(const u8 *data, size_t len, u8 out[SHA256_DIGEST_SIZE]);
/* State for the SHA-512 (and SHA-384) compression function */
struct sha512_block_state {
u64 h[8];
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 69fe76fd92334..b835033c65eb1 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -749,11 +749,11 @@ int kexec_add_buffer(struct kexec_buf *kbuf)
}
/* Calculate and store the digest of segments */
static int kexec_calculate_store_digests(struct kimage *image)
{
- struct sha256_state state;
+ struct sha256_ctx sctx;
int ret = 0, i, j, zero_buf_sz, sha_region_sz;
size_t nullsz;
u8 digest[SHA256_DIGEST_SIZE];
void *zero_buf;
struct kexec_sha_region *sha_regions;
@@ -768,11 +768,11 @@ static int kexec_calculate_store_digests(struct kimage *image)
sha_region_sz = KEXEC_SEGMENT_MAX * sizeof(struct kexec_sha_region);
sha_regions = vzalloc(sha_region_sz);
if (!sha_regions)
return -ENOMEM;
- sha256_init(&state);
+ sha256_init(&sctx);
for (j = i = 0; i < image->nr_segments; i++) {
struct kexec_segment *ksegment;
#ifdef CONFIG_CRASH_HOTPLUG
@@ -794,11 +794,11 @@ static int kexec_calculate_store_digests(struct kimage *image)
* the current index
*/
if (check_ima_segment_index(image, i))
continue;
- sha256_update(&state, ksegment->kbuf, ksegment->bufsz);
+ sha256_update(&sctx, ksegment->kbuf, ksegment->bufsz);
/*
* Assume rest of the buffer is filled with zero and
* update digest accordingly.
*/
@@ -806,20 +806,20 @@ static int kexec_calculate_store_digests(struct kimage *image)
while (nullsz) {
unsigned long bytes = nullsz;
if (bytes > zero_buf_sz)
bytes = zero_buf_sz;
- sha256_update(&state, zero_buf, bytes);
+ sha256_update(&sctx, zero_buf, bytes);
nullsz -= bytes;
}
sha_regions[j].start = ksegment->mem;
sha_regions[j].len = ksegment->memsz;
j++;
}
- sha256_final(&state, digest);
+ sha256_final(&sctx, digest);
ret = kexec_purgatory_get_set_symbol(image, "purgatory_sha_regions",
sha_regions, sha_region_sz, 0);
if (ret)
goto out_free_sha_regions;
diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
index ccaae70880166..3e7797a4489de 100644
--- a/lib/crypto/sha256.c
+++ b/lib/crypto/sha256.c
@@ -16,10 +16,24 @@
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
+static const struct sha256_block_state sha224_iv = {
+ .h = {
+ SHA224_H0, SHA224_H1, SHA224_H2, SHA224_H3,
+ SHA224_H4, SHA224_H5, SHA224_H6, SHA224_H7,
+ },
+};
+
+static const struct sha256_block_state sha256_iv = {
+ .h = {
+ SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3,
+ SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7,
+ },
+};
+
/*
* If __DISABLE_EXPORTS is defined, then this file is being compiled for a
* pre-boot environment. In that case, ignore the kconfig options, pull the
* generic code into the same translation unit, and use that only.
*/
@@ -30,65 +44,97 @@
static inline bool sha256_purgatory(void)
{
return __is_defined(__DISABLE_EXPORTS);
}
-static inline void sha256_blocks(u32 state[SHA256_STATE_WORDS], const u8 *data,
- size_t nblocks)
+static inline void sha256_blocks(struct sha256_block_state *state,
+ const u8 *data, size_t nblocks)
+{
+ sha256_choose_blocks(state->h, data, nblocks, sha256_purgatory(), false);
+}
+
+static void __sha256_init(struct __sha256_ctx *ctx,
+ const struct sha256_block_state *iv,
+ u64 initial_bytecount)
+{
+ ctx->state = *iv;
+ ctx->bytecount = initial_bytecount;
+}
+
+void sha224_init(struct sha224_ctx *ctx)
+{
+ __sha256_init(&ctx->ctx, &sha224_iv, 0);
+}
+EXPORT_SYMBOL_GPL(sha224_init);
+
+void sha256_init(struct sha256_ctx *ctx)
{
- sha256_choose_blocks(state, data, nblocks, sha256_purgatory(), false);
+ __sha256_init(&ctx->ctx, &sha256_iv, 0);
}
+EXPORT_SYMBOL_GPL(sha256_init);
-void sha256_update(struct sha256_state *sctx, const u8 *data, size_t len)
+void __sha256_update(struct __sha256_ctx *ctx, const u8 *data, size_t len)
{
- size_t partial = sctx->count % SHA256_BLOCK_SIZE;
+ size_t partial = ctx->bytecount % SHA256_BLOCK_SIZE;
- sctx->count += len;
- BLOCK_HASH_UPDATE_BLOCKS(sha256_blocks, sctx->ctx.state, data, len,
- SHA256_BLOCK_SIZE, sctx->buf, partial);
+ ctx->bytecount += len;
+ BLOCK_HASH_UPDATE_BLOCKS(sha256_blocks, &ctx->state, data, len,
+ SHA256_BLOCK_SIZE, ctx->buf, partial);
}
-EXPORT_SYMBOL(sha256_update);
+EXPORT_SYMBOL(__sha256_update);
-static inline void __sha256_final(struct sha256_state *sctx, u8 *out,
- size_t digest_size)
+static void __sha256_final(struct __sha256_ctx *ctx,
+ u8 *out, size_t digest_size)
{
- size_t partial = sctx->count % SHA256_BLOCK_SIZE;
+ u64 bitcount = ctx->bytecount << 3;
+ size_t partial = ctx->bytecount % SHA256_BLOCK_SIZE;
+
+ ctx->buf[partial++] = 0x80;
+ if (partial > SHA256_BLOCK_SIZE - 8) {
+ memset(&ctx->buf[partial], 0, SHA256_BLOCK_SIZE - partial);
+ sha256_blocks(&ctx->state, ctx->buf, 1);
+ partial = 0;
+ }
+ memset(&ctx->buf[partial], 0, SHA256_BLOCK_SIZE - 8 - partial);
+ *(__be64 *)&ctx->buf[SHA256_BLOCK_SIZE - 8] = cpu_to_be64(bitcount);
+ sha256_blocks(&ctx->state, ctx->buf, 1);
- sha256_finup(&sctx->ctx, sctx->buf, partial, out, digest_size,
- sha256_purgatory(), false);
- memzero_explicit(sctx, sizeof(*sctx));
+ for (size_t i = 0; i < digest_size; i += 4)
+ put_unaligned_be32(ctx->state.h[i / 4], out + i);
}
-void sha224_final(struct sha256_state *sctx, u8 out[SHA224_DIGEST_SIZE])
+void sha224_final(struct sha224_ctx *ctx, u8 out[SHA224_DIGEST_SIZE])
{
- __sha256_final(sctx, out, SHA224_DIGEST_SIZE);
+ __sha256_final(&ctx->ctx, out, SHA224_DIGEST_SIZE);
+ memzero_explicit(ctx, sizeof(*ctx));
}
EXPORT_SYMBOL(sha224_final);
-void sha256_final(struct sha256_state *sctx, u8 out[SHA256_DIGEST_SIZE])
+void sha256_final(struct sha256_ctx *ctx, u8 out[SHA256_DIGEST_SIZE])
{
- __sha256_final(sctx, out, SHA256_DIGEST_SIZE);
+ __sha256_final(&ctx->ctx, out, SHA256_DIGEST_SIZE);
+ memzero_explicit(ctx, sizeof(*ctx));
}
EXPORT_SYMBOL(sha256_final);
void sha224(const u8 *data, size_t len, u8 out[SHA224_DIGEST_SIZE])
{
- struct sha256_state sctx;
+ struct sha224_ctx ctx;
- sha224_init(&sctx);
- sha224_update(&sctx, data, len);
- sha224_final(&sctx, out);
+ sha224_init(&ctx);
+ sha224_update(&ctx, data, len);
+ sha224_final(&ctx, out);
}
EXPORT_SYMBOL(sha224);
void sha256(const u8 *data, size_t len, u8 out[SHA256_DIGEST_SIZE])
{
- struct sha256_state sctx;
+ struct sha256_ctx ctx;
- sha256_init(&sctx);
- sha256_update(&sctx, data, len);
- sha256_final(&sctx, out);
+ sha256_init(&ctx);
+ sha256_update(&ctx, data, len);
+ sha256_final(&ctx, out);
}
EXPORT_SYMBOL(sha256);
MODULE_DESCRIPTION("SHA-256 Algorithm");
MODULE_LICENSE("GPL");
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 07/14] lib/crypto: sha256: Propagate sha256_block_state type to implementations
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (5 preceding siblings ...)
2025-06-30 16:06 ` [PATCH v2 06/14] lib/crypto: sha256: Make library API use strongly-typed contexts Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 08/14] lib/crypto: sha256: Add HMAC-SHA224 and HMAC-SHA256 support Eric Biggers
` (8 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
The previous commit made the SHA-256 compression function state be
strongly typed, but it wasn't propagated all the way down to the
implementations of it. Do that now.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
.../mips/cavium-octeon/crypto/octeon-sha256.c | 2 +-
include/crypto/internal/sha2.h | 8 +++----
lib/crypto/arm/sha256-ce.S | 2 +-
lib/crypto/arm/sha256.c | 8 +++----
lib/crypto/arm64/sha256-ce.S | 2 +-
lib/crypto/arm64/sha256.c | 8 +++----
lib/crypto/powerpc/sha256.c | 2 +-
.../sha256-riscv64-zvknha_or_zvknhb-zvkb.S | 2 +-
lib/crypto/riscv/sha256.c | 7 +++---
lib/crypto/s390/sha256.c | 2 +-
lib/crypto/sha256-generic.c | 24 ++++++++++++++-----
lib/crypto/sparc/sha256.c | 4 ++--
lib/crypto/x86/sha256-avx-asm.S | 2 +-
lib/crypto/x86/sha256-avx2-asm.S | 2 +-
lib/crypto/x86/sha256-ni-asm.S | 2 +-
lib/crypto/x86/sha256-ssse3-asm.S | 2 +-
lib/crypto/x86/sha256.c | 10 ++++----
17 files changed, 51 insertions(+), 38 deletions(-)
diff --git a/arch/mips/cavium-octeon/crypto/octeon-sha256.c b/arch/mips/cavium-octeon/crypto/octeon-sha256.c
index c20038239cb6b..f8664818d04ec 100644
--- a/arch/mips/cavium-octeon/crypto/octeon-sha256.c
+++ b/arch/mips/cavium-octeon/crypto/octeon-sha256.c
@@ -20,11 +20,11 @@
/*
* We pass everything as 64-bit. OCTEON can handle misaligned data.
*/
-void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(struct sha256_block_state *state,
const u8 *data, size_t nblocks)
{
struct octeon_cop2_state cop2_state;
u64 *state64 = (u64 *)state;
unsigned long flags;
diff --git a/include/crypto/internal/sha2.h b/include/crypto/internal/sha2.h
index 5a25ccc493886..f0f455477bbd7 100644
--- a/include/crypto/internal/sha2.h
+++ b/include/crypto/internal/sha2.h
@@ -15,23 +15,23 @@ bool sha256_is_arch_optimized(void);
static inline bool sha256_is_arch_optimized(void)
{
return false;
}
#endif
-void sha256_blocks_generic(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_generic(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
-void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
static __always_inline void sha256_choose_blocks(
u32 state[SHA256_STATE_WORDS], const u8 *data, size_t nblocks,
bool force_generic, bool force_simd)
{
if (!IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_SHA256) || force_generic)
- sha256_blocks_generic(state, data, nblocks);
+ sha256_blocks_generic((struct sha256_block_state *)state, data, nblocks);
else
- sha256_blocks_arch(state, data, nblocks);
+ sha256_blocks_arch((struct sha256_block_state *)state, data, nblocks);
}
static __always_inline void sha256_finup(
struct crypto_sha256_state *sctx, u8 buf[SHA256_BLOCK_SIZE],
size_t len, u8 out[SHA256_DIGEST_SIZE], size_t digest_size,
diff --git a/lib/crypto/arm/sha256-ce.S b/lib/crypto/arm/sha256-ce.S
index ac2c9b01b22d2..7481ac8e6c0d9 100644
--- a/lib/crypto/arm/sha256-ce.S
+++ b/lib/crypto/arm/sha256-ce.S
@@ -65,11 +65,11 @@
.word 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3
.word 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208
.word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
/*
- * void sha256_ce_transform(u32 state[SHA256_STATE_WORDS],
+ * void sha256_ce_transform(struct sha256_block_state *state,
* const u8 *data, size_t nblocks);
*/
ENTRY(sha256_ce_transform)
/* load state */
vld1.32 {dga-dgb}, [r0]
diff --git a/lib/crypto/arm/sha256.c b/lib/crypto/arm/sha256.c
index 2c9cfdaaa0691..7d90823586952 100644
--- a/lib/crypto/arm/sha256.c
+++ b/lib/crypto/arm/sha256.c
@@ -8,21 +8,21 @@
#include <crypto/internal/sha2.h>
#include <crypto/internal/simd.h>
#include <linux/kernel.h>
#include <linux/module.h>
-asmlinkage void sha256_block_data_order(u32 state[SHA256_STATE_WORDS],
+asmlinkage void sha256_block_data_order(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
-asmlinkage void sha256_block_data_order_neon(u32 state[SHA256_STATE_WORDS],
+asmlinkage void sha256_block_data_order_neon(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
-asmlinkage void sha256_ce_transform(u32 state[SHA256_STATE_WORDS],
+asmlinkage void sha256_ce_transform(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_ce);
-void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(struct sha256_block_state *state,
const u8 *data, size_t nblocks)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
static_branch_likely(&have_neon) && crypto_simd_usable()) {
kernel_neon_begin();
diff --git a/lib/crypto/arm64/sha256-ce.S b/lib/crypto/arm64/sha256-ce.S
index f3e21c6d87d2e..b99d9589c4217 100644
--- a/lib/crypto/arm64/sha256-ce.S
+++ b/lib/crypto/arm64/sha256-ce.S
@@ -69,11 +69,11 @@
.word 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3
.word 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208
.word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
/*
- * size_t __sha256_ce_transform(u32 state[SHA256_STATE_WORDS],
+ * size_t __sha256_ce_transform(struct sha256_block_state *state,
* const u8 *data, size_t nblocks);
*/
.text
SYM_FUNC_START(__sha256_ce_transform)
/* load round constants */
diff --git a/lib/crypto/arm64/sha256.c b/lib/crypto/arm64/sha256.c
index fb9bff40357be..609ffb8151987 100644
--- a/lib/crypto/arm64/sha256.c
+++ b/lib/crypto/arm64/sha256.c
@@ -8,21 +8,21 @@
#include <crypto/internal/sha2.h>
#include <crypto/internal/simd.h>
#include <linux/kernel.h>
#include <linux/module.h>
-asmlinkage void sha256_block_data_order(u32 state[SHA256_STATE_WORDS],
+asmlinkage void sha256_block_data_order(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
-asmlinkage void sha256_block_neon(u32 state[SHA256_STATE_WORDS],
+asmlinkage void sha256_block_neon(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
-asmlinkage size_t __sha256_ce_transform(u32 state[SHA256_STATE_WORDS],
+asmlinkage size_t __sha256_ce_transform(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_ce);
-void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(struct sha256_block_state *state,
const u8 *data, size_t nblocks)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
static_branch_likely(&have_neon) && crypto_simd_usable()) {
if (static_branch_likely(&have_ce)) {
diff --git a/lib/crypto/powerpc/sha256.c b/lib/crypto/powerpc/sha256.c
index 6b0f079587eb6..c3f844ae0aceb 100644
--- a/lib/crypto/powerpc/sha256.c
+++ b/lib/crypto/powerpc/sha256.c
@@ -40,11 +40,11 @@ static void spe_end(void)
disable_kernel_spe();
/* reenable preemption */
preempt_enable();
}
-void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(struct sha256_block_state *state,
const u8 *data, size_t nblocks)
{
do {
/* cut input data into smaller blocks */
u32 unit = min_t(size_t, nblocks,
diff --git a/lib/crypto/riscv/sha256-riscv64-zvknha_or_zvknhb-zvkb.S b/lib/crypto/riscv/sha256-riscv64-zvknha_or_zvknhb-zvkb.S
index fad501ad06171..1618d1220a6e7 100644
--- a/lib/crypto/riscv/sha256-riscv64-zvknha_or_zvknhb-zvkb.S
+++ b/lib/crypto/riscv/sha256-riscv64-zvknha_or_zvknhb-zvkb.S
@@ -104,11 +104,11 @@
sha256_4rounds \last, \k1, W1, W2, W3, W0
sha256_4rounds \last, \k2, W2, W3, W0, W1
sha256_4rounds \last, \k3, W3, W0, W1, W2
.endm
-// void sha256_transform_zvknha_or_zvknhb_zvkb(u32 state[SHA256_STATE_WORDS],
+// void sha256_transform_zvknha_or_zvknhb_zvkb(struct sha256_block_state *state,
// const u8 *data, size_t nblocks);
SYM_FUNC_START(sha256_transform_zvknha_or_zvknhb_zvkb)
// Load the round constants into K0-K15.
vsetivli zero, 4, e32, m1, ta, ma
diff --git a/lib/crypto/riscv/sha256.c b/lib/crypto/riscv/sha256.c
index aa77349d08f30..a2079aa3ae925 100644
--- a/lib/crypto/riscv/sha256.c
+++ b/lib/crypto/riscv/sha256.c
@@ -13,16 +13,17 @@
#include <crypto/internal/sha2.h>
#include <crypto/internal/simd.h>
#include <linux/kernel.h>
#include <linux/module.h>
-asmlinkage void sha256_transform_zvknha_or_zvknhb_zvkb(
- u32 state[SHA256_STATE_WORDS], const u8 *data, size_t nblocks);
+asmlinkage void
+sha256_transform_zvknha_or_zvknhb_zvkb(struct sha256_block_state *state,
+ const u8 *data, size_t nblocks);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_extensions);
-void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(struct sha256_block_state *state,
const u8 *data, size_t nblocks)
{
if (static_branch_likely(&have_extensions) && crypto_simd_usable()) {
kernel_vector_begin();
sha256_transform_zvknha_or_zvknhb_zvkb(state, data, nblocks);
diff --git a/lib/crypto/s390/sha256.c b/lib/crypto/s390/sha256.c
index 7dfe120fafaba..fb565718f7539 100644
--- a/lib/crypto/s390/sha256.c
+++ b/lib/crypto/s390/sha256.c
@@ -10,11 +10,11 @@
#include <linux/kernel.h>
#include <linux/module.h>
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_cpacf_sha256);
-void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(struct sha256_block_state *state,
const u8 *data, size_t nblocks)
{
if (static_branch_likely(&have_cpacf_sha256))
cpacf_kimd(CPACF_KIMD_SHA_256, state, data,
nblocks * SHA256_BLOCK_SIZE);
diff --git a/lib/crypto/sha256-generic.c b/lib/crypto/sha256-generic.c
index 2968d95d04038..99f904033c261 100644
--- a/lib/crypto/sha256-generic.c
+++ b/lib/crypto/sha256-generic.c
@@ -68,11 +68,11 @@ static inline void BLEND_OP(int I, u32 *W)
t2 = e0(a) + Maj(a, b, c); \
d += t1; \
h = t1 + t2; \
} while (0)
-static void sha256_block_generic(u32 state[SHA256_STATE_WORDS],
+static void sha256_block_generic(struct sha256_block_state *state,
const u8 *input, u32 W[64])
{
u32 a, b, c, d, e, f, g, h;
int i;
@@ -99,12 +99,18 @@ static void sha256_block_generic(u32 state[SHA256_STATE_WORDS],
BLEND_OP(i + 6, W);
BLEND_OP(i + 7, W);
}
/* load the state into our registers */
- a = state[0]; b = state[1]; c = state[2]; d = state[3];
- e = state[4]; f = state[5]; g = state[6]; h = state[7];
+ a = state->h[0];
+ b = state->h[1];
+ c = state->h[2];
+ d = state->h[3];
+ e = state->h[4];
+ f = state->h[5];
+ g = state->h[6];
+ h = state->h[7];
/* now iterate */
for (i = 0; i < 64; i += 8) {
SHA256_ROUND(i + 0, a, b, c, d, e, f, g, h);
SHA256_ROUND(i + 1, h, a, b, c, d, e, f, g);
@@ -114,15 +120,21 @@ static void sha256_block_generic(u32 state[SHA256_STATE_WORDS],
SHA256_ROUND(i + 5, d, e, f, g, h, a, b, c);
SHA256_ROUND(i + 6, c, d, e, f, g, h, a, b);
SHA256_ROUND(i + 7, b, c, d, e, f, g, h, a);
}
- state[0] += a; state[1] += b; state[2] += c; state[3] += d;
- state[4] += e; state[5] += f; state[6] += g; state[7] += h;
+ state->h[0] += a;
+ state->h[1] += b;
+ state->h[2] += c;
+ state->h[3] += d;
+ state->h[4] += e;
+ state->h[5] += f;
+ state->h[6] += g;
+ state->h[7] += h;
}
-void sha256_blocks_generic(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_generic(struct sha256_block_state *state,
const u8 *data, size_t nblocks)
{
u32 W[64];
do {
diff --git a/lib/crypto/sparc/sha256.c b/lib/crypto/sparc/sha256.c
index 8bdec2db08b30..060664b88a6d3 100644
--- a/lib/crypto/sparc/sha256.c
+++ b/lib/crypto/sparc/sha256.c
@@ -17,14 +17,14 @@
#include <linux/kernel.h>
#include <linux/module.h>
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_sha256_opcodes);
-asmlinkage void sha256_sparc64_transform(u32 state[SHA256_STATE_WORDS],
+asmlinkage void sha256_sparc64_transform(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
-void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(struct sha256_block_state *state,
const u8 *data, size_t nblocks)
{
if (static_branch_likely(&have_sha256_opcodes))
sha256_sparc64_transform(state, data, nblocks);
else
diff --git a/lib/crypto/x86/sha256-avx-asm.S b/lib/crypto/x86/sha256-avx-asm.S
index 0d7b2c3e45d9a..73bcff2b548f4 100644
--- a/lib/crypto/x86/sha256-avx-asm.S
+++ b/lib/crypto/x86/sha256-avx-asm.S
@@ -339,11 +339,11 @@ a = TMP_
add y0, h # h = h + S1 + CH + k + w + S0 + MAJ
ROTATE_ARGS
.endm
########################################################################
-## void sha256_transform_avx(u32 state[SHA256_STATE_WORDS],
+## void sha256_transform_avx(struct sha256_block_state *state,
## const u8 *data, size_t nblocks);
########################################################################
.text
SYM_FUNC_START(sha256_transform_avx)
ANNOTATE_NOENDBR # since this is called only via static_call
diff --git a/lib/crypto/x86/sha256-avx2-asm.S b/lib/crypto/x86/sha256-avx2-asm.S
index 25d3380321ec3..45787570387f2 100644
--- a/lib/crypto/x86/sha256-avx2-asm.S
+++ b/lib/crypto/x86/sha256-avx2-asm.S
@@ -516,11 +516,11 @@ STACK_SIZE = _CTX + _CTX_SIZE
ROTATE_ARGS
.endm
########################################################################
-## void sha256_transform_rorx(u32 state[SHA256_STATE_WORDS],
+## void sha256_transform_rorx(struct sha256_block_state *state,
## const u8 *data, size_t nblocks);
########################################################################
.text
SYM_FUNC_START(sha256_transform_rorx)
ANNOTATE_NOENDBR # since this is called only via static_call
diff --git a/lib/crypto/x86/sha256-ni-asm.S b/lib/crypto/x86/sha256-ni-asm.S
index d3548206cf3d4..4af7d22e29e47 100644
--- a/lib/crypto/x86/sha256-ni-asm.S
+++ b/lib/crypto/x86/sha256-ni-asm.S
@@ -104,11 +104,11 @@
* input data, and the number of 64-byte blocks to process. Once all blocks
* have been processed, the state is updated with the new state. This function
* only processes complete blocks. State initialization, buffering of partial
* blocks, and digest finalization is expected to be handled elsewhere.
*
- * void sha256_ni_transform(u32 state[SHA256_STATE_WORDS],
+ * void sha256_ni_transform(struct sha256_block_state *state,
* const u8 *data, size_t nblocks);
*/
.text
SYM_FUNC_START(sha256_ni_transform)
ANNOTATE_NOENDBR # since this is called only via static_call
diff --git a/lib/crypto/x86/sha256-ssse3-asm.S b/lib/crypto/x86/sha256-ssse3-asm.S
index 7f24a4cdcb257..407b30adcd37f 100644
--- a/lib/crypto/x86/sha256-ssse3-asm.S
+++ b/lib/crypto/x86/sha256-ssse3-asm.S
@@ -346,11 +346,11 @@ a = TMP_
add y0, h # h = h + S1 + CH + k + w + S0 + MAJ
ROTATE_ARGS
.endm
########################################################################
-## void sha256_transform_ssse3(u32 state[SHA256_STATE_WORDS],
+## void sha256_transform_ssse3(struct sha256_block_state *state,
## const u8 *data, size_t nblocks);
########################################################################
.text
SYM_FUNC_START(sha256_transform_ssse3)
ANNOTATE_NOENDBR # since this is called only via static_call
diff --git a/lib/crypto/x86/sha256.c b/lib/crypto/x86/sha256.c
index baba74d7d26f2..cbb45defbefab 100644
--- a/lib/crypto/x86/sha256.c
+++ b/lib/crypto/x86/sha256.c
@@ -9,24 +9,24 @@
#include <crypto/internal/simd.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/static_call.h>
-asmlinkage void sha256_transform_ssse3(u32 state[SHA256_STATE_WORDS],
+asmlinkage void sha256_transform_ssse3(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
-asmlinkage void sha256_transform_avx(u32 state[SHA256_STATE_WORDS],
+asmlinkage void sha256_transform_avx(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
-asmlinkage void sha256_transform_rorx(u32 state[SHA256_STATE_WORDS],
+asmlinkage void sha256_transform_rorx(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
-asmlinkage void sha256_ni_transform(u32 state[SHA256_STATE_WORDS],
+asmlinkage void sha256_ni_transform(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_sha256_x86);
DEFINE_STATIC_CALL(sha256_blocks_x86, sha256_transform_ssse3);
-void sha256_blocks_arch(u32 state[SHA256_STATE_WORDS],
+void sha256_blocks_arch(struct sha256_block_state *state,
const u8 *data, size_t nblocks)
{
if (static_branch_likely(&have_sha256_x86) && crypto_simd_usable()) {
kernel_fpu_begin();
static_call(sha256_blocks_x86)(state, data, nblocks);
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 08/14] lib/crypto: sha256: Add HMAC-SHA224 and HMAC-SHA256 support
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (6 preceding siblings ...)
2025-06-30 16:06 ` [PATCH v2 07/14] lib/crypto: sha256: Propagate sha256_block_state type to implementations Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 09/14] crypto: sha256 - Wrap library and add HMAC support Eric Biggers
` (7 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
Since HMAC support is commonly needed and is fairly simple, include it
as a first-class citizen of the SHA-256 library.
The API supports both incremental and one-shot computation, and either
preparing the key ahead of time or just using a raw key. The
implementation is much more streamlined than crypto/hmac.c.
I've kept it consistent with the HMAC-SHA384 and HMAC-SHA512 code as
much as possible.
Testing of these functions will be via sha224_kunit and sha256_kunit,
added by a later commit.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
include/crypto/sha2.h | 222 ++++++++++++++++++++++++++++++++++++++++++
lib/crypto/sha256.c | 147 +++++++++++++++++++++++++++-
2 files changed, 364 insertions(+), 5 deletions(-)
diff --git a/include/crypto/sha2.h b/include/crypto/sha2.h
index 18e1eec841b71..2e3fc2cf4aa0d 100644
--- a/include/crypto/sha2.h
+++ b/include/crypto/sha2.h
@@ -129,10 +129,26 @@ struct __sha256_ctx {
u64 bytecount;
u8 buf[SHA256_BLOCK_SIZE] __aligned(__alignof__(__be64));
};
void __sha256_update(struct __sha256_ctx *ctx, const u8 *data, size_t len);
+/*
+ * HMAC key and message context structs, shared by HMAC-SHA224 and HMAC-SHA256.
+ * The hmac_sha224_* and hmac_sha256_* structs wrap this one so that the API has
+ * proper typing and doesn't allow mixing the functions arbitrarily.
+ */
+struct __hmac_sha256_key {
+ struct sha256_block_state istate;
+ struct sha256_block_state ostate;
+};
+struct __hmac_sha256_ctx {
+ struct __sha256_ctx sha_ctx;
+ struct sha256_block_state ostate;
+};
+void __hmac_sha256_init(struct __hmac_sha256_ctx *ctx,
+ const struct __hmac_sha256_key *key);
+
/**
* struct sha224_ctx - Context for hashing a message with SHA-224
* @ctx: private
*/
struct sha224_ctx {
@@ -146,10 +162,113 @@ static inline void sha224_update(struct sha224_ctx *ctx,
__sha256_update(&ctx->ctx, data, len);
}
void sha224_final(struct sha224_ctx *ctx, u8 out[SHA224_DIGEST_SIZE]);
void sha224(const u8 *data, size_t len, u8 out[SHA224_DIGEST_SIZE]);
+/**
+ * struct hmac_sha224_key - Prepared key for HMAC-SHA224
+ * @key: private
+ */
+struct hmac_sha224_key {
+ struct __hmac_sha256_key key;
+};
+
+/**
+ * struct hmac_sha224_ctx - Context for computing HMAC-SHA224 of a message
+ * @ctx: private
+ */
+struct hmac_sha224_ctx {
+ struct __hmac_sha256_ctx ctx;
+};
+
+/**
+ * hmac_sha224_preparekey() - Prepare a key for HMAC-SHA224
+ * @key: (output) the key structure to initialize
+ * @raw_key: the raw HMAC-SHA224 key
+ * @raw_key_len: the key length in bytes. All key lengths are supported.
+ *
+ * Note: the caller is responsible for zeroizing both the struct hmac_sha224_key
+ * and the raw key once they are no longer needed.
+ *
+ * Context: Any context.
+ */
+void hmac_sha224_preparekey(struct hmac_sha224_key *key,
+ const u8 *raw_key, size_t raw_key_len);
+
+/**
+ * hmac_sha224_init() - Initialize an HMAC-SHA224 context for a new message
+ * @ctx: (output) the HMAC context to initialize
+ * @key: the prepared HMAC key
+ *
+ * If you don't need incremental computation, consider hmac_sha224() instead.
+ *
+ * Context: Any context.
+ */
+static inline void hmac_sha224_init(struct hmac_sha224_ctx *ctx,
+ const struct hmac_sha224_key *key)
+{
+ __hmac_sha256_init(&ctx->ctx, &key->key);
+}
+
+/**
+ * hmac_sha224_update() - Update an HMAC-SHA224 context with message data
+ * @ctx: the HMAC context to update; must have been initialized
+ * @data: the message data
+ * @data_len: the data length in bytes
+ *
+ * This can be called any number of times.
+ *
+ * Context: Any context.
+ */
+static inline void hmac_sha224_update(struct hmac_sha224_ctx *ctx,
+ const u8 *data, size_t data_len)
+{
+ __sha256_update(&ctx->ctx.sha_ctx, data, data_len);
+}
+
+/**
+ * hmac_sha224_final() - Finish computing an HMAC-SHA224 value
+ * @ctx: the HMAC context to finalize; must have been initialized
+ * @out: (output) the resulting HMAC-SHA224 value
+ *
+ * After finishing, this zeroizes @ctx. So the caller does not need to do it.
+ *
+ * Context: Any context.
+ */
+void hmac_sha224_final(struct hmac_sha224_ctx *ctx, u8 out[SHA224_DIGEST_SIZE]);
+
+/**
+ * hmac_sha224() - Compute HMAC-SHA224 in one shot, using a prepared key
+ * @key: the prepared HMAC key
+ * @data: the message data
+ * @data_len: the data length in bytes
+ * @out: (output) the resulting HMAC-SHA224 value
+ *
+ * If you're using the key only once, consider using hmac_sha224_usingrawkey().
+ *
+ * Context: Any context.
+ */
+void hmac_sha224(const struct hmac_sha224_key *key,
+ const u8 *data, size_t data_len, u8 out[SHA224_DIGEST_SIZE]);
+
+/**
+ * hmac_sha224_usingrawkey() - Compute HMAC-SHA224 in one shot, using a raw key
+ * @raw_key: the raw HMAC-SHA224 key
+ * @raw_key_len: the key length in bytes. All key lengths are supported.
+ * @data: the message data
+ * @data_len: the data length in bytes
+ * @out: (output) the resulting HMAC-SHA224 value
+ *
+ * If you're using the key multiple times, prefer to use
+ * hmac_sha224_preparekey() followed by multiple calls to hmac_sha224() instead.
+ *
+ * Context: Any context.
+ */
+void hmac_sha224_usingrawkey(const u8 *raw_key, size_t raw_key_len,
+ const u8 *data, size_t data_len,
+ u8 out[SHA224_DIGEST_SIZE]);
+
/**
* struct sha256_ctx - Context for hashing a message with SHA-256
* @ctx: private
*/
struct sha256_ctx {
@@ -163,10 +282,113 @@ static inline void sha256_update(struct sha256_ctx *ctx,
__sha256_update(&ctx->ctx, data, len);
}
void sha256_final(struct sha256_ctx *ctx, u8 out[SHA256_DIGEST_SIZE]);
void sha256(const u8 *data, size_t len, u8 out[SHA256_DIGEST_SIZE]);
+/**
+ * struct hmac_sha256_key - Prepared key for HMAC-SHA256
+ * @key: private
+ */
+struct hmac_sha256_key {
+ struct __hmac_sha256_key key;
+};
+
+/**
+ * struct hmac_sha256_ctx - Context for computing HMAC-SHA256 of a message
+ * @ctx: private
+ */
+struct hmac_sha256_ctx {
+ struct __hmac_sha256_ctx ctx;
+};
+
+/**
+ * hmac_sha256_preparekey() - Prepare a key for HMAC-SHA256
+ * @key: (output) the key structure to initialize
+ * @raw_key: the raw HMAC-SHA256 key
+ * @raw_key_len: the key length in bytes. All key lengths are supported.
+ *
+ * Note: the caller is responsible for zeroizing both the struct hmac_sha256_key
+ * and the raw key once they are no longer needed.
+ *
+ * Context: Any context.
+ */
+void hmac_sha256_preparekey(struct hmac_sha256_key *key,
+ const u8 *raw_key, size_t raw_key_len);
+
+/**
+ * hmac_sha256_init() - Initialize an HMAC-SHA256 context for a new message
+ * @ctx: (output) the HMAC context to initialize
+ * @key: the prepared HMAC key
+ *
+ * If you don't need incremental computation, consider hmac_sha256() instead.
+ *
+ * Context: Any context.
+ */
+static inline void hmac_sha256_init(struct hmac_sha256_ctx *ctx,
+ const struct hmac_sha256_key *key)
+{
+ __hmac_sha256_init(&ctx->ctx, &key->key);
+}
+
+/**
+ * hmac_sha256_update() - Update an HMAC-SHA256 context with message data
+ * @ctx: the HMAC context to update; must have been initialized
+ * @data: the message data
+ * @data_len: the data length in bytes
+ *
+ * This can be called any number of times.
+ *
+ * Context: Any context.
+ */
+static inline void hmac_sha256_update(struct hmac_sha256_ctx *ctx,
+ const u8 *data, size_t data_len)
+{
+ __sha256_update(&ctx->ctx.sha_ctx, data, data_len);
+}
+
+/**
+ * hmac_sha256_final() - Finish computing an HMAC-SHA256 value
+ * @ctx: the HMAC context to finalize; must have been initialized
+ * @out: (output) the resulting HMAC-SHA256 value
+ *
+ * After finishing, this zeroizes @ctx. So the caller does not need to do it.
+ *
+ * Context: Any context.
+ */
+void hmac_sha256_final(struct hmac_sha256_ctx *ctx, u8 out[SHA256_DIGEST_SIZE]);
+
+/**
+ * hmac_sha256() - Compute HMAC-SHA256 in one shot, using a prepared key
+ * @key: the prepared HMAC key
+ * @data: the message data
+ * @data_len: the data length in bytes
+ * @out: (output) the resulting HMAC-SHA256 value
+ *
+ * If you're using the key only once, consider using hmac_sha256_usingrawkey().
+ *
+ * Context: Any context.
+ */
+void hmac_sha256(const struct hmac_sha256_key *key,
+ const u8 *data, size_t data_len, u8 out[SHA256_DIGEST_SIZE]);
+
+/**
+ * hmac_sha256_usingrawkey() - Compute HMAC-SHA256 in one shot, using a raw key
+ * @raw_key: the raw HMAC-SHA256 key
+ * @raw_key_len: the key length in bytes. All key lengths are supported.
+ * @data: the message data
+ * @data_len: the data length in bytes
+ * @out: (output) the resulting HMAC-SHA256 value
+ *
+ * If you're using the key multiple times, prefer to use
+ * hmac_sha256_preparekey() followed by multiple calls to hmac_sha256() instead.
+ *
+ * Context: Any context.
+ */
+void hmac_sha256_usingrawkey(const u8 *raw_key, size_t raw_key_len,
+ const u8 *data, size_t data_len,
+ u8 out[SHA256_DIGEST_SIZE]);
+
/* State for the SHA-512 (and SHA-384) compression function */
struct sha512_block_state {
u64 h[8];
};
diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
index 3e7797a4489de..12b4b59052c4a 100644
--- a/lib/crypto/sha256.c
+++ b/lib/crypto/sha256.c
@@ -1,24 +1,23 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * SHA-256, as specified in
- * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
- *
- * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>.
+ * SHA-224, SHA-256, HMAC-SHA224, and HMAC-SHA256 library functions
*
* Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
* Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* Copyright (c) 2014 Red Hat Inc.
*/
+#include <crypto/hmac.h>
#include <crypto/internal/blockhash.h>
#include <crypto/internal/sha2.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
+#include <linux/wordpart.h>
static const struct sha256_block_state sha224_iv = {
.h = {
SHA224_H0, SHA224_H1, SHA224_H2, SHA224_H3,
SHA224_H4, SHA224_H5, SHA224_H6, SHA224_H7,
@@ -134,7 +133,145 @@ void sha256(const u8 *data, size_t len, u8 out[SHA256_DIGEST_SIZE])
sha256_update(&ctx, data, len);
sha256_final(&ctx, out);
}
EXPORT_SYMBOL(sha256);
-MODULE_DESCRIPTION("SHA-256 Algorithm");
+/* pre-boot environment (as indicated by __DISABLE_EXPORTS) doesn't need HMAC */
+#ifndef __DISABLE_EXPORTS
+static void __hmac_sha256_preparekey(struct __hmac_sha256_key *key,
+ const u8 *raw_key, size_t raw_key_len,
+ const struct sha256_block_state *iv)
+{
+ union {
+ u8 b[SHA256_BLOCK_SIZE];
+ unsigned long w[SHA256_BLOCK_SIZE / sizeof(unsigned long)];
+ } derived_key = { 0 };
+
+ if (unlikely(raw_key_len > SHA256_BLOCK_SIZE)) {
+ if (iv == &sha224_iv)
+ sha224(raw_key, raw_key_len, derived_key.b);
+ else
+ sha256(raw_key, raw_key_len, derived_key.b);
+ } else {
+ memcpy(derived_key.b, raw_key, raw_key_len);
+ }
+
+ for (size_t i = 0; i < ARRAY_SIZE(derived_key.w); i++)
+ derived_key.w[i] ^= REPEAT_BYTE(HMAC_IPAD_VALUE);
+ key->istate = *iv;
+ sha256_blocks(&key->istate, derived_key.b, 1);
+
+ for (size_t i = 0; i < ARRAY_SIZE(derived_key.w); i++)
+ derived_key.w[i] ^= REPEAT_BYTE(HMAC_OPAD_VALUE ^
+ HMAC_IPAD_VALUE);
+ key->ostate = *iv;
+ sha256_blocks(&key->ostate, derived_key.b, 1);
+
+ memzero_explicit(&derived_key, sizeof(derived_key));
+}
+
+void hmac_sha224_preparekey(struct hmac_sha224_key *key,
+ const u8 *raw_key, size_t raw_key_len)
+{
+ __hmac_sha256_preparekey(&key->key, raw_key, raw_key_len, &sha224_iv);
+}
+EXPORT_SYMBOL_GPL(hmac_sha224_preparekey);
+
+void hmac_sha256_preparekey(struct hmac_sha256_key *key,
+ const u8 *raw_key, size_t raw_key_len)
+{
+ __hmac_sha256_preparekey(&key->key, raw_key, raw_key_len, &sha256_iv);
+}
+EXPORT_SYMBOL_GPL(hmac_sha256_preparekey);
+
+void __hmac_sha256_init(struct __hmac_sha256_ctx *ctx,
+ const struct __hmac_sha256_key *key)
+{
+ __sha256_init(&ctx->sha_ctx, &key->istate, SHA256_BLOCK_SIZE);
+ ctx->ostate = key->ostate;
+}
+EXPORT_SYMBOL_GPL(__hmac_sha256_init);
+
+static void __hmac_sha256_final(struct __hmac_sha256_ctx *ctx,
+ u8 *out, size_t digest_size)
+{
+ /* Generate the padded input for the outer hash in ctx->sha_ctx.buf. */
+ __sha256_final(&ctx->sha_ctx, ctx->sha_ctx.buf, digest_size);
+ memset(&ctx->sha_ctx.buf[digest_size], 0,
+ SHA256_BLOCK_SIZE - digest_size);
+ ctx->sha_ctx.buf[digest_size] = 0x80;
+ *(__be32 *)&ctx->sha_ctx.buf[SHA256_BLOCK_SIZE - 4] =
+ cpu_to_be32(8 * (SHA256_BLOCK_SIZE + digest_size));
+
+ /* Compute the outer hash, which gives the HMAC value. */
+ sha256_blocks(&ctx->ostate, ctx->sha_ctx.buf, 1);
+ for (size_t i = 0; i < digest_size; i += 4)
+ put_unaligned_be32(ctx->ostate.h[i / 4], out + i);
+
+ memzero_explicit(ctx, sizeof(*ctx));
+}
+
+void hmac_sha224_final(struct hmac_sha224_ctx *ctx,
+ u8 out[SHA224_DIGEST_SIZE])
+{
+ __hmac_sha256_final(&ctx->ctx, out, SHA224_DIGEST_SIZE);
+}
+EXPORT_SYMBOL_GPL(hmac_sha224_final);
+
+void hmac_sha256_final(struct hmac_sha256_ctx *ctx,
+ u8 out[SHA256_DIGEST_SIZE])
+{
+ __hmac_sha256_final(&ctx->ctx, out, SHA256_DIGEST_SIZE);
+}
+EXPORT_SYMBOL_GPL(hmac_sha256_final);
+
+void hmac_sha224(const struct hmac_sha224_key *key,
+ const u8 *data, size_t data_len, u8 out[SHA224_DIGEST_SIZE])
+{
+ struct hmac_sha224_ctx ctx;
+
+ hmac_sha224_init(&ctx, key);
+ hmac_sha224_update(&ctx, data, data_len);
+ hmac_sha224_final(&ctx, out);
+}
+EXPORT_SYMBOL_GPL(hmac_sha224);
+
+void hmac_sha256(const struct hmac_sha256_key *key,
+ const u8 *data, size_t data_len, u8 out[SHA256_DIGEST_SIZE])
+{
+ struct hmac_sha256_ctx ctx;
+
+ hmac_sha256_init(&ctx, key);
+ hmac_sha256_update(&ctx, data, data_len);
+ hmac_sha256_final(&ctx, out);
+}
+EXPORT_SYMBOL_GPL(hmac_sha256);
+
+void hmac_sha224_usingrawkey(const u8 *raw_key, size_t raw_key_len,
+ const u8 *data, size_t data_len,
+ u8 out[SHA224_DIGEST_SIZE])
+{
+ struct hmac_sha224_key key;
+
+ hmac_sha224_preparekey(&key, raw_key, raw_key_len);
+ hmac_sha224(&key, data, data_len, out);
+
+ memzero_explicit(&key, sizeof(key));
+}
+EXPORT_SYMBOL_GPL(hmac_sha224_usingrawkey);
+
+void hmac_sha256_usingrawkey(const u8 *raw_key, size_t raw_key_len,
+ const u8 *data, size_t data_len,
+ u8 out[SHA256_DIGEST_SIZE])
+{
+ struct hmac_sha256_key key;
+
+ hmac_sha256_preparekey(&key, raw_key, raw_key_len);
+ hmac_sha256(&key, data, data_len, out);
+
+ memzero_explicit(&key, sizeof(key));
+}
+EXPORT_SYMBOL_GPL(hmac_sha256_usingrawkey);
+#endif /* !__DISABLE_EXPORTS */
+
+MODULE_DESCRIPTION("SHA-224, SHA-256, HMAC-SHA224, and HMAC-SHA256 library functions");
MODULE_LICENSE("GPL");
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 09/14] crypto: sha256 - Wrap library and add HMAC support
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (7 preceding siblings ...)
2025-06-30 16:06 ` [PATCH v2 08/14] lib/crypto: sha256: Add HMAC-SHA224 and HMAC-SHA256 support Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 10/14] crypto: sha256 - Use same state format as legacy drivers Eric Biggers
` (6 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
Like I did for crypto/sha512.c, rework crypto/sha256.c to simply wrap
the normal library functions instead of accessing the low-level arch-
optimized and generic block functions directly. Also add support for
HMAC-SHA224 and HMAC-SHA256, again just wrapping the library functions.
Since the replacement crypto_shash algorithms are implemented using the
(potentially arch-optimized) library functions, give them driver names
ending with "-lib" rather than "-generic". Update crypto/testmgr.c and
a couple odd drivers to take this change in driver name into account.
Besides the above cases which are accounted for, there are no known
cases where the driver names were being depended on. There is
potential for confusion for people manually checking /proc/crypto (e.g.
https://lore.kernel.org/r/9e33c893-2466-4d4e-afb1-966334e451a2@linux.ibm.com/),
but really people just need to get used to the driver name not being
meaningful for the software algorithms. Historically, the optimized
code was disabled by default, so there was some purpose to checking
whether it was enabled or not. However, this is now fixed for all SHA-2
algorithms, and the library code just always does the right thing. E.g.
if the CPU supports SHA-256 instructions, they are used.
This change does also mean that the generic partial block handling code
in crypto/shash.c, which got added in 6.16, no longer gets used. But
that's fine; the library has to implement the partial block handling
anyway, and it's better to do it in the library since the block size and
other properties of the algorithm are all fixed at compile time there,
resulting in more streamlined code.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/Kconfig | 4 +-
crypto/Makefile | 1 -
crypto/sha256.c | 286 ++++++++++++--------------
crypto/testmgr.c | 12 ++
drivers/crypto/img-hash.c | 4 +-
drivers/crypto/starfive/jh7110-hash.c | 8 +-
6 files changed, 148 insertions(+), 167 deletions(-)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index cb40a9b469722..3ea1397214e02 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -990,13 +990,13 @@ config CRYPTO_SHA1
config CRYPTO_SHA256
tristate "SHA-224 and SHA-256"
select CRYPTO_HASH
select CRYPTO_LIB_SHA256
- select CRYPTO_LIB_SHA256_GENERIC
help
- SHA-224 and SHA-256 secure hash algorithms (FIPS 180, ISO/IEC 10118-3)
+ SHA-224 and SHA-256 secure hash algorithms (FIPS 180, ISO/IEC
+ 10118-3), including HMAC support.
This is required for IPsec AH (XFRM_AH) and IPsec ESP (XFRM_ESP).
Used by the btrfs filesystem, Ceph, NFS, and SMB.
config CRYPTO_SHA512
diff --git a/crypto/Makefile b/crypto/Makefile
index 271c77462cec9..5098fa6d5f39c 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -75,11 +75,10 @@ obj-$(CONFIG_CRYPTO_NULL) += crypto_null.o
obj-$(CONFIG_CRYPTO_MD4) += md4.o
obj-$(CONFIG_CRYPTO_MD5) += md5.o
obj-$(CONFIG_CRYPTO_RMD160) += rmd160.o
obj-$(CONFIG_CRYPTO_SHA1) += sha1_generic.o
obj-$(CONFIG_CRYPTO_SHA256) += sha256.o
-CFLAGS_sha256.o += -DARCH=$(ARCH)
obj-$(CONFIG_CRYPTO_SHA512) += sha512.o
obj-$(CONFIG_CRYPTO_SHA3) += sha3_generic.o
obj-$(CONFIG_CRYPTO_SM3_GENERIC) += sm3_generic.o
obj-$(CONFIG_CRYPTO_STREEBOG) += streebog_generic.o
obj-$(CONFIG_CRYPTO_WP512) += wp512.o
diff --git a/crypto/sha256.c b/crypto/sha256.c
index 15c57fba256b7..d81166cbba953 100644
--- a/crypto/sha256.c
+++ b/crypto/sha256.c
@@ -1,283 +1,253 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
- * Crypto API wrapper for the SHA-256 and SHA-224 library functions
+ * Crypto API support for SHA-224, SHA-256, HMAC-SHA224, and HMAC-SHA256
*
* Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
* Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* SHA224 Support Copyright 2007 Intel Corporation <jonathan.lynch@intel.com>
+ * Copyright 2025 Google LLC
*/
#include <crypto/internal/hash.h>
-#include <crypto/internal/sha2.h>
+#include <crypto/sha2.h>
#include <linux/kernel.h>
#include <linux/module.h>
+/* SHA-224 */
+
const u8 sha224_zero_message_hash[SHA224_DIGEST_SIZE] = {
0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 0x47,
0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4, 0x15, 0xa2,
0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, 0xc5, 0xb3, 0xe4,
0x2f
};
EXPORT_SYMBOL_GPL(sha224_zero_message_hash);
+#define SHA224_CTX(desc) ((struct sha224_ctx *)shash_desc_ctx(desc))
+
+static int crypto_sha224_init(struct shash_desc *desc)
+{
+ sha224_init(SHA224_CTX(desc));
+ return 0;
+}
+
+static int crypto_sha224_update(struct shash_desc *desc,
+ const u8 *data, unsigned int len)
+{
+ sha224_update(SHA224_CTX(desc), data, len);
+ return 0;
+}
+
+static int crypto_sha224_final(struct shash_desc *desc, u8 *out)
+{
+ sha224_final(SHA224_CTX(desc), out);
+ return 0;
+}
+
+static int crypto_sha224_digest(struct shash_desc *desc,
+ const u8 *data, unsigned int len, u8 *out)
+{
+ sha224(data, len, out);
+ return 0;
+}
+
+/* SHA-256 */
+
const u8 sha256_zero_message_hash[SHA256_DIGEST_SIZE] = {
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
};
EXPORT_SYMBOL_GPL(sha256_zero_message_hash);
+#define SHA256_CTX(desc) ((struct sha256_ctx *)shash_desc_ctx(desc))
+
static int crypto_sha256_init(struct shash_desc *desc)
{
- sha256_block_init(shash_desc_ctx(desc));
+ sha256_init(SHA256_CTX(desc));
return 0;
}
-static inline int crypto_sha256_update(struct shash_desc *desc, const u8 *data,
- unsigned int len, bool force_generic)
+static int crypto_sha256_update(struct shash_desc *desc,
+ const u8 *data, unsigned int len)
{
- struct crypto_sha256_state *sctx = shash_desc_ctx(desc);
- int remain = len % SHA256_BLOCK_SIZE;
-
- sctx->count += len - remain;
- sha256_choose_blocks(sctx->state, data, len / SHA256_BLOCK_SIZE,
- force_generic, !force_generic);
- return remain;
+ sha256_update(SHA256_CTX(desc), data, len);
+ return 0;
}
-static int crypto_sha256_update_generic(struct shash_desc *desc, const u8 *data,
- unsigned int len)
+static int crypto_sha256_final(struct shash_desc *desc, u8 *out)
{
- return crypto_sha256_update(desc, data, len, true);
+ sha256_final(SHA256_CTX(desc), out);
+ return 0;
}
-static int crypto_sha256_update_lib(struct shash_desc *desc, const u8 *data,
- unsigned int len)
+static int crypto_sha256_digest(struct shash_desc *desc,
+ const u8 *data, unsigned int len, u8 *out)
{
- sha256_update(shash_desc_ctx(desc), data, len);
+ sha256(data, len, out);
return 0;
}
-static int crypto_sha256_update_arch(struct shash_desc *desc, const u8 *data,
- unsigned int len)
-{
- return crypto_sha256_update(desc, data, len, false);
-}
+/* HMAC-SHA224 */
-static int crypto_sha256_final_lib(struct shash_desc *desc, u8 *out)
-{
- sha256_final(shash_desc_ctx(desc), out);
- return 0;
-}
+#define HMAC_SHA224_KEY(tfm) ((struct hmac_sha224_key *)crypto_shash_ctx(tfm))
+#define HMAC_SHA224_CTX(desc) ((struct hmac_sha224_ctx *)shash_desc_ctx(desc))
-static __always_inline int crypto_sha256_finup(struct shash_desc *desc,
- const u8 *data,
- unsigned int len, u8 *out,
- bool force_generic)
+static int crypto_hmac_sha224_setkey(struct crypto_shash *tfm,
+ const u8 *raw_key, unsigned int keylen)
{
- struct crypto_sha256_state *sctx = shash_desc_ctx(desc);
- unsigned int remain = len;
- u8 *buf;
-
- if (len >= SHA256_BLOCK_SIZE)
- remain = crypto_sha256_update(desc, data, len, force_generic);
- sctx->count += remain;
- buf = memcpy(sctx + 1, data + len - remain, remain);
- sha256_finup(sctx, buf, remain, out,
- crypto_shash_digestsize(desc->tfm), force_generic,
- !force_generic);
+ hmac_sha224_preparekey(HMAC_SHA224_KEY(tfm), raw_key, keylen);
return 0;
}
-static int crypto_sha256_finup_generic(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
+static int crypto_hmac_sha224_init(struct shash_desc *desc)
{
- return crypto_sha256_finup(desc, data, len, out, true);
+ hmac_sha224_init(HMAC_SHA224_CTX(desc), HMAC_SHA224_KEY(desc->tfm));
+ return 0;
}
-static int crypto_sha256_finup_arch(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
+static int crypto_hmac_sha224_update(struct shash_desc *desc,
+ const u8 *data, unsigned int len)
{
- return crypto_sha256_finup(desc, data, len, out, false);
+ hmac_sha224_update(HMAC_SHA224_CTX(desc), data, len);
+ return 0;
}
-static int crypto_sha256_digest_generic(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
+static int crypto_hmac_sha224_final(struct shash_desc *desc, u8 *out)
{
- crypto_sha256_init(desc);
- return crypto_sha256_finup_generic(desc, data, len, out);
+ hmac_sha224_final(HMAC_SHA224_CTX(desc), out);
+ return 0;
}
-static int crypto_sha256_digest_lib(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
+static int crypto_hmac_sha224_digest(struct shash_desc *desc,
+ const u8 *data, unsigned int len,
+ u8 *out)
{
- sha256(data, len, out);
+ hmac_sha224(HMAC_SHA224_KEY(desc->tfm), data, len, out);
return 0;
}
-static int crypto_sha256_digest_arch(struct shash_desc *desc, const u8 *data,
- unsigned int len, u8 *out)
+/* HMAC-SHA256 */
+
+#define HMAC_SHA256_KEY(tfm) ((struct hmac_sha256_key *)crypto_shash_ctx(tfm))
+#define HMAC_SHA256_CTX(desc) ((struct hmac_sha256_ctx *)shash_desc_ctx(desc))
+
+static int crypto_hmac_sha256_setkey(struct crypto_shash *tfm,
+ const u8 *raw_key, unsigned int keylen)
{
- crypto_sha256_init(desc);
- return crypto_sha256_finup_arch(desc, data, len, out);
+ hmac_sha256_preparekey(HMAC_SHA256_KEY(tfm), raw_key, keylen);
+ return 0;
}
-static int crypto_sha224_init(struct shash_desc *desc)
+static int crypto_hmac_sha256_init(struct shash_desc *desc)
{
- sha224_block_init(shash_desc_ctx(desc));
+ hmac_sha256_init(HMAC_SHA256_CTX(desc), HMAC_SHA256_KEY(desc->tfm));
return 0;
}
-static int crypto_sha224_final_lib(struct shash_desc *desc, u8 *out)
+static int crypto_hmac_sha256_update(struct shash_desc *desc,
+ const u8 *data, unsigned int len)
{
- sha224_final(shash_desc_ctx(desc), out);
+ hmac_sha256_update(HMAC_SHA256_CTX(desc), data, len);
return 0;
}
-static int crypto_sha256_import_lib(struct shash_desc *desc, const void *in)
+static int crypto_hmac_sha256_final(struct shash_desc *desc, u8 *out)
{
- struct __sha256_ctx *sctx = shash_desc_ctx(desc);
- const u8 *p = in;
-
- memcpy(sctx, p, sizeof(*sctx));
- p += sizeof(*sctx);
- sctx->bytecount += *p;
+ hmac_sha256_final(HMAC_SHA256_CTX(desc), out);
return 0;
}
-static int crypto_sha256_export_lib(struct shash_desc *desc, void *out)
+static int crypto_hmac_sha256_digest(struct shash_desc *desc,
+ const u8 *data, unsigned int len,
+ u8 *out)
{
- struct __sha256_ctx *sctx0 = shash_desc_ctx(desc);
- struct __sha256_ctx sctx = *sctx0;
- unsigned int partial;
- u8 *p = out;
-
- partial = sctx.bytecount % SHA256_BLOCK_SIZE;
- sctx.bytecount -= partial;
- memcpy(p, &sctx, sizeof(sctx));
- p += sizeof(sctx);
- *p = partial;
+ hmac_sha256(HMAC_SHA256_KEY(desc->tfm), data, len, out);
return 0;
}
+/* Algorithm definitions */
+
static struct shash_alg algs[] = {
- {
- .base.cra_name = "sha256",
- .base.cra_driver_name = "sha256-generic",
- .base.cra_priority = 100,
- .base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
- CRYPTO_AHASH_ALG_FINUP_MAX,
- .base.cra_blocksize = SHA256_BLOCK_SIZE,
- .base.cra_module = THIS_MODULE,
- .digestsize = SHA256_DIGEST_SIZE,
- .init = crypto_sha256_init,
- .update = crypto_sha256_update_generic,
- .finup = crypto_sha256_finup_generic,
- .digest = crypto_sha256_digest_generic,
- .descsize = sizeof(struct crypto_sha256_state),
- },
{
.base.cra_name = "sha224",
- .base.cra_driver_name = "sha224-generic",
- .base.cra_priority = 100,
- .base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
- CRYPTO_AHASH_ALG_FINUP_MAX,
+ .base.cra_driver_name = "sha224-lib",
+ .base.cra_priority = 300,
.base.cra_blocksize = SHA224_BLOCK_SIZE,
.base.cra_module = THIS_MODULE,
.digestsize = SHA224_DIGEST_SIZE,
.init = crypto_sha224_init,
- .update = crypto_sha256_update_generic,
- .finup = crypto_sha256_finup_generic,
- .descsize = sizeof(struct crypto_sha256_state),
+ .update = crypto_sha224_update,
+ .final = crypto_sha224_final,
+ .digest = crypto_sha224_digest,
+ .descsize = sizeof(struct sha224_ctx),
},
{
.base.cra_name = "sha256",
.base.cra_driver_name = "sha256-lib",
+ .base.cra_priority = 300,
.base.cra_blocksize = SHA256_BLOCK_SIZE,
.base.cra_module = THIS_MODULE,
.digestsize = SHA256_DIGEST_SIZE,
.init = crypto_sha256_init,
- .update = crypto_sha256_update_lib,
- .final = crypto_sha256_final_lib,
- .digest = crypto_sha256_digest_lib,
+ .update = crypto_sha256_update,
+ .final = crypto_sha256_final,
+ .digest = crypto_sha256_digest,
.descsize = sizeof(struct sha256_ctx),
- .statesize = sizeof(struct crypto_sha256_state) +
- SHA256_BLOCK_SIZE + 1,
- .import = crypto_sha256_import_lib,
- .export = crypto_sha256_export_lib,
},
{
- .base.cra_name = "sha224",
- .base.cra_driver_name = "sha224-lib",
+ .base.cra_name = "hmac(sha224)",
+ .base.cra_driver_name = "hmac-sha224-lib",
+ .base.cra_priority = 300,
.base.cra_blocksize = SHA224_BLOCK_SIZE,
+ .base.cra_ctxsize = sizeof(struct hmac_sha224_key),
.base.cra_module = THIS_MODULE,
.digestsize = SHA224_DIGEST_SIZE,
- .init = crypto_sha224_init,
- .update = crypto_sha256_update_lib,
- .final = crypto_sha224_final_lib,
- .descsize = sizeof(struct sha224_ctx),
- .statesize = sizeof(struct crypto_sha256_state) +
- SHA256_BLOCK_SIZE + 1,
- .import = crypto_sha256_import_lib,
- .export = crypto_sha256_export_lib,
+ .setkey = crypto_hmac_sha224_setkey,
+ .init = crypto_hmac_sha224_init,
+ .update = crypto_hmac_sha224_update,
+ .final = crypto_hmac_sha224_final,
+ .digest = crypto_hmac_sha224_digest,
+ .descsize = sizeof(struct hmac_sha224_ctx),
},
{
- .base.cra_name = "sha256",
- .base.cra_driver_name = "sha256-" __stringify(ARCH),
+ .base.cra_name = "hmac(sha256)",
+ .base.cra_driver_name = "hmac-sha256-lib",
.base.cra_priority = 300,
- .base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
- CRYPTO_AHASH_ALG_FINUP_MAX,
.base.cra_blocksize = SHA256_BLOCK_SIZE,
+ .base.cra_ctxsize = sizeof(struct hmac_sha256_key),
.base.cra_module = THIS_MODULE,
.digestsize = SHA256_DIGEST_SIZE,
- .init = crypto_sha256_init,
- .update = crypto_sha256_update_arch,
- .finup = crypto_sha256_finup_arch,
- .digest = crypto_sha256_digest_arch,
- .descsize = sizeof(struct crypto_sha256_state),
- },
- {
- .base.cra_name = "sha224",
- .base.cra_driver_name = "sha224-" __stringify(ARCH),
- .base.cra_priority = 300,
- .base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
- CRYPTO_AHASH_ALG_FINUP_MAX,
- .base.cra_blocksize = SHA224_BLOCK_SIZE,
- .base.cra_module = THIS_MODULE,
- .digestsize = SHA224_DIGEST_SIZE,
- .init = crypto_sha224_init,
- .update = crypto_sha256_update_arch,
- .finup = crypto_sha256_finup_arch,
- .descsize = sizeof(struct crypto_sha256_state),
+ .setkey = crypto_hmac_sha256_setkey,
+ .init = crypto_hmac_sha256_init,
+ .update = crypto_hmac_sha256_update,
+ .final = crypto_hmac_sha256_final,
+ .digest = crypto_hmac_sha256_digest,
+ .descsize = sizeof(struct hmac_sha256_ctx),
},
};
-static unsigned int num_algs;
-
static int __init crypto_sha256_mod_init(void)
{
- /* register the arch flavours only if they differ from generic */
- num_algs = ARRAY_SIZE(algs);
- BUILD_BUG_ON(ARRAY_SIZE(algs) <= 2);
- if (!sha256_is_arch_optimized())
- num_algs -= 2;
return crypto_register_shashes(algs, ARRAY_SIZE(algs));
}
module_init(crypto_sha256_mod_init);
static void __exit crypto_sha256_mod_exit(void)
{
- crypto_unregister_shashes(algs, num_algs);
+ crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
}
module_exit(crypto_sha256_mod_exit);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Crypto API wrapper for the SHA-256 and SHA-224 library functions");
+MODULE_DESCRIPTION("Crypto API support for SHA-224, SHA-256, HMAC-SHA224, and HMAC-SHA256");
-MODULE_ALIAS_CRYPTO("sha256");
-MODULE_ALIAS_CRYPTO("sha256-generic");
-MODULE_ALIAS_CRYPTO("sha256-" __stringify(ARCH));
MODULE_ALIAS_CRYPTO("sha224");
-MODULE_ALIAS_CRYPTO("sha224-generic");
-MODULE_ALIAS_CRYPTO("sha224-" __stringify(ARCH));
+MODULE_ALIAS_CRYPTO("sha224-lib");
+MODULE_ALIAS_CRYPTO("sha256");
+MODULE_ALIAS_CRYPTO("sha256-lib");
+MODULE_ALIAS_CRYPTO("hmac(sha224)");
+MODULE_ALIAS_CRYPTO("hmac-sha224-lib");
+MODULE_ALIAS_CRYPTO("hmac(sha256)");
+MODULE_ALIAS_CRYPTO("hmac-sha256-lib");
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 9d8b11ea4af7f..4e95567f7ed17 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -4268,45 +4268,51 @@ static const struct alg_test_desc alg_test_descs[] = {
.alg = "authenc(hmac(sha1),rfc3686(ctr(aes)))",
.test = alg_test_null,
.fips_allowed = 1,
}, {
.alg = "authenc(hmac(sha224),cbc(des))",
+ .generic_driver = "authenc(hmac-sha224-lib,cbc(des-generic))",
.test = alg_test_aead,
.suite = {
.aead = __VECS(hmac_sha224_des_cbc_tv_temp)
}
}, {
.alg = "authenc(hmac(sha224),cbc(des3_ede))",
+ .generic_driver = "authenc(hmac-sha224-lib,cbc(des3_ede-generic))",
.test = alg_test_aead,
.suite = {
.aead = __VECS(hmac_sha224_des3_ede_cbc_tv_temp)
}
}, {
.alg = "authenc(hmac(sha256),cbc(aes))",
+ .generic_driver = "authenc(hmac-sha256-lib,cbc(aes-generic))",
.test = alg_test_aead,
.fips_allowed = 1,
.suite = {
.aead = __VECS(hmac_sha256_aes_cbc_tv_temp)
}
}, {
.alg = "authenc(hmac(sha256),cbc(des))",
+ .generic_driver = "authenc(hmac-sha256-lib,cbc(des-generic))",
.test = alg_test_aead,
.suite = {
.aead = __VECS(hmac_sha256_des_cbc_tv_temp)
}
}, {
.alg = "authenc(hmac(sha256),cbc(des3_ede))",
+ .generic_driver = "authenc(hmac-sha256-lib,cbc(des3_ede-generic))",
.test = alg_test_aead,
.suite = {
.aead = __VECS(hmac_sha256_des3_ede_cbc_tv_temp)
}
}, {
.alg = "authenc(hmac(sha256),ctr(aes))",
.test = alg_test_null,
.fips_allowed = 1,
}, {
.alg = "authenc(hmac(sha256),cts(cbc(aes)))",
+ .generic_driver = "authenc(hmac-sha256-lib,cts(cbc(aes-generic)))",
.test = alg_test_aead,
.suite = {
.aead = __VECS(krb5_test_aes128_cts_hmac_sha256_128)
}
}, {
@@ -5013,17 +5019,19 @@ static const struct alg_test_desc alg_test_descs[] = {
.suite = {
.sig = __VECS(ecrdsa_tv_template)
}
}, {
.alg = "essiv(authenc(hmac(sha256),cbc(aes)),sha256)",
+ .generic_driver = "essiv(authenc(hmac-sha256-lib,cbc(aes-generic)),sha256-lib)",
.test = alg_test_aead,
.fips_allowed = 1,
.suite = {
.aead = __VECS(essiv_hmac_sha256_aes_cbc_tv_temp)
}
}, {
.alg = "essiv(cbc(aes),sha256)",
+ .generic_driver = "essiv(cbc(aes-generic),sha256-lib)",
.test = alg_test_skcipher,
.fips_allowed = 1,
.suite = {
.cipher = __VECS(essiv_aes_cbc_tv_template)
}
@@ -5119,17 +5127,19 @@ static const struct alg_test_desc alg_test_descs[] = {
.suite = {
.hash = __VECS(hmac_sha1_tv_template)
}
}, {
.alg = "hmac(sha224)",
+ .generic_driver = "hmac-sha224-lib",
.test = alg_test_hash,
.fips_allowed = 1,
.suite = {
.hash = __VECS(hmac_sha224_tv_template)
}
}, {
.alg = "hmac(sha256)",
+ .generic_driver = "hmac-sha256-lib",
.test = alg_test_hash,
.fips_allowed = 1,
.suite = {
.hash = __VECS(hmac_sha256_tv_template)
}
@@ -5457,17 +5467,19 @@ static const struct alg_test_desc alg_test_descs[] = {
.suite = {
.hash = __VECS(sha1_tv_template)
}
}, {
.alg = "sha224",
+ .generic_driver = "sha224-lib",
.test = alg_test_hash,
.fips_allowed = 1,
.suite = {
.hash = __VECS(sha224_tv_template)
}
}, {
.alg = "sha256",
+ .generic_driver = "sha256-lib",
.test = alg_test_hash,
.fips_allowed = 1,
.suite = {
.hash = __VECS(sha256_tv_template)
}
diff --git a/drivers/crypto/img-hash.c b/drivers/crypto/img-hash.c
index e050f5ff5efb6..f312eb075feca 100644
--- a/drivers/crypto/img-hash.c
+++ b/drivers/crypto/img-hash.c
@@ -708,16 +708,16 @@ static int img_hash_cra_sha1_init(struct crypto_tfm *tfm)
return img_hash_cra_init(tfm, "sha1-generic");
}
static int img_hash_cra_sha224_init(struct crypto_tfm *tfm)
{
- return img_hash_cra_init(tfm, "sha224-generic");
+ return img_hash_cra_init(tfm, "sha224-lib");
}
static int img_hash_cra_sha256_init(struct crypto_tfm *tfm)
{
- return img_hash_cra_init(tfm, "sha256-generic");
+ return img_hash_cra_init(tfm, "sha256-lib");
}
static void img_hash_cra_exit(struct crypto_tfm *tfm)
{
struct img_hash_ctx *tctx = crypto_tfm_ctx(tfm);
diff --git a/drivers/crypto/starfive/jh7110-hash.c b/drivers/crypto/starfive/jh7110-hash.c
index 4abbff07412ff..6cfe0238f615f 100644
--- a/drivers/crypto/starfive/jh7110-hash.c
+++ b/drivers/crypto/starfive/jh7110-hash.c
@@ -491,17 +491,17 @@ static int starfive_hash_setkey(struct crypto_ahash *hash,
return starfive_hash_long_setkey(ctx, key, keylen, alg_name);
}
static int starfive_sha224_init_tfm(struct crypto_ahash *hash)
{
- return starfive_hash_init_tfm(hash, "sha224-generic",
+ return starfive_hash_init_tfm(hash, "sha224-lib",
STARFIVE_HASH_SHA224, 0);
}
static int starfive_sha256_init_tfm(struct crypto_ahash *hash)
{
- return starfive_hash_init_tfm(hash, "sha256-generic",
+ return starfive_hash_init_tfm(hash, "sha256-lib",
STARFIVE_HASH_SHA256, 0);
}
static int starfive_sha384_init_tfm(struct crypto_ahash *hash)
{
@@ -521,17 +521,17 @@ static int starfive_sm3_init_tfm(struct crypto_ahash *hash)
STARFIVE_HASH_SM3, 0);
}
static int starfive_hmac_sha224_init_tfm(struct crypto_ahash *hash)
{
- return starfive_hash_init_tfm(hash, "hmac(sha224-generic)",
+ return starfive_hash_init_tfm(hash, "hmac-sha224-lib",
STARFIVE_HASH_SHA224, 1);
}
static int starfive_hmac_sha256_init_tfm(struct crypto_ahash *hash)
{
- return starfive_hash_init_tfm(hash, "hmac(sha256-generic)",
+ return starfive_hash_init_tfm(hash, "hmac-sha256-lib",
STARFIVE_HASH_SHA256, 1);
}
static int starfive_hmac_sha384_init_tfm(struct crypto_ahash *hash)
{
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 10/14] crypto: sha256 - Use same state format as legacy drivers
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (8 preceding siblings ...)
2025-06-30 16:06 ` [PATCH v2 09/14] crypto: sha256 - Wrap library and add HMAC support Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 11/14] lib/crypto: sha256: Remove sha256_is_arch_optimized() Eric Biggers
` (5 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
Make the export and import functions for the sha224, sha256,
hmac(sha224), and hmac(sha256) shash algorithms use the same format as
the padlock-sha and nx-sha256 drivers, as required by Herbert.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
crypto/sha256.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/crypto/sha256.c b/crypto/sha256.c
index d81166cbba953..052806559f06c 100644
--- a/crypto/sha256.c
+++ b/crypto/sha256.c
@@ -11,10 +11,47 @@
#include <crypto/internal/hash.h>
#include <crypto/sha2.h>
#include <linux/kernel.h>
#include <linux/module.h>
+/*
+ * Export and import functions. crypto_shash wants a particular format that
+ * matches that used by some legacy drivers. It currently is the same as the
+ * library SHA context, except the value in bytecount must be block-aligned and
+ * the remainder must be stored in an extra u8 appended to the struct.
+ */
+
+#define SHA256_SHASH_STATE_SIZE 105
+static_assert(offsetof(struct __sha256_ctx, state) == 0);
+static_assert(offsetof(struct __sha256_ctx, bytecount) == 32);
+static_assert(offsetof(struct __sha256_ctx, buf) == 40);
+static_assert(sizeof(struct __sha256_ctx) + 1 == SHA256_SHASH_STATE_SIZE);
+
+static int __crypto_sha256_export(const struct __sha256_ctx *ctx0, void *out)
+{
+ struct __sha256_ctx ctx = *ctx0;
+ unsigned int partial;
+ u8 *p = out;
+
+ partial = ctx.bytecount % SHA256_BLOCK_SIZE;
+ ctx.bytecount -= partial;
+ memcpy(p, &ctx, sizeof(ctx));
+ p += sizeof(ctx);
+ *p = partial;
+ return 0;
+}
+
+static int __crypto_sha256_import(struct __sha256_ctx *ctx, const void *in)
+{
+ const u8 *p = in;
+
+ memcpy(ctx, p, sizeof(*ctx));
+ p += sizeof(*ctx);
+ ctx->bytecount += *p;
+ return 0;
+}
+
/* SHA-224 */
const u8 sha224_zero_message_hash[SHA224_DIGEST_SIZE] = {
0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, 0x47,
0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4, 0x15, 0xa2,
@@ -49,10 +86,20 @@ static int crypto_sha224_digest(struct shash_desc *desc,
{
sha224(data, len, out);
return 0;
}
+static int crypto_sha224_export(struct shash_desc *desc, void *out)
+{
+ return __crypto_sha256_export(&SHA224_CTX(desc)->ctx, out);
+}
+
+static int crypto_sha224_import(struct shash_desc *desc, const void *in)
+{
+ return __crypto_sha256_import(&SHA224_CTX(desc)->ctx, in);
+}
+
/* SHA-256 */
const u8 sha256_zero_message_hash[SHA256_DIGEST_SIZE] = {
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
@@ -87,10 +134,20 @@ static int crypto_sha256_digest(struct shash_desc *desc,
{
sha256(data, len, out);
return 0;
}
+static int crypto_sha256_export(struct shash_desc *desc, void *out)
+{
+ return __crypto_sha256_export(&SHA256_CTX(desc)->ctx, out);
+}
+
+static int crypto_sha256_import(struct shash_desc *desc, const void *in)
+{
+ return __crypto_sha256_import(&SHA256_CTX(desc)->ctx, in);
+}
+
/* HMAC-SHA224 */
#define HMAC_SHA224_KEY(tfm) ((struct hmac_sha224_key *)crypto_shash_ctx(tfm))
#define HMAC_SHA224_CTX(desc) ((struct hmac_sha224_ctx *)shash_desc_ctx(desc))
@@ -126,10 +183,23 @@ static int crypto_hmac_sha224_digest(struct shash_desc *desc,
{
hmac_sha224(HMAC_SHA224_KEY(desc->tfm), data, len, out);
return 0;
}
+static int crypto_hmac_sha224_export(struct shash_desc *desc, void *out)
+{
+ return __crypto_sha256_export(&HMAC_SHA224_CTX(desc)->ctx.sha_ctx, out);
+}
+
+static int crypto_hmac_sha224_import(struct shash_desc *desc, const void *in)
+{
+ struct hmac_sha224_ctx *ctx = HMAC_SHA224_CTX(desc);
+
+ ctx->ctx.ostate = HMAC_SHA224_KEY(desc->tfm)->key.ostate;
+ return __crypto_sha256_import(&ctx->ctx.sha_ctx, in);
+}
+
/* HMAC-SHA256 */
#define HMAC_SHA256_KEY(tfm) ((struct hmac_sha256_key *)crypto_shash_ctx(tfm))
#define HMAC_SHA256_CTX(desc) ((struct hmac_sha256_ctx *)shash_desc_ctx(desc))
@@ -165,10 +235,23 @@ static int crypto_hmac_sha256_digest(struct shash_desc *desc,
{
hmac_sha256(HMAC_SHA256_KEY(desc->tfm), data, len, out);
return 0;
}
+static int crypto_hmac_sha256_export(struct shash_desc *desc, void *out)
+{
+ return __crypto_sha256_export(&HMAC_SHA256_CTX(desc)->ctx.sha_ctx, out);
+}
+
+static int crypto_hmac_sha256_import(struct shash_desc *desc, const void *in)
+{
+ struct hmac_sha256_ctx *ctx = HMAC_SHA256_CTX(desc);
+
+ ctx->ctx.ostate = HMAC_SHA256_KEY(desc->tfm)->key.ostate;
+ return __crypto_sha256_import(&ctx->ctx.sha_ctx, in);
+}
+
/* Algorithm definitions */
static struct shash_alg algs[] = {
{
.base.cra_name = "sha224",
@@ -179,11 +262,14 @@ static struct shash_alg algs[] = {
.digestsize = SHA224_DIGEST_SIZE,
.init = crypto_sha224_init,
.update = crypto_sha224_update,
.final = crypto_sha224_final,
.digest = crypto_sha224_digest,
+ .export = crypto_sha224_export,
+ .import = crypto_sha224_import,
.descsize = sizeof(struct sha224_ctx),
+ .statesize = SHA256_SHASH_STATE_SIZE,
},
{
.base.cra_name = "sha256",
.base.cra_driver_name = "sha256-lib",
.base.cra_priority = 300,
@@ -192,11 +278,14 @@ static struct shash_alg algs[] = {
.digestsize = SHA256_DIGEST_SIZE,
.init = crypto_sha256_init,
.update = crypto_sha256_update,
.final = crypto_sha256_final,
.digest = crypto_sha256_digest,
+ .export = crypto_sha256_export,
+ .import = crypto_sha256_import,
.descsize = sizeof(struct sha256_ctx),
+ .statesize = SHA256_SHASH_STATE_SIZE,
},
{
.base.cra_name = "hmac(sha224)",
.base.cra_driver_name = "hmac-sha224-lib",
.base.cra_priority = 300,
@@ -207,11 +296,14 @@ static struct shash_alg algs[] = {
.setkey = crypto_hmac_sha224_setkey,
.init = crypto_hmac_sha224_init,
.update = crypto_hmac_sha224_update,
.final = crypto_hmac_sha224_final,
.digest = crypto_hmac_sha224_digest,
+ .export = crypto_hmac_sha224_export,
+ .import = crypto_hmac_sha224_import,
.descsize = sizeof(struct hmac_sha224_ctx),
+ .statesize = SHA256_SHASH_STATE_SIZE,
},
{
.base.cra_name = "hmac(sha256)",
.base.cra_driver_name = "hmac-sha256-lib",
.base.cra_priority = 300,
@@ -222,11 +314,14 @@ static struct shash_alg algs[] = {
.setkey = crypto_hmac_sha256_setkey,
.init = crypto_hmac_sha256_init,
.update = crypto_hmac_sha256_update,
.final = crypto_hmac_sha256_final,
.digest = crypto_hmac_sha256_digest,
+ .export = crypto_hmac_sha256_export,
+ .import = crypto_hmac_sha256_import,
.descsize = sizeof(struct hmac_sha256_ctx),
+ .statesize = SHA256_SHASH_STATE_SIZE,
},
};
static int __init crypto_sha256_mod_init(void)
{
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 11/14] lib/crypto: sha256: Remove sha256_is_arch_optimized()
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (9 preceding siblings ...)
2025-06-30 16:06 ` [PATCH v2 10/14] crypto: sha256 - Use same state format as legacy drivers Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 12/14] lib/crypto: sha256: Consolidate into single module Eric Biggers
` (4 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
Remove sha256_is_arch_optimized(), since it is no longer used.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
arch/mips/cavium-octeon/crypto/octeon-sha256.c | 6 ------
include/crypto/internal/sha2.h | 8 --------
lib/crypto/arm/sha256.c | 7 -------
lib/crypto/arm64/sha256.c | 7 -------
lib/crypto/powerpc/sha256.c | 6 ------
lib/crypto/riscv/sha256.c | 6 ------
lib/crypto/s390/sha256.c | 6 ------
lib/crypto/sparc/sha256.c | 6 ------
lib/crypto/x86/sha256.c | 6 ------
9 files changed, 58 deletions(-)
diff --git a/arch/mips/cavium-octeon/crypto/octeon-sha256.c b/arch/mips/cavium-octeon/crypto/octeon-sha256.c
index f8664818d04ec..c7c67bdc2bd06 100644
--- a/arch/mips/cavium-octeon/crypto/octeon-sha256.c
+++ b/arch/mips/cavium-octeon/crypto/octeon-sha256.c
@@ -59,14 +59,8 @@ void sha256_blocks_arch(struct sha256_block_state *state,
state64[3] = read_octeon_64bit_hash_dword(3);
octeon_crypto_disable(&cop2_state, flags);
}
EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-bool sha256_is_arch_optimized(void)
-{
- return octeon_has_crypto();
-}
-EXPORT_SYMBOL_GPL(sha256_is_arch_optimized);
-
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SHA-256 Secure Hash Algorithm (OCTEON)");
MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
diff --git a/include/crypto/internal/sha2.h b/include/crypto/internal/sha2.h
index f0f455477bbd7..7915a3a46bc86 100644
--- a/include/crypto/internal/sha2.h
+++ b/include/crypto/internal/sha2.h
@@ -7,18 +7,10 @@
#include <linux/compiler_attributes.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/unaligned.h>
-#if IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_SHA256)
-bool sha256_is_arch_optimized(void);
-#else
-static inline bool sha256_is_arch_optimized(void)
-{
- return false;
-}
-#endif
void sha256_blocks_generic(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
void sha256_blocks_arch(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
diff --git a/lib/crypto/arm/sha256.c b/lib/crypto/arm/sha256.c
index 7d90823586952..27181be0aa92e 100644
--- a/lib/crypto/arm/sha256.c
+++ b/lib/crypto/arm/sha256.c
@@ -35,17 +35,10 @@ void sha256_blocks_arch(struct sha256_block_state *state,
sha256_block_data_order(state, data, nblocks);
}
}
EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-bool sha256_is_arch_optimized(void)
-{
- /* We always can use at least the ARM scalar implementation. */
- return true;
-}
-EXPORT_SYMBOL_GPL(sha256_is_arch_optimized);
-
static int __init sha256_arm_mod_init(void)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && (elf_hwcap & HWCAP_NEON)) {
static_branch_enable(&have_neon);
if (elf_hwcap2 & HWCAP2_SHA2)
diff --git a/lib/crypto/arm64/sha256.c b/lib/crypto/arm64/sha256.c
index 609ffb8151987..a5a4982767089 100644
--- a/lib/crypto/arm64/sha256.c
+++ b/lib/crypto/arm64/sha256.c
@@ -45,17 +45,10 @@ void sha256_blocks_arch(struct sha256_block_state *state,
sha256_block_data_order(state, data, nblocks);
}
}
EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-bool sha256_is_arch_optimized(void)
-{
- /* We always can use at least the ARM64 scalar implementation. */
- return true;
-}
-EXPORT_SYMBOL_GPL(sha256_is_arch_optimized);
-
static int __init sha256_arm64_mod_init(void)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
cpu_have_named_feature(ASIMD)) {
static_branch_enable(&have_neon);
diff --git a/lib/crypto/powerpc/sha256.c b/lib/crypto/powerpc/sha256.c
index c3f844ae0aceb..437e587b05754 100644
--- a/lib/crypto/powerpc/sha256.c
+++ b/lib/crypto/powerpc/sha256.c
@@ -58,13 +58,7 @@ void sha256_blocks_arch(struct sha256_block_state *state,
nblocks -= unit;
} while (nblocks);
}
EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-bool sha256_is_arch_optimized(void)
-{
- return true;
-}
-EXPORT_SYMBOL_GPL(sha256_is_arch_optimized);
-
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SHA-256 Secure Hash Algorithm, SPE optimized");
diff --git a/lib/crypto/riscv/sha256.c b/lib/crypto/riscv/sha256.c
index a2079aa3ae925..01004cb9c6e9e 100644
--- a/lib/crypto/riscv/sha256.c
+++ b/lib/crypto/riscv/sha256.c
@@ -32,16 +32,10 @@ void sha256_blocks_arch(struct sha256_block_state *state,
sha256_blocks_generic(state, data, nblocks);
}
}
EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-bool sha256_is_arch_optimized(void)
-{
- return static_key_enabled(&have_extensions);
-}
-EXPORT_SYMBOL_GPL(sha256_is_arch_optimized);
-
static int __init riscv64_sha256_mod_init(void)
{
/* Both zvknha and zvknhb provide the SHA-256 instructions. */
if ((riscv_isa_extension_available(NULL, ZVKNHA) ||
riscv_isa_extension_available(NULL, ZVKNHB)) &&
diff --git a/lib/crypto/s390/sha256.c b/lib/crypto/s390/sha256.c
index fb565718f7539..6ebfd35a5d44c 100644
--- a/lib/crypto/s390/sha256.c
+++ b/lib/crypto/s390/sha256.c
@@ -21,16 +21,10 @@ void sha256_blocks_arch(struct sha256_block_state *state,
else
sha256_blocks_generic(state, data, nblocks);
}
EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-bool sha256_is_arch_optimized(void)
-{
- return static_key_enabled(&have_cpacf_sha256);
-}
-EXPORT_SYMBOL_GPL(sha256_is_arch_optimized);
-
static int __init sha256_s390_mod_init(void)
{
if (cpu_have_feature(S390_CPU_FEATURE_MSA) &&
cpacf_query_func(CPACF_KIMD, CPACF_KIMD_SHA_256))
static_branch_enable(&have_cpacf_sha256);
diff --git a/lib/crypto/sparc/sha256.c b/lib/crypto/sparc/sha256.c
index 060664b88a6d3..f41c109c1c18d 100644
--- a/lib/crypto/sparc/sha256.c
+++ b/lib/crypto/sparc/sha256.c
@@ -30,16 +30,10 @@ void sha256_blocks_arch(struct sha256_block_state *state,
else
sha256_blocks_generic(state, data, nblocks);
}
EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-bool sha256_is_arch_optimized(void)
-{
- return static_key_enabled(&have_sha256_opcodes);
-}
-EXPORT_SYMBOL_GPL(sha256_is_arch_optimized);
-
static int __init sha256_sparc64_mod_init(void)
{
unsigned long cfr;
if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
diff --git a/lib/crypto/x86/sha256.c b/lib/crypto/x86/sha256.c
index cbb45defbefab..9ee38d2b3d572 100644
--- a/lib/crypto/x86/sha256.c
+++ b/lib/crypto/x86/sha256.c
@@ -35,16 +35,10 @@ void sha256_blocks_arch(struct sha256_block_state *state,
sha256_blocks_generic(state, data, nblocks);
}
}
EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-bool sha256_is_arch_optimized(void)
-{
- return static_key_enabled(&have_sha256_x86);
-}
-EXPORT_SYMBOL_GPL(sha256_is_arch_optimized);
-
static int __init sha256_x86_mod_init(void)
{
if (boot_cpu_has(X86_FEATURE_SHA_NI)) {
static_call_update(sha256_blocks_x86, sha256_ni_transform);
} else if (cpu_has_xfeatures(XFEATURE_MASK_SSE |
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 12/14] lib/crypto: sha256: Consolidate into single module
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (10 preceding siblings ...)
2025-06-30 16:06 ` [PATCH v2 11/14] lib/crypto: sha256: Remove sha256_is_arch_optimized() Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 13/14] lib/crypto: sha256: Sync sha256_update() with sha512_update() Eric Biggers
` (3 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
Consolidate the CPU-based SHA-256 code into a single module, following
what I did with SHA-512:
- Each arch now provides a header file lib/crypto/$(SRCARCH)/sha256.h,
replacing lib/crypto/$(SRCARCH)/sha256.c. The header defines
sha256_blocks() and optionally sha256_mod_init_arch(). It is included
by lib/crypto/sha256.c, and thus the code gets built into the single
libsha256 module, with proper inlining and dead code elimination.
- sha256_blocks_generic() is moved from lib/crypto/sha256-generic.c into
lib/crypto/sha256.c. It's now a static function marked with
__maybe_unused, so the compiler automatically eliminates it in any
cases where it's not used.
- Whether arch-optimized SHA-256 is buildable is now controlled
centrally by lib/crypto/Kconfig instead of by
lib/crypto/$(SRCARCH)/Kconfig. The conditions for enabling it remain
the same as before, and it remains enabled by default.
- Any additional arch-specific translation units for the optimized
SHA-256 code (such as assembly files) are now compiled by
lib/crypto/Makefile instead of lib/crypto/$(SRCARCH)/Makefile.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
arch/mips/cavium-octeon/Kconfig | 6 -
arch/mips/cavium-octeon/crypto/Makefile | 1 -
include/crypto/internal/sha2.h | 52 ------
lib/crypto/Kconfig | 26 ++-
lib/crypto/Makefile | 39 ++++-
lib/crypto/arm/Kconfig | 6 -
lib/crypto/arm/Makefile | 8 +-
lib/crypto/arm/{sha256.c => sha256.h} | 27 +---
lib/crypto/arm64/Kconfig | 5 -
lib/crypto/arm64/Makefile | 9 +-
lib/crypto/arm64/{sha256.c => sha256.h} | 29 ++--
.../crypto/mips/sha256.h | 14 +-
lib/crypto/powerpc/Kconfig | 6 -
lib/crypto/powerpc/Makefile | 3 -
lib/crypto/powerpc/{sha256.c => sha256.h} | 13 +-
lib/crypto/riscv/Kconfig | 7 -
lib/crypto/riscv/Makefile | 3 -
lib/crypto/riscv/{sha256.c => sha256.h} | 24 +--
lib/crypto/s390/Kconfig | 6 -
lib/crypto/s390/Makefile | 3 -
lib/crypto/s390/{sha256.c => sha256.h} | 23 +--
lib/crypto/sha256-generic.c | 150 ------------------
lib/crypto/sha256.c | 146 +++++++++++++++--
lib/crypto/sparc/Kconfig | 8 -
lib/crypto/sparc/Makefile | 4 -
lib/crypto/sparc/{sha256.c => sha256.h} | 29 +---
lib/crypto/x86/Kconfig | 7 -
lib/crypto/x86/Makefile | 3 -
lib/crypto/x86/{sha256.c => sha256.h} | 29 +---
29 files changed, 226 insertions(+), 460 deletions(-)
delete mode 100644 include/crypto/internal/sha2.h
rename lib/crypto/arm/{sha256.c => sha256.h} (64%)
rename lib/crypto/arm64/{sha256.c => sha256.h} (67%)
rename arch/mips/cavium-octeon/crypto/octeon-sha256.c => lib/crypto/mips/sha256.h (80%)
rename lib/crypto/powerpc/{sha256.c => sha256.h} (80%)
rename lib/crypto/riscv/{sha256.c => sha256.h} (63%)
rename lib/crypto/s390/{sha256.c => sha256.h} (50%)
delete mode 100644 lib/crypto/sha256-generic.c
delete mode 100644 lib/crypto/sparc/Kconfig
delete mode 100644 lib/crypto/sparc/Makefile
rename lib/crypto/sparc/{sha256.c => sha256.h} (62%)
rename lib/crypto/x86/{sha256.c => sha256.h} (70%)
diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig
index 11f4aa6e80e9b..450e979ef5d93 100644
--- a/arch/mips/cavium-octeon/Kconfig
+++ b/arch/mips/cavium-octeon/Kconfig
@@ -21,16 +21,10 @@ config CAVIUM_OCTEON_CVMSEG_SIZE
local memory; the larger CVMSEG is, the smaller the cache is.
This selects the size of CVMSEG LM, which is in cache blocks. The
legally range is from zero to 54 cache blocks (i.e. CVMSEG LM is
between zero and 6192 bytes).
-config CRYPTO_SHA256_OCTEON
- tristate
- default CRYPTO_LIB_SHA256
- select CRYPTO_ARCH_HAVE_LIB_SHA256
- select CRYPTO_LIB_SHA256_GENERIC
-
endif # CPU_CAVIUM_OCTEON
if CAVIUM_OCTEON_SOC
config CAVIUM_OCTEON_LOCK_L2
diff --git a/arch/mips/cavium-octeon/crypto/Makefile b/arch/mips/cavium-octeon/crypto/Makefile
index 168b19ef7ce89..db428e4b30bce 100644
--- a/arch/mips/cavium-octeon/crypto/Makefile
+++ b/arch/mips/cavium-octeon/crypto/Makefile
@@ -5,6 +5,5 @@
obj-y += octeon-crypto.o
obj-$(CONFIG_CRYPTO_MD5_OCTEON) += octeon-md5.o
obj-$(CONFIG_CRYPTO_SHA1_OCTEON) += octeon-sha1.o
-obj-$(CONFIG_CRYPTO_SHA256_OCTEON) += octeon-sha256.o
diff --git a/include/crypto/internal/sha2.h b/include/crypto/internal/sha2.h
deleted file mode 100644
index 7915a3a46bc86..0000000000000
--- a/include/crypto/internal/sha2.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef _CRYPTO_INTERNAL_SHA2_H
-#define _CRYPTO_INTERNAL_SHA2_H
-
-#include <crypto/sha2.h>
-#include <linux/compiler_attributes.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/unaligned.h>
-
-void sha256_blocks_generic(struct sha256_block_state *state,
- const u8 *data, size_t nblocks);
-void sha256_blocks_arch(struct sha256_block_state *state,
- const u8 *data, size_t nblocks);
-
-static __always_inline void sha256_choose_blocks(
- u32 state[SHA256_STATE_WORDS], const u8 *data, size_t nblocks,
- bool force_generic, bool force_simd)
-{
- if (!IS_ENABLED(CONFIG_CRYPTO_ARCH_HAVE_LIB_SHA256) || force_generic)
- sha256_blocks_generic((struct sha256_block_state *)state, data, nblocks);
- else
- sha256_blocks_arch((struct sha256_block_state *)state, data, nblocks);
-}
-
-static __always_inline void sha256_finup(
- struct crypto_sha256_state *sctx, u8 buf[SHA256_BLOCK_SIZE],
- size_t len, u8 out[SHA256_DIGEST_SIZE], size_t digest_size,
- bool force_generic, bool force_simd)
-{
- const size_t bit_offset = SHA256_BLOCK_SIZE - 8;
- __be64 *bits = (__be64 *)&buf[bit_offset];
- int i;
-
- buf[len++] = 0x80;
- if (len > bit_offset) {
- memset(&buf[len], 0, SHA256_BLOCK_SIZE - len);
- sha256_choose_blocks(sctx->state, buf, 1, force_generic,
- force_simd);
- len = 0;
- }
-
- memset(&buf[len], 0, bit_offset - len);
- *bits = cpu_to_be64(sctx->count << 3);
- sha256_choose_blocks(sctx->state, buf, 1, force_generic, force_simd);
-
- for (i = 0; i < digest_size; i += 4)
- put_unaligned_be32(sctx->state[i / 4], out + i);
-}
-
-#endif /* _CRYPTO_INTERNAL_SHA2_H */
diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig
index 9bd740475a898..3305c69085816 100644
--- a/lib/crypto/Kconfig
+++ b/lib/crypto/Kconfig
@@ -142,24 +142,21 @@ config CRYPTO_LIB_SHA256
help
Enable the SHA-256 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_ARCH_HAVE_LIB_SHA256
+config CRYPTO_LIB_SHA256_ARCH
bool
- help
- Declares whether the architecture provides an arch-specific
- accelerated implementation of the SHA-256 library interface.
-
-config CRYPTO_LIB_SHA256_GENERIC
- tristate
- default CRYPTO_LIB_SHA256 if !CRYPTO_ARCH_HAVE_LIB_SHA256
- help
- This symbol can be selected by arch implementations of the SHA-256
- 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_SHA256.
+ depends on CRYPTO_LIB_SHA256 && !UML
+ default y if ARM && !CPU_V7M
+ default y if ARM64
+ default y if MIPS && CPU_CAVIUM_OCTEON
+ default y if PPC && SPE
+ default y if RISCV && 64BIT && RISCV_ISA_V && TOOLCHAIN_HAS_VECTOR_CRYPTO
+ default y if S390
+ default y if SPARC64
+ default y if X86_64
config CRYPTO_LIB_SHA512
tristate
help
The SHA-384, SHA-512, HMAC-SHA384, and HMAC-SHA512 library functions.
@@ -197,13 +194,10 @@ if RISCV
source "lib/crypto/riscv/Kconfig"
endif
if S390
source "lib/crypto/s390/Kconfig"
endif
-if SPARC
-source "lib/crypto/sparc/Kconfig"
-endif
if X86
source "lib/crypto/x86/Kconfig"
endif
endif
diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile
index 5823137fa5a8c..a887bf103bf05 100644
--- a/lib/crypto/Makefile
+++ b/lib/crypto/Makefile
@@ -64,15 +64,43 @@ libpoly1305-generic-$(CONFIG_ARCH_SUPPORTS_INT128) := poly1305-donna64.o
libpoly1305-generic-y += poly1305-generic.o
obj-$(CONFIG_CRYPTO_LIB_SHA1) += libsha1.o
libsha1-y := sha1.o
-obj-$(CONFIG_CRYPTO_LIB_SHA256) += libsha256.o
-libsha256-y := sha256.o
+################################################################################
-obj-$(CONFIG_CRYPTO_LIB_SHA256_GENERIC) += libsha256-generic.o
-libsha256-generic-y := sha256-generic.o
+obj-$(CONFIG_CRYPTO_LIB_SHA256) += libsha256.o
+libsha256-y := sha256.o
+ifeq ($(CONFIG_CRYPTO_LIB_SHA256_ARCH),y)
+CFLAGS_sha256.o += -I$(src)/$(SRCARCH)
+
+ifeq ($(CONFIG_ARM),y)
+libsha256-y += arm/sha256-ce.o arm/sha256-core.o
+$(obj)/arm/sha256-core.S: $(src)/arm/sha256-armv4.pl
+ $(call cmd,perlasm)
+clean-files += arm/sha256-core.S
+AFLAGS_arm/sha256-core.o += $(aflags-thumb2-y)
+endif
+
+ifeq ($(CONFIG_ARM64),y)
+libsha256-y += arm64/sha256-core.o
+$(obj)/arm64/sha256-core.S: $(src)/arm64/sha2-armv8.pl
+ $(call cmd,perlasm_with_args)
+clean-files += arm64/sha256-core.S
+libsha256-$(CONFIG_KERNEL_MODE_NEON) += arm64/sha256-ce.o
+endif
+
+libsha256-$(CONFIG_PPC) += powerpc/sha256-spe-asm.o
+libsha256-$(CONFIG_RISCV) += riscv/sha256-riscv64-zvknha_or_zvknhb-zvkb.o
+libsha256-$(CONFIG_SPARC) += sparc/sha256_asm.o
+libsha256-$(CONFIG_X86) += x86/sha256-ssse3-asm.o \
+ x86/sha256-avx-asm.o \
+ x86/sha256-avx2-asm.o \
+ x86/sha256-ni-asm.o
+endif # CONFIG_CRYPTO_LIB_SHA256_ARCH
+
+################################################################################
obj-$(CONFIG_CRYPTO_LIB_SHA512) += libsha512.o
libsha512-y := sha512.o
ifeq ($(CONFIG_CRYPTO_LIB_SHA512_ARCH),y)
CFLAGS_sha512.o += -I$(src)/$(SRCARCH)
@@ -98,10 +126,12 @@ libsha512-$(CONFIG_SPARC) += sparc/sha512_asm.o
libsha512-$(CONFIG_X86) += x86/sha512-ssse3-asm.o \
x86/sha512-avx-asm.o \
x86/sha512-avx2-asm.o
endif # CONFIG_CRYPTO_LIB_SHA512_ARCH
+################################################################################
+
obj-$(CONFIG_MPILIB) += mpi/
obj-$(CONFIG_CRYPTO_SELFTESTS_FULL) += simd.o
obj-$(CONFIG_CRYPTO_LIB_SM3) += libsm3.o
@@ -111,7 +141,6 @@ obj-$(CONFIG_ARM) += arm/
obj-$(CONFIG_ARM64) += arm64/
obj-$(CONFIG_MIPS) += mips/
obj-$(CONFIG_PPC) += powerpc/
obj-$(CONFIG_RISCV) += riscv/
obj-$(CONFIG_S390) += s390/
-obj-$(CONFIG_SPARC) += sparc/
obj-$(CONFIG_X86) += x86/
diff --git a/lib/crypto/arm/Kconfig b/lib/crypto/arm/Kconfig
index 9f3ff30f40328..e8444fd0aae30 100644
--- a/lib/crypto/arm/Kconfig
+++ b/lib/crypto/arm/Kconfig
@@ -20,11 +20,5 @@ config CRYPTO_CHACHA20_NEON
config CRYPTO_POLY1305_ARM
tristate
default CRYPTO_LIB_POLY1305
select CRYPTO_ARCH_HAVE_LIB_POLY1305
-
-config CRYPTO_SHA256_ARM
- tristate
- depends on !CPU_V7M
- default CRYPTO_LIB_SHA256
- select CRYPTO_ARCH_HAVE_LIB_SHA256
diff --git a/lib/crypto/arm/Makefile b/lib/crypto/arm/Makefile
index 431f77c3ff6fd..4c042a4c77ed6 100644
--- a/lib/crypto/arm/Makefile
+++ b/lib/crypto/arm/Makefile
@@ -8,25 +8,19 @@ chacha-neon-y := chacha-scalar-core.o chacha-glue.o
chacha-neon-$(CONFIG_KERNEL_MODE_NEON) += chacha-neon-core.o
obj-$(CONFIG_CRYPTO_POLY1305_ARM) += poly1305-arm.o
poly1305-arm-y := poly1305-core.o poly1305-glue.o
-obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o
-sha256-arm-y := sha256.o sha256-core.o
-sha256-arm-$(CONFIG_KERNEL_MODE_NEON) += sha256-ce.o
-
quiet_cmd_perl = PERL $@
cmd_perl = $(PERL) $(<) > $(@)
$(obj)/%-core.S: $(src)/%-armv4.pl
$(call cmd,perl)
-clean-files += poly1305-core.S sha256-core.S
+clean-files += poly1305-core.S
aflags-thumb2-$(CONFIG_THUMB2_KERNEL) := -U__thumb2__ -D__thumb2__=1
# massage the perlasm code a bit so we only get the NEON routine if we need it
poly1305-aflags-$(CONFIG_CPU_V7) := -U__LINUX_ARM_ARCH__ -D__LINUX_ARM_ARCH__=5
poly1305-aflags-$(CONFIG_KERNEL_MODE_NEON) := -U__LINUX_ARM_ARCH__ -D__LINUX_ARM_ARCH__=7
AFLAGS_poly1305-core.o += $(poly1305-aflags-y) $(aflags-thumb2-y)
-
-AFLAGS_sha256-core.o += $(aflags-thumb2-y)
diff --git a/lib/crypto/arm/sha256.c b/lib/crypto/arm/sha256.h
similarity index 64%
rename from lib/crypto/arm/sha256.c
rename to lib/crypto/arm/sha256.h
index 27181be0aa92e..da75cbdc51d41 100644
--- a/lib/crypto/arm/sha256.c
+++ b/lib/crypto/arm/sha256.h
@@ -1,16 +1,13 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* SHA-256 optimized for ARM
*
* Copyright 2025 Google LLC
*/
#include <asm/neon.h>
-#include <crypto/internal/sha2.h>
#include <crypto/internal/simd.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
asmlinkage void sha256_block_data_order(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
asmlinkage void sha256_block_data_order_neon(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
@@ -18,12 +15,12 @@ asmlinkage void sha256_ce_transform(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_ce);
-void sha256_blocks_arch(struct sha256_block_state *state,
- const u8 *data, size_t nblocks)
+static void sha256_blocks(struct sha256_block_state *state,
+ const u8 *data, size_t nblocks)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
static_branch_likely(&have_neon) && crypto_simd_usable()) {
kernel_neon_begin();
if (static_branch_likely(&have_ce))
@@ -33,25 +30,17 @@ void sha256_blocks_arch(struct sha256_block_state *state,
kernel_neon_end();
} else {
sha256_block_data_order(state, data, nblocks);
}
}
-EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-static int __init sha256_arm_mod_init(void)
+#ifdef CONFIG_KERNEL_MODE_NEON
+#define sha256_mod_init_arch sha256_mod_init_arch
+static inline void sha256_mod_init_arch(void)
{
- if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && (elf_hwcap & HWCAP_NEON)) {
+ if (elf_hwcap & HWCAP_NEON) {
static_branch_enable(&have_neon);
if (elf_hwcap2 & HWCAP2_SHA2)
static_branch_enable(&have_ce);
}
- return 0;
}
-subsys_initcall(sha256_arm_mod_init);
-
-static void __exit sha256_arm_mod_exit(void)
-{
-}
-module_exit(sha256_arm_mod_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SHA-256 optimized for ARM");
+#endif /* CONFIG_KERNEL_MODE_NEON */
diff --git a/lib/crypto/arm64/Kconfig b/lib/crypto/arm64/Kconfig
index 49e57bfdb5b52..0b903ef524d85 100644
--- a/lib/crypto/arm64/Kconfig
+++ b/lib/crypto/arm64/Kconfig
@@ -10,10 +10,5 @@ config CRYPTO_CHACHA20_NEON
config CRYPTO_POLY1305_NEON
tristate
depends on KERNEL_MODE_NEON
default CRYPTO_LIB_POLY1305
select CRYPTO_ARCH_HAVE_LIB_POLY1305
-
-config CRYPTO_SHA256_ARM64
- tristate
- default CRYPTO_LIB_SHA256
- select CRYPTO_ARCH_HAVE_LIB_SHA256
diff --git a/lib/crypto/arm64/Makefile b/lib/crypto/arm64/Makefile
index 946c099037117..6207088397a73 100644
--- a/lib/crypto/arm64/Makefile
+++ b/lib/crypto/arm64/Makefile
@@ -6,19 +6,12 @@ chacha-neon-y := chacha-neon-core.o chacha-neon-glue.o
obj-$(CONFIG_CRYPTO_POLY1305_NEON) += poly1305-neon.o
poly1305-neon-y := poly1305-core.o poly1305-glue.o
AFLAGS_poly1305-core.o += -Dpoly1305_init=poly1305_block_init_arch
AFLAGS_poly1305-core.o += -Dpoly1305_emit=poly1305_emit_arch
-obj-$(CONFIG_CRYPTO_SHA256_ARM64) += sha256-arm64.o
-sha256-arm64-y := sha256.o sha256-core.o
-sha256-arm64-$(CONFIG_KERNEL_MODE_NEON) += sha256-ce.o
-
quiet_cmd_perlasm = PERLASM $@
cmd_perlasm = $(PERL) $(<) void $(@)
$(obj)/%-core.S: $(src)/%-armv8.pl
$(call cmd,perlasm)
-$(obj)/sha256-core.S: $(src)/sha2-armv8.pl
- $(call cmd,perlasm)
-
-clean-files += poly1305-core.S sha256-core.S
+clean-files += poly1305-core.S
diff --git a/lib/crypto/arm64/sha256.c b/lib/crypto/arm64/sha256.h
similarity index 67%
rename from lib/crypto/arm64/sha256.c
rename to lib/crypto/arm64/sha256.h
index a5a4982767089..a211966c124a9 100644
--- a/lib/crypto/arm64/sha256.c
+++ b/lib/crypto/arm64/sha256.h
@@ -1,16 +1,14 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* SHA-256 optimized for ARM64
*
* Copyright 2025 Google LLC
*/
#include <asm/neon.h>
-#include <crypto/internal/sha2.h>
#include <crypto/internal/simd.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/cpufeature.h>
asmlinkage void sha256_block_data_order(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
asmlinkage void sha256_block_neon(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
@@ -18,12 +16,12 @@ asmlinkage size_t __sha256_ce_transform(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_neon);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_ce);
-void sha256_blocks_arch(struct sha256_block_state *state,
- const u8 *data, size_t nblocks)
+static void sha256_blocks(struct sha256_block_state *state,
+ const u8 *data, size_t nblocks)
{
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
static_branch_likely(&have_neon) && crypto_simd_usable()) {
if (static_branch_likely(&have_ce)) {
do {
@@ -43,26 +41,17 @@ void sha256_blocks_arch(struct sha256_block_state *state,
}
} else {
sha256_block_data_order(state, data, nblocks);
}
}
-EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-static int __init sha256_arm64_mod_init(void)
+#ifdef CONFIG_KERNEL_MODE_NEON
+#define sha256_mod_init_arch sha256_mod_init_arch
+static inline void sha256_mod_init_arch(void)
{
- if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) &&
- cpu_have_named_feature(ASIMD)) {
+ if (cpu_have_named_feature(ASIMD)) {
static_branch_enable(&have_neon);
if (cpu_have_named_feature(SHA2))
static_branch_enable(&have_ce);
}
- return 0;
}
-subsys_initcall(sha256_arm64_mod_init);
-
-static void __exit sha256_arm64_mod_exit(void)
-{
-}
-module_exit(sha256_arm64_mod_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SHA-256 optimized for ARM64");
+#endif /* CONFIG_KERNEL_MODE_NEON */
diff --git a/arch/mips/cavium-octeon/crypto/octeon-sha256.c b/lib/crypto/mips/sha256.h
similarity index 80%
rename from arch/mips/cavium-octeon/crypto/octeon-sha256.c
rename to lib/crypto/mips/sha256.h
index c7c67bdc2bd06..ccccfd131634b 100644
--- a/arch/mips/cavium-octeon/crypto/octeon-sha256.c
+++ b/lib/crypto/mips/sha256.h
@@ -1,6 +1,6 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* SHA-256 Secure Hash Algorithm.
*
* Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>.
*
@@ -12,20 +12,17 @@
* SHA224 Support Copyright 2007 Intel Corporation <jonathan.lynch@intel.com>
*/
#include <asm/octeon/crypto.h>
#include <asm/octeon/octeon.h>
-#include <crypto/internal/sha2.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
/*
* We pass everything as 64-bit. OCTEON can handle misaligned data.
*/
-void sha256_blocks_arch(struct sha256_block_state *state,
- const u8 *data, size_t nblocks)
+static void sha256_blocks(struct sha256_block_state *state,
+ const u8 *data, size_t nblocks)
{
struct octeon_cop2_state cop2_state;
u64 *state64 = (u64 *)state;
unsigned long flags;
@@ -57,10 +54,5 @@ void sha256_blocks_arch(struct sha256_block_state *state,
state64[1] = read_octeon_64bit_hash_dword(1);
state64[2] = read_octeon_64bit_hash_dword(2);
state64[3] = read_octeon_64bit_hash_dword(3);
octeon_crypto_disable(&cop2_state, flags);
}
-EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SHA-256 Secure Hash Algorithm (OCTEON)");
-MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
diff --git a/lib/crypto/powerpc/Kconfig b/lib/crypto/powerpc/Kconfig
index 3f9e1bbd9905b..2eaeb7665a6a0 100644
--- a/lib/crypto/powerpc/Kconfig
+++ b/lib/crypto/powerpc/Kconfig
@@ -12,11 +12,5 @@ config CRYPTO_POLY1305_P10
depends on PPC64 && CPU_LITTLE_ENDIAN && VSX
depends on BROKEN # Needs to be fixed to work in softirq context
default CRYPTO_LIB_POLY1305
select CRYPTO_ARCH_HAVE_LIB_POLY1305
select CRYPTO_LIB_POLY1305_GENERIC
-
-config CRYPTO_SHA256_PPC_SPE
- tristate
- depends on SPE
- default CRYPTO_LIB_SHA256
- select CRYPTO_ARCH_HAVE_LIB_SHA256
diff --git a/lib/crypto/powerpc/Makefile b/lib/crypto/powerpc/Makefile
index 27f231f8e334a..5709ae14258a0 100644
--- a/lib/crypto/powerpc/Makefile
+++ b/lib/crypto/powerpc/Makefile
@@ -3,8 +3,5 @@
obj-$(CONFIG_CRYPTO_CHACHA20_P10) += chacha-p10-crypto.o
chacha-p10-crypto-y := chacha-p10-glue.o chacha-p10le-8x.o
obj-$(CONFIG_CRYPTO_POLY1305_P10) += poly1305-p10-crypto.o
poly1305-p10-crypto-y := poly1305-p10-glue.o poly1305-p10le_64.o
-
-obj-$(CONFIG_CRYPTO_SHA256_PPC_SPE) += sha256-ppc-spe.o
-sha256-ppc-spe-y := sha256.o sha256-spe-asm.o
diff --git a/lib/crypto/powerpc/sha256.c b/lib/crypto/powerpc/sha256.h
similarity index 80%
rename from lib/crypto/powerpc/sha256.c
rename to lib/crypto/powerpc/sha256.h
index 437e587b05754..d923698de5745 100644
--- a/lib/crypto/powerpc/sha256.c
+++ b/lib/crypto/powerpc/sha256.h
@@ -1,19 +1,16 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* SHA-256 Secure Hash Algorithm, SPE optimized
*
* Based on generic implementation. The assembler module takes care
* about the SPE registers so it can run from interrupt context.
*
* Copyright (c) 2015 Markus Stockhausen <stockhausen@collogia.de>
*/
#include <asm/switch_to.h>
-#include <crypto/internal/sha2.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/preempt.h>
/*
* MAX_BYTES defines the number of bytes that are allowed to be processed
* between preempt_disable() and preempt_enable(). SHA256 takes ~2,000
@@ -40,12 +37,12 @@ static void spe_end(void)
disable_kernel_spe();
/* reenable preemption */
preempt_enable();
}
-void sha256_blocks_arch(struct sha256_block_state *state,
- const u8 *data, size_t nblocks)
+static void sha256_blocks(struct sha256_block_state *state,
+ const u8 *data, size_t nblocks)
{
do {
/* cut input data into smaller blocks */
u32 unit = min_t(size_t, nblocks,
MAX_BYTES / SHA256_BLOCK_SIZE);
@@ -56,9 +53,5 @@ void sha256_blocks_arch(struct sha256_block_state *state,
data += unit * SHA256_BLOCK_SIZE;
nblocks -= unit;
} while (nblocks);
}
-EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SHA-256 Secure Hash Algorithm, SPE optimized");
diff --git a/lib/crypto/riscv/Kconfig b/lib/crypto/riscv/Kconfig
index c100571feb7e8..bc7a43f33eb3a 100644
--- a/lib/crypto/riscv/Kconfig
+++ b/lib/crypto/riscv/Kconfig
@@ -4,12 +4,5 @@ config CRYPTO_CHACHA_RISCV64
tristate
depends on 64BIT && RISCV_ISA_V && TOOLCHAIN_HAS_VECTOR_CRYPTO
default CRYPTO_LIB_CHACHA
select CRYPTO_ARCH_HAVE_LIB_CHACHA
select CRYPTO_LIB_CHACHA_GENERIC
-
-config CRYPTO_SHA256_RISCV64
- tristate
- depends on 64BIT && RISCV_ISA_V && TOOLCHAIN_HAS_VECTOR_CRYPTO
- default CRYPTO_LIB_SHA256
- select CRYPTO_ARCH_HAVE_LIB_SHA256
- select CRYPTO_LIB_SHA256_GENERIC
diff --git a/lib/crypto/riscv/Makefile b/lib/crypto/riscv/Makefile
index b7cb877a2c07e..e27b78f317fc8 100644
--- a/lib/crypto/riscv/Makefile
+++ b/lib/crypto/riscv/Makefile
@@ -1,7 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_CRYPTO_CHACHA_RISCV64) += chacha-riscv64.o
chacha-riscv64-y := chacha-riscv64-glue.o chacha-riscv64-zvkb.o
-
-obj-$(CONFIG_CRYPTO_SHA256_RISCV64) += sha256-riscv64.o
-sha256-riscv64-y := sha256.o sha256-riscv64-zvknha_or_zvknhb-zvkb.o
diff --git a/lib/crypto/riscv/sha256.c b/lib/crypto/riscv/sha256.h
similarity index 63%
rename from lib/crypto/riscv/sha256.c
rename to lib/crypto/riscv/sha256.h
index 01004cb9c6e9e..c0f79c18f1199 100644
--- a/lib/crypto/riscv/sha256.c
+++ b/lib/crypto/riscv/sha256.h
@@ -1,6 +1,6 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* SHA-256 (RISC-V accelerated)
*
* Copyright (C) 2022 VRULL GmbH
* Author: Heiko Stuebner <heiko.stuebner@vrull.eu>
@@ -8,49 +8,35 @@
* Copyright (C) 2023 SiFive, Inc.
* Author: Jerry Shih <jerry.shih@sifive.com>
*/
#include <asm/vector.h>
-#include <crypto/internal/sha2.h>
#include <crypto/internal/simd.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
asmlinkage void
sha256_transform_zvknha_or_zvknhb_zvkb(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_extensions);
-void sha256_blocks_arch(struct sha256_block_state *state,
- const u8 *data, size_t nblocks)
+static void sha256_blocks(struct sha256_block_state *state,
+ const u8 *data, size_t nblocks)
{
if (static_branch_likely(&have_extensions) && crypto_simd_usable()) {
kernel_vector_begin();
sha256_transform_zvknha_or_zvknhb_zvkb(state, data, nblocks);
kernel_vector_end();
} else {
sha256_blocks_generic(state, data, nblocks);
}
}
-EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-static int __init riscv64_sha256_mod_init(void)
+#define sha256_mod_init_arch sha256_mod_init_arch
+static inline void sha256_mod_init_arch(void)
{
/* Both zvknha and zvknhb provide the SHA-256 instructions. */
if ((riscv_isa_extension_available(NULL, ZVKNHA) ||
riscv_isa_extension_available(NULL, ZVKNHB)) &&
riscv_isa_extension_available(NULL, ZVKB) &&
riscv_vector_vlen() >= 128)
static_branch_enable(&have_extensions);
- return 0;
}
-subsys_initcall(riscv64_sha256_mod_init);
-
-static void __exit riscv64_sha256_mod_exit(void)
-{
-}
-module_exit(riscv64_sha256_mod_exit);
-
-MODULE_DESCRIPTION("SHA-256 (RISC-V accelerated)");
-MODULE_AUTHOR("Heiko Stuebner <heiko.stuebner@vrull.eu>");
-MODULE_LICENSE("GPL");
diff --git a/lib/crypto/s390/Kconfig b/lib/crypto/s390/Kconfig
index e3f855ef43934..069b355fe51aa 100644
--- a/lib/crypto/s390/Kconfig
+++ b/lib/crypto/s390/Kconfig
@@ -3,11 +3,5 @@
config CRYPTO_CHACHA_S390
tristate
default CRYPTO_LIB_CHACHA
select CRYPTO_LIB_CHACHA_GENERIC
select CRYPTO_ARCH_HAVE_LIB_CHACHA
-
-config CRYPTO_SHA256_S390
- tristate
- default CRYPTO_LIB_SHA256
- select CRYPTO_ARCH_HAVE_LIB_SHA256
- select CRYPTO_LIB_SHA256_GENERIC
diff --git a/lib/crypto/s390/Makefile b/lib/crypto/s390/Makefile
index 5df30f1e79307..06c2cf77178ef 100644
--- a/lib/crypto/s390/Makefile
+++ b/lib/crypto/s390/Makefile
@@ -1,7 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_CRYPTO_CHACHA_S390) += chacha_s390.o
chacha_s390-y := chacha-glue.o chacha-s390.o
-
-obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256-s390.o
-sha256-s390-y := sha256.o
diff --git a/lib/crypto/s390/sha256.c b/lib/crypto/s390/sha256.h
similarity index 50%
rename from lib/crypto/s390/sha256.c
rename to lib/crypto/s390/sha256.h
index 6ebfd35a5d44c..70a81cbc06b2c 100644
--- a/lib/crypto/s390/sha256.c
+++ b/lib/crypto/s390/sha256.h
@@ -1,41 +1,28 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* SHA-256 optimized using the CP Assist for Cryptographic Functions (CPACF)
*
* Copyright 2025 Google LLC
*/
#include <asm/cpacf.h>
-#include <crypto/internal/sha2.h>
#include <linux/cpufeature.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_cpacf_sha256);
-void sha256_blocks_arch(struct sha256_block_state *state,
- const u8 *data, size_t nblocks)
+static void sha256_blocks(struct sha256_block_state *state,
+ const u8 *data, size_t nblocks)
{
if (static_branch_likely(&have_cpacf_sha256))
cpacf_kimd(CPACF_KIMD_SHA_256, state, data,
nblocks * SHA256_BLOCK_SIZE);
else
sha256_blocks_generic(state, data, nblocks);
}
-EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-static int __init sha256_s390_mod_init(void)
+#define sha256_mod_init_arch sha256_mod_init_arch
+static inline void sha256_mod_init_arch(void)
{
if (cpu_have_feature(S390_CPU_FEATURE_MSA) &&
cpacf_query_func(CPACF_KIMD, CPACF_KIMD_SHA_256))
static_branch_enable(&have_cpacf_sha256);
- return 0;
}
-subsys_initcall(sha256_s390_mod_init);
-
-static void __exit sha256_s390_mod_exit(void)
-{
-}
-module_exit(sha256_s390_mod_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SHA-256 using the CP Assist for Cryptographic Functions (CPACF)");
diff --git a/lib/crypto/sha256-generic.c b/lib/crypto/sha256-generic.c
deleted file mode 100644
index 99f904033c261..0000000000000
--- a/lib/crypto/sha256-generic.c
+++ /dev/null
@@ -1,150 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SHA-256, as specified in
- * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf
- *
- * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>.
- *
- * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
- * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
- * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
- * Copyright (c) 2014 Red Hat Inc.
- */
-
-#include <crypto/internal/sha2.h>
-#include <linux/export.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/unaligned.h>
-
-static const u32 SHA256_K[] = {
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
- 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
- 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
- 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
- 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
- 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
-};
-
-static inline u32 Ch(u32 x, u32 y, u32 z)
-{
- return z ^ (x & (y ^ z));
-}
-
-static inline u32 Maj(u32 x, u32 y, u32 z)
-{
- return (x & y) | (z & (x | y));
-}
-
-#define e0(x) (ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22))
-#define e1(x) (ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25))
-#define s0(x) (ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3))
-#define s1(x) (ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10))
-
-static inline void LOAD_OP(int I, u32 *W, const u8 *input)
-{
- W[I] = get_unaligned_be32((__u32 *)input + I);
-}
-
-static inline void BLEND_OP(int I, u32 *W)
-{
- W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
-}
-
-#define SHA256_ROUND(i, a, b, c, d, e, f, g, h) do { \
- u32 t1, t2; \
- t1 = h + e1(e) + Ch(e, f, g) + SHA256_K[i] + W[i]; \
- t2 = e0(a) + Maj(a, b, c); \
- d += t1; \
- h = t1 + t2; \
-} while (0)
-
-static void sha256_block_generic(struct sha256_block_state *state,
- const u8 *input, u32 W[64])
-{
- u32 a, b, c, d, e, f, g, h;
- int i;
-
- /* load the input */
- for (i = 0; i < 16; i += 8) {
- LOAD_OP(i + 0, W, input);
- LOAD_OP(i + 1, W, input);
- LOAD_OP(i + 2, W, input);
- LOAD_OP(i + 3, W, input);
- LOAD_OP(i + 4, W, input);
- LOAD_OP(i + 5, W, input);
- LOAD_OP(i + 6, W, input);
- LOAD_OP(i + 7, W, input);
- }
-
- /* now blend */
- for (i = 16; i < 64; i += 8) {
- BLEND_OP(i + 0, W);
- BLEND_OP(i + 1, W);
- BLEND_OP(i + 2, W);
- BLEND_OP(i + 3, W);
- BLEND_OP(i + 4, W);
- BLEND_OP(i + 5, W);
- BLEND_OP(i + 6, W);
- BLEND_OP(i + 7, W);
- }
-
- /* load the state into our registers */
- a = state->h[0];
- b = state->h[1];
- c = state->h[2];
- d = state->h[3];
- e = state->h[4];
- f = state->h[5];
- g = state->h[6];
- h = state->h[7];
-
- /* now iterate */
- for (i = 0; i < 64; i += 8) {
- SHA256_ROUND(i + 0, a, b, c, d, e, f, g, h);
- SHA256_ROUND(i + 1, h, a, b, c, d, e, f, g);
- SHA256_ROUND(i + 2, g, h, a, b, c, d, e, f);
- SHA256_ROUND(i + 3, f, g, h, a, b, c, d, e);
- SHA256_ROUND(i + 4, e, f, g, h, a, b, c, d);
- SHA256_ROUND(i + 5, d, e, f, g, h, a, b, c);
- SHA256_ROUND(i + 6, c, d, e, f, g, h, a, b);
- SHA256_ROUND(i + 7, b, c, d, e, f, g, h, a);
- }
-
- state->h[0] += a;
- state->h[1] += b;
- state->h[2] += c;
- state->h[3] += d;
- state->h[4] += e;
- state->h[5] += f;
- state->h[6] += g;
- state->h[7] += h;
-}
-
-void sha256_blocks_generic(struct sha256_block_state *state,
- const u8 *data, size_t nblocks)
-{
- u32 W[64];
-
- do {
- sha256_block_generic(state, data, W);
- data += SHA256_BLOCK_SIZE;
- } while (--nblocks);
-
- memzero_explicit(W, sizeof(W));
-}
-EXPORT_SYMBOL_GPL(sha256_blocks_generic);
-
-MODULE_DESCRIPTION("SHA-256 Algorithm (generic implementation)");
-MODULE_LICENSE("GPL");
diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
index 12b4b59052c4a..68936d5cd7745 100644
--- a/lib/crypto/sha256.c
+++ b/lib/crypto/sha256.c
@@ -4,19 +4,21 @@
*
* Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
* Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* Copyright (c) 2014 Red Hat Inc.
+ * Copyright 2025 Google LLC
*/
#include <crypto/hmac.h>
#include <crypto/internal/blockhash.h>
-#include <crypto/internal/sha2.h>
+#include <crypto/sha2.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
+#include <linux/unaligned.h>
#include <linux/wordpart.h>
static const struct sha256_block_state sha224_iv = {
.h = {
SHA224_H0, SHA224_H1, SHA224_H2, SHA224_H3,
@@ -29,30 +31,132 @@ static const struct sha256_block_state sha256_iv = {
SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3,
SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7,
},
};
-/*
- * If __DISABLE_EXPORTS is defined, then this file is being compiled for a
- * pre-boot environment. In that case, ignore the kconfig options, pull the
- * generic code into the same translation unit, and use that only.
- */
-#ifdef __DISABLE_EXPORTS
-#include "sha256-generic.c"
-#endif
+static const u32 sha256_K[64] = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
+ 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
+ 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
+ 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
+ 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
+ 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
+};
+
+#define Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define Maj(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
+#define e0(x) (ror32((x), 2) ^ ror32((x), 13) ^ ror32((x), 22))
+#define e1(x) (ror32((x), 6) ^ ror32((x), 11) ^ ror32((x), 25))
+#define s0(x) (ror32((x), 7) ^ ror32((x), 18) ^ ((x) >> 3))
+#define s1(x) (ror32((x), 17) ^ ror32((x), 19) ^ ((x) >> 10))
+
+static inline void LOAD_OP(int I, u32 *W, const u8 *input)
+{
+ W[I] = get_unaligned_be32((__u32 *)input + I);
+}
+
+static inline void BLEND_OP(int I, u32 *W)
+{
+ W[I] = s1(W[I - 2]) + W[I - 7] + s0(W[I - 15]) + W[I - 16];
+}
-static inline bool sha256_purgatory(void)
+#define SHA256_ROUND(i, a, b, c, d, e, f, g, h) \
+ do { \
+ u32 t1, t2; \
+ t1 = h + e1(e) + Ch(e, f, g) + sha256_K[i] + W[i]; \
+ t2 = e0(a) + Maj(a, b, c); \
+ d += t1; \
+ h = t1 + t2; \
+ } while (0)
+
+static void sha256_block_generic(struct sha256_block_state *state,
+ const u8 *input, u32 W[64])
{
- return __is_defined(__DISABLE_EXPORTS);
+ u32 a, b, c, d, e, f, g, h;
+ int i;
+
+ /* load the input */
+ for (i = 0; i < 16; i += 8) {
+ LOAD_OP(i + 0, W, input);
+ LOAD_OP(i + 1, W, input);
+ LOAD_OP(i + 2, W, input);
+ LOAD_OP(i + 3, W, input);
+ LOAD_OP(i + 4, W, input);
+ LOAD_OP(i + 5, W, input);
+ LOAD_OP(i + 6, W, input);
+ LOAD_OP(i + 7, W, input);
+ }
+
+ /* now blend */
+ for (i = 16; i < 64; i += 8) {
+ BLEND_OP(i + 0, W);
+ BLEND_OP(i + 1, W);
+ BLEND_OP(i + 2, W);
+ BLEND_OP(i + 3, W);
+ BLEND_OP(i + 4, W);
+ BLEND_OP(i + 5, W);
+ BLEND_OP(i + 6, W);
+ BLEND_OP(i + 7, W);
+ }
+
+ /* load the state into our registers */
+ a = state->h[0];
+ b = state->h[1];
+ c = state->h[2];
+ d = state->h[3];
+ e = state->h[4];
+ f = state->h[5];
+ g = state->h[6];
+ h = state->h[7];
+
+ /* now iterate */
+ for (i = 0; i < 64; i += 8) {
+ SHA256_ROUND(i + 0, a, b, c, d, e, f, g, h);
+ SHA256_ROUND(i + 1, h, a, b, c, d, e, f, g);
+ SHA256_ROUND(i + 2, g, h, a, b, c, d, e, f);
+ SHA256_ROUND(i + 3, f, g, h, a, b, c, d, e);
+ SHA256_ROUND(i + 4, e, f, g, h, a, b, c, d);
+ SHA256_ROUND(i + 5, d, e, f, g, h, a, b, c);
+ SHA256_ROUND(i + 6, c, d, e, f, g, h, a, b);
+ SHA256_ROUND(i + 7, b, c, d, e, f, g, h, a);
+ }
+
+ state->h[0] += a;
+ state->h[1] += b;
+ state->h[2] += c;
+ state->h[3] += d;
+ state->h[4] += e;
+ state->h[5] += f;
+ state->h[6] += g;
+ state->h[7] += h;
}
-static inline void sha256_blocks(struct sha256_block_state *state,
- const u8 *data, size_t nblocks)
+static void __maybe_unused
+sha256_blocks_generic(struct sha256_block_state *state,
+ const u8 *data, size_t nblocks)
{
- sha256_choose_blocks(state->h, data, nblocks, sha256_purgatory(), false);
+ u32 W[64];
+
+ do {
+ sha256_block_generic(state, data, W);
+ data += SHA256_BLOCK_SIZE;
+ } while (--nblocks);
+
+ memzero_explicit(W, sizeof(W));
}
+#if defined(CONFIG_CRYPTO_LIB_SHA256_ARCH) && !defined(__DISABLE_EXPORTS)
+#include "sha256.h" /* $(SRCARCH)/sha256.h */
+#else
+#define sha256_blocks sha256_blocks_generic
+#endif
+
static void __sha256_init(struct __sha256_ctx *ctx,
const struct sha256_block_state *iv,
u64 initial_bytecount)
{
ctx->state = *iv;
@@ -271,7 +375,21 @@ void hmac_sha256_usingrawkey(const u8 *raw_key, size_t raw_key_len,
memzero_explicit(&key, sizeof(key));
}
EXPORT_SYMBOL_GPL(hmac_sha256_usingrawkey);
#endif /* !__DISABLE_EXPORTS */
+#ifdef sha256_mod_init_arch
+static int __init sha256_mod_init(void)
+{
+ sha256_mod_init_arch();
+ return 0;
+}
+subsys_initcall(sha256_mod_init);
+
+static void __exit sha256_mod_exit(void)
+{
+}
+module_exit(sha256_mod_exit);
+#endif
+
MODULE_DESCRIPTION("SHA-224, SHA-256, HMAC-SHA224, and HMAC-SHA256 library functions");
MODULE_LICENSE("GPL");
diff --git a/lib/crypto/sparc/Kconfig b/lib/crypto/sparc/Kconfig
deleted file mode 100644
index e5c3e4d3dba62..0000000000000
--- a/lib/crypto/sparc/Kconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-config CRYPTO_SHA256_SPARC64
- tristate
- depends on SPARC64
- default CRYPTO_LIB_SHA256
- select CRYPTO_ARCH_HAVE_LIB_SHA256
- select CRYPTO_LIB_SHA256_GENERIC
diff --git a/lib/crypto/sparc/Makefile b/lib/crypto/sparc/Makefile
deleted file mode 100644
index 75ee244ad6f79..0000000000000
--- a/lib/crypto/sparc/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-
-obj-$(CONFIG_CRYPTO_SHA256_SPARC64) += sha256-sparc64.o
-sha256-sparc64-y := sha256.o sha256_asm.o
diff --git a/lib/crypto/sparc/sha256.c b/lib/crypto/sparc/sha256.h
similarity index 62%
rename from lib/crypto/sparc/sha256.c
rename to lib/crypto/sparc/sha256.h
index f41c109c1c18d..1d10108eb1954 100644
--- a/lib/crypto/sparc/sha256.c
+++ b/lib/crypto/sparc/sha256.h
@@ -1,58 +1,43 @@
-// SPDX-License-Identifier: GPL-2.0-only
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* SHA-256 accelerated using the sparc64 sha256 opcodes
*
* Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
* Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
* Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
* SHA224 Support Copyright 2007 Intel Corporation <jonathan.lynch@intel.com>
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
#include <asm/elf.h>
#include <asm/opcodes.h>
#include <asm/pstate.h>
-#include <crypto/internal/sha2.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_sha256_opcodes);
asmlinkage void sha256_sparc64_transform(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
-void sha256_blocks_arch(struct sha256_block_state *state,
- const u8 *data, size_t nblocks)
+static void sha256_blocks(struct sha256_block_state *state,
+ const u8 *data, size_t nblocks)
{
if (static_branch_likely(&have_sha256_opcodes))
sha256_sparc64_transform(state, data, nblocks);
else
sha256_blocks_generic(state, data, nblocks);
}
-EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-static int __init sha256_sparc64_mod_init(void)
+#define sha256_mod_init_arch sha256_mod_init_arch
+static inline void sha256_mod_init_arch(void)
{
unsigned long cfr;
if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
- return 0;
+ return;
__asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
if (!(cfr & CFR_SHA256))
- return 0;
+ return;
static_branch_enable(&have_sha256_opcodes);
pr_info("Using sparc64 sha256 opcode optimized SHA-256/SHA-224 implementation\n");
- return 0;
}
-subsys_initcall(sha256_sparc64_mod_init);
-
-static void __exit sha256_sparc64_mod_exit(void)
-{
-}
-module_exit(sha256_sparc64_mod_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SHA-256 accelerated using the sparc64 sha256 opcodes");
diff --git a/lib/crypto/x86/Kconfig b/lib/crypto/x86/Kconfig
index e344579db3d85..546fe2afe0b51 100644
--- a/lib/crypto/x86/Kconfig
+++ b/lib/crypto/x86/Kconfig
@@ -22,12 +22,5 @@ config CRYPTO_CHACHA20_X86_64
config CRYPTO_POLY1305_X86_64
tristate
depends on 64BIT
default CRYPTO_LIB_POLY1305
select CRYPTO_ARCH_HAVE_LIB_POLY1305
-
-config CRYPTO_SHA256_X86_64
- tristate
- depends on 64BIT
- default CRYPTO_LIB_SHA256
- select CRYPTO_ARCH_HAVE_LIB_SHA256
- select CRYPTO_LIB_SHA256_GENERIC
diff --git a/lib/crypto/x86/Makefile b/lib/crypto/x86/Makefile
index abceca3d31c01..c2ff8c5f1046e 100644
--- a/lib/crypto/x86/Makefile
+++ b/lib/crypto/x86/Makefile
@@ -8,13 +8,10 @@ chacha-x86_64-y := chacha-avx2-x86_64.o chacha-ssse3-x86_64.o chacha-avx512vl-x8
obj-$(CONFIG_CRYPTO_POLY1305_X86_64) += poly1305-x86_64.o
poly1305-x86_64-y := poly1305-x86_64-cryptogams.o poly1305_glue.o
targets += poly1305-x86_64-cryptogams.S
-obj-$(CONFIG_CRYPTO_SHA256_X86_64) += sha256-x86_64.o
-sha256-x86_64-y := sha256.o sha256-ssse3-asm.o sha256-avx-asm.o sha256-avx2-asm.o sha256-ni-asm.o
-
quiet_cmd_perlasm = PERLASM $@
cmd_perlasm = $(PERL) $< > $@
$(obj)/%.S: $(src)/%.pl FORCE
$(call if_changed,perlasm)
diff --git a/lib/crypto/x86/sha256.c b/lib/crypto/x86/sha256.h
similarity index 70%
rename from lib/crypto/x86/sha256.c
rename to lib/crypto/x86/sha256.h
index 9ee38d2b3d572..3b5456c222ba6 100644
--- a/lib/crypto/x86/sha256.c
+++ b/lib/crypto/x86/sha256.h
@@ -1,16 +1,13 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* SHA-256 optimized for x86_64
*
* Copyright 2025 Google LLC
*/
#include <asm/fpu/api.h>
-#include <crypto/internal/sha2.h>
#include <crypto/internal/simd.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/static_call.h>
asmlinkage void sha256_transform_ssse3(struct sha256_block_state *state,
const u8 *data, size_t nblocks);
asmlinkage void sha256_transform_avx(struct sha256_block_state *state,
@@ -22,47 +19,37 @@ asmlinkage void sha256_ni_transform(struct sha256_block_state *state,
static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_sha256_x86);
DEFINE_STATIC_CALL(sha256_blocks_x86, sha256_transform_ssse3);
-void sha256_blocks_arch(struct sha256_block_state *state,
- const u8 *data, size_t nblocks)
+static void sha256_blocks(struct sha256_block_state *state,
+ const u8 *data, size_t nblocks)
{
if (static_branch_likely(&have_sha256_x86) && crypto_simd_usable()) {
kernel_fpu_begin();
static_call(sha256_blocks_x86)(state, data, nblocks);
kernel_fpu_end();
} else {
sha256_blocks_generic(state, data, nblocks);
}
}
-EXPORT_SYMBOL_GPL(sha256_blocks_arch);
-static int __init sha256_x86_mod_init(void)
+#define sha256_mod_init_arch sha256_mod_init_arch
+static inline void sha256_mod_init_arch(void)
{
if (boot_cpu_has(X86_FEATURE_SHA_NI)) {
static_call_update(sha256_blocks_x86, sha256_ni_transform);
- } else if (cpu_has_xfeatures(XFEATURE_MASK_SSE |
- XFEATURE_MASK_YMM, NULL) &&
+ } else if (cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM,
+ NULL) &&
boot_cpu_has(X86_FEATURE_AVX)) {
if (boot_cpu_has(X86_FEATURE_AVX2) &&
boot_cpu_has(X86_FEATURE_BMI2))
static_call_update(sha256_blocks_x86,
sha256_transform_rorx);
else
static_call_update(sha256_blocks_x86,
sha256_transform_avx);
} else if (!boot_cpu_has(X86_FEATURE_SSSE3)) {
- return 0;
+ return;
}
static_branch_enable(&have_sha256_x86);
- return 0;
}
-subsys_initcall(sha256_x86_mod_init);
-
-static void __exit sha256_x86_mod_exit(void)
-{
-}
-module_exit(sha256_x86_mod_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SHA-256 optimized for x86_64");
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 13/14] lib/crypto: sha256: Sync sha256_update() with sha512_update()
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (11 preceding siblings ...)
2025-06-30 16:06 ` [PATCH v2 12/14] lib/crypto: sha256: Consolidate into single module Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-06-30 16:06 ` [PATCH v2 14/14] lib/crypto: sha256: Document the SHA-224 and SHA-256 API Eric Biggers
` (2 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
The BLOCK_HASH_UPDATE_BLOCKS macro is difficult to read. For now, let's
just write the update explicitly in the straightforward way, mirroring
sha512_update(). It's possible that we'll bring back a macro for this
later, but it needs to be properly justified and hopefully a bit more
readable.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
lib/crypto/sha256.c | 28 +++++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
index 68936d5cd7745..808438d4f4278 100644
--- a/lib/crypto/sha256.c
+++ b/lib/crypto/sha256.c
@@ -8,11 +8,10 @@
* Copyright (c) 2014 Red Hat Inc.
* Copyright 2025 Google LLC
*/
#include <crypto/hmac.h>
-#include <crypto/internal/blockhash.h>
#include <crypto/sha2.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
@@ -178,12 +177,35 @@ EXPORT_SYMBOL_GPL(sha256_init);
void __sha256_update(struct __sha256_ctx *ctx, const u8 *data, size_t len)
{
size_t partial = ctx->bytecount % SHA256_BLOCK_SIZE;
ctx->bytecount += len;
- BLOCK_HASH_UPDATE_BLOCKS(sha256_blocks, &ctx->state, data, len,
- SHA256_BLOCK_SIZE, ctx->buf, partial);
+
+ if (partial + len >= SHA256_BLOCK_SIZE) {
+ size_t nblocks;
+
+ if (partial) {
+ size_t l = SHA256_BLOCK_SIZE - partial;
+
+ memcpy(&ctx->buf[partial], data, l);
+ data += l;
+ len -= l;
+
+ sha256_blocks(&ctx->state, ctx->buf, 1);
+ }
+
+ nblocks = len / SHA256_BLOCK_SIZE;
+ len %= SHA256_BLOCK_SIZE;
+
+ if (nblocks) {
+ sha256_blocks(&ctx->state, data, nblocks);
+ data += nblocks * SHA256_BLOCK_SIZE;
+ }
+ partial = 0;
+ }
+ if (len)
+ memcpy(&ctx->buf[partial], data, len);
}
EXPORT_SYMBOL(__sha256_update);
static void __sha256_final(struct __sha256_ctx *ctx,
u8 *out, size_t digest_size)
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v2 14/14] lib/crypto: sha256: Document the SHA-224 and SHA-256 API
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (12 preceding siblings ...)
2025-06-30 16:06 ` [PATCH v2 13/14] lib/crypto: sha256: Sync sha256_update() with sha512_update() Eric Biggers
@ 2025-06-30 16:06 ` Eric Biggers
2025-07-03 17:38 ` [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
2025-07-04 13:26 ` Ard Biesheuvel
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-06-30 16:06 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld, Eric Biggers
Add kerneldoc comments, consistent with the kerneldoc comments of the
SHA-384 and SHA-512 API.
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
include/crypto/sha2.h | 76 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/include/crypto/sha2.h b/include/crypto/sha2.h
index 2e3fc2cf4aa0d..e0a08f6addd00 100644
--- a/include/crypto/sha2.h
+++ b/include/crypto/sha2.h
@@ -153,17 +153,55 @@ void __hmac_sha256_init(struct __hmac_sha256_ctx *ctx,
*/
struct sha224_ctx {
struct __sha256_ctx ctx;
};
+/**
+ * sha224_init() - Initialize a SHA-224 context for a new message
+ * @ctx: the context to initialize
+ *
+ * If you don't need incremental computation, consider sha224() instead.
+ *
+ * Context: Any context.
+ */
void sha224_init(struct sha224_ctx *ctx);
+
+/**
+ * sha224_update() - Update a SHA-224 context with message data
+ * @ctx: the context to update; must have been initialized
+ * @data: the message data
+ * @len: the data length in bytes
+ *
+ * This can be called any number of times.
+ *
+ * Context: Any context.
+ */
static inline void sha224_update(struct sha224_ctx *ctx,
const u8 *data, size_t len)
{
__sha256_update(&ctx->ctx, data, len);
}
+
+/**
+ * sha224_final() - Finish computing a SHA-224 message digest
+ * @ctx: the context to finalize; must have been initialized
+ * @out: (output) the resulting SHA-224 message digest
+ *
+ * After finishing, this zeroizes @ctx. So the caller does not need to do it.
+ *
+ * Context: Any context.
+ */
void sha224_final(struct sha224_ctx *ctx, u8 out[SHA224_DIGEST_SIZE]);
+
+/**
+ * sha224() - Compute SHA-224 message digest in one shot
+ * @data: the message data
+ * @len: the data length in bytes
+ * @out: (output) the resulting SHA-224 message digest
+ *
+ * Context: Any context.
+ */
void sha224(const u8 *data, size_t len, u8 out[SHA224_DIGEST_SIZE]);
/**
* struct hmac_sha224_key - Prepared key for HMAC-SHA224
* @key: private
@@ -273,17 +311,55 @@ void hmac_sha224_usingrawkey(const u8 *raw_key, size_t raw_key_len,
*/
struct sha256_ctx {
struct __sha256_ctx ctx;
};
+/**
+ * sha256_init() - Initialize a SHA-256 context for a new message
+ * @ctx: the context to initialize
+ *
+ * If you don't need incremental computation, consider sha256() instead.
+ *
+ * Context: Any context.
+ */
void sha256_init(struct sha256_ctx *ctx);
+
+/**
+ * sha256_update() - Update a SHA-256 context with message data
+ * @ctx: the context to update; must have been initialized
+ * @data: the message data
+ * @len: the data length in bytes
+ *
+ * This can be called any number of times.
+ *
+ * Context: Any context.
+ */
static inline void sha256_update(struct sha256_ctx *ctx,
const u8 *data, size_t len)
{
__sha256_update(&ctx->ctx, data, len);
}
+
+/**
+ * sha256_final() - Finish computing a SHA-256 message digest
+ * @ctx: the context to finalize; must have been initialized
+ * @out: (output) the resulting SHA-256 message digest
+ *
+ * After finishing, this zeroizes @ctx. So the caller does not need to do it.
+ *
+ * Context: Any context.
+ */
void sha256_final(struct sha256_ctx *ctx, u8 out[SHA256_DIGEST_SIZE]);
+
+/**
+ * sha256() - Compute SHA-256 message digest in one shot
+ * @data: the message data
+ * @len: the data length in bytes
+ * @out: (output) the resulting SHA-256 message digest
+ *
+ * Context: Any context.
+ */
void sha256(const u8 *data, size_t len, u8 out[SHA256_DIGEST_SIZE]);
/**
* struct hmac_sha256_key - Prepared key for HMAC-SHA256
* @key: private
--
2.50.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v2 00/14] SHA-256 library improvements
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (13 preceding siblings ...)
2025-06-30 16:06 ` [PATCH v2 14/14] lib/crypto: sha256: Document the SHA-224 and SHA-256 API Eric Biggers
@ 2025-07-03 17:38 ` Eric Biggers
2025-07-04 13:26 ` Ard Biesheuvel
15 siblings, 0 replies; 17+ messages in thread
From: Eric Biggers @ 2025-07-03 17:38 UTC (permalink / raw)
To: linux-crypto
Cc: linux-kernel, linux-arm-kernel, linux-mips, linuxppc-dev,
linux-riscv, linux-s390, sparclinux, x86, Ard Biesheuvel,
Jason A . Donenfeld
On Mon, Jun 30, 2025 at 09:06:31AM -0700, Eric Biggers wrote:
> This series is also available at:
>
> git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git sha256-lib-cleanup-v2
>
> This series improves the SHA-224 and SHA-256 library code to be
> consistent with what I did for SHA-384 and SHA-512. This includes:
>
> - Use stronger typing in the SHA-224 and SHA-256 functions.
>
> - Add support for HMAC-SHA224 and HMAC-SHA256. (I'll send a separate
> patch with KUnit test cases for this.)
>
> - Make the old-school crypto API's support for sha224 and sha256 just
> use the actual library API, instead of unsafe low-level functions.
>
> - Consolidate the CPU-based SHA-224 and SHA-256 code into a single
> module, with better inlining and dead code elimination.
>
> - Properly document the SHA-224 and SHA-256 functions.
>
> - Other changes to synchronize the code with SHA-384 and SHA-512.
>
> Changed in v2:
> - Dropped sha224_kunit.c changes; it will be added later in the history
> - Dropped some patches that I folded into the SHA-512 series
> - Removed redundant checks of IS_ENABLED(CONFIG_KERNEL_MODE_NEON)
> - Removed obsolete setting of -DARCH for sha256.o
> - Fixed a commit title to mention sha256 instead of sha512
> - Excluded HMAC-SHA{224,256} code from purgatory, where it isn't needed
>
> Eric Biggers (14):
> libceph: Rename hmac_sha256() to ceph_hmac_sha256()
> cxl/test: Simplify fw_buf_checksum_show()
> lib/crypto: sha256: Reorder some code
> lib/crypto: sha256: Remove sha256_blocks_simd()
> lib/crypto: sha256: Add sha224() and sha224_update()
> lib/crypto: sha256: Make library API use strongly-typed contexts
> lib/crypto: sha256: Propagate sha256_block_state type to
> implementations
> lib/crypto: sha256: Add HMAC-SHA224 and HMAC-SHA256 support
> crypto: sha256 - Wrap library and add HMAC support
> crypto: sha256 - Use same state format as legacy drivers
> lib/crypto: sha256: Remove sha256_is_arch_optimized()
> lib/crypto: sha256: Consolidate into single module
> lib/crypto: sha256: Sync sha256_update() with sha512_update()
> lib/crypto: sha256: Document the SHA-224 and SHA-256 API
FYI, applied to libcrypto-next. Reviews and acks would be greatly appreciated,
though!
To fix https://lore.kernel.org/r/202507010837.ERX7aWw7-lkp@intel.com/
I applied the following fixup to
"lib/crypto: sha256: Propagate sha256_block_state type to implementations".
diff --git a/lib/crypto/powerpc/sha256.c b/lib/crypto/powerpc/sha256.c
index c3f844ae0aceb..55f42403d572a 100644
--- a/lib/crypto/powerpc/sha256.c
+++ b/lib/crypto/powerpc/sha256.c
@@ -26,7 +26,8 @@
*/
#define MAX_BYTES 1024
-extern void ppc_spe_sha256_transform(u32 *state, const u8 *src, u32 blocks);
+extern void ppc_spe_sha256_transform(struct sha256_block_state *state,
+ const u8 *src, u32 blocks);
static void spe_begin(void)
{
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v2 00/14] SHA-256 library improvements
2025-06-30 16:06 [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
` (14 preceding siblings ...)
2025-07-03 17:38 ` [PATCH v2 00/14] SHA-256 library improvements Eric Biggers
@ 2025-07-04 13:26 ` Ard Biesheuvel
15 siblings, 0 replies; 17+ messages in thread
From: Ard Biesheuvel @ 2025-07-04 13:26 UTC (permalink / raw)
To: Eric Biggers
Cc: linux-crypto, linux-kernel, linux-arm-kernel, linux-mips,
linuxppc-dev, linux-riscv, linux-s390, sparclinux, x86,
Jason A . Donenfeld
On Mon, 30 Jun 2025 at 18:09, Eric Biggers <ebiggers@kernel.org> wrote:
>
> This series is also available at:
>
> git fetch https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git sha256-lib-cleanup-v2
>
> This series improves the SHA-224 and SHA-256 library code to be
> consistent with what I did for SHA-384 and SHA-512. This includes:
>
> - Use stronger typing in the SHA-224 and SHA-256 functions.
>
> - Add support for HMAC-SHA224 and HMAC-SHA256. (I'll send a separate
> patch with KUnit test cases for this.)
>
> - Make the old-school crypto API's support for sha224 and sha256 just
> use the actual library API, instead of unsafe low-level functions.
>
> - Consolidate the CPU-based SHA-224 and SHA-256 code into a single
> module, with better inlining and dead code elimination.
>
> - Properly document the SHA-224 and SHA-256 functions.
>
> - Other changes to synchronize the code with SHA-384 and SHA-512.
>
> Changed in v2:
> - Dropped sha224_kunit.c changes; it will be added later in the history
> - Dropped some patches that I folded into the SHA-512 series
> - Removed redundant checks of IS_ENABLED(CONFIG_KERNEL_MODE_NEON)
> - Removed obsolete setting of -DARCH for sha256.o
> - Fixed a commit title to mention sha256 instead of sha512
> - Excluded HMAC-SHA{224,256} code from purgatory, where it isn't needed
>
> Eric Biggers (14):
> libceph: Rename hmac_sha256() to ceph_hmac_sha256()
> cxl/test: Simplify fw_buf_checksum_show()
> lib/crypto: sha256: Reorder some code
> lib/crypto: sha256: Remove sha256_blocks_simd()
> lib/crypto: sha256: Add sha224() and sha224_update()
> lib/crypto: sha256: Make library API use strongly-typed contexts
> lib/crypto: sha256: Propagate sha256_block_state type to
> implementations
> lib/crypto: sha256: Add HMAC-SHA224 and HMAC-SHA256 support
> crypto: sha256 - Wrap library and add HMAC support
> crypto: sha256 - Use same state format as legacy drivers
> lib/crypto: sha256: Remove sha256_is_arch_optimized()
> lib/crypto: sha256: Consolidate into single module
> lib/crypto: sha256: Sync sha256_update() with sha512_update()
> lib/crypto: sha256: Document the SHA-224 and SHA-256 API
>
Acked-by: Ard Biesheuvel <ardb@kernel.org>
> arch/mips/cavium-octeon/Kconfig | 6 -
> arch/mips/cavium-octeon/crypto/Makefile | 1 -
> arch/riscv/purgatory/purgatory.c | 8 +-
> arch/s390/purgatory/purgatory.c | 2 +-
> arch/x86/purgatory/purgatory.c | 2 +-
> crypto/Kconfig | 4 +-
> crypto/Makefile | 1 -
> crypto/sha256.c | 371 +++++++++-------
> crypto/testmgr.c | 12 +
> drivers/char/tpm/tpm2-sessions.c | 12 +-
> drivers/crypto/img-hash.c | 4 +-
> drivers/crypto/starfive/jh7110-hash.c | 8 +-
> include/crypto/internal/sha2.h | 66 ---
> include/crypto/sha2.h | 390 +++++++++++++++--
> kernel/kexec_file.c | 10 +-
> lib/crypto/Kconfig | 34 +-
> lib/crypto/Makefile | 39 +-
> lib/crypto/arm/Kconfig | 7 -
> lib/crypto/arm/Makefile | 8 +-
> lib/crypto/arm/sha256-armv4.pl | 20 +-
> lib/crypto/arm/sha256-ce.S | 2 +-
> lib/crypto/arm/sha256.c | 64 ---
> lib/crypto/arm/sha256.h | 46 ++
> lib/crypto/arm64/Kconfig | 6 -
> lib/crypto/arm64/Makefile | 9 +-
> lib/crypto/arm64/sha2-armv8.pl | 2 +-
> lib/crypto/arm64/sha256-ce.S | 2 +-
> lib/crypto/arm64/sha256.c | 75 ----
> lib/crypto/arm64/sha256.h | 57 +++
> lib/crypto/arm64/sha512.h | 6 +-
> .../crypto/mips/sha256.h | 20 +-
> lib/crypto/powerpc/Kconfig | 6 -
> lib/crypto/powerpc/Makefile | 3 -
> lib/crypto/powerpc/{sha256.c => sha256.h} | 19 +-
> lib/crypto/riscv/Kconfig | 8 -
> lib/crypto/riscv/Makefile | 3 -
> .../sha256-riscv64-zvknha_or_zvknhb-zvkb.S | 2 +-
> lib/crypto/riscv/sha256.c | 67 ---
> lib/crypto/riscv/sha256.h | 42 ++
> lib/crypto/s390/Kconfig | 6 -
> lib/crypto/s390/Makefile | 3 -
> lib/crypto/s390/sha256.c | 47 --
> lib/crypto/s390/sha256.h | 28 ++
> lib/crypto/sha256-generic.c | 138 ------
> lib/crypto/sha256.c | 413 ++++++++++++++++--
> lib/crypto/sparc/Kconfig | 8 -
> lib/crypto/sparc/Makefile | 4 -
> lib/crypto/sparc/{sha256.c => sha256.h} | 37 +-
> lib/crypto/x86/Kconfig | 8 -
> lib/crypto/x86/Makefile | 3 -
> lib/crypto/x86/sha256-avx-asm.S | 2 +-
> lib/crypto/x86/sha256-avx2-asm.S | 2 +-
> lib/crypto/x86/sha256-ni-asm.S | 2 +-
> lib/crypto/x86/sha256-ssse3-asm.S | 2 +-
> lib/crypto/x86/sha256.c | 80 ----
> lib/crypto/x86/sha256.h | 55 +++
> net/ceph/messenger_v2.c | 12 +-
> tools/testing/cxl/test/mem.c | 21 +-
> 58 files changed, 1307 insertions(+), 1008 deletions(-)
> delete mode 100644 include/crypto/internal/sha2.h
> delete mode 100644 lib/crypto/arm/sha256.c
> create mode 100644 lib/crypto/arm/sha256.h
> delete mode 100644 lib/crypto/arm64/sha256.c
> create mode 100644 lib/crypto/arm64/sha256.h
> rename arch/mips/cavium-octeon/crypto/octeon-sha256.c => lib/crypto/mips/sha256.h (76%)
> rename lib/crypto/powerpc/{sha256.c => sha256.h} (76%)
> delete mode 100644 lib/crypto/riscv/sha256.c
> create mode 100644 lib/crypto/riscv/sha256.h
> delete mode 100644 lib/crypto/s390/sha256.c
> create mode 100644 lib/crypto/s390/sha256.h
> delete mode 100644 lib/crypto/sha256-generic.c
> delete mode 100644 lib/crypto/sparc/Kconfig
> delete mode 100644 lib/crypto/sparc/Makefile
> rename lib/crypto/sparc/{sha256.c => sha256.h} (53%)
> delete mode 100644 lib/crypto/x86/sha256.c
> create mode 100644 lib/crypto/x86/sha256.h
>
> --
> 2.50.0
>
^ permalink raw reply [flat|nested] 17+ messages in thread