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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/build-and-run-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,30 @@ jobs:
done
done
done

# The client and the server are separate binaries with separate
# user_settings.h, so the client can be built with no software SLH-DSA at
# all while the server keeps its own. That is the only way to prove the
# callback-only path really reaches the server: with the software stripped
# the client has nothing to fall back to, so a passing demo means every
# SLH-DSA operation was served over the wire. Only one transport needs to
# run it; the ONLY macro is orthogonal to the transport.
- 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
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;
}
91 changes: 91 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

#include "wh_demo_client_crypto.h"

#if !defined(NO_RSA)
Expand Down Expand Up @@ -1692,4 +1696,91 @@ 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 use it purely by key
* id. Only the smallest parameter set produces a signature that fits the comm
* buffer, so that is what this demo asks for. */
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);

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;
}

/* The private key is generated on and never leaves the HSM; only the
* public key comes back. */
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 holds no key material at all, 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;
}

ret = wc_SlhDsaKey_SignDeterministic(handle, NULL, 0, message,
sizeof(message), signature, &sigLen);
if (ret != 0) {
WOLFHSM_CFG_PRINTF("Failed to wc_SlhDsaKey_SignDeterministic %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_ */
7 changes: 7 additions & 0 deletions examples/posix/wh_posix_client/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ ifeq ($(AUTH),1)
DEF += -DWOLFHSM_CFG_ENABLE_AUTHENTICATION
endif

# Strip the software SLH-DSA from the client so every operation has to reach
# the server. The server is a separate binary with its own settings, so it
# keeps its software implementation.
ifeq ($(SLHDSA_CB_ONLY),1)
DEF += -DWH_CFG_SLHDSA_CB_ONLY
endif

else
DEF += -DWOLFHSM_CFG_NO_CRYPTO
endif
Expand Down
17 changes: 17 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,23 @@
#define WOLFSSL_CMAC
#define HAVE_HKDF

/* SLH-DSA. Only the smallest parameter set is built: its 7856-byte signature
* is the only one that fits 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

/* Build the client with no software SLH-DSA at all, so every operation must
* reach the server or fail closed. Set -DWH_CFG_SLHDSA_CB_ONLY to select it;
* the server keeps its software implementation either way. */
#ifdef WH_CFG_SLHDSA_CB_ONLY
#define WOLF_CRYPTO_CB_ONLY_SLHDSA
#endif

/* wolfCrypt benchmark settings */
#define NO_MAIN_DRIVER
#define BENCH_EMBEDDED
Expand Down
7 changes: 7 additions & 0 deletions examples/posix/wh_posix_server/user_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,13 @@ extern "C" {
#define WOLFSSL_MLDSA_NO_MAKE_KEY
#endif

/* SLH-DSA Options. Only the smallest parameter set is built: its 7856-byte
* signature is the only one that fits 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