LWN.net Logo

Trusted and encrypted keys

By Jake Edge
October 6, 2010

The Trusted Platform Module (TPM) present on many of today's systems can be used in various ways, from making completely locked-down systems that cannot be changed by users to protecting sensitive systems from various kinds of attacks. While the TPM-using integrity measurement architecture (IMA), which can measure and attest to the integrity of a running Linux system, has been part of the kernel for some time now, the related extended verification module (EVM) has not made it into the mainline. One of the concerns raised about EVM was that it obtained a cryptographic key from user space that is then used as a key for integrity verification—largely nullifying the integrity guarantees that EVM is supposed to provide. A set of patches that were recently posted for comments to the linux-security-module mailing list would add two new key types to the kernel that would allow user space to provide the key without being able to see the actual key data.

We last looked in on EVM back in June when it seemed like it might make it into 2.6.36. That didn't happen, nor has EVM been incorporated into linux-next, so its path into the mainline is a bit unclear at this point. EVM calculates HMAC (hash-based message authentication code) values for on-disk files, uses the EVM key and TPM to sign the values, and stores them in extended attributes (xattrs) in the security namespace. If the EVM key is subverted, all bets are off in terms of the integrity of the system. While they are targeted for use by EVM, Mimi Zohar's patches to add trusted and encrypted key types could also be used for other purposes such as handling the keys for filesystem encryption.

The basic idea is that these keys would be generated by the kernel, and would never be touched by user space in an unencrypted form. Encrypted "blobs" would be provided to user space by the kernel and would contain the key material. User space could store the keys, for example, but the blobs would be completely opaque to anything outside of the kernel. The patches come with two new flavors of these in-kernel keys: trusted and encrypted.

Trusted keys are generated by the TPM and then encrypted using the TPM's storage root key (SRK), which is a 2048-bit RSA key (this is known as "sealing" the key in TPM terminology). Furthermore, trusted keys can also be sealed to a particular set of TPM platform configuration register (PCR) values so that the keys cannot be unsealed unless the PCR values match. The PCR contains an integrity measurement of the system BIOS, bootloader, and operating system, so tying keys to PCR values means that the trusted keys cannot be accessed except from those systems for which it was specifically authorized. Any change to the underlying code will result in undecryptable keys.

Since the PCR values change based on the kernel and initramfs used, trusted keys can be updated to use different PCRs, once they have been added to a keyring (so that the existing PCR values have been verified). There can also be multiple versions of a single trusted key, each of which is sealed to different PCR values. This can be used to support booting multiple kernels that use the same key. While the underlying, unencrypted key data will not need to change for different kernels, the user-space blob will change because of the different PCR values, which will require some kind of key management in user space.

Encrypted keys, on the other hand, do not rely on the TPM, and use the kernel's AES encryption instead which is faster than the TPM's public key encryption. Keys are generated as random numbers of the requested length from the kernel's random pool and, when they are exported as user-space blobs, they are encrypted using a master key. That master key can either be the new trusted key type or the user key type that already exists in the kernel. Obviously, if the master key is not a trusted key, it needs to be handled securely, as it provides security for any other encrypted keys.

The user-space blobs contain an HMAC that the kernel can use to verify the integrity of a key. The keyctl utility (or keyctl() system call) can be used to generate keys, add them to a kernel keyring, as well as to extract a key blob from the kernel. The patch set introduction gives some examples of using keyctl to manipulate both trusted and encrypted keys.

A recent proposal for a kernel crypto API was not particularly well-received, in part because it was not integrated with the existing kernel keyring API, but Zohar's proposal doesn't suffer from that problem. Both have the idea of wrapping keys into opaque blobs before handing them off to user space, but the crypto API went much further, adding lots of ways to actually use the keys from user space for encryption and decryption.

While the trusted and encrypted key types would be useful to kernel services (like EVM or filesystem encryption), they aren't very useful to applications that want to do cryptography without exposing key data to user space. The keys could potentially be used by hardware cryptographic accelerators, or possibly be wired into the existing kernel crypto services, but they won't provide all of the different algorithms envisioned by the kernel crypto API.

The existing IMA code only solves part of the integrity problem, leaving the detection of offline attacks against disk files (e.g. by mounting the disk under another OS) to EVM. If EVM is to eventually be added to the kernel to complete the integrity verification puzzle, then trusted keys or something similar will be needed. So far, the patches have attracted few comments or complaints, but they were posted to various Linux security mailing lists, and have not yet run the linux-kernel gauntlet.


(Log in to post comments)

Copyright © 2010, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds