Phase 8 A: virtio-rng entropy source for real Ed25519 signing

The kernel's ed25519_verify() is deliberately verify-only -- no signing,
no keygen, no entropy source. That conflicts with the on-device MINT
word vision (Zuse signing new user certs live at runtime), so this
reopens that constraint on request rather than reshaping MINT around
verify-only.

vm_uuid.h already found the real gap: amd64 has RDRAND, riscv64 has Zkr,
but QEMU's aarch64 CPU models have neither -- confirmed against QEMU
10.2.1. A deterministic PRNG (fine for VM UUIDs) is not safe for key
generation, so this adds a virtio-rng device instead of a per-arch split:
real host entropy, identical guest-side protocol on all three arches.

New src/starkernel/virtio/virtio_rng.c + include/starkernel/virtio_rng.h,
transport plumbing mirroring the existing virtio_blk.c driver exactly.
Wired into kernel_main.c boot, -device virtio-rng-pci added to all three
QEMU targets.

Verified live (temp probe, written/run/captured/reverted): 16 real bytes
pulled through the full request/notify/poll round trip on all three
arches, three different values confirming real entropy. Final boot
against the reverted, permanent code: clean compile, clean boot to ok>
on amd64/aarch64/riscv64, Stadium conservation intact, no panics or
guest errors.

Ed25519 keygen/signing itself (Phase B) and the MINT word design
(Phase C) remain open, 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:
Robert Allan James
2026-08-26 14:32:20 -04:00
co-authored by Claude Sonnet 5
parent 6f5605d479
commit 309e792f07
13 changed files with 54761 additions and 1 deletions
+47
View File
@@ -346,6 +346,53 @@ decisions get added here, not to `FABRIC-2.md`. Follow the same discipline `FABR
ACL is opt-in (`init.4th`'s `S" ACL.4th" EXEC` commented out by default) so the new words
weren't exercised live from the REPL this pass — compile/lint/boot verification only.
**MINT word design, picked up 2026-08-26.** Before scoping `MINT` itself, found a real
conflict with an existing, deliberate decision: `include/starkernel/ed25519.h` is verify-
only by design — "this kernel never signs or generates keys (no entropy source to do so
safely anyway); signing happens in the host-side build tool" (`FABRIC-2.md`, Milestone 6,
2026-08-22). But the vision for `MINT` (§D below) is an *interactive*, on-device
`S" name" MINT` word — an authenticated Zuse session signing a new user's cert live, at
runtime. A kernel that structurally never signs can't do that as envisioned. Raised
directly; **decided (Captain Bob, 2026-08-26): give the kernel a real signing capability**
rather than reshape `MINT` around verify-only. This reopens the prior "no entropy source"
constraint deliberately, not by accident.
**Phase A — `virtio-rng`, done 2026-08-26.** Checked what entropy is actually available
before choosing a design: `include/starkernel/vm_uuid.h` already found, for VM UUIDs, that
amd64 has RDRAND and riscv64 has the Zkr extension, but QEMU's aarch64 CPU models (including
`max`) expose neither RNDR nor any RNG property at all — confirmed directly against QEMU
10.2.1. That's why VM UUIDs use a deterministic PRNG uniformly instead of a per-arch split;
that same choice is **not safe for Ed25519 keygen** — a seed drawn from a known value makes
the private key predictable. Decided: add a `virtio-rng` device instead of a per-arch
RDRAND/Zkr split with a weaker aarch64 fallback — QEMU supplies real host entropy
identically on all three arches, closing the aarch64 gap directly (QEMU-only; real hardware
at Milestone 8 needs a real per-arch RNG driver, a separate later problem).
New `include/starkernel/virtio_rng.h` + `src/starkernel/virtio/virtio_rng.c`, transport
plumbing (PCI capability walk, common-cfg feature negotiation, split virtqueue) mirroring
the existing `virtio_blk.c` exactly — same device family, same quirks. Simpler shape than
block: one virtqueue, one device-writable descriptor, no request header or status byte (the
entropy device has none); `virtio_rng_get_bytes()` loops internally since the device may
return fewer bytes than requested per round. `-object rng-random,id=rng0,filename=/dev/urandom`
+ `-device virtio-rng-pci` added to all three arches' QEMU invocations
(`Makefile.starkernel`). Wired into boot (`kernel_main.c`, right after the existing
`virtio_blk_find_artemis()` call site, same graceful-noop-on-absence precedent).
**Verified live, not just compiled:** a temporary probe (written, run once, captured,
reverted — per this project's standing probe convention) pulled 16 real bytes through the
full request/notify/poll/used-ring round trip on all three architectures and printed them:
amd64 `be9223909b86a8ccbfff705ccae2caa6`, aarch64 `861487df65a6d7a26b2c9c34f5ff96ee`, riscv64
`fec51d80e8c169a35aad9d908eab2f39` — three different values, confirming real entropy, not a
stale or repeated buffer. Probe reverted; permanent code is just the driver + init call. A
second, final 3-arch acceptance boot ran against that reverted code (not the probe build) to
confirm the shipped state itself is clean. Clean zero-warning compile and clean boot to
`ok>` on all three architectures, Stadium conservation intact (43691/21845/65536), no panics
or guest errors on either pass.
**Still open: Phase B (real Ed25519 keygen/signing, seeded from this entropy) and Phase C
(the `MINT` word itself, cert format, and whether Zuse's own keypair needs to chain to the
Milestone 6 offline root CA or is a self-sovereign instance-local root of trust).**
### 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