Skip to content

ca2a start cannot turn on mutual attestation or a caller verifier #160

Description

@Susanpdl

Problem statement

PeerNode grew the mutual-attestation knobs in #89 and #90: require_caller_attestation (the none / any / hardware ladder), caller_verifier, and challenge_ttl_seconds. None of them are reachable from ca2a start. Ca2aConfig has no fields for them, bootstrap.build_peer_node never passes them, and docs/configuration.md does not mention them.

So the protocol is only usable from Python. Anyone running the reference transport through the CLI gets a callee that never appraises its callers and cannot be told to. LIMITATIONS.md describes mutual attestation as "off by default"; through ca2a start it is off with no switch. That also means the hardware verifier seam, the thing #47 section 3 needs a callee to exercise on a confidential VM, cannot be driven from a config file.

I added ca2a start in #52, so this is a gap in my own work.

Proposed solution

Extend the attestation block of the config and thread it through bootstrap:

attestation:
  provider: tpm
  require_caller_attestation: hardware   # none (default) | any | hardware
  caller_verifier:
    platform: tpm
    trusted_roots_path: vtpm-roots.pem   # resolved relative to the config file
  challenge_ttl_seconds: 60

Behaviour, all fail-closed and mirroring what PeerNode already enforces:

  • require_caller_attestation is validated against peer.REQUIREMENT_VALUES; anything else is a CONFIG_ERROR.
  • hardware without caller_verifier is a startup error, not a per-call refusal. PeerNode already does this; the config layer should surface it with the field name.
  • caller_verifier.platform: tpm builds ca2a_verify.tpm.tpm_verifier(roots_pem) from the PEM file. Missing or empty file is a CONFIG_ERROR.
  • caller_verifier.platform: sev-snp or tdx is rejected with a message saying why: there is no AttestationReport-shaped verifier for either yet (verify_sev_snp_report and verify_tdx_quote exist, but they take raw bytes and a certificate chain, and the SNP collector deliberately drops the auxblob rather than guess at its format). Refusing is better than a config that looks like it appraises and does not.
  • challenge_ttl_seconds must be a positive integer.
  • ca2a start prints the requirement rung on startup alongside the provider, so an operator can see what the callee will demand.

require_holder_proof is deliberately left out. It defaults to on and turning it off is a downgrade with no attestation rationale; if a case for exposing it appears it can come separately.

Alternatives considered

  • Leave it library-only and document that. Rejected: ca2a start exists so that a config file is enough to run a peer, and the transport spec already lists it as implemented. A CLI that cannot reach half the protocol undercuts that.
  • Expose a generic caller_verifier: <dotted.path> import hook. Rejected: it turns a config file into code execution and hides which platforms actually have a working verifier.
  • Ship SNP and TDX report-level verifiers in the same change. Rejected for scope: that is real design work (KDS fetch or auxblob parsing for the VCEK chain, root pinning, measurement policy) and should be its own issue. This change should refuse those platforms clearly rather than block on them.

Security/TEE impact

Positive. It lets a config-driven callee demand caller attestation, which today it cannot. All new paths fail closed: unknown rung, missing verifier under hardware, unsupported verifier platform, unreadable roots file. No change to the wire format, the record hash, or what PeerNode accepts.

Spec alignment

No trace-spec change required. docs/spec/mutual-attestation.md already documents the ladder and the requirement that "hardware" without a verifier is refused at construction; this exposes it through the existing config surface. docs/configuration.md gets the new fields.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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