Skip to content
Closed
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
38 changes: 26 additions & 12 deletions .github/workflows/auto-pin-dependencies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,44 @@ jobs:
changed=0
failed=0

# These dependencies publish stable release tags. wolfPSA remains
# manual while this branch carries fork-only runtime-devId/device-ID
# changes; including it here would undo the tested replacement
# patches on the next upstream release scan.
# These dependencies publish stable release tags. A required commit
# prevents a release from dropping newer integration work already in
# the pinned tree. wolfPSA remains manual while this branch carries
# fork-only runtime-devId/device-ID changes.
specs=(
"lib/wolfSSL|https://github.com/wolfSSL/wolfSSL.git|v*-stable"
"lib/wolfHSM|https://github.com/wolfSSL/wolfHSM.git|wolfHSM-v*"
"lib/wolfIP|https://github.com/wolfSSL/wolfIP.git|v*"
"lib/wolfSSL|https://github.com/wolfSSL/wolfSSL.git|v*-stable|51975e27a5439668733976a584d417dfd7776026"
"lib/wolfHSM|https://github.com/wolfSSL/wolfHSM.git|wolfHSM-v*|97dbbd72ad2bf757279d7dc5101580290525c647"
"lib/wolfIP|https://github.com/wolfSSL/wolfIP.git|v*|"
)

for spec in "${specs[@]}"; do
IFS='|' read -r path repo pattern <<< "$spec"
IFS='|' read -r path repo pattern required <<< "$spec"
latest=$(git ls-remote --tags --refs "$repo" "$pattern" \
| awk -F/ '{print $NF}' | sort -V | tail -n 1)
test -n "$latest"
current=$(git -C "$path" rev-parse HEAD)
candidate=$(git ls-remote "$repo" "refs/tags/$latest" | awk '{print $1}')
git -C "$path" fetch --no-tags "$repo" "refs/tags/$latest"
candidate=$(git -C "$path" rev-parse 'FETCH_HEAD^{commit}')
echo "$path: current=$current latest=$latest candidate=$candidate"

if [ -n "$required" ] &&
! git -C "$path" merge-base --is-ancestor \
"$required" "$candidate"; then
echo "$path: $latest lacks required commit $required; keeping current pin"
continue
fi
if [ "$current" = "$candidate" ]; then
continue
fi

if git -C "$path" merge-base --is-ancestor \
"$candidate" "$current"; then
echo "$path: current pin is newer than $latest; keeping current pin"
continue
fi

changed=1
git -C "$path" fetch --depth 1 "$repo" "$latest"
git -C "$path" checkout --detach FETCH_HEAD
git -C "$path" checkout --detach "$candidate"

if ! make test; then
failed=1
Expand All @@ -74,9 +87,10 @@ jobs:
done

if [ "$changed" -eq 0 ]; then
echo "No upstream release tags advanced. Pins unchanged."
echo "No compatible upstream release tags advanced. Pins unchanged."
fi
echo "failed=$failed" >> "$GITHUB_OUTPUT"
exit "$failed"

- name: Commit green release pins
if: steps.gate.outputs.failed == '0'
Expand Down
2 changes: 2 additions & 0 deletions docs/Testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ vectors, Secure Partition layout and recovery, HSM relay and key isolation,
vault and storage services, attestation and COSE integration, firmware update,
runtime remeasurement, VNET, public PSA headers, boot-handoff record
consumption, and negative paths.
The attestation IAK suite runs wolfHSM NVM with both the default 8-byte and
STM32H5 16-byte flash programming units.

Additional host checks:

Expand Down
2 changes: 1 addition & 1 deletion lib/wolfHSM
Submodule wolfHSM updated 260 files
2 changes: 1 addition & 1 deletion lib/wolfSSL
Submodule wolfSSL updated 1821 files
1 change: 1 addition & 0 deletions mk/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ WOLFCRYPT_SECURE_SRCS := \
$(WOLFSSL_DIR)/wolfcrypt/src/hash.c \
$(WOLFSSL_DIR)/wolfcrypt/src/hmac.c \
$(WOLFSSL_DIR)/wolfcrypt/src/logging.c \
$(WOLFSSL_DIR)/wolfcrypt/src/memory.c \
$(WOLFSSL_DIR)/wolfcrypt/src/random.c \
$(WOLFSSL_DIR)/wolfcrypt/src/sha256.c \
$(ARCH_WOLFCRYPT_SP_SRCS) \
Expand Down
52 changes: 52 additions & 0 deletions src/services/wolfhsm/runner/libc_stubs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* libc_stubs.h
*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfTrust.
*
* wolfTrust 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.
*
* wolfTrust 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335,
* USA
*/

