Skip to content

What varve needs from wsc to go keyless at v1.0 — a consolidated ask, with what 0.11.0 already solved #268

Description

@avrabe

varve is deciding, for its v1.0 trust-root ceremony, whether to keep a file-based ed25519 root or move to keyless signing over wsc. This is the consolidated version of what that would require, replacing the scattered asks in #256#260.

First: credit where it is due. #257 is closed and 0.11.0 changed the picture materially. I re-read the source today rather than trusting my earlier notes, and src/airgapped/verifier.rs is no longer the stub it was in 0.10.0 — 1241 lines performing certificate-chain validation to a bundle Fulcio root, leaf validity at Rekor's integrated_time with codeSigning EKU, mandatory Rekor SET verification, ECDSA P-256 over the digest via the SEC1 point in the SPKI BIT STRING, revocation and identity checks — and the Rekor body binding (#135 UCA-2) verified offline. The # Not verified offline doc block is exactly the right way to ship this: it names the Merkle inclusion gap and the SCT gap and explains why each is skipped rather than leaving a reader to discover it. A previous decision on our side (DD-026) partly rested on that verifier being a stub. That premise is now wrong and we are correcting it.

Why varve cares about the answer

varve distributes signed toolchain layers. Its current root is a long-lived ed25519 key that lives in CI and signs every deposit. We just documented (varve#110) that this key exists only as a write-only GitHub Actions secret: it cannot be backed up, cannot be moved to another repository, and cannot be recovered if lost — and varve has no rotation and no revocation, so losing it ends the realm.

Keyless is attractive to us for exactly one reason, and it is worth being precise about it: it takes the long-lived secret out of CI. We are not under the illusion that it removes long-lived keys. Your own doc comment is explicit:

The bundle is signed with a long-lived offline key. Devices verify the signature against a pre-provisioned public key before using.

That is fine. A bundle-signing key is used rarely, changes rarely, and can be held under a real ceremony — offline, split custody, paper backup, annual read test. A per-deposit CI key cannot. The question is not "keys or no keys", it is which key has to be online.

What we would need

1. Signing over an arbitrary 32-byte digest (#256) — the blocker

varve signs DSSE-wrapped layer manifests, which are JSON, not WASM modules. The verify side already looks digest-shaped (verify_signature(&self, signature: &KeylessSignature, module_hash: &[u8; 32], …)), which is encouraging. What we need is the signing half to accept a caller-supplied digest with no assumption that the bytes behind it are a component.

If the parameter genuinely is just "a 32-byte hash", renaming it away from module_hash in the public API would help — the name currently implies a constraint that may not exist, and we would rather not guess.

2. A cosign-bundle adapter (#260)

Every PulseEngine repo publishes a cosign-signed SHA256SUMS.txt, and varve already ingests releases on that basis. Being able to turn an existing cosign bundle into a KeylessSignature would let us verify what we already ingest through one code path instead of two.

3. The trust bundle's own distribution story

This is the part we most want your opinion on rather than a feature. If consumers must pin a bundle-verification key, then that key is the ceremony subject, and its rotation story is the one that matters. Specifically:

  • Is there an intended path for rotating the bundle-signing key, or for a new bundle to be verified against the old one?
  • Is SignedTrustBundle expected to be distributed in-band with artifacts, or provisioned out-of-band per device?
  • src/airgapped/tuf.rs fetches trusted_root.json over HTTPS from a raw.githubusercontent URL and parses it. That is a fetch, not TUF — there is no root.json signature chain, no threshold, no snapshot/timestamp metadata verification. Is TUF metadata verification intended to land, or is the signed bundle deliberately the trust anchor instead? Either answer is workable; we just need to know which, because our documentation has to describe it honestly to people making custody decisions.

4. #258 — the air-gapped e2e test that cannot fail

Still open, and worth prioritising above the features above. A test that never calls verify_signature reports green whatever the verifier does, and the verifier is now substantial enough that a vacuous test around it is actively misleading. We hit this class often enough in our own repo to have a name for it; we would trust the 0.11.0 verifier considerably more with a negative control proving that test goes red.

5. #259 — one Rekor log embedded, two live

Relevant to us because a signature from the non-embedded log would fail to verify offline for reasons that look nothing like the actual cause.

Hardware, since it is adjacent

We noticed HardwareSigner with tpm2 / sgx / trustzone / secure_element backends, and that sigil ships a wsc-linux-x86_64-tpm2 binary. If the v1.0 answer turns out to be "a long-lived bundle key held properly" rather than "no long-lived key", a hardware-backed signer is the natural home for it.

There is no PKCS#11 backend, which is the usual route to a YubiKey. Is that a deliberate scope decision, or simply unbuilt? Not asking for it yet — asking whether to plan around it existing.

What we are not asking for

We are not asking wsc to solve varve's custody problem. We are asking for enough surface and enough honesty about the trust model to let us decide where our long-lived key should live, and to describe that decision truthfully to people who will pin it for years. The # Not verified offline block in verifier.rs is precisely the standard we are hoping to hold ourselves to.

Happy to take any of this as a PR rather than a request if it helps — say which.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions