| Cryptohome manages a tamper-evident file which is meant to contain |
| install-lifetime system attributes. |
| |
| = Overview |
| |
| Tamper-evident storage can be accessed by consumers over DBus using |
| the InstallAttributes* calls. Essentially, this provides a name-value |
| storage interface for Get()ing and Set()ing values during install. 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: |
| |
| 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 sanity 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 cryptohome.xml for the exact DBus API calls. See lockbox.h and |
| install_attributes.h for more information on what each provides. |
| |
| = Device integration |
| |
| InstallAttributes and Lockbox are initialized by default whenever the |
| cryptohomed 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 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, cryptohomed will call Finalize() any time a (Async)Mount |
| request is received over DBus. 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. |
| |
| = 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. |