From 5fd925ed1641244ca1f79bf1f2ccd282bf897db2 Mon Sep 17 00:00:00 2001 From: Transaction Science Date: Wed, 21 Oct 2026 19:13:56 -0400 Subject: [PATCH] sandbox: a confidential run sealed on TDX hardware, its PCK checked to Intel's root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TDX path (#399) and its PCK chain check (#415) had only met quotes this crate built itself. This runs the reference host inside a TDX guest and records the result as evidence anyone can re-check offline. sandbox-runtime examples: - confidential_run_tdx, run inside the guest. It takes quotes through configfs-tsm and derives the PCK anchor from a probe quote's chain, checked to Intel's root, which the verifier's side supplies. It seals an S6 run against a challenge, then checks the attestation: verified against the challenge, refused against another and against none. - verify_run now reads the evidence kind. For TDX its anchor argument is Intel's root, and the PCK is derived from the quote's chain checked to it. SEV-SNP is unchanged, and the 2026-10-21 SEV-SNP evidence still verifies. - sandbox-runtime's dev-dependencies enable sandbox-tee's intel-pcs feature for these examples. sandbox/proof/hardware/2026-10-21-tdx: the attestation (with the DCAP v4 quote), the challenge, Intel's published root certificate, and a README saying what it shows and what it does not. The unit is a placeholder and revocation lists were not consulted. Checked on our side, away from the guest: - The quote's chain is PCK Certificate, then PCK Platform CA, then Root CA, and its root is byte-identical to Intel's published root (SHA-256 44:A0:19:6B:…:74:D3). - 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). - Another certificate given as the root yields no anchor. Co-Authored-By: Claude Opus 5.5 --- .../proof/hardware/2026-10-21-tdx/README.md | 65 ++++++++++++ .../hardware/2026-10-21-tdx/attestation.json | 29 ++++++ .../hardware/2026-10-21-tdx/challenge.hex | 1 + .../hardware/2026-10-21-tdx/intel-root.der | Bin 0 -> 659 bytes .../crates/sandbox-runtime/Cargo.toml | 2 + .../examples/confidential_run_tdx.rs | 96 ++++++++++++++++++ .../sandbox-runtime/examples/verify_run.rs | 28 +++-- 7 files changed, 214 insertions(+), 7 deletions(-) create mode 100644 sandbox/proof/hardware/2026-10-21-tdx/README.md create mode 100644 sandbox/proof/hardware/2026-10-21-tdx/attestation.json create mode 100644 sandbox/proof/hardware/2026-10-21-tdx/challenge.hex create mode 100644 sandbox/proof/hardware/2026-10-21-tdx/intel-root.der create mode 100644 sandbox/sandbox-rs/crates/sandbox-runtime/examples/confidential_run_tdx.rs diff --git a/sandbox/proof/hardware/2026-10-21-tdx/README.md b/sandbox/proof/hardware/2026-10-21-tdx/README.md new file mode 100644 index 000000000..ead522c39 --- /dev/null +++ b/sandbox/proof/hardware/2026-10-21-tdx/README.md @@ -0,0 +1,65 @@ +# A confidential run on TDX hardware, 2026-10-21 + +The report-data binding of SPEC §7.6 on genuine Intel silicon, with the PCK +anchor derived from the quote's own certificate chain checked to Intel's +root, and the run verified by a party other than the host. + +## What ran + +- **Platform:** a confidential VM with Intel TDX (`c3-standard-4`, kernel + `7.0.0-1014-gcp`), created for the run and deleted after it. +- **Inside the guest:** the reference host + ([`confidential_run_tdx`](../../../sandbox-rs/crates/sandbox-runtime/examples/confidential_run_tdx.rs)). + - It took quotes through `configfs-tsm` (provider `tdx_guest`). + - It derived the anchor from a probe quote's PCK chain, checked to Intel's + root, which the verifier's side uploaded rather than the guest fetching it. + - It sealed an S6 run whose `report_data` binds the unit, the receipt, the + outcome and a 32-byte challenge ([`challenge.hex`](challenge.hex)). +- **The quote:** DCAP version 4, TEE type `0x81`. The interface returns it in + an 8000-byte buffer, 4935 bytes of quote followed by padding. It travels in + the attestation as `tee.report_hex`. + +The quote's certification data carries three certificates: + +```text +CN=Intel SGX PCK Certificate issued by CN=Intel SGX PCK Platform CA +CN=Intel SGX PCK Platform CA issued by CN=Intel SGX Root CA +CN=Intel SGX Root CA self-signed +``` + +The root it carries is byte-identical to Intel's published root +([`intel-root.der`](intel-root.der)), whose SHA-256 fingerprint is +`44:A0:19:6B:2B:99:F8:89:B8:E1:49:E9:5B:80:7A:35:0E:74:24:96:43:99:E8:85:A7:CB:B8:CC:FA:B6:74:D3`. +Compare it with the one Intel publishes, not with this file. + +## What it shows + +Verified away from the guest, from these files alone: + +```text +cd ../../../sandbox-rs +cargo run -p sandbox-runtime --example verify_run -- \ + ../proof/hardware/2026-10-21-tdx/attestation.json \ + "$(cat ../proof/hardware/2026-10-21-tdx/challenge.hex)" \ + ../proof/hardware/2026-10-21-tdx/intel-root.der +``` + +- The quote's PCK chain checks to Intel's root (`sandbox-tee::intel_pcs`), and + the quote verifies through that PCK: the quote signature, the QE report's + endorsement of the attestation key, and the PCK's signature over the QE + report. +- Its `report_data` is the binding of this attestation's unit, receipt and + outcome, and of the challenge issued. It is refused for any other + challenge, and without one. +- An attestation whose outcome is changed is refused. +- Given another certificate in place of Intel's root, no anchor is derived. + +## What it does not show + +- The unit is a fixed placeholder. This exercises the binding, the chain + check and the verifier on real hardware, not an executor's isolation of a + workload. +- Revocation was not consulted: Intel publishes CRLs for the PCK CAs, and + checking them is the deployment's step. +- The receipt and Supervisor keys are fixed development keys. The trust here + rests on the quote, not on those signatures. diff --git a/sandbox/proof/hardware/2026-10-21-tdx/attestation.json b/sandbox/proof/hardware/2026-10-21-tdx/attestation.json new file mode 100644 index 000000000..cabb9ad05 --- /dev/null +++ b/sandbox/proof/hardware/2026-10-21-tdx/attestation.json @@ -0,0 +1,29 @@ +{ + "audit_prev": null, + "devices": [ + { + "class": "Cpu", + "driver": "host", + "model": "confidential guest" + } + ], + "finished_at_us": 1792624764379210, + "grants_id": "b3:ej-h9yIoVIBjnlA-OMDiy95_Jlk7nqn6djvXYNv035w", + "host_id": "confidential-vm", + "image_id": "b3:sfsM4tYpFQT10UkAZVEdN5C2user1jDf-76b0oYeI8o", + "journal_root": null, + "locality": null, + "mechanism": null, + "outcome": "Completed", + "receipt_id": "b3:kCkhM2_jsKJyBwLL17ivdqhPhyPEIJaWjPUVDFRR6hU", + "started_at_us": 1792624764379209, + "tee": { + "challenge_hex": "8a7e3b2032714567827ad2e65ae0739125dad921db483725436d3af51d8cd4dc", + "kind": "Tdx", + "measurement_hex": "c1ee9c16e3afc506cfe042c5b846a368528f3b37618eafb27469bc114cf914e9222c91618470e7f2b28ac360968270a5", + "report_hex": "040002008100000000000000939a7233f79c4ca9940a0db3957f060700000000000000000000000000000000000000000f010a00000000000000000000000000ab62561a173acbd18ee50ff37750db44184c6cf5e886df74247cc575e163b04c34b9e18374757c235affa614d4127f6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000e702060000000000c1ee9c16e3afc506cfe042c5b846a368528f3b37618eafb27469bc114cf914e9222c91618470e7f2b28ac360968270a5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fa5765c24c4a9309a29e544ff1decbb2e5b46ed62be3c15da7fcd87c102da73b1ebc7c36536cd7c9aeb0045868611d75000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e141b935e09370f3ea1267004ce17d14f31166eafd811ad09964393e0a731de7b5f825b41c31490fa634b9fc8b3ee4355d1f3f04ba6040b9e15f821b3fe1e9dee16e64f85a2426bfb4a51040cf8a2a739134df3f7de3a6d5d97de850a26cddb46a71247d1392cb1e178026d62828d9ad298d77126cbd6c555652c95335a35ab0d665a83f8f53fc6dc83705646fb29fae000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000593a383ecae912bead8925e91f30693973217efb2bba4d03198dd616e2706c08ca1193825079c0c35b307fc34e3de11061be98a8e23a1f14048c6d3e83aaa10ccb1000000640fb3c412a18a70edcc216d5b7cd268535251b52180983fcb11d8a1481390fc6f344b7f406b895ca0d444ec7476ca80bb454abe785aa277a923c1e19b34b3baf97b4981bf43ff1fe1cd41d8a91382e91108d6bbbaa904d24c5275972a85c832af8e6d0eb2d87f4d81d116d885fbc5458f99abef0aa45d30676be5b08d194810600451000000a0aff1b06ff0006000000000000000000000000000000000000000000000000000000000000000000000000000000001500000000000000e700000000000000e5a3a7b5d830c2953b98534c6c59a3a34fdc34e933f7f5898f0a85cf08846bca0000000000000000000000000000000000000000000000000000000000000000dc9e2a7c6f948f17474e34a7fc43ed030f7c1563f1babddf6340c82e0e54a8c50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016a9ec51a70be29a68404aae2654f34b505eef1dfeec411a11d0604f2ef1025b000000000000000000000000000000000000000000000000000000000000000033f9c9be10d9bdfce4705a4a1cc5dad711b72c371e3a11f6a9b349b3c60d315b284dfa03017bb1a8e073b418d76bbed455c55118690c4aa20641d8766f86d3662000000000000000000000000000000000000000000000000000000000000000000005005d0e00002d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d49494538444343424a61674177494241674955626c7969715a476a655835766f5a62314665336d487a2b6d34394d77436759494b6f5a497a6a3045417749770a634445694d434147413155454177775a535735305a577767553064594946424453794251624746305a6d397962534244515445614d42674741315545436777520a535735305a577767513239796347397959585270623234784644415342674e564241634d43314e68626e526849454e7359584a684d51737743515944565151490a44414a445154454c4d416b474131554542684d4356564d774868634e4d6a59784d4445324d54497a4f4449345768634e4d7a4d784d4445324d54497a4f4449340a576a42774d534977494159445651514444426c4a626e526c624342545231676755454e4c49454e6c636e52705a6d6c6a5958526c4d526f77474159445651514b0a4442464a626e526c6243424462334a7762334a6864476c76626a45554d424947413155454277774c553246756447456751327868636d4578437a414a42674e560a4241674d416b4e424d517377435159445651514745774a56557a425a4d424d4742797147534d34394167454743437147534d34394177454841304941424142540a6a6744377749627258316e3033654939375673497549467264516368356f7935686b643150472b4c374732464535667275523065774452755357636a76696d730a37786d7271697874366e4870526558595250476a67674d4d4d4949444344416642674e5648534d4547444157674253566231334e765276683655424a796454300a4d383442567776655644427242674e56485238455a4442694d47436758714263686c706f64485277637a6f764c32467761533530636e567a6447566b633256790a646d6c6a5a584d75615735305a577775593239744c334e6e6543396a5a584a3061575a7059324630615739754c3359304c33426a61324e796244396a595431770a624746305a6d397962535a6c626d4e765a476c755a7a316b5a584977485159445652304f424259454649513731694f7439576c696978437a44636f37484f68320a6b505a734d41344741315564447745422f775145417749477744414d42674e5648524d4241663845416a41414d4949434f51594a4b6f5a496876684e415130420a424949434b6a4343416959774867594b4b6f5a496876684e4151304241515151552b2b356c337a744a36572b39713156414f71494644434341574d47436971470a534962345451454e41514977676746544d42414743797147534962345451454e415149424167454b4d42414743797147534962345451454e415149434167454b0a4d42414743797147534962345451454e41514944416745434d42414743797147534962345451454e41514945416745434d42414743797147534962345451454e0a41514946416745474d42414743797147534962345451454e41514947416745424d42414743797147534962345451454e41514948416745414d424147437971470a534962345451454e41514949416745474d42414743797147534962345451454e4151494a416745414d42414743797147534962345451454e4151494b416745410a4d42414743797147534962345451454e4151494c416745414d42414743797147534962345451454e4151494d416745414d42414743797147534962345451454e0a4151494e416745414d42414743797147534962345451454e4151494f416745414d42414743797147534962345451454e41514950416745414d424147437971470a534962345451454e41514951416745414d42414743797147534962345451454e415149524167454e4d42384743797147534962345451454e415149534242414b0a43674943426745414267414141414141414141414d42414743697147534962345451454e41514d45416741414d42514743697147534962345451454e415151450a42674341627755414144415042676f71686b69472b45304244514546436745424d42344743697147534962345451454e41515945454f68674d705268394938620a5a5838484d362f724a6e34775241594b4b6f5a496876684e41513042427a41324d42414743797147534962345451454e415163424151482f4d424147437971470a534962345451454e41516343415145414d42414743797147534962345451454e415163444151482f4d416f4743437147534d343942414d43413067414d4555430a49416249616a776259687159786345723575587167565a696d73724367526c4d2b6f542f78786c6d6a476659416945416d735454334f4672584c30774b2f64350a636d6b53724d4b76597975763464744974316152645232747848513d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d4949436c6a4343416a32674177494241674956414a567658633239472b487051456e4a3150517a7a674658433935554d416f4743437147534d343942414d430a4d476778476a415942674e5642414d4d45556c756447567349464e48574342536232393049454e424d526f77474159445651514b4442464a626e526c624342440a62334a7762334a6864476c76626a45554d424947413155454277774c553246756447456751327868636d4578437a414a42674e564241674d416b4e424d5173770a435159445651514745774a56557a4165467730784f4441314d6a45784d4455774d5442614677307a4d7a41314d6a45784d4455774d5442614d484178496a41670a42674e5642414d4d47556c756447567349464e4857434251513073675547786864475a76636d306751304578476a415942674e5642416f4d45556c75644756730a49454e76636e4276636d4630615739754d5251774567594456515148444174545957353059534244624746795954454c4d416b474131554543417743513045780a437a414a42674e5642415954416c56544d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a304441516344516741454e53422f377432316c58534f0a3243757a7078773734654a423732457944476757357258437478327456544c7136684b6b367a2b5569525a436e71523770734f766771466553786c6d546c4a6c0a65546d693257597a33714f42757a43427544416642674e5648534d4547444157674251695a517a575770303069664f44744a5653763141624f536347724442530a42674e5648523845537a424a4d45656752614244686b466f64485277637a6f764c324e6c636e52705a6d6c6a5958526c63793530636e567a6447566b633256790a646d6c6a5a584d75615735305a577775593239744c306c756447567355306459556d397664454e424c6d526c636a416442674e5648513445466751556c5739640a7a62306234656c4153636e553944504f4156634c336c517744675944565230504151482f42415144416745474d42494741315564457745422f7751494d4159420a4166384341514177436759494b6f5a497a6a30454177494452774177524149675873566b6930772b6936565947573355462f32327561586530594a446a3155650a6e412b546a44316169356343494359623153416d4435786b66545670766f34556f79695359787244574c6d5552344349394e4b7966504e2b0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a2d2d2d2d2d424547494e2043455254494649434154452d2d2d2d2d0a4d4949436a7a4343416a53674177494241674955496d554d316c71644e496e7a6737535655723951477a6b6e42717777436759494b6f5a497a6a3045417749770a614445614d4267474131554541777752535735305a5777675530645949464a766233516751304578476a415942674e5642416f4d45556c756447567349454e760a636e4276636d4630615739754d5251774567594456515148444174545957353059534244624746795954454c4d416b47413155454341774351304578437a414a0a42674e5642415954416c56544d423458445445344d4455794d5445774e4455784d466f58445451354d54497a4d54497a4e546b314f566f77614445614d4267470a4131554541777752535735305a5777675530645949464a766233516751304578476a415942674e5642416f4d45556c756447567349454e76636e4276636d46300a615739754d5251774567594456515148444174545957353059534244624746795954454c4d416b47413155454341774351304578437a414a42674e56424159540a416c56544d466b77457759484b6f5a497a6a3043415159494b6f5a497a6a3044415163445167414543366e45774d4449595a4f6a2f69505773437a61454b69370a314f694f534c52466857476a626e42564a66566e6b59347533496a6b4459594c304d784f346d717379596a6c42616c54565978465032734a424b357a6c4b4f420a757a43427544416642674e5648534d4547444157674251695a517a575770303069664f44744a5653763141624f5363477244425342674e5648523845537a424a0a4d45656752614244686b466f64485277637a6f764c324e6c636e52705a6d6c6a5958526c63793530636e567a6447566b63325679646d6c6a5a584d75615735300a5a577775593239744c306c756447567355306459556d397664454e424c6d526c636a416442674e564851344546675155496d554d316c71644e496e7a673753560a55723951477a6b6e4271777744675944565230504151482f42415144416745474d42494741315564457745422f7751494d4159424166384341514577436759490a4b6f5a497a6a3045417749445351417752674968414f572f35516b522b533943695344634e6f6f774c7550524c735747662f59693747535839344267775477670a41694541344a306c72486f4d732b586f356f2f7358364f39515778485241765a55474f6452513763767152586171493d0a2d2d2d2d2d454e442043455254494649434154452d2d2d2d2d0a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "tcb": "0x0f010a0000000000" + }, + "tier": "S6", + "unit_id": "b3:StLoFp1GgfFDM6RVELdOlbduOMrjpLZGE6kSdYoLFNg" +} diff --git a/sandbox/proof/hardware/2026-10-21-tdx/challenge.hex b/sandbox/proof/hardware/2026-10-21-tdx/challenge.hex new file mode 100644 index 000000000..e454f367c --- /dev/null +++ b/sandbox/proof/hardware/2026-10-21-tdx/challenge.hex @@ -0,0 +1 @@ +8a7e3b2032714567827ad2e65ae0739125dad921db483725436d3af51d8cd4dc diff --git a/sandbox/proof/hardware/2026-10-21-tdx/intel-root.der b/sandbox/proof/hardware/2026-10-21-tdx/intel-root.der new file mode 100644 index 0000000000000000000000000000000000000000..768806c673709fb71537020abbabad2b1dc23773 GIT binary patch literal 659 zcmXqLV(K?&Vlr94%*4pVB%+kcb1iDFN$2P0EmMQ`2S{70v#l}UV&l+i^EhYA!pvll zVJKxF!NwfQ!ptM+nOBmUqY&&Kp%9dxU!vgb2$SQ2$vNj2733EsmSpDV8HyMPf%LKS za0e&ml_V-S=Oh*-8gd(OfM-Ch~kvMtrKjmv1bZ!Z(*nQf5%loS+O>FXz_7L{bCWhN(hi5#{Wtmy%j!APX{+k420HyOn$(X?{k= z|17|0XJi9Mo~$s4&tbp@q?i~PkrM{9Cxd|-lOn^@{ZBasf9gARD%>&aGSGW`QSWG5 z{WqmIDbv3SH3&@mV{?50sw!g B#yS81 literal 0 HcmV?d00001 diff --git a/sandbox/sandbox-rs/crates/sandbox-runtime/Cargo.toml b/sandbox/sandbox-rs/crates/sandbox-runtime/Cargo.toml index dc3235e6f..14ab18ed5 100644 --- a/sandbox/sandbox-rs/crates/sandbox-runtime/Cargo.toml +++ b/sandbox/sandbox-rs/crates/sandbox-runtime/Cargo.toml @@ -21,4 +21,6 @@ thiserror.workspace = true [dev-dependencies] p256.workspace = true +# The examples check a TDX quote's PCK chain to Intel's root. +sandbox-tee = { workspace = true, features = ["intel-pcs"] } serde_json.workspace = true diff --git a/sandbox/sandbox-rs/crates/sandbox-runtime/examples/confidential_run_tdx.rs b/sandbox/sandbox-rs/crates/sandbox-runtime/examples/confidential_run_tdx.rs new file mode 100644 index 000000000..c55ecd140 --- /dev/null +++ b/sandbox/sandbox-rs/crates/sandbox-runtime/examples/confidential_run_tdx.rs @@ -0,0 +1,96 @@ +//! Seal a confidential run on TDX hardware and verify it as a third party +//! would (SPEC §7.6): the TDX counterpart of `confidential_run`. +//! +//! Run as root inside a TDX guest with `configfs-tsm`: +//! +//! ```text +//! confidential_run_tdx +//! ``` +//! +//! `intel-root.der` is Intel's published root CA certificate, which the +//! verifier pins. The PCK anchor is derived from the chain a quote carries, +//! checked to that root, so the trust comes from the root and not from the +//! quote. The host seals an S6 run whose quote the platform makes over the +//! run's binding and the challenge, and the attestation is verified against +//! the challenge, against another, and against none. It prints the verdicts +//! and the attestation as JSON. + +use ed25519_dalek::SigningKey; +use sandbox_attest::{DeviceIdentity, Outcome, TeeKind}; +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::{AttestationProvider, ConfigfsTsmProvider}; + +fn main() { + let args: Vec = std::env::args().collect(); + let (Some(challenge_hex), Some(root_path)) = (args.get(1), args.get(2)) else { + eprintln!("usage: confidential_run_tdx "); + 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 root = std::fs::read(root_path).expect("read Intel's root certificate"); + let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).expect("a clock after 1970"); + + // A probe quote carries the platform's PCK chain; check it to the root. + let probe = ConfigfsTsmProvider::for_kind(TeeKind::Tdx).report(&[0; 64]).expect("a TDX quote"); + let pck = sandbox_tee::intel_pcs::pck_from_quote(&probe, &root, now.as_secs()).expect("a PCK chain to Intel's root"); + let anchor = TeeAnchor::Tdx(pck); + let policy = TeePolicy::tdx_baseline(); + + let host = Host::new("confidential-vm", "steward.hardware-check", SigningKey::from_bytes(&[1; 32]), SigningKey::from_bytes(&[2; 32])) + .with_tee(TeeConfig { + provider: Box::new(ConfigfsTsmProvider::for_kind(TeeKind::Tdx)), + 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 = now.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(), "probe_hex": hex::encode(&probe) })); + 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; + println!( + "{}", + serde_json::json!({ + "sealed": true, + "verified": verified.is_ok(), + "verify_error": verified.err().map(|e| e.to_string()), + "refused_another_challenge": verify_run_evidence(a, Some(&other), &policy, &anchor).is_err(), + "refused_no_challenge": verify_run_evidence(a, None, &policy, &anchor).is_err(), + "kind": format!("{:?}", tee.kind), + "measurement_hex": tee.measurement_hex, + "tcb": tee.tcb, + "attestation": a, + }) + ); +} diff --git a/sandbox/sandbox-rs/crates/sandbox-runtime/examples/verify_run.rs b/sandbox/sandbox-rs/crates/sandbox-runtime/examples/verify_run.rs index edacb54c6..7f75f356f 100644 --- a/sandbox/sandbox-rs/crates/sandbox-runtime/examples/verify_run.rs +++ b/sandbox/sandbox-rs/crates/sandbox-runtime/examples/verify_run.rs @@ -3,14 +3,16 @@ //! with nothing from the host that sealed it. //! //! ```text -//! verify_run +//! verify_run //! ``` //! -//! `vcek.der` is the chip's VCEK, as AMD's KDS issues it. The run is verified +//! For SEV-SNP evidence, `anchor.der` is the chip's VCEK, as AMD's KDS issues +//! it. For TDX evidence, it is Intel's root CA certificate: the PCK anchor is +//! derived from the chain the quote carries, checked to that root. The run is verified //! against the challenge, and must be refused against any other challenge and //! against none. Exits non-zero unless all three hold. -use sandbox_attest::Attestation; +use sandbox_attest::{Attestation, TeeKind}; use sandbox_runtime::verify_run_evidence; use sandbox_tee::policy::{TeeAnchor, TeePolicy}; @@ -24,10 +26,22 @@ fn main() { serde_json::from_str(&std::fs::read_to_string(path).expect("read the attestation")).expect("an attestation"); let challenge: [u8; 32] = hex::decode(challenge_hex.trim()).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"); - let at = der.windows(4).position(|w| w == [0x03, 0x62, 0x00, 0x04]).expect("a P-384 point in the VCEK"); - let anchor = TeeAnchor::SevSnp(p384::ecdsa::VerifyingKey::from_sec1_bytes(&der[at + 3..at + 3 + 97]).expect("a P-384 key")); - let policy = TeePolicy::sev_snp_baseline(); + let der = std::fs::read(vcek_path).expect("read the anchor"); + let tee = attestation.tee.as_ref().expect("TEE evidence to verify"); + let (anchor, policy) = match tee.kind { + TeeKind::SevSnp => { + 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"); + (TeeAnchor::SevSnp(vcek), TeePolicy::sev_snp_baseline()) + } + TeeKind::Tdx => { + let quote = hex::decode(tee.report_hex.as_ref().expect("the quote")).expect("a hex quote"); + let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).expect("a clock").as_secs(); + let pck = sandbox_tee::intel_pcs::pck_from_quote("e, &der, now).expect("a PCK chain to Intel's root"); + (TeeAnchor::Tdx(pck), TeePolicy::tdx_baseline()) + } + TeeKind::ArmCca => panic!("no ArmCca verifier"), + }; let verified = verify_run_evidence(&attestation, Some(&challenge), &policy, &anchor); let mut other = challenge; -- 2.54.0 (Apple Git-157)