Recently Microsoft started mandating TPM2 as a hardware requirement for all platforms running recent versions of windows. This means that eventually all shipping systems (starting with laptops first) will have a TPM2 chip. The reason this impacts Linux is that TPM2 is radically different from its predecessor TPM1.2; so different, in fact, that none of the existing TPM1.2 software on Linux (trousers, the libtpm.so plug in for openssl, even my gnome keyring enhancements) will work with TPM2. The purpose of this blog is to explore the differences and how we can make ready for the transition.
What are the Main 1.2 vs 2.0 Differences?
The big one is termed Algorithm Agility. TPM1.2 had SHA1 and RSA2048 only. TPM2 is designed to have many possible algorithms, including support for elliptic curve and a host of government mandated (Russian and Chinese) crypto systems. There’s no requirement for any shipping TPM2 to support any particular algorithms, so you actually have to ask your TPM what it supports. The bedrock for TPM2 in the West seems to be RSA1024-2048, ECC and AES for crypto and SHA1 and SHA256 for hashes1.
What algorithm agility means is that you can no longer have root keys (EK and SRK see here for details) like TPM1.2 did, because a key requires a specific crypto algorithm. Instead TPM2 has primary “seeds” and a Key Derivation Function (KDF). The way this works is that a seed is simply a long string of random numbers, but it is used as input to the KDF along with the key parameters and the algorithm and out pops a real key based on the seed. The KDF is deterministic, so if you input the same algorithm and the same parameters you get the same key again. There are four primary seeds in the TPM2: Three permanent ones which only change when the TPM2 is cleared: endorsement (EPS), Platform (PPS) and Storage (SPS). There’s also a Null seed, which is used for ephemeral keys and changes every reboot. A key derived from the SPS can be regarded as the SRK and a key derived from the EPS can be regarded as the EK. Objects descending from these keys are called members of hierarchies2. One of the interesting aspects of the TPM is that the root of a hierarchy is a key not a seed (because you need to exchange secret information with the TPM), and that there can be multiple of these roots with different key algorithms and parameters.
Additionally, the mechanism for making use of keys has changed slightly. In TPM 1.2 to import a secret key you wrapped it asymmetrically to the SRK and then called LoadKeyByBlob to get a use handle. In TPM2 this is a two stage operation, firstly you import a wrapped (or otherwise protected) private key with TPM2_Import, but that returns a private key structure encrypted with the parent key’s internal symmetric key. This symmetrically encrypted key is then loaded (using TPM2_Load) to obtain a use handle whenever needed. The philosophical change is from online keys in TPM 1.2 (keys which were resident inside the TPM) to offline keys in TPM2 (keys which now can be loaded when needed). This philosophy has been reinforced by reducing the space available to keep keys loaded in TPM2 (see later).
Playing with TPM2
If you have a recent laptop, chances are you either have or can software upgrade to a TPM2. I have a dell XPS13 the skylake version which comes with a software upgradeable Nuvoton TPM. Dell kindly provides a 1.2->2 switching program here, which seems to work under Freedos (odin boot) so I have a physical TPM2 based system. For those of you who aren’t so lucky, you can still play along, but you need a TPM2 emulator. The best one is here; simply download and untar it then type make in the src directory and run it as ./tpm_server. It listens on two TCP ports, 2321 and 2322, for TPM commands so there’s no need to install it anywhere, it can be run directly from the source directory.
After that, you need the interface software called tss2. The source is here, but Fedora 25 and recent Ubuntu already package it. I’ve also built openSUSE packages here. The configuration of tss2 is controlled by environment variables. The most important one is TPM_INTERFACE_TYPE which tells it how to connect to the TPM2. If you’re using a simulator, you set this to “socsim” and if you have a real TPM2 device you set it to “dev”. One final thing about direct device connection: in tss2 there’s no daemon like trousers had to broker the connection, all your users connect directly to the TPM2 device /dev/tpm0. To do this, the device has to support read and write by arbitrary users, so its permissions need to be 0666. I’ve got a udev script to achieve this
# tpm 2 devices need to be world readable SUBSYSTEM=="tpm", ACTION=="add", MODE="0666"
Which goes in /etc/udev/rules.d/80-tpm-2.rules on openSUSE. The next thing you need to do, if you’re running the simulator, is power it on and start it up (for a real device, this is done by the bios):
The simulator will now create a NVChip file wherever you started it to store NV ram based objects, which it will read on next start up. The first thing you need to do is create an SRK and store it in NV memory. Microsoft uses the well known key handle 81000001 for this, so we’ll do the same. The reason for doing this is that a real TPM takes ages to run the KDF for RSA keys because it has to look for prime numbers:
jejb@jarvis:~> TPM_INTERFACE_TYPE=socsim time tsscreateprimary -hi o -st -rsa Handle 80000000 0.03 user 0.00 system 0:00.06 elapsed jejb@jarvis:~> TPM_INTERFACE_TYPE=dev time tsscreateprimary -hi o -st -rsa Handle 80000000 0.04 user 0.00 system 0:20.51 elapsed
As you can see: the simulator created a primary storage key (the SRK) in a few milliseconds, but it took my real TPM2 20 seconds to do it3 … not something you want to wait for, hence the need to store this permanently under a well known key handle and get rid of the temporary copy
tssevictcontrol -hi o -ho 80000000 -hp 81000001 tssflushcontext -ha 80000000
tssevictcontrol tells the TPM to copy the key at transient handle 800000004 to permanent NV handle 81000001 and tssflushcontext erases the transient key. Flushing transient objects is very important, because TPM2 has a lot less transient storage space than TPM1.2 did; usually only about three handles worth. You can tell how much you have by doing
tssgetcapability -cap 6|grep -i transient TPM_PT 0000010e value 00000003 TPM_PT_HR_TRANSIENT_MIN - the minimum number of transient objects that can be held in TPM RAM
Where the value (00000003) tells me that the TPM can store at least 3 transient objects. After that you’ll start getting out of space errors from it.
The final step in taking ownership of a TPM2 is to set the authorization passwords. Each of the four hierarchies (Null, Owner, Endorsement, Platform) and the Lockout has a possible authority password. The Platform authority is cleared on startup, so there’s not much point setting it (it’s used by the BIOS or Firmware to perform TPM functions). Of the other four, you really only need to set Owner, Endorsement and Lockout (I use the same password for all of them).
tsshierarchychangeauth -hi l -pwdn <your password> tsshierarchychangeauth -hi e -pwdn <your password> tsshierarchychangeauth -hi o -pwdn <your password>
After this is done, you’re all set. Note that as well as these authorizations, each object can have its own authorization (or even policy), so the SRK you created earlier still has no password, allowing it to be used by anyone. Note also that the owner authorization controls access to the NV memory, so you’ll need to supply it now to make other objects persistent.
An Aside about Real TPM2 devices and the Resource Manager
Although I’m using the code below to store my keys in the TPM2, there’s a couple of practical limitations which means it won’t work for you if you have multiple TPM2 using applications without a kernel update. The two problems are
- The Linux Kernel TPM2 device /dev/tpm0 only allows one user at once. If a second application tries to open the device it will get an EBUSY which causes TSS_Create() to fail.
- Because most applications make use of transient key slots and most TPM2s have only a couple of these, simultaneous users can end up running out of these and getting unexpected out of space errors.
The solution to both of these is something called a Resource Manager (RM). What the RM does is effectively swap transient objects in and out of the TPM as needed to prevent it from running out of space. Linux has an issue in that both the kernel and userspace are potential users of TPM keys so the resource manager has to live inside the kernel. Jarkko Sakkinen has preliminary resource manager patches here, and they will likely make it into kernel 4.11 or 4.12. I’m currently running my laptop with the RM patches applied, so multiple applications work for me, but since these are preliminary patches, I wouldn’t currently advise others to do this. The way these patches work is that once you declare to the kernel via an ioctl that you want to use the RM, every time you send a command to the TPM, your context gets swapped in, the command is executed, the context is swapped out and the response sent meaning that no other user of the TPM sees your transient objects. The moment you send the ioctl, the TPM device allows another user to open it as well.
Using TPM2 as a keystore
Once the implementation is sorted out, openssl and gnome-keyring patches can be produced for TPM2. The only slight wrinkle is that for create_tpm2_key you require a parent key to exist in the NV storage (at the 81000001 handle we talked about previously). So to convert from a password protected openssh RSA key to a TPM2 based one, you do
create_tpm2_key -a -p 81000001 -w id_rsa id_rsa.tpm mv id_rsa.tpm id_rsa
And then gnome keyring manager will work nicely (make sure you keep a copy of your original private key in case you want to move to a new laptop or reseed the TPM2). If you use the same TPM2 password as your original key password, you won’t even need to update the gnome loginkeyring for the new password.
Because of the lack of an in-kernel Resource Manager, TPM2 is ready for experimentation in Linux but definitely not ready for prime time yet (unless you’re willing to patch your kernel). Hopefully this will change in the 4.11 or 4.12 kernel when the Resource Manager finally goes upstream5.
Looking forwards to the new stack, the lack of a central daemon is really a nice feature: tcsd crashing used to kill all of my TPM key based applications, but with tss2 having no central daemon, everything has just worked(tm) so far. A kernel based RM also means that the kernel can happily use the TPM (for its trusted keys and disk encryption) without interfering with whatever userspace is doing.