+++ date = "2021-06-09" draft = false path = "/blog/tpm-ssh" tags = ["tpm", "linux"] title = "Using a TPM 2.0 to secure ssh keys" +++ A while ago I [read a tweet][bullying tweet] that reminded me I felt guilty about the state of my ssh key security and wanted to do something about it, eventually. Well, my watch reads "eventually", so let's do it. My workstation is a modern AMD system, which has a firmware based TPM 2.0 implementation available "for free", which sounded pretty nice, so let's use it. This guide is partially [sourced from this docs page][ssh.md]. Required packages (Arch Linux names): * `tpm2-tools` * `tpm2-tss` * `tpm2-pkcs11` * `tpm2-abrmd` --- Before doing anything with this, reboot into BIOS and enable (if needed) and clear the TPM. Mine at least had decided that someone was dictionary attacking it. Not sure how it got that idea, but clearing it reset that flag. Boot back into your system and enable and start `tpm2-abrmd.service`. This provides a D-Bus interface that applications can talk to for access to the tpm. You also need to be in the `tss` group for the tpm stuff to initialize. --- Next, provision tss2/fapi (no I don't know what this is either. it complains on every usage that fapi is uninitialized if you don't, even though it is unused per the docs): Try doing `tss2_provision`. This might fail with something to do with key size. If that happens, you'll have to set `"profile_name": "P_RSA2048SHA256",` in `/etc/tpm2-tss/fapi-config.json` from its default of some ECC. There may also be complaints about EK certificates being unknown or similar, which I have failed to figure out how to deal with properly, but you can at least suppress the error by setting `"ek_cert_less": "yes"` in the same file. --- Once you have the fapi set up, you can follow the [ssh configuration guide][ssh.md], which I will summarize with real invocations. ``` # initialize pkcs11 store in ~/.tpm2_pkcs11 tpm2_ptool init # NOTE: the following two commands have secrets in them. consider prefixing # them with a space in order to avoid them getting into a history file # add a token. the `userpin` here is the one you type in to log into stuff # the sopin is the supervisor pin, which is a backup pin. you can stuff that # into a password manager or write it down or something. tpm2_ptool addtoken --pid 1 --label sshtok --sopin [SUPERVISOR PIN] \ --userpin [USER PIN] # add a key on that token. the key label will show up next to the key when you # pull it out using ssh-keygen. see notes below for why it's rsa2048/ecc256 # suggested despite others being supported. tpm2_ptool addkey --algorithm [rsa2048 or ecc256] --label sshtok \ --key-label [KEY LABEL] --userpin [USER PIN] # pull out the public keys to stdout. idk put them somewhere i guess. you can # do this again later, it will give you the same output ssh-keygen -D /usr/lib/pkcs11/libtpm2_pkcs11.so # if you want, you can use ssh-agent to remember your PIN for this session pgrep -u $UID ssh-agent || eval `ssh-agent` ssh-add -s /usr/lib/pkcs11/libtpm2_pkcs11.so # add your ssh key to some remote hosts' authorized_keys # add the pkcs11 module to ssh_config on your client cat <(echo 'PKCS11Provider /usr/lib/pkcs11/libtpm2_pkcs11.so') .ssh/config \ | tee .ssh/config # try it!!! ssh yourhost ``` Some notes: On my system, `rsa2048` and `ecc256` seem to work as algorithms. Notably, `ecc384` does not work when you actually try to log into a computer with it: ``` WARNING:esys:src/tss2-esys/api/Esys_Sign.c:311:Esys_Sign_Finish() Received TPM Error ERROR:esys:src/tss2-esys/api/Esys_Sign.c:105:Esys_Sign() Esys Finish ErrorCode (0x000001d5) ERROR: Esys_Sign: tpm:parameter(1):structure is the wrong size ``` --- If you want to grab all the repos, here's the invocation I used to clone all of them for `rg`'ing: ``` gh repo list --json nameWithOwner \ --template '{{range .}}{{.nameWithOwner}}{{"\n"}}{{end}}' tpm2-software \ | xargs -i -- git clone 'https://github.com/{}' ``` If you're having an unfortunate day and are running into a suspected bug, there are `-git` versions of all of these on the AUR, which you can build with symbols. --- Error messages with the TPM stuff are not extremely googleable. If you want help, check out the [gitter for the tpm2-software tools][gitter], and perhaps the source code. [ssh.md]: https://github.com/tpm2-software/tpm2-pkcs11/blob/master/docs/SSH.md [bullying tweet]: https://twitter.com/a_hoverbear/status/1394475693413568514 [gitter]: https://gitter.im/tpm2-software/community