Skip to content

Commit c0338db

Browse files
committed
Add fwTPM HAL unit tests for clock and NV
1 parent a1b5f3d commit c0338db

1 file changed

Lines changed: 147 additions & 0 deletions

File tree

tests/fwtpm_unit_tests.c

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,6 +1937,146 @@ static void test_fwtpm_clock_set(void)
19371937
printf("Test fwTPM:\tClockSet/ClockRateAdjust:\tPassed\n");
19381938
}
19391939

1940+
/* ================================================================== */
1941+
/* HAL registration tests */
1942+
/* ================================================================== */
1943+
1944+
/* Mock clock HAL state */
1945+
static UINT64 gMockClockMs;
1946+
static int gMockClockCalls;
1947+
static void* gMockClockCtxSeen;
1948+
1949+
static UINT64 mock_clock_get_ms(void* ctx)
1950+
{
1951+
gMockClockCalls++;
1952+
gMockClockCtxSeen = ctx;
1953+
return gMockClockMs;
1954+
}
1955+
1956+
static void test_fwtpm_clock_sethal(void)
1957+
{
1958+
FWTPM_CTX ctx;
1959+
int rc;
1960+
UINT64 v;
1961+
void* halCtx = (void*)0xC0FFEE;
1962+
1963+
memset(&ctx, 0, sizeof(ctx));
1964+
rc = FWTPM_Init(&ctx);
1965+
AssertIntEQ(rc, 0);
1966+
1967+
/* Register mock clock HAL */
1968+
gMockClockMs = 0x12345678ULL;
1969+
gMockClockCalls = 0;
1970+
gMockClockCtxSeen = NULL;
1971+
rc = FWTPM_Clock_SetHAL(&ctx, mock_clock_get_ms, halCtx);
1972+
AssertIntEQ(rc, 0);
1973+
1974+
/* Verify callback fires. FWTPM_Clock_GetMs returns
1975+
* clockHal.get_ms() + ctx->clockOffset — so verify the relative
1976+
* contribution of the mock, not the absolute value. */
1977+
v = FWTPM_Clock_GetMs(&ctx);
1978+
AssertIntGT(gMockClockCalls, 0);
1979+
AssertTrue(gMockClockCtxSeen == halCtx);
1980+
AssertIntEQ((int)((v - ctx.clockOffset) & 0xFFFFFFFFU), 0x12345678);
1981+
1982+
/* Confirm the HAL is re-read on every call: change mock value,
1983+
* verify next call reflects it. */
1984+
gMockClockMs = 0xABCDEF00ULL;
1985+
v = FWTPM_Clock_GetMs(&ctx);
1986+
AssertIntEQ((int)((v - ctx.clockOffset) & 0xFFFFFFFFU), (int)0xABCDEF00);
1987+
1988+
/* Error path: NULL ctx must be rejected */
1989+
rc = FWTPM_Clock_SetHAL(NULL, mock_clock_get_ms, NULL);
1990+
AssertIntNE(rc, 0);
1991+
1992+
FWTPM_Cleanup(&ctx);
1993+
printf("Test fwTPM:\tClock HAL:\t\t\tPassed\n");
1994+
}
1995+
1996+
/* Mock NV HAL backend: 64 KB byte buffer with per-call counters. */
1997+
#define MOCK_NV_SIZE (64 * 1024)
1998+
static byte gMockNvStore[MOCK_NV_SIZE];
1999+
static int gMockNvReads;
2000+
static int gMockNvWrites;
2001+
static int gMockNvErases;
2002+
2003+
static int mock_nv_read(void* c, word32 off, byte* buf, word32 sz)
2004+
{
2005+
(void)c;
2006+
if ((size_t)off + sz > MOCK_NV_SIZE) {
2007+
return -1;
2008+
}
2009+
memcpy(buf, gMockNvStore + off, sz);
2010+
gMockNvReads++;
2011+
return TPM_RC_SUCCESS;
2012+
}
2013+
static int mock_nv_write(void* c, word32 off, const byte* buf, word32 sz)
2014+
{
2015+
(void)c;
2016+
if ((size_t)off + sz > MOCK_NV_SIZE) {
2017+
return -1;
2018+
}
2019+
memcpy(gMockNvStore + off, buf, sz);
2020+
gMockNvWrites++;
2021+
return TPM_RC_SUCCESS;
2022+
}
2023+
static int mock_nv_erase(void* c, word32 off, word32 sz)
2024+
{
2025+
(void)c;
2026+
if ((size_t)off + sz > MOCK_NV_SIZE) {
2027+
return -1;
2028+
}
2029+
memset(gMockNvStore + off, 0xFF, sz);
2030+
gMockNvErases++;
2031+
return TPM_RC_SUCCESS;
2032+
}
2033+
2034+
/* Register a mock NV HAL before FWTPM_Init and verify that NV writes
2035+
* go to the mock backend rather than the default file. */
2036+
static void test_fwtpm_nv_sethal_mock(void)
2037+
{
2038+
#ifndef FWTPM_NO_NV
2039+
FWTPM_CTX ctx;
2040+
FWTPM_NV_HAL hal;
2041+
int rc;
2042+
2043+
/* Fresh mock store: erased-flash pattern */
2044+
memset(gMockNvStore, 0xFF, sizeof(gMockNvStore));
2045+
gMockNvReads = gMockNvWrites = gMockNvErases = 0;
2046+
2047+
memset(&ctx, 0, sizeof(ctx));
2048+
memset(&hal, 0, sizeof(hal));
2049+
hal.read = mock_nv_read;
2050+
hal.write = mock_nv_write;
2051+
hal.erase = mock_nv_erase;
2052+
hal.ctx = NULL;
2053+
hal.maxSize = MOCK_NV_SIZE;
2054+
2055+
/* SetHAL before Init: FWTPM_Init preserves pre-set HAL */
2056+
rc = FWTPM_NV_SetHAL(&ctx, &hal);
2057+
AssertIntEQ(rc, 0);
2058+
2059+
rc = FWTPM_Init(&ctx);
2060+
AssertIntEQ(rc, 0);
2061+
2062+
/* Fresh init must have written the journal header + seed state via
2063+
* the mock HAL. If this fails, the mock was not wired up. */
2064+
AssertIntGT(gMockNvWrites, 0);
2065+
AssertIntGT(gMockNvReads, 0);
2066+
2067+
/* Error paths */
2068+
rc = FWTPM_NV_SetHAL(NULL, &hal);
2069+
AssertIntNE(rc, 0);
2070+
rc = FWTPM_NV_SetHAL(&ctx, NULL);
2071+
AssertIntNE(rc, 0);
2072+
2073+
FWTPM_Cleanup(&ctx);
2074+
printf("Test fwTPM:\tNV HAL (mock backend):\t\tPassed\n");
2075+
#else
2076+
printf("Test fwTPM:\tNV HAL (mock backend):\t\tSkipped\n");
2077+
#endif
2078+
}
2079+
19402080
/* ================================================================== */
19412081
/* main */
19422082
/* ================================================================== */
@@ -1995,6 +2135,13 @@ int fwtpm_unit_tests(int argc, char *argv[])
19952135
test_fwtpm_readclock();
19962136
test_fwtpm_clock_set();
19972137

2138+
/* HAL registration (clock + NV). The NV HAL test uses a mock
2139+
* backend and must not leave the default file in a half-written
2140+
* state, so remove FWTPM_NV_FILE afterwards. */
2141+
test_fwtpm_clock_sethal();
2142+
test_fwtpm_nv_sethal_mock();
2143+
remove(FWTPM_NV_FILE);
2144+
19982145
/* Key operations */
19992146
#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN)
20002147
test_fwtpm_create_primary_rsa();

0 commit comments

Comments
 (0)