Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ jobs:
repository: wolfssl/wolfssl
path: wolfssl

- name: Build and test refactor
run: cd test-refactor && make clean && make -j WOLFSSL_DIR=../wolfssl && make run

# Build and test standard build
- name: Build and test
run: cd test && make clean && make -j WOLFSSL_DIR=../wolfssl && make run
Expand Down
129 changes: 129 additions & 0 deletions test-refactor/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
## Makefile for wolfHSM test-refactor prototype
## Mirrors test/Makefile conventions with minimal sources

## Project name
BIN = wh_test_refactor

## Important directories
PROJECT_DIR ?= .
CONFIG_DIR ?= $(PROJECT_DIR)/../test/config
WOLFSSL_DIR ?= ../../wolfssl
WOLFHSM_DIR ?= ../
WOLFHSM_PORT_DIR ?= $(WOLFHSM_DIR)/port/posix
TEST_DIR ?= $(WOLFHSM_DIR)/test

BUILD_DIR ?= $(PROJECT_DIR)/Build

# Includes
INC = -I$(PROJECT_DIR) \
-I$(CONFIG_DIR) \
-I$(TEST_DIR) \
-I$(WOLFSSL_DIR) \
-I$(WOLFHSM_DIR) \
-I$(WOLFHSM_PORT_DIR)

# POSIX requires C source be defined before any header
DEF += -D_POSIX_C_SOURCE=200809L

# Library configuration defines for user-supplied settings
DEF += -DWOLFSSL_USER_SETTINGS -DWOLFHSM_CFG

# Enable POSIX test features and server
DEF += -DWOLFHSM_CFG_TEST_POSIX
DEF += -DWOLFHSM_CFG_ENABLE_CLIENT
DEF += -DWOLFHSM_CFG_ENABLE_SERVER

# C standard
CSTD ?= -std=c90

# Compiler flags
CFLAGS_EXTRA = -Werror -Wall -Wextra
CFLAGS_EXTRA += -ffunction-sections -fdata-sections
CFLAGS_EXTRA += -MMD -MP

ARCHFLAGS ?=
CFLAGS ?= $(ARCHFLAGS) $(CSTD) $(CFLAGS_EXTRA)
LDFLAGS ?= $(ARCHFLAGS)

# Dead-strip unused sections
OS_NAME := $(shell uname -s | tr A-Z a-z)
ifeq ($(OS_NAME),darwin)
LDFLAGS += -Wl,-dead_strip
else
LDFLAGS += -Wl,--gc-sections
endif

## Optional flags (same as test/Makefile)

ifeq ($(DEBUG),1)
DBGFLAGS = -ggdb -g3
CFLAGS += $(DBGFLAGS)
LDFLAGS += $(DBGFLAGS)
DEF += -DWOLFHSM_CFG_DEBUG
endif

ifeq ($(DEBUG_VERBOSE),1)
DBGFLAGS = -ggdb -g3
CFLAGS += $(DBGFLAGS)
LDFLAGS += $(DBGFLAGS)
DEF += -DWOLFHSM_CFG_DEBUG -DWOLFHSM_CFG_DEBUG_VERBOSE
endif

ifeq ($(ASAN),1)
CFLAGS += -fsanitize=address
LDFLAGS += -fsanitize=address
endif

## Source files

