Skip to content

Instantly share code, notes, and snippets.

@jjmcdn
Created October 21, 2016 16:53
Show Gist options
  • Save jjmcdn/f4fafef25e257490f1007c92168df407 to your computer and use it in GitHub Desktop.
Save jjmcdn/f4fafef25e257490f1007c92168df407 to your computer and use it in GitHub Desktop.
Using a TPM

copied from http://www.lorier.net/docs/tpm, all credit there:

Using a TPM

A TPM is designed to hold private keys and do operations on them. This means that you can avoid the private key ever being unencrypted in memory on your machine which makes stealing the private key, even with access to the machine hopefully impossible. Hopefully, even with physical access to the machine the worst the attacker can do is destroy the key material, unless they go to rather extreme lengths.

The downside of this is that it's complicated (hence the long list of things to do below), and the TPM is also quite slow. NOTES

Before we begin:

*opencryptoki* creates exportable keys (ie, with the password you can get the key out of the TPM), this is not really expected. You can perhaps experiment with Thomas Habet's implementation of pkcs11 for trousers

*opensc* appears to be much nicer than opencryptoki, but doesn't currently appear to support the TSS API exported by Trousers.

If things go wrong, unplug the power, unplug the battery (if any), and then when you reassemble everything on the first boot (only!) go to the BIOS and make sure the TPM is enabled, and clear it. The option in the BIOS often won't show unless it's been fully powered down since the last boot. This is to protect against remote attacks.

General principals

The general principal here is to use trousers as an API to the TPM. Then use opencryptoki's support for trousters to make that available as a pkcs11 module. Once we have a pkcs11 module, we can configure the machine to use it (using p11-kit) and/or individually configure programs to use pkcs11 directly. In theory a TPM is just another kind of Hardware Security Module (HSM), like a smart card. So we just use the same APIs. Setting up the TPM

trousers is the tpm management daemon. You'll need that.

  1. Install "trousers" Make sure tscd is running. Keep an eye out, it will open a tcp port, make sure it's bound to localhost!

  2. Install "tpm-tools" Run sudo tpm_version and sudo tpm_selftest and make sure everything looks healthy. If not, go back and try and figure out what's wrong. The most common reason is that you don't actually have a tpm, or it's disabled in the bios.

3. run sudo tpm_takeownership to initialise the tpm.
    Hit "enter" when asked for passwords. tpmtoken_init doesn't understand passwords. (sigh)
    If you get the error message "TPM is deactivated" then you need to enable it in your BIOS. This is done because clearing the tpm is a security risk, so it's enforced to have local access by forcing you to use the BIOS.
    If you've already taken ownership, you may need to power off the machine completely (incl. taking out the battery and unplugging power) before the "clear tpm" option appears in the BIOS if it's not there.

If you get a "No EK" error anywhere along the lines, try sudo tpm_createek

 4. Add your user to the "tss" and "pkcs11" group using sudo vigr, make sure you've picked up this new group information (probably by logging out and logging in again)

 5.  Run pkcs_startup

 6.  Restart the pkcsslotd daemon: sudo service opencryptoki restart

Setting up your user.

7. Run tpmtoken_init to create your user key.
    Under debian this was failing for me, I had to add /usr/lib/opencryptoki/stdll/ to the library search path.
    Verify this with: p11tool --provider /usr/lib/pkcs11/libopencryptoki.so --list-tokens
    If this fails with a set pin failure, you need to go back and take ownership again with an empty password.
    The default "security officer" password is "87654321".

8. Use /usr/sbin/pkcsconf -t to list the tokens.

9.  Create an RSA key: pkcs11-tool --module=/usr/lib/opencryptoki/libopencryptoki.so.0 --login --keypairgen -d 01 -a "$(whoami)@$(hostname --fqdn) key" --key-type rsa:2048
    You may get a warning about ALWAYS_AUTHENTICATE, which means that your tpm doesn't support that feature, don't worry about it.
    Most tools will use all keys (or the first key) in the PKCS11 token, so you might as well just create one key and use it for everything (ie: both ssh and client certs)
   If you don't set an ID, ssh will claim "no keys".
  1. List the keys: pkcs11-tool --module=/usr/lib/opencryptoki/libopencryptoki.so.0 --list-objects --login

