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:
| Platform | Typical 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):
| Slot | Purpose | Typical use |
|---|---|---|
| 9a | Authentication | TLS client/server certs |
| 9c | Digital Signature | Code/document signing |
| 9d | Key Management | Encryption |
| 9e | Card Authentication | Physical 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