blob: 5c7a166472bab6fcfd402e6f661a66c1e03e95b1 [file] [log] [blame] [view] [edit]
# Lockbox
Device Management manages a tamper-evident file which is meant to contain
install-lifetime system attributes.
## Overview
Tamper-evident storage can be accessed by consumers over D-Bus using the
InstallAttributes* calls. Essentially, this provides a name-value storage
interface for Get()ing and Set()ing values during install time. The datastore is made
`tamper-evident` by serializing it to a bytestream and persisting it to the
filesystem via the `Lockbox` class. This is done when
`InstallAttributes::Finalize()` is called. After finalization, the data becomes
`read-only`.
The Lockbox class provides a clear interface for implemented TPM NVRAM-backed,
tamper-evident data storage. It allows for the creation, destruction, storage,
and retrieval of tamper-evident data. InstallAttributes stores its serialized
data via this mechanism and reloads it similarly to ensure data integrity.
Each lockbox assures tamper-evidence cryptographically by storing a SHA256
digest of the supplied data blob in a TPM NVRAM space. The space itself is
logically defined as follows:
```c
struct {
uint32_t data_size;
uint8_t flags;
uint8_t salt[SHA256_DIGEST_LENGTH];
uint8_t hash[SHA256_DIGEST_LENGTH];
} __attribute__((packed));
```
* The data size is the expected size of the "locked" data. This provides a simple
validity check and ensures collision attacks against the stored data are
size-limited.
* Flags is reserved for future use, primarily in anticipation of future digest
changes or data serialization changes (encrypted versus not). At present, flags
is always 0.
* The salt is 32 bytes of randomly generated data sourced from the TPM itself.
This also aids in collision attack deterrence. Many devices will likely share
the same file. If a collision is found for the hash of that file, arbitrary
replacement attacks would be feasible. The added salt serves to increase the
difficulty of these forms of attack.
* The hash is computed as `SHA256(data||salt)`.
Once the struct is filled, it is written to the NVRAM space. A subsequent 0 byte
write locks the NVRAM space (bWriteDefine) from future modification without
redefinition using the TPM Owner passphrase or by asserting physical presence.
See `device_management/dbus_bindings/org.chromium.DeviceManagement.xml`
for the exact D-Bus API calls. See `lockbox.h` and
`install_attributes.h` for more information on what they provide.
## Device Integration
InstallAttributes and Lockbox are initialized by default whenever the
device_management service is started. On any system that is upgraded to support
InstallAttributes, it will treat the InstallAttributes as an empty-locked store
by observing that no NVRAM space was defined nor backing lockbox file created.
On a fresh installation, cryptohomed will start and immediately begin the TPM
ownership process. Upon completion, InstallAttributes from device_management
service will perform one-time initialization that creates its Lockbox and destroys
any existing Lockbox data. cryptohomed will then "forget" the TPM owner password
when told to by Chrome
(such as at the end of the EULA view or at the login screen). Chrome will
populate the InstallAttributes during the system's first boot and call
Finalize() upon completion. In addition, device_managementd will call Finalize() any
time a (Async)Mount request is received over D-Bus. This is to ensure that the
InstallAttributes are fully populated prior to the system going into general
use. On first login, a very fast user may perform the first Mount call prior to
the TPM being owned. In that case, the InstallAttributes will remain freshly
initialized and unlocked until the next Mount attempt occurs (after TPM
ownership has completed).
Recovery from a corrupt Lockbox requires the TPM to be cleared of a TPM owner.
This can be triggered by toggling the developer mode switch and rebooting, or by
going through the system recovery flow.
### Frontend APIs
- Fetches the install-time attributes from the given attribute name (if any):
```bash
device_management_client --action=install_attributes_get --name=<attribute_name>
```
- Sets the attribute value to the given attribute name:
```bash
device_management_client --action=install_attributes_set --name=<attribute_name> \
--value=<attribute_value>
```
- Finalizes the install-time attributes:
```bash
device_management_client --action=install_attributes_finalize
```
- Fetches the current status of install-time attributes (`UNKNOWN` / `TPM_NOT_OWNED`/ `FIRST_INSTALL` / `VALID` / `INVALID`):
```bash
device_management_client --action=install_attributes_get_status
```
- Fetches the total number of install-time attributes stored in the storage:
```bash
device_management_client --action=install_attributes_count
```
- Fetches the current status and returns `1` if the install-time attributes storage
is ready, `0` otherwise:
```bash
device_management_client --action=install_attributes_is_ready
```
- Fetches the current status and returns `1` if the install-time attributes storage
is secure, `0` otherwise:
```bash
device_management_client --action=install_attributes_is_secure
```
- Fetches the current status and returns `1` if the install-time attributes storage
is invalid, `0` otherwise:
```bash
device_management_client --action=install_attributes_is_invalid
```
- Fetches the current status and returns `1` if the status is `FIRST_INSTALL`,
`0` otherwise:
```bash
device_management_client --action=install_attributes_is_first_install
```
## NVRAM Index Selection
This value was picked by reviewing the related specification documents. The
index is a managed namespace as laid out below:
```
3 2 1
1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|T|P|U|D| resvd | Purview | Index |
(T=TPM, P=platform maker, U=platform user, D=pre-defined)
```
(from TCG TPM Structures rev 103)
Some ranges have been declared reserved in other specs:
* `0xFFFFFFFF` is the NVRAM lock (permanent).
* `0x50010000` is reserved for BIOS use.
* `0x0000Fxxx` preallocated/reserved by for locality use.
* `0x0001xxxx` are a handful of TSS reserved ranges.
* `0x10000001` is the deprecated NV_INDEX_DIR.
* `0x00000000` is the bGlobalLock index.
In addition, there is at least one other major user. For tboot, Intel uses:
* `0x20000001`: `00100000000000000000000000000001`
* `0x20000002`: `00100000000000000000000000000010`
in the Platform User range. It's unclear if they'll expand further out in the
future, so we leave room for them to add a single space.
* `0x20000004`: `00100000000000000000000000000100`
Arguably, we could use a 'P' space, but that would complicate Chromium OS use on
non-Chrome hardware.