open-standards/sandbox/sandbox-rs/crates/sandbox-runtime/examples/confidential_run.rs
Transaction Science 328d89b676
All checks were successful
standards workspaces build + test / which workspaces this change touches (pull_request) Successful in 5s
repository checks / lockfiles, tests in CI, workflow hygiene, spec and section references, public text (pull_request) Successful in 47s
standards workspaces build + test / jcp-rs (jcp-conformance, jcp/jcp-rs, -p jcp-energy --features nvml, jcp-rs, linux) (pull_request) Successful in 1m43s
standards workspaces build + test / joule-ui-rs (joule-ui/joule-ui-rs, joule-ui-rs, linux) (pull_request) Successful in 1m14s
standards workspaces build + test / proof-rs (proof-conformance, proof/proof-rs, proof-rs, linux, true) (pull_request) Successful in 1m33s
standards workspaces build + test / sandbox-rs (sandbox-conformance, sandbox/sandbox-rs, sandbox-rs, linux) (pull_request) Successful in 2m47s
standards workspaces build + test / joulecontract-rs (joulecontract/joulecontract-rs, joulecontract-rs, linux-arm64, true) (pull_request) Successful in 1m57s
standards workspaces build + test / joule-code-rs (joule-code/joule-code-rs, joule-code-rs, linux-arm64, true) (pull_request) Successful in 4m59s
standards workspaces build + test / macOS energy backends (pull_request) Successful in 7m46s
standards workspaces build + test / jouledesk-rs (jouledesk/jouledesk-rs, jouledesk-rs, macos) (pull_request) Successful in 2m50s
sandbox: a confidential run sealed on SEV-SNP hardware, verified by a third party
The run binding of #392 had only met software-grounded reports. This runs
the reference host inside an SEV-SNP guest and records the result as
evidence anyone can re-check offline.

sandbox-runtime examples:
- confidential_run, run inside the guest. It takes reports through
  configfs-tsm and seals an S6 run against a challenge; the report_data is
  the run binding of SPEC §7.6. It then checks the attestation through the
  chip's VCEK: verified against the challenge, refused against another and
  against none.
- verify_run: the third party's check, from the attestation, the challenge
  issued and the VCEK alone.

sandbox/proof/hardware/2026-10-21-sev-snp: the attestation (with the
1184-byte v5 report), the challenge, the chip's VCEK and AMD's cert chain,
and a README saying what it shows and what it does not. The unit is a
placeholder, so this exercises the binding and verifier on silicon, not
isolation.

Checked on our side, away from the guest:
- The VCEK was fetched from AMD's KDS by the chip id and TCB inside the
  report, and openssl verifies it to ARK-Milan.
- verify_run on the build host verifies the run, and refuses another
  challenge and no challenge.
- An attestation with its outcome changed is refused ("report-data binding
  mismatch"): the AMD signature covers the outcome through the binding.

sandbox-tee: the version comment now says what the code does (v2 layout
and later; a v5 report verified on hardware).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 16:25:26 -04:00

93 lines
4.1 KiB
Rust

//! Seal a confidential run on real hardware and verify it as a third party
//! would (SPEC §7.6).
//!
//! Run as root inside an SEV-SNP guest with `configfs-tsm`:
//!
//! ```text
//! confidential_run <challenge-hex> <vcek.der>
//! ```
//!
//! `vcek.der` is the chip's VCEK, from AMD's KDS. The host seals an S6 run whose
//! report the platform signs over the run's binding and the challenge. The
//! attestation is then verified through the VCEK alone, against the verifier's
//! own challenge, and against another challenge, which must fail. The run's
//! unit is a fixed placeholder: what this exercises is the binding and the
//! verifier on genuine silicon. It prints the verdicts and the attestation as
//! JSON.
use ed25519_dalek::SigningKey;
use sandbox_attest::{DeviceIdentity, Outcome};
use sandbox_capability::Grants;
use sandbox_meter::{DeviceEnergy, Provenance};
use sandbox_runtime::{verify_run_evidence, Host, RunReport, TeeConfig};
use sandbox_schema::{ContentId, DeviceClass, Tier};
use sandbox_tee::policy::{TeeAnchor, TeePolicy};
use sandbox_tee::provider::ConfigfsTsmProvider;
fn main() {
let args: Vec<String> = std::env::args().collect();
let (Some(challenge_hex), Some(vcek_path)) = (args.get(1), args.get(2)) else {
eprintln!("usage: confidential_run <challenge-hex> <vcek.der>");
std::process::exit(2);
};
let challenge: [u8; 32] =
hex::decode(challenge_hex).ok().and_then(|v| v.try_into().ok()).expect("a 32-byte hex challenge");
let der = std::fs::read(vcek_path).expect("read the VCEK");
// The P-384 public point in the certificate's SubjectPublicKeyInfo: the
// BIT STRING `03 62 00 04` followed by x ‖ y.
let at = der.windows(4).position(|w| w == [0x03, 0x62, 0x00, 0x04]).expect("a P-384 point in the VCEK");
let vcek = p384::ecdsa::VerifyingKey::from_sec1_bytes(&der[at + 3..at + 3 + 97]).expect("a P-384 key");
let anchor = TeeAnchor::SevSnp(vcek);
let policy = TeePolicy::sev_snp_baseline();
let host = Host::new("gcp-confidential-vm", "steward.hardware-check", SigningKey::from_bytes(&[1; 32]), SigningKey::from_bytes(&[2; 32]))
.with_tee(TeeConfig { provider: Box::new(ConfigfsTsmProvider::default()), policy: policy.clone(), anchor: anchor.clone() });
let report = RunReport {
device_energy: vec![DeviceEnergy { class: DeviceClass::Cpu, measured_uj: None, estimated_uj: 1, provenance: Provenance::Estimator }],
device_identity: vec![DeviceIdentity { class: DeviceClass::Cpu, model: "confidential guest".into(), driver: "host".into() }],
outcome: Outcome::Completed,
journal: None,
storage: None,
};
let now_us = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).map_or(0, |d| d.as_micros() as u64);
let sealed = match host.seal_run_with_mechanism(
ContentId::of_bytes(b"hardware check unit"),
ContentId::of_bytes(b"hardware check image"),
&Grants::default(),
Tier::S6,
report,
0,
[0; 8],
now_us,
now_us + 1,
None,
Some(challenge),
) {
Ok(s) => s,
Err(e) => {
println!("{}", serde_json::json!({ "sealed": false, "error": e.to_string() }));
std::process::exit(1);
}
};
let a = &sealed.attestation;
let tee = a.tee.as_ref().expect("an S6 run carries TEE evidence");
let verified = verify_run_evidence(a, Some(&challenge), &policy, &anchor);
let mut other = challenge;
other[0] ^= 1;
let refused_other = verify_run_evidence(a, Some(&other), &policy, &anchor).is_err();
let refused_none = verify_run_evidence(a, None, &policy, &anchor).is_err();
println!(
"{}",
serde_json::json!({
"sealed": true,
"verified": verified.is_ok(),
"verify_error": verified.err().map(|e| e.to_string()),
"refused_another_challenge": refused_other,
"refused_no_challenge": refused_none,
"kind": format!("{:?}", tee.kind),
"measurement_hex": tee.measurement_hex,
"tcb": tee.tcb,
"attestation": a,
})
);
}