Setting up p11-kit

Freedesktop have a reasonably sensible api for registering pkcs11 modules called p11-kit. Create a file in /etc/pkcs11/modules/opencryptoki.module with the contents (if it doesn't already exist):

module: /usr/lib/opencryptoki/libopencryptoki.so.0 critical: no

There are other things you might want to specify in this file, see http://p11-glue.freedesktop.org/doc/p11-kit/pkcs11-conf.html. If you don't have root, you can instead use the filename ~/data/.pkcs11/modules/opencryptoki.module

By default, I believe gnutls will use pkcs11 modules that are registered with p11-kit. Setting up Gnome Keyring

From what I've seen Gnome Keyring doesn't yet (2013) support using an external pkcs11 implementation to seal it's key database. It will however export it's database via pkcs11 for other applications to use. Setting up SSH

By telling ssh-agent how to use the TPM, when you want to authenticate to other machines, ssh-agent will get the TPM to do the crypto operations on it's behalf. Thus the even the ssh-agent doesn't have direct access to the secret material of your private key.

Unfortunately the TPM is very slow, so doing this may add a second or two to your login process.

Optionally, get the public key as a ssh public key: ssh-keygen -D /usr/lib/opencryptoki/libopencryptoki.so.0 >~/.ssh/id_rsa.pub

Test this with: ssh -v -I/usr/lib/opencryptoki/libopencryptoki.so.0 $remotehost
    Can't find private key might mean you have two public keys and it's trying to use the wrong one.
    "no keys" might mean you don't have an identifier (-d) on your key.
    Be careful that you're not logging in with an existing ssh key.

Add the private key to your agent: ssh-add -s /usr/lib/opencryptoki/libopencryptoki.so.0

Alternatively, use p11-kit's proxy (which will use libopencryptoki since you added it previously): ssh-add -s /usr/lib/p11-kit-proxy.so

Verify it's there: ssh-add -l

Alternatively, instead of using ssh-agent, you can add: PKCS11Provider /usr/lib/opencryptoki/libopencryptoki.so.0 to ~/.ssh/config

If you have problems with gnome-keyring not supporting a feature (eg ssh certificates), you can use ssh-agent with p11-kit-proxy to get at keys in gnome-keyring (untested).

Setting up Chrome

Chrome doesn't have any UI that lets you configure PCKS11, but does support it. New versions of chrome may use p11-kit automatically (untested).

  1. Install nss-tools

  2. Add the TPM PKCS11 module to the chrome db (make sure you've quit chrome first) modutil -dbdir sql:$HOME/.pki/nssdb/ -add "TPM" -libfile /usr/lib/opencryptoki/libopencryptoki.so.0

  3. Alternatively, if you're using p11-kit, you can run the command: modutil --dbdir sql:$HOME/.pki/nssdb/ -add p11-kit -libfile /usr/lib/p11-kit-proxy.so -mechanisms RSA:DSA

  4. Verify with: modutil -dbdir sql:$HOME/.pki/nssdb/ -list

Firefox is similar, just substitue sql:$HOME/.pki/nssdb/ with ~/.mozilla/firefox/*.default/ Setting up dnssec-signzone

TODO: Try and figure out how on earth dnssec-signzone works. dnssec-signzone appears to take a -E argument that can probably deal with this. These notes are not yet complete.

5. Install bind9 (duh)

6. Generate a bind key from the key in the TPM. dnssec-keyfromlabel -l "$(whoami)@$(hostname --fqdn) key" -f KSK example.net

Setting up OpenVPN

TODO: OpenVPN appears to support PKCS11 so this should work fine, but I've not experimented yet. Cribbed from Open's PCKS#11 Token Config Docs

openvpn --show-pkcs11-ids /usr/lib/pkcs11/ should list key ids. Pick one with a

adding: pcks11-providers /usr/lib/pkcs11/ pkcs11-id 'aaaa/bbb/41545F5349474E415455524581D2A1A1B23C4AA4CB17FAF7A4600'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment