From 55711243c66a0b10bb5d10fdfb1a0e5621ec4f52 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Fri, 4 Sep 2026 11:24:13 +0200 Subject: [PATCH] F-11026: image: declare wolfHSM DER sig length as word32 wc_ecc_rs_raw_to_sig() takes a word32* outlen, but the wolfHSM client/server path in wolfBoot_verify_signature_ecc() declared the buffer length as size_t and cast the pointer. On a 64-bit big-endian target the API reads the high (zero) half, so the DER conversion sees outlen 0 and the write-back lands in the wrong half of the size_t. Declare tmpSigSz as word32 and pass &tmpSigSz directly; this also matches the word32 sigLen of wc_ecc_verify_hash() below. Add a host compile check for the WOLFBOOT_ENABLE_WOLFHSM_CLIENT build of image.c, which unit CI did not cover (only the PIC32CZ cross build). --- src/image.c | 4 +- tools/unit-tests/Makefile | 8 ++++ .../unit-image-wolfhsm-client-build.py | 46 +++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100755 tools/unit-tests/unit-image-wolfhsm-client-build.py diff --git a/src/image.c b/src/image.c index 3492d292..8914ba99 100644 --- a/src/image.c +++ b/src/image.c @@ -326,7 +326,7 @@ static void wolfBoot_verify_signature_ecc(uint8_t key_slot, defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) uint8_t tmpSigBuf[ECC_MAX_SIG_SIZE] = {0}; - size_t tmpSigSz = sizeof(tmpSigBuf); + word32 tmpSigSz = sizeof(tmpSigBuf); #if defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) || \ (defined(WOLFBOOT_ENABLE_WOLFHSM_SERVER) && \ @@ -386,7 +386,7 @@ static void wolfBoot_verify_signature_ecc(uint8_t key_slot, and left-zero-padded, and the conversion strips the padding. */ ret = wc_ecc_rs_raw_to_sig(sig, (word32)point_sz, &sig[point_sz], (word32)point_sz, - (byte*)&tmpSigBuf, (word32*)&tmpSigSz); + (byte*)&tmpSigBuf, &tmpSigSz); /* Verify the (temporary) DER representation of the signature */ if (ret == 0) { VERIFY_FN(img, &verify_res, wc_ecc_verify_hash, tmpSigBuf, tmpSigSz, diff --git a/tools/unit-tests/Makefile b/tools/unit-tests/Makefile index 6d2ada2d..6efd8e0b 100644 --- a/tools/unit-tests/Makefile +++ b/tools/unit-tests/Makefile @@ -223,6 +223,7 @@ run: $(TESTS) python3 unit-sign-delta-basehash-cleanup.py || exit 1 python3 unit-delta-sector-align.py || exit 1 python3 unit-elf-scatter-db-build.py || exit 1 + python3 unit-image-wolfhsm-client-build.py || exit 1 python3 unit-x86-fsp-stage1auth-build.py || exit 1 python3 unit-sign-custom-tlv-le.py || exit 1 python3 unit-sign-custom-tlv-large.py || exit 1 @@ -844,6 +845,13 @@ unit-update-flash-delta-misalign: ../../include/target.h unit-update-flash.c unit-update-flash-elf-scatter-db: ../../include/target.h unit-update-flash.c FORCE gcc -c -o /dev/null unit-update-flash.c $(CFLAGS) +unit-image-wolfhsm-client-build:CFLAGS+=-I$(WOLFBOOT_LIB_WOLFHSM) \ + -DWOLFHSM_CFG_NO_SYS_TIME -DMOCK_PARTITIONS -DWOLFBOOT_HASH_SHA256 \ + -DWOLFBOOT_SIGN_ECC256 -DWOLFBOOT_ENABLE_WOLFHSM_CLIENT \ + -DIMAGE_HEADER_SIZE=256 -D__WOLFBOOT +unit-image-wolfhsm-client-build: ../../include/target.h ../../src/image.c FORCE + gcc -c -o /dev/null ../../src/image.c $(CFLAGS) + unit-update-flash-enc:CFLAGS+=-DMOCK_PARTITIONS -DWOLFBOOT_NO_SIGN -DUNIT_TEST_AUTH \ -DWOLFBOOT_HASH_SHA256 -DPRINTF_ENABLED -DEXT_FLASH -DPART_UPDATE_EXT \ -DPART_SWAP_EXT -DEXT_ENCRYPTED -DENCRYPT_WITH_CHACHA -DHAVE_CHACHA \ diff --git a/tools/unit-tests/unit-image-wolfhsm-client-build.py b/tools/unit-tests/unit-image-wolfhsm-client-build.py new file mode 100755 index 00000000..626ec430 --- /dev/null +++ b/tools/unit-tests/unit-image-wolfhsm-client-build.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 +# unit-image-wolfhsm-client-build.py +# +# Compile check for the WOLFBOOT_ENABLE_WOLFHSM_CLIENT path in +# wolfBoot_verify_signature_ecc() (src/image.c). The raw-to-DER +# signature conversion passes the output length to +# wc_ecc_rs_raw_to_sig(), which expects a word32*; this branch was +# only built by the PIC32CZ cross CI, so keep it compiling in the +# host unit CI as well. +# +# Copyright (C) 2026 wolfSSL Inc. +# +# This file is part of wolfBoot. +# +# wolfBoot is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3 of the License, +# or (at your option) any later version. +# +# wolfBoot is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + +import subprocess +import sys + + +def main(): + p = subprocess.run(["make", "unit-image-wolfhsm-client-build"], + capture_output=True, text=True) + if p.returncode != 0: + print("FAIL: WOLFBOOT_ENABLE_WOLFHSM_CLIENT image.c " + "does not compile:\n") + print(p.stderr[-2000:]) + return 1 + print("PASS: WOLFBOOT_ENABLE_WOLFHSM_CLIENT image.c compiles") + return 0 + + +if __name__ == "__main__": + sys.exit(main())