Phase 8 C (2/n): expand cert storage; NVRAM persistence crashed, reverted
Cert storage expanded from the old 16-byte placeholder to a real 32-byte seed + 32-byte pubkey. vm_zuse_cert_install() now has a kernel-side duplicate in src/starkernel/vm/vm_core.c -- the kernel build's VM_EXCLUDE list drops src/vm.c entirely (same reason vm_set_base() already has two independent copies), so the hosted-only version added earlier this session was never actually linked into the kernel. FORTH-side ZUSE-CERT-LO@/HI@ replaced with ZUSE-PUBKEY@ (i -- u) over the public half only; ACL-ZUSE-BOOT now checks ZUSE-CERT-INSTALLED? before authenticating instead of unconditionally. Attempted NVRAM-based persistence (GetVariable/SetVariable) for the first-boot mint flow: page-faulted inside OVMF's variable service (CR2 in the flash MMIO window). Moving the call site to match the one proven-safe existing SetVariable call site in this codebase produced the identical crash -- not a timing issue. Localized with debug markers (one boot): GetVariable works; SetVariable with real data never returns. The existing "working" precedent call is actually a delete-of-nonexistent-variable (size=0, data=NULL), a cheaper path that never touches flash, so it proved nothing about real writes. Root cause: this kernel's VMM never maps the region OVMF's variable service needs for real flash writes -- a genuine gap in UEFI runtime- services support, not Zuse-specific, and not obviously fixable in a 3-arch-uniform way (flash window location is firmware/arch-specific). Independently, storing the raw seed in RUNTIME_ACCESS NVRAM would have been a real security defect regardless of the crash -- readable by any later-loaded UEFI app or the booted OS. Reverted to a known-safe state: all NVRAM/mint code removed from kernel_main.c, init.4th's ACL.4th line back to its documented commented-out default. Verified clean compile and clean boot on all three architectures. Cert storage expansion (the part that works) stays. A dedicated system-identity disk (virtio-blk, already proven for writes via Artemis) is the recommended next substrate -- not yet decided or built. Full investigation documented in FABRIC-3.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U14ET9CWAtbQMbYqomKgXd
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
f223a31cec
commit
e5cbc71f46
+51
@@ -475,6 +475,57 @@ decisions get added here, not to `FABRIC-2.md`. Follow the same discipline `FABR
|
||||
first-boot mint-vs-already-minted boot sequence using `SetVariable`/`GetVariable`, and the
|
||||
`MINT` word itself.
|
||||
|
||||
**Cert struct expanded (2026-08-26):** `vm_zuse_cert_install()` (both `src/vm.c`'s hosted
|
||||
copy and a new kernel-side duplicate in `src/starkernel/vm/vm_core.c` -- the kernel build's
|
||||
`VM_EXCLUDE` list drops `src/vm.c` entirely, same reason `vm_set_base()` already has two
|
||||
independent copies) now takes a real 32-byte seed + 32-byte pubkey instead of the old
|
||||
16-byte placeholder. FORTH-side `ZUSE-CERT-LO@`/`HI@` replaced with `ZUSE-PUBKEY@ ( i -- u )`
|
||||
(8-byte LE chunk `i`, 0..3, of the public half only -- the seed has no FORTH access at all).
|
||||
`ACL-ZUSE-BOOT` now checks `ZUSE-CERT-INSTALLED?` before authenticating rather than
|
||||
authenticating unconditionally. Verified: clean compile and clean boot on all three
|
||||
architectures.
|
||||
|
||||
**NVRAM persistence attempt: crashed, root-caused, reverted -- do not retry as designed.**
|
||||
First attempt placed the mint-or-load `GetVariable`/`SetVariable` logic right after
|
||||
`virtio_rng_init()` (before `capsule_birth_mama()`); it page-faulted (`CR2` inside the OVMF
|
||||
flash MMIO window, a supervisor write to a not-present page) partway through boot. Moved the
|
||||
same logic to the one place in this codebase already calling `SetVariable` post-
|
||||
`ExitBootServices` successfully (`SF_VAR_REBOOT_TRIES`, much later in boot) — **identical
|
||||
crash, same RIP and CR2** — which disproved the "too early in boot" theory outright: it isn't
|
||||
a timing issue.
|
||||
|
||||
**Localized precisely (advisor-directed, one boot, debug markers around each call):**
|
||||
`GetVariable` returns fine. `SetVariable` **with real 64-byte data** never returns — that's
|
||||
the exact fault site. The pre-existing `SF_VAR_REBOOT_TRIES` call that looked like a working
|
||||
precedent is actually a **delete of a variable that's never existed** (`size=0, data=NULL`) —
|
||||
a fundamentally different, much cheaper internal path than a real data write, so it proved
|
||||
nothing about real persistence being safe. **Root cause: this kernel's VMM never maps
|
||||
whatever memory region OVMF's variable service needs to actually write flash-backed variable
|
||||
data** — a real gap in UEFI runtime-services support, not specific to Zuse. Fixing it for
|
||||
real means walking the UEFI memory map for the relevant regions and mapping them into the
|
||||
kernel's own page tables, and per Section U's own note, the flash window's location is
|
||||
firmware/arch-specific (OVMF's differs from AAVMF's and EDK2-riscv64's), so "walk the map and
|
||||
map everything" is not guaranteed 3-arch-uniform even once attempted.
|
||||
|
||||
**Second, independent finding (not a bug, a design flaw in the persistence choice): storing
|
||||
the raw 32-byte seed in NVRAM was a real defect regardless of the crash.** `SetVariable` was
|
||||
called with `EFI_VARIABLE_RUNTIME_ACCESS`, meaning any later-loaded UEFI application or the
|
||||
booted OS itself could read Zuse's private key straight out of NVRAM. For an irrevocable
|
||||
"one and only one Zuse, ever" root of trust, that undermines the property the design exists
|
||||
to provide — this would have needed fixing even had the crash not happened.
|
||||
|
||||
**Decision needed, not yet made:** given virtio-blk writes are already proven working on all
|
||||
three architectures in this repo (`vblk_write`, Artemis's own persistence across runs), a
|
||||
dedicated file-backed system-identity disk (mirroring `disk/artemis.img`'s existing pattern,
|
||||
separate from Artemis's internal storage and separate from home-blocks USB thumbdrives) is
|
||||
the substrate with no open unknowns today — recommended over either fixing the UEFI
|
||||
flash-mapping gap (real but large, unscoped VMM work) or accepting the NVRAM approach as
|
||||
originally designed (has the exposed-seed defect regardless). Not decided or built yet.
|
||||
**Reverted to a known-safe state:** all Zuse mint/NVRAM code removed from `kernel_main.c`
|
||||
(only two harmless includes remain), `init.4th`'s `ACL.4th` line back to its documented
|
||||
commented-out default. Verified clean compile and clean boot on all three architectures in
|
||||
this reverted state.
|
||||
|
||||
### From FABRIC-2.md §X, Milestone 5 — Console/VM key-match binding
|
||||
|
||||
- [ ] Settle the still-open question: reuse `ACL-PIN`/`acl_allow` directly, or build a
|
||||
|
||||
Reference in New Issue
Block a user