Skip to content
Open
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
20 changes: 20 additions & 0 deletions .github/workflows/build-and-run-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,23 @@ jobs:
done
done
done

- name: Build and run the callback-only SLH-DSA client
if: ${{ matrix.transport == 'tcp' }}
run: |
WS="$(pwd)"
SERVER_DIR="$WS/examples/posix/wh_posix_server"
CLIENT_DIR="$WS/examples/posix/wh_posix_client"
make -C "$SERVER_DIR" clean
make -C "$CLIENT_DIR" clean
DEMO_KEK=1 make -C "$SERVER_DIR" -j WOLFSSL_DIR=../../../wolfssl
SLHDSA_CB_ONLY=1 make -C "$CLIENT_DIR" -j WOLFSSL_DIR=../../../wolfssl
rm -f "$SERVER_DIR"/*.bin
cd "$SERVER_DIR"
./Build/wh_posix_server.elf --type tcp &
SERVER_PID=$!
sleep 1
cd "$CLIENT_DIR"
./Build/wh_posix_client.elf --type tcp --test
kill $SERVER_PID 2>/dev/null || true
wait $SERVER_PID 2>/dev/null || true
4 changes: 4 additions & 0 deletions .github/workflows/build-and-test-refactor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ jobs:
if: matrix.group == 'pq-dma'
run: cd test-refactor/posix && make clean && make -j DMA=1 ASAN=1 NOKEYGEN=1 LMS_VERIFY_ONLY=1 XMSS_VERIFY_ONLY=1 WOLFSSL_DIR=../../wolfssl && make run

- name: Build and test refactor DMA ASAN SLHDSA verify-only
if: matrix.group == 'pq-dma'
run: cd test-refactor/posix && make clean && make -j DMA=1 ASAN=1 SLHDSA_VERIFY_ONLY=1 WOLFSSL_DIR=../../wolfssl && make run

# Build and test ASAN build, with wolfCrypt tests enabled.
- name: Build and test refactor ASAN TESTWOLFCRYPT
if: matrix.group == 'wolfcrypt'
Expand Down
2 changes: 1 addition & 1 deletion docs/src/2-FAQs.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ Clients reach these algorithms through the wolfHSM client library, which offload

## Does wolfHSM support post-quantum cryptography?

Yes! wolfHSM supports ML-KEM (FIPS 203) for key exchange and ML-DSA (FIPS 204), LMS, and XMSS for digital signatures, with more algorithms being added every day. Clients use them through the standard wolfCrypt API like any other algorithm, and private keys can be generated on the server so they never leave the HSM.
Yes! wolfHSM supports ML-KEM (FIPS 203) for key exchange and ML-DSA (FIPS 204), SLH-DSA (FIPS 205), LMS, and XMSS for digital signatures, with more algorithms being added every day. Clients use them through the standard wolfCrypt API like any other algorithm, and private keys can be generated on the server so they never leave the HSM.

Like any algorithm without hardware support, post-quantum algorithms run in wolfCrypt software on the HSM core unless the port provides a hardware driver for them.

Expand Down
2 changes: 1 addition & 1 deletion docs/src/5-Features.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ The wolfHSM server exposes the full set of wolfCrypt software algorithms, and th
- **Message authentication**: HMAC (over the supported hash functions) and CMAC
- **Asymmetric**: RSA (encryption, signing, key generation), ECC (ECDSA, ECDH, public key derivation, key validation), Ed25519, Curve25519
- **Random number generation**: DRBG/RNG backed by the server's entropy source
- **Post-quantum cryptography**: ML-DSA (FIPS 204) and ML-KEM (FIPS 203)
- **Post-quantum cryptography**: ML-DSA (FIPS 204), SLH-DSA (FIPS 205) and ML-KEM (FIPS 203)

For the authoritative list of algorithms, parameter ranges, and options, see the [wolfCrypt API reference](https://www.wolfssl.com/documentation/manuals/wolfssl/index.html). An algorithm not yet wired through the crypto callback can still be used locally against the client's own wolfCrypt instance — only operations dispatched to the client's `devId` are offloaded.

Expand Down
7 changes: 7 additions & 0 deletions examples/demo/client/wh_demo_client_all.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,5 +201,12 @@ int wh_DemoClient_All(whClientContext* clientContext)

#endif /* WOLFSSL_CMAC */

