Chapter 4. Configuring applications to use cryptographic hardware through PKCS #11
Separating parts of your secret information on dedicated cryptographic devices, such as smart cards and cryptographic tokens for end-user authentication and hardware security modules (HSM) for server applications, provides an additional layer of security. In Red Hat Enterprise Linux 8, support for cryptographic hardware through the PKCS #11 API is consistent across different applications, and the isolation of secrets on cryptographic hardware is not a complicated task.
4.1. Cryptographic hardware support through PKCS #11
PKCS #11 (Public-Key Cryptography Standard) defines an application programming interface (API) to cryptographic devices that hold cryptographic information and perform cryptographic functions. These devices are called tokens, and they can be implemented in a hardware or software form.
A PKCS #11 token can store various object types including a certificate; a data object; and a public, private, or secret key. These objects are uniquely identifiable through the PKCS #11 URI scheme.
A PKCS #11 URI is a standard way to identify a specific object in a PKCS #11 module according to the object attributes. This enables you to configure all libraries and applications with the same configuration string in the form of a URI.
Red Hat Enterprise Linux 8 provides the OpenSC PKCS #11 driver for smart cards by default. However, hardware tokens and HSMs can have their own PKCS #11 modules that do not have their counterpart in Red Hat Enterprise Linux. You can register such PKCS #11 modules with the
p11-kit tool, which acts as a wrapper over the registered smart card drivers in the system.
To make your own PKCS #11 module work on the system, add a new text file to the
You can add your own PKCS #11 module into the system by creating a new text file in the
/etc/pkcs11/modules/ directory. For example, the OpenSC configuration file in
p11-kit looks as follows:
$ cat /usr/share/p11-kit/modules/opensc.module module: opensc-pkcs11.so
4.2. Using SSH keys stored on a smart card
Red Hat Enterprise Linux enables you to use RSA and ECDSA keys stored on a smart card on OpenSSH clients. Use this procedure to enable authentication using a smart card instead of using a password.
On the client side, the
openscpackage is installed and the
pcscdservice is running.
List all keys provided by the OpenSC PKCS #11 module including their PKCS #11 URIs and save the output to the keys.pub file:
$ ssh-keygen -D pkcs11: > keys.pub $ ssh-keygen -D pkcs11: ssh-rsa AAAAB3NzaC1yc2E...KKZMzcQZzx pkcs11:id=%02;object=SIGN%20pubkey;token=SSH%20key;manufacturer=piv_II?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so ecdsa-sha2-nistp256 AAA...J0hkYnnsM= pkcs11:id=%01;object=PIV%20AUTH%20pubkey;token=SSH%20key;manufacturer=piv_II?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so
To enable authentication using a smart card on a remote server (example.com), transfer the public key to the remote server. Use the
ssh-copy-idcommand with keys.pub created in the previous step:
$ ssh-copy-id -f -i keys.pub firstname.lastname@example.org
To connect to example.com using the ECDSA key from the output of the
ssh-keygen -Dcommand in step 1, you can use just a subset of the URI, which uniquely references your key, for example:
$ ssh -i "pkcs11:id=%01?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so" example.com Enter PIN for 'SSH key': [example.com] $
You can use the same URI string in the
~/.ssh/configfile to make the configuration permanent:
$ cat ~/.ssh/config IdentityFile "pkcs11:id=%01?module-path=/usr/lib64/pkcs11/opensc-pkcs11.so" $ ssh example.com Enter PIN for 'SSH key': [example.com] $
Because OpenSSH uses the
p11-kit-proxywrapper and the OpenSC PKCS #11 module is registered to PKCS#11 Kit, you can simplify the previous commands:
$ ssh -i "pkcs11:id=%01" example.com Enter PIN for 'SSH key': [example.com] $
If you skip the
id= part of a PKCS #11 URI, OpenSSH loads all keys that are available in the proxy module. This can reduce the amount of typing required:
$ ssh -i pkcs11: example.com Enter PIN for 'SSH key': [example.com] $
- Fedora 28: Better smart card support in OpenSSH
4.3. Using HSMs protecting private keys in Apache and Nginx
Nginx HTTP servers can work with private keys stored on hardware security modules (HSMs), which helps to prevent the keys' disclosure and man-in-the-middle attacks. Note that this usually requires high-performance HSMs for busy servers.
Apache HTTP server
For secure communication in the form of the HTTPS protocol, the
Apache HTTP server (
httpd) uses the OpenSSL library. OpenSSL does not support PKCS #11 natively. To utilize HSMs, you have to install the
openssl-pkcs11 package, which provides access to PKCS #11 modules through the engine interface. You can use a PKCS #11 URI instead of a regular file name to specify a server key and a certificate in the
/etc/httpd/conf.d/ssl.conf configuration file, for example:
SSLCertificateFile "pkcs11:id=%01;token=softhsm;type=cert" SSLCertificateKeyFile "pkcs11:id=%01;token=softhsm;type=private?pin-value=111111"
httpd-manual package to obtain complete documentation for the
Apache HTTP Server, including TLS configuration. The directives available in the
/etc/httpd/conf.d/ssl.conf configuration file are described in detail in /usr/share/httpd/manual/mod/mod_ssl.html.
Nginx HTTP and proxy server
Nginx also uses the OpenSSL for cryptographic operations, support for PKCS #11 must go through the
Nginx currently supports only loading private keys from an HSM, and a certificate must be provided separately as a regular file. Modify the
ssl_certificate_key options in the
server section of the
/etc/nginx/nginx.conf configuration file:
ssl_certificate /path/to/cert.pem ssl_certificate_key "engine:pkcs11:pkcs11:token=softhsm;id=%01;type=private?pin-value=111111";
Note that the
engine:pkcs11: prefix is needed for the PKCS #11 URI in the
Nginx configuration file. This is because the other
pkcs11 prefix refers to the engine name.
4.4. Configuring applications to authenticate using certificates from smart cards
wgetnetwork downloader enables you to specify PKCS #11 URIs instead of paths to locally stored private keys, and thus simplifies creating scripts for tasks that require safely stored private keys and certificates. For example:
$ wget --private-key 'pkcs11:token=softhsm;id=%01;type=private?pin-value=111111' --certificate 'pkcs11:token=softhsm;id=%01;type=cert' https://example.com/
wget(1)man page for more information.
Specifying PKCS #11 URI for use by the
curltool is analogous:
$ curl --key 'pkcs11:token=softhsm;id=%01;type=private?pin-value=111111' --cert 'pkcs11:token=softhsm;id=%01;type=cert' https://example.com/
curl(1)man page for more information.
Firefoxweb browser automatically loads the
p11-kit-proxymodule. This means that every supported smart card in the system is automatically detected. For using TLS client authentication, no additional setup is required and keys from a smart card are automatically used when a server requests them.
Using PKCS #11 URIs in custom applications
If your application uses the
NSS library, support for PKCS #11 URIs is ensured by their built-in support for PKCS #11. Also, applications relying on the
OpenSSL library can access cryptographic hardware modules thanks to the
With applications that require working with private keys on smart cards and that do not use
p11-kit to implement registering PKCS #11 modules.
p11-kit(8) man page for more information.