Skip to content

stage1: dual sha256/ed25519 admission, signed args, fallback URLs; measure code only#11

Merged
HarryR merged 1 commit into
mainfrom
feat-stage2-ed25519
Jul 5, 2026
Merged

stage1: dual sha256/ed25519 admission, signed args, fallback URLs; measure code only#11
HarryR merged 1 commit into
mainfrom
feat-stage2-ed25519

Conversation

@HarryR

@HarryR HarryR commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Gives stage1 the same payload admission stage0 already has for the UKI, so a cloud instance can be deployed once with a pinned public key and updated by "re-sign the payload, reboot" — no reconfiguration.

What changed

  • Dual admission_stage2 accepts a pinned sha256 or an ed25519 release pubkey (detached <url>.sig), exactly one per arch. New crates/stage1/src/sig.rs ports stage0's verifier (ed25519-compact); the .sig is a byte-for-byte wire contract with stage0/mkuki.
  • Signed remote argsargs_url (+ args_sig_url, else <args_url>.sig): a signed JSON string-array verified against the same key, overriding inline args.
  • Fallback URLs — every URL field (url/sig_url/args_url/args_sig_url) takes a string or a list, tried in order (mirror resiliency); {sha256} is substituted in the sig/args URLs; non-2xx falls through to the next mirror.
  • Measure code only — PCR 14 = the stage2 binary hash, nothing else. extend_pcrs and the pre-exec attestation no longer bind the config JSON; PCR 15 is freed for the app. The admission pin/key/signature is a gate, never measured. This keeps the platform quote reproducible from boot artifacts alone and lets the app attest its own config.
  • Schemaschema/stage2.schema.json (JSON Schema 2020-12) for the _stage2 input format.
  • Tooling--make-config-ed25519; the Makefile chain test gains SIGN=1 (signs the UKI + stage2), SIGN_ARGS=1, and FALLBACK=1 knobs.

Verification

  • 15 unit tests: validate() table (exactly-one-of, https, coupling rules), UrlList string|list parse + serialize round-trip, {sha256} substitution, ed25519 sign/verify round-trip.
  • 4 end-to-end QEMU+KVM boots (stage0 → UKI → stage1 → example-stage2), all reaching a clean power-off: sha256 pin, ed25519 signature, signed remote args (applied as argv), and fallback (dead mirror skipped → real mirror served → verified).
  • Crate builds for x86_64 and aarch64 musl.

Note: schema/stage2.schema.json is hand-traced but not yet machine-validated in CI — a follow-up config tool (Rust, jsonschema + serde) will own creation/validation/modification of these docs and validate the schema.

🤖 Generated with Claude Code

…asure code only

Give stage1 the same payload admission stage0 has for the UKI, so a cloud instance
can be deployed once with a pinned public key and updated by "re-sign the payload,
reboot" — no reconfiguration.

- Admission: `_stage2` accepts either a pinned `sha256` or an `ed25519` release pubkey
  (detached `<url>.sig`), exactly one per arch. New `sig.rs` ports stage0's verifier
  (ed25519-compact); the .sig is a byte-for-byte wire contract with stage0/mkuki.
- Signed remote args: `args_url` (+ `args_sig_url`, else `<args_url>.sig`) — a signed
  JSON string array verified against the same key — overrides inline args.
- Fallback URLs: every URL field (`url`/`sig_url`/`args_url`/`args_sig_url`) accepts a
  string or a list, tried in order (mirror resiliency); `{sha256}` is substituted in the
  sig/args URLs. Non-2xx responses fall through to the next mirror.
- Measure code only: PCR 14 = stage2 binary hash, nothing else. `extend_pcrs` and the
  pre-exec attestation no longer bind the config JSON; PCR 15 is freed for the app.
  Admission (pin/key/signature) is a gate, never measured.
- JSON Schema for the `_stage2` input format (schema/stage2.schema.json).
- Tooling: `--make-config-ed25519`; the Makefile chain test gains SIGN=1 (signs the UKI
  and stage2), SIGN_ARGS=1, and FALLBACK=1 knobs.

Verified: 15 unit tests (validate() table, UrlList string|list, {sha256} substitution,
sign/verify round-trip) and 4 end-to-end QEMU boot modes (sha256, ed25519, signed args,
fallback) all pass; the crate builds for x86_64 and aarch64 musl.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@HarryR HarryR merged commit 089f602 into main Jul 5, 2026
4 checks passed
@HarryR HarryR deleted the feat-stage2-ed25519 branch July 5, 2026 06:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant