[Guardian] Verify Nitro enclave attestation + pin PCR0#666
Open
mskd12 wants to merge 11 commits into
Open
Conversation
…ey anchor) `verify_enclave_attestation` now actually verifies the AWS Nitro attestation via fastcrypto's `nitro_attestation` module instead of being a no-op: - parse + verify the COSE_Sign1 signature and the X.509 cert chain to the AWS Nitro root, freshness checked against now (ms). - anchor the document's `public_key` to the session signing pubkey — the enclave binds its signing key into the attestation. Gated behind `non-enclave-dev` (+ cfg(test)) so off-enclave/dev/e2e builds, which run a mock enclave, accept the stub document; the feature propagates from hashi-guardian's existing `non-enclave-dev`. Pins fastcrypto to the `nitro-attestation` branch. TODO(check C): pin the document's PCRs against an expected set. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`ExpectedPcrs` mandates PCR0 at construction (`ExpectedPcrs::new`), and is threaded from config to `verify_enclave_attestation`, which pins the attestation's PCR0 (the EIF image hash) after the COSE/cert/pubkey checks: - source -> sink: an `expected_pcr0` config field -> `GuardianReader::new` -> `GuardianSessionKeyCache` -> `get_verified_enclave_pubkey`, plus `GetGuardianInfoResponse::verify(&ExpectedPcrs)` for the relay path. - Both the provisioner (`ProvisionerConfig`) and the monitor auditor (`hashi-monitor` `Config`) supply `expected_pcr0`; sample YAMLs + README updated. A single mandatory PCR0 for now; accepting multiple measurements during a software upgrade is a follow-up (TODO on `ExpectedPcrs`). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
0e8ac5e to
293abf5
Compare
- Drop needless `return` in verify_enclave_attestation dev stub (clippy). - Add expected_pcr0 to the two hashi-monitor test Config literals. - Commit the hex Cargo.lock entry for hashi-monitor (docs is-dirty). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…attestation-verify # Conflicts: # crates/hashi-guardian-init/src/provisioner.rs
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A build's measurement set is the durable concept; the future commit->PCRs allowlist will be a separate type keyed on untrusted_git_revision. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The AWS Nitro attestation module (fastcrypto #971) merged to main, so pin to main HEAD instead of the nitro-attestation branch tip. Drop the now-stale no-op TODO on get_verified_enclave_pubkey: it takes build_pcrs and binds the logged signing key to the attestation's public_key. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…attestation-verify
Main's tip (ecbf72b) carries a breaking AVSS rework (fastcrypto #954, #974) the MPC code isn't migrated to, so the merged nitro module can't be taken from main yet. Pin to the nitro-attestation branch tip (our prior base + the nitro module) and TODO moving to a main rev once #954/#974 are adopted. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0xsiddharthks
added a commit
that referenced
this pull request
Jun 18, 2026
Replace the node's on-chain ephemeral-key pin with attestation. The committee node builds a PcrAllowlist from the on-chain guardian build (the PCR0 anchor from the parent PR) and calls GetGuardianInfoResponse::verify, which checks the signed_info signature and pins the live attestation's PCR0. A guardian that reboots with a fresh ephemeral key is now trusted because attestation vouches for it — no on-chain key pin to go stale. Falls back to a signature-only check when no build is pinned on-chain yet; the BTC 2-of-2 still gates funds. The non-enclave-dev feature stubs the attestation leg to a no-op off-enclave (dev/e2e), where only the signature is enforced. Deletes the now-dead verify_guardian_signing_pubkey / verify_signing_pub_key_matches and their tests; keeps the BTC-key pin and verify_guardian_signed_info. Adds a CARGO_FEATURES build arg to docker/hashi/Containerfile (empty default = prod-safe) so the dev node image can be built with non-enclave-dev; the devnet build opts in (sui-operations, separate PR). A prod node image builds without it, enforcing real attestation. Depends on #666 + #675 (PcrAllowlist + verify + the hashi-types non-enclave-dev feature); does not compile until those land on main. Will rebase + compile-verify once they merge.
benr-ml
approved these changes
Jun 18, 2026
| /// Expected enclave-image measurement: PCR0 as hex, pinned against every | ||
| /// session's attestation. Required (a value is needed even in non-Nitro dev, | ||
| /// where verification is a no-op). | ||
| pub expected_pcr0: String, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Turns
verify_enclave_attestationfrom a no-op stub into real AWS Nitro attestation verification, and threads an expected PCR0 measurement through every consumer that reads guardian S3 state.Why
A guardian publishes an attestation document alongside its session signing key. Until now we trusted that key blindly. This change makes any reader (KP provisioner-init, hashi monitor/auditor) cryptographically verify, on first use of each session, that:
doc.public_key == signing_pub_key);PCR0).How
verify_enclave_attestation(attestation, signing_pubkey, build_pcrs)(hashi-types): parses + verifies viafastcrypto::nitro_attestation, binds the signing key, and pins PCR0.parse_nitro_attestation(.., true, true, true)keeps PCR0 inpcr_mapeven if zero so the pin can't be bypassed by a missing entry.BuildPcrs— known-good measurement an attestation is pinned to. Construction mandates PCR0. Records only PCR0 because in a StageX reproducible single-binary build it's the only measurement carrying signal. Follow-up (noted inTODO(check C)): acommit -> BuildPcrsallowlist keyed onuntrusted_git_revision, to span all the valid images during an upgrade.GuardianReader/GuardianSessionKeyCache/get_verified_enclave_pubkey/GetGuardianInfoResponse::verifyall takebuild_pcrs; provisioner and monitor configs gainexpected_pcr0(hex).non-enclave-devfeature (hashi-types, mirrored from hashi-guardian): stubs verification to a no-op so off-enclave e2e/dev consumers accept the mock document the guardian emits outside an enclave. Never enabled in prod.ecbf72b(the AWS Nitro module, fastcrypto #971).Notes for reviewers
expected_pcr0values are all-zero placeholders; real PCR0s are filled in at provisioning from the reproducible build.non-enclave-dev/teststub path.