In recent years, there have been a number of security issues taking advantage of flaws in applications and even computer processors. These opened new attack vectors or made some others more viable and exploitable than before. We can talk about timing differences, cache access patterns and other side-channel attacks that can be exploited either locally, from the same machine or even over the network to read or reconstruct our secrets.

Keeping secret information storage isolated from other unrelated applications on a single system is a long-standing data protection technique. Storage isolation is usually implemented in software by isolating processes, applications, containers or virtual machines running on the same physical machine. Hardware tokens are taking this principle to another level, providing the physical isolation of the secret information, which has the potential to improve security significantly. Working with external hardware for storing secrets in an operating system historically has been difficult for system administrators and end users, and this is what we are improving in Red Hat Enterprise Linux 8.

Moving secrets to hardware: how does it work?

Dedicated hardware to store secrets means smart cards and cryptographic tokens typically used for end-user authentication and Hardware Security Modules (HSM) for server applications. The advantage is in using separate hardware circuits independent from the host computer, exposing limited interfaces for specific operations only, preventing the extraction of secrets and mitigating most of the attacks of the past. Some cards are also tamper-resistant, so any unauthorized physical attempt to retrieve the secrets should result in destroying them.

More consistent access to cryptographic hardware

Smart cards and HSMs are generally accessed by applications using the PKCS #11 API. But it is a very low-level interface and not intended to be used by users or system administrators. For this reason, every application or library that wanted to support hardware cryptographic tokens had to implement a way to identify them, which was not standardized until the introduction of PKCS #11 URIs (RFC 7512) in 2015. This is the first piece of our solution, which enables your applications and libraries to identify objects in a consistent way. The example of a PKCS #11 URI can look like this:

pkcs11:token=Test%20Cardholder%20VIII;id=%02;object=SIGN%20pubkey;type=public

To be able to identify objects originating from various sources, in Red Hat Enterprise Linux 8, we provide the OpenSC PKCS #11 driver for smart cards by default, but some hardware tokens or HSMs may come with their own PKCS #11 modules that are not part of the Red Hat Enterprise Linux.

In the past, the set up and configuration of an application using hardware tokens required the user to specify the token to be used together with the path to the driver. This had to be repeated for every application or library which could potentially use hardware tokens. In Red Hat Enterprise Linux 8, we provide a simpler way of registering third-party PKCS #11 modules with p11-kit. The p11-kit configured drivers should be automatically propagated to applications and libraries that use hardware tokens.

Adding your own PKCS #11 module into the system requires a new text file in the /etc/pkcs11/modules/ directory. For example, the OpenSC configuration file in p11-kit is as simple as that:

$ cat /usr/share/p11-kit/modules/opensc.module
module: opensc-pkcs11.so

Using PKCS #11 in applications and libraries

In the next sections, we will provide more information on which use cases are handled by common applications and libraries in Red Hat Enterprise Linux 8. The whole picture of the software stack is summed up on the following diagram. 

Software stack in RHEL 8

How to use OpenSSH clients with smart cards

In the past, the keys on smart cards were limited to RSA keys and the user had to provide the path to the PKCS #11 module directly. Currently, we have added support for ECDSA keys and users can reference the keys by the PKCS #11 URI, wherever they would put the path to the private key before. The simplest way to connect to a remote server with a private key from a smart card is as easy as that:

$ ssh -i pkcs11: example.com

OpenSSH now knows where to look for the p11-kit-proxy module, which provides access to all configured PKCS #11 tokens. PKCS #11 URI can further narrow the key specification with arguments, such as an ID to select specific key for authentication, which was not possible before:

$ ssh -i “pkcs11:id=%01” example.com

How HTTPS clients (curl, wget) can use smart cards

Both command-line HTTPS clients now work with PKCS #11 URIs when specified instead of the path to the private key and certificate for TLS Client Authentication. This is useful for scripting simple tasks requiring safely stored private keys. For example:

$ wget --private-key 'pkcs11:id=%01;type=private?pin-value=111111' \
 --certificate 'pkcs11:id=%01;type=cert' https://example.com/
$ curl --key 'pkcs11:id=%01;type=private?pin-value=111111' \
 --cert 'pkcs11:id=%01;type=cert' https://example.com/

How HTTPS servers (httpd, nginx) can use HSMs

These HTTPS servers can work with private keys stored on HSMs, which prevents their disclosure and MitM attacks. Note that this use case might require fast HSMs for busy servers.

Apache's httpd uses the OpenSSL library, which does not support PKCS #11 natively. To utilize HSMs, you have to install also openssl-pkcs11 package, providing access to PKCS #11 modules through the engine interface. You can use the PKCS #11 URI instead of a regular file to specify server key and certificate:

SSLCertificateFile    pkcs11:id=%01;type=cert
SSLCertificateKeyFile pkcs11:id=%01;type=private?pin-value=111111

The nginx web server also uses the OpenSSL library for cryptographic operations, so support has to go through the openssl-pkcs11 engine. At the time of writing this document, nginx only supports loading the private keys from an HSM, and a certificate needs to be provided separately as a regular file.

ssl_certificate     /path/to/cert.pem
ssl_certificate_key "engine:pkcs11:pkcs11:id=%01;type=private?pin-value=111111";

Note that the prefix engine:pkcs11: is needed for the PKCS #11 URI in the nginx configuration file, since the first pkcs11 refers to the engine name.

Libreswan VPN client

Libreswan uses the NSS cryptographic library, which supports PKCS #11 natively. Therefore, PKCS #11 URIs can be used instead of the certificate nickname in NSS DB:

conn example
   [...]
   authby=rsasig
   leftrsasigkey=%cert
   leftcert=”pkcs11:id=%01;type=cert”

What is new in Firefox regarding PKCS #11 support

Firefox automatically loads the p11-kit-proxy module to automatically detect  smart cards in the system. For using TLS client authentication, no additional setup is required and keys from a smart card are automatically used when a server requests it.

What about my custom applications?

Your existing applications should work the same as in previous versions of Red Hat Enterprise Linux. If you are designing a new application using some of the main cryptographic libraries, it should simplify your access to the cryptographic hardware. GnuTLS and NSS support PKCS #11 natively and use p11-kit automatically, while OpenSSL can use the hardware modules through the openssl-pkcs11 engine.

If your application requires providing a PKCS #11 module manually, it is a good idea to start using p11-kit or its proxy module. If you are seeking a way how to identify objects on the cryptographic hardware, we recommend the use of  PKCS #11 URI (RFC 7512) for consistency with the operating system. The p11-kit library provides a simple API to work with PKCS #11 URIs.

Conclusion

As vulnerabilities continue to be discovered, identity theft and data leaks are becoming more and more common. Smart cards and HSMs help to mitigate some of these attacks, but isolation of secrets to separate hardware, such as smart cards or HSMs, used to be a complicated task. We made it more accessible to users and administrators by adding p11-kit to the core of our operating system and updating the most important applications to be able to use it. This creates a system-wide registry of PKCS #11 modules and provides consistent identification using PKCS #11 URIs and simplified  configuration and usage.

Jakub Jelen is a senior software engineer in Red Hat Enterprise Linux Crypto team.