Integrity and TPM
What is TPM?
The Trusted Platfgorm Module (TMP) is hardware chip designed to enable computers to achieve greater levels of security. TPM stores cryptographic keys and other sensitive data in its internal, shielded memory, and provides ways to platform software to use those keys to achive security goals. To understand relations and how securly use TPM with Linux integrity a quick brief on TPM architecture is needed.
TPM must support a minimum set of algorithms and operations to meet its specifications.
Additional algorithms (DSA, elliptic curve) and protocols may be available.
TPM implements operations such as:
- asymmetric key generation (RSA)
- asymmetric enycryption/decryption (RSA)
- hashing (SHA-1)
- Random number generation (RNG)
The RSA asymmetric algorithm is used for digital signatures and for encryption. TPM use the RSA algorithm for signature operations where signed data is verified by entities other than the TPM performed the sign operation.
Symmetric encryption is used only for internal TPM use to encrypt authentication information, provide confidentiality in transport sessions, provide internal encryption of blobs stored off the TPM, and it's not expose to general users of TPM. The TPM is only a generator, storage device and protector of symmetric keys. Generation of the symmetric keys would use the TPM RNG.
Each TPM consits of a minimum 16, a 160-bit Platform Configuration Register (PCR) which are storage locations for integrity measurements. A large number of integrity metrics may be measured in a platform, and a particular integrity metric may change with time and a new value may need to be stored. The PCR is designed to hold an unlimited number of measurements in the register. It does this by using a cryptographic hash and hashing all updates to a PCR. The pseudo code for this is:
PCRi New = HASH ( PCRi Old value || value to add)
In a well configured machine, some of these registers are set to known values during the boot up process or at other times. For example, a PCR might contain the hash of a boot loader in memory before it is run.
Each TPM has a unique public/private key pair called the endorsement key (EK), set at manufacture time. EK is intended to be a long-term key and can be taken to be the identity of the TPM. In addition to EK, when ownership of the TPM is taken using the command takeownership, the TPM generates a public/private key pair called the storage root key (SRK) which is the root of the tree of storage keys.
Trusted and Encrypted Keys
Trusted and Encrypted Keys are two key types added to the existing kernel key ring service. Both of these new types are variable length symmetric keys, and in both cases all keys are created in the kernel, and user space sees, stores, and loads only encrypted blobs. Trusted Keys require the availability of a Trusted Platform Module (TPM) chip for greater security, while Encrypted Keys can be used on any system. All user level blobs, are displayed and loaded in hex ascii for convenience, and are integrity verified.
Trusted Keys use a TPM both to generate and to seal the keys. Keys are sealed under a 2048 bit RSA key in the TPM, and optionally sealed to specified PCR (integrity measurement) values, and only unsealed by the TPM, if PCRs and blob integrity verifications match. A loaded Trusted Key can be updated with new (future) PCR values, so keys are easily migrated to new pcr values, such as when the kernel and initramfs are updated. The same key can have many saved blobs under different PCR values, so multiple boots are easily supported.
By default, trusted keys are sealed under the SRK, which has the default authorization value (20 zeros). This can be set at takeownership time with the TPM takeownership operation.
IMA/EVM - using trusted/encrypted keys
IMA, or Integrity Measurement Architecture, is a Linux kernel integrity subsystem which aims to detect if files have been altered. It supports the collection of file integrity data (hashing), storage of the integrity values both locally (in extended attributes) and through TPM (Trusted Platform Module) protection. If a TPM is present, it can sign these integrity results so that interested parties can attest that the system has not been tampered with.
With EVM, the security sensitive extended attributes are verified against offline tampering. To accomplish this, EVM creates a cryptographic hash (actually an HMAC) or a signature of the extended attributes made with a key loaded at boot time. This hash/signature is validated every time the extended attributes of a resource are consulted and the action is only allowed if the hash or signature checks out. A malicious person will need access to this key in order to tamper with the extended attributes (and if IMA is enabled, to tamper with the files). Although the key needs to be loaded at boot time, a couple of mechanisms exist to seal it away:
- Use TPM to seal the key; this creates what is called a trusted key as it cannot be found (unencrypted) on the file system at any time
- Use encryption with offloaded passphrase protection for the keys, and ask for the passphrase early at boot time. With this we can use regular user keys (the terminology will be used later).
Setting up the keys (for cryptographic hashing)
We will now be creating the key for EVM. Since the key will be used often, it has to be a "fast" key to use. As such, we will use a standard user-encrypted key for this. To properly protect the key, a master key will be created first from which the EVM key can then be generated. The security of this master key is important, so if you have a TPM chip that you control, it is wise to use a trusted key for the master key. The EVM key remains a user key but is generated (and validated) by the master key.
We will store the blobs (binary dumps of the encrypted keys) in /etc/keys:
Use this if you have a TPM chip that you control:
root # keyctl add trusted kmk-trusted "new 32" @u root # keyctl pipe `keyctl search @u trusted kmk-trusted` > /etc/keys/kmk-trusted.blob root # keyctl add encrypted evm-key "new trusted:kmk-trusted 32" @u root # keyctl pipe `keyctl search @u encrypted evm-key` > /etc/keys/evm-trusted.blob
Use this if you do not have a TPM chip that you control:
root # keyctl add user kmk-user "`dd if=/dev/urandom bs=1 count=32 2>/dev/null`" @u root # keyctl pipe `keyctl search @u user kmk-user` > /etc/keys/kmk-user.blob root # keyctl add encrypted evm-key "new user:kmk-user 32" @u root # keyctl pipe `keyctl search @u encrypted evm-key` > /etc/keys/evm-user.blob
These four commands execute the following tasks:
- Create a master key named kmk-trusted or kmk-user. If we asked for a trusted key, then the key is generated by the TPM and sealed by the TPM (meaning it is encrypted by the TPM itself and can only be decrypted by the TPM). The key is made 256 bits long (32 bytes) and added to the user keyring (@u).
- Look for the key we generated in the first step, and output the key value into a file. The output is an encrypted value in case of a trusted key, or the key itself in case of the user key.
- Next, we generate a user key through the master key. In other words, the master key is used to encrypt (seal) the user key. The generated user key is called evm-key.
- Finally, we search for the key generated in the third step, and output the value into a file. The output is an encrypted value of the key (encrypted through the master key).
It is important that the key for EVM is called evm-key as this is the key searched for by the EVM subsystem on the root's keyring (i.e. the user keyring for the root Linux user).
Verifying IMA Measurements
The first element in the runtime measurement list is the boot_aggregate. The boot_aggregate is a SHA1 hash over tpm registers 0-7, assuming a TPM chip exists, and zeroes, if the TPM chip does not exist.
display the bios measurement list entries, used in calculating the boot aggregate
root # head /sys/kernel/security/tpm0/ascii_bios_measurements
Verifying IMA Measurements
Using the TPM's binary bios measurement list, re-calculate the boot aggregate.
root # /usr/local/bin/ima_boot_aggregate /sys/kernel/security/tpm0/binary_bios_measurements 000 f797cb88c4b07745a129f35ea01b47c6c309cda9 000 dca68da0707a9a52b24db82def84f26fa463b44d < snip > 005 6895eb784cdaf843eaad522e639f75d24d4c1ff5 PCR-00: 07274edf7147abda49200100fd668ce2c3a374d7 PCR-01: 48dff4fbf3a34d56a08dfc1504a3a9d707678ff7 PCR-02: 53de584dcef03f6a7dac1a240a835893896f218d PCR-03: 3a3f780f11a4b49969fcaa80cd6e3957c33b2275 PCR-04: acb44e9dd4594d3f121df2848f572e4d891f0574 PCR-05: df72e880e68a2b52e6b6738bb4244b932e0f1c76 PCR-06: 585e579e48997fee8efd20830c6a841eb353c628 PCR-07: 3a3f780f11a4b49969fcaa80cd6e3957c33b2275 boot_aggregate:b5a166c10d153b7cc3e5b4f1eab1f71672b7c524
and compare the value with the ascii_runtime_measurement list value.
root # cat /sys/kernel/security/ima/ascii_runtime_measurements | grep boot_aggregate 10 7971593a7ad22a7cce5b234e4bc5d71b04696af4 ima b5a166c10d153b7cc3e5b4f1eab1f71672b7c524 boot_aggregate
using the IMA binary measurement list, calculate the PCR aggregate value.
root # /usr/local/bin/ima_measure /sys/kernel/security/ima/binary_runtime_measurements --validate PCRAggr (re-calculated): B4 D1 93 D8 FB 31 B4 DD 36 5D DA AD C1 51 AC 84 FA 88 78 1B
and compare it against the PCR-10 value (Each new measurement added to list extends a PCR-10)
root # cat /sys/devices/pnp0/00:0a/pcrs | grep PCR-10 PCR-10: B4 D1 93 D8 FB 31 B4 DD 36 5D DA AD C1 51 AC 84 FA 88 78 1B
Attestation proves to third party that the IMA measurement list is valid, because it matches the hash in the IMA PCR, which is signed by the TPM.
Even evil software cannot remove its measurement from the list without invalidating the signature.