add wolfHSM DTLS server demo

pull/561/head
JacobBarthelmeh 2026-02-27 15:14:35 -07:00
parent f2dec15dde
commit 8b3c7bee89
7 changed files with 1332 additions and 0 deletions

View File

@ -0,0 +1,146 @@
## Makefile for TLS/DTLS Server using wolfHSM for crypto operations
##
## This example demonstrates a server that offloads all cryptographic
## operations to a wolfHSM server running on the POSIX transport with
## DMA support. By default, DTLS (UDP) mode is used.
##
## Usage:
## 1. Build: make DEBUG=1
## 2. Start the wolfHSM server: cd ../../posix/wh_posix_server && ./Build/wh_posix_server.elf --type dma
## 3. Run this server: ./Build/wh_server.elf
## 4. Connect with a client
## Project name - sets output filename
BIN = wh_server
## Important directories
PROJECT_DIR ?= .
CONFIG_DIR ?= $(PROJECT_DIR)/config
# wolfSSL and wolfHSM directories (relative to this Makefile)
WOLFSSL_DIR ?= ../../../../wolfssl
WOLFHSM_DIR ?= ../../..
WOLFHSM_PORT_DIR ?= $(WOLFHSM_DIR)/port/posix
# Output directory for build files
BUILD_DIR ?= $(PROJECT_DIR)/Build
## Includes
INC = -I$(PROJECT_DIR) \
-I$(CONFIG_DIR) \
-I$(WOLFSSL_DIR) \
-I$(WOLFHSM_DIR) \
-I$(WOLFHSM_PORT_DIR)
## Defines
# POSIX requires C source be defined before any header
DEF += -D_POSIX_C_SOURCE=200809L
# Library configuration defines for user-supplied settings
DEF += -DWOLFSSL_USER_SETTINGS -DWOLFHSM_CFG
# Enable DMA transport by default (matches server --type dma)
DEF += -DWOLFHSM_CFG_DMA
## Architecture flags
ARCHFLAGS ?=
## Compiler and linker flags
ASFLAGS ?= $(ARCHFLAGS)
CFLAGS_EXTRA ?= -Wextra
CFLAGS ?= $(ARCHFLAGS) -Wno-cpp -std=c99 -Wall -Werror $(CFLAGS_EXTRA)
LDFLAGS ?= $(ARCHFLAGS)
LIBS = -lc -lm
# Platform-specific linker flags for dead code stripping
OS_NAME := $(shell uname -s | tr A-Z a-z)
ifeq ($(OS_NAME),darwin)
LDFLAGS += -Wl,-dead_strip
else
LDFLAGS += -Wl,--gc-sections
endif
## Makefile options
# Set to @ to suppress command echo
CMD_ECHO ?=
# Debug build
ifeq ($(DEBUG),1)
DBGFLAGS = -ggdb -g3 -O0
CFLAGS += $(DBGFLAGS)
LDFLAGS += $(DBGFLAGS)
DEF += -DWOLFHSM_CFG_DEBUG
endif
# Verbose debug output
ifeq ($(DEBUG_VERBOSE),1)
DBGFLAGS = -ggdb -g3 -O0
CFLAGS += $(DBGFLAGS)
LDFLAGS += $(DBGFLAGS)
DEF += -DWOLFHSM_CFG_DEBUG -DWOLFHSM_CFG_DEBUG_VERBOSE
endif
# Address sanitizer
ifeq ($(ASAN),1)
CFLAGS += -fsanitize=address
LDFLAGS += -fsanitize=address
endif
## Source files
# wolfCrypt source files
SRC_C += $(wildcard $(WOLFSSL_DIR)/wolfcrypt/src/*.c)
# wolfSSL TLS source files
SRC_C += $(wildcard $(WOLFSSL_DIR)/src/*.c)
# wolfHSM source files
SRC_C += $(wildcard $(WOLFHSM_DIR)/src/*.c)
# wolfHSM POSIX port/HAL code
SRC_C += $(wildcard $(WOLFHSM_PORT_DIR)/*.c)
# Project source files
SRC_C += $(PROJECT_DIR)/server.c
SRC_C += $(PROJECT_DIR)/server_io.c
## Automated processing
FILENAMES_C = $(notdir $(SRC_C))
OBJS_C = $(addprefix $(BUILD_DIR)/, $(FILENAMES_C:.c=.o))
vpath %.c $(dir $(SRC_C))
## Makefile Targets
.PHONY: all build clean help
all: build
build: $(BUILD_DIR) $(BUILD_DIR)/$(BIN).elf
$(BUILD_DIR):
$(CMD_ECHO) mkdir -p $(BUILD_DIR)
$(BUILD_DIR)/%.o: %.c
@echo "Compiling: $(notdir $<)"
$(CMD_ECHO) $(CC) $(CFLAGS) $(DEF) $(INC) -c -o $@ $<
$(BUILD_DIR)/$(BIN).elf: $(OBJS_C)
@echo "Linking: $(notdir $@)"
$(CMD_ECHO) $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:
@echo "Cleaning build files..."
@rm -rf $(BUILD_DIR)
help:
@echo "TLS/DTLS Server with wolfHSM Crypto Offload"
@echo ""
@echo "Options:"
@echo " DEBUG=1 - Enable debug build with symbols"
@echo " DEBUG_VERBOSE=1 - Enable verbose debug output"
@echo " ASAN=1 - Enable address sanitizer"
@echo ""
@echo "Example:"
@echo " make DEBUG=1"

View File

@ -0,0 +1,219 @@
# TLS/DTLS Server with wolfHSM Crypto Offload
This example demonstrates a TLS/DTLS server that offloads cryptographic
operations to a wolfHSM server. By default, DTLS (UDP-based) is used, but
the code can be adapted for TLS (TCP-based) connections.
The wolfHSM server runs separately and communicates via the chosen transport.
## Architecture
```
+-------------------+ Shared Memory (DMA) +-------------------+
| | <-----------------------------> | |
| TLS/DTLS Server | Crypto Operations Request | wolfHSM Server |
| (This Example) | <-----------------------------> | (wh_posix_server)|
| | Crypto Operations Response | |
+-------------------+ +-------------------+
| |
| TLS/DTLS | Performs all
| | crypto ops:
v | - Key Exchange
+-------------------+ | - Signing
| TLS/DTLS Client | | - Encryption
| | | - Hashing
+-------------------+ +
```
## How It Works
1. **wolfHSM Server**: The `wh_posix_server` runs with `--type dma` to provide
crypto services over shared memory with DMA support.
2. **TLS/DTLS Server**: This example connects to the wolfHSM server as a client
and registers a crypto callback. All wolfSSL/wolfCrypt operations are
forwarded to the HSM.
3. **Crypto Offload**: When `wolfSSL_CTX_SetDevId()` is called with `WH_DEV_ID`,
wolfSSL routes crypto operations through the registered callback to the
wolfHSM server.
## Building
### Prerequisites
1. wolfSSL library built with crypto callback support
2. wolfHSM library with POSIX port
### Build Steps
```bash
# Build the server
cd examples/demo/dtls_server
make
# Build the wolfHSM POSIX server (if not already built)
cd ../../posix/wh_posix_server
make DMA=1
```
## Running
### Step 1: Start the wolfHSM Server
```bash
cd examples/posix/wh_posix_server
./Build/wh_posix_server.elf --type dma
```
You should see:
```
Example wolfHSM POSIX server built with wolfSSL version X.X.X
Using DMA with shared memory transport
Waiting for connection...
```
### Step 2: Start the Server
In a new terminal:
```bash
cd examples/demo/dtls_server
./Build/wh_server.elf
```
#### Command-Line Options
```
Usage: ./Build/wh_server.elf [options]
Options:
-A <file> CA certificate file (PEM or DER format)
If not specified, uses built-in test certificate
-c <file> Server certificate file (PEM or DER format)
-k <file> Server private key file (PEM or DER format)
-p <port> Port to listen on (default: 11111)
-h Show this help message
```
#### Examples
```bash
# Use default built-in certificates
./Build/wh_server.elf
# Use client-cert.pem from wolfssl bundle for example client to connect
./Build/wh_server.elf -A /path/to/wolfssl/certs/client-cert.pem
# Use custom certificates and port
./Build/wh_server.elf -A ca.pem -c server.pem -k server-key.pem -p 4433
```
You should see:
```
DTLS server starting on port 11111...
Connected to wolfHSM server successfully
Waiting for client on port 11111...
```
### Step 3: Connect a Client
In a third terminal:
```bash
# For DTLS (default mode) - using wolfssl with DTLS 1.3
./examples/examples/client -u -v 4
```
## Key Integration Points
### 1. Registering Crypto Callbacks
In `server.c`, we register the wolfHSM crypto callbacks:
```c
/* Register crypto callback for non-DMA operations */
wc_CryptoCb_RegisterDevice(WH_DEV_ID, wh_Client_CryptoCb, (void*)g_client);
/* Register crypto callback for DMA operations (larger data) */
wc_CryptoCb_RegisterDevice(WH_DEV_ID_DMA, wh_Client_CryptoCbDma, (void*)g_client);
```
### 2. Setting Device ID on wolfSSL Object
In `server_io.c`, we configure wolfSSL to use the HSM on the WOLFSSL_CTX object:
```c
wolfSSL_CTX_SetDevId(ctx, WH_DEV_ID);
```
### 3. DMA vs Non-DMA
- **WH_DEV_ID**: Uses standard message-based crypto operations. Suitable for
smaller data sizes.
- **WH_DEV_ID_DMA**: Uses DMA (Direct Memory Access) for data transfer.
More efficient for larger data like TLS record encryption.
## Configuration
### wolfSSL Configuration (`config/user_settings.h`)
Key settings for TLS/DTLS with wolfHSM:
```c
/* Enable DTLS 1.3 (for UDP mode) */
#define WOLFSSL_DTLS
#define WOLFSSL_DTLS13
#define WOLFSSL_TLS13
/* Enable crypto callbacks for wolfHSM */
#define WOLF_CRYPTO_CB
/* Hash DRBG for RNG */
#define HAVE_HASHDRBG
```
### wolfHSM Configuration (`config/wolfhsm_cfg.h`)
Key settings for wolfHSM client:
```c
/* Enable wolfHSM client */
#define WOLFHSM_CFG_ENABLE_CLIENT
/* Enable DMA transport */
#define WOLFHSM_CFG_DMA
```
## Troubleshooting
### "Failed to connect to wolfHSM server"
Make sure the `wh_posix_server` is running with `--type dma` before starting
the DTLS server.
### Handshake Failures
1. Check that both the wolfHSM server and DTLS server are built with the same
wolfSSL version.
2. Verify the shared memory name matches between client and server
(default: "wh_example_shm").
3. Enable verbose debugging:
```bash
make DEBUG_VERBOSE=1
```
## Adapting for TLS
To use TLS instead of DTLS:
1. In `server_io.c`, change the method from `wolfDTLS_server_method()` to
`wolfTLSv1_3_server_method()` or another TLS method.
2. Change the socket initialization from UDP to TCP (replace
`initialize_udp_socket()` with a TCP equivalent).
3. Remove the DTLS-specific peer address setup in `setup_ssl_accept()`.

View File

@ -0,0 +1,135 @@
/*
* Copyright (C) 2024 wolfSSL Inc.
*
* This file is part of wolfHSM.
*
* user_settings.h - wolfSSL configuration for DTLS server demo
*
* Based on the posix server user_settings.h with TLS enabled.
*/
#ifndef USER_SETTINGS_H
#define USER_SETTINGS_H
#ifdef __cplusplus
extern "C" {
#endif
/** wolfHSM required settings for wolfCrypt */
#define WOLF_CRYPTO_CB
#define WOLFSSL_KEY_GEN
#define WOLFSSL_ASN_TEMPLATE
#define WOLFSSL_BASE64_ENCODE
#define HAVE_ANONYMOUS_INLINE_AGGREGATES 1
/** Math library */
#define USE_FAST_MATH
#define FP_MAX_BITS 8192
/** General recommended settings */
#define WOLFSSL_USE_ALIGN
#define WOLFSSL_IGNORE_FILE_WARN
#define TFM_TIMING_RESISTANT
#define ECC_TIMING_RESISTANT
#define WC_RSA_BLINDING
/** Remove unneeded features */
#define NO_MAIN_DRIVER
#define NO_INLINE
#define NO_DO178
/** Remove unneeded namespace */
#define NO_OLD_RNGNAME
#define NO_OLD_WC_NAMES
#define NO_OLD_SSL_NAMES
#define NO_OLD_SHA_NAMES
#define NO_OLD_MD5_NAME
/** RSA Options */
#define RSA_MIN_SIZE 1024
#define WC_RSA_PSS
#define WOLFSSL_PSS_LONG_SALT
/** ECC Options */
#define HAVE_ECC
#define TFM_ECC256
#define ECC_SHAMIR
#define HAVE_ECC_DHE /* Required for ECDH key agreement (TLS 1.3 key share) */
/** Curve25519 Options - disabled for this demo
* TLS 1.3 will use ECC (P-256) for key share instead */
/* #define HAVE_CURVE25519 */
/** Ed25519 Options - disabled for this demo */
/* #define HAVE_ED25519 */
/** DH Options */
#define HAVE_DH_DEFAULT_PARAMS
#define HAVE_FFDHE_2048
/** AES Options */
#define HAVE_AES_CBC
#define HAVE_AESGCM
#define WOLFSSL_AES_COUNTER
#define GCM_TABLE_4BIT
#define WOLFSSL_AES_DIRECT
#define HAVE_AES_ECB
#define WOLFSSL_CMAC
/** SHA Options */
/* Keep SHA-1 enabled - required for DTLS 1.2 cipher suites */
#define WOLFSSL_SHA224
#define WOLFSSL_SHA384
#define WOLFSSL_SHA512
#define WOLFSSL_SHA512_HASHTYPE
/** Composite features */
#define HAVE_HKDF
/** RNG configuration */
/* Use Hash DRBG (NIST SP 800-90A compliant) */
#define HAVE_HASHDRBG
/** Remove unneeded crypto */
#define NO_DSA
#define NO_RC4
#define NO_MD4
/* Keep MD5 for TLS PRF */
#define NO_DES3
#define NO_PWDBASED
/** TLS/DTLS settings */
#define HAVE_TLS_EXTENSIONS
#define HAVE_SUPPORTED_CURVES
#define HAVE_EXTENDED_MASTER
#define HAVE_ENCRYPT_THEN_MAC
#define HAVE_SERVER_RENEGOTIATION_INFO
/* DTLS support */
#define WOLFSSL_DTLS
#define WOLFSSL_DTLS13
#define WOLFSSL_TLS13
#define WOLFSSL_SEND_HRR_COOKIE /* Required for DTLS 1.3 server */
/* Disable features we don't need */
#define NO_PSK
#define NO_OLD_TLS
/* Test certificate buffers for demo */
#define USE_CERT_BUFFERS_256
#define USE_CERT_BUFFERS_2048
/* Debug (optional - enabled via Makefile DEBUG=1) */
#ifdef WOLFHSM_CFG_DEBUG
#define DEBUG_WOLFSSL
#endif
/* Include for POSIX extensions needed by wolfSSL */
#include <sys/time.h> /* for struct timeval, gettimeofday */
#include <strings.h> /* for strcasecmp */
#ifdef __cplusplus
}
#endif
#endif /* USER_SETTINGS_H */

View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2024 wolfSSL Inc.
*
* This file is part of wolfHSM.
*
* wolfhsm_cfg.h - wolfHSM configuration for DTLS server demo
*
* This configures the wolfHSM client to connect to the HSM server
* for crypto operations.
*/
#ifndef WOLFHSM_CFG_H_
#define WOLFHSM_CFG_H_
#include "port/posix/posix_time.h"
/* Time function for wolfHSM */
#define WOLFHSM_CFG_PORT_GETTIME posixGetTime
/* Enable wolfHSM client */
#define WOLFHSM_CFG_ENABLE_CLIENT
/* DMA transport is enabled via Makefile -DWOLFHSM_CFG_DMA */
/* Debug output is enabled via Makefile when DEBUG=1 */
/* Verbose debug output (uncomment for detailed tracing) */
/* #define WOLFHSM_CFG_DEBUG_VERBOSE */
/* Enable hexdump utility */
#define WOLFHSM_CFG_HEXDUMP
/* Communication data length - must match server configuration */
#define WOLFHSM_CFG_COMM_DATA_LEN 5000
/* Enable key wrapping support */
#define WOLFHSM_CFG_KEYWRAP
/* Enable global keys feature */
#define WOLFHSM_CFG_GLOBAL_KEYS
#endif /* WOLFHSM_CFG_H_ */

View File

@ -0,0 +1,276 @@
/*
* Copyright (C) 2024 wolfSSL Inc.
*
* This file is part of wolfHSM.
*
* TLS/DTLS Server Demo using wolfHSM for Crypto Operations
*
* This example demonstrates a server that offloads all cryptographic
* operations to a wolfHSM server running on the POSIX transport with
* DMA support. By default, DTLS is used but the code can be adapted
* for TLS connections.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include "server.h"
/* wolfHSM client includes */
#include "wolfhsm/wh_error.h"
#include "wolfhsm/wh_comm.h"
#include "wolfhsm/wh_client.h"
#include "wolfhsm/wh_client_cryptocb.h"
#include "port/posix/posix_transport_shm.h"
/* wolfSSL includes for crypto callback registration */
#include "wolfssl/wolfcrypt/settings.h"
#include "wolfssl/wolfcrypt/cryptocb.h"
/* Shared POSIX example configuration */
#include "examples/posix/wh_posix_cfg.h"
/* Global wolfHSM client context */
static whClientContext g_client[1] = {{0}};
static posixTransportShmClientContext g_shm_client_ctx;
static posixTransportShmConfig g_shm_config;
static whCommClientConfig g_comm_config;
static whClientConfig g_client_config;
#ifdef WOLFHSM_CFG_DMA
/* DMA configuration for large data transfers */
static whClientDmaConfig g_dma_config;
#endif
/*
* Connect to the wolfHSM server over shared memory DMA transport.
*
* This establishes a connection to the HSM server and registers the
* crypto callback so that wolfSSL crypto operations are forwarded to
* the HSM.
*/
static int connect_to_hsm_server(void)
{
int ret;
static const whTransportClientCb shm_cb = POSIX_TRANSPORT_SHM_CLIENT_CB;
/* Initialize transport context */
memset(&g_shm_client_ctx, 0, sizeof(g_shm_client_ctx));
memset(&g_comm_config, 0, sizeof(g_comm_config));
memset(&g_client_config, 0, sizeof(g_client_config));
/* Configure shared memory transport with DMA */
g_shm_config.name = WH_POSIX_SHARED_MEMORY_NAME;
g_shm_config.req_size = WH_POSIX_REQ_SIZE;
g_shm_config.resp_size = WH_POSIX_RESP_SIZE;
g_shm_config.dma_size = WH_POSIX_DMA_SIZE;
/* Configure comm layer */
g_comm_config.transport_cb = &shm_cb;
g_comm_config.transport_context = (void*)&g_shm_client_ctx;
g_comm_config.transport_config = (void*)&g_shm_config;
g_comm_config.client_id = WH_POSIX_CLIENT_ID;
#ifdef WOLFHSM_CFG_DMA
/* Configure DMA callbacks for static memory operations */
g_dma_config.cb = posixTransportShm_ClientStaticMemDmaCallback;
g_dma_config.dmaAddrAllowList = NULL;
g_client_config.dmaConfig = &g_dma_config;
#endif
/* Configure client */
g_client_config.comm = &g_comm_config;
/* Initialize the client */
ret = wh_Client_Init(g_client, &g_client_config);
if (ret != WH_ERROR_OK) {
fprintf(stderr, "Failed to initialize wolfHSM client: %d\n", ret);
return -1;
}
/* Initialize communication with the server */
ret = wh_Client_CommInit(g_client, NULL, NULL);
if (ret != WH_ERROR_OK) {
fprintf(stderr, "Failed to initialize wolfHSM client communication: %d\n", ret);
wh_Client_Cleanup(g_client);
return -1;
}
/* Register crypto callback for non-DMA operations */
ret = wc_CryptoCb_RegisterDevice(WH_DEV_ID, wh_Client_CryptoCb,
(void*)g_client);
if (ret != 0) {
fprintf(stderr, "Failed to register crypto callback: %d\n", ret);
wh_Client_CommClose(g_client);
wh_Client_Cleanup(g_client);
return -1;
}
#ifdef WOLFHSM_CFG_DMA
/* Register crypto callback for DMA operations */
ret = wc_CryptoCb_RegisterDevice(WH_DEV_ID_DMA, wh_Client_CryptoCbDma,
(void*)g_client);
if (ret != 0) {
fprintf(stderr, "Failed to register DMA crypto callback: %d\n", ret);
wc_CryptoCb_UnRegisterDevice(WH_DEV_ID);
wh_Client_CommClose(g_client);
wh_Client_Cleanup(g_client);
return -1;
}
#endif
printf("Connected to wolfHSM server successfully\n");
return 0;
}
/* Disconnect from wolfHSM server */
static void disconnect_from_hsm_server(void)
{
printf("Disconnecting from wolfHSM server...\n");
#ifdef WOLFHSM_CFG_DMA
wc_CryptoCb_UnRegisterDevice(WH_DEV_ID_DMA);
#endif
wc_CryptoCb_UnRegisterDevice(WH_DEV_ID);
wh_Client_CommClose(g_client);
wh_Client_Cleanup(g_client);
}
/* Print usage information */
static void print_usage(const char* progname)
{
printf("Usage: %s [options]\n", progname);
printf("\n");
printf("TLS/DTLS server demo using wolfHSM for crypto operations.\n");
printf("By default, uses DTLS over UDP.\n");
printf("\n");
printf("Options:\n");
printf(" -A <file> CA certificate file (PEM or DER format)\n");
printf(" If not specified, uses built-in test certificate\n");
printf(" -c <file> Server certificate file (PEM or DER format)\n");
printf(" -k <file> Server private key file (PEM or DER format)\n");
printf(" -p <port> Port to listen on (default: 11111)\n");
printf(" -h Show this help message\n");
printf("\n");
printf("Prerequisites:\n");
printf(" Start the wolfHSM server first:\n");
printf(" cd examples/posix/wh_posix_server\n");
printf(" ./Build/wh_posix_server.elf --type dma\n");
printf("\n");
printf("Example:\n");
printf(" %s -A ca-cert.pem\n", progname);
printf("\n");
}
/*
* Main application entry point.
*
* This sets up the wolfHSM client connection, then initializes the
* server which will use wolfHSM for all crypto operations.
*/
int main(int argc, char** argv)
{
SERVER_CONTEXT* ctx;
ServerConfig config = {0};
int ret;
int exit_code = 0;
unsigned char buf[256];
int bytesRead;
int opt;
/* Set default port */
config.port = 11111;
/* Parse command line arguments */
while ((opt = getopt(argc, argv, "A:c:k:p:h")) != -1) {
switch (opt) {
case 'A':
config.caCertFile = optarg;
break;
case 'c':
config.serverCertFile = optarg;
break;
case 'k':
config.serverKeyFile = optarg;
break;
case 'p':
config.port = atoi(optarg);
if (config.port <= 0 || config.port > 65535) {
fprintf(stderr, "Invalid port number: %s\n", optarg);
return 1;
}
break;
case 'h':
print_usage(argv[0]);
return 0;
default:
print_usage(argv[0]);
return 1;
}
}
printf("DTLS server starting on port %d...\n", config.port);
/* Initialize wolfCrypt */
ret = wolfCrypt_Init();
if (ret != 0) {
fprintf(stderr, "Failed to initialize wolfCrypt: %d\n", ret);
return 1;
}
/* Connect to the wolfHSM server */
if (connect_to_hsm_server() != 0) {
fprintf(stderr, "Failed to connect to wolfHSM server\n");
fprintf(stderr, "Make sure wh_posix_server is running with --type dma\n");
wolfCrypt_Cleanup();
return 1;
}
/* Get the server context and initialize it */
ctx = Server_Get();
ret = Server_Init(ctx, g_client, &config);
if (ret != 0) {
fprintf(stderr, "Failed to initialize server: %d\n", ret);
exit_code = 1;
goto cleanup;
}
/* Accept a connection */
printf("Waiting for client...\n");
ret = Server_Accept(ctx);
if (ret != 0) {
fprintf(stderr, "Failed to accept connection: %d\n", ret);
exit_code = 1;
goto cleanup;
}
printf("Connected. Entering echo mode...\n");
while (1) {
memset(buf, 0, sizeof(buf));
bytesRead = Server_Read(ctx, buf, sizeof(buf) - 1);
if (bytesRead <= 0) {
printf("Client disconnected\n");
break;
}
printf("Received %d bytes: %s\n", bytesRead, buf);
/* Echo back */
ret = Server_Write(ctx, buf, bytesRead);
if (ret < 0) {
fprintf(stderr, "Failed to write response\n");
break;
}
}
cleanup:
Server_Cleanup(ctx);
disconnect_from_hsm_server();
wolfCrypt_Cleanup();
return exit_code;
}

View File

@ -0,0 +1,58 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/
/*
* server.h
*
* Header for the TLS/DTLS server demo that uses wolfHSM for crypto operations.
* This API is protocol-agnostic and can be used for both TLS and DTLS.
*/
#ifndef SERVER_H_
#define SERVER_H_
#include <stdint.h>
#include <stddef.h>
#include <netinet/in.h>
#include "wolfhsm/wh_client.h"
/* Forward declaration for opaque server structure */
typedef struct SERVER_CONTEXT SERVER_CONTEXT;
/* Server configuration */
typedef struct ServerConfig {
const char* caCertFile; /* Path to CA certificate file (PEM or DER) */
const char* serverCertFile; /* Path to server certificate file (optional) */
const char* serverKeyFile; /* Path to server private key file (optional) */
int port; /* Port to listen on (default: 11111) */
} ServerConfig;
/* Server management functions */
SERVER_CONTEXT* Server_Get(void);
int Server_Init(SERVER_CONTEXT* ctx, whClientContext* client,
const ServerConfig* config);
int Server_Accept(SERVER_CONTEXT* ctx);
void Server_Cleanup(SERVER_CONTEXT* ctx);
int Server_Close(SERVER_CONTEXT* ctx);
/* Data transfer functions */
int Server_Read(SERVER_CONTEXT* ctx, unsigned char* data, size_t length);
int Server_Write(SERVER_CONTEXT* ctx, unsigned char* data, size_t length);
#endif /* SERVER_H_ */

View File

@ -0,0 +1,457 @@
/*
* Copyright (C) 2024 wolfSSL Inc.
*
* This file is part of wolfHSM.
*
* Server I/O functions for the TLS/DTLS server demo.
*
* This module handles TLS/DTLS I/O operations. By default, DTLS is used.
* The key integration point with wolfHSM is setting the device ID (WH_DEV_ID)
* on the wolfSSL context so that crypto operations are forwarded to the HSM.
*/
#include "server.h"
/* wolfSSL includes */
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/cryptocb.h>
/* wolfHSM client includes */
#include "wolfhsm/wh_client.h"
/* Standard includes */
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
/* Test certificate buffers from wolfSSL for demo purposes */
#undef USE_CERT_BUFFERS_2048
#define USE_CERT_BUFFERS_2048
#undef USE_CERT_BUFFERS_256
#define USE_CERT_BUFFERS_256
#include "wolfssl/certs_test.h"
/* Default server port */
#define SERVER_PORT_DEFAULT 11111
/* Static wolfSSL context - shared across connections */
static WOLFSSL_CTX* g_ctx = NULL;
/* Static configuration - set during init */
static ServerConfig g_config = {0};
/* Server context structure */
struct SERVER_CONTEXT {
WOLFSSL* ssl;
whClientContext* hsm_client;
int listenfd;
struct sockaddr_in cliaddr;
socklen_t cliLen;
int port;
};
/* Single static instance of the server */
static SERVER_CONTEXT g_server = {
.ssl = NULL,
.hsm_client = NULL,
.listenfd = -1,
.port = 0
};
/*
* Initialize wolfSSL library and create a context.
*
* Uses DTLS server method with version negotiation (prefers DTLS 1.3).
* This can be changed to TLS by modifying the method call below.
*
* The key here is setting the device ID to WH_DEV_ID so that all
* crypto operations are forwarded to the wolfHSM server.
*/
static int initialize_wolfssl(WOLFSSL_CTX** ctx, whClientContext* hsm_client)
{
int ret = 0;
ret = wolfSSL_Init();
if (ret != WOLFSSL_SUCCESS) {
printf("Failed to initialize wolfSSL, ret = %d\n", ret);
return -1;
}
/* Enable debug output */
wolfSSL_Debugging_ON();
/* Create a new context for server - DTLS with version negotiation
* This will use DTLS 1.3 if both sides support it, otherwise falls back.
* Note: For DTLS 1.3-only, use wolfDTLSv1_3_server_method() but ensure
* the crypto callback supports TLS 1.3 key exchange operations. */
*ctx = wolfSSL_CTX_new(wolfDTLS_server_method());
if (*ctx == NULL) {
printf("Failed to create wolfSSL context\n");
return -1;
}
/* @TODO have an option for WH_DEV_ID_DMA */
wolfSSL_CTX_SetDevId(*ctx, WH_DEV_ID);
/* Load CA certificate for client verification */
if (g_config.caCertFile != NULL) {
/* wolfSSL_CTX_load_verify_locations auto-detects PEM vs DER format */
ret = wolfSSL_CTX_load_verify_locations(*ctx, g_config.caCertFile, NULL);
if (ret != WOLFSSL_SUCCESS) {
printf("Failed to load CA certificate from %s, ret = %d\n",
g_config.caCertFile, ret);
wolfSSL_CTX_free(*ctx);
*ctx = NULL;
return -1;
}
}
else {
/* Use built-in test certificate */
ret = wolfSSL_CTX_load_verify_buffer(*ctx, ca_cert_der_2048,
sizeof_ca_cert_der_2048,
WOLFSSL_FILETYPE_ASN1);
if (ret != WOLFSSL_SUCCESS) {
printf("Failed to load built-in CA certificate, ret = %d\n", ret);
wolfSSL_CTX_free(*ctx);
*ctx = NULL;
return -1;
}
}
/* Load server certificate */
if (g_config.serverCertFile != NULL) {
ret = wolfSSL_CTX_use_certificate_file(*ctx, g_config.serverCertFile,
WOLFSSL_FILETYPE_PEM);
if (ret != WOLFSSL_SUCCESS) {
/* Try DER format */
ret = wolfSSL_CTX_use_certificate_file(*ctx, g_config.serverCertFile,
WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS) {
printf("Failed to load server certificate from %s, ret = %d\n",
g_config.serverCertFile, ret);
wolfSSL_CTX_free(*ctx);
*ctx = NULL;
return -1;
}
}
else {
ret = wolfSSL_CTX_use_certificate_buffer(*ctx, server_cert_der_2048,
sizeof_server_cert_der_2048,
WOLFSSL_FILETYPE_ASN1);
if (ret != WOLFSSL_SUCCESS) {
printf("Failed to load built-in server certificate, ret = %d\n", ret);
wolfSSL_CTX_free(*ctx);
*ctx = NULL;
return -1;
}
}
/* Load server private key */
if (g_config.serverKeyFile != NULL) {
ret = wolfSSL_CTX_use_PrivateKey_file(*ctx, g_config.serverKeyFile,
WOLFSSL_FILETYPE_PEM);
if (ret != WOLFSSL_SUCCESS) {
/* Try DER format */
ret = wolfSSL_CTX_use_PrivateKey_file(*ctx, g_config.serverKeyFile,
WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS) {
printf("Failed to load server private key from %s, ret = %d\n",
g_config.serverKeyFile, ret);
wolfSSL_CTX_free(*ctx);
*ctx = NULL;
return -1;
}
}
else {
ret = wolfSSL_CTX_use_PrivateKey_buffer(*ctx, server_key_der_2048,
sizeof_server_key_der_2048,
WOLFSSL_FILETYPE_ASN1);
if (ret != WOLFSSL_SUCCESS) {
printf("Failed to load built-in server private key, ret = %d\n", ret);
wolfSSL_CTX_free(*ctx);
*ctx = NULL;
return -1;
}
}
/* Require mutual authentication */
wolfSSL_CTX_set_verify(*ctx,
WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT,
NULL);
(void)hsm_client;
return 0;
}
/*
* Initialize the UDP socket for DTLS.
* For TLS, this would need to be changed to TCP socket initialization.
*/
static int initialize_udp_socket(SERVER_CONTEXT* ctx)
{
int ret;
struct sockaddr_in servAddr;
char peekBuf[1];
int optval = 1;
/* Create a UDP socket */
ctx->listenfd = socket(AF_INET, SOCK_DGRAM, 0);
if (ctx->listenfd < 0) {
perror("socket()");
return -1;
}
/* Allow socket reuse */
ret = setsockopt(ctx->listenfd, SOL_SOCKET, SO_REUSEADDR, &optval,
sizeof(optval));
if (ret < 0) {
perror("setsockopt(SO_REUSEADDR)");
close(ctx->listenfd);
ctx->listenfd = -1;
return -1;
}
/* Bind to all interfaces on the specified port */
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(ctx->port);
ret = bind(ctx->listenfd, (struct sockaddr*)&servAddr, sizeof(servAddr));
if (ret < 0) {
perror("bind()");
close(ctx->listenfd);
ctx->listenfd = -1;
return -1;
}
/* Wait for the first packet to get client address */
printf("Waiting for client on port %d...\n", ctx->port);
ctx->cliLen = sizeof(ctx->cliaddr);
ret = recvfrom(ctx->listenfd, peekBuf, sizeof(peekBuf), MSG_PEEK,
(struct sockaddr*)&ctx->cliaddr, &ctx->cliLen);
if (ret < 0) {
perror("recvfrom()");
close(ctx->listenfd);
ctx->listenfd = -1;
return -1;
}
printf("Received initial packet from %s:%d\n",
inet_ntoa(ctx->cliaddr.sin_addr),
ntohs(ctx->cliaddr.sin_port));
return 0;
}
/*
* Set up the WOLFSSL object for accepting a connection.
* For DTLS, this includes setting the peer address.
*/
static int setup_ssl_accept(SERVER_CONTEXT* ctx)
{
ctx->ssl = wolfSSL_new(g_ctx);
if (ctx->ssl == NULL) {
fprintf(stderr, "wolfSSL_new error - check debug output above\n");
return -1;
}
/* Set the peer address (DTLS-specific) */
if (wolfSSL_dtls_set_peer(ctx->ssl, &ctx->cliaddr,
ctx->cliLen) != WOLFSSL_SUCCESS) {
fprintf(stderr, "wolfSSL_dtls_set_peer error\n");
wolfSSL_free(ctx->ssl);
ctx->ssl = NULL;
return -1;
}
if (wolfSSL_set_fd(ctx->ssl, ctx->listenfd) != WOLFSSL_SUCCESS) {
fprintf(stderr, "wolfSSL_set_fd error\n");
wolfSSL_free(ctx->ssl);
ctx->ssl = NULL;
return -1;
}
return 0;
}
/*
* Perform the TLS/DTLS handshake.
*
* All crypto operations during this handshake (key exchange, signatures,
* encryption) will be performed by the wolfHSM server.
*/
static int perform_ssl_accept(SERVER_CONTEXT* ctx)
{
int ret;
printf("Starting handshake (crypto via wolfHSM)...\n");
ret = wolfSSL_accept(ctx->ssl);
if (ret != WOLFSSL_SUCCESS) {
int err = wolfSSL_get_error(ctx->ssl, ret);
fprintf(stderr, "wolfSSL_accept failed: error = %d, %s\n", err,
wolfSSL_ERR_reason_error_string(err));
return -1;
}
printf("Handshake successful!\n");
printf("Cipher: %s\n", wolfSSL_get_cipher(ctx->ssl));
return 0;
}
/* Public API implementations */
SERVER_CONTEXT* Server_Get(void)
{
return &g_server;
}
int Server_Init(SERVER_CONTEXT* ctx, whClientContext* client,
const ServerConfig* config)
{
int ret;
if (ctx == NULL || client == NULL) {
return -1;
}
/* Store config in static variable for use by initialize_wolfssl */
if (config != NULL) {
g_config = *config;
} else {
memset(&g_config, 0, sizeof(g_config));
g_config.port = SERVER_PORT_DEFAULT;
}
memset(ctx, 0, sizeof(SERVER_CONTEXT));
ctx->listenfd = -1; /* Initialize to invalid fd to prevent closing stdin */
ctx->hsm_client = client;
ctx->port = (g_config.port > 0) ? g_config.port : SERVER_PORT_DEFAULT;
/* Initialize wolfSSL with HSM crypto offload */
ret = initialize_wolfssl(&g_ctx, client);
if (ret != 0) {
fprintf(stderr, "Failed to initialize wolfSSL\n");
return -1;
}
/* Initialize UDP socket and wait for client (DTLS mode) */
ret = initialize_udp_socket(ctx);
if (ret != 0) {
fprintf(stderr, "Failed to initialize socket\n");
wolfSSL_CTX_free(g_ctx);
g_ctx = NULL;
return -1;
}
/* Set up SSL for accepting connection */
ret = setup_ssl_accept(ctx);
if (ret != 0) {
fprintf(stderr, "Failed to set up SSL accept\n");
close(ctx->listenfd);
ctx->listenfd = -1;
wolfSSL_CTX_free(g_ctx);
g_ctx = NULL;
return -1;
}
return 0;
}
int Server_Accept(SERVER_CONTEXT* ctx)
{
if (ctx == NULL || ctx->ssl == NULL) {
return -1;
}
return perform_ssl_accept(ctx);
}
int Server_Read(SERVER_CONTEXT* ctx, unsigned char* data, size_t length)
{
int ret;
if (ctx == NULL || ctx->ssl == NULL || data == NULL) {
return -1;
}
if (length > INT_MAX) {
return -1;
}
ret = wolfSSL_read(ctx->ssl, data, (int)length);
if (ret < 0) {
int err = wolfSSL_get_error(ctx->ssl, ret);
if (err != WOLFSSL_ERROR_WANT_READ) {
fprintf(stderr, "wolfSSL_read failed: error = %d, %s\n", err,
wolfSSL_ERR_reason_error_string(err));
}
return -1;
}
return ret;
}
int Server_Write(SERVER_CONTEXT* ctx, unsigned char* data, size_t length)
{
int ret;
if (ctx == NULL || ctx->ssl == NULL || data == NULL) {
return -1;
}
if (length > INT_MAX) {
return -1;
}
ret = wolfSSL_write(ctx->ssl, data, (int)length);
if (ret < 0) {
int err = wolfSSL_get_error(ctx->ssl, ret);
fprintf(stderr, "wolfSSL_write failed: error = %d, %s\n", err,
wolfSSL_ERR_reason_error_string(err));
return -1;
}
return ret;
}
void Server_Cleanup(SERVER_CONTEXT* ctx)
{
if (ctx == NULL) {
return;
}
if (ctx->ssl != NULL) {
wolfSSL_shutdown(ctx->ssl);
wolfSSL_free(ctx->ssl);
ctx->ssl = NULL;
}
if (ctx->listenfd >= 0) {
close(ctx->listenfd);
ctx->listenfd = -1;
}
if (g_ctx != NULL) {
wolfSSL_CTX_free(g_ctx);
g_ctx = NULL;
}
wolfSSL_Cleanup();
}
int Server_Close(SERVER_CONTEXT* ctx)
{
Server_Cleanup(ctx);
return 0;
}