lib: sm3: implement U-Boot parts

add the U-Boot specific parts for the SM3 hash
implementation:

Signed-off-by: Heiko Schocher <hs@nabladev.com>
This commit is contained in:
Heiko Schocher
2025-12-04 09:38:58 -06:00
committed by Tom Rini
parent 41c0131b95
commit c4ab316269
8 changed files with 240 additions and 1 deletions
+1
View File
@@ -1689,6 +1689,7 @@ F: test/lib/slre.c
SM3 SM3
M: Heiko Schocher <hs@nabladev.com> M: Heiko Schocher <hs@nabladev.com>
S: Maintained S: Maintained
F: cmd/sm3sum.c
F: include/u-boot/sm3.h F: include/u-boot/sm3.h
F: lib/sm3.c F: lib/sm3.c
+1
View File
@@ -1042,6 +1042,7 @@ config MEASURED_BOOT
select SHA256 select SHA256
select SHA384 select SHA384
select SHA512 select SHA512
select SM3
help help
This option enables measurement of the boot process when booting This option enables measurement of the boot process when booting
without UEFI . Measurement involves creating cryptographic hashes without UEFI . Measurement involves creating cryptographic hashes
+15
View File
@@ -264,6 +264,21 @@ config CMD_SBI
help help
Display information about the SBI implementation. 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 config CMD_SMBIOS
bool "smbios" bool "smbios"
depends on SMBIOS depends on SMBIOS
+1
View File
@@ -177,6 +177,7 @@ obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
obj-$(CONFIG_CMD_SETEXPR_FMT) += printf.o obj-$(CONFIG_CMD_SETEXPR_FMT) += printf.o
obj-$(CONFIG_CMD_SPI) += spi.o obj-$(CONFIG_CMD_SPI) += spi.o
obj-$(CONFIG_CMD_STRINGS) += strings.o obj-$(CONFIG_CMD_STRINGS) += strings.o
obj-$(CONFIG_CMD_SM3SUM) += sm3sum.o
obj-$(CONFIG_CMD_SMBIOS) += smbios.o obj-$(CONFIG_CMD_SMBIOS) += smbios.o
obj-$(CONFIG_CMD_SMC) += smccc.o obj-$(CONFIG_CMD_SMC) += smccc.o
obj-$(CONFIG_CMD_SYSBOOT) += sysboot.o obj-$(CONFIG_CMD_SYSBOOT) += sysboot.o
+48
View File
@@ -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 <command.h>
#include <env.h>
#include <hash.h>
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) */
+41 -1
View File
@@ -34,6 +34,7 @@
#include <u-boot/sha256.h> #include <u-boot/sha256.h>
#include <u-boot/sha512.h> #include <u-boot/sha512.h>
#include <u-boot/md5.h> #include <u-boot/md5.h>
#include <u-boot/sm3.h>
static int __maybe_unused hash_init_sha1(struct hash_algo *algo, void **ctxp) 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; 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, static int __maybe_unused hash_init_crc16_ccitt(struct hash_algo *algo,
void **ctxp) void **ctxp)
{ {
@@ -298,6 +327,17 @@ static struct hash_algo hash_algo[] = {
#endif #endif
}, },
#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) #if CONFIG_IS_ENABLED(CRC16)
{ {
.name = "crc16-ccitt", .name = "crc16-ccitt",
@@ -334,7 +374,7 @@ static struct hash_algo hash_algo[] = {
#if CONFIG_IS_ENABLED(SHA256) || IS_ENABLED(CONFIG_CMD_SHA1SUM) || \ #if CONFIG_IS_ENABLED(SHA256) || IS_ENABLED(CONFIG_CMD_SHA1SUM) || \
CONFIG_IS_ENABLED(CRC32_VERIFY) || IS_ENABLED(CONFIG_CMD_HASH) || \ CONFIG_IS_ENABLED(CRC32_VERIFY) || IS_ENABLED(CONFIG_CMD_HASH) || \
CONFIG_IS_ENABLED(SHA384) || CONFIG_IS_ENABLED(SHA512) || \ 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 #define multi_hash() 1
#else #else
#define multi_hash() 0 #define multi_hash() 0
+8
View File
@@ -24,4 +24,12 @@ struct sm3_context {
uint8_t buffer[SM3_BLOCK_SIZE]; uint8_t buffer[SM3_BLOCK_SIZE];
int buflen; 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 #endif
+125
View File
@@ -185,3 +185,128 @@ static inline void sm3_block(struct sm3_context *sctx,
data += SM3_BLOCK_SIZE; 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);
}