Firmware Management Parameters

Cryptohome manages a TPM space which holds management parameters for the firmware.

Overview

Firmware Management Parameters (FWMP) control the rewritable (RW) firmware boot process. They can be used to disable developer mode on enterprise devices. If developer mode is enabled, they can limit which kernel key can be used to sign developer images, and/or enable developer features such as booting from USB or legacy OS.

The FWMP is stored in a TPM NVRAM space. The space is logically defined as follows:

struct FirmwareManagementParametersRawV1_0 {
  uint8_t crc;
  uint8_t struct_size;
  uint8_t struct_version;
  uint8_t reserved0;
  uint32_t flags;
  uint8_t developer_key_hash[SHA256_DIGEST_LENGTH];
} __attribute__((packed));

The crc is a CRC8 over the struct_version...hash fields.

The struct_size is the size of the entire structure in bytes.

The struct_version contains the major version in the high nibble and the minor version in the low nibble. Current structure is version 0x10 = 1.0. Minor version changes are backwards-compatible; a 1.0 reader can parse any 1.x data, though there may be new fields following hash[]. Major version changes are not backwards-compatible; a 1.0 reader cannot parse any 2.x data.

The reserved0 field is written 0 by current writers and ignored by current readers. It is for padding the flags to a 32-bit boundary. Future 1.x versions of the struct may use it.

The flags field contains several bitflags. Unused flags bits are set to 0 by current writers.

DEVELOPER_DISABLE_BOOT = 1;
DEVELOPER_DISABLE_RECOVERY_INSTALL = 2;
DEVELOPER_DISABLE_RECOVERY_ROOTFS = 4;
DEVELOPER_ENABLE_USB = 8;
DEVELOPER_ENABLE_LEGACY = 16;
DEVELOPER_USE_KEY_HASH = 32;
DEVELOPER_DISABLE_CASE_CLOSED_DEBUGGING_UNLOCK = 64;

The developer_key_hash is a SHA-256 hash of the developer key data (vb2_packed_key.key_size bytes at offset vb2_packed_key.key_offset from the start of a vb2_packed_key).

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 D-Bus API calls. See firmware_management_parameters.h for more information. See src/platform/vboot_reference/ for the firmware implementation. Note that the contents of the space and the NVRAM index must be consistent with src/platform/vboot_reference/firmware/lib/include/rollback_index.h.

Device integration

FWMP is an optional space. If it is not present, the firmware behaves in a default manner, as if FWMP were present with flags=0.

On a fresh installation, enterprise enrollment or a developer may create a FWMP while the TPM owner password is still known:

cryptohome --action=set_firmware_management_parameters \
  --flags=XXX [--developer_key_hash=YYY]

Where XXX is the flags as a 32-bit value, and YYY is the optional SHA-256 developer key hash digest as a 64-character hexadecimal string.

If the device is de-enrolled, or a developer wants to remove a FWMP they previously created:

cryptohome --action=remove_firmware_management_parameters

Note that still requires the TPM owner password to be known, or the TPM owner to have been reset by toggling developer mode off and back on using the firmware or by issuing:

crossystem clear_tpm_owner_request=1

and then rebooting.

On subsequent boots, the TPM owner password is no longer known, preventing the space from being reset or removed. The current settings can still be read back via:

cryptohome --action=get_firmware_management_parameters

NVRAM Index Selection

The NVRAM space index 0x100A was picked to follow the other spaces used by the firmware (0x1007 - 0x1009).