# wolfCrypt
SRC_C += $(wildcard $(WOLFSSL_DIR)/wolfcrypt/src/*.c)

# wolfSSL TLS (needed by cert manager APIs)
SRC_C += $(wildcard $(WOLFSSL_DIR)/src/*.c)

# wolfHSM library
SRC_C += $(wildcard $(WOLFHSM_DIR)/src/*.c)

# POSIX port (timestamps, flash file, etc.)
SRC_C += $(wildcard $(WOLFHSM_PORT_DIR)/*.c)

# Test-refactor sources (runner, tests, main)
SRC_C += $(wildcard $(PROJECT_DIR)/*.c)


## Build rules

FILENAMES_C = $(notdir $(SRC_C))
OBJS_C = $(addprefix $(BUILD_DIR)/, $(FILENAMES_C:.c=.o))
vpath %.c $(dir $(SRC_C))

.PHONY: build_app clean run

build_app: $(BUILD_DIR) $(BUILD_DIR)/$(BIN).elf
@echo Build complete.

$(BUILD_DIR):
mkdir -p $(BUILD_DIR)

# Workaround: pre-existing warnings in upstream files that
# -Werror promotes to errors.
$(BUILD_DIR)/internal.o: CFLAGS += -Wno-error=implicit-function-declaration
$(BUILD_DIR)/wh_client_crypto.o: CFLAGS += -Wno-error=sign-compare

$(BUILD_DIR)/%.o: %.c
@echo "Compiling: $(notdir $<)"
$(CC) $(CFLAGS) $(DEF) $(INC) -c -o $@ $<

-include $(OBJS_C:.o=.d)

$(BUILD_DIR)/$(BIN).elf: $(OBJS_C)
@echo "Linking: $(notdir $@)"
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)

clean:
@echo "Cleaning build files"
@rm -rf $(BUILD_DIR)

run: build_app
$(BUILD_DIR)/$(BIN).elf
108 changes: 108 additions & 0 deletions test-refactor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# test-refactor

Prototype of the refactored wolfHSM test infrastructure.

## Key differences from test/

- **Runner** (`wh_test_runner.h/c`): generic suite executor.
Each suite is a struct with a name, NULL-terminated test
array, and optional setup/cleanup. `WH_TEST_RUN_SUITE`
macro drives execution from main.
- **Helpers** (`wh_test_helpers.h/c`): portable init/cleanup
for server-only and client-server contexts. Encapsulates
flash, NVM, crypto, transport, and server/client wiring.
- **Transport shim**: simplifies sequential tests. In single-process mode,
a Recv wrapper pumps the server on `NOTREADY` so blocking client APIs
work without manual `HandleRequestMessage` calls or
separate threads.
- **Platform split**: platform-specific code is isolated in two
files (`wh_test_helpers_posix.c`, `wh_test_main.c`).
Test modules are identical on all platforms.

## Suites implemented so far

| Suite | Pattern | Description |
|-------|---------|-------------|
| Flash RamSim | Standalone, no setup | Write-lock, erase, program, verify, blank-check |
| NVM Flash | Standalone, custom setup | Flash unit ops, NVM add/overwrite/destroy/reclaim |
| Cert (Server) | Server helper | Server-side cert add/verify/chain/erase |
| ClientServer | CS helper | Echo round-trip, server info query |
| ThreadSafe Stress | Wrapped existing test | Phased multi-thread contention (unchanged internals) |

## Remaining tests to port

| Suite | Pattern | Description |
|-------|---------|-------------|
| Comm | CS helper | Transport layer (mem, TCP, SHM) |
| Crypto | CS helper | AES, RSA, ECC, CMAC, curve25519, ed25519, etc. |
| Crypto Affinity | CS helper | Device ID operation routing |
| SHE | CS helper | Secure Hardware Extension key load, crypto, secure boot |
| Keywrap | CS helper | Key wrap/unwrap operations |
| Log | Standalone, custom setup | Logging frontend, ringbuf, POSIX file backends |
| Lock | Standalone, custom setup | Lock primitives with POSIX backend |
| DMA | Standalone, custom setup | DMA address translation and allow-list |
| Server Img Mgr | Server helper | Image manager verify/install/erase |
| Timeout | CS helper | POSIX timeout enforcement |
| wolfCrypt Test | CS helper | wolfCrypt test suite via wolfHSM transport |
| MultiClient | Wrap or custom setup | 2 CS pairs, shared NVM, global/local key isolation |

## Platforms requiring update

Each platform with test infrastructure needs a
`wh_test_helpers_<port>.c` and `wh_test_main.c`
implementing the port API (see "Porting" below).

| Platform | Vendor | Test files |
|----------|--------|------------|
| POSIX | wolfSSL | `test-refactor/wh_test_helpers_posix.c` (done) |
| Bernina | STMicro | `bernina-server/src/bh_test.c` |
| SR6 | STMicro | (no test files found) |
| TC3xx | Infineon | `port/client/wolfhsm_tests.c`, `port/server/ccb_tests.c` |
| RH850 F1KM | Renesas | `rh850_test2_1/`, `rh850_test2_2/` |
| PIC32CZ | Microchip | `czhsm-client/tests/`, `czhsm-server/` |
| TDA4VH | TI | (no test files found) |
| New Eagle | Customer | (no test files found) |

## File layout

```
Portable (ships in wolfHSM):
wh_test_runner.h/c - suite runner
wh_test_helpers.h - helper API + config struct
wh_test_helpers.c - helper implementation
wh_test_helpers_port.h - functions each port must implement
wh_test_*.c/h - test modules

Platform-specific (one set per platform):
wh_test_helpers_posix.c - POSIX defaults, transport shim
wh_test_main.c - suite selection, #ifdef gates
Makefile - build rules
```

## Porting to other platforms

1. Implement the two functions declared in
`wh_test_helpers_port.h`:
- `whTestHelper_Server_Init` -- call
`whTestHelper_Server_InitWithConfig` with your flash,
NVM, and transport backends.
- `whTestHelper_CS_Init` -- call
`whTestHelper_CS_InitWithConfig` then
`whTestHelper_CS_AttachClient` with your client
transport. On single-process targets, wrap the client
transport Recv to pump the server on `NOTREADY`
(see `wh_test_helpers_posix.c` for the pattern).
2. Provide a `main()` that calls `WH_TEST_RUN_SUITE` for
each suite, gated by the appropriate `#ifdef`s.
3. Add the portable `.c` files and your port files to your
build system.

See `wh_test_helpers_posix.c` as a reference implementation.

## Build and run (POSIX)

```
make run
make run DEBUG=1
make run THREADSAFE=1 # enables stress test gate
```
129 changes: 129 additions & 0 deletions test-refactor/wh_test_cert.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfHSM.
*
* wolfHSM 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.
*
* wolfHSM 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 wolfHSM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* test-refactor/wh_test_cert.c
*
* Server-side certificate test suite. Exercises the cert
* manager through direct server API calls. Uses the shared
* server helper for setup/cleanup.
*/

#include "wolfhsm/wh_settings.h"

#if defined(WOLFHSM_CFG_CERTIFICATE_MANAGER) \
&& !defined(WOLFHSM_CFG_NO_CRYPTO)

#include "wolfhsm/wh_error.h"
#include "wolfhsm/wh_server.h"
#include "wolfhsm/wh_server_cert.h"

#include "wh_test_common.h"
#include "wh_test_helpers.h"
#include "wh_test_cert.h"
#include "wh_test_cert_data.h"


/*
* Add trusted roots, verify valid and invalid certs/chains,
* then remove roots.
*/
static int test_cert_verify(void* ctx)
{
whServerContext* server =
whTestHelper_Server_GetServer(ctx);
const whNvmId rootA = 1;
const whNvmId rootB = 2;

WH_TEST_RETURN_ON_FAIL(wh_Server_CertInit(server));

/* Add trusted roots */
WH_TEST_RETURN_ON_FAIL(wh_Server_CertAddTrusted(
server, rootA, WH_NVM_ACCESS_ANY,
WH_NVM_FLAGS_NONMODIFIABLE,
NULL, 0, ROOT_A_CERT, ROOT_A_CERT_len));

WH_TEST_RETURN_ON_FAIL(wh_Server_CertAddTrusted(
server, rootB, WH_NVM_ACCESS_ANY,
WH_NVM_FLAGS_NONMODIFIABLE,
NULL, 0, ROOT_B_CERT, ROOT_B_CERT_len));

/* Valid single cert (intermediate against its root) */
WH_TEST_RETURN_ON_FAIL(wh_Server_CertVerify(
server, INTERMEDIATE_A_CERT, INTERMEDIATE_A_CERT_len,
rootA, WH_CERT_FLAGS_NONE,
WH_NVM_FLAGS_USAGE_ANY, NULL));

/* Invalid: leaf without intermediate -- must fail */
WH_TEST_ASSERT_RETURN(
WH_ERROR_CERT_VERIFY == wh_Server_CertVerify(
server, LEAF_A_CERT, LEAF_A_CERT_len,
rootA, WH_CERT_FLAGS_NONE,
WH_NVM_FLAGS_USAGE_ANY, NULL));

/* Invalid: intermediate against wrong root */
WH_TEST_ASSERT_RETURN(
WH_ERROR_CERT_VERIFY == wh_Server_CertVerify(
server, INTERMEDIATE_B_CERT,
INTERMEDIATE_B_CERT_len,
rootA, WH_CERT_FLAGS_NONE,
WH_NVM_FLAGS_USAGE_ANY, NULL));

/* Valid chains */
WH_TEST_RETURN_ON_FAIL(wh_Server_CertVerify(
server, RAW_CERT_CHAIN_A, RAW_CERT_CHAIN_A_len,
rootA, WH_CERT_FLAGS_NONE,
WH_NVM_FLAGS_USAGE_ANY, NULL));

WH_TEST_RETURN_ON_FAIL(wh_Server_CertVerify(
server, RAW_CERT_CHAIN_B, RAW_CERT_CHAIN_B_len,
rootB, WH_CERT_FLAGS_NONE,
WH_NVM_FLAGS_USAGE_ANY, NULL));

/* Cross-chain: must fail */
WH_TEST_ASSERT_RETURN(
WH_ERROR_CERT_VERIFY == wh_Server_CertVerify(
server, RAW_CERT_CHAIN_A, RAW_CERT_CHAIN_A_len,
rootB, WH_CERT_FLAGS_NONE,
WH_NVM_FLAGS_USAGE_ANY, NULL));

WH_TEST_ASSERT_RETURN(
WH_ERROR_CERT_VERIFY == wh_Server_CertVerify(
server, RAW_CERT_CHAIN_B, RAW_CERT_CHAIN_B_len,
rootA, WH_CERT_FLAGS_NONE,
WH_NVM_FLAGS_USAGE_ANY, NULL));

/* Remove trusted roots */
WH_TEST_RETURN_ON_FAIL(
wh_Server_CertEraseTrusted(server, rootA));
WH_TEST_RETURN_ON_FAIL(
wh_Server_CertEraseTrusted(server, rootB));

return 0;
}


static whTestFn _tests[] = {
test_cert_verify,
NULL
};

whTestSuite whTestSuite_Cert =
WH_TEST_SUITE_SERVER("Cert (Server)", _tests);

#endif
Loading
Loading