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:
co-authored by
Claude Sonnet 5
parent
6f5605d479
commit
309e792f07
+47
@@ -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
|
||||
|
||||
@@ -764,6 +764,8 @@ ifeq ($(ARCH),amd64)
|
||||
-drive id=artdisk,file=$(ARTDISK),format=raw,if=none \
|
||||
-device virtio-blk-pci,drive=artdisk \
|
||||
-device qemu-xhci,id=xhci0 \
|
||||
-object rng-random,id=rng0,filename=/dev/urandom \
|
||||
-device virtio-rng-pci,rng=rng0 \
|
||||
-chardev socket,id=cserial,path=$$SERIAL_SOCK,server=on,wait=off,logfile=$$LOG \
|
||||
-serial chardev:cserial \
|
||||
-qmp unix:$$QMP_SOCK,server=on,wait=off \
|
||||
@@ -828,6 +830,8 @@ else ifeq ($(ARCH),aarch64)
|
||||
-device virtio-blk-pci,drive=artdisk \
|
||||
-device virtio-keyboard-pci,addr=0x3 \
|
||||
-device qemu-xhci,id=xhci0,addr=0x4 \
|
||||
-object rng-random,id=rng0,filename=/dev/urandom \
|
||||
-device virtio-rng-pci,rng=rng0,addr=0x5 \
|
||||
-device ramfb \
|
||||
-chardev socket,id=cserial,path=$$SERIAL_SOCK,server=on,wait=off,logfile=$$LOG \
|
||||
-serial chardev:cserial \
|
||||
@@ -912,6 +916,8 @@ else ifeq ($(ARCH),riscv64)
|
||||
-device virtio-blk-pci,drive=artdisk,addr=0x1 \
|
||||
-device virtio-keyboard-pci,addr=0x3 \
|
||||
-device qemu-xhci,id=xhci0,addr=0x4 \
|
||||
-object rng-random,id=rng0,filename=/dev/urandom \
|
||||
-device virtio-rng-pci,rng=rng0,addr=0x5 \
|
||||
-device ramfb \
|
||||
-chardev socket,id=cserial,path=$$SERIAL_SOCK,server=on,wait=off,logfile=$$LOG \
|
||||
-serial chardev:cserial \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Capsule Block Manifest — Auto-generated
|
||||
<!-- Generated by mkcapsule --manifest 2026-08-26T17:54:43Z -->
|
||||
<!-- Generated by mkcapsule --manifest 2026-08-26T18:28:05Z -->
|
||||
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
||||
<!-- Hand-written justifications and immutability notes live -->
|
||||
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* virtio_rng.h — Virtio 1.0 entropy source driver for StarKernel
|
||||
*
|
||||
* Real hardware/host entropy, uniformly across all three architectures.
|
||||
* Exists specifically because this kernel has no per-arch RNG that covers
|
||||
* all three ISAs: amd64 has RDRAND and riscv64 has the Zkr extension, but
|
||||
* QEMU's aarch64 CPU models (including "max") expose neither RNDR nor any
|
||||
* other RNG property (checked directly against QEMU 10.2.1, see
|
||||
* vm_uuid.h's identical finding). A paravirtualized virtio-rng device
|
||||
* sidesteps the per-ISA gap entirely: the host supplies the entropy, the
|
||||
* guest-side protocol is identical on all three arches.
|
||||
*
|
||||
* QEMU-only: there is no virtio-rng on real hardware (Milestone 8, bare-
|
||||
* metal boot). A real per-arch RNG driver is a separate, later problem.
|
||||
*
|
||||
* Only one virtio-rng device is supported.
|
||||
*/
|
||||
|
||||
#ifndef STARKERNEL_VIRTIO_RNG_H
|
||||
#define STARKERNEL_VIRTIO_RNG_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* virtio PCI vendor (shared with every virtio device) */
|
||||
#define VIRTIO_RNG_PCI_VENDOR_ID 0x1AF4u
|
||||
/* device IDs: virtio device id 4 (entropy source) */
|
||||
#define VIRTIO_RNG_DEVICE_MODERN 0x1044u
|
||||
#define VIRTIO_RNG_DEVICE_LEGACY 0x1005u
|
||||
|
||||
/*
|
||||
* virtio_rng_init — locate the virtio-rng device on the PCI bus and bring
|
||||
* the driver up. Call once, before the first virtio_rng_get_bytes() call.
|
||||
*
|
||||
* Returns 0 on success.
|
||||
* Returns -1 if no virtio-rng device was found on the PCI bus.
|
||||
* Returns -2 on driver initialisation failure (bad BAR, queue setup, etc.).
|
||||
*/
|
||||
int virtio_rng_init(void);
|
||||
|
||||
/*
|
||||
* virtio_rng_ready — 1 if virtio_rng_init() has already succeeded.
|
||||
*/
|
||||
int virtio_rng_ready(void);
|
||||
|
||||
/*
|
||||
* virtio_rng_get_bytes — fill buf with n bytes of real host-supplied
|
||||
* entropy, blocking (polling) until all n bytes are obtained. The device
|
||||
* may return fewer bytes than requested per request; this loops
|
||||
* internally until the buffer is full.
|
||||
*
|
||||
* Returns 0 on success (buf fully filled).
|
||||
* Returns -1 if virtio_rng_init() has not succeeded.
|
||||
* Returns -2 on a device/timeout error partway through.
|
||||
*/
|
||||
int virtio_rng_get_bytes(uint8_t *buf, size_t n);
|
||||
|
||||
#endif /* STARKERNEL_VIRTIO_RNG_H */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -64,6 +64,7 @@ EFI_RUNTIME_SERVICES *g_sk_runtime_services = NULL;
|
||||
#include "starkernel/repl.h"
|
||||
#include "starkernel/pci.h"
|
||||
#include "starkernel/virtio_blk.h"
|
||||
#include "starkernel/virtio_rng.h"
|
||||
#include "starkernel/virtio_input.h"
|
||||
#include "starkernel/xhci_driver.h"
|
||||
#include "block_subsystem.h"
|
||||
@@ -610,6 +611,23 @@ static void kernel_main_deep(BootInfo *boot_info) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Phase 8: virtio-rng entropy source. Real per-arch RNG doesn't cover
|
||||
* all three architectures (amd64 RDRAND, riscv64 Zkr, but aarch64 has
|
||||
* neither in QEMU's CPU models -- see vm_uuid.h's identical finding),
|
||||
* so signing/keygen entropy comes from this paravirtualized device
|
||||
* instead. Unconditional call site, same graceful-noop precedent as
|
||||
* virtio_blk_find_artemis() above -- boot proceeds either way, the
|
||||
* device is only required once something actually calls
|
||||
* virtio_rng_get_bytes(). */
|
||||
{
|
||||
int rrc = virtio_rng_init();
|
||||
if (rrc == 0) {
|
||||
console_println("virtio-rng: ready");
|
||||
} else {
|
||||
console_println("virtio-rng: not available (continuing without)");
|
||||
}
|
||||
}
|
||||
|
||||
/* item 4.3.5c: virtio-keyboard-pci, riscv64 only today. Unconditional
|
||||
* call site, same as virtio_blk_find_artemis() above -- the function
|
||||
* itself no-ops with a console message on architectures/boards where
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user