#if defined(WOLFSSL_HAVE_SLHDSA) && !defined(WOLFSSL_SLHDSA_VERIFY_ONLY)
rc = wh_DemoClient_CryptoSlhDsa(clientContext);
if (rc != 0) {
return rc;
}
#endif /* WOLFSSL_HAVE_SLHDSA && !WOLFSSL_SLHDSA_VERIFY_ONLY */

return rc;
}
92 changes: 92 additions & 0 deletions examples/demo/client/wh_demo_client_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
#include "wolfssl/wolfcrypt/kdf.h"
#endif

#ifdef WOLFSSL_HAVE_SLHDSA
#include "wolfssl/wolfcrypt/wc_slhdsa.h"
#endif /* WOLFSSL_HAVE_SLHDSA */

#include "wh_demo_client_crypto.h"

#if !defined(NO_RSA)
Expand Down Expand Up @@ -1692,4 +1696,92 @@ int wh_DemoClient_CryptoCmacKdfCacheInputs(whClientContext* clientContext)

#endif /* HAVE_CMAC_KDF && WOLFSSL_CMAC */

#if defined(WOLFSSL_HAVE_SLHDSA) && !defined(WOLFSSL_SLHDSA_VERIFY_ONLY)

/* Generate an SLH-DSA key that stays on the server and reference it by ID. */
int wh_DemoClient_CryptoSlhDsa(whClientContext* clientContext)
{
int ret;
int devId = WH_CLIENT_DEVID(clientContext);
whKeyId keyId = WH_KEYID_ERASED;
SlhDsaKey pub[1];
SlhDsaKey handle[1];
uint8_t label[] = "slhdsa-demo";
byte message[] = "wolfHSM SLH-DSA demo message";
byte signature[WC_SLHDSA_SHAKE128S_SIG_LEN];
word32 sigLen = sizeof(signature);
byte addRnd[WC_SLHDSA_MAX_SEED];

/* Placeholder for user-supplied random input */
memset(addRnd, 0x42, sizeof(addRnd));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The answer to the ultimate question. But perhaps also a comment saying "placeholder for user-supplied random input"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comment


ret = wc_SlhDsaKey_Init(pub, SLHDSA_SHAKE128S, NULL, devId);
if (ret != 0) {
WOLFHSM_CFG_PRINTF("Failed to wc_SlhDsaKey_Init %d\n", ret);
return ret;
}

ret = wc_SlhDsaKey_Init(handle, SLHDSA_SHAKE128S, NULL, devId);
if (ret != 0) {
WOLFHSM_CFG_PRINTF("Failed to wc_SlhDsaKey_Init %d\n", ret);
wc_SlhDsaKey_Free(pub);
return ret;
}

/* Private key stays on the HSM; only the public key is returned */
ret = wh_Client_SlhDsaMakeCacheKeyAndExportPublic(
clientContext, SLHDSA_SHAKE128S, &keyId,
WH_NVM_FLAGS_USAGE_SIGN | WH_NVM_FLAGS_USAGE_VERIFY, sizeof(label),
label, pub);
if (ret != 0) {
WOLFHSM_CFG_PRINTF("Failed to generate SLH-DSA key %d\n", ret);
goto exit;
}

/* handle contains no key material, just the server key id */
ret = wh_Client_SlhDsaSetKeyId(handle, keyId);
if (ret != 0) {
WOLFHSM_CFG_PRINTF("Failed to wh_Client_SlhDsaSetKeyId %d\n", ret);
goto exit;
}

/* handle has no PK.seed, so supply the randomizer */
ret = wc_SlhDsaKey_SignWithRandom(handle, NULL, 0, message, sizeof(message),
signature, &sigLen, addRnd);
if (ret != 0) {
WOLFHSM_CFG_PRINTF("Failed to wc_SlhDsaKey_SignWithRandom %d\n", ret);
goto exit;
}

ret = wc_SlhDsaKey_Verify(pub, NULL, 0, message, sizeof(message), signature,
sigLen);
if (ret != 0) {
WOLFHSM_CFG_PRINTF("Failed to wc_SlhDsaKey_Verify %d\n", ret);
goto exit;
}

/* A tampered signature must not verify */
signature[0] ^= 0xFF;
if (wc_SlhDsaKey_Verify(pub, NULL, 0, message, sizeof(message), signature,
sigLen) == 0) {
WOLFHSM_CFG_PRINTF("SLH-DSA verified a tampered signature\n");
ret = -1;
goto exit;
}

WOLFHSM_CFG_PRINTF("SLH-DSA sign/verify with a server-resident key: "
"SUCCESS\n");
ret = 0;

exit:
if (!WH_KEYID_ISERASED(keyId)) {
(void)wh_Client_KeyEvict(clientContext, keyId);
}
wc_SlhDsaKey_Free(handle);
wc_SlhDsaKey_Free(pub);
return ret;
}

