Phase A of the identity pipeline (FABRIC-3.md §F.2/§F.16, §F.13):
- New include/starkernel/vm_identity.h: VMIdentity{owner_pubkey[32],
installed, acl_caps}, its own header per the project's "give real-shaped
data its own header" convention (VMUuid's own precedent), embedded by
value on struct VM. acl_caps is an independent capability bitmask, not
an ordered privilege tier (decided 2026-08-28) -- Zuse isn't a
structurally special VM, her identity just has every bit set
(VM_IDENTITY_CAP_ALL). No individual capability bits assigned yet,
deliberate slack matching blk_meta_t's own acl_reserved precedent --
real bits get names once the operation they gate (BINDSTEP, MINT, ...)
actually gets built.
- Applied the devblock-1 relocation decided in §F.13: new
HOMEBLOCKS_SIG_START_FBLOCK constant (homeblocks_sig.h), repl.c's
homeblocks_sig_check() call site updated from the literal 0. Also
applied the still-owed blockmap_offset/blockmap_devblocks ->
identity_src_offset/identity_src_devblocks rename decided in §F.6 (no
other code referenced the old names). Updated the header's own stale
GPT-relative doc comments to match -- GPT was dropped permanently, this
location is final, not an interim stand-in.
Verified live on all three architectures: clean compile, clean boot to
ok>, Hermes/Artemis both confirmed live with no KILL (no regression from
last session's session-less fix). One pre-existing, unrelated anomaly
observed consistently on all three arches, not caused by this change (no
code touched here intersects Zuse's own fence-write path): "Zuse: minted
but fence write FAILED (not persistent)" -- flagged for its own
investigation, not chased here.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019ZGkimpfyh63EZyRkNbkPD
196 lines
9.7 KiB
C
196 lines
9.7 KiB
C
/*
|
||
StarForth — Steady-State Virtual Machine Runtime
|
||
|
||
Copyright (c) 2023–2025 Robert A. James
|
||
All rights reserved.
|
||
|
||
This file is part of the StarForth project.
|
||
|
||
Licensed under the StarForth License, Version 1.0 (the "License");
|
||
you may not use this file except in compliance with the License.
|
||
|
||
You may obtain a copy of the License at:
|
||
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
|
||
|
||
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
express or implied, including but not limited to the warranties of
|
||
merchantability, fitness for a particular purpose, and noninfringement.
|
||
|
||
See the License for the specific language governing permissions and
|
||
limitations under the License.
|
||
*/
|
||
|
||
/**
|
||
* homeblocks_sig.h - Home-blocks drive signature format (FABRIC-3.md,
|
||
* Milestone 4, Phase 8 kickoff; relocated + GPT dropped §F.13/§F.8,
|
||
* 2026-08-28)
|
||
*
|
||
* Identifies and authenticates a physical thumb drive as a legitimate
|
||
* LithosAnanke home-blocks drive, before any write path touches it.
|
||
* Lives at forth-block HOMEBLOCKS_SIG_START_FBLOCK (devblock 1) of the raw
|
||
* device -- GPT partitioning was decided against permanently (§F.8): this
|
||
* is the real, final on-disk location, not an interim stand-in. Devblock 0
|
||
* is left alone for the block-subsystem's own generic 'STFR'/v2 volume
|
||
* header (block_subsystem.h) -- the two formats would otherwise collide
|
||
* (§F.13, found while scoping BMAPREAD).
|
||
*
|
||
* Mirrors two existing precedents exactly, not invented fresh:
|
||
* - CAPSULE_MAGIC_PACK's bit-packed magic (starkernel/capsule.h)
|
||
* - blk_volume_meta_t's magic+version+fields+pad-to-4096 structural
|
||
* convention (block_subsystem.h)
|
||
*
|
||
* Deliberately narrow in scope: this header identifies/authenticates the
|
||
* DRIVE only. It reserves offset/size pointers to where the cert
|
||
* (CERTVERIFY, §F.7) and this identity's own personality/init source
|
||
* (RUNCAP/MINT, §F.6/§F.8) attach, so this format doesn't need revisiting
|
||
* when those get built -- it does not itself decide their content.
|
||
*/
|
||
|
||
#ifndef STARKERNEL_HOMEBLOCKS_SIG_H
|
||
#define STARKERNEL_HOMEBLOCKS_SIG_H
|
||
|
||
#include <stdint.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/*===========================================================================
|
||
* Magic Field Packing -- same bit layout convention as CAPSULE_MAGIC_PACK
|
||
*
|
||
* bits 0..31 : 'LAHB' (0x4248414C little-endian) -- LithosAnanke Home Blocks
|
||
* bits 32..39 : version (0 for v0)
|
||
* bits 40..63 : reserved (zero)
|
||
*===========================================================================*/
|
||
|
||
#define HOMEBLOCKS_SIG_MAGIC 0x4248414CULL /* 'LAHB', same little-endian ASCII
|
||
* packing as CAPSULE_DESC_MAGIC's 'CAPS' */
|
||
#define HOMEBLOCKS_SIG_VERSION_0 0
|
||
|
||
#define HOMEBLOCKS_SIG_PACK(ver) \
|
||
(HOMEBLOCKS_SIG_MAGIC | ((uint64_t)(ver) << 32))
|
||
|
||
#define HOMEBLOCKS_SIG_GET_MAGIC(m) ((uint32_t)((m) & 0xFFFFFFFFULL))
|
||
#define HOMEBLOCKS_SIG_GET_VERSION(m) ((uint8_t)(((m) >> 32) & 0xFF))
|
||
|
||
/* Where this header actually lives on a home-blocks drive: forth-block 4
|
||
* (devblock 1), NOT devblock 0 -- FABRIC-3.md §F.13, decided 2026-08-28.
|
||
* Devblock 0 is reserved for the block-subsystem's own generic 'STFR'/v2
|
||
* volume header (block_subsystem.c); the two formats collide if both try
|
||
* to occupy devblock 0 of the same raw device. GPT is permanently dropped
|
||
* (§F.8) -- this is not an interim stand-in pending a GPT parser, it's the
|
||
* real, final location. */
|
||
#define HOMEBLOCKS_SIG_START_FBLOCK 4u
|
||
|
||
/*===========================================================================
|
||
* homeblocks_sig_t - drive signature header (exactly one 4KiB devblock)
|
||
*===========================================================================*/
|
||
|
||
typedef struct {
|
||
uint64_t magic; /* HOMEBLOCKS_SIG_PACK(...) */
|
||
uint8_t drive_uuid[16]; /* Unique per-mint instance id -- Phase 8 mints multiple
|
||
* distinct drives, needs something to tell them apart. */
|
||
uint64_t minted_time_ns; /* Monotonic timestamp at mint time. */
|
||
uint64_t metadata_devblocks; /* Size of the metadata region at the start of this raw
|
||
* device (sig header + cert + identity-source regions),
|
||
* in 4KiB devblocks -- everything past this is the owning
|
||
* identity's own general block-storage pool directly (§F.6
|
||
* decision 3), no partition boundary involved. */
|
||
|
||
uint32_t cert_offset; /* Devblock offset from this device's start where this
|
||
* identity's Zuse-signed cert blob starts (§F.7); 0 = not
|
||
* yet minted. */
|
||
uint32_t cert_devblocks; /* Size reserved for the cert blob, in devblocks. */
|
||
|
||
uint32_t identity_src_offset; /* Devblock offset where this identity's own record
|
||
* starts (RUNCAP/MINT, FABRIC-3.md §F.6/§F.8): first
|
||
* devblock is a user_identity_seed_t, remainder is raw
|
||
* FORTH personality/init source. Renamed from
|
||
* blockmap_offset -- BMAPFMT (§F.4) repurposed blk_meta_t
|
||
* instead of a centralized block-map, making the original
|
||
* field unnecessary; this reuses the same reserved bytes
|
||
* rather than adding new ones. 0 = not yet minted. */
|
||
uint32_t identity_src_devblocks; /* Size reserved for the identity record, in devblocks. */
|
||
|
||
uint64_t hdr_crc; /* REAL from day one, not a placeholder like
|
||
* blk_volume_meta_t's "unused yet" hdr_crc -- this header's
|
||
* whole job is gating a warn-and-refuse security check
|
||
* against blank/foreign/unrecognized media, so the crc has
|
||
* to actually work. Computed over every field above this
|
||
* one; callers must fill every other field before computing
|
||
* or verifying it. */
|
||
|
||
/* Padding to keep the header exactly one 4KiB devblock. */
|
||
uint8_t _pad[4096 - (
|
||
8 + /* magic */
|
||
16 + /* drive_uuid */
|
||
8 + /* minted_time_ns */
|
||
8 + /* metadata_devblocks */
|
||
4 + 4 + /* cert_offset, cert_devblocks */
|
||
4 + 4 + /* identity_src_offset, identity_src_devblocks */
|
||
8 /* hdr_crc */
|
||
)];
|
||
} homeblocks_sig_t;
|
||
|
||
/* C99-portable compile-time size assertion (no _Static_assert -- that's C11),
|
||
* same discipline stadium.h's own header-size checks already use. */
|
||
typedef char homeblocks_sig_size_check[(sizeof(homeblocks_sig_t) == 4096) ? 1 : -1];
|
||
|
||
/*===========================================================================
|
||
* Signature check (FABRIC-3.md, Milestone 4)
|
||
*===========================================================================*/
|
||
|
||
typedef enum {
|
||
HOMEBLOCKS_SIG_OK = 0, /* magic, version, and crc all check out */
|
||
HOMEBLOCKS_SIG_BLANK, /* magic does not match -- blank or foreign media */
|
||
HOMEBLOCKS_SIG_BAD_VERSION, /* magic matches, version unrecognized */
|
||
HOMEBLOCKS_SIG_BAD_CRC, /* magic+version match, crc fails -- corrupt or tampered */
|
||
HOMEBLOCKS_SIG_READ_ERROR /* could not read from the device at all */
|
||
} homeblocks_sig_result_t;
|
||
|
||
/* Forward-declared, not included here -- avoids a hard dependency from this
|
||
* small format header onto blkio.h's full device/vtable machinery for
|
||
* callers that only need the struct layout (e.g. a future minting tool). */
|
||
struct blkio_dev;
|
||
|
||
/*
|
||
* homeblocks_sig_check - Read and verify the drive signature header.
|
||
*
|
||
* Reads 4 consecutive 1KB "forth blocks" (dev->read()'s own unit) starting
|
||
* at sig_start_fblock into a local 4KB buffer and interprets it as a
|
||
* homeblocks_sig_t. Deliberately takes the starting block as a plain
|
||
* parameter rather than resolving it internally, even though every real
|
||
* caller now passes the same fixed HOMEBLOCKS_SIG_START_FBLOCK (GPT was
|
||
* dropped, §F.8) -- keeps this function's own job (verify a signature
|
||
* given a location) separate from callers deciding what that location is.
|
||
*
|
||
* @param dev Open block device to read from.
|
||
* @param sig_start_fblock First of 4 consecutive forth-blocks holding the
|
||
* 4KB header -- HOMEBLOCKS_SIG_START_FBLOCK for
|
||
* every real caller today.
|
||
* @param out_sig On HOMEBLOCKS_SIG_OK, populated with the verified
|
||
* header. Left unspecified on any other result.
|
||
* @return HOMEBLOCKS_SIG_OK, or the specific reason for refusal.
|
||
*/
|
||
homeblocks_sig_result_t homeblocks_sig_check(struct blkio_dev *dev,
|
||
uint32_t sig_start_fblock,
|
||
homeblocks_sig_t *out_sig);
|
||
|
||
/*
|
||
* homeblocks_sig_compute_crc - CRC-64 over every field of `sig` up to but
|
||
* not including hdr_crc itself and the trailing padding -- the same
|
||
* boundary homeblocks_sig_check() verifies against and any future minting
|
||
* code must use when writing a fresh header. Exposed publicly since both
|
||
* directions (check and future mint) need the identical computation.
|
||
*
|
||
* @param sig Header to checksum. hdr_crc and _pad are not read.
|
||
* @return The CRC-64 value that hdr_crc should hold for `sig` to verify.
|
||
*/
|
||
uint64_t homeblocks_sig_compute_crc(const homeblocks_sig_t *sig);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* STARKERNEL_HOMEBLOCKS_SIG_H */
|