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
129 lines
5.9 KiB
C
129 lines
5.9 KiB
C
/*
|
||
StarForth — Steady-State Virtual Machine Runtime
|
||
|
||
Copyright (c) 2023–2025 Robert A. James
|
||
All rights reserved.
|
||
|
||
Licensed under the StarForth License, Version 1.0
|
||
*/
|
||
|
||
/**
|
||
* capsule_zuse_boot.h - Thumbdrive-resident Zuse genesis/attach
|
||
* (FABRIC-2.md §F.20/§F.21). Replaces kernel_main.c's old one-shot
|
||
* block-fence mint-or-load: Zuse's own identity now lives only on her
|
||
* own minted thumbdrive, never system-resident. Since USB attach
|
||
* detection only happens inside the idle loop (sk_repl_idle(), not at
|
||
* a fixed point in the boot sequence), this runs per-attach from there
|
||
* instead of once at boot.
|
||
*/
|
||
|
||
#ifndef STARKERNEL_CAPSULE_ZUSE_BOOT_H
|
||
#define STARKERNEL_CAPSULE_ZUSE_BOOT_H
|
||
|
||
#ifdef __STARKERNEL__
|
||
|
||
#include "starkernel/homeblocks_sig.h"
|
||
#include "vm.h"
|
||
|
||
struct blkio_dev;
|
||
|
||
/**
|
||
* capsule_zuse_boot_try_attach - Try to genesis-mint or authenticate
|
||
* Zuse from a just-attached drive.
|
||
*
|
||
* No-op if mama_vm->zuse_cert_installed is already 1 (Zuse already has a
|
||
* real identity this boot, from an earlier attach). Otherwise:
|
||
* - No genesis marker yet in the fence, drive reads HOMEBLOCKS_SIG_BLANK:
|
||
* mint Zuse's own identity onto it (capsule_mint_identity(), genesis
|
||
* mode), record the pubkey in the fence, install the cert, and
|
||
* re-run ACL-ZUSE-BOOT (zuse.4th) so zuse_session activates exactly
|
||
* like it always has for a same-boot-installed cert.
|
||
* - Genesis marker present, drive reads HOMEBLOCKS_SIG_OK: read its
|
||
* own user_identity_seed_t, compare pubkey against the marker: if it
|
||
* matches, install the cert and re-run ACL-ZUSE-BOOT the same way.
|
||
* If it doesn't match, this is some other identity's drive -- no-op
|
||
* here, that's a regular attach for BINDSTEP to handle later.
|
||
* - Anything else (foreign/corrupt media, no marker and non-blank
|
||
* drive): no-op.
|
||
*
|
||
* @param dev The just-attached, already-open block device.
|
||
* @param sig_rc homeblocks_sig_check()'s own result for this attach.
|
||
* @param sig The checked homeblocks_sig_t (only meaningful if
|
||
* sig_rc == HOMEBLOCKS_SIG_OK; may be NULL otherwise).
|
||
* @param mama_vm Hera's own VM (zuse_cert_seed/installed/session live
|
||
* here; also the target of the ACL-ZUSE-BOOT re-run).
|
||
*/
|
||
void capsule_zuse_boot_try_attach(struct blkio_dev *dev,
|
||
homeblocks_sig_result_t sig_rc,
|
||
const homeblocks_sig_t *sig,
|
||
VM *mama_vm);
|
||
|
||
/**
|
||
* capsule_zuse_boot_logout - End Zuse's session when her own attached
|
||
* drive detaches (FABRIC-2.md §I.8, re-scoped 2026-09-04: no identity is
|
||
* different here -- Zuse logs out on device removal exactly like a
|
||
* WIREBIND user does, not via a Stadium-patron TTL. She has no separate
|
||
* VM or blocks of her own, so unlike capsule_wirebind_eject()/
|
||
* _unclean_detach() there is no flush step to skip on the abrupt path --
|
||
* one function covers both the graceful (EJECT) and abrupt (hot-unplug)
|
||
* call sites identically.
|
||
*
|
||
* No-op if `dev` isn't the device currently tracked as Zuse's own (nothing
|
||
* to do -- some other identity's drive is what's leaving, or nothing is
|
||
* attached at all) -- FABRIC-3.md §VII follow-on, 2026-09-06: this doc
|
||
* comment always claimed that no-op, but the check itself was missing
|
||
* until now (the function took no device parameter at all) -- confirmed
|
||
* live as a real bug once genuine multi-device attach made it reachable
|
||
* (detaching an unrelated device logged Zuse out too). Clears
|
||
* mama_vm->zuse_session only -- zuse_cert_installed and the cert itself
|
||
* stay put, permanently, per vm_zuse_cert_install()'s own one-way design;
|
||
* re-attaching her own drive re-authenticates via
|
||
* capsule_zuse_boot_try_attach() without re-minting anything.
|
||
*
|
||
* @param mama_vm Hera's own VM (zuse_session lives here).
|
||
* @param dev The device that just detached -- compared against the one
|
||
* tracked as hers; every other value is a no-op.
|
||
*/
|
||
void capsule_zuse_boot_logout(VM *mama_vm, struct blkio_dev *dev);
|
||
|
||
/**
|
||
* capsule_zuse_boot_attached_dev - The device currently tracked as Zuse's
|
||
* own, or NULL if she isn't attached this boot. FABRIC-3.md §VII follow-on,
|
||
* 2026-09-06: exists so an explicit, operator-initiated logout (EJECT,
|
||
* mama_forth_words.c) can pass her own device back into
|
||
* capsule_zuse_boot_logout() without needing to already know it -- unlike
|
||
* the abrupt hot-unplug path, EJECT isn't reacting to any specific
|
||
* device's detach event, so there is no other device value available at
|
||
* that call site to check against.
|
||
*/
|
||
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_CAPSULE_ZUSE_BOOT_H */
|