#endif /* WOLFSSL_HAVE_SLHDSA && !WOLFSSL_SLHDSA_VERIFY_ONLY */

#endif /* WOLFHSM_CFG_NO_CRYPTO */
2 changes: 2 additions & 0 deletions examples/demo/client/wh_demo_client_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ int wh_DemoClient_CryptoCmacKdfExport(whClientContext* clientContext);
int wh_DemoClient_CryptoCmacKdfCache(whClientContext* clientContext);
int wh_DemoClient_CryptoCmacKdfCacheInputs(whClientContext* clientContext);

int wh_DemoClient_CryptoSlhDsa(whClientContext* clientContext);

#endif /* !DEMO_CLIENT_CRYPTO_H_ */
4 changes: 4 additions & 0 deletions examples/posix/wh_posix_client/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ ifeq ($(AUTH),1)
DEF += -DWOLFHSM_CFG_ENABLE_AUTHENTICATION
endif

ifeq ($(SLHDSA_CB_ONLY),1)
DEF += -DWOLFHSM_CFG_SLHDSA_CB_ONLY
endif

else
DEF += -DWOLFHSM_CFG_NO_CRYPTO
endif
Expand Down
13 changes: 13 additions & 0 deletions examples/posix/wh_posix_client/user_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@
#define WOLFSSL_CMAC
#define HAVE_HKDF

/* SLH-DSA: only 128s fits in the default WOLFHSM_CFG_COMM_DATA_LEN */
#define WOLFSSL_HAVE_SLHDSA
#define WOLFSSL_SHA3
#define WOLFSSL_SHAKE128
#define WOLFSSL_SHAKE256
#define WOLFSSL_SLHDSA_PARAM_NO_128F
#define WOLFSSL_SLHDSA_PARAM_NO_192
#define WOLFSSL_SLHDSA_PARAM_NO_256

#ifdef WOLFHSM_CFG_SLHDSA_CB_ONLY
#define WOLF_CRYPTO_CB_ONLY_SLHDSA
#endif /* WOLFHSM_CFG_SLHDSA_CB_ONLY */

/* wolfCrypt benchmark settings */
#define NO_MAIN_DRIVER
#define BENCH_EMBEDDED
Expand Down
8 changes: 7 additions & 1 deletion examples/posix/wh_posix_server/user_settings.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2024 wolfSSL Inc.
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfHSM.
*
Expand Down Expand Up @@ -150,6 +150,12 @@ extern "C" {
#define WOLFSSL_MLDSA_NO_MAKE_KEY
#endif

/* SLH-DSA: only 128s fits in the default WOLFHSM_CFG_COMM_DATA_LEN */
#define WOLFSSL_HAVE_SLHDSA
#define WOLFSSL_SLHDSA_PARAM_NO_128F
#define WOLFSSL_SLHDSA_PARAM_NO_192
#define WOLFSSL_SLHDSA_PARAM_NO_256

/* ML-KEM Options */
#define WOLFSSL_HAVE_MLKEM

Expand Down
Loading
Loading