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)