This repository started as a fork of https://github.com/rancher-sandbox/go-tpm with additional capabilities for TPM.
This library provides a complete implementation for remote attestation with a Key Management Service (KMS) using TPM-based cryptographic proofs over WebSocket connections. The flow supports both initial enrollment and subsequent verification seamlessly.
The remote attestation flow allows a machine to:
- Prove its TPM identity to a remote KMS
- Demonstrate boot state integrity via PCR measurements
- Obtain decryption passphrases securely over a WebSocket connection
The client doesn't need to know whether it's the first time contacting the KMS (enrollment) or a repeat visit (verification) — the same flow works for both.
- TPM Identity: Endorsement Key (EK) proves requests come from a genuine TPM
- Key Binding: Attestation Key (AK) is bound to the specific TPM chip
- Boot State Verification: PCRs 0, 7, 11 prove system integrity hasn't changed
- Connection Security: WebSocket connection provides session binding and prevents replay attacks
- Cryptographic Proof: TPM quotes and credential activation provide cryptographic proof of TPM ownership
For complete, working examples of how to use this library, please refer to the kcrypt-challenger repository.
The WebSocket flow uses these data structures for the attestation protocol:
Contains the credential activation challenge sent by the server.
Contains the secret from credential activation (proves TPM ownership) and the TPM quote (cryptographic proof of TPM state).
Contains the decryption passphrase returned by the server.
The library supports direct use with go-attestation library types (recommended approach). You can get EK and AttestationParameters directly and use go-attestation types for challenge generation.
The library provides helper functions for KMS WebSocket server implementation including:
- Parsing attestation data from client requests
- Generating credential activation challenge using go-attestation native types
- Validating challenge responses
- Verifying PCR quote signature and ensuring PCR values are cryptographically bound to the quote
Client Server
|-- WebSocket Connect --------->|
| |
|<------ Challenge -------------| Server sends AttestationChallengeResponse
| |
|------ ProofRequest --------->| Client proves TPM ownership
| |
|<------ ProofResponse ---------| Server sends passphrase
| |
Connection closed
The KMS WebSocket server should:
-
On WebSocket Connection:
- Upgrade HTTP connection to WebSocket
- Get client's attestation data (EK and AttestationParameters)
- Use
tpm.GenerateChallenge()to create credential activation challenge - Use PCR measurements to determine enrollment vs verification
- Store challenge secret for this specific WebSocket session
-
On ProofRequest:
- Use
tpm.ValidateChallenge()to verify the secret matches - Verify
PCRQuotesignature and content (optional) - Return decryption passphrase
- Close connection to prevent reuse
- Use
The WebSocket approach provides inherent security against replay attacks without requiring nonces:
-
Session Binding
- Each challenge is bound to a specific WebSocket connection
- Challenges cannot be replayed across different connections
- Connection state prevents skipping authentication steps
-
Sequential Protocol
- Server only sends passphrase after successful challenge resolution
- No separate endpoints - single sequential flow within the connection
- Impossible to "jump to step 2" without completing step 1
-
Automatic Cleanup
- Connection closure automatically invalidates any stored secrets
- No need for complex nonce expiry or cleanup mechanisms
- Natural session lifecycle management
Why WebSockets Prevent Replay Attacks:
- ✅ Fresh Connection Required: Each attestation requires a new WebSocket connection
- ✅ Fresh Challenge: Server generates a new challenge for each connection
- ✅ Session Isolation: Secrets are tied to the specific connection session
- ✅ Sequential Flow: Cannot skip challenge step to request passphrase
- ✅ Connection Closure: Automatic cleanup when connection ends
Attack Scenarios That Are Prevented:
-
Replaying Old Challenges: Attacker cannot reuse old challenge/response pairs because:
- They need a new WebSocket connection
- Server will generate a fresh challenge for the new connection
- Old challenge response won't match new challenge
-
Man-in-the-Middle: Even if attacker captures the entire flow:
- They still need to establish their own WebSocket connection
- Server will issue a different challenge
- Captured responses won't work with the new challenge
-
Session Hijacking: Connection-based security prevents:
- Interception of in-flight messages
- Reuse of authentication across sessions
- Bypassing the challenge step
- Simpler Code: No nonce generation, storage, or validation logic needed
- Better Performance: No database/cache operations for nonce management
- Natural Security: WebSocket protocol provides session binding
- Cleaner Architecture: Single connection handles entire flow
- Reduced Attack Surface: Fewer moving parts means fewer vulnerabilities
The VerifyPCRQuote function provides comprehensive verification of TPM PCR quotes:
- Signature Verification: Verifies the PCR quote signature using the Attestation Key (AK) public key
- PCR Consistency Check: Ensures the provided PCR values match what was actually quoted by the TPM
- Cryptographic Binding: Verifies that PCR values are cryptographically bound to the quote digest
- Authenticity: The quote signature proves the quote came from a genuine TPM
- Integrity: PCR values are verified against the TPM quote digest
- Non-repudiation: An attacker cannot provide fake PCR values without also providing a fake quote signature
The implementation reads and verifies these PCRs:
- PCR 0: BIOS/UEFI measurements
- PCR 7: Secure Boot state
- PCR 11: Unified Kernel Image (UKI) measurements
These PCRs establish the "golden" boot state during enrollment and verify it hasn't changed during subsequent requests.