HSM/PKCS#11 Support

Ghostunnel can load private keys from any hardware security module that exposes a PKCS#11 interface. CGO is required for PKCS#11 support. SoftHSM is an easy way to test without real hardware.

To import the server test key into SoftHSM, for example:

softhsm2-util --init-token \
    --slot 0 \
    --label ghostunnel-server \
    --so-pin 1234 \
    --pin 1234

softhsm2-util --id 01 \
    --token ghostunnel-server \
    --label ghostunnel-server \
    --import test-keys/server-pkcs8.pem \
    --so-pin 1234 \
    --pin 1234

To launch Ghostunnel with the SoftHSM-backed PKCS#11 key:

ghostunnel server \
    --cert test-keys/server-cert.pem \
    --pkcs11-module /path/to/libsofthsm2.so \
    --pkcs11-token-label ghostunnel-server \
    --pkcs11-pin 1234 \
    --listen localhost:8443 \
    --target localhost:8080 \
    --cacert test-keys/cacert.pem \
    --allow-cn client

The --pkcs11-module, --pkcs11-token-label, and --pkcs11-pin flags select the private key from the PKCS#11 module. You can also set these via environment variables (PKCS11_MODULE, PKCS11_TOKEN_LABEL, PKCS11_PIN) to keep the PIN off the command line.

Note: --cert must point to the certificate chain matching the private key in the PKCS#11 module, with the leaf certificate first (see Certificate Formats). Ghostunnel cannot read the certificate chain from the module directly.

Using a YubiKey

YubiKey 4 and 5 series support the PIV (FIPS 201) standard, which exposes a PKCS#11 interface via the YKCS11 module, so you can use a YubiKey to hold Ghostunnel’s private key in hardware.

Prerequisites

You’ll need yubico-piv-tool, which ships the CLI and the libykcs11 PKCS#11 module:

# macOS
brew install yubico-piv-tool

# Debian/Ubuntu
apt install yubico-piv-tool ykcs11

The module lives in different places depending on your platform:

PlatformTypical path
macOS (Apple Silicon)/opt/homebrew/lib/libykcs11.dylib
macOS (Intel)/usr/local/lib/libykcs11.dylib
Linux (x86_64)/usr/lib/x86_64-linux-gnu/libykcs11.so or /usr/local/lib/libykcs11.so

PIV slots

YubiKey PIV has several key slots. For TLS with Ghostunnel, you’ll usually want slot 9a (Authentication):

SlotPurposeTypical use
9aAuthenticationTLS client/server certs
9cDigital SignatureCode/document signing
9dKey ManagementEncryption
9eCard AuthenticationPhysical access

Generating a Key and Certificate

Generate a key pair on the YubiKey itself (the private key never leaves the device):

# Generate an RSA 2048 key in slot 9a
yubico-piv-tool -s 9a -a generate -A RSA2048 -o public-key.pem

# Create a certificate signing request (CSR)
yubico-piv-tool -s 9a -a verify-pin -a request-certificate \
    -S '/CN=my-server/' -i public-key.pem -o csr.pem

Sign the CSR with your CA, then import the signed certificate back:

yubico-piv-tool -s 9a -a import-certificate -i server-cert.pem

Exporting the Certificate for Ghostunnel

Ghostunnel reads the certificate chain from disk, not from the PKCS#11 module, so you’ll need to export it:

yubico-piv-tool -s 9a -a read-certificate -o server-cert.pem

If your CA has an intermediate, concatenate them into a chain (leaf first):

cat server-cert.pem intermediate.pem > chain.pem

Launching Ghostunnel with a YubiKey

ghostunnel server \
    --cert chain.pem \
    --pkcs11-module /opt/homebrew/lib/libykcs11.dylib \
    --pkcs11-token-label "YubiKey PIV #12345678" \
    --pkcs11-pin 123456 \
    --listen localhost:8443 \
    --target localhost:8080 \
    --cacert cacert.pem \
    --allow-cn client

The default PIV PIN is 123456. Change it before doing anything real. To keep the PIN off the command line, use the PKCS11_PIN environment variable instead of --pkcs11-pin.

To find the correct token label for your YubiKey:

pkcs11-tool --module /opt/homebrew/lib/libykcs11.dylib -L

Debugging

If things aren’t working, set YKCS11_DBG (values 1–9) for verbose output from the YKCS11 module:

YKCS11_DBG=1 ghostunnel server ...

pkcs11-tool is also handy for poking around on the YubiKey:

# List available slots/tokens
pkcs11-tool --module /path/to/libykcs11.dylib -L

# List objects (keys, certificates) on the token
pkcs11-tool --module /path/to/libykcs11.dylib -O

Certificate Hotswapping

When using PKCS#11, certificate hotswapping (via SIGHUP/SIGUSR1 or --timed-reload) reloads only the certificate from disk. The private key in the HSM is not reloaded, so the new certificate must still match it.

Note that Landlock sandboxing is automatically disabled when PKCS#11 is used, as PKCS#11 modules are opaque shared libraries that may need access to arbitrary files and sockets.

Inspecting PKCS#11 State

Use the pkcs11-tool utility from OpenSC to inspect PKCS#11 module/token state. For example:

# List slots on a module
pkcs11-tool --module $MODULE -L

# Show certificates (if any) available
pkcs11-tool --module $MODULE -O -y cert

# Read certificate chain given a label
pkcs11-tool --module $MODULE --label $LABEL --read-object -y cert