/* 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. */ /** * vm_identity.h - Per-VM owner identity + ACL capabilities (FABRIC-3.md * §F.2/§F.16, decided 2026-08-27/28) * * Holds only what a VM needs to prove *who owns it* and *what that owner * is allowed to do* -- never a private key. A regular VM's lock never * signs anything itself, so no seed/private material belongs here at all * (unlike Zuse's own zuse_cert_seed/zuse_cert_pubkey pair, which does need * one because she actively signs). Deliberately its own header rather * than inline fields on struct VM, mirroring VMUuid's own precedent * (vm_uuid.h) -- standing instruction: give real-shaped data its own * header and integrate as a field, don't grow struct VM ad hoc. * * acl_caps is a capability bitmask, not an ordered privilege tier * (decided 2026-08-28) -- independent bits, not a nested hierarchy. Zuse * is not a structurally special VM: her identity just has every bit set. * No bit values are assigned yet -- deliberate slack, per this project's * "flexibility until we understand the recipe" precedent (see * blk_meta_t's own acl_reserved bytes, FABRIC-3.md §F.4) -- real bits get * names only once the operation they gate actually gets built (BINDSTEP, * MINT, ...), not speculatively here. */ #ifndef STARKERNEL_VM_IDENTITY_H #define STARKERNEL_VM_IDENTITY_H #ifdef __STARKERNEL__ #include #include typedef struct { uint8_t owner_pubkey[32]; /**< Ed25519 public key of this VM's owning * identity. Meaningless unless installed * is set. */ uint8_t installed; /**< 0 = no identity installed yet (e.g. * Hera/Hermes/Artemis today, before * D.5's per-VM-identity work lands) -- * BINDSTEP-style checks must treat this * as "no lock, allow freely," matching * §F.9 decision 2. 1 = owner_pubkey/ * acl_caps are real. */ uint32_t acl_caps; /**< Capability bitmask. All-zero until a * real caller defines and checks a bit; * VM_IDENTITY_CAP_ALL for Zuse's own * identity ("her ACL just grants * everything," not a special VM type). */ } VMIdentity; /** Every capability bit set -- Zuse's own identity uses this, not a * distinct "is this Zuse" flag anywhere else in the system. */ #define VM_IDENTITY_CAP_ALL 0xFFFFFFFFu /** * vm_identity_has_cap - Check whether an installed identity holds a * capability. Returns 0 (denied) if identity isn't installed at all -- * callers that mean "no lock, allow freely" (§F.9 decision 2) must check * installed themselves first, not call this and treat 0 as a denial in * that case. * * @param id Identity to check. * @param cap A single capability bit (or bits) to test for. * @return Non-zero if id is installed and every bit in cap is set. */ int vm_identity_has_cap(const VMIdentity *id, uint32_t cap); /** * vm_identity_from_cert - CERTVERIFY (FABRIC-3.md §F.7/§F.17): verify a * DER-encoded, Zuse-signed X.509 cert and populate a VMIdentity from it. * * Three checks, all must pass: the cert's own signature verifies against * issuer_pubkey (Zuse's own on-device key -- a separate trust root from * the capsule-PKI chain, no chain walk needed); the cert's serialNumber * equals drive_uuid byte-for-byte (binds this cert to one physical drive, * §F.7 decision 2 -- a copied cert on different media will not verify); * the subject's Ed25519 public key extracts cleanly. * * acl_caps is *not* read from the cert -- nothing in the decided cert * fields encodes capabilities (§F.16). It's supplied by the caller, whose * job it is to decide what this verified identity is allowed to do (e.g. * comparing the extracted pubkey against Zuse's own system-resident * pubkey to decide VM_IDENTITY_CAP_ALL vs. a lesser default) -- that * policy decision doesn't belong inside a pure verification function. * * @param out Populated on success; left untouched on failure. * @param der DER-encoded certificate bytes. * @param der_len Their length. * @param issuer_pubkey Zuse's own Ed25519 public key. * @param drive_uuid This physical drive's own 16-byte drive_uuid * (homeblocks_sig_t), compared against the cert's * serialNumber. * @param acl_caps Capability bitmask to install, caller-decided. * @return 0 on success, -1 if any check fails (malformed DER, wrong * signature algorithm, signature doesn't verify, serial mismatch, * or the extracted key isn't a valid Ed25519 point). */ int vm_identity_from_cert(VMIdentity *out, const uint8_t *der, size_t der_len, const uint8_t issuer_pubkey[32], const uint8_t drive_uuid[16], uint32_t acl_caps); #endif /* __STARKERNEL__ */ #endif /* STARKERNEL_VM_IDENTITY_H */