When we wrote about our CVM base images in April, the punchline was that a hardened, immutable image makes the verifier's job answerable: one rootfs hash, one kernel command line, one expected measurement per release. What we glossed over was an awkward question. Where does the verifier get that expected measurement from in the first place?
Until this week, the honest answer across most of the confidential computing industry, ours included, was: you boot a reference VM, read the measurement registers back, and declare those values the expected ones. That works, but it is circular. The values you verify against were produced by the very kind of machine you are trying to verify. If the build pipeline, the reference VM, or the operator publishing the values were compromised, the attestation would verify perfectly, against the wrong baseline.
Starting with this week's releases of cvm-images, we close that loop. Every release now ships the measurements a TDX machine will produce when it boots that image, computed from the disk artifact alone, before any VM exists. No reference boot, no trusted first machine, no circularity.
What a release now contains
Each tdx-base and tdx-gpu release publishes, alongside the image
itself:
*.roothash: the dm-verity root hash of the rootfs, recomputed independently in CI from the built filesystem (not just read back from the build).*.measurements.json: the predicted values ofRTMR[1]andRTMR[2], plus the inputs that produced them: per-event digests for every boot component the firmware will measure.- A human-readable measurements table in the release notes, so an auditor can eyeball the values without parsing JSON.
The prediction is exact, not approximate. We validated it byte-for-byte against the CC event log (CCEL) and live RTMR values of freshly booted VMs on GCP TDX hardware: the JSON computed by CI before the image ever touched a hypervisor matches what the silicon reports after boot, bit for bit.
How you predict a measurement register
TDX runtime measurement registers are hash chains:
RTMR ← SHA384(RTMR ∥ digest), starting from zero, extended once per
boot event. So predicting an RTMR means knowing exactly which events
the firmware and bootloader will log, in order, and what digest each
one contributes. On GCP's TDVF firmware, everything extended into
RTMR[1] (the EFI boot path) and RTMR[2] (OS boot) is a pure
function of the disk image:
- EFI boot applications (shim, GRUB) are measured by their PE/COFF Authenticode hash: SHA-384 over the binary with the checksum field, the certificate-table directory entry, and any embedded signature excluded, sections processed in file-offset order. This is the same hash a Secure Boot signature would cover, which is exactly the point: it identifies the code, not the file's incidental bytes.
- The GPT partition table is measured as a digest of the partition
entries. This is why our tooling also proves a useful negative
result: resizing a disk on GCE does not alter the measured GPT, so
growing a boot disk does not change
RTMR[1]. - Every GRUB command in
grub.cfgis measured individually asgrub_cmd: …events, after GRUB's own normalisation (variables like${grub_platform}expanded, quoting stripped). Our predictor parses the config with a strict state machine that refuses any construct it does not recognise; an unparseable grub.cfg fails the build rather than producing a silently wrong prediction. - The kernel, the initrd, and the kernel command line are measured
as file and string digests. The command line includes the dm-verity
root hash, which is how the entire read-only rootfs, every userland
binary on the machine, chains into
RTMR[2]through a single measured value.
The predictor replays this event sequence from the raw image: it reads the ESP, Authenticode-hashes the bootloaders, parses the GRUB configuration, hashes the kernel and initrd, and folds everything into the two hash chains. Around 200 lines of careful digest rules, and the end of "boot it and see" as a verification methodology.
MRTD and RTMR[0] (the firmware itself and its configuration) are
the hypervisor's contribution, not the image's, so they are observed
per platform rather than predicted from the artifact. The split is the
honest one: we publish what the image determines; the platform
attests what the cloud determines.
Pinned inputs: the build is now a fixed point
Predicting measurements from the artifact is only half of
transparency. The other half is being able to say what went into the
artifact. As of these releases, every image build pulls its packages
from snapshot.ubuntu.com at a timestamp
pinned in the repository, not from the moving archive.ubuntu.com.
Two builds of the same tag see the same package universe, down to the
exact .deb files.
We are deliberate about what this does and does not claim. It is not
yet full bit-for-bit reproducibility: the build toolchain itself is
not yet content-addressed (that is on the roadmap, and the design
keeps a Nix-based toolchain as the natural next step). What pinning
buys today is that the inputs to any given release are enumerable
and frozen. An auditor who checks out the tag knows precisely which
upstream packages, at which versions, from which snapshot, are inside
the rootfs whose hash is measured into RTMR[2].
A measured line between production and development
The same releases introduce one more measured fact: an image
profile marker baked into the rootfs, distinguishing production
images from dev ones (dev images carry an SSH server and a baked
operator key; production images have no interactive access at all).
Because the marker lives in the dm-verity-protected rootfs, it is
covered by RTMR[2]. A dev image cannot claim to be production any
more than it could swap out its kernel.
Enclave OS surfaces the profile in its RA-TLS certificates under our
OID arc (1.3.6.1.4.1.65230.2.8), and all our client libraries (Go,
Python, TypeScript, Rust, .NET) now fail closed on it: a client
refuses to talk to a dev-profile enclave unless the application
explicitly opts in. The trust decision moved from "we deployed the
right image, surely" to a cryptographically measured property checked
on every handshake.
And SEV-SNP joined the family on real hardware
A quieter milestone from the same release train: sev-snp-base had
its first boot on production AMD hardware, running SEV-SNP at VMPL0
with the same hardened kernel, lockdown, and dm-verity rootfs as the
TDX images. Measurement prediction for SNP (launch digests and vTPM
PCRs work differently from RTMRs) is on the roadmap; the image
architecture is already shared.
What this unlocks
The practical payoff is that admission to our platform can now be
grounded in published, independently recomputable values. When a new
confidential VM enrolls, it presents a TDX quote; the platform
extracts its MRTD and RTMRs and an operator compares them against
the measurements.json of the release the machine is supposed to be
running. Those values existed before that machine ever booted, anyone
can recompute them from the public repository, and no reference VM
had to be trusted to produce them.
Attestation tells you what booted. As of this release, you can know what should boot, from source, ahead of time, byte for byte. That is the difference between checking a measurement and actually verifying one, and it is what this level of transparency has always been about for us: the expected value is not something we hand you, it is something you can compute yourself.