From b26d38ed414fe7c0d9b678b5cc13e381cdebeab4 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Wed, 22 Apr 2026 12:22:43 +0200 Subject: [PATCH] Fix fTPM NSC bounds handling --- src/ftpm_callable.c | 27 ++++++---- test-app/wcs/ftpm_stub.c | 17 +++++-- tools/unit-tests/Makefile | 7 ++- tools/unit-tests/unit-ftpm-stub.c | 83 +++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 14 deletions(-) create mode 100644 tools/unit-tests/unit-ftpm-stub.c diff --git a/src/ftpm_callable.c b/src/ftpm_callable.c index 8a4c39ab..94d98793 100644 --- a/src/ftpm_callable.c +++ b/src/ftpm_callable.c @@ -117,28 +117,37 @@ void wcs_ftpm_init(void) int CSME_NSE_API wcs_ftpm_transmit(const uint8_t *cmd, uint32_t cmdSz, uint8_t *rsp, uint32_t *rspSz) { + int rc; int rspLen; + uint32_t rspCapacity; + uint32_t wireSz; if (!ftpm_ready) { return TPM_RC_INITIALIZE; } if (cmd == NULL || rsp == NULL || rspSz == NULL || cmdSz == 0U || - cmdSz > WCS_FTPM_MAX_COMMAND_SIZE || *rspSz == 0U || - *rspSz > WCS_FTPM_MAX_COMMAND_SIZE) { + cmdSz > WCS_FTPM_MAX_COMMAND_SIZE) { return BAD_FUNC_ARG; } - rspLen = (int)*rspSz; - int rc = FWTPM_ProcessCommand(&ftpm_ctx, cmd, (int)cmdSz, rsp, &rspLen, 0); - if (rc >= 0) { - uint32_t wireSz = ftpm_rsp_size(rsp, rspLen); - if (wireSz > 0U && wireSz <= *rspSz) { + rspCapacity = *rspSz; + if (rspCapacity == 0U || rspCapacity > WCS_FTPM_MAX_COMMAND_SIZE) { + return BAD_FUNC_ARG; + } + + rspLen = (int)rspCapacity; + rc = FWTPM_ProcessCommand(&ftpm_ctx, cmd, (int)cmdSz, rsp, &rspLen, 0); + if (rc == TPM_RC_SUCCESS) { + wireSz = ftpm_rsp_size(rsp, rspLen); + if (wireSz > 0U && wireSz <= rspCapacity) { *rspSz = wireSz; - rc = TPM_RC_SUCCESS; } - else if (rspLen >= 0) { + else if (rspLen >= 0 && (uint32_t)rspLen <= rspCapacity) { *rspSz = (uint32_t)rspLen; } + else { + rc = TPM_RC_FAILURE; + } } return rc; } diff --git a/test-app/wcs/ftpm_stub.c b/test-app/wcs/ftpm_stub.c index c698c02f..9df3de32 100644 --- a/test-app/wcs/ftpm_stub.c +++ b/test-app/wcs/ftpm_stub.c @@ -50,9 +50,15 @@ static struct ftpm_tis_state ftpm_tis = { FTPM_STS_VALID | FTPM_STS_COMMAND_READY }; -static uint32_t ftpm_reg_offset(uint32_t addr) +static int ftpm_reg_offset(uint32_t addr, uint32_t *off) { - return (addr - FTPM_TIS_BASE) & 0x0FFFU; + if (off == NULL || addr < FTPM_TIS_BASE || + addr >= (FTPM_TIS_BASE + 0x1000U)) { + return BAD_FUNC_ARG; + } + + *off = addr - FTPM_TIS_BASE; + return TPM_RC_SUCCESS; } static void ftpm_store_le(uint8_t *buf, uint16_t size, uint32_t val) @@ -107,11 +113,14 @@ int TPM2_IoCb_FtpmNsc(TPM2_CTX *ctx, INT32 isRead, UINT32 addr, (void)ctx; (void)userCtx; - if (buf == NULL || size == 0U || addr < FTPM_TIS_BASE) { + if (buf == NULL || size == 0U) { + return BAD_FUNC_ARG; + } + + if (ftpm_reg_offset(addr, &off) != TPM_RC_SUCCESS) { return BAD_FUNC_ARG; } - off = ftpm_reg_offset(addr); burst = FTPM_BURST_COUNT; if (isRead) { diff --git a/tools/unit-tests/Makefile b/tools/unit-tests/Makefile index 63b4334a..c9a82b9d 100644 --- a/tools/unit-tests/Makefile +++ b/tools/unit-tests/Makefile @@ -50,7 +50,7 @@ TESTS:=unit-parser unit-fdt unit-extflash unit-string unit-spi-flash unit-aes128 unit-enc-nvm-flagshome unit-delta unit-update-flash unit-update-flash-delta \ unit-update-flash-self-update \ unit-update-flash-enc unit-update-ram unit-update-ram-nofixed unit-pkcs11_store unit-psa_store unit-disk \ - unit-update-disk unit-multiboot unit-boot-x86-fsp unit-loader-tpm-init unit-qspi-flash unit-tpm-rsa-exp \ + unit-update-disk unit-multiboot unit-boot-x86-fsp unit-loader-tpm-init unit-qspi-flash unit-ftpm-stub unit-tpm-rsa-exp \ unit-image-nopart unit-image-sha384 unit-image-sha3-384 unit-store-sbrk \ unit-tpm-blob unit-policy-create unit-policy-sign unit-rot-auth unit-sdhci-response-bits \ unit-sdhci-disk-unaligned unit-sign-encrypted-output @@ -168,6 +168,11 @@ unit-tpm-check-rot-auth: ../../include/target.h unit-tpm-check-rot-auth.c ../../ -DWOLFBOOT_HASH_SHA256 \ -ffunction-sections -fdata-sections $(LDFLAGS) -Wl,--gc-sections +unit-ftpm-stub: ../../include/target.h unit-ftpm-stub.c + gcc -o $@ $^ $(CFLAGS) -I$(WOLFBOOT_LIB_WOLFTPM) \ + -DWOLFTPM_USER_SETTINGS -ffunction-sections -fdata-sections \ + $(LDFLAGS) -Wl,--gc-sections + unit-tpm-blob: ../../include/target.h unit-tpm-blob.c gcc -o $@ $^ $(CFLAGS) -I$(WOLFBOOT_LIB_WOLFTPM) -DWOLFBOOT_TPM \ -DWOLFTPM_USER_SETTINGS -DWOLFBOOT_TPM_SEAL -DWOLFBOOT_SIGN_RSA2048 \ diff --git a/tools/unit-tests/unit-ftpm-stub.c b/tools/unit-tests/unit-ftpm-stub.c new file mode 100644 index 00000000..bd46bf3c --- /dev/null +++ b/tools/unit-tests/unit-ftpm-stub.c @@ -0,0 +1,83 @@ +/* unit-ftpm-stub.c + * + * Unit tests for the fTPM non-secure TIS callback shim. + */ + +#include +#include + +#define WOLFBOOT_TZ_FTPM + +int wcs_ftpm_transmit(const uint8_t *cmd, uint32_t cmdSz, uint8_t *rsp, + uint32_t *rspSz) +{ + (void)cmd; + (void)cmdSz; + (void)rsp; + (void)rspSz; + return -1; +} + +#include "../../test-app/wcs/ftpm_stub.c" + +START_TEST(ftpm_tis_rejects_address_below_window) +{ + BYTE buf[4] = {0}; + + ck_assert_int_eq(TPM2_IoCb_FtpmNsc(NULL, 1, FTPM_TIS_BASE - 1U, + buf, sizeof(buf), NULL), BAD_FUNC_ARG); +} +END_TEST + +START_TEST(ftpm_tis_rejects_address_above_window) +{ + BYTE buf[4] = {0}; + + ck_assert_int_eq(TPM2_IoCb_FtpmNsc(NULL, 1, FTPM_TIS_BASE + 0x1000U, + buf, sizeof(buf), NULL), BAD_FUNC_ARG); +} +END_TEST + +START_TEST(ftpm_tis_accepts_valid_window_register) +{ + BYTE buf[4] = {0}; + + ck_assert_int_eq(TPM2_IoCb_FtpmNsc(NULL, 1, + FTPM_TIS_BASE + FTPM_TIS_DID_VID, buf, sizeof(buf), NULL), + TPM_RC_SUCCESS); + ck_assert_uint_eq(buf[0], 0x4EU); + ck_assert_uint_eq(buf[1], 0x1BU); + ck_assert_uint_eq(buf[2], 0x01U); + ck_assert_uint_eq(buf[3], 0x00U); +} +END_TEST + +static Suite *ftpm_stub_suite(void) +{ + Suite *s; + TCase *tc; + + s = suite_create("ftpm_stub"); + tc = tcase_create("tis_window"); + tcase_add_test(tc, ftpm_tis_rejects_address_below_window); + tcase_add_test(tc, ftpm_tis_rejects_address_above_window); + tcase_add_test(tc, ftpm_tis_accepts_valid_window_register); + suite_add_tcase(s, tc); + + return s; +} + +int main(void) +{ + int fails; + Suite *s; + SRunner *sr; + + s = ftpm_stub_suite(); + sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + fails = srunner_ntests_failed(sr); + srunner_free(sr); + + return fails == 0 ? 0 : 1; +}