Correct the verification claims in the hardened-boot i.MX93 note - #477
Correct the verification claims in the hardened-boot i.MX93 note#477jetm wants to merge 6 commits into
Conversation
The Coverage table said every control was Verified on i.MX93 FRDM hardware. None of it was. The implementing PRs (meta-avocado #232, #236) are still open, the hardware validation task has never been run, and Avocado could not boot on this board at all on the BSP those PRs target until the meta-imx pin moved - the 6.6.36 SPL stalls before Normal Boot on Rev1.2 silicon, from any medium. The page asserted a finished hardware pass for a board that could not run the OS when it was written. The proxy column was wrong in the other direction. It named five harness assertions; three exist and only on the #232 branch, so they gate nothing on scarthgap, and the two for IMA and module signing do not exist anywhere. Both columns now say what actually holds, and the two proxy results the original omitted are stated as the open questions they are: TPM2 unseal fails on reboot and falls back to Argon2, and dm-verity is not active on that target. The unseal failure is the one that matters, because it is plausibly a QEMU artifact and equally plausibly the design sealing to a PCR that will not be stable - only the board settles it. The design content is unchanged and still correct; it was the verification status that was false. Verify-it and Reproduce-it are reframed from results into the checks the hardware pass owes, and the first-boot wedge found on the proxy is recorded, since it strands a device in emergency mode permanently and re-provisioning does not clear it. Signed-off-by: Javier Tia <javier@peridio.com>
There was a problem hiding this comment.
Pull request overview
This PR corrects overstated verification claims in the “hardened-boot i.MX93” field note, clearly separating what has been observed in the QEMU proxy run from what is still pending hardware validation on the i.MX93 FRDM.
Changes:
- Updates
tested_againstmetadata and theTestStatustargets to remove the implied hardware validation. - Adds a prominent verification-status caution banner and reframes “Verify it” / “Reproduce it” as hardware-pass checks rather than completed results.
- Rebuilds the coverage table and open-questions section to reflect current proxy findings and explicitly mark hardware status as “Not yet run”.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The note contradicted itself on which TPM the qemuarm64 proxy runs: the Coverage paragraph said QEMU swtpm while the open-questions bullet said OP-TEE fTPM. The layer settles which half is wrong. meta-avocado-qemu/conf/machine/avocado-qemuarm64.conf sets MACHINE_FEATURES += " optee-ftpm", and its own comment on the /var mapper change says the key is sealed to the OP-TEE fTPM rather than swtpm - swtpm is the qemux86-64 path. So the Coverage paragraph was the wrong half, and reconciling the bullet against it would have replaced a correct statement with an incorrect one. Correcting that cost the bullet its stated cause, which had blamed unstable PCR 7 measurement under the emulator. That was a guess, and optee-ftpm-init.bb already documents the mechanism: the QEMU virt machine has no RPMB, so OP-TEE cannot commit its secure-storage rollback counter, does not trust the fTPM's saved state, and the fTPM re-derives its seed on the next boot. Using the documented cause instead of the guess also sharpens the note's own thesis, because it means the proxy structurally cannot demonstrate reboot survival rather than merely having failed to. The admonition moves to the space-delimited title form the other 22 admonitions on the site use, so the one bracketed instance stops being a second convention nobody else follows. The Verify it lead-in becomes two sentences because "not output it has produced" parsed two ways as one. Prettier's italic and table-padding normalisation lands here too. Those lines are this branch's own additions, not a drive-by: scripts/checks.sh was already failing on them before this commit. Signed-off-by: Javier Tia <javier@peridio.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:183
- In the "Verify it" intro and expected output, the text reads awkwardly ("not output a board has already produced"), and the
systemd-cryptenroll --listexpectation is overly specific/inconsistent with the earlier section that describes Argon2id as slot 0 and TPM2 as slot 1. Consider tightening the intro sentence and making the expectation describe the condition (Argon2id slot removed; TPM2 slot present) without hard-coding a slot number.
These are the checks the hardware pass still has to run. The output below is what they should produce, not output a board has already produced. Run them on the board after boot:
```bash
# /var is LUKS2 and mounted from the mapped device
cryptsetup status /dev/mapper/var
…d not cover The note has been carrying "not yet run" against every hardware row since the claims correction. The board pass ran on 2026-08-12, so the LUKS2 row can be filled in - but only that row, and the reason the rest stay open is worth more to a reader than the tick mark. Three defects had to be fixed before the board could unlock /var at all, and all three were invisible on the qemuarm64 proxy because that machine carries an override imx93 lacked: DM_CRYPT silently demoted to =m by kconfig, AVOCADO_VAR_PART_DEV unset so fstab pointed at the raw partition, and a key provider reading a secret no recipe creates. Each is recorded with what it looked like rather than just that it was fixed, because the pattern - proxy passes, board cannot - is the transferable part. Phase-2 TPM2 changes from "not yet run" to "not possible on this board yet", which is a different claim. There is no TPM on the FRDM-IMX93 to seal to: no discrete part on the board, and the i.MX9 route to a TPM 2.0 interface is a firmware TPM on OP-TEE that is currently built for qemuarm64 only. So the open question about the TPM2 slot reopening /var is now pinned precisely: the proxy cannot show it for want of RPMB, and the board cannot show it for want of a TPM. Half of it - that /var reopens at all from an existing container across a reboot - the board did show. The security-properties section needed the sharpest correction. It claims two independent factors; on this board today there is one, and it is weaker than "passphrase" implies. The key derives from the SoC UID, which binds the volume to one board but is not a secret - anyone who can read it from a running system can rederive the key. Device binding is a real property and worth claiming; confidentiality against an attacker who has had code execution on the device is not, and the note said otherwise. Adds a reproduce section, since none of this is reachable without knowing that the image ships root login disabled, that the board boots from eMMC by default so an SD image needs the switches moved, and that the default flash task rewrites var. Verified: npm run build succeeds, static files generated. Signed-off-by: Javier Tia <javier@peridio.com>
|
The hardware pass this note was waiting on ran today, so the LUKS2 row is filled in - What the board showed. FRDM-IMX93 on the wrynose BSP (meta-avocado#271): Three defects had to be fixed before any of that worked, and each was invisible on the proxy because Phase-2 TPM2 moves from "not yet run" to "not possible on this board yet", which is a different claim and I think the more useful one. There is no TPM on the FRDM-IMX93 to seal to - no discrete part (UM12181, and the schematic BOMs for the i.MX95 siblings), and the i.MX9 route to a TPM 2.0 interface is a firmware TPM on OP-TEE that The security-properties section needed the sharpest edit. It claimed two independent factors. On this board today there is one, and it is weaker than "passphrase" implies: the key derives from the SoC UID, which binds the volume to one board but is not a secret, since anyone who can read it from a running system can rederive it. Device binding is real and worth claiming; confidentiality against an attacker who has already had code execution on the device is not, and the note said otherwise. Also adds a reproduce section - none of this is reachable without knowing that the stock image ships root login disabled (
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (5)
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:294
- There are two top-level sections titled “## Reproduce it” (one around build/flash steps and one for adversarial tests). Duplicate headings create duplicate anchors and make the ToC ambiguous; rename one of them (e.g., the adversarial section) to a distinct heading.
## Reproduce it
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:236
- PR description says the coverage table’s hardware column is “Not yet run throughout”, but this table marks hardware as Verified for LUKS2
/var(and the frontmatter also claims validation on 2026-08-12). Either the PR description needs updating or the table/frontmatter should be adjusted so they match, because reviewers will otherwise read the change as contradicting the stated intent.
| Control | `avocado-qemuarm64` (proxy) | `avocado-imx93-frdm` (hardware) |
| :------------- | :---------------------------------------------- | :------------------------------------------------- |
| LUKS2 `/var` | Verified on first boot | **Verified**, first boot and reboot (2026-08-12) |
| Phase-2 TPM2 | Enrollment verified; unseal on reboot **fails** | **Not possible on this board yet** - see below |
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:45
- The caution admonition says “What is not verified: any of it on the i.MX93 FRDM board”, but later the page claims LUKS2
/varwas validated on hardware (frontmattertested_against, coverage table, and “The hardware pass (2026-08-12)”). This reads as self-contradictory and undermines the corrected verification messaging. Rephrase this paragraph to reflect that only LUKS2/varhas been verified on hardware so far, while the rest remains proxy-only/not yet run.
This issue also appears on line 233 of the same file.
What is not verified: any of it on the i.MX93 FRDM board. The implementation is still
in review ([meta-avocado #232](https://github.com/avocado-linux/meta-avocado/pull/232)
and [#236](https://github.com/avocado-linux/meta-avocado/pull/236) are open), and two
results from the proxy run are open questions rather than details: TPM2 unseal on
_reboot_ fails there and falls back to the Argon2 slot, and dm-verity is not active on
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:204
- This paragraph is still grammatically incorrect/ambiguous (“not output anything has produced yet”). It also mixes “output a board has produced” with “checks that should produce output” in one sentence. Consider rephrasing so it clearly distinguishes verified command output from expected output for not-yet-run checks.
This issue also appears on line 294 of the same file.
## Verify it
Everything under LUKS2 below is output a board has produced. The TPM2, dm-verity, IMA/EVM and module-signing checks are what they should produce, not output anything has produced yet - see the coverage table.
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:288
- The page gives conflicting guidance on whether a re-flash clears
/var: earlier it saysfwup -t completerewrites the whole medium includingvar(line 199), but here it says re-provisioning doesn’t clear the wedge becausefwup -t completedoes not touchvar. These two statements can’t both be true; please verify the actualfwupbehavior and make the doc consistent so readers don’t brick devices based on incorrect recovery steps.
- **An interrupted first boot wedges the device permanently.** `cryptsetup-var.sh` only runs `mkfs.btrfs` in its first-boot branch. A first boot that dies after `luksFormat` but before `mkfs.btrfs` leaves a LUKS2 header with no filesystem inside, so every later boot takes the open-existing branch, never creates the filesystem, and drops to emergency forever. Re-provisioning does not clear it, because `fwup -t complete` does not touch the `var` partition; recovery means zeroing the LUKS header by hand. The fix is either to detect "header present, no filesystem on the opened mapper" and re-`mkfs`, or to make format-plus-mkfs atomic behind a completion marker.
… never written The build-flow snippet showed a fourth SRC_URI gate pulling file://ima.cfg on the ima DISTRO_FEATURE, and the source-layout tree listed an ima-policy recipe with a policy file and a public cert. None of it exists: ima.cfg is absent from scarthgap and from both secure-boot branches, no recipe or kas feature references ima, and the board confirms it - no /sys/kernel/security/ima, no ima_policy on the cmdline. A reader following the snippet greps for a file nobody ever wrote and concludes the docs are stale rather than the control is missing. The earlier pass on this note corrected the coverage table while leaving the snippet asserting the wiring exists, so the two halves disagreed. Replace the snippet with the three gates the bbappend actually carries - including the encrypted-var one it omitted - and say plainly that the IMA gate is design. Correcting the snippet meant reading the surrounding block against the tree, which surfaced the same defect in the fragment paths and packagegroup names; those are fixed here rather than left knowingly wrong in a block being rewritten. Signed-off-by: Javier Tia <javier@peridio.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (3)
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:182
- There are now two sections titled “Reproduce it” (this one and another later in the note). Duplicate headings create ambiguous anchors and make the document harder to navigate; consider renaming this earlier section to reflect that it’s the build/flash steps.
## Reproduce it
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:208
- Minor wording/grammar: “output a board has produced” / “not output anything has produced yet” reads awkwardly. Rephrase so it’s clear what output is confirmed vs expected.
Everything under LUKS2 below is output a board has produced. The TPM2, dm-verity, IMA/EVM and module-signing checks are what they should produce, not output anything has produced yet - see the coverage table.
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:50
- The admonition contradicts the rest of the note: it says nothing is verified on i.MX93 hardware, but the frontmatter and Coverage table state LUKS2
/varwas validated onavocado-imx93-frdm(2026-08-12). Update the admonition title/body so it accurately reflects partial hardware verification (LUKS2 only) and that the remaining controls are still proxy-only / design-only.
This issue also appears in the following locations of the same file:
- line 182
- line 208
What is verified, on `avocado-qemuarm64` standing in for the board: LUKS2 `/var`
formatted on first boot, and the two-phase enrollment landing an Argon2 recovery
keyslot alongside a TPM2 keyslot sealed to PCR 7.
What is not verified: any of it on the i.MX93 FRDM board. The implementation is still
The note described a designed secure boot; the chain now actually boots on the board, so the coverage table gains a row it can back with output rather than intent. Three things are worth a reader's time more than the walkthrough. Signing is SPSDK rather than CST, because cst_signer refuses AHAB without it and its own README puts i.MX 9 on that path - which also means there are no container offsets to scrape out of a build log. Enabling AHAB changes what booti means, so a bare Image no longer boots and a container staged at its own payload destination is destroyed by its own authentication. And ahab_status cannot report zero events before the fuses are burned, which inverts the order this note previously implied: burn while open, then check, then close. Also states plainly what is still not covered - the initramfs is passed outside the container and is therefore unauthenticated, on an image where it is what unlocks LUKS /var, and an open part logs a signature failure rather than refusing to boot. Signed-off-by: Javier Tia <javier@peridio.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (4)
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:49
- The admonition currently says “proxy only” and “What is not verified: any of it on the i.MX93 FRDM board,” but the page now documents hardware verification for LUKS2
/var(2026-08-12) and AHAB signed boot (2026-08-13) and the coverage table marks those as verified. This is internally inconsistent and may mislead readers skimming the banner.
What is verified, on `avocado-qemuarm64` standing in for the board: LUKS2 `/var`
formatted on first boot, and the two-phase enrollment landing an Argon2 recovery
keyslot alongside a TPM2 keyslot sealed to PCR 7.
What is not verified: any of it on the i.MX93 FRDM board. The implementation is still
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:208
- This sentence is hard to parse (“not output anything has produced yet”) and reads as contradictory with the rest of the section. Rephrase to clearly separate the LUKS2 commands (real output) from the other checks (expected output not yet validated on hardware).
## Verify it
Everything under LUKS2 below is output a board has produced. The TPM2, dm-verity, IMA/EVM and module-signing checks are what they should produce, not output anything has produced yet - see the coverage table.
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:10
- PR description says the hardware column is “Not yet run throughout,” but this note now claims hardware verification for LUKS2
/var(2026-08-12) and includes a signed-boot pass (2026-08-13). Please align the PR description with the content (or, if these hardware results shouldn’t ship yet, remove/adjust the new hardware-verified claims).
tested_against: 'Avocado 0.41.2, avocado-qemuarm64 (fTPM via QEMU). LUKS2 /var validated on avocado-imx93-frdm hardware 2026-08-12 (wrynose BSP, meta-avocado #271), first boot and reboot. Phase-2 TPM2, dm-verity and module signing NOT yet validated on that hardware; IMA/EVM is design only and not implemented in the layer.'
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:360
- There are now two top-level sections named “Reproduce it” (this one and the earlier build/flash section). Duplicate headings can create confusing navigation and collide on generated anchors/links. Consider renaming this section to describe its purpose (adversarial validation) while keeping the earlier “Reproduce it” for build steps.
## Reproduce it
Three adversarial tests, stated as predictions the hardware pass should confirm or break. None has been run on a board yet, and each one failing would say something specific about which control is not doing its job:
The signed-boot pass recorded here has `Loading Ramdisk` in its own output, and that line was the hole: AHAB covered the kernel and device tree, while booti takes its ramdisk from argv[1] and never authenticates it. On this image that initrd derives the LUKS key, so the only unsigned component sat in front of the storage control the note is about. Record what closed it and why the obvious route does not. A second container payload is authenticated and then never located, because the lookup stops at the first exec and first data image; keeping the separate load for its size leaves the length under an attacker's control, which a concatenated cpio turns into file replacement. Bundling into the kernel removes the argument entirely. The size consequences are worth a reader's time as much as the fix, since they are what the next person hits: an uncompressed embed that sextuples the kernel, boot partitions that have to double, and a memory map that breaks twice - once on the device tree, once on a DRAM hole this board has and a flat 2 GB assumption does not survive. Verified with `make build`. Signed-off-by: Javier Tia <javier@peridio.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (5)
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:44
- This paragraph says nothing is verified on i.MX93 FRDM hardware, but later sections and the Coverage table claim LUKS2
/var(and signed boot) have been validated on hardware. Reword this to reflect what is verified vs still unverified on hardware, and keep the proxy-only caveats for the remaining open questions.
What is not verified: any of it on the i.MX93 FRDM board. The implementation is still
in review ([meta-avocado #232](https://github.com/avocado-linux/meta-avocado/pull/232)
and [#236](https://github.com/avocado-linux/meta-avocado/pull/236) are open), and two
results from the proxy run are open questions rather than details: TPM2 unseal on
_reboot_ fails there and falls back to the Argon2 slot, and dm-verity is not active on
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:208
- The second sentence reads ungrammatically (“not output anything has produced yet”). Rephrase so it’s clear these are expected outputs for checks that haven’t been demonstrated yet.
Everything under LUKS2 below is output a board has produced. The TPM2, dm-verity, IMA/EVM and module-signing checks are what they should produce, not output anything has produced yet - see the coverage table.
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:242
- The PR description says the hardware column is “Not yet run throughout” and that
tested_against/TestStatus no longer claim the hardware target, but this doc now asserts multiple hardware validations (e.g., LUKS2/varverified on 2026-08-12; signed boot verified on 2026-08-13/14). Please reconcile the PR description vs the updated claims so reviewers/readers have a consistent source of truth.
| Control | `avocado-qemuarm64` (proxy) | `avocado-imx93-frdm` (hardware) |
| :------------- | :---------------------------------------------- | :------------------------------------------------- |
| LUKS2 `/var` | Verified on first boot | **Verified**, first boot and reboot (2026-08-12) |
| AHAB signed boot | No harness case exists | **Verified** on an open part - bootloader and OS container (2026-08-13), initramfs folded into the signed container (2026-08-14). See below |
| Phase-2 TPM2 | Enrollment verified; unseal on reboot **fails** | **Not possible on this board yet** - see below |
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:32
- The admonition title says “proxy only”, but this note now includes verified i.MX93 hardware results (e.g.,
tested_againstand the Coverage table). Update the title so it doesn’t contradict the rest of the page.
This issue also appears in the following locations of the same file:
- line 40
- line 238
:::caution Verification status: proxy only, the hardware pass is still open
src/field-notes/2026-06-24-hardened-boot-imx93.mdx:419
- There are now two
## Reproduce itheadings in this document (at lines 182 and 419), which will generate duplicate anchors/TOC entries in MDX. Rename one of them to keep heading IDs unique.
## Reproduce it
Problem
The published field note
2026-06-24-hardened-boot-imx93.mdxstates in its Coverage table that LUKS2/var, phase-2 TPM2 sealing, dm-verity, IMA/EVM and module signing are all Verified onavocado-imx93-frdmhardware. None of that holds.Normal Booton Rev1.2 silicon, from any medium; the board first booted after themeta-imxpin moved to 6.18.20. The note was published 2026-06-24; the board came up 2026-08-05.The proxy column was wrong in the other direction: it named five harness assertions, of which three exist and only on the #232 branch (so they gate nothing on
scarthgap), and two do not exist anywhere in the repo.This matters because the page is public and Secure Boot is an open ask from several accounts.
Solution
Correct the verification status and leave the design content alone. The technical write-up is sound; only the claims about what has been proven were false. A status admonition near the top states plainly what is and is not verified and links both open PRs, so the page stays useful rather than reading as retracted.
Key changes
Not yet runthroughout; proxy column reports what the qemuarm64 run actually producedTestStatustargets andtested_againstno longer claim the hardware targetVerify itandReproduce itreframed from results obtained into checks the hardware pass owesReviewer notes
The unseal-on-reboot failure is the open question worth attention. It is plausibly a QEMU artifact, since PCR 7 has no real Secure Boot state to measure under the OP-TEE fTPM, and equally plausibly the design sealing to a PCR that will not be stable. Only the hardware pass settles it, and that pass is starting now against a wrynose-based port of the two PRs.
npm run buildexits 0. This page is not a draft, so the production build genuinely compiles it, and I checked the rendered banner and table in a browser.