From: Heiko Schocher Date: Tue, 18 Nov 2025 04:30:39 +0000 (+0100) Subject: lib: sm3: implement U-Boot parts X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c4ab316269debc321907acc4f8f02dfe5653aeaf;p=thirdparty%2Fu-boot.git lib: sm3: implement U-Boot parts add the U-Boot specific parts for the SM3 hash implementation: Signed-off-by: Heiko Schocher --- diff --git a/MAINTAINERS b/MAINTAINERS index e1d79206e50..dc62990a090 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1689,6 +1689,7 @@ F: test/lib/slre.c SM3 M: Heiko Schocher S: Maintained +F: cmd/sm3sum.c F: include/u-boot/sm3.h F: lib/sm3.c diff --git a/boot/Kconfig b/boot/Kconfig index 85f4d468069..76cc628c9bd 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -1042,6 +1042,7 @@ config MEASURED_BOOT select SHA256 select SHA384 select SHA512 + select SM3 help This option enables measurement of the boot process when booting without UEFI . Measurement involves creating cryptographic hashes diff --git a/cmd/Kconfig b/cmd/Kconfig index 5b9c13d85e7..8e3efff2bee 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -264,6 +264,21 @@ config CMD_SBI help Display information about the SBI implementation. +config CMD_SM3SUM + bool "sm3sum" + select SM3 + select HASH + help + Compute SM3 checksum. + add SM3 hash functionality + +config SM3SUM_VERIFY + bool "sm3sum -v" + depends on CMD_SM3SUM + help + Add for the sm3sum command the -v option + to verify data against an SM3 checksum. + config CMD_SMBIOS bool "smbios" depends on SMBIOS diff --git a/cmd/Makefile b/cmd/Makefile index 25479907797..642042cfe00 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -177,6 +177,7 @@ obj-$(CONFIG_CMD_SETEXPR) += setexpr.o obj-$(CONFIG_CMD_SETEXPR_FMT) += printf.o obj-$(CONFIG_CMD_SPI) += spi.o obj-$(CONFIG_CMD_STRINGS) += strings.o +obj-$(CONFIG_CMD_SM3SUM) += sm3sum.o obj-$(CONFIG_CMD_SMBIOS) += smbios.o obj-$(CONFIG_CMD_SMC) += smccc.o obj-$(CONFIG_CMD_SYSBOOT) += sysboot.o diff --git a/cmd/sm3sum.c b/cmd/sm3sum.c new file mode 100644 index 00000000000..9044a322e22 --- /dev/null +++ b/cmd/sm3sum.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2025 + * Heiko Schocher, Nabladev Software Engineering, hs@nabladev.com + * + * based on code from cmd/md5sum.c + */ + +#include +#include +#include + +static int do_sm3sum(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int flags = HASH_FLAG_ENV; + int ac; + char *const *av; + + if (argc < 3) + return CMD_RET_USAGE; + + av = argv + 1; + ac = argc - 1; + if (IS_ENABLED(CONFIG_SM3SUM_VERIFY) && strcmp(*av, "-v") == 0) { + flags |= HASH_FLAG_VERIFY; + av++; + ac--; + } + + return hash_command("sm3_256", flags, cmdtp, flag, ac, av); +} + +#if IS_ENABLED(CONFIG_SM3SUM_VERIFY) +U_BOOT_CMD(sm3sum, 5, 1, do_sm3sum, + "compute SM3 message digest", + "address count [[*]sum]\n" + " - compute SM3 message digest [save to sum]\n" + "sm3sum -v address count [*]sum\n" + " - verify sm3sum of memory area" +); +#else +U_BOOT_CMD(sm3sum, 4, 1, do_sm3sum, + "compute SM3 message digest", + "address count [[*]sum]\n" + " - compute SM3 message digest [save to sum]" +); +#endif /* IS_ENABLED(CONFIG_SM3SUM_VERIFY) */ diff --git a/common/hash.c b/common/hash.c index 0c45992d5c7..71c4bef5826 100644 --- a/common/hash.c +++ b/common/hash.c @@ -34,6 +34,7 @@ #include #include #include +#include static int __maybe_unused hash_init_sha1(struct hash_algo *algo, void **ctxp) { @@ -143,6 +144,34 @@ static int __maybe_unused hash_finish_sha512(struct hash_algo *algo, void *ctx, return 0; } +static int __maybe_unused hash_init_sm3(struct hash_algo *algo, void **ctxp) +{ + struct sm3_context *ctx = malloc(sizeof(struct sm3_context)); + + sm3_init(ctx); + *ctxp = ctx; + return 0; +} + +static int __maybe_unused hash_update_sm3(struct hash_algo *algo, void *ctx, + const void *buf, uint size, + int is_last) +{ + sm3_update((struct sm3_context *)ctx, buf, size); + return 0; +} + +static int __maybe_unused hash_finish_sm3(struct hash_algo *algo, void *ctx, + void *dest_buf, int size) +{ + if (size < algo->digest_size) + return -1; + + sm3_final((struct sm3_context *)ctx, dest_buf); + free(ctx); + return 0; +} + static int __maybe_unused hash_init_crc16_ccitt(struct hash_algo *algo, void **ctxp) { @@ -298,6 +327,17 @@ static struct hash_algo hash_algo[] = { #endif }, #endif +#if CONFIG_IS_ENABLED(SM3) + { + .name = "sm3_256", + .digest_size = SM3_DIGEST_SIZE, + .chunk_size = SM3_BLOCK_SIZE, + .hash_func_ws = sm3_csum_wd, + .hash_init = hash_init_sm3, + .hash_update = hash_update_sm3, + .hash_finish = hash_finish_sm3, + }, +#endif #if CONFIG_IS_ENABLED(CRC16) { .name = "crc16-ccitt", @@ -334,7 +374,7 @@ static struct hash_algo hash_algo[] = { #if CONFIG_IS_ENABLED(SHA256) || IS_ENABLED(CONFIG_CMD_SHA1SUM) || \ CONFIG_IS_ENABLED(CRC32_VERIFY) || IS_ENABLED(CONFIG_CMD_HASH) || \ CONFIG_IS_ENABLED(SHA384) || CONFIG_IS_ENABLED(SHA512) || \ - IS_ENABLED(CONFIG_CMD_MD5SUM) + IS_ENABLED(CONFIG_CMD_MD5SUM) || CONFIG_IS_ENABLED(SM3) #define multi_hash() 1 #else #define multi_hash() 0 diff --git a/include/u-boot/sm3.h b/include/u-boot/sm3.h index de16684ca0a..b4ead96c776 100644 --- a/include/u-boot/sm3.h +++ b/include/u-boot/sm3.h @@ -24,4 +24,12 @@ struct sm3_context { uint8_t buffer[SM3_BLOCK_SIZE]; int buflen; }; + +void sm3_init(struct sm3_context *sctx); +void sm3_update(struct sm3_context *sctx, const uint8_t *input, size_t ilen); +void sm3_final(struct sm3_context *sctx, uint8_t output[SM3_DIGEST_SIZE]); +void sm3_hash(const uint8_t *input, size_t ilen, uint8_t output[SM3_DIGEST_SIZE]); + +void sm3_csum_wd(const unsigned char *input, uint32_t len, + unsigned char *output, unsigned int chunk_sz); #endif diff --git a/lib/sm3.c b/lib/sm3.c index bb994d187ef..2a4e825481d 100644 --- a/lib/sm3.c +++ b/lib/sm3.c @@ -185,3 +185,128 @@ static inline void sm3_block(struct sm3_context *sctx, data += SM3_BLOCK_SIZE; } } + +void sm3_init(struct sm3_context *sctx) +{ + memset(sctx, 0, sizeof(*sctx)); + + /* Load initial values */ + sctx->state[0] = SM3_IVA; + sctx->state[1] = SM3_IVB; + sctx->state[2] = SM3_IVC; + sctx->state[3] = SM3_IVD; + sctx->state[4] = SM3_IVE; + sctx->state[5] = SM3_IVF; + sctx->state[6] = SM3_IVG; + sctx->state[7] = SM3_IVH; + sctx->count = 0; +} + +void sm3_update(struct sm3_context *sctx, const uint8_t *input, size_t ilen) +{ + unsigned int partial = sctx->count % SM3_BLOCK_SIZE; + u32 W[16]; + + sctx->count += ilen; + + if ((partial + ilen) >= SM3_BLOCK_SIZE) { + int blocks; + + if (partial) { + int p = SM3_BLOCK_SIZE - partial; + + memcpy(sctx->buffer + partial, input, p); + input += p; + ilen -= p; + + sm3_block(sctx, sctx->buffer, 1, W); + } + + blocks = ilen / SM3_BLOCK_SIZE; + ilen %= SM3_BLOCK_SIZE; + + if (blocks) { + sm3_block(sctx, input, blocks, W); + input += blocks * SM3_BLOCK_SIZE; + } + + memset(W, 0, sizeof(W)); + + partial = 0; + } + if (ilen) + memcpy(sctx->buffer + partial, input, ilen); +} + +void sm3_final(struct sm3_context *sctx, uint8_t output[SM3_DIGEST_SIZE]) +{ + const int bit_offset = SM3_BLOCK_SIZE - sizeof(u64); + __be64 *bits = (__be64 *)(sctx->buffer + bit_offset); + __be32 *digest = (__be32 *)&output[0]; + unsigned int partial = sctx->count % SM3_BLOCK_SIZE; + u32 W[16]; + int i; + + sctx->buffer[partial++] = 0x80; + if (partial > bit_offset) { + memset(sctx->buffer + partial, 0, SM3_BLOCK_SIZE - partial); + partial = 0; + + sm3_block(sctx, sctx->buffer, 1, W); + } + + memset(sctx->buffer + partial, 0, bit_offset - partial); + *bits = cpu_to_be64(sctx->count << 3); + sm3_block(sctx, sctx->buffer, 1, W); + + for (i = 0; i < 8; i++) + put_unaligned_be32(sctx->state[i], digest++); + + /* Zeroize sensitive information. */ + memset(W, 0, sizeof(W)); + memset(sctx, 0, sizeof(*sctx)); +} + +/** + * sm3_hash - Calculate SM3 hash of input data + * @input: Input data + * @ilen: Input data length in bytes + * @output: Output buffer for hash (32 bytes) + */ +void sm3_hash(const uint8_t *input, size_t ilen, uint8_t output[SM3_DIGEST_SIZE]) +{ + struct sm3_context sctx; + + sm3_init(&sctx); + sm3_update(&sctx, input, ilen); + sm3_final(&sctx, output); +} + +/** + * sm3_csum_wd - Calculate SM3 checksum on memory region using watchdog + * @addr: Starting address + * @len: Length in bytes + * @output: Output buffer for checksum (32 bytes) + * @flags: Flags for watchdog behavior + * + * This is the U-Boot API entry function for SM3 hash calculation + */ +void sm3_csum_wd(const unsigned char *input, uint32_t len, + unsigned char *output, unsigned int chunk_sz) +{ + struct sm3_context ctx; + uint32_t chunk; + + sm3_init(&ctx); + + /* Process data in chunks, kicking watchdog between chunks */ + while (len > 0) { + chunk = (len > chunk_sz) ? chunk_sz : len; + sm3_update(&ctx, input, chunk); + input += chunk; + len -= chunk; + + schedule(); + } + sm3_final(&ctx, output); +}