#ifndef WOLFTRUST_LIBC_STUBS_H
#define WOLFTRUST_LIBC_STUBS_H

#include <stddef.h>

void* memcpy(void* dst, const void* src, size_t size);
void* memset(void* dst, int value, size_t size);
void* memmove(void* dst, const void* src, size_t size);
int memcmp(const void* lhs, const void* rhs, size_t size);

size_t strlen(const char* str);
int strcmp(const char* lhs, const char* rhs);
int strncmp(const char* lhs, const char* rhs, size_t size);
char* strncpy(char* dst, const char* src, size_t size);
int strcasecmp(const char* lhs, const char* rhs);
int strncasecmp(const char* lhs, const char* rhs, size_t size);

int tolower(int value);
int toupper(int value);
int isspace(int value);
int isdigit(int value);
int isalpha(int value);
int isalnum(int value);
int isxdigit(int value);
int isupper(int value);
int islower(int value);
int iscntrl(int value);
int isprint(int value);

#endif /* WOLFTRUST_LIBC_STUBS_H */
10 changes: 10 additions & 0 deletions src/services/wolfhsm/runner/user_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
* Disable the TLS/SSL layer — wolfCrypt primitives only.
* ---------------------------------------------------------------------- */
#define WOLFCRYPT_ONLY
#define NO_CRYPT_BENCHMARK

/* -------------------------------------------------------------------------
* No heap.
Expand All @@ -51,9 +52,17 @@
* static or stack-owned objects. NO_WOLFSSL_MEMORY avoids wolfSSL's allocator
* layer entirely, while WOLFSSL_NO_MALLOC makes any accidental XMALLOC path
* fail closed instead of requiring malloc/sbrk or a static heap arena.
* NO_STDLIB_H and NO_STRING_H keep the freestanding Cortex-M build
* independent of libc headers; the linked local stubs provide these calls.
* ---------------------------------------------------------------------- */
#define NO_WOLFSSL_MEMORY
#define WOLFSSL_NO_MALLOC
#define NO_STDLIB_H
#define NO_STRING_H
#define NO_CTYPE_H
#define WOLFSSL_NO_ASSERT_H

#include "libc_stubs.h"

/* -------------------------------------------------------------------------
* Threading model: single-threaded from wolfCrypt's perspective.
Expand All @@ -66,6 +75,7 @@
* No OS services.
* ---------------------------------------------------------------------- */
#define NO_FILESYSTEM
#define NO_STDIO_FILESYSTEM
#define NO_WOLFSSL_DIR
#define WOLFSSL_USER_IO /* no BSD socket I/O callbacks needed */
#define NO_WRITEV
Expand Down
3 changes: 3 additions & 0 deletions src/services/wolfhsm/runner/wh_settings_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,7 @@
*---------------------------------------------------------------------------*/
#define WOLFHSM_CFG_NO_SYS_TIME

/* The secure image is freestanding and leaves wolfHSM debug output disabled. */
#define WOLFHSM_CFG_PRINTF(...) ((int)0)

