Last year, during an uptick in media attention for Trusted Platform Module (TPM) security triggered by a blog post from the Dolos Group describing a sniffing attack on Windows Bitlocker relying on a TPM, a customer asked us to investigate their TPM-based Full Disk Encryption (FDE) set up in light of this type of attack. The related research and commentary that followed, like the Dolos Group post, seems to have focused on TPMs as used by Windows Bitlocker , , , . As such, we thought it would be interesting to elaborate on this scenario as applied to other TPM use-cases.
TPM Sniffing Attacks Against Non-Bitlocker Targets
10 June 2022 |
Jos Wetzels - Principal Security Consultant
A Trusted Platform Module (TPM) typically refers to a dedicated secure cryptoprocessor conforming to the ISO/IEC 11889 standard by the Trusted Computing Group (TCG). TPMs can be used for various purposes, ranging from platform integrity and FDE support to storage of key material and credentials (such as for SSH authentication). TPMs can be used in various platforms ranging from servers and laptops to cloud-connected IoT devices.
Two main versions of the standard exist, TPM 1.2 and TPM 2.0, with the latter not being backward compatible with the former. TPMs can be implemented in a variety of manners (with dTPMs and fTPMs being the most common):
- Discrete TPMs (dTPM): which come in the form of a dedicated, tamper-resistant chip.
- Integrated TPMs: which are implemented as a hardware subsystem within a different chip.
- Firmware TPMs (fTPMs): which are firmware-based and typically run in a CPU's Trusted Execution Environment (TEE).
- Hypervisor TPMs (vTPMs): which are segmented away from a virtual machine by running on top of a hypervisor.
- Software TPMs: which are purely software-based and the least secure implementation.
For platform integrity, TPMs provide mechanisms to support measured boot. Starting from a Core Root of Trust for Measurement (CRTM) (e.g., boot ROM of some SoC), hashes are calculated of various platform components (e.g., BIOS/UEFI, bootloader, embedded controller firmware, etc.) and stored in Platform Configuration Register (PCR) slots. This information can be incorporated into the secure boot process (possibly as part of FDE) to ensure these various components have not been tampered with.
TPMs also provide mechanisms to support encryption solutions to provide confidentiality and integrity authentication guarantees. These mechanisms include key generation, the ability to encrypt key material with a TPM-specific key, and tamper-resistant features to make the TPM function as a secure storage for secrets. Using a TPM-protected key by itself is typically referred to as binding while adding measured boot PCR values into the cryptographic mix is typically referred to as sealing.
In encryption scenarios, TPMs can typically be configured in one of several modes:
- TPM only: here, the TPM automatically supplies the key to the encryption solution upon request (e.g., on boot).
- TPM + PIN: here, the TPM needs a system-supplied secret (typically a PIN entered by the user) before it will unseal the key.
- TPM + PIN + MFA: here, an additional factor, such as a USB key with a secret or TOTP, is required.
In the case of FDE, additional secrets have to be provided pre-boot. Tamper-resistant features on the TPM (ought to) prevent brute-forcing of PINs, extracting private keys, and glitching to bypass these features.
While there have been invasive probing, various side-channel, interposer, and design and implementation attacks on TPMs in the past, we will only focus on sniffing attacks against dTPMs in FDE support scenarios in this post since these types of attacks are inherent to the design of dTPMs.
Since dTPMs are dedicated chips separate from the main CPU and other controllers on a device, they need some way to communicate with them. The standard specifies the LPC, I2C, and SPI busses for this purpose, and the dTPM will have to be put on a bus together with any device that might need to talk to it (depending on whether there are single- or multi-master roles).
To put it in a somewhat simplified fashion, during encryption setup, the CPU takes ownership of the TPM, configures it, and sends a key to the TPM for binding or sealing. The TPM encrypts this key using authentication data, its own secret key, and optional PCR measurements and sends the encrypted key blob back. This blob is then stored somewhere (typically as part of an encrypted volume header). During decryption, the CPU sends the encrypted key blob to the TPM, and authentication data and optional measurements are obtained by the TPM and used together with its secret key to decrypt the blob. The plaintext key is sent back to the CPU for usage.
Hence, at some point during the decryption process, the plaintext key can be sent over the bus to the CPU in plaintext by design. While the TPM 2.0 standard allows for so-called 'parameter encryption', this feature is rarely implemented by encryption solutions and, as pointed out by Trammell Hudson, comes with the chicken-and-egg problem of trust establishment without the ability to store secrets on the main CPU.
Our threat model operated under the assumption of an attacker with physical access for a limited time to a device using a dTPM-supported FDE solution. This assumed provisioning/commissioning had been done, and the data in question was encrypted. While a whole host of others threats fall under this scope, we specifically focussed on sniffing the TPM bus since PCR measurements are irrelevant to this scenario.
During our investigation, we compared Windows 10 Bitlocker with TPM against several Linux-based FDE implementations, being: systemd-cryptsetup, clevis, luks-tpm2, safeboot, and coreboot. The TPM in question was an Infineon OPTIGA SLB 9670 TPM 2.0 module with an SPI interface (though obviously, this scenario works against I2C and LPC, as has been shown before).
As we can see, parameter encryption simply isn't used in practice, and except for safeboot none of the solutions enforce PIN/MFA by default. While we didn't look at pureboot, U-Boot, tboot, and TrustedGRUB2 in detail, we suspect similar findings apply there.
To aid others in assessing and demonstrating the feasibility of TPM sniffing attacks against Linux-based FDE implementations, I developed two Saleae Logic 2 plugins, as shown below. They are available on Github.
All solutions we investigated are based on the Linux Unified Key Setup (LUKS). LUKS2 volumes have a header with a keyslot area holding different keyslots for different passwords or key files that can be used to decrypt the volume. These keyslot entries specify key derivation information such as priority, key derivation function, parameters, salt, and encryption algorithm. An encrypted master key (MK), stored in anti-forensics (AF) stripes, is then decrypted using the derived key.
To use LUKS together with a TPM, most solutions (system-cryptsetup, safeboot, luks_tpm2) make use of tpm2-tools, a sort of BusyBox-like toolkit for interacting with the Trusted Computing Group's (TCG) TPM2 Software Stack (TSS).
In systemd-cryptsetup, a TPM token is enrolled and linked to a LUKS2 keyslot. With a `cryptsetup luksDump /dev/sda1 --debug-json` command, we can see the token holds a base64 encoded tpm2-blob entry which is sent to the TPM for unsealing. The unsealing traffic is pretty easy to spot on an SPI bus and consists of a TPM_READ operation on TPM_DATA_FIFO_0 (d40024) with a data structure consisting of a DWORD with value 00000022 followed by a WORD-sized length field (typically value 0020) and the subsequent 256-bit key.
My Saleae Logic plugin formats the key for LUKS keyfile output:
Mounting a volume can be done with `cryptsetup open ./sda1-luks myvolumename --key-slot 1 --key-file ./mykey --keyfile-size 44`.
While luks-tpm2 works a little differently, it can store keys in a sealed on-disk file or TPM NVRAM and has passphrase support for unsealing. Its unsealing operation looks the same over the SPI bus, and the plugin works here too. Safeboot seems the most robust out of the investigated solutions, forcing users to use PIN by default, and works a little differently under the hood, but the tpm2-tools plugin works for this one too.
Clevis is a pluggable automated decryption framework with a number of 'pins' (not to be confused with a PIN), where each pin implements crypto support using a different backend. For encryption, Clevis takes some data and a JSON configuration to produce a JSON Web Encryption (JWE) object holding data encrypted using a JSON Web KEY (JWK) and some metadata. On decryption, Clevis obtains the key from the JWK and metadata and decrypts the ciphertext from the JWE.
The Clevis tpm2 'pin' generates a JWK, creates an object in the TPM with the JWK as secret data, and binds or seals it to the TPM. The resulting JWE (associated with a LUKS2 key slot) holds both the public and sealed sensitive portions of the created object as well as unsealing-related metadata. On decryption, the tpm2 'pin' takes the JWE, loads it into the TPM, unseals the JWK, and decrypts the ciphertext in the JWE.
As a result of this approach, the TPM SPI traffic looks a little different. What we're looking for is a TPM_READ operation on TPM_DATA_FIFO_0 (d40024) with a data structure consisting of a DWORD with value 00000072, followed by a variable WORD-sized length field, followed by a bunch of JSON data.
My Saleae Logic plugin validates the JSON and extracts the key and relevant metadata:
IoT and TPMs
IoT devices often fall under the typical 'physical access by an adversary' threat model, especially for those devices deployed in public locations or where the user is a potential adversary. Various related use-cases require some sort of trusted security subsystem functionality such as device authentication, identification, secure maintenance, remote attestation, and protection of data-at-rest and in transit.
As illustrated below, the Azure approach for Windows 10 IoT Core is pretty typical for this use case. Here a Shared Access Key (SAK) is established between the IoT device and cloud during the provisioning process by supplying the cloud with the public parts of the TPM's Endorsement Key (EK) and Storage Root Key (SRK). The SAK is imprinted in the TPM on the device end, while on the cloud end, the physical device is associated with a device ID in the cloud device hub. Next, a Shared Access Signature (SAS) token is generated, specifying a request for access associated with certain policies. This token is signed by the TPM using an HMAC keyed with the SAK.
The Windows 10 IoT Core TPM implementation doesn't use parameter encryption either. As such, the SAK could be sniffed during provisioning (which isn't a very troubling scenario), and SAS tokens could be sniffed during operations. Depending on the device's threat model, this latter issue could be a problem. In addition, an attacker with physical access to the IoT device could simply request the TPM sign arbitrary data either by interposing on the bus or by removing the TPM altogether.
Defending against these types of threats in IoT devices is complicated by the fact that access control to the TPM, in the form of a PIN, is complicated by the typical need for zero user interaction during operations (or untrusted users altogether). And simply storing the PIN for automatic entry by the main CPU produces a chicken-and-egg problem. As such, two complementary lines of defense come to mind for TPM-protected IoT devices where physical access is a concern:
- Diversification and revocability. To limit the impact of compromised secrets, they ought to be diversified for each device during provisioning so that the compromise of a single device doesn't scale to the entire fleet in pwn-once, exploit everywhere style. In addition, authentication secrets ought to be revocable, so defensive telemetry becomes actionable.
- Tamper resistance. Since TPMs do not have the ability to be hooked up directly to external tamper switches, they should be integrated into a protected subsystem where tamper switch activation immediately triggers the erasure of the TPM secret. Ideally, tamper switch activation also raises backend alerts so revocation processes can be initiated.
Considerations for Red Teams
Carrying out a TPM sniffing attack in practice isn't quite the same as doing it under lab conditions. TPM sniffing attacks against FDE solutions can be a powerful tool in a red team's arsenal and fit into a wide array of threat models such as physical attackers with on-premise access, unattended/stolen laptops, rogue insiders, and supply chain interdiction. Still, all of these scenarios have in common that the window within which red team operators can execute their attack is limited. Some measure of stealth is required—as such, going in completely blind and fumbling for half an hour while you planned on minutes and leaving a hastily-reassembled laptop behind can make this all harder to pull off in practice than it is on purely technical grounds.
First of all, the accessibility of TPM bus communications can vary greatly. In most of the prior work, researchers chose to attach SOIC8 test clips or grabber probes to some chip that happened to sit on the same bus as the TPM. You might encounter motherboard designs, however, where none of the chips on the TPM bus have an easy-to-access chip package type. Tapping bus pins on a TQFP, QFN, or BGA chip is quite a bit trickier than nice and easy SOIC chips. Sometimes you're lucky, and there will be large pads or nearby test points, but in other cases, you'll need to use needle probes or some very thin wire soldering skills. And then it might turn out you expected SPI communications while on this motherboard revision, the TPM still used LPC...
In other cases, chips and/or test points are simply hard to access. They can be hidden under layers of plastic and coating, wedged under fan arms, or on the other side of the motherboard, requiring a complete disassembly and flip-over. And all that stuff will have to be put back together inconspicuously and in working order before you get caught.
To prevent surprises and unnecessary fumbling, red team operators should take the following preparations when executing a TPM sniffing attack:
- Collect intelligence on the FDE solution deployed and its configuration (PIN used?), and ensure analyzer tooling is available for it.
- Collect intelligence on the laptop models in use, obtain schematics, ensure tooling can handle the bus type in question, and at least practice a few times on the model in question.
- Collect intelligence on any tamper-evident measures (security labels, switches, etc.) in use and prepare accordingly.
- Ensure you bring a fast disk cloning solution to copy ciphertext from the drive for later decryption, you don't want to do this on the spot, nor do you want to wait for hours.
Defeating an additional factor in practice won't be trivial. Still, two possible avenues could be bootkit-based tamper-and-revert attacks and leaving a tiny hardware implant with bus-sniffing capabilities on the motherboard. Upon entering the additional factor and unsealing the TPM secret, the implant could either store it for later physical retrieval or possibly exfiltrate it over an integrated comms capability (RF, 4G, etc.) depending on available space and miniaturization capabilities. Trammell Hudson presented a great talk on this subject for a related use case at 35C3.
- Deploy an additional factor such as a PIN, password, or TOTP to regulate TPM unsealing.
- Use an fTPM instead of a dTPM if possible.
- Configure the TPM for measured boot integration into the FDE configuration to protect against firmware threats.
- Deploy tamper-evident security seals on sensitive devices (though the degree to which this aid varies greatly).