Files
LithosAnanke/kernel/include/starkernel/capsule_zuse_boot.h
T
Claude bfe3506aec wip(kernel): the proxy Zuse -- a stick's first boot mints its own Zuse (#92, Task 1) [skip ci]
Work in progress on StarForth-v4.0.0; not yet accepted (plan
2026-10-29-stick-5, Task 1).

- zuse_genesis_marker.h: the marker's version 2 -- the proxy's key and the
  real Zuse's -- beside version 1.
- capsule_zuse_boot.c: capsule_zuse_boot_check_key() (the identity-record
  half of the check) and capsule_zuse_boot_genesis_mint() (the mint half of
  v3's genesis) split out; v3's two callers unchanged in behaviour.
- sk_v4_marker.c: the v4 boot reads version 1 as a proxy with no real Zuse,
  and writes version 2.
- sk_v4_identity.c: no marker and a blank identity partition -> genesis:
  mint, read back, then the marker; the proxy logs in. A marker with a real
  key: no session for the proxy (the fixed screen is Task 5).
- qemu_session.py: boot()/shutdown(), so a mode can boot twice; modes
  genesis and stick_genesis; stick_boot now expects genesis and the prompt.

Logs: genesis on amd64 before the change (both boots: "no genesis on this
disk", FAIL) and after (minted, then recognised: PASS). The DoE CSV of
032532 is from a run whose QEMU never started (no display; its empty log
directory was removed).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GE3SDvQn5EoxdGufk84zz2
2026-11-08 03:43:33 +00:00

181 lines
8.5 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
*/
/**
* 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;
/** What a just-attached drive is to Zuse (capsule_zuse_boot_check()). */
typedef enum {
ZUSE_DRIVE_NOT_HERS = 0, /* another identity's, foreign, corrupt, or no genesis and not blank */
ZUSE_DRIVE_HERS, /* the genesis marker's drive: its identity record checks out */
ZUSE_DRIVE_GENESIS /* no genesis marker yet, and the drive is blank: eligible */
} zuse_drive_t;
/**
* capsule_zuse_boot_check - The check capsule_zuse_boot_try_attach() makes,
* with no VM: the v3 path and the v4 boot both use it
* (docs/v4.0.0/plans/2026-10-26-engine-step4-identity-gate.md, D1).
* Reads the genesis marker from the block subsystem's metadata fence and,
* when there is one, the drive's own identity record (magic, version,
* CRC-64, public key against the marker's). Writes nothing.
*
* @param seed, pubkey Zuse's seed and public key, filled in only for
* ZUSE_DRIVE_HERS.
*/
zuse_drive_t capsule_zuse_boot_check(struct blkio_dev *dev,
homeblocks_sig_result_t sig_rc,
const homeblocks_sig_t *sig,
uint8_t seed[32], uint8_t pubkey[32]);
/**
* capsule_zuse_boot_check_key - The identity-record half of
* capsule_zuse_boot_check(): the drive's identity record (magic, version,
* CRC-64) and its public key against @p want, with no marker read
* (plan 2026-10-29-stick-5, Task 1: the v4 boot checks against either of the
* version 2 marker's keys). ZUSE_DRIVE_HERS, with @p seed and @p pubkey
* filled in, or ZUSE_DRIVE_NOT_HERS. Writes nothing.
*/
zuse_drive_t capsule_zuse_boot_check_key(struct blkio_dev *dev,
homeblocks_sig_result_t sig_rc,
const homeblocks_sig_t *sig,
const uint8_t want[32],
uint8_t seed[32], uint8_t pubkey[32]);
/**
* capsule_zuse_boot_genesis_mint - The mint half of v3's genesis, with no VM:
* Zuse's identity minted onto the blank drive @p dev (genesis mode,
* capsule_mint_identity()). Returns 0 with @p seed and @p pubkey filled in,
* or -1. Writes no marker: each caller writes its own.
*/
int capsule_zuse_boot_genesis_mint(struct blkio_dev *dev, uint8_t seed[32], uint8_t pubkey[32]);
/**
* capsule_zuse_boot_root_pubkey - Zuse's public key from the genesis
* marker. Returns 0 with @p pubkey filled in, or -1 (no genesis yet, or the
* marker fails its checks; @p pubkey untouched).
*/
int capsule_zuse_boot_root_pubkey(uint8_t pubkey[32]);
/**
* 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 */