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:
@@ -1689,6 +1689,7 @@ F: test/lib/slre.c
|
||||
SM3
|
||||
M: Heiko Schocher <hs@nabladev.com>
|
||||
S: Maintained
|
||||
F: cmd/sm3sum.c
|
||||
F: include/u-boot/sm3.h
|
||||
F: lib/sm3.c
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
15
cmd/Kconfig
15
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
|
||||
|
||||
@@ -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
|
||||
|
||||
48
cmd/sm3sum.c
Normal file
48
cmd/sm3sum.c
Normal 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) */
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <u-boot/sha256.h>
|
||||
#include <u-boot/sha512.h>
|
||||
#include <u-boot/md5.h>
|
||||
#include <u-boot/sm3.h>
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
125
lib/sm3.c
125
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user