Files
LithosAnanake/src/starkernel/capsule/capsule_zuse_boot.c
T
Robert Allan JamesandClaude Sonnet 5 ac4d431aee Fix zuse_root_pubkey_known never set after a same-session genesis mint
capsule_zuse_boot_load_root_pubkey() is the only writer of
zuse_root_pubkey_known, and it only ever runs once, synchronously, at
Artemis's boot-time virtio-blk attach -- before genesis mint has
happened on a fresh artemis.img, so it finds no marker yet and leaves
the flag 0. Nothing re-triggers it after genesis mint completes.

Silent result: capsule_wirebind_try_attach()'s own
`if (!mama_vm->zuse_root_pubkey_known) return;` gate then refuses
every identity attach for the rest of that boot, with no message at
all -- meaning WIREBIND was silently dead on any boot that reset
artemis.img fresh, which is exactly what this project's own
acceptance convention does before every run.

Found live verifying FABRIC-3.6.md task 3.9's console-session
acceptance. Fixed at the source: install_and_activate() already has
the root pubkey in hand (from genesis mint or an already-Zuse
re-attach) -- activate it directly there instead of relying on a disk
re-read that may never happen in-session.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 12:38:40 -04:00

212 lines
10 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 2023–2025 Robert A. James
All rights reserved.
Licensed under the StarForth License, Version 1.0
*/
#ifndef __STARKERNEL__
#error "capsule_zuse_boot.c is kernel-only"
#endif
#include "starkernel/capsule_zuse_boot.h"
#include "starkernel/capsule_mint.h"
#include "starkernel/zuse_genesis_marker.h"
#include "starkernel/user_identity_seed.h"
#include "starkernel/console.h"
#include "block_subsystem.h" /* compute_crc64(), blk_meta_zone_read/write */
#include "blkio.h"
#include <string.h>
#include <stddef.h>
/* FABRIC-3.md §VII follow-on, 2026-09-06: g_zuse_attached_this_device was a
* bare boolean under the single-USB-device constraint (§F.8) -- "a detach
* event is hers" needed no device comparison because only one device could
* ever be attached at all. That premise is stale (FABRIC-3.md §VII, the
* xHCI/BOT driver now supports genuine simultaneous multi-device attach) --
* confirmed live during this session's own 8-identity verification: with
* Zuse's drive and a WIREBIND target both attached, detaching the *target*
* incorrectly logged Zuse out too, because capsule_zuse_boot_logout() had
* no way to tell "some other device detached" from "my own device
* detached." g_zuse_attached_dev is the fix, mirroring capsule_wirebind.c's
* own g_wirebind_attached_dev precedent exactly -- the boolean stays (still
* useful as a fast "is she attached at all" check) but logout now also
* requires the departing device to match. */
static int g_zuse_attached_this_device = 0;
static struct blkio_dev *g_zuse_attached_dev = (struct blkio_dev *) 0;
/* Read exactly one devblock (4096 bytes) at devblock offset `devblock`,
* as 4 consecutive 1KiB forth-block reads -- mirrors capsule_runcap.c's
* and homeblocks_sig_check()'s own read convention. */
static int read_devblock(struct blkio_dev *dev, uint32_t devblock, uint8_t *buf4096) {
uint32_t base = devblock * 4u;
for (uint32_t i = 0; i < 4u; i++) {
if (blkio_read((blkio_dev_t *)dev, base + i,
buf4096 + (size_t)i * BLKIO_FORTH_BLOCK_SIZE) != BLKIO_OK) {
return -1;
}
}
return 0;
}
static int genesis_marker_read(zuse_genesis_marker_t *out) {
if (blk_meta_zone_read(0, (uint8_t *)out) != 0) return -1;
if (out->magic != ZUSE_GENESIS_MARKER_MAGIC) return -1;
if (out->version != ZUSE_GENESIS_MARKER_VERSION) return -1;
uint64_t want_crc = compute_crc64((const uint8_t *)out, offsetof(zuse_genesis_marker_t, crc));
if (want_crc != out->crc) return -1;
return 0;
}
static void install_and_activate(VM *mama_vm, struct blkio_dev *dev,
const uint8_t seed[32], const uint8_t pubkey[32]) {
/* vm_zuse_cert_install() is deliberately one-way (returns -1, no-op,
* once vm->zuse_cert_installed is already 1) -- that's a real
* security property (the cert/pubkey must never be re-installed or
* swapped) and stays untouched here. Its return is NOT used to gate
* ACL-ZUSE-BOOT below anymore (FABRIC-2.md §I.8, re-scoped
* 2026-09-04): re-authenticating after capsule_zuse_boot_logout()
* needs ACL-ZUSE-BOOT to re-run and re-set zuse_session even when
* the cert itself was already installed from an earlier boot-time
* attach -- gating it on install's success/failure made re-login
* impossible, since a second install always fails by design. */
vm_zuse_cert_install(mama_vm, seed, pubkey);
/* Real defect found live 2026-09-22 verifying FABRIC-3.6.md task 3.9:
* capsule_zuse_boot_load_root_pubkey() is the only other writer of
* zuse_root_pubkey_known, and it only runs once, at Artemis's
* boot-time virtio-blk attach (kernel_main.c) -- before genesis mint
* has happened on a fresh artemis.img, so it finds no marker yet and
* leaves the flag 0. Nothing re-triggers it after genesis mint
* completes. Silent result: capsule_wirebind_try_attach()'s own
* `if (!mama_vm->zuse_root_pubkey_known) return;` gate (this file's
* sibling function) then refuses every identity attach for the rest
* of the boot, with no message at all -- exactly the failure mode
* FABRIC-3.5.md SXXXV.0 names. Fixed at the source: the pubkey this
* function was just handed (from genesis mint, above, or from an
* already-Zuse re-attach, below) IS the root pubkey -- activate it
* directly here instead of relying on a disk re-read that may never
* happen this session. Matches vm_zuse_cert_install()'s own one-way
* idempotence (harmless to set twice). */
memcpy(mama_vm->zuse_root_pubkey, pubkey, 32);
mama_vm->zuse_root_pubkey_known = 1;
/* zuse.4th's ACL-ZUSE-BOOT self-activated once already at Mama's own
* birth, when no cert was installed yet (the thumbdrive wasn't
* attached at that early, one-shot point) -- ACL-PIN only blocks
* *redefinition*, not re-execution, so re-running the same policy
* word here is the correct, already-designed way to activate
* zuse_session now that a cert genuinely exists. No new C-side auth
* logic; policy stays in ACL.4th/zuse.4th per this project's own
* convention. */
vm_interpret(mama_vm, "ACL-ZUSE-BOOT");
g_zuse_attached_this_device = 1;
g_zuse_attached_dev = dev;
/* Decided 2026-09-05: no console for the running system unless a
* thumbdrive is present. Zuse's own login is not special here --
* "nothing special about zuse as a user except zuse has no ACLs,"
* per direct instruction. Revised 2026-09-06: no longer calls
* sk_console_mark_login() (a one-way sticky flag) -- the gate is now a
* live check (sk_console_identity_present(), repl.c) driven directly
* by mama_vm->zuse_session, which vm_interpret(mama_vm,
* "ACL-ZUSE-BOOT") above already sets. Nothing to call here anymore. */
}
void capsule_zuse_boot_try_attach(struct blkio_dev *dev,
homeblocks_sig_result_t sig_rc,
const homeblocks_sig_t *sig,
VM *mama_vm) {
if (!dev || !mama_vm) return;
/* FABRIC-2.md §I.8, re-scoped 2026-09-04: gate on zuse_session, not
* zuse_cert_installed. zuse_cert_installed never clears (one-way,
* see install_and_activate()'s own comment) and would permanently
* block re-authentication after a logout; zuse_session does clear
* (capsule_zuse_boot_logout()), which is exactly the "already have
* Zuse THIS SESSION" check this early-return is actually for. */
if (mama_vm->zuse_session) return;
zuse_genesis_marker_t marker;
int have_marker = (genesis_marker_read(&marker) == 0);
if (!have_marker) {
if (sig_rc != HOMEBLOCKS_SIG_BLANK) return; /* not eligible for genesis */
uint8_t seed[32], pubkey[32];
MintResult r = capsule_mint_identity(dev, (VM *)0, "Zuse", "zuse",
(const char *)0, (const char *)0,
pubkey, seed,
MINT_PERSONALITY_DEFAULT, /* Zuse is the superuser -- never restricted */
1 /* sig_rc already confirmed BLANK above */);
if (r != MINT_OK) {
console_println("Zuse: genesis mint failed");
return;
}
zuse_genesis_marker_t wm;
memset(&wm, 0, sizeof(wm));
wm.magic = ZUSE_GENESIS_MARKER_MAGIC;
wm.version = ZUSE_GENESIS_MARKER_VERSION;
memcpy(wm.zuse_pubkey, pubkey, 32);
wm.crc = compute_crc64((const uint8_t *)&wm, offsetof(zuse_genesis_marker_t, crc));
if (blk_meta_zone_write(0, (const uint8_t *)&wm) != 0) {
console_println("Zuse: genesis minted but fence marker write FAILED (not persistent)");
} else {
console_println("Zuse: genesis minted onto attached thumbdrive");
}
install_and_activate(mama_vm, dev, seed, pubkey);
return;
}
/* Marker present: genesis already happened, on some thumbdrive.
* Only act if THIS attach is that drive. */
if (sig_rc != HOMEBLOCKS_SIG_OK || !sig) return;
if (sig->identity_src_offset == 0 || sig->identity_src_devblocks < 1) return;
user_identity_seed_t idrec;
if (read_devblock(dev, sig->identity_src_offset, (uint8_t *)&idrec) != 0) return;
/* Same magic -> version -> CRC-64 discipline as genesis_marker_read():
* this record carries Zuse's private key (the seed), so a corrupt or
* format-mismatched record must be refused, never loaded -- a bad CRC
* could otherwise install a garbage seed as Zuse's identity. */
if (idrec.magic != USER_IDENTITY_SEED_MAGIC) return;
if (idrec.version != USER_IDENTITY_SEED_VERSION) return;
uint64_t want_crc = compute_crc64((const uint8_t *)&idrec,
offsetof(user_identity_seed_t, crc));
if (want_crc != idrec.crc) return;
if (memcmp(idrec.pubkey, marker.zuse_pubkey, 32) != 0) return; /* not Zuse's drive */
console_println("Zuse: identity confirmed from attached thumbdrive");
install_and_activate(mama_vm, dev, idrec.seed, idrec.pubkey);
}
void capsule_zuse_boot_logout(VM *mama_vm, struct blkio_dev *dev) {
if (!mama_vm || !g_zuse_attached_this_device) return;
/* The device actually detaching must be hers -- see g_zuse_attached_dev's
* own doc comment above. A different device (a WIREBIND target,
* general-purpose USB use) detaching while her own drive stays
* attached must not touch her session at all. */
if (dev != g_zuse_attached_dev) return;
mama_vm->zuse_session = 0;
g_zuse_attached_this_device = 0;
g_zuse_attached_dev = (struct blkio_dev *) 0;
console_println("Zuse: session ended -- reattach to re-authenticate");
}
struct blkio_dev *capsule_zuse_boot_attached_dev(void) {
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;
}