WIREBIND cert verification: load Zuse's root pubkey independently of her live session
Build / build-amd64-iso (push) Waiting to run
Build / build-aarch64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run

Root cause of the remaining "identity attach doesn't complete when Zuse
never attaches this boot" issue: capsule_wirebind_verify_cert() gated on
mama_vm->zuse_cert_installed, which is only ever set when Zuse's own
drive attaches and authenticates this specific boot
(capsule_zuse_boot_try_attach() -> install_and_activate() ->
vm_zuse_cert_install()). Without her, any other identity's WIREBIND cert
verification silently refused -- correctly, by the old design, but that
design conflated two genuinely different things: "can mint new
identities" (needs Zuse's live private seed, a real privileged
operation) and "can verify an existing identity's cert" (needs nothing
but her already-public key).

That public key was already being persisted independently of her live
session: zuse_genesis_marker_t (zuse_genesis_marker.h) stores it in the
kernel's own top-of-device metadata fence (Artemis's resident storage),
written once at genesis, specifically *not* alongside her private seed
(which stays only on her own removable thumbdrive) -- the type's own doc
comment says as much. It just wasn't being loaded for anything but
confirming which drive is genuinely hers.

Fix: a new capsule_zuse_boot_load_root_pubkey() (capsule_zuse_boot.c)
reads that marker and populates two new VM fields, zuse_root_pubkey_known
/ zuse_root_pubkey (vm.h) -- deliberately separate from
zuse_cert_installed/zuse_cert_seed/zuse_cert_pubkey, which stay
untouched and still gate MINT exactly as before. Called once from
kernel_main.c as soon as Artemis's own storage attaches, unconditionally,
independent of whether Zuse's own drive is ever attached this boot.
capsule_wirebind_verify_cert()/capsule_wirebind_try_attach() now check
zuse_root_pubkey_known instead of zuse_cert_installed.

One identity's attach must not depend on another identity's live
presence -- each identity stands on its own once the fleet's root of
trust has been established once, ever.

