@@ -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