Certificate authorities use some serious security measures to protect their signing keys (or at least they’re supposed to). These high security requirements are the realm of the traditional hardware security module (HSM). These things address threat models that include attacks against both software and hardware, sometimes very sophisticated ones (like decapping). You get what you pay for, and so HSMs can get pretty pricey. These extreme levels of security and the associated price seems reasonable to me, at least for the CAs whose keys are trusted by the likes of Chrome and Firefox (and subsequently all of their users).
Not all CAs need that kind of security though. Definitely not the CA I use for various test applications. For this I’ve always just kept the keys on a thumb drive as a way to keep them off of my laptop.
The type, strength and cost of the security measures appropriate for an application aren’t binary. The two example applications above are likely the extremes since the key protection schemes have such radically different security properties: HSM vs commodity OS storing keys / files on disk. But between these two applications are a spectrum of others with varying threat models.
root CA signing key in TPM2
What these applications are isn’t the interesting part so long as we’re willing to admit that they exist. What *is* interesting are the technologies available to mitigate relevant threats. Historically, there haven’t been many options available between the two extremes described above. Recently however some products have emerged to fill this space including TPM2. Microsoft added TPM2 to their logo requirements for Windows 10 so it’s effectively ubiquitous in newer laptops. TPM2 is an interesting option because it mitigates key theft through the use of “shielded locations” where sensitive operations (use of private keys) are carried out separate from the main CPU. For my particular application this is “good enough”.
I’ve always used the OpenSSL tools and the associated commands to manage my local CA. The available documentation and collective knowledge on the internet make this tool indispensable and I’ve got my workflow scripted. What I want to do is integrate the TPM2 OpenSSL engine into my existing scripts and configurations.
Documentation for building and installing tpm2tss openssl engine is here: https://github.com/tpm2-software/tpm2-tss-engine/blob/master/INSTALL.md. The rest of this document assumes you have it installed and properly configured.
make your root key
Using the TPM2 to protect your CA signing keys is surprisingly easy. I typically shy away from using the word “easy” when talking about the TPM but in this case, and thanks to the TPM2 OpenSSL Engine it really is. The `tpm2tss` engine provides a binary `tpm2tss-genkey` for key key generation. For this example a simple RSA 2k key is generated:
$ tpm2tss-genkey --alg rsa --keysize 2048 ca-root.key.tss
I’ve given the root key the extension `.tss` because it’s in a form unique to the tpm2tss engine.
Once you’ve got your ca root key we can use the `openssl` command line tool to generate a CSR for it.
NOTE: The details of the openssl configuration file used for root CA signing keys is beyond the scope of this document. I’m using unmodified versions of these same files from the exceptional OpenSSL Certificate Authority by Jamie Nguyen, openssl.cnf.
$ openssl req \ -config openssl.cnf \ -new -x509 \ -engine tpm2tss \ -key ca-root.key.tss \ -keyform engine \ -new -x509 \ -days 7300 \ -sha256 \ -extensions v3_ca \ -out ca-root.cert
Notice that the options for this command include `-engine tpm2tss` as well as `-keyform engine`. This causes openssl to generate & sign a CSR for the root key. The output is a self signed cert for the `ca-root.key.tss` key. It’s possible to include the engine configuration in the `openssl.cnf`. They’re provided on the commend line here for emphasis.
The rest of this is CA stuff is mechanical: We use the `openssl` tool `req` and `ca` commands to issue subkeys for various purposes while providing the new engine specific command line options. All of this is signing operations and certificate generation and all supported by the tpm2tss openssl engine. I followed Jamie Nguyen’s documentation above substituting in use of the `tpm2tss` engine on the command line where appropriate and everything worked as expected.
TPM2 is a powerful tool and thanks to the `tpm2-tss-engine` we can continue to use the `openssl` command line tools we all know and love while benefiting from the protections offered by TPM2. The example above is just an example though. Root signing keys are rarely used and so storing them offline or in a token like a yubikey is often the best choice. TPM2 may be a better fit for intermediate keys, like those on a signing server integrated into a CI pipeline. Might be fun to build an “ideal” home CA architecture with a yubikey for the root keys and an embedded platform with a TPM2 for issuing credentials as an an intermediate CA for some application.