If you're curious on how to use the TPM (Trusted Platform Module) on your computer or have an interest in IoT and are looking to incorporate a TPM module in your Thing, then hopefully I can shed some light on how to use it from an application perspective.
There are quite a few good articles out there to explain what a TPM is and how it's used but I'll just give a short background here and how we can use it to secure files on our device by building a primitive Bitlocker clone using the CLI in Linux. The concepts applies to other OS' as well but the tooling was much simpler to demonstrate in Linux with only a few simple commands.
By the end of this you should be able to understand:
- What a TPM is and how to use it
- How encrypt and decrypt data using asymmetric keys with GPG
- How to Seal/Wrap and Unseal/Unwrap data
- How to lock down our data to a particular device and how losing the generated keyblob from the TPM won't jeopardize our data
The TLDR on a TPM
The TPM is an actual co-processor living on the motherboard of your device. It can be on a desktop or laptop computer, it can be a chip on an IoT Thing. It's an implementation of a Hardware Security Module.
In the diagram we can see that the TPM sits on a different bus than the CPU. All its internal data is encrypted and the important thing is that the TPM can take measurements against the system it's installed on such as the BIOS, MBR, platform manufacturer and so on which are stored on the PCR (Platform Configuration Registers). This is important because the TPM can store and encrypt data based on these measurements. What does that mean?
It means if you take the TPM chip out and placed it in another motherboard -- it won't work.
It also means that if you take the output generated by this TPM chip and that output was generated against specific measurements then that output can never be decrypted on another TPM unless it was somehow identical to your current device -- I'll demo this in a minute. This should never be the case even if it's the same model of laptop because the manufacturer would have put in different serial numbers and you would all have different configurations etc.
Boot loaders such as Trusted Grub can take advantage of the TPM to enable trusted boot. That's a bit out of the scope of this article but here's a nice link that explains the difference between secure boot and trusted boot with the TPM.
Asymmetric Cryptography - The Public Key and Private Key
A quick review on asymmetric cryptography.
- The public key and private key are mathematically linked.
- When encrypting data, we use the public key and some algorithm to generate an encrypted piece of data.
- To decrypt it, we use the private key.
This is also true of the other way around as well though using it the other way around is digital signing. Because someone can decrypt your data encrypted with the private key, it proves that you own that private key.
I like to think of the public key as a lock. You can give that out and lock any number of things and only you hold the master key to go and unlock all the things.
Enabling the TPM
The first thing we need to do is check and enable our TPM chip. They usually ship "unowned" and disabled.
Getting into the BIOS is device specific but on laptops it's usually the F12 key or the DEL button. My Sony Pro Duo has a special "assist" button that does that.
Now this might take a couple of restarts. What I found was that my TPM was already enabled but it wasn't cleared. We can programmatically clear it or use the CLI but for both my devices I had to clear it in the BIOS.
After ticking a button in the security tab and clearing the TPM, the TPM will switch to the
Re-enter the BIOS again and
enable the TPM. You do not need to check the clear checkbox if it exists.
Now boot into the OS and we're ready for the next step.
Install TPM Tools
On Ubuntu 16.04, you can install the below packages based on your TPM version. Your BIOS/Spec sheet should indicate which version.
For TPM 1.2:
sudo apt-get install tpm-tools (TPM 1.2)
For TPM 2.0:
sudo apt-get install tpm2-tools (TPM 2.0)
What's the difference between 2.0 and 1.2?
I link you to this article here from Dell. Basically it supports more algorithms and a Hierarchy. By Hierarchy I mean like a grouping to manage the various different keys. For TPM 1.2, which is on a lot of devices, one "owner" manages the TPM.
Take Ownership of the TPM
After clearing the TPM we need to take ownership of it.
It will prompt you to enter the Owner password. This is a new password which will restrict TPM usage to the owner. Then confirm the password once again.
It will then prompt you to enter the SRK (Storage Root Key) Password. This is the password we'll be using the most to call TPM operations.
Every time you take ownership of a TPM, a new password is generated which grants access to the SRK. The SRK contains a public key and a private key. The private key is stored encrypted on the TPM memory and nobody has access to read it including you.
Remember, if this chip is taken out of the motherboard or another SRK is used, it won't be able to decrypt the data -- which is a good thing! By having the private key in the TPM, we can never accidentally lose it or expose it.
Taking ownership usually takes a few seconds after entering the passwords. No output should be given if it's successful. If there's a problem, it'll tell you.
Primitive Bitlocker Example
So now that we're armed to the teeth with basic TPM and cryptography, how can we use it?
One thing we can do is use a set of commands to simulate a very primitive version of Bitlocker. Bitlocker is a Windows application that encrypts your hard drive for that extra sauce of security. One of the things that had always worried me is losing my laptop when attending events, meetups or just going to a client's site where many other contractors are bustling about. I don't really care about losing the hardware but I don't want any private or client data to be exposed.
Anyway, what we're gonna do is encrypt a sample file using a public key. Store the private key in the TPM and then throw away the private key! Though that's just to get my point across in the article. I'd back that private key up somewhere else (not on the same machine) on an encrypted file store or service just in case the machine ever died. That way I can recover the data. Probably worth mentioning now that if your TPM or Device dies and you rely on the TPM to retrieve data, you will have lost that data forever.
Then I'll demonstrate on how to retrieve the private key from the TPM to decrypt our data and how this won't work across two different TPMs.
Generate GPG Keys
So going back to asymmetric cryptography, we're going to use GPG commands for examples on how to encrypt and decrypt files using public key and private key pairs. But wait, you ask, why use another set of keys when we can just use the TPM? Well the TPM is very slow for cryptographic functions so we only encrypt (also called sealing) the private key of another key pair. This is also because the TPM will never give out its own private key otherwise you would just be able to read it all in memory. By wrapping and unwrapping keys, we only take the performance hit once before we use it.
Since the general purpose CPU is much faster, we can pair it with the public key to encrypt all the things. Call the TPM once to unwrap our private key and use the CPU with the private key to decrypt all the things.
First let's create our keys:
It will prompt you for some information, ask you to wiggle your mouse and type in some keys on the keyboard to generate a little bit of entropy/randomness when generating your key. Then it'll output your key ID.
The keys themselves are stored in GPG's database locally. We can get a list of public keys stored locally by running:
tony@tony-xps:~/Documents/tpm$ gpg --list-keys /home/tony/.gnupg/pubring.gpg ----------------------------- pub 2048R/1E2214B6 2017-01-03 uid Tony Truong (For TPM Demo) <email@example.com> sub 2048R/09B8CDF9 2017-01-03
My Key ID is
1E2214B6. If I ever wanted to upload this to the public gpg keyservers, I could tell a friend to go download my public key by referencing this ID. But we're not doing that today. Everything is local.
Let's export the private key:
gpg --export-secret-keys -a 1E2214B6 > privateKey.asc
And also the public key:
gpg --armor --export firstname.lastname@example.org > publicKey.asc
--armor command makes the key ASCII and readable instead of binary.
Encrypt/Decrypt Data with GPG
Remember, the keys are still stored locally, we're not doing anything with those files yet. Let's create a file to encrypt:
echo 'Hello World!' > file.txt
Now to encrypt it we do:
gpg --encrypt --recipient 'email@example.com` file.txt
--recipient command tells me to use the public key for
firstname.lastname@example.org. This generates the encrypted file
To view the contents on STDOUT we just simply run:
gpg --decrypt file.txt.gpg
gpg: encrypted with 2048-bit RSA key, ID 09B8CDF9, created 2017-01-03 "Tony Truong (For TPM Demo) <email@example.com>" Hello World!
Delete The Local Keys
Let's delete the local keys from gpg. First we need to delete the private key before the public one otherwise it'll complain.
gpg --delete-secret-keys 'firstname.lastname@example.org'
gpg --delete-keys 'email@example.com'
To prove that the keys aren't there anymore we can run these commands:
tony@tony-xps:~/Documents/tpm$ gpg --list-keys gpg: checking the trustdb gpg: no ultimately trusted keys found tony@tony-xps:~/Documents/tpm$ gpg --list-secret-keys tony@tony-xps:~/Documents/tpm$
And now we can't decrypt that file anymore either:
tony@tony-xps:~/Documents/tpm$ gpg --decrypt file.txt.gpg gpg: encrypted with RSA key, ID 09B8CDF9 gpg: decryption failed: secret key not available
Wrapping/Sealing keys With The TPM
When we seal the private key generated from the steps above, we combine it with the PCR. If you recall the PCR stores measurements specific to this device. In my case I have 2 devices. The commands above ran on a Dell XPS 9550. I'm going to encrypt this privateKey.asc with PCR's 0 and 7 though much more can be used.
Some examples of what PCR numbers and what they represent:
PCR 0 is the BIOS PCR 7 is platform manufacturer measurements PCR 4 is MBR ...
The output of sealing the private key will be a TPM keyblob. This is your encrypted private key.
tony@tony-xps:~/Documents/tpm$ tpm_sealdata --infile privateKey.asc --outfile keyblob --pcr 0 --pcr 7
This takes a few seconds to complete. The TPM is not very fast as previously mentioned. So we use it on a small dataset.
Now you could throw away the private key...though you should back it up fo' reals.
Unsealing the Private Key
Now on the same machine let's retrieve the private key using the TPM:
tony@tony-xps:~/Documents/tpm$ tpm_unsealdata --infile keyblob --outfile unsealedPrivateKey.key
Now is it the same as the old private key? We still have the private key...yeah I didn't delete it.
Let's do a hash to see if they're the same:
tony@tony-xps:~/Documents/tpm$ sha256sum privateKey.asc 785b6e72062aaea82f20b1e14f27df0dd5734c4c1f5bb1a83f6d69a8e69446a6 privateKey.asc tony@tony-xps:~/Documents/tpm$ sha256sum unsealedPrivateKey.key 785b6e72062aaea82f20b1e14f27df0dd5734c4c1f5bb1a83f6d69a8e69446a6 unsealedPrivateKey.key
Looks good, but will it blend?
tony@tony-xps:~/Documents/tpm$ gpg --import unsealedPrivateKey.key gpg: key 1E2214B6: secret key imported gpg: key 1E2214B6: public key "Tony Truong (For TPM Demo) <firstname.lastname@example.org>" imported gpg: Total number processed: 1 gpg: imported: 1 (RSA: 1) gpg: secret keys read: 1 gpg: secret keys imported: 1
Ooh looking good! Let's see if we can decrypt our file now:
tony@tony-xps:~/Documents/tpm$ gpg --decrypt file.txt.gpg gpg: encrypted with 2048-bit RSA key, ID 09B8CDF9, created 2017-01-03 "Tony Truong (For TPM Demo) <email@example.com>" Hello World!
Trying to Unseal Keyblob On Another Machine
So on an old Sony Pro Duo which also has a TPM chip, I pwned it and then copied the encrypted file, the keyblob and the public key over from the XPS:
tony@sony-ubuntu:~/tpm$ ls file.txt.gpg keyblob publicKey.asc
Let's see if we can unseal the data using another TPM. I happened to pwn it with the same owner password and same SRK password.
tony@sony-ubuntu:~/tpm$ tpm_unsealdata --infile keyblob --outfile unsealedKey.key Enter SRK password: Unable to write output file
Hmm looks like we can't get to the contents of that file unless the person actually has physical access to my device and the password that goes with it and hasn't changed any settings in the BIOS to boot their own malware.
I'm not too concerned either if I lost my encrypted file and keyblob. But given enough encrypted data, the attacker can derive the private key eventually because the asymmetric keys are mathematically linked. So I should still change the keys used to decrypt / encrypt my files and change the SRK.
I hope that gives you a better understanding of the TPM at an application level.
If you read all the way down here, thank you so much and please send corrections in an email and praises publicly in the comments below!