OpenSSL v1.x uses the engine API to support HSMs. The OpenSC project provides a PKCS#11 engine, suitable for using HSMs that provide a PKCS#11 module. OpenSSL v1 is however deprecated, and in OpenSSL v3 the engine concept is replaced with that of a provider
Instead of using OpenSC's PKCS#11 engine, you can use pkcs11-provider with OpenSSL v3.x
This document describes how to use the YubiHSM with OpenSSL v3 and this provider.
Currently (July 2024), pkcs11-provider
is not distributed yet with various Linux distributions.
It is however in Debian-unstable.
For this test, we are using Docker with a recent Debian sid
image:
docker run --rm -it --name pkcs11-provider-test debian:sid bash
First update the list of available packages and install package management tools:
apt update
apt install -y apt-utils
Install git and clone the YubiHSM SDK repository to build from source:
apt install -y git
git clone https://github.com/Yubico/yubihsm-shell.git
cd yubihsm-shell/
Follow the build instructions from the SDK's README file:
mkdir build
cd build/
apt install -y build-essential cmake gengetopt help2man libcurl4-openssl-dev libedit-dev libpcsclite-dev libssl-dev libusb-1.0-0-dev pkg-config
cmake ..
cmake --build .
In case you encounter this error message:
/usr/include/PCSC/winscard.h:44:10: fatal error: pcsclite.h: No such file or directory
there is something wrong with your install. Probably an issue with pkg-config.
A quick workaround is to edit the .h files in /usr/include/PCSC
:
sed -i'' 's#<pcsclite.h#<PCSC/pcsclite.h#;s#<wintypes.h#<PCSC/wintypes.h#' /usr/include/PCSC/*.h
When the build is succesful, install the binaries:
make install
You shound now be able to tun the YubiHSM shell:
yubihsm-shell -h
On the docker host, start yubihsm-connector
, so we can connect to it remotely over HTTP.
to verify the connector can be accessed, retrieve the status page:
apt install -y curl
curl http://host.docker.internal:12345/connector/status
this should return status=OK
.
Create the YubiHSM configuration file pointing to your connector, and make its location known to YubiHSM's PKCS#11 module using the appropriate environment variable:
echo "connector=http://host.docker.internal:12345" > yubihsm.conf
export YUBIHSM_PKCS11_CONF=$PWD/yubihsm.conf
Assume the YubiHSM has been factory reset with the default authentication password. Together with its ID, this will be the PKCS#11 user PIN:
export PIN=0001password
Define an environment variable to point to the YibiHSM PKCS#11 module On Debian, this is:
export PKCS11_PROVIDER_MODULE=/usr/local/lib/pkcs11/yubihsm_pkcs11.so
Install pkcs11-tool
(part of OpenSC) to generate keys (and simultaneously test the YubiHSM PKCS#11 module setup):
apt install -y opensc
pkcs11-tool --module $PKCS11_PROVIDER_MODULE --login --pin $PIN --keypairgen --key-type rsa:2048 --label "my_key" --usage-sign
We use the label my_key
to refer to this key.
Install pkcs11-provider:
apt install -y pkcs11-provider
This should install the provider in OpenSSL's modules directory. The location of that directory can be retrieved with:
openssl version -m
This should output something like:
MODULESDIR: "/usr/lib/aarch64-linux-gnu/ossl-modules"
Verify that the file /usr/lib/aarch64-linux-gnu/ossl-modules/pkcs11.so
exists.
OpenSSL v3 should already be installed on your system.
To interface with the PKCS#11 provider, we need to use a configuration file:
cat << EOF > openssl.cnf
HOME = .
openssl_conf = openssl_init
[openssl_init]
providers = provider_sect
[provider_sect]
default = default_sect
pkcs11 = pkcs11_sect
[default_sect]
activate = 1
[pkcs11_sect]
module = /usr/lib/aarch64-linux-gnu/ossl-modules/pkcs11.so
pkcs11-module-path = $PKCS11_PROVIDER_MODULE
pkcs11-module-token-pin = $PWD/pinfile.txt
activate = 1
EOF
Store the PIN in a file (not the best option, but fine for this test):
echo $PIN > pinfile.txt
Use a pkcs11 URI to refer to the key we generated earlier. Note the use of the key's label, my_key
:
export KEY="pkcs11:token=YubiHSM;object=my_key;type=private;pin-value=$PIN"
Generate a self-signed certificate for the key stored in the HSM, using OpenSSL, the PKCS#11 provider, and the YubiHSM PKCS#11 module, according to the configuration file:
openssl req -config ./openssl.cnf -new -x509 -days 365 -subj '/CN=localhost/' -sha256 -key "$KEY" -out cert.pem
Use OpenSSL as a simple HTTPS server with the generated certificate and the key stored in the HSM:
OPENSSL_CONF=./openssl.cnf openssl s_server -cert cert.pem -key $KEY -www
As a client, use curl
to connect with the web server.
docker exec pkcs11-provider-test curl -s https://localhost:4433/ -k
This should succesfully establish an HTTPS connection with the web server.