Verified live, amd64: identity 00 (disk/thumbdrives/00-thumb-ident.img)
now attaches and completes WIREBIND in 19 seconds with Zuse's own drive
never attached this boot at all (previously: unbounded, many real
minutes or effectively never, before today's other fixes; still slow/
stuck after those, stuck specifically on this silent refusal). Zuse's
own attach flow re-verified unaffected (regression check, amd64).
Three-arch clean qemu acceptance (amd64/aarch64/riscv64) passed with
this change included.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Ec88YKxxhZGG1RNnune78
This commit is contained in:
Robert Allan James
2026-09-09 14:30:14 -04:00
co-authored by Claude Sonnet 5
parent 1a263555e2
commit 1839a2b0c3
20 changed files with 62948 additions and 6 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
# Capsule Block Manifest — Auto-generated # Capsule Block Manifest — Auto-generated
<!-- Generated by mkcapsule --manifest 2026-09-09T15:57:24Z --> <!-- Generated by mkcapsule --manifest 2026-09-09T18:24:33Z -->
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. --> <!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
<!-- Hand-written justifications and immutability notes live --> <!-- Hand-written justifications and immutability notes live -->
<!-- in MANIFEST.md alongside this auto-generated index. --> <!-- in MANIFEST.md alongside this auto-generated index. -->
BIN
View File
Binary file not shown.
+25
View File
@@ -98,6 +98,31 @@ void capsule_zuse_boot_logout(VM *mama_vm, struct blkio_dev *dev);
*/ */
struct blkio_dev *capsule_zuse_boot_attached_dev(void); struct blkio_dev *capsule_zuse_boot_attached_dev(void);
/**
* capsule_zuse_boot_load_root_pubkey - Populate mama_vm->zuse_root_pubkey/
* zuse_root_pubkey_known from the persistent genesis-marker fence
* (zuse_genesis_marker_t, block_subsystem.h's blk_meta_zone_read()),
* independently of whether Zuse's own thumbdrive is attached this boot.
*
* Call once, early -- as soon as the block subsystem and Artemis's own
* resident storage are up (the fence lives there, not on any removable
* drive) -- from kernel_main.c. No-op (leaves zuse_root_pubkey_known 0)
* if no genesis has ever happened yet (no marker in the fence): there is
* no root identity to verify against, so no WIREBIND identity could have
* a cert chained to one either.
*
* Deliberately does not touch zuse_cert_installed/zuse_cert_seed/
* zuse_cert_pubkey -- that triple stays reserved for Zuse's own live,
* authenticated session (capsule_zuse_boot_try_attach()), gating MINT
* (needs her private seed). This function only ever loads her already-
* public key, for WIREBIND cert *verification* (capsule_wirebind.c),
* which needs nothing else -- see zuse_root_pubkey_known's own doc
* comment (vm.h) for the full reasoning.
*
* @param mama_vm Hera's own VM (zuse_root_pubkey/_known live here).
*/
void capsule_zuse_boot_load_root_pubkey(VM *mama_vm);
#endif /* __STARKERNEL__ */ #endif /* __STARKERNEL__ */
#endif /* STARKERNEL_CAPSULE_ZUSE_BOOT_H */ #endif /* STARKERNEL_CAPSULE_ZUSE_BOOT_H */
+15
View File
@@ -485,6 +485,21 @@ typedef struct VM
* redefinition-only guarantee can't be bypassed via >BODY on a * redefinition-only guarantee can't be bypassed via >BODY on a
* CONSTANT (see FABRIC-2.md). Read-only FORTH access via * CONSTANT (see FABRIC-2.md). Read-only FORTH access via
* ZUSE-PUBKEY@. */ * ZUSE-PUBKEY@. */
uint8_t zuse_root_pubkey_known; /**< 1 = zuse_root_pubkey holds a real value, loaded from the
* persistent genesis-marker fence (zuse_genesis_marker_t,
* capsule_zuse_boot_load_root_pubkey()) independently of whether
* Zuse's own thumbdrive is attached this boot. Deliberately
* separate from zuse_cert_installed/zuse_cert_seed above -- that
* pair is a one-way fuse gating MINT (needs her live private
* seed); this pair gates WIREBIND cert *verification* only (needs
* nothing but her already-public key), so a WIREBIND identity can
* be verified and attach without requiring Zuse's own live session
* this boot. Bob, 2026-09-09: "zuse is zuse, [each identity] is
* [itself]" -- one identity's attach must not depend on another's
* live presence. */
uint8_t zuse_root_pubkey[32]; /**< Ed25519 public key, loaded from the genesis-marker fence.
* Same value zuse_cert_pubkey ends up holding once Zuse herself
* attaches -- this is just available earlier and unconditionally. */
/** @} */ /** @} */
/** @name Dictionary Management /** @name Dictionary Management
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
File diff suppressed because it is too large Load Diff
+12 -5
View File
@@ -85,9 +85,16 @@ int capsule_wirebind_verify_cert(struct blkio_dev *dev,
* try_attach() owns that case, not this one. */ * try_attach() owns that case, not this one. */
if (sig->cert_offset == 0 || sig->cert_devblocks == 0) return -1; if (sig->cert_offset == 0 || sig->cert_devblocks == 0) return -1;
/* Nothing to verify a regular cert against until Zuse herself has /* FABRIC-3.md, 2026-09-09: verifying a WIREBIND cert needs nothing but
* authenticated this boot. */ * Zuse's already-public key -- it does not need her live session.
if (!mama_vm->zuse_cert_installed) return -1; * zuse_root_pubkey_known/zuse_root_pubkey (capsule_zuse_boot_load_
* root_pubkey(), loaded unconditionally from the persistent genesis-
* marker fence as soon as Artemis's own storage is up) is what this
* checks now, not zuse_cert_installed -- that pair stays reserved for
* MINT, which genuinely does need her live private seed. One
* identity's attach must not depend on another identity's live
* presence. */
if (!mama_vm->zuse_root_pubkey_known) return -1;
/* Read the cert region into a local buffer. */ /* Read the cert region into a local buffer. */
uint32_t n_devblocks = sig->cert_devblocks; uint32_t n_devblocks = sig->cert_devblocks;
@@ -102,7 +109,7 @@ int capsule_wirebind_verify_cert(struct blkio_dev *dev,
memset(out, 0, sizeof(*out)); memset(out, 0, sizeof(*out));
return vm_identity_from_cert(out, cert_der, cert_len, return vm_identity_from_cert(out, cert_der, cert_len,
mama_vm->zuse_cert_pubkey, sig->drive_uuid, mama_vm->zuse_root_pubkey, sig->drive_uuid,
0 /* acl_caps: no bits assigned yet, §F.2 */); 0 /* acl_caps: no bits assigned yet, §F.2 */);
} }
@@ -117,7 +124,7 @@ void capsule_wirebind_try_attach(struct blkio_dev *dev,
* verify_cert()'s own -1, but avoids a misleading refusal message * verify_cert()'s own -1, but avoids a misleading refusal message
* for a drive this function was never going to act on anyway). */ * for a drive this function was never going to act on anyway). */
if (sig->cert_offset == 0 || sig->cert_devblocks == 0) return; if (sig->cert_offset == 0 || sig->cert_devblocks == 0) return;
if (!mama_vm->zuse_cert_installed) return; if (!mama_vm->zuse_root_pubkey_known) return;
VMIdentity identity; VMIdentity identity;
if (capsule_wirebind_verify_cert(dev, sig, mama_vm, &identity) != 0) { if (capsule_wirebind_verify_cert(dev, sig, mama_vm, &identity) != 0) {
@@ -181,3 +181,13 @@ void capsule_zuse_boot_logout(VM *mama_vm, struct blkio_dev *dev) {
struct blkio_dev *capsule_zuse_boot_attached_dev(void) { struct blkio_dev *capsule_zuse_boot_attached_dev(void) {
return g_zuse_attached_this_device ? g_zuse_attached_dev : (struct blkio_dev *) 0; return g_zuse_attached_this_device ? g_zuse_attached_dev : (struct blkio_dev *) 0;
} }
void capsule_zuse_boot_load_root_pubkey(VM *mama_vm) {
if (!mama_vm || mama_vm->zuse_root_pubkey_known) return;
zuse_genesis_marker_t marker;
if (genesis_marker_read(&marker) != 0) return; /* no genesis yet -- nothing to load */
memcpy(mama_vm->zuse_root_pubkey, marker.zuse_pubkey, 32);
mama_vm->zuse_root_pubkey_known = 1;
}
+9
View File
@@ -62,6 +62,7 @@ EFI_RUNTIME_SERVICES *g_sk_runtime_services = NULL;
#include "starkernel/capsule_generated.h" #include "starkernel/capsule_generated.h"
#include "starkernel/capsule_loader.h" #include "starkernel/capsule_loader.h"
#include "starkernel/capsule_birth.h" /* capsule_birth_mama, capsule_find_mama_init */ #include "starkernel/capsule_birth.h" /* capsule_birth_mama, capsule_find_mama_init */
#include "starkernel/capsule_zuse_boot.h" /* capsule_zuse_boot_load_root_pubkey */
#include "starkernel/kmalloc.h" #include "starkernel/kmalloc.h"
#include "starkernel/repl.h" #include "starkernel/repl.h"
#include "starkernel/pci.h" #include "starkernel/pci.h"
@@ -594,6 +595,14 @@ static void kernel_main_deep(BootInfo *boot_info) {
if (vrc == 0) { if (vrc == 0) {
console_println("Artemis: virtio-blk attached"); console_println("Artemis: virtio-blk attached");
blk_subsys_attach_device(&artemis_dev); blk_subsys_attach_device(&artemis_dev);
/* FABRIC-3.md, 2026-09-09: load Zuse's own already-public root
* key from the persistent genesis-marker fence (lives here, on
* Artemis's own resident storage, not on Zuse's removable
* thumbdrive) as soon as that storage is up -- independent of
* whether Zuse's own drive is ever attached this boot. See
* capsule_zuse_boot_load_root_pubkey()'s own doc comment for
* why this is safe and separate from her live-session cert. */
capsule_zuse_boot_load_root_pubkey((VM *)mama_vm);
} else { } else {
console_println("Artemis: no virtio-blk disk (continuing without)"); console_println("Artemis: no virtio-blk disk (continuing without)");
} }