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 improvementspull/611/head
parent
dc6a012c30
commit
c586428531
10
README.md
10
README.md
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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
|
||||||
|
```
|
||||||
|
|
@ -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_ */
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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_ */
|
||||||
Loading…
Reference in New Issue