[ req ]
distinguished_name = req_dn
string_mask = utf8only
utf8 = yes
[ req_dn ]
commonName = Common Name (eg, your name)
Install engine_pkcs11
and pkcs11-tool
from OpenSC before proceeding.
Depending on your operating system and configuration you may have to install
[libp11](https://github.com/OpenSC/libp11/blob/master/INSTALL.md) as well.
If you are on macOS you will have to [symlink pkg-config
](https://gist.github.com/aklap/e885721ef15c8668ed0a1dd64d2ea1a7#gistcomment-2814899)
in order to do so.
OpenSSL requires engine settings in the openssl.cnf
file.
Some OpenSSL commands allow specifying -conf ossl.conf
and some do not.
Setting the environment variable OPENSSL_CONF
always works, but be aware that
sometimes the default openssl.cnf
contains entries that are needed by
commands like openssl req
.
In other words, you may have to add the engine entries to your default OpenSSL
config file (openssl.cnf
in the directory shown by openssl version -d
) or
add other requirements for your OpenSSL command into the config file.
It is suggested that you create a separate config file for interactions with the HSM in order to prevent conflicts with previous settings or defaults.
An alias can be created to easily read from a dedicated config file and ensure compatibility across systems
alias yubissl='OPENSSL_CONF=/path/to/yubihsm.conf openssl'
Here is an example of generating a key in the device, creating a self-signed certificate and then signing a CSR with it:
pkcs11-tool --module /path/to/yubihsm_pkcs11.so --login --pin 0001password \ --keypairgen --key-type rsa:2048 --label "my_key" --usage-sign Using slot 0 with a present token (0x0) Logging in to "YubiHSM". Please enter User PIN: Key pair generated: Private Key Object; RSA label: my_key ID: 04ec Usage: sign Public Key Object; RSA 2048 bits label: my_key ID: 04ec Usage: none openssl req -new -x509 -days 365 -subj '/CN=my key/' -sha256 -config \ engine.conf -engine pkcs11 -keyform engine -key slot_0-label_my_key \ -out cert.pem engine "pkcs11" set. PKCS#11 token PIN: OPENSSL_CONF=engine.conf openssl x509 -req -CAkeyform engine -engine pkcs11 \ -in req.csr -CA cert.pem -CAkey slot_0-label_my_key -set_serial 1 -sha256 engine "pkcs11" set. Signature ok subject=/CN=test Getting CA Private Key PKCS#11 token PIN: -----BEGIN CERTIFICATE----- MIICkzCCAXsCAQEwDQYJKoZIhvcNAQELBQAwETEPMA0GA1UEAwwGbXkga2V5MB4X DTE3MDQyNDA3Mzc1MFoXDTE3MDUyNDA3Mzc1MFowDjEMMAoGA1UEAwwDZm9vMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqBARJLAIjSqKk2OuRWrs91EC MYjjZhxJE8IAMIiDDM2wSuQhB7A2CVW+/d1SG0k5cTEiasDBHbH9Bc2w+xn0l3Dh 8cXafvcFkjcNabHesrbcwRgItugw7PWBtyopWDtDhVWKS1zkpDO8iKjwiYciweaP 96nEHlQPPRUp7bf3IE7RTXENAqJai6QIYBZOrzHM9NrIz/6YaR2ua7SY7V/B3xaJ 7KsiQ8oHWuf+RDNkJOhbD+1fgeMtN8x+W4XYnCPQPjJ/MfjuHJ2n5EM3Vb/plh9H uT+D56ozIk41FeXgC4gNu8fIv2KE1XBMuJCGRbyh5xk0dkQdvKxtVEfiDcwxBwID AQABMA0GCSqGSIb3DQEBCwUAA4IBAQCHyskEU84T/YGhcjlpsdmobtyNhWc2ae/x fmQpY/XGzQkSmUZJA+Z04JMUbli7UKEOItmqSlU6j0BPy03UjavNHdDPYcUZIS28 fPtzTkU3FdEBM/zkPXStBCo9+N34l4qSdir9hFWM1/CpkfP8PhteUQAqImXjbDVh qhrfOg+kY3dAz91kLLXuA4YfuC+eEJh0JGuXCivhGre5LL9njrajHnJ+HSt6HHjC R4U27/hzoK3r12XE5NjznjcaKk1AKFXZE92nqG/WYliyLpNNSrN+AmEKrPOHb8My ZJlaGAfm3K9vLEjwrLQSAIKpMdpUcNE7Ay+EsEYTQpy43VvwI8vL -----END CERTIFICATE-----
For these examples, we assume you have all defaults and the engine config
below in engine.conf
, and provide an example of how to do the latter in
the certificate request example below.
cat > engine.conf <<EOF openssl_conf = openssl_init [openssl_init] engines = engine_section [engine_section] pkcs11 = pkcs11_section [pkcs11_section] engine_id = pkcs11 dynamic_path is not required if you have installed the appropriate pkcs11 engines to your openssl directory dynamic_path = /path/to/engine_pkcs11.{so|dylib} MODULE_PATH = /path/to/yubihsm_pkcs11.{so|dylib} it is not recommended to use "debug" for production use INIT_ARGS = connector=http://127.0.0.1:12345 debug init = 0 EOF OPENSSL_CONF=engine.conf openssl engine -t -c pkcs11 (pkcs11) pkcs11 engine [RSA, DSA, DH, RAND] [ available ]
Here is an example of using the YubiHSM 2 PRNG via OpenSSL to retrieve 64 bytes of data:
OPENSSL_CONF=engine.conf openssl rand -engine pkcs11 -hex 64 engine "pkcs11" set. 2aae245fc6d1c0419684ee8968ce26fba2dc3bb48a91bae912c8a82b11db818649325800e6e984fedfa1940a24731dc2721431979a287252a214ebb87624dcf1
The following two examples will fail if you are only using the config above
because it doesn’t have the req entries in openssl.cnf
.
You can integrate the engine.conf
entries into the system’s openssl.cnf
, or add
the following to the end of the above engine.conf
:
[ req ]
distinguished_name = req_dn
string_mask = utf8only
utf8 = yes
[ req_dn ]
commonName = Common Name (eg, your name)
Here is an example of requesting a certificate for an existing RSA key with ID 3:
openssl req -new -subj '/CN=test/' -sha256 -config engine.conf \ -engine pkcs11 -keyform engine -key 0:0003 engine "pkcs11" set. PKCS#11 token PIN: -----BEGIN CERTIFICATE REQUEST----- MIICVDCCATwCAQAwDzENMAsGA1UEAwwEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAJoTtK9p5XNDBaqy65IBDSj3mP9cpM0cw/sF/GZai6cx8Skf DjAhqOkloN+Jdc2OsnaBVSqCbsSjVTXfc83oB2q4M3U/tl/nfzTGHGCA48dbKUiz M807KoyYzFds9b7ZnGrwCmeXWjt2sAEGiJYEQt9gS9twabnCwxY4KySa9aNSNeHt AwnfP5V60C73xA7ATOPjuWXq4TWgMWzRD0IwA3h7MIgtevJio2MTPWlspdGbYrxr KsVfl/AocrSqYb44pMaRbAJAgOpJ8hsPjc9gkJnnrhmbkfV0v0AqjgwqxZa+BCWn gdGl5HwKVFLu+X3lsBw7xHHJtOYgeFpp8twfvT0CAwEAAaAAMA0GCSqGSIb3DQEB CwUAA4IBAQAcyImLuv7CrZJ1RPOf5d6u5LfYUadPXSGnozf3Ebgue12B51etKjYK 3cY8m9rRP3jRU5yWk3qoquZ7vCF7RNPf0N+7/blXHfoawx+ffEl/ToUZ5xr7IL0V Qz9qzEumdNmm6MoQPxPOgrb1oCAz103gkf+S4HZGntO83/D31znsEhCSakoAa44s 3I+7vmzhjwUZsvMUg3sg2NCjRYRX2RPIPmtkDgufqsdAkNyWHlzitjfVMZxf8BcY 9DBrpQe1O6UbE1K9kYj2YBJ9h/FxfNJUk8t+rCcSOcQjmcRtgbHwhk2q77rapmg2 YliaYEU1/e5kl+v+0WEg7rvXgh/VkY2h -----END CERTIFICATE REQUEST-----
Or alternatively a self-signed certificate for the same existing RSA key with ID 3:
openssl req -new -x509 -days 365 -subj '/CN=test/' -sha256 \ -config engine.conf -engine pkcs11 -keyform engine -key 0:0003 engine "pkcs11" set. PKCS#11 token PIN: -----BEGIN CERTIFICATE----- MIICmjCCAYICCQDX5mJwg+YmMjANBgkqhkiG9w0BAQsFADAPMQ0wCwYDVQQDDAR0 ZXN0MB4XDTE3MDMxNTIwMDkzOVoXDTE4MDMxNTIwMDkzOVowDzENMAsGA1UEAwwE dGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJoTtK9p5XNDBaqy 65IBDSj3mP9cpM0cw/sF/GZai6cx8SkfDjAhqOkloN+Jdc2OsnaBVSqCbsSjVTXf c83oB2q4M3U/tl/nfzTGHGCA48dbKUizM807KoyYzFds9b7ZnGrwCmeXWjt2sAEG iJYEQt9gS9twabnCwxY4KySa9aNSNeHtAwnfP5V60C73xA7ATOPjuWXq4TWgMWzR D0IwA3h7MIgtevJio2MTPWlspdGbYrxrKsVfl/AocrSqYb44pMaRbAJAgOpJ8hsP jc9gkJnnrhmbkfV0v0AqjgwqxZa+BCWngdGl5HwKVFLu+X3lsBw7xHHJtOYgeFpp 8twfvT0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAHeSL6Qwqr8ST4SqnC1T2jjME cjAT5eK4MqK3ayAy/Y/vYGtzARGIi9tGatyV6AFjs/0Me3/8du4bBVdC2DaP1hTf m4m1HShHKFdUlwUGcwYoVNquCz8d6hDu3nL0XvtFKX77aHHQZeB3t0uD8evYZdTS 8oAduJpkAdJV7CtCLbGhLlLD3siYkd5fD35lhHlg8T2n5F4srDafQVdrDb/myYmI 2UmrZWvKDWZ3UvzKt1XVS8omIx7aTrUAPqv/SEdpPmJvg0pgWTKvzAtsnsxlRQdd tdtJ/6nqhwXVSNXlDbyhFVo6J2u8BMEss2iausoSZBzf+YDOw2H+4GH6E11TmA== -----END CERTIFICATE-----
Here is an example of using OpenSSL s_server with an RSA key and cert with ID 3.
By default this command listens on port 4433 for HTTPS connections.
env OPENSSL_CONF=engine.conf openssl s_server -engine pkcs11 \ -keyform engine -key 0:0003 -cert rsa.crt -www engine "pkcs11" set. PKCS#11 token PIN: Using default temp DH parameters ACCEPT ACCEPT
Here is an example of using OpenSSL s_server with an ECDSA key and cert with ID 2:
env OPENSSL_CONF=engine.conf openssl s_server -engine pkcs11 -keyform engine \ -key 0:0002 -cert ecdsa.crt -www
We would like to thank Uri Blumenthal (uri@mit.edu) for contributing to this document.