WIREBIND: real thumbdrive-attach call site, no manual steps
Assembles pieces already built and individually verified this session -- CERTVERIFY (vm_identity_from_cert(), Phase A/B), RUNCAP, the console-VM + user-VM pair (§F.22) -- into one automatic sequence, replacing the RUNCAP-TEST/PAIR-TEST diagnostic words that exercised each piece by hand. New capsule_wirebind_try_attach() (capsule_wirebind.h/.c), called from sk_repl_idle() alongside capsule_zuse_boot_try_attach() on every HOMEBLOCKS_SIG_OK attach: sig->cert_offset==0 means this is Zuse's own genesis-mode drive (no cert region) -- that's already capsule_zuse_boot_try_attach()'s job, skip. Otherwise, with Zuse already authenticated this boot (nothing to verify a regular cert against otherwise), reads the cert devblock(s) and calls vm_identity_from_cert() against mama_vm's own zuse_cert_pubkey and the drive's own drive_uuid. On success: reads the drive's own user_identity_seed_t for its username, births a console VM + RUNCAP-born user VM pair (idempotent -- no-ops if that username is already live this session), installs the verified VMIdentity onto the user VM, and registers the "<username>~user" pairing sk_repl_dispatch_line() (repl.c, §F.22) looks for. Deliberately does NOT auto-USE the new console -- that stays an explicit, ACL-gated step (BINDSTEP, §F.9), not something a bare attach should trigger silently. Verified end-to-end live in QEMU, including a genuine negative case: attached disk/user1.img (signed by a different, earlier-session Zuse instance) and got a correct "cert verification FAILED -- drive refused" -- proof the check is real, not a rubber stamp. Minted a fresh identity with this boot's own Zuse, reattached, and got "WIREBIND: SamS attached and ready" printed with zero manual commands, followed by a working USE + async WELCOME relay end to end (queued, no UNKNOWN WORD, delivered and executed in the paired user VM on the next idle tick). Clean 3-architecture regression: Hermes/Artemis both birth live, no unexpected ACL denials or UNKNOWN WORD. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019ZGkimpfyh63EZyRkNbkPD
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
c9cf9b09d9
commit
6fc0ee33a9
@@ -1,5 +1,5 @@
|
||||
# Capsule Block Manifest — Auto-generated
|
||||
<!-- Generated by mkcapsule --manifest 2026-08-28T20:37:43Z -->
|
||||
<!-- Generated by mkcapsule --manifest 2026-08-28T20:55:57Z -->
|
||||
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
||||
<!-- Hand-written justifications and immutability notes live -->
|
||||
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
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_wirebind.h - WIREBIND: the real thumbdrive-attach call site
|
||||
* (FABRIC-3.md §F.5/§F.23). Assembles pieces already built and
|
||||
* individually verified this session -- CERTVERIFY (vm_identity.h's
|
||||
* vm_identity_from_cert()), RUNCAP (capsule_runcap.h), the console-VM +
|
||||
* user-VM pair (capsule_console.h, sk_repl_dispatch_line() in repl.c) --
|
||||
* into one automatic sequence, replacing the RUNCAP-TEST/PAIR-TEST
|
||||
* diagnostic words that exercised each piece by hand.
|
||||
*/
|
||||
|
||||
#ifndef STARKERNEL_CAPSULE_WIREBIND_H
|
||||
#define STARKERNEL_CAPSULE_WIREBIND_H
|
||||
|
||||
#ifdef __STARKERNEL__
|
||||
|
||||
#include "starkernel/homeblocks_sig.h"
|
||||
#include "vm.h"
|
||||
|
||||
struct blkio_dev;
|
||||
|
||||
/**
|
||||
* capsule_wirebind_try_attach - Try to verify and bind a just-attached
|
||||
* regular (non-Zuse) identity drive.
|
||||
*
|
||||
* No-op if sig->cert_offset is 0 (a genesis-mode Zuse drive has no cert
|
||||
* region -- that's capsule_zuse_boot_try_attach()'s own job, not this
|
||||
* one's) or if mama_vm has no installed Zuse cert yet (nothing to verify
|
||||
* the attached cert against). Otherwise: reads the cert devblock(s),
|
||||
* calls vm_identity_from_cert() against mama_vm's own zuse_cert_pubkey
|
||||
* and sig->drive_uuid. On success, reads the drive's own
|
||||
* user_identity_seed_t for its username and births a console VM +
|
||||
* RUNCAP-born user VM pair (idempotent -- no-ops if that username is
|
||||
* already live this session), installs the verified VMIdentity onto the
|
||||
* user VM, and registers the "<username>~user" pairing
|
||||
* (sk_repl_dispatch_line(), repl.c, looks for this). Does NOT USE the
|
||||
* new console automatically -- that stays an explicit, later,
|
||||
* ACL-gated step (BINDSTEP, §F.9), not something a bare attach should
|
||||
* trigger silently.
|
||||
*
|
||||
* @param dev The just-attached, already-open block device.
|
||||
* @param sig Its already-checked homeblocks_sig_t.
|
||||
* @param mama_vm Hera's own VM (the verifier -- her zuse_cert_pubkey is
|
||||
* the trust root regular user certs are checked against).
|
||||
*/
|
||||
void capsule_wirebind_try_attach(struct blkio_dev *dev,
|
||||
const homeblocks_sig_t *sig,
|
||||
VM *mama_vm);
|
||||
|
||||
#endif /* __STARKERNEL__ */
|
||||
|
||||
#endif /* STARKERNEL_CAPSULE_WIREBIND_H */
|
||||
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
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
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_wirebind.c is kernel-only"
|
||||
#endif
|
||||
|
||||
#include "starkernel/capsule_wirebind.h"
|
||||
#include "starkernel/capsule_birth.h"
|
||||
#include "starkernel/capsule_runcap.h"
|
||||
#include "starkernel/capsule_console.h"
|
||||
#include "starkernel/vm_identity.h"
|
||||
#include "starkernel/user_identity_seed.h"
|
||||
#include "starkernel/console.h"
|
||||
#include "blkio.h"
|
||||
#include "freestanding/stdio.h"
|
||||
#include <string.h>
|
||||
|
||||
/* WIREBIND_CERT_MAX_DEVBLOCKS: a sane upper bound on how much cert
|
||||
* content this reads, independent of whatever sig->cert_devblocks
|
||||
* claims -- MINT (capsule_mint.c) only ever writes 1 devblock's worth
|
||||
* (a real cert is ~150-250 bytes), so 4 devblocks (16KB) is already
|
||||
* generous headroom, not a real constraint. */
|
||||
#define WIREBIND_CERT_MAX_DEVBLOCKS 4u
|
||||
|
||||
/* Read exactly one devblock (4096 bytes) at devblock offset `devblock`
|
||||
* -- same convention capsule_runcap.c/capsule_mint.c already use. */
|
||||
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;
|
||||
}
|
||||
|
||||
void capsule_wirebind_try_attach(struct blkio_dev *dev,
|
||||
const homeblocks_sig_t *sig,
|
||||
VM *mama_vm) {
|
||||
if (!dev || !sig || !mama_vm) return;
|
||||
|
||||
/* Genesis-mode Zuse drives have no cert region -- capsule_zuse_boot_
|
||||
* try_attach() already owns that case. */
|
||||
if (sig->cert_offset == 0 || sig->cert_devblocks == 0) return;
|
||||
|
||||
/* Nothing to verify a regular cert against until Zuse herself has
|
||||
* authenticated this boot. */
|
||||
if (!mama_vm->zuse_cert_installed) return;
|
||||
|
||||
/* Read the cert region into a local buffer. */
|
||||
uint32_t n_devblocks = sig->cert_devblocks;
|
||||
if (n_devblocks > WIREBIND_CERT_MAX_DEVBLOCKS) n_devblocks = WIREBIND_CERT_MAX_DEVBLOCKS;
|
||||
uint8_t cert_der[WIREBIND_CERT_MAX_DEVBLOCKS * 4096];
|
||||
for (uint32_t d = 0; d < n_devblocks; d++) {
|
||||
if (read_devblock(dev, sig->cert_offset + d, cert_der + (size_t)d * 4096) != 0) {
|
||||
console_println("WIREBIND: cert read failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
size_t cert_len = (size_t)n_devblocks * 4096;
|
||||
|
||||
VMIdentity identity;
|
||||
memset(&identity, 0, sizeof(identity));
|
||||
if (vm_identity_from_cert(&identity, cert_der, cert_len,
|
||||
mama_vm->zuse_cert_pubkey, sig->drive_uuid,
|
||||
0 /* acl_caps: no bits assigned yet, §F.2 */) != 0) {
|
||||
console_println("WIREBIND: cert verification FAILED -- drive refused");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Verified. Read the drive's own profile for its username. */
|
||||
if (sig->identity_src_offset == 0 || sig->identity_src_devblocks < 1) {
|
||||
console_println("WIREBIND: verified cert but no identity_src region -- refusing");
|
||||
return;
|
||||
}
|
||||
user_identity_seed_t idrec;
|
||||
if (read_devblock(dev, sig->identity_src_offset, (uint8_t *)&idrec) != 0 ||
|
||||
idrec.magic != USER_IDENTITY_SEED_MAGIC) {
|
||||
console_println("WIREBIND: verified cert but identity record unreadable -- refusing");
|
||||
return;
|
||||
}
|
||||
|
||||
char username[USER_IDENTITY_USERNAME_MAX];
|
||||
memcpy(username, idrec.username, sizeof(username));
|
||||
username[sizeof(username) - 1] = '\0'; /* defensive; MINT already NUL-terminates */
|
||||
|
||||
char user_vm_name[USER_IDENTITY_USERNAME_MAX + 8];
|
||||
size_t ulen = strlen(username);
|
||||
if (ulen == 0 || ulen + 6 > sizeof(user_vm_name)) {
|
||||
console_println("WIREBIND: empty or oversized username -- refusing");
|
||||
return;
|
||||
}
|
||||
memcpy(user_vm_name, username, ulen);
|
||||
memcpy(user_vm_name + ulen, "~user", 6);
|
||||
|
||||
/* Idempotent: already bound this session (console VM already live
|
||||
* under this username) -- nothing to do. Matches BIRTH's own
|
||||
* idempotent convention. */
|
||||
{
|
||||
VMRegistryEntry existing;
|
||||
if (capsule_vm_find_by_name(username, &existing) == 0 &&
|
||||
existing.state == VM_STATE_LIVE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
VMUuid console_id, user_id;
|
||||
void *console_ctx = (void *)0;
|
||||
void *user_ctx = (void *)0;
|
||||
if (capsule_console_birth(username, &console_id, &console_ctx) != CAPSULE_RUN_OK) {
|
||||
console_println("WIREBIND: console VM birth FAILED");
|
||||
return;
|
||||
}
|
||||
if (capsule_runcap_birth(dev, sig, user_vm_name, &user_id, &user_ctx) != CAPSULE_RUN_OK) {
|
||||
console_println("WIREBIND: user VM birth FAILED");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Install the verified identity onto the user VM -- the one BINDSTEP
|
||||
* (§F.9) will later re-verify against on every USE. */
|
||||
if (user_ctx) {
|
||||
((VM *)user_ctx)->identity = identity;
|
||||
}
|
||||
|
||||
/* Register the pairing in the console's own routing table, index 3
|
||||
* -- the fixed convention sk_repl_dispatch_line() (repl.c) uses. */
|
||||
{
|
||||
char reg_cmd[sizeof(user_vm_name) + 32];
|
||||
int n = snprintf(reg_cmd, sizeof(reg_cmd), "S\" %s\" 3 VM-NAME-REG", user_vm_name);
|
||||
if (n > 0 && (size_t)n < sizeof(reg_cmd)) {
|
||||
vm_interpret((VM *)console_ctx, reg_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
console_puts("WIREBIND: ");
|
||||
console_puts(username);
|
||||
console_println(" attached and ready -- USE it to begin");
|
||||
}
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "starkernel/homeblocks_sig.h"
|
||||
#include "starkernel/capsule_birth.h"
|
||||
#include "starkernel/capsule_zuse_boot.h"
|
||||
#include "starkernel/capsule_wirebind.h"
|
||||
#include "starkernel/capsule_run.h"
|
||||
#include "starkernel/vm/bootstrap/sk_vm_bootstrap.h"
|
||||
#include "block_subsystem.h"
|
||||
@@ -195,6 +196,18 @@ static void sk_repl_idle(VM *active_vm)
|
||||
* detect it). No-ops immediately if Zuse already has a real
|
||||
* identity this boot. */
|
||||
capsule_zuse_boot_try_attach(&usb_blk_dev, sig_rc, &sig, (VM *)sk_get_mama_vm());
|
||||
|
||||
/* FABRIC-3.md §F.5/§F.23 (WIREBIND): the real thumbdrive-
|
||||
* attach call site for a regular (non-Zuse) identity --
|
||||
* verify-then-birth-then-pair, replacing the RUNCAP-TEST/
|
||||
* PAIR-TEST diagnostic words that exercised each piece by
|
||||
* hand. Only meaningful for a drive that actually checked
|
||||
* out (HOMEBLOCKS_SIG_OK); capsule_wirebind_try_attach()
|
||||
* itself no-ops for a genesis-mode Zuse drive (no cert
|
||||
* region) or before Zuse has authenticated this boot. */
|
||||
if (sig_rc == HOMEBLOCKS_SIG_OK) {
|
||||
capsule_wirebind_try_attach(&usb_blk_dev, &sig, (VM *)sk_get_mama_vm());
|
||||
}
|
||||
}
|
||||
if (rc == 0 && blk_subsys_attach_device(&usb_blk_dev) == BLK_OK) {
|
||||
xdev->bot_msc_attached = 1;
|
||||
|
||||
Reference in New Issue
Block a user