Command-line tool and Rust library to calculate expected measurement of an Intel TDX guest VM for confidential computing.
The tdx-measure
tool takes a set of image binaries and platform config files as an input and outputs the corresponding TDX measurements. This makes it possible to exhaustively publish all images and config files that uniquely identify a TDX workload on a machine, making TD environments transparent and auditable.
The tool specifically targets the boot chains from the Canonical TDX repo.
This project is a fork of dstack-mr from the Dstack-TEE/dstack repository.
tdx-measure [OPTIONS] <METADATA>
<METADATA>
Path to metadata json file (see format lower down)
--two-pass-add-pages Enable two-pass add pages
--direct-boot <BOOL> Use direct/indirect boot method [true, false]
--json Output JSON
--json-file <JSON_FILE> Output JSON to file
--platform-only Compute MRTD and RTMR0 only
--runtime-only Compute RTMR1 and RTMR2 only
-h, --help Print help
-V, --version Print version
WARNING: when running with --runtime-only
, the tool will assume a VM memory size higher that 2.75GB.
To correctly compute measurements, tdx-measure
requires a set of binaries that correspond the platform/firmware configuration or to the image that is executed.
The required binaries and their locations are provided to the tool using a metadata JSON file (see details under).
Platform configuration files can be extracted by running the extract_boot_vars.py
script inside a TD guest configured identically on the target platform.
These files follow standard formats that can easily be audited (for instance, ACPI tables can be disassembled). Building tool to programmatically generate these files is future work.
{
"boot_config": {
"cpus": 32,
"memory": "10G",
"bios": "OVMF.fd",
"acpi_tables": "acpi_tables.bin",
"rsdp": "rsdp.bin",
"table_loader": "table_loader.bin",
"boot_order": "BootOrder.bin",
"path_boot_xxxx": [path for Bootxxxx.bin variables],
},
"direct": {
"kernel": "vmlinuz",
"initrd": "initrd",
"cmdline": "console=ttyS0 root=/dev/vda1"
}
}
{
"boot_config": {
"cpus": 32,
"memory": "10G",
"bios": "OVMF.fd",
"acpi_tables": "acpi_tables.bin",
"rsdp": "rsdp.bin",
"table_loader": "table_loader.bin",
"boot_order": "BootOrder.bin",
"path_boot_xxxx": [path for Bootxxxx.bin variables],
},
"indirect": {
"qcow2": "tdx-guest-ubuntu-24.04-generic.qcow2",
"cmdline": "console=ttyS0 root=/dev/vda1",
"mok_list": "MokList.bin",
"mok_list_trusted": "MokListTrusted.bin",
"mok_list_x": "MokListX.bin",
"sbat_level": "SbatLevel.bin"
}
}
# Build the project
cargo build --release
# Install the CLI tool
cargo install --path cli
Install Rust if not already installed
Canonical repo offer two boot options:
-
Direct Boot: With this method,
OVMF
(the TDVF or virtual firmware) directly boots the kernel image. In this mode, thekernel
,initrd
and the kernelcmdline
are directly supplied toqemu
. -
Indirect Boot: With this method,
tdvirsh
is used to run TDs, the boot chain is more complex and involvesOVMF
, aSHIM
,Grub
, and finally thekernel
+initrd
image.
TDX attestation reports expose 4 measurement registers (MR).
The first one, MRTD
, represent the measurements for the TD virtual firmware binary (TDVF, specifically OVMF.fd in our case).
Three other runtime measurement registers (RTMR
) correspond to different boot stages and vary depending on the boot chain.
RTMR[0]
contains firmware configuration and platform specific measurements. This includes hashes of:
- The TD HOB which mostly contains a description of the memory accessible to the TD.
- TDX configuration values.
- Various Secure Boot variables.
- ACPI tables that describe the device tree.
- Boot variables (BootOrder and others).
- [for indirect boot only] SbatLevel variable.
RTMR[1]
contains measurements of the kernel
for direct boot. For indirect boot, it contains measurement for the bootchain a.k.a. gpt
(GUID Partition Table), shim
, and grub
.
RTMR[2]
contains measurements of the kernel cmdline
and initrd
for direct boot. For indirect boot, it also contains the measurements of machine owner key (MOK) vairables.