Files
StarForth/src/starkernel/capsule/capsule_zuse_boot.c
T
Robert Allan JamesandClaude Sonnet 5 60d9c2520e FABRIC-3.md §I.3/§I.8: WIREBIND EJECT/detach + EXPIRE re-scoped as logout
Closes §I.3 (Milestone 5 remainder): WIREBIND now tracks which VM is
attached via the home-blocks USB path, and a new EJECT word plus the
existing hot-unplug signal both flush/reset-console/kill through it
(FABRIC-3.md §F.10).

Closes §I.8 (EXPIRE/ACL), re-scoped: the original "admit the zuse
session as a Stadium patron and reap on TTL" plan was invalidated a
second time -- Zuse authenticates directly onto Hera, who is patron
zero and permanently pinned, so there is no patron for a reap sweep to
ever find. Built instead as a detach-triggered logout
(capsule_zuse_boot_logout()), the same trigger EJECT/hot-unplug use for
regular WIREBIND users, so neither identity is a special case. Required
a companion fix: install_and_activate() used to skip re-running
ACL-ZUSE-BOOT whenever the cert was already installed, which made a
logout permanent for the rest of the boot; the outer re-attach gate now
checks zuse_session (clears on logout) instead of zuse_cert_installed
(a deliberate permanent one-way ratchet, left untouched).

Verified 3-arch boot to ok> (amd64/aarch64/riscv64, each in the
foreground) after both steps; logs and DoE CSVs from this session's
verification runs included per this repo's own audit-artifact
convention.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
2026-09-04 09:21:01 -04:00

154 lines
6.8 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 §I.8 (re-scoped 2026-09-04): tracks whether the currently
* home-blocks-attached device is Zuse's own -- the single-USB-device
* constraint (§F.8) means capsule_zuse_boot_logout() only needs one flag,
* not a device/uuid comparison, to know a detach event is hers to act on
* (a regular WIREBIND user occupying the one slot instead is tracked
* separately, in capsule_wirebind.c -- the two paths never overlap). */
static int g_zuse_attached_this_device = 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, 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-3.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);
/* 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;
}
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-3.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,
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, 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, idrec.seed, idrec.pubkey);
}
void capsule_zuse_boot_logout(VM *mama_vm) {
if (!mama_vm || !g_zuse_attached_this_device) return;
mama_vm->zuse_session = 0;
g_zuse_attached_this_device = 0;
console_println("Zuse: session ended -- reattach to re-authenticate");
}