diff --git a/README.md b/README.md
index 09ecc3fa..6caefd8d 100644
--- a/README.md
+++ b/README.md
@@ -379,6 +379,16 @@ Please see the [utasker/README.md](utasker/README.md) for further usage and
details.
+
+
+#### HSM (Hardware Security Module)
+
+This directory contains examples demonstrating wolfSSL integration with wolfHSM,
+a portable Hardware Security Module framework.
+
+Please see the [wolfhsm/README.md](wolfhsm/README.md) for further details.
+
+
#### UEFI (wolfCrypt UEFI application Example)
diff --git a/hsm/README.md b/hsm/README.md
new file mode 100644
index 00000000..8991aaad
--- /dev/null
+++ b/hsm/README.md
@@ -0,0 +1,23 @@
+# wolfHSM Examples
+
+Examples demonstrating wolfSSL integration with [wolfHSM](https://github.com/wolfssl/wolfhsm),
+a portable Hardware Security Module (HSM) framework.
+
+## Examples
+
+### DTLS Client (`dtls_client/`)
+
+DTLS client with HSM-backed cryptography. Private keys stay on the HSM.
+
+Quick start:
+```bash
+cd dtls_client
+make download_repos all
+# Then run each component in separate terminals (see README)
+```
+
+See [dtls_client/README.md](dtls_client/README.md) for details.
+
+## Support
+
+For questions please email support@wolfssl.com
diff --git a/hsm/dtls_client/Makefile b/hsm/dtls_client/Makefile
new file mode 100644
index 00000000..79bc3e30
--- /dev/null
+++ b/hsm/dtls_client/Makefile
@@ -0,0 +1,166 @@
+# wolfHSM DTLS Client Example
+#
+# Usage:
+# make download_repos # Clone wolfSSL and wolfHSM repos
+# make all # Build everything (wolfSSL server, wolfHSM server, client)
+# make run_hsm_server # Start wolfHSM server
+# make run_dtls_server # Start wolfSSL DTLS server
+# make run_client # Run the DTLS client
+# make clean # Clean build artifacts
+# make clean_repos # Remove cloned repositories
+
+BIN = wh_dtls_client
+
+WOLFSSL_DIR ?= ./wolfssl
+WOLFHSM_DIR ?= ./wolfhsm
+WOLFHSM_PORT_DIR = $(WOLFHSM_DIR)/port/posix
+WOLFHSM_SERVER_DIR = $(WOLFHSM_DIR)/examples/posix/wh_posix_server
+
+PROJECT_DIR = .
+BUILD_DIR = $(PROJECT_DIR)/Build
+
+# Compiler settings
+CC = gcc
+CSTD = -std=c99
+CFLAGS_EXTRA = -Werror -Wall -Wextra -ffunction-sections -fdata-sections
+CFLAGS = $(CSTD) $(CFLAGS_EXTRA)
+DEF = -D_POSIX_C_SOURCE=200809L -DWOLFSSL_USER_SETTINGS -DWOLFHSM_CFG
+DEF += -DWC_USE_DEVID=0x5748534D
+
+INC = -I$(PROJECT_DIR) -I$(WOLFSSL_DIR) -I$(WOLFHSM_DIR) -I$(WOLFHSM_PORT_DIR)
+
+# Linker settings
+LDFLAGS = -Wl,--gc-sections
+LIBS = -lc -lm
+
+# Source files (wolfCrypt, wolfSSL, wolfHSM, port, project)
+WOLFCRYPT_SRC := $(wildcard $(WOLFSSL_DIR)/wolfcrypt/src/*.c)
+SRC_C = $(filter-out %/evp.c %/misc.c,$(WOLFCRYPT_SRC))
+WOLFSSL_SRC := $(wildcard $(WOLFSSL_DIR)/src/*.c)
+SRC_C += $(filter-out %/bio.c %/conf.c %/pk.c %/ssl_asn1.c %/ssl_bn.c %/ssl_certman.c %/ssl_crypto.c %/ssl_load.c %/ssl_misc.c %/ssl_p7p12.c %/ssl_sess.c %/ssl_sk.c %/x509.c %/x509_str.c,$(WOLFSSL_SRC))
+SRC_C += $(wildcard $(WOLFHSM_DIR)/src/*.c)
+SRC_C += $(wildcard $(WOLFHSM_PORT_DIR)/*.c)
+SRC_C += $(wildcard $(PROJECT_DIR)/*.c)
+
+# Debug support
+ifeq ($(DEBUG),1)
+ CFLAGS += -ggdb -g3
+ LDFLAGS += -ggdb -g3
+ DEF += -DWOLFHSM_CFG_DEBUG
+endif
+
+# Object files
+FILENAMES_C = $(notdir $(SRC_C))
+OBJS_C = $(addprefix $(BUILD_DIR)/, $(FILENAMES_C:.c=.o))
+vpath %.c $(dir $(SRC_C))
+
+# Phony targets
+.PHONY: all download_repos build_wolfssl build_wolfhsm_server build_app run_hsm_server run_dtls_server run_client clean clean_repos
+
+# Default target
+all: check_repos build_wolfssl build_wolfhsm_server build_app
+ @echo "Build complete. Run 'make help' for usage instructions."
+
+# Clone repositories
+download_repos:
+ @echo "=== Cloning repositories ==="
+ @if [ ! -d "$(WOLFSSL_DIR)" ]; then \
+ git clone --depth 1 https://github.com/wolfssl/wolfssl.git $(WOLFSSL_DIR); \
+ else \
+ echo "wolfssl already exists, skipping clone"; \
+ fi
+ @if [ ! -d "$(WOLFHSM_DIR)" ]; then \
+ git clone --depth 1 https://github.com/wolfssl/wolfhsm.git $(WOLFHSM_DIR); \
+ else \
+ echo "wolfhsm already exists, skipping clone"; \
+ fi
+
+# Check that repos exist
+check_repos:
+ @if [ ! -d "$(WOLFSSL_DIR)" ] || [ ! -d "$(WOLFHSM_DIR)" ]; then \
+ echo "Error: Repositories not found. Run 'make download_repos' first."; \
+ exit 1; \
+ fi
+
+# Build wolfSSL
+# Note: The DTLS client uses its own user_settings.h to build wolfSSL statically,
+# so this configure is only for the wolfSSL example server/client binaries.
+build_wolfssl: check_repos
+ @echo "=== Building wolfSSL ==="
+ @if [ ! -f "$(WOLFSSL_DIR)/examples/server/server" ]; then \
+ cd $(WOLFSSL_DIR) && \
+ ./autogen.sh && \
+ ./configure --enable-dtls --enable-dtls13 --enable-ecc && \
+ make -j; \
+ else \
+ echo "wolfSSL already built, skipping"; \
+ fi
+
+# Build wolfHSM POSIX server
+# Note: The wolfHSM server Makefile expects WOLFSSL_DIR relative to its location
+# Server is at ./wolfhsm/examples/posix/wh_posix_server/
+# wolfssl is at ./wolfssl/
+# So from server: ../../../../wolfssl
+build_wolfhsm_server: check_repos
+ @echo "=== Building wolfHSM server ==="
+ @if [ ! -f "$(WOLFHSM_SERVER_DIR)/Build/wh_posix_server.elf" ]; then \
+ $(MAKE) -C $(WOLFHSM_SERVER_DIR) clean || true; \
+ $(MAKE) -C $(WOLFHSM_SERVER_DIR) WOLFSSL_DIR=../../../../wolfssl -j; \
+ else \
+ echo "wolfHSM server already built, skipping"; \
+ fi
+
+# Build DTLS client
+build_app: $(BUILD_DIR) $(BUILD_DIR)/$(BIN).elf
+ @echo "DTLS client built: $(BUILD_DIR)/$(BIN).elf"
+
+$(BUILD_DIR):
+ mkdir -p $(BUILD_DIR)
+
+$(BUILD_DIR)/%.o: %.c
+ @echo "Compiling: $(notdir $<)"
+ $(CC) $(CFLAGS) $(DEF) $(INC) -c -o $@ $<
+
+$(BUILD_DIR)/$(BIN).elf: $(OBJS_C)
+ @echo "Linking: $(notdir $@)"
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+# Convenience targets for running each component in separate terminals
+
+run_hsm_server: all
+ @echo "Starting wolfHSM server..."
+ @echo "Press Ctrl+C to stop"
+ @echo ""
+ $(WOLFHSM_SERVER_DIR)/Build/wh_posix_server.elf --type tcp \
+ --key $(WOLFSSL_DIR)/certs/ecc-client-key.der \
+ --id 1 --client 12
+
+run_dtls_server: all
+ @echo "Starting wolfSSL DTLS server..."
+ @echo "Press Ctrl+C to stop"
+ @echo ""
+ cd $(WOLFSSL_DIR) && ./examples/server/server -u -v 4 \
+ -c ./certs/server-ecc.pem \
+ -k ./certs/ecc-key.pem \
+ -A ./certs/client-ecc-cert.pem \
+ -p 11111 -i
+
+run_client: all
+ $(BUILD_DIR)/$(BIN).elf 127.0.0.1
+
+# Clean build artifacts
+clean:
+ @echo "Cleaning build files"
+ rm -rf $(BUILD_DIR)
+ @# Clean wolfHSM server build
+ @if [ -d "$(WOLFHSM_SERVER_DIR)" ]; then \
+ $(MAKE) -C $(WOLFHSM_SERVER_DIR) clean 2>/dev/null || true; \
+ fi
+ @# Clean wolfSSL build
+ @if [ -f "$(WOLFSSL_DIR)/Makefile" ]; then \
+ $(MAKE) -C $(WOLFSSL_DIR) clean 2>/dev/null || true; \
+ fi
+
+clean_repos: clean
+ @echo "Removing cloned repositories"
+ rm -rf $(WOLFSSL_DIR) $(WOLFHSM_DIR)
diff --git a/hsm/dtls_client/README.md b/hsm/dtls_client/README.md
new file mode 100644
index 00000000..35a7dd5f
--- /dev/null
+++ b/hsm/dtls_client/README.md
@@ -0,0 +1,73 @@
+# wolfHSM DTLS Client Example
+
+Demonstrates a DTLS client using wolfHSM for cryptographic operations.
+All private key operations are performed on the HSM - keys never leave
+the secure environment.
+The example uses wolfHSM posix server for HSM communication/simulation.
+
+
+## Quick Start
+
+### Build
+```bash
+make download_repos # Clone repos (first time only)
+make all # Build everything
+```
+
+### Run (3 separate terminals)
+
+**Terminal 1** - Start wolfHSM posix server:
+```bash
+make run_hsm_server
+```
+
+**Terminal 2** - Start DTLS server:
+```bash
+make run_dtls_server
+```
+
+**Terminal 3** - Run client:
+```bash
+make run_client
+```
+
+## Using Existing Repositories
+
+```bash
+make WOLFSSL_DIR=/path/to/wolfssl WOLFHSM_DIR=/path/to/wolfhsm all
+```
+
+## Architecture
+
+```
++------------------+ TCP +------------------+
+| DTLS Client |<------------>| wolfHSM Server |
+| | | (crypto ops) |
++--------+---------+ +------------------+
+ | UDP/DTLS
+ v
++------------------+
+| DTLS Server |
+| (application) |
++------------------+
+```
+
+## Makefile Targets
+
+| Target | Description |
+|--------|-------------|
+| `download_repos` | Clone wolfSSL and wolfHSM |
+| `all` | Build everything (default) |
+| `run_hsm_server` | Start wolfHSM server (Terminal 1) |
+| `run_dtls_server` | Start wolfSSL DTLS server (Terminal 2) |
+| `run_client` | Run the DTLS client (Terminal 3) |
+| `clean` | Clean build artifacts |
+| `clean_repos` | Remove cloned repositories |
+| `help` | Show help |
+
+## Debug Build
+
+```bash
+make clean
+make DEBUG=1
+```
diff --git a/hsm/dtls_client/user_settings.h b/hsm/dtls_client/user_settings.h
new file mode 100644
index 00000000..412bd891
--- /dev/null
+++ b/hsm/dtls_client/user_settings.h
@@ -0,0 +1,52 @@
+#ifndef USER_SETTINGS_H_
+#define USER_SETTINGS_H_
+
+
+/* POSIX system headers */
+#define HAVE_SYS_TIME_H
+
+/** wolfHSM Client required settings */
+/* CryptoCB support - required for offloading crypto to HSM */
+#define WOLF_CRYPTO_CB
+#define HAVE_ANONYMOUS_INLINE_AGGREGATES 1
+
+/* PK callbacks - required for TLS-level HSM key operations */
+#define HAVE_PK_CALLBACKS
+
+/* Enable DTLS support */
+#define WOLFSSL_DTLS
+#define WOLFSSL_DTLS13
+#define WOLFSSL_TLS13
+#define HAVE_TLS_EXTENSIONS
+#define WOLFSSL_SEND_HRR_COOKIE
+
+/* Remove old TLS versions */
+#define NO_OLD_TLS
+
+/** Crypto Algorithm Options */
+
+/* ECC for ECDHE key exchange and ECDSA authentication */
+#define HAVE_ECC
+#define HAVE_SUPPORTED_CURVES
+
+/* AES-GCM for symmetric encryption */
+#define HAVE_AESGCM
+
+/* HKDF for key derivation */
+#define HAVE_HKDF
+
+/* Timing resistance / side-channel attack protection */
+#define TFM_TIMING_RESISTANT
+#define ECC_TIMING_RESISTANT
+#define WC_RSA_BLINDING
+
+/* Use wolfSSL's internal string comparison instead of system strcasecmp */
+#define USE_WOLF_STRCASECMP
+
+/* Remove unneeded features */
+#define NO_MAIN_DRIVER
+#define NO_DO178
+#define NO_RSA
+#define NO_DH
+
+#endif /* USER_SETTINGS_H_ */
diff --git a/hsm/dtls_client/wh_dtls_client.c b/hsm/dtls_client/wh_dtls_client.c
new file mode 100644
index 00000000..63e05fff
--- /dev/null
+++ b/hsm/dtls_client/wh_dtls_client.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2024 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 .
+ */
+/*
+ * wh_dtls_client.c
+ *
+ * wolfHSM DTLS Client Example
+ *
+ * This example demonstrates a DTLS client that uses wolfHSM as a cryptographic
+ * backend. ECC signing operations are performed on the HSM - private keys
+ * never leave the secure environment.
+ *
+ * The client makes two connections:
+ * 1. TCP to wolfHSM server - for all cryptographic operations
+ * 2. UDP to external DTLS server - for secure application communication
+ *
+ * Usage:
+ * 1. Start wolfHSM server with client private key:
+ * ./wh_posix_server.elf --type tcp \
+ * --key --id 1 --client 12
+ *
+ * 2. Start external DTLS server (from wolfssl directory):
+ * ./examples/server/server -u -v 3 \
+ * -c ./certs/server-ecc-cert.pem -k ./certs/ecc-key.pem \
+ * -A ./certs/client-ecc-cert.pem -V
+ *
+ * 3. Run this DTLS client:
+ * ./wh_dtls_client.elf 127.0.0.1
+ *
+ * Note: Client certificates are built-in from certs_test.h, eliminating
+ * the need for a fixed wolfssl directory location.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* wolfSSL headers */
+#include "wolfssl/wolfcrypt/settings.h"
+#include "wolfssl/ssl.h"
+#include "wolfssl/wolfcrypt/ecc.h"
+#include "wolfssl/wolfcrypt/cryptocb.h"
+
+/* Enable 256-bit ECC certificate buffers */
+#define USE_CERT_BUFFERS_256
+#include "wolfssl/certs_test.h"
+
+/* wolfHSM headers */
+#include "wolfhsm/wh_error.h"
+#include "wolfhsm/wh_comm.h"
+#include "wolfhsm/wh_client.h"
+#include "wolfhsm/wh_client_crypto.h"
+#include "wolfhsm/wh_client_cryptocb.h"
+
+/* posix headers */
+#include "wolfhsm/port/posix/posix_transport_tcp.h"
+
+/* Configuration constants (wolfHSM posix default port wh_posix_cfg.h) */
+#define HSM_POSIX_SERVER_TCP_PORT 23456
+#define HSM_POSIX_SERVER_TCP_IPSTRING "127.0.0.1"
+#define HSM_CLIENT_ID 12
+
+/* DTLS server connection parameters */
+#define DTLS_SERVER_PORT 11111
+#define MAX_LINE 4096
+
+/* Default HSM key ID for client private key (must match server --id parameter) */
+#define HSM_KEY_ID 1
+
+/* Context passed to crypto callback containing wolfHSM client info */
+typedef struct {
+ whClientContext* whClient; /* wolfHSM client context */
+ whKeyId clientKeyId; /* HSM key ID for client private key */
+} DtlsHsmCtx;
+
+static DtlsHsmCtx hsmCtx;
+
+static posixTransportTcpClientContext tccTcp;
+static posixTransportTcpConfig tcpConfig;
+static whCommClientConfig commConfig;
+static whTransportClientCb tcpCb = PTT_CLIENT_CB;
+
+/* wolfHSM client configuration setup for TCP transport to wolfHSM server */
+static int InitWolfHSMPosixTcpConfig(whClientConfig* conf)
+{
+
+ memset(&tccTcp, 0, sizeof(posixTransportTcpClientContext));
+ memset(&commConfig, 0, sizeof(whCommClientConfig));
+
+ tcpConfig.server_ip_string = HSM_POSIX_SERVER_TCP_IPSTRING;
+ tcpConfig.server_port = HSM_POSIX_SERVER_TCP_PORT;
+
+ commConfig.transport_cb = &tcpCb;
+ commConfig.transport_context = (void*)&tccTcp;
+ commConfig.transport_config = (void*)&tcpConfig;
+ commConfig.client_id = HSM_CLIENT_ID;
+ conf->comm = &commConfig;
+
+ return WH_ERROR_OK;
+}
+/**
+ * ECC Sign callback - called during TLS CertificateVerify
+ *
+ * This callback intercepts ECC signing operations during TLS handshake.
+ * Instead of using a local private key, it delegates signing to the HSM
+ * where the private key is stored.
+ *
+ * @param ssl wolfSSL session pointer (unused)
+ * @param in Hash to sign
+ * @param inSz Size of hash
+ * @param out Output buffer for signature
+ * @param outSz Input/output signature size
+ * @param keyDer DER-encoded key (unused - we use HSM key)
+ * @param keySz Size of DER key (unused)
+ * @param ctx User context containing HSM client and key ID
+ * @return 0 on success, negative on error
+ */
+static int myEccSignCb(WOLFSSL* ssl, const unsigned char* in, unsigned int inSz,
+ unsigned char* out, word32* outSz,
+ const unsigned char* keyDer, unsigned int keySz,
+ void* ctx)
+{
+ DtlsHsmCtx* hsmCtx = (DtlsHsmCtx*)ctx;
+ ecc_key eccKey[1];
+ int ret;
+ uint16_t sigLen;
+
+ (void)ssl;
+ (void)keyDer;
+ (void)keySz; /* unused - we use HSM key */
+
+ /* Initialize ECC key structure with HSM device ID */
+ ret = wc_ecc_init_ex(eccKey, NULL, WH_DEV_ID);
+ if (ret != 0) {
+ printf(" EccSignCb: wc_ecc_init_ex failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Set curve parameters (P-256) */
+ ret = wc_ecc_set_curve(eccKey, 32, ECC_SECP256R1);
+ if (ret != 0) {
+ printf(" EccSignCb: wc_ecc_set_curve failed: %d\n", ret);
+ wc_ecc_free(eccKey);
+ return ret;
+ }
+
+ /* Associate the HSM key ID with this ecc_key structure */
+ ret = wh_Client_EccSetKeyId(eccKey, hsmCtx->clientKeyId);
+ if (ret != 0) {
+ printf(" EccSignCb: wh_Client_EccSetKeyId failed: %d\n", ret);
+ wc_ecc_free(eccKey);
+ return ret;
+ }
+
+ /* Perform signing on HSM - private key never leaves the HSM */
+ sigLen = (uint16_t)*outSz;
+ ret = wh_Client_EccSign(hsmCtx->whClient, eccKey, in, (uint16_t)inSz, out,
+ &sigLen);
+ if (ret == 0) {
+ *outSz = sigLen;
+ }
+ else {
+ printf(" EccSignCb: wh_Client_EccSign failed: %d\n", ret);
+ }
+
+ wc_ecc_free(eccKey);
+ return ret;
+}
+
+static void Usage(const char* progName)
+{
+ printf("Usage: %s \n", progName);
+ printf(" DTLS server IP: IP address of the external DTLS server\n");
+ printf("\nBefore running this client, start the servers in separate terminals:\n");
+ printf("\n Terminal 1 - Start wolfHSM server:\n");
+ printf(" ./wh_posix_server.elf --type tcp \\\n");
+ printf(" --key --id 1 --client 12\n");
+ printf("\n Terminal 2 - Start wolfSSL DTLS server (from wolfssl directory):\n");
+ printf(" ./examples/server/server -u -v 4 \\\n");
+ printf(" -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem \\\n");
+ printf(" -A ./certs/client-ecc-cert.pem -p 11111 -i\n");
+ printf("\n Terminal 3 - Run this client:\n");
+ printf(" %s 127.0.0.1\n", progName);
+}
+
+int main(int argc, char** argv)
+{
+ int ret;
+ int sockfd = -1;
+ const char* dtlsServerIp;
+ whKeyId hsmKeyId = HSM_KEY_ID;
+ struct sockaddr_in servAddr;
+ char sendLine[MAX_LINE];
+ char recvLine[MAX_LINE];
+ int n;
+
+ /* wolfHSM client */
+ whClientContext whClient[1];
+ whClientConfig whConfig[1];
+
+ /* wolfSSL/DTLS */
+ WOLFSSL_CTX* ctx = NULL;
+ WOLFSSL* ssl = NULL;
+ int err;
+
+ /* Parse command line arguments */
+ if (argc != 2) {
+ Usage(argv[0]);
+ return 1;
+ }
+ dtlsServerIp = argv[1];
+
+ printf("wolfHSM DTLS Client Example\n");
+ printf(" HSM Key ID: %u\n", hsmKeyId);
+ printf(" DTLS Server: %s:%d\n", dtlsServerIp, DTLS_SERVER_PORT);
+
+ /*
+ * Initialize wolfHSM client (TCP connection to HSM server)
+ */
+ printf("\n[1] Connecting to wolfHSM server...\n");
+ memset(whConfig, 0, sizeof(whClientConfig));
+ ret = InitWolfHSMPosixTcpConfig(whConfig);
+ if (ret != 0) {
+ printf("ERROR: wh_PosixDtlsClient_TcpConfig failed with %d\n", ret);
+ return 1;
+ }
+
+ ret = wh_Client_Init(whClient, whConfig);
+ if (ret != 0) {
+ printf("ERROR: wh_Client_Init failed with %d\n", ret);
+ return 1;
+ }
+
+ ret = wh_Client_CommInit(whClient, NULL, NULL);
+ if (ret != 0) {
+ printf("ERROR: wh_Client_CommInit failed with %d\n", ret);
+ goto cleanup_whclient;
+ }
+ printf(" Connected to wolfHSM server\n");
+
+ /*
+ * Set up a global context to be used in the callbacks
+ */
+ hsmCtx.whClient = whClient;
+ hsmCtx.clientKeyId = hsmKeyId;
+
+ /*
+ * Initialize wolfSSL library
+ */
+ ret = wolfSSL_Init();
+ if (ret != WOLFSSL_SUCCESS) {
+ printf("ERROR: wolfSSL_Init failed\n");
+ goto cleanup;
+ }
+
+ /*
+ * Register wolfHSM crypto callback This callback will intercepts wolfCrypt
+ * cryptographic operations and offloads them to HSM.
+ */
+ ret = wc_CryptoCb_RegisterDevice(WH_DEV_ID, wh_Client_CryptoCb, whClient);
+ if (ret != 0) {
+ printf("ERROR: wc_CryptoCb_RegisterDevice failed with %d\n", ret);
+ goto cleanup;
+ }
+ printf(" Registered wolfHSM crypto callback (devId=0x%08X)\n", WH_DEV_ID);
+
+ /*
+ * Create DTLS client context
+ */
+ printf("\n[2] Creating DTLS context...\n");
+ ctx = wolfSSL_CTX_new(wolfDTLS_client_method());
+ if (ctx == NULL) {
+ printf("ERROR: wolfSSL_CTX_new failed\n");
+ goto cleanup;
+ }
+
+ /*
+ * Configure crypto callback device ID
+ * This tells wolfSSL to use our HSM for crypto operations
+ */
+ ret = wolfSSL_CTX_SetDevId(ctx, WH_DEV_ID);
+ if (ret != WOLFSSL_SUCCESS) {
+ printf("ERROR: wolfSSL_CTX_SetDevId failed\n");
+ goto cleanup;
+ }
+ printf(" Configured HSM device ID for crypto operations\n");
+
+ /*
+ * Register PK callbacks for HSM operations
+ * These callbacks intercept (D)TLS-level ECC operations (signing during
+ * CertificateVerify) and delegate them to the
+ * HSM. It allows to use the id of a private key stored on the HSM without
+ * ever exposing the private key itself.
+ */
+ wolfSSL_CTX_SetEccSignCb(ctx, myEccSignCb);
+ wolfSSL_CTX_SetEccSignCtx(ctx, &hsmCtx);
+ printf(" Registered ECC PK callbacks for HSM operations\n");
+
+ /*
+ * Load CA certificate for verifying DTLS server
+ */
+ ret = wolfSSL_CTX_load_verify_buffer(ctx, ca_ecc_cert_der_256,
+ sizeof_ca_ecc_cert_der_256,
+ WOLFSSL_FILETYPE_ASN1);
+ if (ret != WOLFSSL_SUCCESS) {
+ printf("ERROR: Failed to load CA certificate buffer\n");
+ goto cleanup;
+ }
+ printf(" Loaded CA certificate from buffer\n");
+
+ /*
+ * Load client certificate (public part only)
+ * The private key is NOT loaded here - it stays on the HSM
+ */
+ ret = wolfSSL_CTX_use_certificate_buffer(ctx, cliecc_cert_der_256,
+ sizeof_cliecc_cert_der_256,
+ WOLFSSL_FILETYPE_ASN1);
+ if (ret != WOLFSSL_SUCCESS) {
+ printf("ERROR: Failed to load client certificate buffer\n");
+ goto cleanup;
+ }
+ printf(" Loaded client certificate from buffer\n");
+
+ /*
+ * Create UDP socket for DTLS
+ */
+ printf("\n[3] Creating UDP socket...\n");
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0) {
+ printf("ERROR: Cannot create socket\n");
+ goto cleanup;
+ }
+
+ /* Set up DTLS server address */
+ memset(&servAddr, 0, sizeof(servAddr));
+ servAddr.sin_family = AF_INET;
+ servAddr.sin_port = htons(DTLS_SERVER_PORT);
+ if (inet_pton(AF_INET, dtlsServerIp, &servAddr.sin_addr) != 1) {
+ printf("ERROR: Invalid IP address: %s\n", dtlsServerIp);
+ goto cleanup;
+ }
+ printf(" Created UDP socket\n");
+
+ /*
+ * Create DTLS session
+ */
+ printf("\n[4] Creating DTLS session...\n");
+ ssl = wolfSSL_new(ctx);
+ if (ssl == NULL) {
+ printf("ERROR: wolfSSL_new failed\n");
+ goto cleanup;
+ }
+
+ /* Configure DTLS peer and socket */
+ ret = wolfSSL_dtls_set_peer(ssl, &servAddr, sizeof(servAddr));
+ if (ret != WOLFSSL_SUCCESS) {
+ printf("ERROR: wolfSSL_dtls_set_peer failed\n");
+ goto cleanup;
+ }
+
+ ret = wolfSSL_set_fd(ssl, sockfd);
+ if (ret != WOLFSSL_SUCCESS) {
+ printf("ERROR: wolfSSL_set_fd failed\n");
+ goto cleanup;
+ }
+ printf(" DTLS session configured\n");
+
+ /*
+ * Step 12: Perform DTLS handshake
+ */
+ printf("\n[5] Performing DTLS handshake...\n");
+ ret = wolfSSL_connect(ssl);
+ if (ret != WOLFSSL_SUCCESS) {
+ err = wolfSSL_get_error(ssl, ret);
+ printf("ERROR: wolfSSL_connect failed: %d (%s)\n",
+ err, wolfSSL_ERR_reason_error_string(err));
+ goto cleanup;
+ }
+ printf(" DTLS handshake successful!\n");
+ printf(" Cipher: %s\n", wolfSSL_get_cipher(ssl));
+
+ /*
+ * Application data exchange
+ */
+ printf("\n[6] Ready for application data\n");
+ printf("Enter message to send (or empty line to quit): ");
+ fflush(stdout);
+
+ if (fgets(sendLine, sizeof(sendLine), stdin) != NULL) {
+ size_t len = strlen(sendLine);
+
+ /* Remove trailing newline if present */
+ if (len > 0 && sendLine[len - 1] == '\n') {
+ sendLine[len - 1] = '\0';
+ len--;
+ }
+
+ if (len > 0) {
+ /* Send message to server */
+ ret = wolfSSL_write(ssl, sendLine, (int)len);
+ if (ret != (int)len) {
+ printf("ERROR: wolfSSL_write failed\n");
+ goto cleanup;
+ }
+ printf(" Sent: %s\n", sendLine);
+
+ /* Receive response from server */
+ memset(recvLine, 0, sizeof(recvLine));
+ n = wolfSSL_read(ssl, recvLine, sizeof(recvLine) - 1);
+ if (n < 0) {
+ err = wolfSSL_get_error(ssl, n);
+ if (err != WOLFSSL_ERROR_WANT_READ) {
+ printf("ERROR: wolfSSL_read failed: %d\n", err);
+ }
+ }
+ else {
+ recvLine[n] = '\0';
+ printf(" Received: %s\n", recvLine);
+ }
+ }
+ }
+
+ /*
+ * Clean shutdown - we made it here so operation was successful
+ */
+ printf("\n[7] Closing connection...\n");
+ wolfSSL_shutdown(ssl);
+ printf(" DTLS connection closed\n");
+
+ ret = WOLFSSL_SUCCESS;
+
+cleanup:
+ wolfSSL_free(ssl);
+ if (sockfd >= 0) {
+ close(sockfd);
+ }
+ wolfSSL_CTX_free(ctx);
+
+ wolfSSL_Cleanup();
+
+cleanup_whclient:
+ wh_Client_CommClose(whClient);
+ wh_Client_Cleanup(whClient);
+ printf(" wolfHSM client disconnected\n");
+
+ printf("\nDone.\n");
+ return (ret == WOLFSSL_SUCCESS) ? 0 : 1;
+}
diff --git a/hsm/dtls_client/wolfhsm_cfg.h b/hsm/dtls_client/wolfhsm_cfg.h
new file mode 100644
index 00000000..b1cf4767
--- /dev/null
+++ b/hsm/dtls_client/wolfhsm_cfg.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2024 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_cfg.h
+ *
+ * wolfHSM compile-time options for DTLS client example
+ */
+
+#ifndef WOLFHSM_CFG_H_
+#define WOLFHSM_CFG_H_
+
+#include "wolfhsm/port/posix/posix_time.h"
+
+#define WOLFHSM_CFG_PORT_GETTIME posixGetTime
+
+/** wolfHSM settings */
+#define WOLFHSM_CFG_ENABLE_CLIENT
+#define WOLFHSM_CFG_COMM_DATA_LEN 5000
+
+#endif /* WOLFHSM_CFG_H_ */