voltage-verify 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. voltage_verify-0.1.0/.gitignore +11 -0
  2. voltage_verify-0.1.0/CHANGELOG.md +18 -0
  3. voltage_verify-0.1.0/LICENSE +21 -0
  4. voltage_verify-0.1.0/PKG-INFO +191 -0
  5. voltage_verify-0.1.0/README.md +136 -0
  6. voltage_verify-0.1.0/SECURITY.md +32 -0
  7. voltage_verify-0.1.0/docs/ATTEST_ON_VM.md +62 -0
  8. voltage_verify-0.1.0/docs/BUNDLE_FORMAT.md +69 -0
  9. voltage_verify-0.1.0/docs/WHAT_IT_PROVES.md +49 -0
  10. voltage_verify-0.1.0/pyproject.toml +74 -0
  11. voltage_verify-0.1.0/src/voltage_verify/__init__.py +4 -0
  12. voltage_verify-0.1.0/src/voltage_verify/__main__.py +9 -0
  13. voltage_verify-0.1.0/src/voltage_verify/attest.py +184 -0
  14. voltage_verify-0.1.0/src/voltage_verify/bundle.py +101 -0
  15. voltage_verify-0.1.0/src/voltage_verify/canonical.py +67 -0
  16. voltage_verify-0.1.0/src/voltage_verify/cli.py +184 -0
  17. voltage_verify-0.1.0/src/voltage_verify/data/intel_sgx_root_ca.pem +16 -0
  18. voltage_verify-0.1.0/src/voltage_verify/der.py +92 -0
  19. voltage_verify-0.1.0/src/voltage_verify/manifest.py +99 -0
  20. voltage_verify-0.1.0/src/voltage_verify/nvidia.py +196 -0
  21. voltage_verify-0.1.0/src/voltage_verify/pcs.py +322 -0
  22. voltage_verify-0.1.0/src/voltage_verify/registry.py +102 -0
  23. voltage_verify-0.1.0/src/voltage_verify/selftest.py +136 -0
  24. voltage_verify-0.1.0/src/voltage_verify/tdx.py +327 -0
  25. voltage_verify-0.1.0/src/voltage_verify/verify.py +263 -0
  26. voltage_verify-0.1.0/tests/conftest.py +37 -0
  27. voltage_verify-0.1.0/tests/fixtures/intel_collateral_90c06f000000_2026-09-12.json +15 -0
  28. voltage_verify-0.1.0/tests/fixtures/nras_h200_2026-09-04.json +1 -0
  29. voltage_verify-0.1.0/tests/fixtures/nras_jwks_2026-09-12.json +1 -0
  30. voltage_verify-0.1.0/tests/fixtures/nras_ppcie_8xh100_2026-09-10.json +1 -0
  31. voltage_verify-0.1.0/tests/fixtures/quote_h200_2026-09-04.bin +0 -0
  32. voltage_verify-0.1.0/tests/fixtures/report_data_h200_2026-09-04.bin +1 -0
  33. voltage_verify-0.1.0/tests/test_canonical_and_manifest.py +65 -0
  34. voltage_verify-0.1.0/tests/test_cli.py +47 -0
  35. voltage_verify-0.1.0/tests/test_example_bundle.py +38 -0
  36. voltage_verify-0.1.0/tests/test_nvidia.py +77 -0
  37. voltage_verify-0.1.0/tests/test_pcs.py +54 -0
  38. voltage_verify-0.1.0/tests/test_tdx.py +68 -0
