From d4285b0c370fc639fcdc03d805d157bcfa92e8b1 Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Wed, 11 Mar 2026 17:41:47 -0400 Subject: [PATCH] Implement a generic client and server. Implement wh_Port API --- .../workflows/build-and-run-generic-port.yml | 40 +++ benchmark/wh_bench.c | 10 +- docs/draft/porting.md | 317 ++++++++++++++++++ examples/generic/README.md | 24 ++ examples/generic/wh_generic_client.c | 105 ++++++ examples/generic/wh_generic_server.c | 106 ++++++ port/posix/Makefile | 16 + port/posix/client/Makefile | 133 ++++++++ port/posix/client/user_settings.h | 73 ++++ port/posix/client/wh_posix_client_port.c | 221 ++++++++++++ port/posix/client/wolfhsm_cfg.h | 57 ++++ port/posix/server/Makefile | 117 +++++++ port/posix/server/user_settings.h | 133 ++++++++ port/posix/server/wh_posix_server_port.c | 242 +++++++++++++ port/posix/server/wolfhsm_cfg.h | 67 ++++ port/skeleton/README.md | 9 - port/template/README.md | 21 ++ port/template/client/user_settings.h | 61 ++++ port/template/client/wh_client_port.c | 177 ++++++++++ port/template/client/wolfhsm_cfg.h | 74 ++++ port/template/server/user_settings.h | 99 ++++++ port/template/server/wh_server_port.c | 177 ++++++++++ port/template/server/wolfhsm_cfg.h | 82 +++++ test/wh_test_wolfcrypt_test.c | 6 +- wolfhsm/wh_port.h | 162 +++++++++ 25 files changed, 2515 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/build-and-run-generic-port.yml create mode 100644 docs/draft/porting.md create mode 100644 examples/generic/README.md create mode 100644 examples/generic/wh_generic_client.c create mode 100644 examples/generic/wh_generic_server.c create mode 100644 port/posix/Makefile create mode 100644 port/posix/client/Makefile create mode 100644 port/posix/client/user_settings.h create mode 100644 port/posix/client/wh_posix_client_port.c create mode 100644 port/posix/client/wolfhsm_cfg.h create mode 100644 port/posix/server/Makefile create mode 100644 port/posix/server/user_settings.h create mode 100644 port/posix/server/wh_posix_server_port.c create mode 100644 port/posix/server/wolfhsm_cfg.h delete mode 100644 port/skeleton/README.md create mode 100644 port/template/README.md create mode 100644 port/template/client/user_settings.h create mode 100644 port/template/client/wh_client_port.c create mode 100644 port/template/client/wolfhsm_cfg.h create mode 100644 port/template/server/user_settings.h create mode 100644 port/template/server/wh_server_port.c create mode 100644 port/template/server/wolfhsm_cfg.h create mode 100644 wolfhsm/wh_port.h diff --git a/.github/workflows/build-and-run-generic-port.yml b/.github/workflows/build-and-run-generic-port.yml new file mode 100644 index 000000000..e4456fe0a --- /dev/null +++ b/.github/workflows/build-and-run-generic-port.yml @@ -0,0 +1,40 @@ +name: Build and Run Generic Port + +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + +jobs: + build: + strategy: + matrix: + include: + - name: "Standard" + flags: "" + - name: "ASAN" + flags: "ASAN=1" + - name: "DEBUG" + flags: "DEBUG=1" + - name: "DEBUG ASAN" + flags: "DEBUG=1 ASAN=1" + + runs-on: ubuntu-latest + timeout-minutes: 10 + name: Generic Port (${{ matrix.name }}) + + steps: + - uses: actions/checkout@v4 + + - name: Checkout wolfssl + uses: actions/checkout@v4 + with: + repository: wolfssl/wolfssl + path: wolfssl + + - name: Build generic server + run: cd port/posix/server && make -j ${{ matrix.flags }} WOLFSSL_DIR=../../../wolfssl + + - name: Build generic client + run: cd port/posix/client && make -j ${{ matrix.flags }} WOLFSSL_DIR=../../../wolfssl diff --git a/benchmark/wh_bench.c b/benchmark/wh_bench.c index 12c47e79b..82d3ded1d 100644 --- a/benchmark/wh_bench.c +++ b/benchmark/wh_bench.c @@ -16,6 +16,9 @@ * You should have received a copy of the GNU General Public License * along with wolfHSM. If not, see . */ + +#include "wolfhsm/wh_settings.h" + #include #include /* For memset, memcpy */ @@ -25,7 +28,6 @@ #include /* For sleep */ #endif -#include "wolfhsm/wh_settings.h" #include "wolfhsm/wh_error.h" #include "wolfhsm/wh_comm.h" @@ -751,6 +753,7 @@ typedef struct { int transport; } whBenchClientTaskData; +#if defined(WOLFHSM_CFG_ENABLE_SERVER) && defined(WOLFHSM_CFG_ENABLE_CLIENT) static void* _whBenchClientTask(void* data) { whBenchClientTaskData* taskData = (whBenchClientTaskData*)data; @@ -838,7 +841,8 @@ static void _whBenchClientServerThreadTest(whClientConfig* c_conf, } } -/* Global static variables for transport configurations */ +/* Global static variables for transport configurations (used by + * wh_Bench_ClientServer_Posix which requires both client and server) */ static uint8_t g_mem_req[BUFFER_SIZE] = {0}; static uint8_t g_mem_resp[BUFFER_SIZE] = {0}; static whTransportMemConfig g_mem_tmcf = { @@ -1016,7 +1020,6 @@ static int _configureServerTransport(whBenchTransportType transport, return ret; } - /* transport is the type of transport to use */ int wh_Bench_ClientServer_Posix(int transport, int moduleIndex) { @@ -1131,6 +1134,7 @@ int wh_Bench_ClientServer_Posix(int transport, int moduleIndex) return WH_ERROR_OK; } +#endif /* WOLFHSM_CFG_ENABLE_SERVER && WOLFHSM_CFG_ENABLE_CLIENT */ #endif /* WOLFHSM_CFG_TEST_POSIX */ diff --git a/docs/draft/porting.md b/docs/draft/porting.md new file mode 100644 index 000000000..dc81d4c5c --- /dev/null +++ b/docs/draft/porting.md @@ -0,0 +1,317 @@ +# Porting wolfHSM + +This guide describes how to port wolfHSM to a new platform. A port provides +platform-specific implementations of transport, flash/NVM, and the `wh_Port_*` +generic API so that the platform-independent client and server examples in +`examples/generic/` can run on your hardware. + +The POSIX port in `port/posix/` serves as a reference implementation throughout +this guide. + +## Directory Layout + +A port lives under `port//` and typically has this structure: + +``` +port// +├── Makefile # Top-level: delegates to client/ and server/ +├── .c/h # Platform-specific shared code +├── client/ +│ ├── Makefile +│ ├── wolfhsm_cfg.h # wolfHSM compile-time configuration +│ ├── user_settings.h # wolfSSL compile-time configuration +│ └── wh__client_port.c # wh_Port_* client implementation +└── server/ + ├── Makefile + ├── wolfhsm_cfg.h + ├── user_settings.h + └── wh__server_port.c # wh_Port_* server implementation +``` + +The client and server are built as separate binaries with separate configuration +headers. This separation is important because the client and server typically +have different wolfSSL feature sets, crypto algorithm support, and wolfHSM roles. + +## Step 1: Implement a Transport + +wolfHSM communicates between client and server through a transport layer. You +must provide callback tables that match these interfaces (defined in +`wolfhsm/wh_comm.h`): + +### Client Transport Callbacks + +```c +typedef struct { + int (*Init)(void* context, const void* config, + whCommSetConnectedCb connectcb, void* connectcb_arg); + int (*Send)(void* context, uint16_t size, const void* data); + int (*Recv)(void* context, uint16_t *out_size, void* data); + int (*Cleanup)(void* context); +} whTransportClientCb; +``` + +### Server Transport Callbacks + +```c +typedef struct { + int (*Init)(void* context, const void* config, + whCommSetConnectedCb connectcb, void* connectcb_arg); + int (*Recv)(void* context, uint16_t *out_size, void* data); + int (*Send)(void* context, uint16_t size, const void* data); + int (*Cleanup)(void* context); +} whTransportServerCb; +``` + +### Return Codes + +All transport callbacks must return: + +- `WH_ERROR_OK` (0) — Success. +- `WH_ERROR_BADARGS` — NULL context/config or invalid parameters. +- `WH_ERROR_NOTREADY` — Operation cannot complete yet; caller should retry. +- `WH_ERROR_ABORTED` — Fatal error; caller should clean up. + +### Guidelines + +- `Init` must store the `connectcb` and call it with `WH_COMM_CONNECTED` when + the transport link is established. The generic server loop relies on this + notification to know when a client has connected. +- `Send` and `Recv` should be non-blocking. Return `WH_ERROR_NOTREADY` if the + operation cannot complete immediately. +- Transport implementations typically define a macro (e.g. `PTT_CLIENT_CB`, + `PTT_SERVER_CB`) that expands to the callback table initializer. + +See `port/posix/posix_transport_tcp.c` for a TCP socket-based reference +implementation. + +wolfHSM also provides a shared memory transport (`wh_transport_mem`) that uses a +shared memory region containing request and response buffers plus an optional DMA +block. One side creates the shared region; the other maps it by name or address. +The DMA region allows the client to use DMA-style requests by setting its DMA +base address to the mapped address of the shared block. This transport is well +suited for platforms where client and server share an address space or have +hardware-mapped shared memory (e.g. dual-core HSM designs). + +## Step 2: Implement Flash and NVM (Server Only) + +The server requires a flash backend for NVM storage. Implement the `whFlashCb` +callback table defined in `wolfhsm/wh_flash.h`: + +```c +typedef struct { + int (*Init)(void* context, const void* config); + int (*Cleanup)(void* context); + uint32_t (*PartitionSize)(void* context); + int (*WriteLock)(void* context, uint32_t offset, uint32_t size); + int (*WriteUnlock)(void* context, uint32_t offset, uint32_t size); + int (*Read)(void* context, uint32_t offset, uint32_t size, uint8_t* data); + int (*Program)(void* context, uint32_t offset, uint32_t size, + const uint8_t* data); + int (*Erase)(void* context, uint32_t offset, uint32_t size); + int (*Verify)(void* context, uint32_t offset, uint32_t size, + const uint8_t* data); + int (*BlankCheck)(void* context, uint32_t offset, uint32_t size); +} whFlashCb; +``` + +For development and testing, wolfHSM provides `wh_flash_ramsim` — a RAM-based +flash simulator that can be used on any platform. The POSIX server port uses +this. For production, you will typically implement callbacks that talk to your +platform's actual flash hardware. + +The flash backend is wired into NVM through `whNvmFlashConfig` and +`whNvmFlashContext`, then into the server via `whNvmConfig`. See +`port/posix/server/wh_posix_server_port.c` (`wh_Port_ConfigureServer`) for the +full wiring example. + +## Step 3: Implement the wh_Port_* API + +The `wh_Port_*` functions (declared in `wolfhsm/wh_port.h`) are the glue +between the generic examples and your platform. You implement them in your +port's `wh__client_port.c` and `wh__server_port.c`. + +### Common Functions + +```c +int wh_Port_InitBoard(void); +``` + +Called once at startup. Initialize any shared platform resources: crypto +libraries, IPC mechanisms, signal handlers, or hardware peripherals. + +```c +int wh_Port_CleanupBoard(void); +``` + +Called at shutdown. Release resources allocated by `InitBoard`. + +### Client Functions + +```c +int wh_Port_ConfigureClient(whClientConfig* clientCfg); +``` + +Populate `clientCfg` with transport callbacks, transport context/config, client +ID, and optionally a connect callback. The transport context and configuration +structures must be statically allocated (they must outlive the client). + +```c +int wh_Port_InitClient(whClientConfig* clientCfg, whClientContext* clientCtx); +``` + +Initialize the client context and establish communication. Typically calls +`wh_Client_Init()` followed by `wh_Client_CommInit()`. + +```c +int wh_Port_RunClient(whClientContext* clientCtx); +``` + +Execute the client workload. This is where your application logic goes — echo +requests, key operations, crypto operations, etc. Should call +`wh_Client_CommClose()` and `wh_Client_Cleanup()` before returning. + +### Server Functions + +```c +int wh_Port_ConfigureServer(size_t instance, whServerConfig* serverCfg); +``` + +Populate `serverCfg` with transport, NVM, and crypto configuration for the given +server instance. The `instance` parameter supports multiple server instances +(e.g. serving multiple clients concurrently). + +```c +int wh_Port_InitServer(size_t instance, whServerConfig* serverCfg, + whServerContext* serverCtx); +``` + +Initialize a server instance. Typically calls `wh_Server_Init()`. + +```c +int wh_Port_CleanupServer(size_t instance, whServerContext* serverCtx); +``` + +Clean up a server instance. Typically calls `wh_Server_Cleanup()`. + +```c +int wh_Port_ClientConnected(size_t instance); +int wh_Port_ClientDisconnected(size_t instance); +``` + +Polling functions that return 1 **once** when a client connects or disconnects +from the given server instance, and 0 otherwise. The generic server loop uses +these to decide when to initialize or tear down server instances. + +How you implement the notification mechanism is platform-specific. The POSIX port +uses a named FIFO: the client's `connect_cb` writes a byte to the FIFO on +connect/disconnect, and the server reads from it in these polling functions. +Other ports might use shared memory flags, hardware interrupts, or mailbox +registers. + +## Step 4: Create Configuration Headers + +### wolfhsm_cfg.h + +This header defines wolfHSM compile-time options. It must be on the include path +before any wolfHSM headers are included (achieved by putting the project +directory first in `-I` flags). + +**Required defines:** + +| Define | Description | +|--------|-------------| +| `WOLFHSM_CFG_ENABLE_CLIENT` | Enable client functionality (client build) | +| `WOLFHSM_CFG_ENABLE_SERVER` | Enable server functionality (server build) | +| `WOLFHSM_CFG_COMM_DATA_LEN` | Max comm payload size in bytes | +| `WOLFHSM_CFG_NVM_OBJECT_COUNT` | Max NVM objects (must match client and server) | + +**Port-specific defines** (naming convention: `WOLFHSM_CFG_PORT_*`): + +| Define | Description | +|--------|-------------| +| `WOLFHSM_CFG_PORT_GETTIME` | Function returning current time in microseconds (`uint64_t`) | +| `WOLFHSM_CFG_PORT_CLIENT_ID` | Client identifier byte | +| `WOLFHSM_CFG_PORT_SERVER_ID` | Server identifier byte | +| `WOLFHSM_CFG_PORT_SERVER_COUNT` | Number of server instances | + +You may define additional `WOLFHSM_CFG_PORT_*` macros for your platform's +transport configuration (IP addresses, ports, memory regions, etc.). + +**Server-specific defines** (see `wolfhsm/wh_settings.h` for full list): + +| Define | Description | +|--------|-------------| +| `WOLFHSM_CFG_SERVER_KEYCACHE_COUNT` | Number of key cache slots | +| `WOLFHSM_CFG_SERVER_KEYCACHE_SIZE` | Size of each key cache slot | +| `WOLFHSM_CFG_SERVER_DMAADDR_COUNT` | Number of DMA address entries | +| `WOLFHSM_CFG_SERVER_CUSTOMCB_COUNT` | Number of custom callback slots | + +**Optional test/benchmark defines:** + +| Define | Description | +|--------|-------------| +| `WOLFHSM_CFG_PORT_ENABLE_WOLFHSM_TESTS` | Build and run wolfHSM tests | +| `WOLFHSM_CFG_PORT_ENABLE_BENCHMARK` | Build and run benchmarks | +| `WOLFHSM_CFG_TEST_POSIX` | Enable POSIX-specific test infrastructure | +| `WOLFHSM_CFG_TEST_CLIENT_ONLY` | Suppress combined client+server test code | + +### user_settings.h + +This header defines wolfSSL compile-time options. Both client and server need +one, but they will differ. + +**Common required defines:** + +```c +#define WOLF_CRYPTO_CB /* CryptoCB support */ +#define WOLFSSL_KEY_GEN /* Key DER export/import */ +#define WOLFSSL_ASN_TEMPLATE /* ASN.1 template support */ +#define WOLFSSL_BASE64_ENCODE /* Base64 encoding */ +#define HAVE_ANONYMOUS_INLINE_AGGREGATES 1 +#define NO_INLINE /* C90 compatibility */ +#define TFM_TIMING_RESISTANT /* Side-channel resistance */ +#define ECC_TIMING_RESISTANT +#define WC_RSA_BLINDING +``` + +Then enable the crypto algorithms your application needs (`HAVE_ECC`, +`HAVE_AESGCM`, `HAVE_CURVE25519`, etc.). + +**Important:** `WOLFHSM_CFG_NVM_OBJECT_COUNT` and `WOLFHSM_CFG_COMM_DATA_LEN` +must have the same values in both client and server configurations. Mismatches +cause runtime failures. + +## Step 5: Create the Build System + +Your Makefile needs to: + +1. Put the project directory (containing `wolfhsm_cfg.h` and `user_settings.h`) + **first** on the include path. +2. Define `-DWOLFSSL_USER_SETTINGS -DWOLFHSM_CFG` so the libraries pick up your + configuration headers. +3. Compile and link: + - wolfSSL/wolfCrypt sources (unless building without crypto) + - wolfHSM sources from `src/` + - Your port's shared code + - Your port's `wh_Port_*` implementation + - The generic entry point (`examples/generic/wh_generic_client.c` or + `wh_generic_server.c`) + - Test and benchmark sources if enabled + +See `port/posix/client/Makefile` for a complete example. + +## Checklist + +- [ ] Transport callbacks implemented (Init, Send, Recv, Cleanup) +- [ ] Flash callbacks implemented (or using `wh_flash_ramsim` for development) +- [ ] `wh_Port_InitBoard` / `wh_Port_CleanupBoard` implemented for both sides +- [ ] `wh_Port_ConfigureClient` / `wh_Port_InitClient` / `wh_Port_RunClient` + implemented +- [ ] `wh_Port_ConfigureServer` / `wh_Port_InitServer` / `wh_Port_CleanupServer` + implemented +- [ ] `wh_Port_ClientConnected` / `wh_Port_ClientDisconnected` implemented +- [ ] `wolfhsm_cfg.h` created for client and server with matching + `WOLFHSM_CFG_COMM_DATA_LEN` and `WOLFHSM_CFG_NVM_OBJECT_COUNT` +- [ ] `user_settings.h` created for client and server +- [ ] Build system compiles and links both binaries +- [ ] Client can connect, send echo requests, and disconnect cleanly diff --git a/examples/generic/README.md b/examples/generic/README.md new file mode 100644 index 000000000..81d73de61 --- /dev/null +++ b/examples/generic/README.md @@ -0,0 +1,24 @@ +# Generic Examples + +Generic client and server entry points that use the `wh_Port_*` abstraction API +defined in `wolfhsm/wh_port.h`. These examples are platform-independent and +rely on a port implementation (e.g. `port/posix/`) to provide the concrete +transport, NVM, and crypto configuration. + +## Files + +- `wh_generic_client.c` - Client entry point. Optionally runs wolfHSM tests and + benchmarks, then connects to the server and executes echo requests. +- `wh_generic_server.c` - Server entry point. Listens for client connections and + handles request messages in a polling loop. + +## Building + +These files are not built directly. Each port provides its own Makefile that +compiles the generic examples together with the port-specific `wh_Port_*` +implementation. For example: + +``` +cd port/posix +make +``` diff --git a/examples/generic/wh_generic_client.c b/examples/generic/wh_generic_client.c new file mode 100644 index 000000000..08df2a9a8 --- /dev/null +++ b/examples/generic/wh_generic_client.c @@ -0,0 +1,105 @@ +/* + * 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 . + */ +/* + * examples/generic/wh_generic_client.c + * + * Generic client entry point using the wh_Port_* abstraction API. + */ + +#include "wolfhsm/wh_settings.h" +#include "wolfhsm/wh_client.h" +#include "wolfhsm/wh_port.h" + +#ifdef WOLFHSM_CFG_PORT_ENABLE_WOLFHSM_TESTS +#include "test/wh_test.h" +#endif /* WOLFHSM_CFG_PORT_ENABLE_WOLFHSM_TESTS */ + +#ifdef WOLFHSM_CFG_PORT_ENABLE_BENCHMARK +#include "benchmark/wh_bench.h" +#endif /* WOLFHSM_CFG_PORT_ENABLE_BENCHMARK */ + +int main(void) +{ + int err; + whClientConfig clientCfg; + whClientContext clientCtx; + + WOLFHSM_CFG_PRINTF("Starting generic client...\n"); + + err = wh_Port_InitBoard(); + if (err) { + WOLFHSM_CFG_PRINTF("wh_Port_InitBoard failed: %d\n", err); + goto loop; + } + + err = wh_Port_ConfigureClient(&clientCfg); + if (err) { + WOLFHSM_CFG_PRINTF("wh_Port_ConfigureClient failed: %d\n", err); + goto loop; + } + +#ifdef WOLFHSM_CFG_PORT_ENABLE_WOLFHSM_TESTS + + WOLFHSM_CFG_PRINTF("\n========== CLIENT TESTS ==========\n\n"); + err = whTest_ClientConfig(&clientCfg); + if (err) { + WOLFHSM_CFG_PRINTF("whTest_ClientConfig failed: %d\n", err); + goto loop; + } + +#endif /* WOLFHSM_CFG_PORT_ENABLE_WOLFHSM_TESTS */ + +#ifdef WOLFHSM_CFG_PORT_ENABLE_BENCHMARK + + WOLFHSM_CFG_PRINTF("\n========== BENCHMARKS ==========\n\n"); + err = wh_Bench_ClientCfg(&clientCfg, WOLFHSM_CFG_PORT_BENCH_TRANSPORT); + if (err) { + WOLFHSM_CFG_PRINTF("wh_Bench_ClientCfg failed: %d\n", err); + goto loop; + } + +#endif /* WOLFHSM_CFG_PORT_ENABLE_BENCHMARK */ + + WOLFHSM_CFG_PRINTF("Connecting to server...\n"); + err = wh_Port_InitClient(&clientCfg, &clientCtx); + if (err) { + WOLFHSM_CFG_PRINTF("wh_Port_InitClient failed: %d\n", err); + goto loop; + } + WOLFHSM_CFG_PRINTF("Client initialized\n"); + + WOLFHSM_CFG_PRINTF("Running client...\n"); + err = wh_Port_RunClient(&clientCtx); + if (err) { + WOLFHSM_CFG_PRINTF("wh_Port_RunClient failed: %d\n", err); + } + + err = wh_Port_CleanupClient(&clientCtx); + if (err) { + WOLFHSM_CFG_PRINTF("wh_Port_CleanupClient failed: %d\n", err); + } + + WOLFHSM_CFG_PRINTF("Client finished\n"); + wh_Port_CleanupBoard(); + +loop: + while (1); + + return 0; +} diff --git a/examples/generic/wh_generic_server.c b/examples/generic/wh_generic_server.c new file mode 100644 index 000000000..b59eefd09 --- /dev/null +++ b/examples/generic/wh_generic_server.c @@ -0,0 +1,106 @@ +/* + * 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 . + */ +/* + * examples/generic/wh_generic_server.c + * + * Generic server entry point using the wh_Port_* abstraction API. + */ + +#include "wolfhsm/wh_settings.h" +#include "wolfhsm/wh_server.h" +#include "wolfhsm/wh_port.h" + +int main(void) +{ + int err; + int isConnected[WOLFHSM_CFG_PORT_SERVER_COUNT] = {0}; + whServerContext serverCtx[WOLFHSM_CFG_PORT_SERVER_COUNT]; + whServerConfig serverCfg[WOLFHSM_CFG_PORT_SERVER_COUNT]; + + WOLFHSM_CFG_PRINTF("Starting generic server...\n"); + + err = wh_Port_InitBoard(); + if (err) { + WOLFHSM_CFG_PRINTF("wh_Port_InitBoard failed: %d\n", err); + goto loop; + } + + for (size_t i = 0; i < WOLFHSM_CFG_PORT_SERVER_COUNT; ++i) { + err = wh_Port_ConfigureServer(i, &serverCfg[i]); + if (err) { + WOLFHSM_CFG_PRINTF("wh_Port_ConfigureServer(%zu) failed: %d\n", i, + err); + goto loop; + } + } + + WOLFHSM_CFG_PRINTF("Server configured, waiting for connections...\n"); + + while (1) { + for (size_t i = 0; i < WOLFHSM_CFG_PORT_SERVER_COUNT; ++i) { + if (!isConnected[i]) { + if (wh_Port_ClientConnected(i)) { + err = wh_Port_InitServer(i, &serverCfg[i], &serverCtx[i]); + if (err) { + WOLFHSM_CFG_PRINTF( + "wh_Port_InitServer(%zu) failed: %d\n", i, err); + goto loop; + } + + err = wh_Server_SetConnected(&serverCtx[i], + WH_COMM_CONNECTED); + if (err) { + WOLFHSM_CFG_PRINTF( + "wh_Server_SetConnected(%zu) failed: %d\n", i, err); + goto loop; + } + isConnected[i] = 1; + WOLFHSM_CFG_PRINTF("Client connected on instance %zu\n", i); + } + } + else { + if (wh_Port_ClientDisconnected(i)) { + WOLFHSM_CFG_PRINTF("Client disconnected on instance %zu\n", + i); + err = wh_Port_CleanupServer(i, &serverCtx[i]); + if (err) { + WOLFHSM_CFG_PRINTF( + "wh_Port_CleanupServer(%zu) failed: %d\n", i, err); + goto loop; + } + isConnected[i] = 0; + } + else { + err = wh_Server_HandleRequestMessage(&serverCtx[i]); + if (err != WH_ERROR_OK && err != WH_ERROR_NOTREADY) { + WOLFHSM_CFG_PRINTF( + "wh_Server_HandleRequestMessage(%zu) failed: " + "%d\n", + i, err); + goto loop; + } + } + } + } + } + +loop: + while (1) + ; +} diff --git a/port/posix/Makefile b/port/posix/Makefile new file mode 100644 index 000000000..6d8d1f78f --- /dev/null +++ b/port/posix/Makefile @@ -0,0 +1,16 @@ +## Makefile for building the generic wolfHSM client and server +## using the POSIX port implementation. + +.PHONY: all client server clean + +all: client server + +client: + $(MAKE) -C client build_app + +server: + $(MAKE) -C server build_app + +clean: + $(MAKE) -C client clean + $(MAKE) -C server clean diff --git a/port/posix/client/Makefile b/port/posix/client/Makefile new file mode 100644 index 000000000..633f4e1c3 --- /dev/null +++ b/port/posix/client/Makefile @@ -0,0 +1,133 @@ +## Makefile for wolfHSM generic client using POSIX port + +BIN = client + +## Important directories +PROJECT_DIR ?= . +WOLFSSL_DIR ?= ../../../../wolfssl +WOLFHSM_DIR ?= ../../../ +PORT_DIR ?= ../ +GENERIC_DIR ?= $(WOLFHSM_DIR)/examples/generic + +BUILD_DIR ?= $(PROJECT_DIR)/Build + +# Includes (project dir first for wolfhsm_cfg.h / user_settings.h) +INC = -I$(PROJECT_DIR) \ + -I$(WOLFSSL_DIR) \ + -I$(WOLFHSM_DIR) \ + -I$(WOLFHSM_DIR)/test \ + -I$(WOLFHSM_DIR)/benchmark \ + -I$(WOLFHSM_DIR)/benchmark/bench_modules \ + -I$(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 + +ARCHFLAGS ?= +CFLAGS_EXTRA ?= -Werror -Wall -Wextra -ffunction-sections -fdata-sections -g +CSTD ?= -std=c99 +CFLAGS ?= $(ARCHFLAGS) $(CSTD) $(CFLAGS_EXTRA) +LDFLAGS ?= $(ARCHFLAGS) + +OS_NAME := $(shell uname -s | tr A-Z a-z) +ifeq ($(OS_NAME),darwin) + LDFLAGS += -Wl,-dead_strip +else + LDFLAGS += -Wl,--gc-sections +endif + +LIBS = -lc -lm +CMD_ECHO ?= + +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 +SRC_C = + +ifneq ($(NOCRYPTO),1) +SRC_C += $(wildcard $(WOLFSSL_DIR)/wolfcrypt/src/*.c) +SRC_C += $(wildcard $(WOLFSSL_DIR)/wolfcrypt/test/*.c) +SRC_C += $(wildcard $(WOLFSSL_DIR)/wolfcrypt/benchmark/*.c) +SRC_C += $(wildcard $(WOLFSSL_DIR)/src/*.c) +DEF += -DWC_USE_DEVID=0x5748534D +else +DEF += -DWOLFHSM_CFG_NO_CRYPTO +endif + +# wolfHSM source files +SRC_C += $(wildcard $(WOLFHSM_DIR)/src/*.c) + +# POSIX port shared code +SRC_C += $(wildcard $(PORT_DIR)/*.c) + +# Port client implementation (wh_Port_* functions) +SRC_C += $(PROJECT_DIR)/wh_posix_client_port.c + +# wolfHSM test sources +SRC_C += $(wildcard $(WOLFHSM_DIR)/test/*.c) + +# wolfHSM benchmark sources +SRC_C += $(WOLFHSM_DIR)/benchmark/wh_bench.c +SRC_C += $(WOLFHSM_DIR)/benchmark/wh_bench_data.c +SRC_C += $(WOLFHSM_DIR)/benchmark/wh_bench_ops.c +SRC_C += $(wildcard $(WOLFHSM_DIR)/benchmark/bench_modules/*.c) + +# Generic client entry point +SRC_C += $(GENERIC_DIR)/wh_generic_client.c + +## Object files in Build directory +OBJS_C = $(addprefix $(BUILD_DIR)/, $(notdir $(SRC_C:.c=.o))) + +## Compile rule: find source by trying each source directory +COMPILE = $(CC) $(CFLAGS) $(DEF) $(INC) -c -o $@ $< + +# Collect unique source directories +SRC_DIRS = $(sort $(dir $(SRC_C))) + +# Generate a pattern rule for each source directory +define COMPILE_RULE +$(BUILD_DIR)/%.o: $(1)%.c | $(BUILD_DIR) + @echo "Compiling: $$(notdir $$<)" + $$(CMD_ECHO) $$(COMPILE) +endef + +$(foreach dir,$(SRC_DIRS),$(eval $(call COMPILE_RULE,$(dir)))) + +## Makefile Targets + +.PHONY: build_app clean + +build_app: | $(BUILD_DIR) +build_app: $(BUILD_DIR)/$(BIN).elf + @echo Build complete. + +$(BUILD_DIR)/$(BIN).elf: $(OBJS_C) | $(BUILD_DIR) + @echo "Linking: $(notdir $@)" + $(CMD_ECHO) $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +$(BUILD_DIR): + $(CMD_ECHO) mkdir -p $(BUILD_DIR) + +clean: + @echo "Cleaning build files" + @rm -rf $(BUILD_DIR) diff --git a/port/posix/client/user_settings.h b/port/posix/client/user_settings.h new file mode 100644 index 000000000..42b8bf937 --- /dev/null +++ b/port/posix/client/user_settings.h @@ -0,0 +1,73 @@ +/* + * 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 . + */ +/* + * port/posix/client/user_settings.h + * + * wolfSSL compile-time options for the POSIX generic client. + */ + +#ifndef USER_SETTINGS_H_ +#define USER_SETTINGS_H_ + +/** wolfHSM Client required settings */ + +/* CryptoCB support */ +#define WOLF_CRYPTO_CB +#define HAVE_ANONYMOUS_INLINE_AGGREGATES 1 + +/* Key DER export/import support */ +#define WOLFSSL_KEY_GEN +#define WOLFSSL_ASN_TEMPLATE +#define WOLFSSL_BASE64_ENCODE + +/* C90 compatibility, which doesn't support inline keyword */ +#define NO_INLINE +/* Suppresses warning in evp.c */ +#define WOLFSSL_IGNORE_FILE_WARN + +/* Either NO_HARDEN or set resistance and blinding */ +#define TFM_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT +#define WC_RSA_BLINDING + +/** Application Settings */ + +/* Crypto Algo Options */ +#define HAVE_CURVE25519 +#define HAVE_ECC +#define HAVE_AES_CBC +#define WOLFSSL_AES_COUNTER +#define HAVE_AESGCM +#define WOLFSSL_AES_DIRECT +#define WOLFSSL_CMAC +#define HAVE_HKDF + +/* Disable PKCS12 (not needed for HSM operations) */ +#define NO_PKCS12 + +/* wolfCrypt test/benchmark settings */ +#define NO_MAIN_DRIVER +#define NO_FILESYSTEM + +/* Include to ensure clock_gettime is declared for benchmark.c */ +#include +/* Include to support strcasecmp with POSIX build */ +#include + +#endif /* USER_SETTINGS_H_ */ diff --git a/port/posix/client/wh_posix_client_port.c b/port/posix/client/wh_posix_client_port.c new file mode 100644 index 000000000..6bec519ec --- /dev/null +++ b/port/posix/client/wh_posix_client_port.c @@ -0,0 +1,221 @@ +/* + * 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 . + */ +/* + * port/posix/client/wh_posix_client_port.c + * + * POSIX client implementation of the wh_Port_* generic port API. + * Uses TCP transport. Configuration is provided through WOLFHSM_CFG_PORT_* + * defines which must be set by the application (e.g. via a config header). + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wolfhsm/wh_settings.h" +#include "wolfhsm/wh_error.h" +#include "wolfhsm/wh_comm.h" +#include "wolfhsm/wh_client.h" +#include "wolfhsm/wh_port.h" + +#include "port/posix/posix_transport_tcp.h" + +/* Transport context and configuration - must persist for lifetime of client */ +static posixTransportTcpClientContext tcpClientCtx; +static posixTransportTcpConfig tcpConfig; +static whCommClientConfig commConfig; +static whTransportClientCb tcpCb = PTT_CLIENT_CB; + +/* Notification FIFO fd — opened once and kept open */ +static int notifyFd = -1; + +int wh_Port_InitBoard(void) +{ + /* Create the FIFO if it doesn't exist (EEXIST is OK) */ + if (mkfifo(WOLFHSM_CFG_PORT_NOTIFY_PATH, 0666) != 0 && errno != EEXIST) { + return WH_ERROR_ABORTED; + } + + /* O_RDWR avoids blocking when no reader is open yet */ + notifyFd = open(WOLFHSM_CFG_PORT_NOTIFY_PATH, O_RDWR | O_NONBLOCK); + if (notifyFd < 0) { + return WH_ERROR_ABORTED; + } + + return WH_ERROR_OK; +} + +int wh_Port_CleanupBoard(void) +{ + if (notifyFd >= 0) { + if (close(notifyFd) != 0) { + return WH_ERROR_ABORTED; + } + notifyFd = -1; + } + + return WH_ERROR_OK; +} + +static int connectCb(void* context, whCommConnected connected) +{ + uint8_t msg; + + (void)context; + + if (notifyFd < 0) { + return WH_ERROR_ABORTED; + } + + msg = (connected == WH_COMM_CONNECTED) ? 1 : 0; + if (write(notifyFd, &msg, 1) != 1) { + return WH_ERROR_ABORTED; + } + + return WH_ERROR_OK; +} + +int wh_Port_ConfigureClient(whClientConfig* clientCfg) +{ + if (clientCfg == NULL) { + return WH_ERROR_BADARGS; + } + + memset(&tcpClientCtx, 0, sizeof(tcpClientCtx)); + memset(&commConfig, 0, sizeof(commConfig)); + + tcpConfig.server_ip_string = WOLFHSM_CFG_PORT_TCP_IPSTRING; + tcpConfig.server_port = WOLFHSM_CFG_PORT_TCP_PORT; + + commConfig.transport_cb = &tcpCb; + commConfig.transport_context = (void*)&tcpClientCtx; + commConfig.transport_config = (void*)&tcpConfig; + commConfig.client_id = WOLFHSM_CFG_PORT_CLIENT_ID; + commConfig.connect_cb = connectCb; + + clientCfg->comm = &commConfig; + + return WH_ERROR_OK; +} + +int wh_Port_InitClient(whClientConfig* clientCfg, whClientContext* clientCtx) +{ + int ret; + + if (clientCfg == NULL || clientCtx == NULL) { + return WH_ERROR_BADARGS; + } + + ret = wh_Client_Init(clientCtx, clientCfg); + if (ret != WH_ERROR_OK) { + return ret; + } + + ret = wh_Client_CommInit(clientCtx, NULL, NULL); + if (ret != WH_ERROR_OK) { + (void)wh_Client_Cleanup(clientCtx); + return ret; + } + + return WH_ERROR_OK; +} + +static void sleepMs(long milliseconds) +{ + struct timespec req; + req.tv_sec = milliseconds / 1000; + req.tv_nsec = (milliseconds % 1000) * 1000000; + nanosleep(&req, NULL); +} + +int wh_Port_RunClient(whClientContext* clientCtx) +{ + int ret; + int counter; + uint8_t tx_req[32] = {0}; + uint16_t tx_req_len = 0; + uint8_t rx_resp[64] = {0}; + uint16_t rx_resp_len = 0; + + if (clientCtx == NULL) { + return WH_ERROR_BADARGS; + } + + WOLFHSM_CFG_PRINTF("Client connected, sending echo requests...\n"); + + for (counter = 0; counter < 20; counter++) { + sprintf((char*)tx_req, "Request:%u", counter); + tx_req_len = strlen((char*)tx_req); + + do { + ret = wh_Client_EchoRequest(clientCtx, tx_req_len, tx_req); + if (ret == WH_ERROR_NOTREADY) { + sleepMs(1); + } + } while (ret == WH_ERROR_NOTREADY); + + if (ret != WH_ERROR_OK) { + WOLFHSM_CFG_PRINTF("EchoRequest failed: %d\n", ret); + break; + } + + rx_resp_len = 0; + memset(rx_resp, 0, sizeof(rx_resp)); + + do { + ret = wh_Client_EchoResponse(clientCtx, &rx_resp_len, rx_resp); + if (ret == WH_ERROR_NOTREADY) { + sleepMs(1); + } + } while (ret == WH_ERROR_NOTREADY); + + if (ret != WH_ERROR_OK) { + WOLFHSM_CFG_PRINTF("EchoResponse failed: %d\n", ret); + break; + } + } + + return ret; +} + +int wh_Port_CleanupClient(whClientContext* clientCtx) +{ + int ret; + + if (clientCtx == NULL) { + return WH_ERROR_BADARGS; + } + + ret = wh_Client_CommClose(clientCtx); + if (ret != WH_ERROR_OK) { + return ret; + } + + ret = wh_Client_Cleanup(clientCtx); + if (ret != WH_ERROR_OK) { + return ret; + } + + return WH_ERROR_OK; +} diff --git a/port/posix/client/wolfhsm_cfg.h b/port/posix/client/wolfhsm_cfg.h new file mode 100644 index 000000000..16ced9809 --- /dev/null +++ b/port/posix/client/wolfhsm_cfg.h @@ -0,0 +1,57 @@ +/* + * 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 . + */ +/* + * port/posix/client/wolfhsm_cfg.h + * + * wolfHSM compile-time options for the POSIX generic client. + */ + +#ifndef WOLFHSM_CFG_H_ +#define WOLFHSM_CFG_H_ + +#include "port/posix/posix_time.h" + +#define WOLFHSM_CFG_PORT_GETTIME posixGetTime + +/** Port configuration */ +#define WOLFHSM_CFG_PORT_CLIENT_ID 12 +#define WOLFHSM_CFG_PORT_TCP_PORT 23456 +#define WOLFHSM_CFG_PORT_TCP_IPSTRING "127.0.0.1" +#define WOLFHSM_CFG_PORT_NOTIFY_PATH "/tmp/wolfhsm_notify" + +/** wolfHSM settings */ +#define WOLFHSM_CFG_ENABLE_CLIENT +#define WOLFHSM_CFG_PORT_ENABLE_WOLFHSM_TESTS +#define WOLFHSM_CFG_TEST_WOLFCRYPTTEST +#define WOLFHSM_CFG_TEST_UNIT_NO_MAIN +#define WOLFHSM_CFG_TEST_POSIX +#define WOLFHSM_CFG_TEST_CLIENT_ONLY +#define WOLFHSM_CFG_PORT_ENABLE_BENCHMARK +#define WOLFHSM_CFG_BENCH_ENABLE +#include "benchmark/wh_bench_ops.h" +#define WOLFHSM_CFG_PORT_BENCH_TRANSPORT WH_BENCH_TRANSPORT_POSIX_TCP +#define WOLFHSM_CFG_COMM_DATA_LEN 5000 +#define WOLFHSM_CFG_NVM_OBJECT_COUNT 30 + +#ifndef WOLFHSM_CFG_NO_CRYPTO +#define WOLFHSM_CFG_KEYWRAP +#define WOLFHSM_CFG_GLOBAL_KEYS +#endif + +#endif /* WOLFHSM_CFG_H_ */ diff --git a/port/posix/server/Makefile b/port/posix/server/Makefile new file mode 100644 index 000000000..f5103493b --- /dev/null +++ b/port/posix/server/Makefile @@ -0,0 +1,117 @@ +## Makefile for wolfHSM generic server using POSIX port + +BIN = server + +## Important directories +PROJECT_DIR ?= . +WOLFSSL_DIR ?= ../../../../wolfssl +WOLFHSM_DIR ?= ../../../ +PORT_DIR ?= ../ +GENERIC_DIR ?= $(WOLFHSM_DIR)/examples/generic + +BUILD_DIR ?= $(PROJECT_DIR)/Build + +# Includes (project dir first for wolfhsm_cfg.h / user_settings.h) +INC = -I$(PROJECT_DIR) \ + -I$(WOLFSSL_DIR) \ + -I$(WOLFHSM_DIR) \ + -I$(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 + +ARCHFLAGS ?= +CFLAGS_EXTRA ?= -Wextra -g +CFLAGS ?= $(ARCHFLAGS) -Wno-cpp -std=c99 -Wall -Werror $(CFLAGS_EXTRA) +LDFLAGS ?= $(ARCHFLAGS) + +OS_NAME := $(shell uname -s | tr A-Z a-z) +ifeq ($(OS_NAME),darwin) + LDFLAGS += -Wl,-dead_strip +else + LDFLAGS += -Wl,--gc-sections +endif + +LIBS = -lc -lm +CMD_ECHO ?= + +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 +SRC_C = + +ifneq ($(NOCRYPTO),1) +SRC_C += $(wildcard $(WOLFSSL_DIR)/wolfcrypt/src/*.c) +SRC_C += $(wildcard $(WOLFSSL_DIR)/src/*.c) +else +DEF += -DWOLFHSM_CFG_NO_CRYPTO +endif + +# wolfHSM source files +SRC_C += $(wildcard $(WOLFHSM_DIR)/src/*.c) + +# POSIX port shared code +SRC_C += $(wildcard $(PORT_DIR)/*.c) + +# Port server implementation (wh_Port_* functions) +SRC_C += $(PROJECT_DIR)/wh_posix_server_port.c + +# Generic server entry point +SRC_C += $(GENERIC_DIR)/wh_generic_server.c + +## Object files in Build directory +OBJS_C = $(addprefix $(BUILD_DIR)/, $(notdir $(SRC_C:.c=.o))) + +## Compile rule: find source by trying each source directory +COMPILE = $(CC) $(CFLAGS) $(DEF) $(INC) -c -o $@ $< + +# Collect unique source directories +SRC_DIRS = $(sort $(dir $(SRC_C))) + +# Generate a pattern rule for each source directory +define COMPILE_RULE +$(BUILD_DIR)/%.o: $(1)%.c | $(BUILD_DIR) + @echo "Compiling: $$(notdir $$<)" + $$(CMD_ECHO) $$(COMPILE) +endef + +$(foreach dir,$(SRC_DIRS),$(eval $(call COMPILE_RULE,$(dir)))) + +## Makefile Targets + +.PHONY: build_app clean + +build_app: | $(BUILD_DIR) +build_app: $(BUILD_DIR)/$(BIN).elf + @echo Build complete. + +$(BUILD_DIR)/$(BIN).elf: $(OBJS_C) | $(BUILD_DIR) + @echo "Linking: $(notdir $@)" + $(CMD_ECHO) $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +$(BUILD_DIR): + $(CMD_ECHO) mkdir -p $(BUILD_DIR) + +clean: + @echo "Cleaning build files" + @rm -rf $(BUILD_DIR) diff --git a/port/posix/server/user_settings.h b/port/posix/server/user_settings.h new file mode 100644 index 000000000..e9ad8ef20 --- /dev/null +++ b/port/posix/server/user_settings.h @@ -0,0 +1,133 @@ +/* + * 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 . + */ +/* + * port/posix/server/user_settings.h + * + * wolfSSL compile-time options for the POSIX generic server. + */ + +#ifndef USER_SETTINGS_H +#define USER_SETTINGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** wolfHSM required settings for wolfCrypt */ +#define WOLF_CRYPTO_CB +#define WOLFSSL_KEY_GEN +#define WOLFSSL_ASN_TEMPLATE +#define WOLFSSL_BASE64_ENCODE +#define HAVE_ANONYMOUS_INLINE_AGGREGATES 1 + +/* These macros reduce footprint size when TLS functionality is not needed */ +#define NO_TLS +#define WOLFSSL_USER_IO +#define WOLFSSL_NO_TLS12 +#define NO_PSK + +/* For ACert support (also requires WOLFSSL_ASN_TEMPLATE) */ +#define WOLFSSL_ACERT + +/** Math library selection */ +#define USE_FAST_MATH + +/** wolfHSM recommended */ +#define WOLFSSL_USE_ALIGN +#define WOLFSSL_IGNORE_FILE_WARN +#define TFM_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT +#define WC_RSA_BLINDING + +/** Remove unneeded features */ +#define NO_MAIN_DRIVER +#define NO_ERROR_STRINGS +#define NO_ERROR_QUEUE +#define NO_INLINE +#define NO_OLD_TLS +#define NO_DO178 +#define WC_NO_DEFAULT_DEVID + +/** Remove unneeded namespace */ +#define NO_OLD_RNGNAME +#define NO_OLD_WC_NAMES +#define NO_OLD_SSL_NAMES +#define NO_OLD_SHA_NAMES +#define NO_OLD_MD5_NAME + +/** RSA Options */ +#define RSA_MIN_SIZE 1024 +#define WC_RSA_PSS +#define WOLFSSL_PSS_LONG_SALT +#define FP_MAX_BITS 8192 + +/** ECC Options */ +#define HAVE_ECC +#define TFM_ECC256 +#define ECC_SHAMIR + +/** Curve25519 Options */ +#define HAVE_CURVE25519 + +/** Ed25519 Options */ +#define HAVE_ED25519 + +/** DH and DHE Options */ +#define HAVE_DH_DEFAULT_PARAMS +#define HAVE_FFDHE_2048 + +/** AES Options */ +#define HAVE_AESGCM +#define WOLFSSL_AES_COUNTER +#define GCM_TABLE_4BIT +#define WOLFSSL_AES_DIRECT +#define HAVE_AES_ECB +#define WOLFSSL_CMAC + +/** SHA Options */ +#define WOLFSSL_SHA224 +#define WOLFSSL_SHA384 +#define WOLFSSL_SHA512 +#define WOLFSSL_SHA512_HASHTYPE + +/* Dilithium Options */ +#define HAVE_DILITHIUM +#define WOLFSSL_WC_DILITHIUM +#define WOLFSSL_SHA3 +#define WOLFSSL_SHAKE128 +#define WOLFSSL_SHAKE256 + +/** Composite features */ +#define HAVE_HKDF +#define HAVE_CMAC_KDF + +/* Remove unneeded crypto */ +#define NO_DSA +#define NO_RC4 +#define NO_MD4 +#define NO_MD5 + +/* POSIX version of strcasecmp */ +#include + +#ifdef __cplusplus +} +#endif + +#endif /* USER_SETTINGS_H */ diff --git a/port/posix/server/wh_posix_server_port.c b/port/posix/server/wh_posix_server_port.c new file mode 100644 index 000000000..3f3eb2033 --- /dev/null +++ b/port/posix/server/wh_posix_server_port.c @@ -0,0 +1,242 @@ +/* + * 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 . + */ +/* + * port/posix/server/wh_posix_server_port.c + * + * POSIX server implementation of the wh_Port_* generic port API. + * Uses TCP transport with RamSim flash and NVM. Configuration is provided + * through WOLFHSM_CFG_PORT_* defines which must be set by the application. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wolfhsm/wh_settings.h" +#include "wolfhsm/wh_error.h" +#include "wolfhsm/wh_comm.h" +#include "wolfhsm/wh_server.h" +#include "wolfhsm/wh_nvm.h" +#include "wolfhsm/wh_nvm_flash.h" +#include "wolfhsm/wh_flash_ramsim.h" +#include "wolfhsm/wh_port.h" + +#include "port/posix/posix_transport_tcp.h" + +#if WOLFHSM_CFG_PORT_SERVER_COUNT > 1 +#error "POSIX port only supports WOLFHSM_CFG_PORT_SERVER_COUNT == 1" +#endif + +/* Transport context and configuration - must persist for lifetime of server */ +static posixTransportTcpServerContext tcpServerCtx; +static posixTransportTcpConfig tcpConfig; +static whCommServerConfig commConfig; +static whTransportServerCb tcpCb = PTT_SERVER_CB; + +/* NVM and flash state */ +static uint8_t flashMemory[WOLFHSM_CFG_PORT_FLASH_RAM_SIZE]; +static whFlashRamsimCfg flashCfg; +static whFlashRamsimCtx flashCtx; +static const whFlashCb flashCb = WH_FLASH_RAMSIM_CB; +static whNvmFlashConfig nvmFlashCfg; +static whNvmFlashContext nvmFlashCtx; +static whNvmCb nvmCb[1] = {WH_NVM_FLASH_CB}; +static whNvmConfig nvmConfig; +static whNvmContext nvmCtx; + +#ifndef WOLFHSM_CFG_NO_CRYPTO +static whServerCryptoContext cryptoCtx; +#endif + +/* Notification FIFO fd — opened once and kept open */ +static int notifyFd = -1; + +static void cleanupHandler(int sig) +{ + wh_Port_CleanupBoard(); + _exit(128 + sig); +} + +int wh_Port_InitBoard(void) +{ +#ifndef WOLFHSM_CFG_NO_CRYPTO + wolfCrypt_Init(); +#endif + + /* Register signal handler to clean up FIFO on exit */ + signal(SIGINT, cleanupHandler); + signal(SIGTERM, cleanupHandler); + + /* Create the FIFO if it doesn't exist (EEXIST is OK) */ + if (mkfifo(WOLFHSM_CFG_PORT_NOTIFY_PATH, 0666) != 0 && errno != EEXIST) { + return WH_ERROR_ABORTED; + } + /* O_RDWR prevents EOF when no writer is connected yet */ + notifyFd = open(WOLFHSM_CFG_PORT_NOTIFY_PATH, O_RDWR | O_NONBLOCK); + if (notifyFd < 0) { + return WH_ERROR_ABORTED; + } + + return WH_ERROR_OK; +} + +int wh_Port_CleanupBoard(void) +{ + if (notifyFd >= 0) { + if (close(notifyFd) != 0) { + return WH_ERROR_ABORTED; + } + notifyFd = -1; + } + if (unlink(WOLFHSM_CFG_PORT_NOTIFY_PATH) != 0 && errno != ENOENT) { + return WH_ERROR_ABORTED; + } + + return WH_ERROR_OK; +} + +int wh_Port_ConfigureServer(size_t instance, whServerConfig* serverCfg) +{ + int ret; + + if (serverCfg == NULL || instance >= WOLFHSM_CFG_PORT_SERVER_COUNT) { + return WH_ERROR_BADARGS; + } + + memset(serverCfg, 0, sizeof(*serverCfg)); + memset(&tcpServerCtx, 0, sizeof(tcpServerCtx)); + memset(&commConfig, 0, sizeof(commConfig)); + memset(flashMemory, 0, sizeof(flashMemory)); + + /* TCP transport configuration */ + tcpConfig.server_ip_string = WOLFHSM_CFG_PORT_TCP_IPSTRING; + tcpConfig.server_port = WOLFHSM_CFG_PORT_TCP_PORT; + + commConfig.transport_cb = &tcpCb; + commConfig.transport_context = (void*)&tcpServerCtx; + commConfig.transport_config = (void*)&tcpConfig; + commConfig.server_id = WOLFHSM_CFG_PORT_SERVER_ID; + + serverCfg->comm_config = &commConfig; + + /* Flash simulation configuration */ + flashCfg.size = WOLFHSM_CFG_PORT_FLASH_RAM_SIZE; + flashCfg.sectorSize = WOLFHSM_CFG_PORT_FLASH_RAM_SIZE / 2; + flashCfg.pageSize = 8; + flashCfg.erasedByte = (uint8_t)0; + flashCfg.memory = flashMemory; + + /* NVM configuration */ + memset(&flashCtx, 0, sizeof(flashCtx)); + memset(&nvmFlashCtx, 0, sizeof(nvmFlashCtx)); + nvmFlashCfg.cb = &flashCb; + nvmFlashCfg.context = &flashCtx; + nvmFlashCfg.config = &flashCfg; + + nvmConfig.cb = nvmCb; + nvmConfig.context = &nvmFlashCtx; + nvmConfig.config = &nvmFlashCfg; + + ret = wh_Nvm_Init(&nvmCtx, &nvmConfig); + if (ret != WH_ERROR_OK) { + WOLFHSM_CFG_PRINTF("Failed to initialize NVM: %d\n", ret); + return ret; + } + + serverCfg->nvm = &nvmCtx; + +#ifndef WOLFHSM_CFG_NO_CRYPTO + memset(&cryptoCtx, 0, sizeof(cryptoCtx)); + serverCfg->crypto = &cryptoCtx; + serverCfg->devId = INVALID_DEVID; + + ret = wc_InitRng_ex(cryptoCtx.rng, NULL, INVALID_DEVID); + if (ret != 0) { + WOLFHSM_CFG_PRINTF("Failed to initialize RNG: %d\n", ret); + return ret; + } +#endif + + (void)instance; + return WH_ERROR_OK; +} + +int wh_Port_InitServer(size_t instance, whServerConfig* serverCfg, + whServerContext* serverCtx) +{ + if (serverCfg == NULL || serverCtx == NULL || + instance >= WOLFHSM_CFG_PORT_SERVER_COUNT) { + return WH_ERROR_BADARGS; + } + + return wh_Server_Init(serverCtx, serverCfg); +} + +int wh_Port_CleanupServer(size_t instance, whServerContext* serverCtx) +{ + if (serverCtx == NULL || instance >= WOLFHSM_CFG_PORT_SERVER_COUNT) { + return WH_ERROR_BADARGS; + } + + return wh_Server_Cleanup(serverCtx); +} + +int wh_Port_ClientConnected(size_t instance) +{ + uint8_t msg; + ssize_t rc; + + (void)instance; + + if (notifyFd < 0) { + return 0; + } + + rc = read(notifyFd, &msg, 1); + if (rc == 1 && msg == 1) { + return 1; + } + + return 0; +} + +int wh_Port_ClientDisconnected(size_t instance) +{ + uint8_t msg; + ssize_t rc; + + (void)instance; + + if (notifyFd < 0) { + return 0; + } + + rc = read(notifyFd, &msg, 1); + if (rc == 1 && msg == 0) { + return 1; + } + + return 0; +} diff --git a/port/posix/server/wolfhsm_cfg.h b/port/posix/server/wolfhsm_cfg.h new file mode 100644 index 000000000..99e132999 --- /dev/null +++ b/port/posix/server/wolfhsm_cfg.h @@ -0,0 +1,67 @@ +/* + * 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 . + */ +/* + * port/posix/server/wolfhsm_cfg.h + * + * wolfHSM compile-time options for the POSIX generic server. + */ + +#ifndef WOLFHSM_CFG_H_ +#define WOLFHSM_CFG_H_ + +#include "port/posix/posix_time.h" + +#define WOLFHSM_CFG_PORT_GETTIME posixGetTime + +/** Port configuration */ +#define WOLFHSM_CFG_PORT_SERVER_ID 57 +#define WOLFHSM_CFG_PORT_SERVER_COUNT 1 +#define WOLFHSM_CFG_PORT_TCP_PORT 23456 +#define WOLFHSM_CFG_PORT_TCP_IPSTRING "127.0.0.1" +#define WOLFHSM_CFG_PORT_NOTIFY_PATH "/tmp/wolfhsm_notify" +#define WOLFHSM_CFG_PORT_FLASH_RAM_SIZE (1024 * 1024) /* 1MB */ + +/** wolfHSM settings */ +#define WOLFHSM_CFG_ENABLE_SERVER + +/* Large enough for ML-DSA level 5 key */ +#define WOLFHSM_CFG_COMM_DATA_LEN 5000 + +#define WOLFHSM_CFG_NVM_OBJECT_COUNT 30 +#define WOLFHSM_CFG_SERVER_KEYCACHE_COUNT 9 +#define WOLFHSM_CFG_SERVER_KEYCACHE_SIZE 1024 +#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_BUFSIZE 4096 +#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_COUNT 5 + +#define WOLFHSM_CFG_SERVER_DMAADDR_COUNT 8 +#define WOLFHSM_CFG_SERVER_CUSTOMCB_COUNT 6 + +#define WOLFHSM_CFG_CERTIFICATE_MANAGER +#define WOLFHSM_CFG_CERTIFICATE_MANAGER_ACERT + +#define XMEMFENCE() __atomic_thread_fence(__ATOMIC_SEQ_CST) + +#define WOLFHSM_CFG_KEYWRAP_MAX_KEY_SIZE 5000 + +#ifndef WOLFHSM_CFG_NO_CRYPTO +#define WOLFHSM_CFG_KEYWRAP +#define WOLFHSM_CFG_GLOBAL_KEYS +#endif + +#endif /* WOLFHSM_CFG_H_ */ diff --git a/port/skeleton/README.md b/port/skeleton/README.md deleted file mode 100644 index 378f065db..000000000 --- a/port/skeleton/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Skeleton Port - -The Skeleton port source code provides a non-functioning layout to be used as a starting point for future hardware/platform ports. Each function provides the basic description and expected flow with error cases explained so that ports can be used interchangeably with consistent results. - -The Skeleton port provides implementations of: -- Transport -- NVM Device -- Flash Device -- Crypto Device diff --git a/port/template/README.md b/port/template/README.md new file mode 100644 index 000000000..42b021b27 --- /dev/null +++ b/port/template/README.md @@ -0,0 +1,21 @@ +# Template Port + +This directory provides a starting point for porting wolfHSM to a new platform. +Each file contains stub implementations of the required interfaces with +documentation explaining what each function should do. + +## Getting Started + +1. Copy this directory to `port//`. +2. Implement the transport layer for your platform (or use an existing one). +3. Fill in the `wh_Port_*` function stubs in `client/wh_client_port.c` and + `server/wh_server_port.c`. +4. Edit `client/wolfhsm_cfg.h` and `server/wolfhsm_cfg.h` with your + platform's configuration values. +5. Edit `client/user_settings.h` and `server/user_settings.h` with the + wolfSSL features your application requires. +6. Create a build system (Makefile, CMake, IDE project, etc.) that compiles + the generic examples together with your port. See `port/posix/` for a + Makefile-based reference. + +See `docs/draft/porting.md` for a detailed porting guide. diff --git a/port/template/client/user_settings.h b/port/template/client/user_settings.h new file mode 100644 index 000000000..3f19ed3ce --- /dev/null +++ b/port/template/client/user_settings.h @@ -0,0 +1,61 @@ +/* + * 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 . + */ +/* + * port/template/client/user_settings.h + * + * Template wolfSSL compile-time options for a client build. + * Enable the crypto algorithms and features your application requires. + */ + +#ifndef USER_SETTINGS_H_ +#define USER_SETTINGS_H_ + +/** wolfHSM required settings */ +#define WOLF_CRYPTO_CB +#define HAVE_ANONYMOUS_INLINE_AGGREGATES 1 +#define WOLFSSL_KEY_GEN +#define WOLFSSL_ASN_TEMPLATE +#define WOLFSSL_BASE64_ENCODE + +/* C90 compatibility */ +#define NO_INLINE +#define WOLFSSL_IGNORE_FILE_WARN + +/* Side-channel resistance */ +#define TFM_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT +#define WC_RSA_BLINDING + +/** Crypto algorithm selection + * TODO: Enable the algorithms your application needs. Common choices: */ +/* #define HAVE_ECC */ +/* #define HAVE_CURVE25519 */ +/* #define HAVE_AES_CBC */ +/* #define HAVE_AESGCM */ +/* #define WOLFSSL_AES_COUNTER */ +/* #define WOLFSSL_AES_DIRECT */ +/* #define WOLFSSL_CMAC */ +/* #define HAVE_HKDF */ + +/** Platform settings + * TODO: Adjust for your platform. */ +#define NO_MAIN_DRIVER +/* #define NO_FILESYSTEM */ + +#endif /* USER_SETTINGS_H_ */ diff --git a/port/template/client/wh_client_port.c b/port/template/client/wh_client_port.c new file mode 100644 index 000000000..28a19cb53 --- /dev/null +++ b/port/template/client/wh_client_port.c @@ -0,0 +1,177 @@ +/* + * 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 . + */ +/* + * port/template/client/wh_client_port.c + * + * Template client implementation of the wh_Port_* generic port API. + * Replace the TODO stubs with your platform-specific logic. + */ + +#include +#include + +#include "wolfhsm/wh_settings.h" +#include "wolfhsm/wh_error.h" +#include "wolfhsm/wh_comm.h" +#include "wolfhsm/wh_client.h" +#include "wolfhsm/wh_port.h" + +/* TODO: Include your transport header here, e.g.: + * #include "port//_transport.h" + */ + +/* TODO: Declare static transport context and configuration structures. + * These must persist for the lifetime of the client. Example: + * + * static myTransportClientContext transportCtx; + * static myTransportConfig transportCfg; + * static whCommClientConfig commConfig; + * static whTransportClientCb transportCb = MY_CLIENT_CB; + */ + + +int wh_Port_InitBoard(void) +{ + /* TODO: Initialize any shared platform resources needed by the client. + * This is called once at startup before any client operations. + * + * Examples: + * - Initialize hardware peripherals + * - Set up IPC mechanisms for server notifications + * - Initialize crypto libraries + */ + return WH_ERROR_OK; +} + +int wh_Port_CleanupBoard(void) +{ + /* TODO: Release resources allocated by wh_Port_InitBoard. + * This is called at shutdown. + */ + return WH_ERROR_OK; +} + +/* TODO: If your transport supports a connect callback, implement it here. + * The callback is invoked by the transport layer when the connection state + * changes. It should notify the server side so that wh_Port_ClientConnected + * and wh_Port_ClientDisconnected work correctly. + * + * static int connectCb(void* context, whCommConnected connected) + * { + * (void)context; + * if (connected == WH_COMM_CONNECTED) { + * // Notify server that client has connected + * } else { + * // Notify server that client has disconnected + * } + * return WH_ERROR_OK; + * } + */ + +int wh_Port_ConfigureClient(whClientConfig* clientCfg) +{ + if (clientCfg == NULL) { + return WH_ERROR_BADARGS; + } + + /* TODO: Initialize and populate the comm configuration with your + * transport callbacks, context, config, client ID, and optionally + * a connect callback. Then assign it to clientCfg->comm. Example: + * + * memset(&transportCtx, 0, sizeof(transportCtx)); + * memset(&commConfig, 0, sizeof(commConfig)); + * + * transportCfg.server_addr = WOLFHSM_CFG_PORT_SERVER_ADDR; + * + * commConfig.transport_cb = &transportCb; + * commConfig.transport_context = (void*)&transportCtx; + * commConfig.transport_config = (void*)&transportCfg; + * commConfig.client_id = WOLFHSM_CFG_PORT_CLIENT_ID; + * commConfig.connect_cb = connectCb; + * + * clientCfg->comm = &commConfig; + */ + + return WH_ERROR_OK; +} + +int wh_Port_InitClient(whClientConfig* clientCfg, whClientContext* clientCtx) +{ + int ret; + + if (clientCfg == NULL || clientCtx == NULL) { + return WH_ERROR_BADARGS; + } + + ret = wh_Client_Init(clientCtx, clientCfg); + if (ret != WH_ERROR_OK) { + return ret; + } + + ret = wh_Client_CommInit(clientCtx, NULL, NULL); + if (ret != WH_ERROR_OK) { + (void)wh_Client_Cleanup(clientCtx); + return ret; + } + + return WH_ERROR_OK; +} + +int wh_Port_RunClient(whClientContext* clientCtx) +{ + if (clientCtx == NULL) { + return WH_ERROR_BADARGS; + } + + /* TODO: Implement your client application logic here. For example: + * - Send echo requests + * - Perform crypto operations + * - Store/retrieve NVM objects + * - Run key management operations + * + * Use wh_Client_* APIs. For async operations, poll with a retry loop: + * + * do { + * ret = wh_Client_EchoRequest(clientCtx, len, data); + * } while (ret == WH_ERROR_NOTREADY); + */ + + return WH_ERROR_OK; +} + +int wh_Port_CleanupClient(whClientContext* clientCtx) +{ + int ret; + + if (clientCtx == NULL) { + return WH_ERROR_BADARGS; + } + + ret = wh_Client_CommClose(clientCtx); + if (ret != WH_ERROR_OK) { + return ret; + } + + ret = wh_Client_Cleanup(clientCtx); + if (ret != WH_ERROR_OK) { + return ret; + } + + return WH_ERROR_OK; +} diff --git a/port/template/client/wolfhsm_cfg.h b/port/template/client/wolfhsm_cfg.h new file mode 100644 index 000000000..c44b37827 --- /dev/null +++ b/port/template/client/wolfhsm_cfg.h @@ -0,0 +1,74 @@ +/* + * 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 . + */ +/* + * port/template/client/wolfhsm_cfg.h + * + * Template wolfHSM compile-time options for a client build. + */ + +#ifndef WOLFHSM_CFG_H_ +#define WOLFHSM_CFG_H_ + +/* TODO: Include your platform's time function header and define + * WOLFHSM_CFG_PORT_GETTIME to a function returning uint64_t microseconds. + * + * #include "port//_time.h" + * #define WOLFHSM_CFG_PORT_GETTIME myPlatformGetTime + */ + +/* TODO: Define a printf-like function for your platform if the default + * stdlib printf is not available. + * + * #define WOLFHSM_CFG_PRINTF myPlatformPrintf + */ + +/** Port configuration + * TODO: Set these to match your platform and server configuration. */ +#define WOLFHSM_CFG_PORT_CLIENT_ID 12 +/* TODO: Add transport-specific defines here, e.g.: + * #define WOLFHSM_CFG_PORT_TCP_PORT 23456 + * #define WOLFHSM_CFG_PORT_TCP_IPSTRING "127.0.0.1" + */ + +/** wolfHSM settings */ +#define WOLFHSM_CFG_ENABLE_CLIENT + +/* Communication data length — must match server */ +#define WOLFHSM_CFG_COMM_DATA_LEN 5000 + +/* NVM object count — must match server */ +#define WOLFHSM_CFG_NVM_OBJECT_COUNT 30 + +/* TODO: Uncomment to enable tests and benchmarks: + * #define WOLFHSM_CFG_PORT_ENABLE_WOLFHSM_TESTS + * #define WOLFHSM_CFG_TEST_WOLFCRYPTTEST + * #define WOLFHSM_CFG_TEST_UNIT_NO_MAIN + * #define WOLFHSM_CFG_TEST_CLIENT_ONLY + * #define WOLFHSM_CFG_PORT_ENABLE_BENCHMARK + * #define WOLFHSM_CFG_BENCH_ENABLE + * #include "benchmark/wh_bench_ops.h" + * #define WOLFHSM_CFG_PORT_BENCH_TRANSPORT WH_BENCH_TRANSPORT_... + */ + +#ifndef WOLFHSM_CFG_NO_CRYPTO +#define WOLFHSM_CFG_KEYWRAP +#define WOLFHSM_CFG_GLOBAL_KEYS +#endif + +#endif /* WOLFHSM_CFG_H_ */ diff --git a/port/template/server/user_settings.h b/port/template/server/user_settings.h new file mode 100644 index 000000000..feda268c3 --- /dev/null +++ b/port/template/server/user_settings.h @@ -0,0 +1,99 @@ +/* + * 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 . + */ +/* + * port/template/server/user_settings.h + * + * Template wolfSSL compile-time options for a server build. + * The server typically needs a broader set of crypto algorithms than the + * client since it must support all operations clients may request. + */ + +#ifndef USER_SETTINGS_H_ +#define USER_SETTINGS_H_ + +/** wolfHSM required settings */ +#define WOLF_CRYPTO_CB +#define HAVE_ANONYMOUS_INLINE_AGGREGATES 1 +#define WOLFSSL_KEY_GEN +#define WOLFSSL_ASN_TEMPLATE +#define WOLFSSL_BASE64_ENCODE + +/* TLS is not needed for wolfHSM server operation */ +#define NO_TLS +#define WOLFSSL_USER_IO +#define WOLFSSL_NO_TLS12 +#define NO_PSK + +/** Math library selection + * TODO: Choose the math library appropriate for your platform. + * USE_FAST_MATH is recommended for most platforms. */ +#define USE_FAST_MATH + +/** wolfHSM recommended */ +#define WOLFSSL_USE_ALIGN +#define WOLFSSL_IGNORE_FILE_WARN +#define TFM_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT +#define WC_RSA_BLINDING + +/* C90 compatibility */ +#define NO_INLINE +#define NO_MAIN_DRIVER + +/** Remove unneeded features + * TODO: Adjust based on your requirements. */ +#define NO_ERROR_STRINGS +#define NO_ERROR_QUEUE +#define NO_OLD_TLS +#define NO_DO178 +#define WC_NO_DEFAULT_DEVID +#define NO_OLD_RNGNAME +#define NO_OLD_WC_NAMES +#define NO_OLD_SSL_NAMES +#define NO_OLD_SHA_NAMES +#define NO_OLD_MD5_NAME + +/** RSA Options */ +#define RSA_MIN_SIZE 1024 +#define WC_RSA_PSS +#define WOLFSSL_PSS_LONG_SALT +#define FP_MAX_BITS 8192 + +/** Crypto algorithm selection + * TODO: Enable the algorithms your application needs. The server should + * support all algorithms that any client may request. */ +/* #define HAVE_ECC */ +/* #define TFM_ECC256 */ +/* #define ECC_SHAMIR */ +/* #define HAVE_CURVE25519 */ +/* #define HAVE_ED25519 */ +/* #define HAVE_AESGCM */ +/* #define WOLFSSL_AES_COUNTER */ +/* #define WOLFSSL_AES_DIRECT */ +/* #define HAVE_AES_ECB */ +/* #define WOLFSSL_CMAC */ +/* #define HAVE_HKDF */ + +/** Remove unneeded crypto + * TODO: Disable algorithms you don't need. */ +#define NO_DSA +#define NO_RC4 +#define NO_MD4 + +#endif /* USER_SETTINGS_H_ */ diff --git a/port/template/server/wh_server_port.c b/port/template/server/wh_server_port.c new file mode 100644 index 000000000..1562add1a --- /dev/null +++ b/port/template/server/wh_server_port.c @@ -0,0 +1,177 @@ +/* + * 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 . + */ +/* + * port/template/server/wh_server_port.c + * + * Template server implementation of the wh_Port_* generic port API. + * Replace the TODO stubs with your platform-specific logic. + */ + +#include +#include + +#include "wolfhsm/wh_settings.h" +#include "wolfhsm/wh_error.h" +#include "wolfhsm/wh_comm.h" +#include "wolfhsm/wh_server.h" +#include "wolfhsm/wh_nvm.h" +#include "wolfhsm/wh_nvm_flash.h" +#include "wolfhsm/wh_flash_ramsim.h" +#include "wolfhsm/wh_port.h" + +/* TODO: Include your transport header here, e.g.: + * #include "port//_transport.h" + */ + +/* TODO: Declare static transport context and configuration structures. + * These must persist for the lifetime of the server. Example: + * + * static myTransportServerContext transportCtx; + * static myTransportConfig transportCfg; + * static whCommServerConfig commConfig; + * static whTransportServerCb transportCb = MY_SERVER_CB; + */ + +/* TODO: Declare NVM and flash state. You can use wh_flash_ramsim for + * development or provide your own flash callbacks. Example using ramsim: + * + * static uint8_t flashMemory[WOLFHSM_CFG_PORT_FLASH_RAM_SIZE]; + * static whFlashRamsimCfg flashCfg; + * static whFlashRamsimCtx flashCtx; + * static const whFlashCb flashCb = WH_FLASH_RAMSIM_CB; + * static whNvmFlashConfig nvmFlashCfg; + * static whNvmFlashContext nvmFlashCtx; + * static whNvmCb nvmCb[1] = {WH_NVM_FLASH_CB}; + * static whNvmConfig nvmConfig; + * static whNvmContext nvmCtx; + */ + +/* TODO: If crypto is enabled, declare crypto context: + * + * #ifndef WOLFHSM_CFG_NO_CRYPTO + * static whServerCryptoContext cryptoCtx; + * #endif + */ + + +int wh_Port_InitBoard(void) +{ + /* TODO: Initialize shared platform resources for the server. + * This is called once at startup. + * + * Examples: + * - Initialize crypto libraries (e.g. wolfCrypt_Init()) + * - Set up signal handlers for graceful shutdown + * - Create IPC mechanisms for client connection notifications + * - Initialize hardware peripherals + */ + return WH_ERROR_OK; +} + +int wh_Port_CleanupBoard(void) +{ + /* TODO: Release resources allocated by wh_Port_InitBoard. + * + * Examples: + * - Close file descriptors or IPC handles + * - Remove temporary files + * - Deinitialize hardware + */ + return WH_ERROR_OK; +} + +int wh_Port_ConfigureServer(size_t instance, whServerConfig* serverCfg) +{ + if (serverCfg == NULL || instance >= WOLFHSM_CFG_PORT_SERVER_COUNT) { + return WH_ERROR_BADARGS; + } + + /* TODO: Populate serverCfg with transport, NVM, and crypto configuration. + * + * 1. Set up transport: + * commConfig.transport_cb = &transportCb; + * commConfig.transport_context = (void*)&transportCtx; + * commConfig.transport_config = (void*)&transportCfg; + * commConfig.server_id = WOLFHSM_CFG_PORT_SERVER_ID; + * serverCfg->comm_config = &commConfig; + * + * 2. Set up flash and NVM: + * - Configure flash backend (ramsim or hardware flash) + * - Initialize NVM with wh_Nvm_Init() + * - Assign: serverCfg->nvm = &nvmCtx; + * + * 3. Set up crypto (if not WOLFHSM_CFG_NO_CRYPTO): + * - Initialize RNG with wc_InitRng_ex() + * - Assign: serverCfg->crypto = &cryptoCtx; + * - Assign: serverCfg->devId = INVALID_DEVID; + */ + + (void)instance; + return WH_ERROR_OK; +} + +int wh_Port_InitServer(size_t instance, whServerConfig* serverCfg, + whServerContext* serverCtx) +{ + if (serverCfg == NULL || serverCtx == NULL || + instance >= WOLFHSM_CFG_PORT_SERVER_COUNT) { + return WH_ERROR_BADARGS; + } + + return wh_Server_Init(serverCtx, serverCfg); +} + +int wh_Port_CleanupServer(size_t instance, whServerContext* serverCtx) +{ + if (serverCtx == NULL || instance >= WOLFHSM_CFG_PORT_SERVER_COUNT) { + return WH_ERROR_BADARGS; + } + + return wh_Server_Cleanup(serverCtx); +} + +int wh_Port_ClientConnected(size_t instance) +{ + (void)instance; + + /* TODO: Check if a client has connected to this server instance. + * Return 1 exactly once per connection event, 0 otherwise. + * + * The mechanism is platform-specific. Examples: + * - Read from a FIFO/pipe for a connect notification byte + * - Check a shared memory flag and clear it + * - Poll a hardware mailbox register + */ + + return 0; +} + +int wh_Port_ClientDisconnected(size_t instance) +{ + (void)instance; + + /* TODO: Check if a client has disconnected from this server instance. + * Return 1 exactly once per disconnection event, 0 otherwise. + * + * Uses the same mechanism as wh_Port_ClientConnected but checks for + * the disconnect notification. + */ + + return 0; +} diff --git a/port/template/server/wolfhsm_cfg.h b/port/template/server/wolfhsm_cfg.h new file mode 100644 index 000000000..b5d7079b3 --- /dev/null +++ b/port/template/server/wolfhsm_cfg.h @@ -0,0 +1,82 @@ +/* + * 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 . + */ +/* + * port/template/server/wolfhsm_cfg.h + * + * Template wolfHSM compile-time options for a server build. + */ + +#ifndef WOLFHSM_CFG_H_ +#define WOLFHSM_CFG_H_ + +/* TODO: Include your platform's time function header and define + * WOLFHSM_CFG_PORT_GETTIME to a function returning uint64_t microseconds. + * + * #include "port//_time.h" + * #define WOLFHSM_CFG_PORT_GETTIME myPlatformGetTime + */ + +/* TODO: Define a printf-like function for your platform if the default + * stdlib printf is not available. + * + * #define WOLFHSM_CFG_PRINTF myPlatformPrintf + */ + +/** Port configuration + * TODO: Set these to match your platform. */ +#define WOLFHSM_CFG_PORT_SERVER_ID 57 +#define WOLFHSM_CFG_PORT_SERVER_COUNT 1 +/* TODO: Add transport-specific defines here, e.g.: + * #define WOLFHSM_CFG_PORT_TCP_PORT 23456 + * #define WOLFHSM_CFG_PORT_TCP_IPSTRING "127.0.0.1" + */ + +/* TODO: Define flash size for NVM storage. Example for RAM simulation: + * #define WOLFHSM_CFG_PORT_FLASH_RAM_SIZE (1024 * 1024) + */ + +/** wolfHSM settings */ +#define WOLFHSM_CFG_ENABLE_SERVER + +/* Communication data length — must match client */ +#define WOLFHSM_CFG_COMM_DATA_LEN 5000 + +/* NVM object count — must match client */ +#define WOLFHSM_CFG_NVM_OBJECT_COUNT 30 + +/** Server resource configuration */ +#define WOLFHSM_CFG_SERVER_KEYCACHE_COUNT 9 +#define WOLFHSM_CFG_SERVER_KEYCACHE_SIZE 1024 +#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_COUNT 5 +#define WOLFHSM_CFG_SERVER_KEYCACHE_BIG_BUFSIZE 4096 +#define WOLFHSM_CFG_SERVER_DMAADDR_COUNT 8 +#define WOLFHSM_CFG_SERVER_CUSTOMCB_COUNT 6 + +/* TODO: Uncomment if your platform needs a memory fence override: + * #define XMEMFENCE() __atomic_thread_fence(__ATOMIC_SEQ_CST) + */ + +#define WOLFHSM_CFG_KEYWRAP_MAX_KEY_SIZE 5000 + +#ifndef WOLFHSM_CFG_NO_CRYPTO +#define WOLFHSM_CFG_KEYWRAP +#define WOLFHSM_CFG_GLOBAL_KEYS +#endif + +#endif /* WOLFHSM_CFG_H_ */ diff --git a/test/wh_test_wolfcrypt_test.c b/test/wh_test_wolfcrypt_test.c index f1db0ca7c..267177781 100644 --- a/test/wh_test_wolfcrypt_test.c +++ b/test/wh_test_wolfcrypt_test.c @@ -135,13 +135,15 @@ static int whTest_ServerCfgLoop(whServerConfig* serverCfg) } #endif /* WOLFHSM_CFG_TEST_POSIX && WOLFHSM_CFG_ENABLE_SERVER */ -#if defined(WOLFHSM_CFG_TEST_POSIX) && defined(WOLFHSM_CFG_ENABLE_CLIENT) +#if defined(WOLFHSM_CFG_TEST_POSIX) && defined(WOLFHSM_CFG_ENABLE_CLIENT) && \ + defined(WOLFHSM_CFG_ENABLE_SERVER) static void* _whClientTask(void* cf) { WH_TEST_ASSERT(0 == whTest_WolfCryptTestCfg(cf)); return NULL; } -#endif /* WOLFHSM_CFG_TEST_POSIX && WOLFHSM_CFG_ENABLE_CLIENT */ +#endif /* WOLFHSM_CFG_TEST_POSIX && WOLFHSM_CFG_ENABLE_CLIENT && \ + WOLFHSM_CFG_ENABLE_SERVER */ #if defined(WOLFHSM_CFG_TEST_POSIX) && defined(WOLFHSM_CFG_ENABLE_SERVER) static void* _whServerTask(void* cf) diff --git a/wolfhsm/wh_port.h b/wolfhsm/wh_port.h new file mode 100644 index 000000000..22fd4a66e --- /dev/null +++ b/wolfhsm/wh_port.h @@ -0,0 +1,162 @@ +/* + * 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 . + */ +/* + * wolfhsm/wh_port.h + * + * Abstract port API for wolfHSM generic examples. Each port (e.g. POSIX, + * bare-metal) provides its own implementation of these functions. + */ + +#ifndef WOLFHSM_WH_PORT_H_ +#define WOLFHSM_WH_PORT_H_ + +#include +#include "wolfhsm/wh_settings.h" +#include "wolfhsm/wh_client.h" +#include "wolfhsm/wh_server.h" + +/** @defgroup Port Port API + * @brief Platform-specific board, client, and server initialization functions. + * @{ + */ + +/* Common API */ + +/** + * @brief Initialize the board and any shared platform resources. + * + * Called once at startup before any client or server operations. Performs + * platform-specific initialization. + * + * @return 0 on success, negative error code on failure. + */ +int wh_Port_InitBoard(void); + +/** + * @brief Clean up board resources allocated by wh_Port_InitBoard. + * + * Called at shutdown to release any shared platform resources. + * + * @return 0 on success, negative error code on failure. + */ +int wh_Port_CleanupBoard(void); + +/* Client API */ + +/** + * @brief Populate a client configuration structure with port-specific settings. + * + * Sets up transport, communication, and callback configuration for the client. + * The resulting configuration can be passed to wh_Port_InitClient. + * + * @param[out] clientCfg Pointer to the client configuration to populate. + * @return 0 on success, negative error code on failure. + */ +int wh_Port_ConfigureClient(whClientConfig* clientCfg); + +/** + * @brief Initialize and connect a client using the given configuration. + * + * Initializes the client context and establishes communication with the server. + * + * @param[in] clientCfg Pointer to the client configuration. + * @param[out] clientCtx Pointer to the client context to initialize. + * @return 0 on success, negative error code on failure. + */ +int wh_Port_InitClient(whClientConfig* clientCfg, whClientContext* clientCtx); + +/** + * @brief Run the main client application logic. + * + * Executes the client workload (e.g. echo requests, tests, benchmarks). + * + * @param[in] clientCtx Pointer to an initialized client context. + * @return 0 on success, negative error code on failure. + */ +int wh_Port_RunClient(whClientContext* clientCtx); + +/** + * @brief Clean up a client and release its resources. + * + * Closes the communication channel and cleans up the client context. + * + * @param[in] clientCtx Pointer to the client context to clean up. + * @return 0 on success, negative error code on failure. + */ +int wh_Port_CleanupClient(whClientContext* clientCtx); + +/* Server API */ + +/** + * @brief Populate a server configuration structure for a given instance. + * + * Sets up transport, NVM, flash, and crypto configuration for the specified + * server instance. + * + * @param[in] instance Server instance index. + * @param[out] serverCfg Pointer to the server configuration to populate. + * @return 0 on success, negative error code on failure. + */ +int wh_Port_ConfigureServer(size_t instance, whServerConfig* serverCfg); + +/** + * @brief Initialize a server instance using the given configuration. + * + * @param[in] instance Server instance index. + * @param[in] serverCfg Pointer to the server configuration. + * @param[out] serverCtx Pointer to the server context to initialize. + * @return 0 on success, negative error code on failure. + */ +int wh_Port_InitServer(size_t instance, whServerConfig* serverCfg, + whServerContext* serverCtx); + +/** + * @brief Clean up a server instance and release its resources. + * + * @param[in] instance Server instance index. + * @param[in] serverCtx Pointer to the server context to clean up. + * @return 0 on success, negative error code on failure. + */ +int wh_Port_CleanupServer(size_t instance, whServerContext* serverCtx); + +/** + * @brief Check if a new client connection notification has been received. + * + * Returns true once when a client has connected to the given server instance. + * Subsequent calls will return 0 until the next client connects. + * + * @param[in] instance Server instance index. + * @return 1 if a client connected notification was received, 0 otherwise. + */ +int wh_Port_ClientConnected(size_t instance); + +/** + * @brief Check if a client disconnection notification has been received. + * + * Returns true once when a client has disconnected from the given server + * instance. Subsequent calls will return 0 until the next client disconnects. + * + * @param[in] instance Server instance index. + * @return 1 if a client disconnected notification was received, 0 otherwise. + */ +int wh_Port_ClientDisconnected(size_t instance); + +/** @} */ /* end Port */ + +#endif /* WOLFHSM_WH_PORT_H_ */