Threat Model
Teton treats the host OS, hypervisor, and cloud operator as untrusted. The trusted computing base is the enclave silicon, the measured workload, and the on-chain verifier.
Isolation comparison
Section titled “Isolation comparison”| Dimension | GCE Confidential VM (AMD SEV-SNP) | AWS Nitro Enclaves |
|---|---|---|
| Isolation | AES memory encryption plus Reverse Map Table | Nitro ASIC core and memory partition |
| Device | Linux /dev/sev-guest (SNP_GET_REPORT) |
Linux /dev/nsm (NSM_REQUEST_ATTESTATION) |
| Report | 1,184-byte binary, ECDSA P-384 / SHA-384 | COSE Sign1 CBOR, ECDSA P-384 |
| Root | AMD ARK → ASK → VCEK / VLEK | AWS Nitro Root CA → intermediate → leaf |
| Measurement | 48-byte SHA-384 launch digest | PCR0 (EIF), PCR1, PCR2, PCR8 |
| User binding | 64-byte REPORT_DATA |
user_data (32-byte pubkey) and nonce |
| Network | Full VM, encrypted RAM | No persistent disk, vsock only |
| On-chain path | register_vcek then verify_and_register / verify_atomic_with_nonce |
verify_nitro_attestation (mode 0 or 1) |
Cryptographic guarantees
Section titled “Cryptographic guarantees”The verifier binds three facts into every accepted report:
- Code identity. Measurement (SNP digest or Nitro PCR0) is on the
PolicyRegistryallowlist. An all-zero measurement fails closed (VerifierError::DisallowedMeasurement). - Key identity. Mode A
REPORT_DATA[0..32](or Nitrouser_data) equals the workload Ed25519 pubkey. Mode BREPORT_DATA[32..64]equalsSHA-256(slot_hash ‖ action_hash ‖ consumer_program_id). - Freshness.
SlotHashesatnonce_slotmust match, with ageclock.slot - nonce_slot ≤ 150slots. A miss isVerifierError::StaleNonce.
Replay inside that window fails with VerifierError::NonceAlreadyUsed. The tombstone is a UsedNonceAccount PDA seeded [b"nonce", signer_pubkey, nonce].
Mode B always consumes that PDA. verify_atomic returns VerifierError::NonceRequired and writes nothing (@spec TETON-SEC-005).
Fail-closed boundaries
Section titled “Fail-closed boundaries”| Gate | Failure |
|---|---|
| Debug / migrate policy bits | VerifierError::UnauthorizedPolicy (@spec TETON-SEC-001) |
TCB below min_tcb_* |
VerifierError::TcbBelowMinimum |
| P-384 / COSE signature | VerifierError::InvalidSignature |
Missing /dev/nsm or ioctl error |
Sidecar SidecarError::IoctlError (no synthetic production document) |
Missing Nitro cabundle |
CryptoError::InvalidAttestationPayload |
| HTTP bind off loopback | Sidecar refuses to listen |
require_nonce == false |
CpiError::NonceRequired |
| Packet above 1,232 bytes (legacy UDP) | TypeScript PacketTooLargeError |
The sidecar HTTP API binds only 127.0.0.1 or ::1. DRY_RUN defaults to true. The on-disk payer is a fee payer. It is never the workload signer.
What the TEE covers
Section titled “What the TEE covers”- Host memory dumps of the signing key
- Operator phishing of the hot wallet
- Launch-image substitution (measurement changes)
Residual risk
Section titled “Residual risk”- Side channels (Spectre, CacheWarp, INCEPTION). Mitigate with
min_tcbmicrocode floors. - Host I/O delay or drop. Sign inside the enclave before the payload leaves vsock.
- Host clock. Freshness uses Solana
SlotHashes, never guest wall time. - Mode A TTL. An attested Ed25519 key stays valid until
expires_slot(216_000slots). There is norevoke_signerinstruction. Consumers must callassert_attested_signer.