[PATCH v2 2/2] ARM: pbl: add PBL support for crypto extensions
Sascha Hauer <[email protected]> Mon, 27 Jul 2026 14:59:45 +0200
| Newsgroups | org.infradead.lists.barebox |
|---|---|
| Message-ID | <[email protected]> |
Hashing large blobs in the PBL with the generic C SHA-256 transform is slow; ARMv8 provides optional Crypto Extensions (sha256h/sha256h2/sha256su0/ sha256su1) that do the transform roughly 100x faster, and barebox proper already uses them via arch/arm/crypto/sha2-ce-glue.c. Reuse that driver in the PBL. Build sha2-ce-glue.c and the shared sha2-ce-core.S transform for the PBL as well (obj-pbl-) and have the glue additionally provide pbl_sha256_ce(), a one-shot hash that drives the asm core directly without the digest API or NEON save/restore, neither of which exist in the PBL. Like the digest registration it gates on ID_AA64ISAR0_EL1.SHA2 and returns -EOPNOTSUPP when the extensions are absent, so pbl_sha256() transparently falls back to the generic C transform. Assisted-by: Claude Opus 4.8 Signed-off-by: Sascha Hauer <[email protected]> --- arch/arm/crypto/Makefile | 3 +-- arch/arm/crypto/sha2-ce-glue.c | 44 ++++++++++++++++++++++++++++++++++++++++++ include/crypto/pbl-sha.h | 10 ++++++++++ pbl/sha256.c | 3 +++ 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile index 55b3ac0538..976c175b71 100644 --- a/arch/arm/crypto/Makefile +++ b/arch/arm/crypto/Makefile @@ -12,8 +12,7 @@ sha256-arm-y := sha256-core.o sha256_glue.o obj-$(CONFIG_DIGEST_SHA1_ARM64_CE) += sha1-ce.o sha1-ce-y := sha1-ce-glue.o sha1-ce-core.o -obj-$(CONFIG_DIGEST_SHA256_ARM64_CE) += sha2-ce.o -sha2-ce-y := sha2-ce-glue.o sha2-ce-core.o +obj-pbl-$(CONFIG_DIGEST_SHA256_ARM64_CE) += sha2-ce-glue.o sha2-ce-core.o quiet_cmd_perl = PERL $@ cmd_perl = $(PERL) $(<) > $(@) diff --git a/arch/arm/crypto/sha2-ce-glue.c b/arch/arm/crypto/sha2-ce-glue.c index 8479b3c60c..4ccf1b86cb 100644 --- a/arch/arm/crypto/sha2-ce-glue.c +++ b/arch/arm/crypto/sha2-ce-glue.c @@ -10,6 +10,7 @@ #include <init.h> #include <crypto/sha.h> #include <crypto/sha256_base.h> +#include <crypto/pbl-sha.h> #include <crypto/internal.h> #include <linux/linkage.h> #include <asm/byteorder.h> @@ -33,6 +34,49 @@ extern const u32 sha256_ce_offsetof_finalize; asmlinkage int sha2_ce_transform(struct sha256_ce_state *sst, u8 const *src, int blocks); +/* + * In the PBL there is no digest API and no NEON save/restore; expose a + * one-shot pbl_sha256_ce() that pbl_sha256() calls in preference to the + * generic C transform. + */ +static void pbl_sha2_ce_transform(struct sha256_state *sst, u8 const *src, + int blocks) +{ + struct sha256_ce_state *s = + container_of(sst, struct sha256_ce_state, sst); + + /* finalize == 0: C does the padding via sha256_base_do_finalize(). */ + s->finalize = 0; + while (blocks) { + int rem = sha2_ce_transform(s, src, blocks); + + src += (blocks - rem) * SHA256_BLOCK_SIZE; + blocks = rem; + } +} + +int pbl_sha256_ce(const void *buf, size_t len, u8 out[SHA256_DIGEST_SIZE]) +{ + struct sha256_ce_state s; + struct digest d = { .ctx = &s, .length = SHA256_DIGEST_SIZE }; + + /* + * The Crypto Extensions are optional on ARMv8 and sha256h & co. trap + * as undefined without them, so gate on ID_AA64ISAR0_EL1.SHA2 like the + * digest registration below does and let the caller fall back to + * generic C. + */ + if (!(read_sysreg(ID_AA64ISAR0_EL1) & ID_AA64ISAR0_EL1_SHA2_MASK)) + return -EOPNOTSUPP; + + sha256_base_init(&d); + sha256_base_do_update(&d, buf, len, pbl_sha2_ce_transform); + sha256_base_do_finalize(&d, pbl_sha2_ce_transform); + sha256_base_finish(&d, out); + + return 0; +} + static void __sha2_ce_transform(struct sha256_state *sst, u8 const *src, int blocks) { diff --git a/include/crypto/pbl-sha.h b/include/crypto/pbl-sha.h index 2508448ab4..3ccd5151e1 100644 --- a/include/crypto/pbl-sha.h +++ b/include/crypto/pbl-sha.h @@ -14,4 +14,14 @@ int sha256_final(struct digest *desc, u8 *out); /* One-shot SHA-256 that picks the best transform available in the PBL. */ void pbl_sha256(const void *buf, size_t len, u8 out[SHA256_DIGEST_SIZE]); +#ifdef CONFIG_DIGEST_SHA256_ARM64_CE +/* ARMv8 Crypto Extensions transform; returns -EOPNOTSUPP if unavailable. */ +int pbl_sha256_ce(const void *buf, size_t len, u8 out[SHA256_DIGEST_SIZE]); +#else +static inline int pbl_sha256_ce(const void *buf, size_t len, u8 out[SHA256_DIGEST_SIZE]) +{ + return -EOPNOTSUPP; +} +#endif + #endif /* __PBL-SHA_H_ */ diff --git a/pbl/sha256.c b/pbl/sha256.c index 853d6bcbf6..04cc64a77d 100644 --- a/pbl/sha256.c +++ b/pbl/sha256.c @@ -21,5 +21,8 @@ static void pbl_sha256_generic(const void *buf, size_t len, u8 *out) void pbl_sha256(const void *buf, size_t len, u8 out[static SHA256_DIGEST_SIZE]) { + if (!pbl_sha256_ce(buf, len, out)) + return; + pbl_sha256_generic(buf, len, out); } -- 2.47.3