wolfHSM: add DTLS client example that uses HSM as cryptographic back end (#555)

* wolfHSM: add DTLS client that uses HSM as cryptographic backend

* address reviewer's comment

* dtls client improvements
pull/611/head
Marco Oliverio 2026-07-22 16:37:34 +02:00 committed by GitHub
parent dc6a012c30
commit c586428531
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 856 additions and 0 deletions

View File

@ -390,6 +390,16 @@ Please see the [utasker/README.md](utasker/README.md) for further usage and
details. details.
<br />
#### hsm (wolfHSM Examples)
This directory contains examples demonstrating wolfSSL integration with wolfHSM,
a portable Hardware Security Module framework.
Please see the [hsm/README.md](hsm/README.md) for further details.
<br /> <br />
#### uefi-static (wolfCrypt UEFI application Example) #### uefi-static (wolfCrypt UEFI application Example)

24
hsm/README.md 100644
View File

@ -0,0 +1,24 @@
# 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 (from the `wolfssl-examples` repository root):
```bash
cd hsm/dtls_client
make download_repos
make 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

View File

@ -0,0 +1,171 @@
# 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
# Several wolfSSL sources (asn_orig.c, pk_ec.c, ssl_*.c, ...) are meant to be
# #included by a parent translation unit and #warning when built standalone, which
# -Werror turns into an error. This macro silences only those, leaving genuine
# configuration warnings (e.g. random.c's insecure-seed warning) still fatal.
DEF += -DWOLFSSL_IGNORE_FILE_WARN
INC = -I$(PROJECT_DIR) -I$(WOLFSSL_DIR) -I$(WOLFHSM_DIR) -I$(WOLFHSM_PORT_DIR)
# Linker settings
LDFLAGS = -Wl,--gc-sections
LIBS = -lm -lpthread
# 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 check_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. See README.md 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)/$(BIN).elf
@echo "DTLS client built: $(BUILD_DIR)/$(BIN).elf"
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
$(BUILD_DIR)/%.o: %.c | $(BUILD_DIR)
@echo "Compiling: $(notdir $<)"
$(CC) $(CFLAGS) $(DEF) $(INC) -c -o $@ $<
$(BUILD_DIR)/$(BIN).elf: $(OBJS_C) | $(BUILD_DIR)
@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 d \
-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)

View File

@ -0,0 +1,72 @@
# 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 |
## Debug Build
```bash
make clean
make DEBUG=1
```

View File

@ -0,0 +1,73 @@
/* user_settings.h
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* wolfSSL 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 2 of the License, or
* (at your option) any later version.
*
* wolfSSL 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-1301, USA
*/
#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_ */

View File

@ -0,0 +1,470 @@
/* wh_dtls_client.c
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* wolfSSL 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 2 of the License, or
* (at your option) any later version.
*
* wolfSSL 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-1301, USA
*/
/*
* 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 <path-to-ecc-client-key.der> --id 1 --client 12
*
* 2. Start external DTLS server (from wolfssl directory):
* ./examples/server/server -u -v d \
* -c ./certs/server-ecc.pem -k ./certs/ecc-key.pem \
* -A ./certs/client-ecc-cert.pem -p 11111 -i
*
* 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 <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
/* 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 "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* dtlsCtx = (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, dtlsCtx->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(dtlsCtx->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 <DTLS server IP>\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 <path-to-ecc-client-key.der> --id 1 --client 12\n");
printf("\n Terminal 2 - Start wolfSSL DTLS server (from wolfssl directory):\n");
printf(" ./examples/server/server -u -v d \\\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: InitWolfHSMPosixTcpConfig 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;
}
/*
* The wolfHSM crypto callback, which intercepts wolfCrypt cryptographic
* operations and offloads them to the HSM, is registered for WH_DEV_ID by
* wh_Client_Init() above, so no explicit registration is needed here.
*/
printf(" Using 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");
ret = -1;
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");
ret = -1;
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);
ret = -1;
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");
ret = -1;
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");
/*
* 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");
ret = -1;
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);
ret = -1;
goto cleanup;
}
}
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;
}

View File

@ -0,0 +1,36 @@
/* wolfhsm_cfg.h
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL. (formerly known as CyaSSL)
*
* wolfSSL 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 2 of the License, or
* (at your option) any later version.
*
* wolfSSL 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-1301, USA
*/
/*
* wolfHSM compile-time options for DTLS client example
*/
#ifndef WOLFHSM_CFG_H_
#define WOLFHSM_CFG_H_
#include "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_ */