#endif /* WOLFTRUST_SECURE_WH_SETTINGS_LOCAL_H */
6 changes: 4 additions & 2 deletions src/services/wolfhsm/wt_hsm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1115,11 +1115,13 @@ static int wt_hsm_attest_generate_key(void)
}
if (ret == WH_ERROR_OK) {
result = (whMessageCrypto_EccKeyGenResponse*)responsePayload;
if ((responseSize !=
if ((responseSize <
sizeof(whMessageCrypto_GenericResponseHeader) +
sizeof(*result)) ||
(result->keyId != WT_HSM_ATTEST_KEY_ID) ||
(result->len != 0u)) {
(result->len != responseSize -
sizeof(whMessageCrypto_GenericResponseHeader) -
sizeof(*result))) {
ret = WH_ERROR_ABORTED;
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/firmware/stm32h563/nonsecure/guest.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

#define WT_ALIGNED_WORD __attribute__((aligned(4)))

int wolfhsm_guest_init(void);
int wolfhsm_guest_init(uint32_t client_id);
int wolfcrypt_benchmark_main(int argc, char** argv);

/* Static buffers to keep large structs off the stack. */
Expand Down Expand Up @@ -878,7 +878,7 @@ static void run_hsm_selftest(void)
uint32_t bench_i;

/* --- Step 1: Init wolfHSM client --- */
rc = wolfhsm_guest_init();
rc = wolfhsm_guest_init(wt_guest_id() + 1u);
if (rc != 0) {
wt_uart_putc('g');
wt_uart_put_u32(wt_guest_id());
Expand Down
14 changes: 11 additions & 3 deletions tests/firmware/stm32h563/nonsecure/wolfhsm_client_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ static whClientContext g_client_ctx;
static whClientConfig g_client_cfg;
static whCommClientConfig g_comm_cfg;
static int g_client_ready;
static uint32_t g_client_id;

/* ---------------------------------------------------------------------------
* Public API
Expand All @@ -78,16 +79,21 @@ static int g_client_ready;
* Call this once from Reset_Handler (or equivalent early-init code) after
* .data/.bss are ready. wc_* calls will be routed to the secure HSM once
* this returns WH_ERROR_OK. */
int wolfhsm_guest_init(void)
int wolfhsm_guest_init(uint32_t client_id)
{
int rc;

if (client_id == 0u) {
return WH_ERROR_BADARGS;
}

g_client_ready = 0;
g_client_id = client_id;

g_comm_cfg.transport_cb = &wt_hsm_psa_transport_cb;
g_comm_cfg.transport_context = &g_guest_tx;
g_comm_cfg.transport_config = &g_guest_tx_cfg;
g_comm_cfg.client_id = 0u;
g_comm_cfg.client_id = g_client_id;

g_client_cfg.comm = &g_comm_cfg;

Expand Down Expand Up @@ -124,7 +130,9 @@ int wolftrust_guest_rng_stub(unsigned char *output, unsigned int sz)
}
/* Boot can race a Secure Partition restart window; one failed init must
* not be terminal — retry the connect on demand. */
if (g_client_ready == 0 && wolfhsm_guest_init() != WH_ERROR_OK) {
if (g_client_ready == 0 &&
(g_client_id == 0u ||
wolfhsm_guest_init(g_client_id) != WH_ERROR_OK)) {
return -1;
}

Expand Down
12 changes: 2 additions & 10 deletions tests/firmware/zephyr-stm32h5/apps/freertos_guest1/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@

#include "wolfssl/wolfcrypt/settings.h"
#include "wolfssl/wolfcrypt/random.h"
#include "wolfssl/wolfcrypt/cryptocb.h"

#include "wolfhsm/wh_error.h"
#include "wolfhsm/wh_client.h"
#include "wolfhsm/wh_client_cryptocb.h"

#include <psa/crypto.h>
#include "wolfpsa/psa_engine.h"
Expand All @@ -42,7 +40,6 @@

/* wolfHSM client glue (module/wolfhsm-client/src/wolfhsm_client_glue.c). */
int wolfhsm_guest_init(void);
int wolfhsm_guest_cryptocb(int devId, wc_CryptoInfo *info, void *ctx);
whClientContext *wolfhsm_guest_client(void);
int wolftrust_guest_rng_stub(unsigned char *output, unsigned int sz);

Expand Down Expand Up @@ -376,8 +373,8 @@ static void run_ffm_negatives(void)
}

/* Bring up the single mediated crypto path: the wolfHSM client over the
* SPM-mediated psa_call transport, its cryptocb registered on WH_DEV_ID, and
* wolfPSA threading that devId through wolfCrypt exactly guest0's wiring,
* SPM-mediated psa_call transport registers WH_DEV_ID during client init, and
* wolfPSA threads that devId through wolfCrypt, exactly guest0's wiring,
* minus the Zephyr SYS_INIT hooks it does not have. */
static int guest_crypto_init(void)
{
Expand All @@ -392,11 +389,6 @@ static int guest_crypto_init(void)
uart_put_i32((int32_t)rc);
uart_puts("\r\n");
}
rc = wc_CryptoCb_RegisterDevice(WH_DEV_ID, wolfhsm_guest_cryptocb, NULL);
if (rc != 0) {
uart_puts("freertos_guest1: cryptocb register FAILED\r\n");
return -1;
}
(void)wolfPSA_SetDefaultDevID(WH_DEV_ID);
/* PSA requires psa_crypto_init before any other psa_* call; guest0 gets
* this from wolfPSA's Zephyr SYS_INIT, the bare FreeRTOS guest does it
Expand Down
4 changes: 2 additions & 2 deletions tests/firmware/zephyr-stm32h5/apps/guest0_psa/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,10 +574,10 @@ static void exercise_hsm_attack_probe(void)
rc = wh_Client_SendRequest(ctx, WH_MESSAGE_GROUP_NVM,
WH_MESSAGE_NVM_ACTION_READ, (uint16_t)sizeof(nvmbuf), nvmbuf);
if (rc == WH_ERROR_OK) {
rSize = (uint16_t)sizeof(nvmbuf);
guard2 = 1000;
do {
rc = wh_Client_RecvResponse(ctx, &rGroup, &rAction, &rSize, nvmbuf);
rc = wh_Client_RecvResponse(ctx, &rGroup, &rAction, &rSize,
(uint16_t)sizeof(nvmbuf), nvmbuf);
} while (rc == WH_ERROR_NOTREADY && guard2-- > 0);
}
if (rc != WH_ERROR_OK) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@
#include "wolfhsm/wh_comm.h"
#include "wolfhsm/wh_client.h"
#include "wolfhsm/wh_client_crypto.h"
#include "wolfhsm/wh_client_cryptocb.h"

#include "wolfssl/wolfcrypt/cryptocb.h"

#include "wolftrust/hsm_psa_transport.h"

/* SERVICE_HSM from the platform manifest (port/stm32h563/manifest.json). */
#define WT_SERVICE_HSM_SID 4102u
#define WT_SERVICE_HSM_VERSION 1u

#ifndef WT_WOLFHSM_CLIENT_ID
#define WT_WOLFHSM_CLIENT_ID 1u
#endif

static wt_hsm_psa_transport_ctx_t g_guest_tx;

static const wt_hsm_psa_transport_cfg_t g_guest_tx_cfg = {
Expand All @@ -64,7 +64,7 @@ int wolfhsm_guest_init(void)
g_comm_cfg.transport_cb = &wt_hsm_psa_transport_cb;
g_comm_cfg.transport_context = &g_guest_tx;
g_comm_cfg.transport_config = &g_guest_tx_cfg;
g_comm_cfg.client_id = 0u;
g_comm_cfg.client_id = WT_WOLFHSM_CLIENT_ID;

g_client_cfg.comm = &g_comm_cfg;

Expand All @@ -82,9 +82,8 @@ whClientContext *wolfhsm_guest_client(void)
return &g_client_ctx;
}

/* Boot can race a Secure Partition restart window (the SPM refuses connects
* while the relay recovers), so one failed init must not be terminal —
* heal on demand by retrying the connect on the next crypto request. */
/* Retry initialization for the direct RNG hook if early initialization did
* not complete. */
static int wolfhsm_guest_ensure_ready(void)
{
if (g_client_ready != 0) {
Expand All @@ -93,15 +92,6 @@ static int wolfhsm_guest_ensure_ready(void)
return wolfhsm_guest_init();
}

int wolfhsm_guest_cryptocb(int devId, wc_CryptoInfo *info, void *ctx)
{
(void)ctx;
if (wolfhsm_guest_ensure_ready() != WH_ERROR_OK) {
return CRYPTOCB_UNAVAILABLE;
}
return wh_Client_CryptoCb(devId, info, &g_client_ctx);
}

int wolftrust_guest_rng_stub(unsigned char *output, unsigned int sz)
{
if (output == NULL && sz != 0u) {
Expand Down
Loading
Loading