PQC-signed hypervisor memory attestation framework for AI workloads. ML-DSA signed claims about memory region state, pluggable backends for AMD SEV-SNP and Intel TDX.
Project description
PQC Hypervisor Attestation
Sigstore for hypervisor memory attestation. When an AI workload runs inside a cloud VM, the hypervisor (KVM, QEMU, Hyper-V) is transparent: nothing cryptographically proves to the tenant that model weights in RAM have not been read or rewritten by a malicious host. This library is the post-quantum cryptographic envelope — MemoryRegion, AttestationClaim, AttestationReport, ML-DSA-signed, independently verifiable — that a hypervisor project, TEE runtime, or confidential-computing framework can plug its memory-reading primitives into. The library ships pluggable backends for AMD SEV-SNP and Intel TDX as stubs, plus a reference InMemoryBackend for tests.
The Problem
Cloud AI inference workloads place multi-hundred-megabyte model weights in guest memory. The hypervisor can read or rewrite every page. Today's tenants rely on contractual trust ("the cloud provider said they wouldn't") plus coarse platform-level attestation (MRTD, launch digest) that only covers VM boot — not the runtime state of the pages you actually care about. An attacker with host compromise, or a curious operator, can:
- Silently exfiltrate proprietary model weights.
- Swap in backdoored weights for a single request.
- Corrupt the KV cache to influence in-flight generations.
None of this is visible to the guest without a runtime memory attestation protocol. And any attestation that signs memory state with RSA or ECDSA today is retroactively forgeable once a CRQC exists — which is why the cryptographic envelope must be post-quantum from day one.
The Solution
Every attestation is a post-quantum signed, freshness-bounded claim about specific memory regions:
- SHA3-256 per-region content hashes — deterministic snapshot of what lives at those pages.
- ML-DSA (FIPS 204) signature over the canonical report bytes, by a known attester DID.
- Expiry and nonce for replay resistance.
- Expected-hash pinning so a remote verifier can detect drift from trusted state.
- Pluggable backends — the library never reads memory itself; backends do, using
/dev/sev-guest,/dev/tdx-guest, or whatever primitive the real TEE exposes.
Installation
pip install pqc-hypervisor-attestation
Development:
pip install -e ".[dev]"
Quick Start
from quantumshield.identity.agent import AgentIdentity
from pqc_hypervisor_attestation import (
AttestationVerifier,
Attester,
ContinuousAttester,
InMemoryBackend,
MemoryRegion,
RegionSnapshot,
)
# 1. Identity + signer.
identity = AgentIdentity.create("llama-host-attester", capabilities=["attest"])
attester = Attester(identity)
# 2. Backend with a pinned region.
backend = InMemoryBackend()
weights = MemoryRegion(
region_id="model-weights-0",
description="Llama weight shard 0",
address=0x1000,
size=128,
protection="RO",
)
content = b"\xaa" * 128
backend.register("model-serving-1", weights, content)
# 3. Continuous attester with pinned expected hash.
loop = ContinuousAttester(
attester=attester,
backend=backend,
workload_id="model-serving-1",
expected_hashes={weights.region_id: RegionSnapshot.hash_bytes(content)},
)
report = loop.attest_once()
result = AttestationVerifier.verify(report, strict=True)
assert result.valid
Architecture
+-----------------------------+ +------------------------------+
| AI workload (guest VM) | | Remote verifier |
| | | |
| ContinuousAttester | | AttestationVerifier |
| | | | | |
| v | | v |
| AttestationBackend | | - ML-DSA signature check |
| (SEV-SNP | TDX | memory) | | - expiry check |
| | | | - expected_hash pinning |
| v | | |
| MemoryRegion ---> RegionSnapshot -> AttestationClaim |
| | |
| v |
| AttestationReport (bundle) |
| | |
| v |
| ML-DSA sign (quantumshield) |
+-----------------------------+ +------------------------------+
| ^
| signed AttestationReport |
+---------------------------------+
Cryptography
| Primitive | Purpose | Algorithm |
|---|---|---|
| Region content hash | Fingerprint memory bytes | SHA3-256 |
| Report canonical digest | Input to signer | SHA3-256 |
| Attestation signature | Bind report to attester DID | ML-DSA-65 |
| Verifier trust anchor | Attester public key (from DID / keystore) | ML-DSA public |
All signing is delegated to quantumshield, which prefers real liboqs ML-DSA when available and falls back to transitional Ed25519.
Threat Model
| Adversary capability | Coverage |
|---|---|
| Forges an attestation report from scratch | Blocked — requires the attester's ML-DSA private key. |
| Replays an old valid report to hide drift | Blocked — expires_at bound + per-report nonce in each claim. |
| Rewrites model weights in guest memory | Detected — region snapshot hash diverges from expected_hash. |
| Substitutes a newer signed report from same key | Mitigated — verifier pins expected hashes independently. |
| Tampers with report fields in transit | Blocked — canonical-bytes + ML-DSA binds every field. |
| Q-day adversary with CRQC | Out of scope for ECDSA/RSA signers; covered here by ML-DSA. |
| Compromises the attester key via guest escape | Out of scope — mitigate with SEV-SNP / TDX sealed key storage. |
Backend Integration Guide
The library defines a single abstract interface:
class AttestationBackend(ABC):
name: str
platform: str
def list_regions(self, workload_id: str) -> list[MemoryRegion]: ...
def snapshot(self, region: MemoryRegion) -> RegionSnapshot: ...
Any backend that can enumerate memory ranges and hash their bytes can plug in.
AMD SEV-SNP (/dev/sev-guest)
The shipped AMDSEVSNPBackend is a stub that documents the expected behaviour. A real integration:
- Reads the SEV-SNP launch digest at VM start and stores per-region base/size in its workload manifest.
- For
list_regions, returnsMemoryRegionentries whoseaddressis the guest-physical base andsizeis the range length. - For
snapshot, issues theSNP_GET_REPORTioctl on/dev/sev-guest, reads the backing pages into a buffer, and returnsRegionSnapshot.create(region_id, buffer).
Intel TDX (/dev/tdx-guest)
IntelTDXBackend follows the same pattern using TDX_CMD_GET_REPORT0 and the TD's MRTD / RTMR measurements.
Your own backend
Subclass AttestationBackend, implement list_regions and snapshot, and pass an instance to ContinuousAttester. The library handles canonicalisation, signing, and verification uniformly.
API Reference
Data types
| Class | Description |
|---|---|
MemoryRegion |
Addressable range (region_id, address, size, protection). |
RegionSnapshot |
(region_id, content_hash, size, taken_at) SHA3-256 fingerprint. |
AttestationClaim |
One signed statement about one region at one point in time. |
AttestationReport |
Bundle of claims + ML-DSA envelope + expiry. |
VerificationResult |
Breakdown of signature / expiry / drift checks. |
Signers and verifiers
| Symbol | Purpose |
|---|---|
Attester |
Wraps an AgentIdentity; signs reports. |
AttestationVerifier |
Static verifier; returns VerificationResult. |
AttestationVerifier.verify_or_raise |
Raises RegionDriftError / AttestationVerificationError. |
ContinuousAttester |
Periodic loop: enumerate regions, snapshot, sign. |
Backends
| Class | Use |
|---|---|
InMemoryBackend |
Reference / tests / tutorials. |
AMDSEVSNPBackend |
Stub for AMD SEV-SNP (plug into /dev/sev-guest). |
IntelTDXBackend |
Stub for Intel TDX (plug into /dev/tdx-guest). |
Exceptions
HypervisorAttestationError -> InvalidRegionError, AttestationVerificationError (-> RegionDriftError), BackendError (-> UnknownBackendError).
Why PQC Matters for Hypervisor Attestation
Cloud confidential-computing deployments live for a decade or more. A VM image spun up in 2026 may still be attested by the same kind of signature in 2036 — long enough for a CRQC to exist. An attestation signed today with ECDSA or RSA can be retroactively forged by any adversary holding a recording of the public key and the signed payload: in 2035 they can manufacture a fresh, valid-looking "clean" attestation for a workload they actually tampered with in 2026, and no auditor can distinguish it from a real one. Post-quantum signatures break that chain: even with Shor's algorithm, ML-DSA remains unbroken, so historical attestations continue to bind the host to its claim. Hypervisor attestation is exactly the place that non-repudiation must survive the cryptographic transition.
Examples
examples/basic_attestation.py— end-to-end sign-and-verify over two in-memory regions.examples/detect_memory_tampering.py— mutate a region between attestations and watch drift surface.examples/continuous_loop_demo.py— run the periodic attestation loop and stream reports.
License
Apache 2.0. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pqc_hypervisor_attestation-0.1.0.tar.gz.
File metadata
- Download URL: pqc_hypervisor_attestation-0.1.0.tar.gz
- Upload date:
- Size: 19.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
66e558995b52c4b51ba11b1dd9a5f5951d41ebc0a546cdf5fc50da1e6d6dfd2e
|
|
| MD5 |
2e22c9df5d2b06280de7a22d38721ea9
|
|
| BLAKE2b-256 |
dbecd084843f50ef8af579f0047d625900abad5962f4693dede707bdd27477ee
|
File details
Details for the file pqc_hypervisor_attestation-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pqc_hypervisor_attestation-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a3daf775f7d9bbbb70da2a6788ed693b69a1cfea395daead30c6f695c8fc757e
|
|
| MD5 |
203cac04b722d64fc7c8d7986b3d59a0
|
|
| BLAKE2b-256 |
c469193b1d37d7a99170b10464f6920dbb5c3db013696610eb7eabdf29abb7b2
|