@@ -0,0 +1,11 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ *.egg-info/
5
+ build/
6
+ dist/
7
+ .pytest_cache/
8
+ .ruff_cache/
9
+ .mypy_cache/
10
+ manifest.json
11
+ bundle.json
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-09-12)
4
+
5
+ First release.
6
+
7
+ * `manifest`: image digest resolution through the OCI registry API (no pull), artifact
8
+ hashing, free-form extras, verifier-side random challenge.
9
+ * `attest`: TDX quote through configfs TSM with `report_data = SHA-512(manifest)`, NVIDIA
10
+ NRAS attestation with `nonce = SHA-256(manifest)`, single-GPU and multi-GPU Protected PCIe
11
+ modes, Intel and NVIDIA collateral embedded for offline verification.
12
+ * `verify`: quote structure, attestation key signature, Quoting Enclave binding and signature,
13
+ PCK chain to the pinned Intel SGX Root CA, TCB level and TDX module identity against Intel's
14
+ signed TCB info, Quoting Enclave identity, CRLs, NRAS ES384 signatures, nonce, claims policy,
15
+ token freshness, challenge and image expectations.
16
+ * `selftest`: six negative tests (image digest, artifact, manifest field, challenge replay,
17
+ quote tampering, GPU claim tampering).
18
+ * Tests against real evidence captured on VoltageGPU Confidential VMs.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 VOLTAGE EI (VoltageGPU), Julien Aubry
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,191 @@
1
+ Metadata-Version: 2.5
2
+ Name: voltage-verify
3
+ Version: 0.1.0
4
+ Summary: Bind an Intel TDX quote and an NVIDIA GPU attestation to the workload you meant to run, then verify the bundle without trusting the cloud provider.
5
+ Project-URL: Homepage, https://voltagegpu.com/blog/two-proofs-tdx-nvidia-h200-attestation-tenant
6
+ Project-URL: Documentation, https://docs.voltagegpu.com/pods/confidential-vm
7
+ Project-URL: Source, https://github.com/Jabsama/voltage-verify
8
+ Project-URL: Issues, https://github.com/Jabsama/voltage-verify/issues
9
+ Project-URL: Changelog, https://github.com/Jabsama/voltage-verify/blob/main/CHANGELOG.md
10
+ Project-URL: Mirror, https://voltagegpu.com/blog/two-proofs/voltage-verify/
11
+ Project-URL: Evidence, https://voltagegpu.com/blog/two-proofs/evidence/README.txt
12
+ Author-email: "VoltageGPU (VOLTAGE EI)" <contact@voltagegpu.com>
13
+ License: MIT License
14
+
15
+ Copyright (c) 2026 VOLTAGE EI (VoltageGPU), Julien Aubry
16
+
17
+ Permission is hereby granted, free of charge, to any person obtaining a copy
18
+ of this software and associated documentation files (the "Software"), to deal
19
+ in the Software without restriction, including without limitation the rights
20
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21
+ copies of the Software, and to permit persons to whom the Software is
22
+ furnished to do so, subject to the following conditions:
23
+
24
+ The above copyright notice and this permission notice shall be included in all
25
+ copies or substantial portions of the Software.
26
+
27
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33
+ SOFTWARE.
34
+ License-File: LICENSE
35
+ Keywords: attestation,confidential-computing,gpu,intel-tdx,nvidia,remote-attestation
36
+ Classifier: Development Status :: 3 - Alpha
37
+ Classifier: Environment :: Console
38
+ Classifier: Intended Audience :: Developers
39
+ Classifier: Intended Audience :: Information Technology
40
+ Classifier: License :: OSI Approved :: MIT License
41
+ Classifier: Programming Language :: Python :: 3
42
+ Classifier: Programming Language :: Python :: 3 :: Only
43
+ Classifier: Topic :: Security :: Cryptography
44
+ Requires-Python: >=3.10
45
+ Requires-Dist: cryptography<47,>=42
46
+ Requires-Dist: pyjwt<3,>=2.7
47
+ Provides-Extra: attest
48
+ Requires-Dist: nv-attestation-sdk>=2.7; extra == 'attest'
49
+ Requires-Dist: nvidia-ml-py>=12; extra == 'attest'
50
+ Provides-Extra: dev
51
+ Requires-Dist: mypy>=1.10; extra == 'dev'
52
+ Requires-Dist: pytest>=7; extra == 'dev'
53
+ Requires-Dist: ruff>=0.6; extra == 'dev'
54
+ Description-Content-Type: text/markdown
55
+
56
+ # voltage-verify
57
+
58
+ Bind an Intel TDX quote and an NVIDIA GPU attestation to the workload you meant to run, then
59
+ verify the bundle on your own machine, without trusting the cloud provider.
60
+
61
+ `voltage-verify` is a small command line tool with three roles:
62
+
63
+ 1. **On your machine**, it writes a *manifest*: the container image digest, the digests of the
64
+ model or files you care about, a free-text statement, and a fresh random challenge. Two
65
+ hashes of that manifest become the *commitments*.
66
+ 2. **Inside the confidential VM**, it asks the hardware to sign those commitments: the Intel
67
+ TDX quote carries `SHA-512(manifest)` as its 64-byte `report_data`, and NVIDIA's Remote
68
+ Attestation Service (NRAS) signs GPU claims over the nonce `SHA-256(manifest)`. It writes
69
+ one JSON *bundle* with the quote, the NVIDIA tokens and the public collateral needed to
70
+ check them later.
71
+ 3. **Back on your machine**, it verifies the bundle: Intel's signature chain to the pinned
72
+ Intel SGX Root CA, the platform's TCB status against Intel's published TCB info, the
73
+ Quoting Enclave identity, revocation lists, NVIDIA's ES384 signatures against NRAS's JWKS,
74
+ the per-GPU claims (measurements ok, secure boot on, debug off), and above all that both
75
+ proofs carry *your* commitments. Then it runs six negative tests to show that any change
76
+ to the manifest, the challenge, the quote or a GPU claim is rejected.
77
+
78
+ It was written by [VoltageGPU](https://voltagegpu.com) so that tenants of its Confidential VMs
79
+ can verify more than "this is a TDX VM with a confidential GPU": they can verify that the two
80
+ hardware proofs were produced *for the workload described in a manifest they wrote*, on a
81
+ challenge they chose. The trust chain ends at Intel and NVIDIA, never at VoltageGPU.
82
+
83
+ ## What it proves, and what it does not
84
+
85
+ Verified means:
86
+
87
+ * the TDX quote was produced inside a genuine Intel TDX Trust Domain, on a platform whose
88
+ provisioning certificate chains to Intel's root, at an acceptable TCB level, by a genuine
89
+ Quoting Enclave, and it embeds `SHA-512` of your manifest;
90
+ * NVIDIA's service signed, over `SHA-256` of your manifest, that the GPU(s) in that VM passed
91
+ attestation with secure boot on and debugging off;
92
+ * both proofs were made after you issued the challenge, so they cannot be replayed from an
93
+ earlier session or copied from another tenant.
94
+
95
+ Verified does **not** mean:
96
+
97
+ * that the GPU *executed* the image or model named in the manifest. Binding a manifest to a
98
+ quote proves the hardware signed your description of the workload; proving that this exact
99
+ code ran needs a measured launcher (for instance the Confidential Containers project with
100
+ a key broker), which is outside this tool;
101
+ * anything about the VM's own software stack beyond what the TDX measurements (`MRTD`,
102
+ `RTMR0..3`) say. The tool prints them; comparing them against a reference image is your
103
+ policy, not the tool's;
104
+ * anything about a VM you did not attest yourself.
105
+
106
+ `docs/WHAT_IT_PROVES.md` goes through every check and its limit.
107
+
108
+ ## Install
109
+
110
+ ```
111
+ # verifier machine: Python 3.10+, cryptography, PyJWT
112
+ pip install voltage-verify
113
+ # inside the VM: the NVIDIA SDK first (it pins cryptography and PyJWT), then the tool
114
+ pip install nv-attestation-sdk nvidia-ml-py
115
+ pip install --no-deps voltage-verify
116
+ ```
117
+
118
+ Source and issues: https://github.com/Jabsama/voltage-verify. The same wheel and source
119
+ archive are mirrored with SHA-256 sums at https://voltagegpu.com/blog/two-proofs/voltage-verify/
120
+ for installs that must not touch PyPI (`pip install <wheel URL>`).
121
+
122
+ ## Reference run
123
+
124
+ `examples/hello-workload/` holds a real bundle captured on 12 September 2026 on a VoltageGPU
125
+ `h100-xlarge` Confidential VM (8x H100, NVIDIA Protected PCIe mode), with its manifest and the
126
+ unedited run log. Replay the verification on your own machine:
127
+
128
+ ```
129
+ voltage-verify verify examples/hello-workload/bundle-8xh100-2026-09-12.json \
130
+ --challenge ef7f54c160627ee536a02b5e73896ac4b1ac2cdefdb7cfaaf2366a7d33cc8731 --hwmodel GH100 --gpus 8
131
+ voltage-verify selftest examples/hello-workload/bundle-8xh100-2026-09-12.json
132
+ ```
133
+
134
+ Expected: every check `PASS`, platform TCB `UpToDate`, Quoting Enclave `UpToDate`, eight
135
+ `GH100` devices with `measres success`, then six mutations rejected.
136
+
137
+ ## Use
138
+
139
+ On your machine, describe the workload and generate a challenge:
140
+
141
+ ```
142
+ voltage-verify manifest --image ghcr.io/you/app:1.4.2 --artifact model.safetensors \
143
+ --statement "inference run for customer X" -o manifest.json
144
+ ```
145
+
146
+ Copy `manifest.json` into the VM (scp), then, as root inside the VM:
147
+
148
+ ```
149
+ sudo -E python -m voltage_verify attest --manifest manifest.json -o bundle.json
150
+ ```
151
+
152
+ Copy `bundle.json` back, then:
153
+
154
+ ```
155
+ voltage-verify verify bundle.json --challenge <the challenge printed by `manifest`>
156
+ voltage-verify selftest bundle.json --challenge <same>
157
+ voltage-verify verify bundle.json --offline # same checks, from the collateral in the bundle
158
+ ```
159
+
160
+ Exit code 0 means verified, 1 means a required check failed, 2 means the bundle or arguments
161
+ are unusable. `--json` prints the machine-readable report.
162
+
163
+ ## Bundle format
164
+
165
+ Documented in `docs/BUNDLE_FORMAT.md`. In short: the manifest verbatim, both commitments, the
166
+ raw TDX quote (base64), the NRAS token array as returned by the NVIDIA SDK, NRAS's JWKS and
167
+ Intel's TCB info, QE identity and CRLs as fetched at attestation time, plus a few facts about
168
+ the VM (kernel, driver, `nvidia-smi conf-compute -q`). The verifier trusts none of it: it
169
+ recomputes the commitments from the manifest and checks every signature.
170
+
171
+ ## Development
172
+
173
+ ```
174
+ python -m venv .venv && . .venv/bin/activate
175
+ pip install -e ".[dev]"
176
+ pytest
177
+ ruff check src tests
178
+ ```
179
+
180
+ The tests run offline against real evidence: a TDX quote captured on a VoltageGPU H200 VM on
181
+ 4 September 2026, NRAS tokens from 4 and 10 September 2026 (single H200, 8x H100 node in
182
+ NVIDIA Protected PCIe mode), and a snapshot of Intel's collateral and NVIDIA's JWKS.
183
+
184
+ ## Security
185
+
186
+ See `SECURITY.md`. In one line: report anything that would make `verify` say yes when it
187
+ should say no to contact@voltagegpu.com, and expect an answer within two working days.
188
+
189
+ ## License
190
+
191
+ MIT. Copyright 2026 VOLTAGE EI (VoltageGPU).
@@ -0,0 +1,136 @@
1
+ # voltage-verify
2
+
3
+ Bind an Intel TDX quote and an NVIDIA GPU attestation to the workload you meant to run, then
4
+ verify the bundle on your own machine, without trusting the cloud provider.
5
+
6
+ `voltage-verify` is a small command line tool with three roles:
7
+
8
+ 1. **On your machine**, it writes a *manifest*: the container image digest, the digests of the
9
+ model or files you care about, a free-text statement, and a fresh random challenge. Two
10
+ hashes of that manifest become the *commitments*.
11
+ 2. **Inside the confidential VM**, it asks the hardware to sign those commitments: the Intel
12
+ TDX quote carries `SHA-512(manifest)` as its 64-byte `report_data`, and NVIDIA's Remote
13
+ Attestation Service (NRAS) signs GPU claims over the nonce `SHA-256(manifest)`. It writes
14
+ one JSON *bundle* with the quote, the NVIDIA tokens and the public collateral needed to
15
+ check them later.
16
+ 3. **Back on your machine**, it verifies the bundle: Intel's signature chain to the pinned
17
+ Intel SGX Root CA, the platform's TCB status against Intel's published TCB info, the
18
+ Quoting Enclave identity, revocation lists, NVIDIA's ES384 signatures against NRAS's JWKS,
19
+ the per-GPU claims (measurements ok, secure boot on, debug off), and above all that both
20
+ proofs carry *your* commitments. Then it runs six negative tests to show that any change
21
+ to the manifest, the challenge, the quote or a GPU claim is rejected.
22
+
23
+ It was written by [VoltageGPU](https://voltagegpu.com) so that tenants of its Confidential VMs
24
+ can verify more than "this is a TDX VM with a confidential GPU": they can verify that the two
25
+ hardware proofs were produced *for the workload described in a manifest they wrote*, on a
26
+ challenge they chose. The trust chain ends at Intel and NVIDIA, never at VoltageGPU.
27
+
28
+ ## What it proves, and what it does not
29
+
30
+ Verified means:
31
+
32
+ * the TDX quote was produced inside a genuine Intel TDX Trust Domain, on a platform whose
33
+ provisioning certificate chains to Intel's root, at an acceptable TCB level, by a genuine
34
+ Quoting Enclave, and it embeds `SHA-512` of your manifest;
35
+ * NVIDIA's service signed, over `SHA-256` of your manifest, that the GPU(s) in that VM passed
36
+ attestation with secure boot on and debugging off;
37
+ * both proofs were made after you issued the challenge, so they cannot be replayed from an
38
+ earlier session or copied from another tenant.
39
+
40
+ Verified does **not** mean:
41
+
42
+ * that the GPU *executed* the image or model named in the manifest. Binding a manifest to a
43
+ quote proves the hardware signed your description of the workload; proving that this exact
44
+ code ran needs a measured launcher (for instance the Confidential Containers project with
45
+ a key broker), which is outside this tool;
46
+ * anything about the VM's own software stack beyond what the TDX measurements (`MRTD`,
47
+ `RTMR0..3`) say. The tool prints them; comparing them against a reference image is your
48
+ policy, not the tool's;
49
+ * anything about a VM you did not attest yourself.
50
+
51
+ `docs/WHAT_IT_PROVES.md` goes through every check and its limit.
52
+
53
+ ## Install
54
+
55
+ ```
56
+ # verifier machine: Python 3.10+, cryptography, PyJWT
57
+ pip install voltage-verify
58
+ # inside the VM: the NVIDIA SDK first (it pins cryptography and PyJWT), then the tool
59
+ pip install nv-attestation-sdk nvidia-ml-py
60
+ pip install --no-deps voltage-verify
61
+ ```
62
+
63
+ Source and issues: https://github.com/Jabsama/voltage-verify. The same wheel and source
64
+ archive are mirrored with SHA-256 sums at https://voltagegpu.com/blog/two-proofs/voltage-verify/
65
+ for installs that must not touch PyPI (`pip install <wheel URL>`).
66
+
67
+ ## Reference run
68
+
69
+ `examples/hello-workload/` holds a real bundle captured on 12 September 2026 on a VoltageGPU
70
+ `h100-xlarge` Confidential VM (8x H100, NVIDIA Protected PCIe mode), with its manifest and the
71
+ unedited run log. Replay the verification on your own machine:
72
+
73
+ ```
74
+ voltage-verify verify examples/hello-workload/bundle-8xh100-2026-09-12.json \
75
+ --challenge ef7f54c160627ee536a02b5e73896ac4b1ac2cdefdb7cfaaf2366a7d33cc8731 --hwmodel GH100 --gpus 8
76
+ voltage-verify selftest examples/hello-workload/bundle-8xh100-2026-09-12.json
77
+ ```
78
+
79
+ Expected: every check `PASS`, platform TCB `UpToDate`, Quoting Enclave `UpToDate`, eight
80
+ `GH100` devices with `measres success`, then six mutations rejected.
81
+
82
+ ## Use
83
+
84
+ On your machine, describe the workload and generate a challenge:
85
+
86
+ ```
87
+ voltage-verify manifest --image ghcr.io/you/app:1.4.2 --artifact model.safetensors \
88
+ --statement "inference run for customer X" -o manifest.json
89
+ ```
90
+
91
+ Copy `manifest.json` into the VM (scp), then, as root inside the VM:
92
+
93
+ ```
94
+ sudo -E python -m voltage_verify attest --manifest manifest.json -o bundle.json
95
+ ```
96
+
97
+ Copy `bundle.json` back, then:
98
+
99
+ ```
100
+ voltage-verify verify bundle.json --challenge <the challenge printed by `manifest`>
101
+ voltage-verify selftest bundle.json --challenge <same>
102
+ voltage-verify verify bundle.json --offline # same checks, from the collateral in the bundle
103
+ ```
104
+
105
+ Exit code 0 means verified, 1 means a required check failed, 2 means the bundle or arguments
106
+ are unusable. `--json` prints the machine-readable report.
107
+
108
+ ## Bundle format
109
+
110
+ Documented in `docs/BUNDLE_FORMAT.md`. In short: the manifest verbatim, both commitments, the
111
+ raw TDX quote (base64), the NRAS token array as returned by the NVIDIA SDK, NRAS's JWKS and
112
+ Intel's TCB info, QE identity and CRLs as fetched at attestation time, plus a few facts about
113
+ the VM (kernel, driver, `nvidia-smi conf-compute -q`). The verifier trusts none of it: it
114
+ recomputes the commitments from the manifest and checks every signature.
115
+
116
+ ## Development
117
+
118
+ ```
119
+ python -m venv .venv && . .venv/bin/activate
120
+ pip install -e ".[dev]"
121
+ pytest
122
+ ruff check src tests
123
+ ```
124
+
125
+ The tests run offline against real evidence: a TDX quote captured on a VoltageGPU H200 VM on
126
+ 4 September 2026, NRAS tokens from 4 and 10 September 2026 (single H200, 8x H100 node in
127
+ NVIDIA Protected PCIe mode), and a snapshot of Intel's collateral and NVIDIA's JWKS.
128
+
129
+ ## Security
130
+
131
+ See `SECURITY.md`. In one line: report anything that would make `verify` say yes when it
132
+ should say no to contact@voltagegpu.com, and expect an answer within two working days.
133
+
134
+ ## License
135
+
136
+ MIT. Copyright 2026 VOLTAGE EI (VoltageGPU).
@@ -0,0 +1,32 @@
1
+ # Security policy
2
+
3
+ `voltage-verify` is a verifier. The bugs that matter are the ones that make it accept
4
+ evidence it should reject: a signature check that can be skipped, a commitment that can be
5
+ recomputed without the hardware noticing, a policy claim that is read but not enforced, a
6
+ collateral document accepted without its signature.
7
+
8
+ ## Reporting
9
+
10
+ Write to contact@voltagegpu.com with the subject `voltage-verify security`. Include the bundle
11
+ or the minimal input that triggers the behaviour, the version (`voltage-verify --version`) and
12
+ what you expected. You will get a human answer within two working days, a fix or a documented
13
+ limitation within thirty, and credit in the changelog if you want it.
14
+
15
+ Please do not open a public issue for a bypass before it is fixed.
16
+
17
+ ## Scope
18
+
19
+ In scope: everything under `src/voltage_verify`, the bundle format, the documented checks in
20
+ `docs/WHAT_IT_PROVES.md`.
21
+
22
+ Out of scope: the security of Intel TDX or NVIDIA confidential computing themselves, the
23
+ availability of Intel's PCS or NVIDIA's NRAS, and the `attest` command running on a machine
24
+ that is already compromised at the hypervisor level (that is what the hardware proofs detect).
25
+
26
+ ## What the tool pins
27
+
28
+ * Intel SGX Root CA, by SHA-256 fingerprint, shipped in the package
29
+ (`src/voltage_verify/data/intel_sgx_root_ca.pem`).
30
+ * NVIDIA NRAS issuer `https://nras.attestation.nvidia.com` and its JWKS, fetched over TLS or
31
+ embedded in the bundle at attestation time.
32
+ * Accepted JWT algorithms: ES384 and ES256 only. `none`, HMAC and RSA are rejected.
@@ -0,0 +1,62 @@
1
+ # Running `attest` inside a Confidential VM
2
+
3
+ `attest` needs three things the VM must expose: the TDX guest device and configfs TSM
4
+ (`/sys/kernel/config/tsm/report`), an NVIDIA GPU in confidential-computing mode with the
5
+ driver's attestation support, and outbound HTTPS to NVIDIA (NRAS, OCSP, RIM) and Intel (PCS).
6
+ On a VoltageGPU Confidential VM all three are there at boot.
7
+
8
+ ## One-time setup in the VM
9
+
10
+ ```
11
+ sudo apt-get update
12
+ sudo apt-get install -y python3-venv python3-pip
13
+ python3 -m venv ~/vv
14
+ . ~/vv/bin/activate
15
+ pip install nv-attestation-sdk nvidia-ml-py
16
+ pip install --no-deps voltage-verify
17
+ ```
18
+
19
+ Install the NVIDIA SDK first: it pins `cryptography==43.0.1` and `PyJWT 2.7`, both inside the
20
+ ranges this tool accepts, and pulls the NVIDIA local verifier and `nvidia-ml-py`. The first
21
+ install takes a minute. `pip install "voltage-verify[attest]"` in one step also works, but
22
+ letting pip resolve both at once is slower on the VM than the two commands above. Without
23
+ PyPI access, install the wheel mirrored at
24
+ https://voltagegpu.com/blog/two-proofs/voltage-verify/ with `--no-deps`.
25
+
26
+ ## Multi-GPU nodes (NVIDIA Protected PCIe mode)
27
+
28
+ On an 8-GPU Hopper node the GPUs run in NVIDIA's multi-GPU *Protected PCIe* mode. `nvidia-smi
29
+ conf-compute -q` shows `CC State: OFF` next to `Multi-GPU Mode: Protected PCIe`; that is the
30
+ normal reading for that mode, not a failure. Two things differ from a single-GPU VM:
31
+
32
+ * the ready state has to be set once after boot: `sudo nvidia-smi conf-compute -srs 1`;
33
+ * the NVIDIA SDK refuses "standalone" attestation on such a node, so `attest` calls it with
34
+ `ppcie_mode=False` (this SDK flag means "not standalone"). `--mode auto` picks this when
35
+ more than one GPU is present.
36
+
37
+ ## Produce the bundle
38
+
39
+ Copy the manifest your verifier produced, then run as root (TSM needs it):
40
+
41
+ ```
42
+ sudo -E ~/vv/bin/python -m voltage_verify attest --manifest manifest.json -o bundle.json
43
+ ```
44
+
45
+ What happens, in order:
46
+
47
+ 1. the manifest is validated and both commitments are computed;
48
+ 2. `report_data = SHA-512(manifest)` is written to a fresh entry under
49
+ `/sys/kernel/config/tsm/report/`, the quote is read from `outblob` (retry only on
50
+ `EINVAL`, which signals a concurrent request; any other error stops);
51
+ 3. the NVIDIA SDK is called with `nonce = SHA-256(manifest)` against NRAS;
52
+ 4. NRAS's JWKS and Intel's TCB info, QE identity and CRLs are fetched and embedded;
53
+ 5. `bundle.json` is written. Nothing secret is in it: quote, public tokens, public collateral,
54
+ and a few `nvidia-smi` lines.
55
+
56
+ Copy `bundle.json` back to your machine and verify it there. The VM's own opinion of the
57
+ bundle is worth nothing; that is the point.
58
+
59
+ ## Timing and cost
60
+
61
+ On a single-H200 VM the whole `attest` step takes about one minute after the SDK is installed.
62
+ Release the VM when you have the bundle; the evidence does not depend on the VM staying up.
@@ -0,0 +1,69 @@
1
+ # Bundle format `voltage-verify-bundle/1`
2
+
3
+ A bundle is one JSON document. Keys are sorted when written; readers must not rely on order.
4
+
5
+ ```json
6
+ {
7
+ "format": "voltage-verify-bundle/1",
8
+ "tool": {"name": "voltage-verify", "version": "0.1.0"},
9
+ "created_at": "2026-09-12T01:02:03+00:00",
10
+ "manifest": {
11
+ "format": "voltage-verify-manifest/1",
12
+ "created_at": "2026-09-12T00:58:11+00:00",
13
+ "challenge": "<64 hex chars, chosen by the verifier>",
14
+ "workload": {
15
+ "image": {"reference": "ghcr.io/you/app:1.4.2", "digest": "sha256:<64 hex>"},
16
+ "artifacts": [{"name": "model.safetensors", "sha256": "<64 hex>", "size": 123456}],
17
+ "extra": {"any": "string"}
18
+ },
19
+ "statement": "free text or null"
20
+ },
21
+ "commitments": {"sha256": "<64 hex>", "sha512": "<128 hex>"},
22
+ "tdx": {"quote_b64": "<base64 of the raw quote, padding removed>", "report_data_hex": "<128 hex>"},
23
+ "nvidia": {
24
+ "mode": "single-gpu | multi-gpu-ppcie",
25
+ "nras": [["JWT", "<overall>"], {"REMOTE_GPU_CLAIMS": [["JWT", "<verifier>"], {"GPU-0": "<jwt>"}]}],
26
+ "jwks": {"keys": [ ... ]}
27
+ },
28
+ "collateral": {
29
+ "intel": {
30
+ "tcb_info": {"kind": "tcb_info", "body": "<exact PCS response>", "issuer_chain_pem": "<PEM chain>"},
31
+ "qe_identity": {"kind": "qe_identity", "body": "<exact PCS response>", "issuer_chain_pem": "<PEM chain>"},
32
+ "pck_crl_pem": "<PEM CRL or null>",
33
+ "root_crl_der_b64": "<base64 DER CRL or null>",
34
+ "fetched_at": "2026-09-12T01:02:00+00:00"
35
+ }
36
+ },
37
+ "environment": {"kernel": "...", "gpus": "...", "conf_compute": "..."}
38
+ }
39
+ ```
40
+
41
+ ## Commitments
42
+
43
+ `canonical = JSON(manifest)` with keys sorted by code point, separators `,` and `:` with no
44
+ spaces, UTF-8, non-ASCII characters kept as is, no floats anywhere. This matches RFC 8785 for
45
+ the value types a manifest contains.
46
+
47
+ * `commitments.sha256 = SHA-256(canonical)`, hex. This is the NVIDIA nonce: the SDK passes it
48
+ to NRAS, which returns it in the verifier token as `eat_nonce`.
49
+ * `commitments.sha512 = SHA-512(canonical)`, hex. This is the TDX `report_data`: written to
50
+ the configfs TSM `inblob`, returned verbatim at byte offset 568 of the quote.
51
+
52
+ A verifier recomputes both from `manifest` and ignores the stored values except to flag a
53
+ mismatch. Everything binding is inside the signed evidence.
54
+
55
+ ## Why the collateral travels with the bundle
56
+
57
+ Intel's TCB info and QE identity are re-issued regularly and NVIDIA rotates its JWKS keys
58
+ within days. A bundle verified six months later would otherwise fail for reasons unrelated
59
+ to the evidence. The embedded copies are signed by Intel (ECDSA P-256 over the exact response
60
+ body, issuer chain to the pinned Intel SGX Root CA) and by NVIDIA (x5c chain in the JWKS),
61
+ so `verify --offline` still ends at a hardware vendor's key. `verify` without `--offline`
62
+ refetches everything and reports which source it used.
63
+
64
+ ## Compatibility rules
65
+
66
+ * A reader must reject any `format` it does not know.
67
+ * Fields may be added in later minor formats; unknown fields are ignored.
68
+ * `nras` is stored exactly as the NVIDIA SDK returns it, so any change in the SDK layout
69
+ shows up as a verification failure rather than a silent reinterpretation.
@@ -0,0 +1,49 @@
1
+ # What each check proves, and what it does not
2
+
3
+ `voltage-verify verify` prints one line per check. This page is the honest reading of each.
4
+
5
+ ## Manifest
6
+
7
+ | Check | Passes when | Proves | Does not prove |
8
+ |---|---|---|---|
9
+ | `manifest.format` | the manifest has the expected shape | the bundle is parseable | anything |
10
+ | `manifest.commitments` | SHA-256 and SHA-512 of the canonical manifest equal the stored values | bookkeeping is consistent | anything: an attacker can recompute them |
11
+ | `manifest.challenge` | the challenge equals the one you passed with `--challenge` | the bundle was made for this session | anything without the TDX and NVIDIA checks below |
12
+ | `manifest.image` | the image digest equals `--image-digest` | the manifest names the image you expect | that the image ran |
13
+
14
+ ## Intel TDX
15
+
16
+ | Check | Passes when | Proves | Does not prove |
17
+ |---|---|---|---|
18
+ | `tdx.structure` | version 4 quote, TEE type TDX, ECDSA-P256 key, QE report and PCK chain present | it is a TDX quote | anything about its origin |
19
+ | `tdx.report_data` | the quote's 64-byte `report_data` equals `SHA-512(manifest)` | the quote was requested with your manifest hash, so after your challenge | who requested it |
20
+ | `tdx.signatures` | attestation key signs header+report; QE report binds the key; PCK certificate signs the QE report; PCK chain verifies to the pinned Intel SGX Root CA and is within validity | the quote was produced by a genuine Intel TDX Quoting Enclave on Intel-provisioned hardware | that the platform's firmware is current |
21
+ | `tdx.collateral` | TCB info and QE identity carry Intel's signature and chain to the root | the collateral is Intel's | freshness (see `tdx.collateral_fresh`) |
22
+ | `tdx.tcb` | the platform's SVNs (from the PCK certificate and the quote's `tee_tcb_svn`) reach a level Intel rates `UpToDate` or `SWHardeningNeeded`; the TDX module identity matches; the Quoting Enclave identity matches and is `UpToDate` | the platform is patched to a level Intel accepts | that no unknown vulnerability exists |
23
+ | `tdx.revocation` | the PCK certificate and its CA are absent from Intel's CRLs | Intel has not revoked this platform's provisioning identity | anything if CRLs are missing (then the line says NOT checked) |
24
+
25
+ The quote's `MRTD` and `RTMR0..3` are printed as facts. They measure the VM's initial state
26
+ and boot chain. This tool does not compare them to a reference: whether a given `MRTD` is the
27
+ image you expect is a policy decision that belongs to you.
28
+
29
+ ## NVIDIA
30
+
31
+ | Check | Passes when | Proves | Does not prove |
32
+ |---|---|---|---|
33
+ | `nvidia.jwks` | a JWKS is available (live or embedded) | keys can be looked up | anything |
34
+ | `nvidia.signatures` | the verifier token and every device token verify (ES384) with a key from NVIDIA's JWKS, issuer is NRAS | NVIDIA issued these claims | when, until `nvidia.freshness` |
35
+ | `nvidia.nonce` | `eat_nonce` equals `SHA-256(manifest)` | the claims were issued for your manifest hash, after your challenge | which VM: the TDX side does that |
36
+ | `nvidia.policy` | overall result true; every GPU: `measres` success, `secboot` true, `dbgstat` disabled, nonce matched, report signature verified, certificate chain validated; optional `--hwmodel` and `--gpus` | NVIDIA's service accepted the GPU's measurements and configuration | that the GPU executed your workload |
37
+ | `nvidia.freshness` | the verifier token's `iat` is within 15 minutes of the bundle's `created_at` | the token belongs to this attestation session | anything if the VM clock is wrong (the check then fails, which is the safe direction) |
38
+
39
+ On a multi-GPU node in NVIDIA Protected PCIe mode, the GPUs are attested as a set through the
40
+ same flow (`nvidia.mode = multi-gpu-ppcie`). NVSwitch attestation is not part of the bundle.
41
+
42
+ ## The gap this tool does not close
43
+
44
+ Both proofs are bound to a description of the workload. Neither proof says that the
45
+ described image or model was what the GPU computed on. Closing that gap requires a measured
46
+ launch: a component inside the VM that measures the container image and the model before
47
+ starting them and extends a TDX runtime measurement (`RTMR`) with the result, so that the
48
+ quote itself carries the measurement. The Confidential Containers project (Kata + Trustee)
49
+ and similar stacks do this. `voltage-verify` stops one step earlier on purpose, and says so.