TPM Device Identity
The TPM Device Identity (DevID) method attests agents running on hosts that have been provisioned with a Trusted Platform Module (TPM) and a DevID certificate. Trust is anchored in an externally-issued identity certificate bound to a TPM-resident key. The agent proves both that it controls the DevID private key and that the key physically resides in a specific TPM chip.
The Trust Domain Server issues a two-part hardware-rooted challenge. Neither part can be satisfied without the other, and neither can be satisfied by a software emulator or a copy of the key.
Choosing between EK and DevID. EK attestation anchors trust in the TPM manufacturer's Endorsement Key and requires no per-host provisioning, but the only identity available is the chip itself. DevID attestation requires you to issue and provision an owner-controlled certificate onto each host, in exchange for meaningful, owner-managed identities (such as a subject Common Name) that you can rotate and revoke independently of the TPM manufacturer. DevID also provides all the guarantees of EK attestation.
What Is DevID Attestation?
A Device Identity (DevID) consists of a private key and a digital certificate pre-provisioned on a device that asserts the device's identity. The DevID private key is TPM-resident and never leaves the chip. The certificate contains the corresponding public key and is issued by a DevID Certificate Authority (CA) that the Trust Domain Server trusts.
An IDevID (Initial Device Identifier) is a permanent, manufacturer-installed identity burned into the TPM at the factory, tied to the device's Endorsement Key and intended to uniquely identify the hardware for its lifetime. An LDevID (Local Device Identifier) is a locally-issued identity provisioned by the device owner after deployment, typically scoped to a specific administrative domain and revocable/replaceable as ownership or policy changes.
This attestor only works with Local DevIDs (LDevIDs), not Initial DevIDs (IDevIDs).
Each successful attestation combines three independent proofs, in this order:
- DevID co-residency. The agent's TPM generates a fresh Attestation Key (AK) and uses it to internally certify that the DevID key is also resident in the same chip. The Trust Domain Server verifies that certification, confirming the DevID key and the AK live in the same TPM.
- DevID ownership. The agent signs a fresh nonce with the DevID private key. Only the holder of that key (the TPM) can produce a valid signature. The Trust Domain Server verifies the signature against the DevID certificate's public key.
- TPM hardware binding. The Trust Domain Server issues an encrypted credential bound to both the agent's specific Endorsement Key (EK) and the same fresh AK. Only the exact TPM that holds both keys can open it.
This attestor includes the same guarantees as the TPM Endorsement Key attestor, and adds additional guarantees specific to DevID certificates.
Attributes available for SVID issuance
The following attributes are produced for a successfully attested agent. All attributes have the origin tpm_devid.
| Attribute | Description | Availability |
|---|---|---|
tpm_devid.certificate.fingerprint | SHA-1 fingerprint of the DevID leaf certificate (lowercase hex). Uniquely identifies the credential. | Always |
tpm_devid.certificate.serial_number | Serial number of the DevID certificate (lowercase hex). | Always |
tpm_devid.certificate.subject_cn | Subject Common Name of the DevID certificate. | Always |
tpm_devid.certificate.issuer_cn | Issuer Common Name of the DevID certificate. | Always |
tpm_devid.ek.public_hash | SHA-256 fingerprint of the TPM's endorsement public key. Uniquely identifies the chip. | Always |
tpm_devid.ek.serial_number | Serial number of the EK certificate (lowercase hex). | Only when an EK certificate is present |
tpm_devid.ek.manufacturer | Manufacturer identifier from the EK certificate (e.g., id:4E544300 for Nuvoton). See the Vendor ID Registry for reference. | Only when EK certificate includes TPM identity fields |
tpm_devid.ek.model | TPM model name from the EK certificate. | Only when EK certificate includes TPM identity fields |
tpm_devid.ek.version | TPM firmware version from the EK certificate. | Only when EK certificate includes TPM identity fields |
Example SPIFFE ID template using the DevID credential fingerprint:
/agents/tpm-devid/{{tpm_devid.certificate.fingerprint}}
Computing the EK Public Hash
To pre-populate an allowedEKHashes list from a known EK certificate:
openssl x509 -in ek.pem -pubkey -noout \
| openssl pkey -pubin -outform DER \
| sha256sum \
| awk '{print $1}'
How to Deploy
Step 1 — Update cluster configuration
Configure the AgentAttestation policy with trust anchors for the DevID certificate and the EK.
CA-based validation (trust any TPM whose EK cert chains to this CA):
section: AgentAttestation
schema: v1
spec:
policies:
- name: tpm_devid_policy
requiredAttestors:
- type: tpm_devid
config:
devIDCACerts: |
-----BEGIN CERTIFICATE-----
MIIBxTCCAW...
-----END CERTIFICATE-----
endorsementCACerts: |
-----BEGIN CERTIFICATE-----
MIIBxTCCAW...
-----END CERTIFICATE-----
Apply it using spirlctl:
spirlctl config set cluster --id <cluster-id> attestation-policy.yaml
Or using Terraform:
resource "spirl_cluster_config" "agent_attestation" {
cluster_id = spirl_cluster.my_cluster.id
sections = {
AgentAttestation = <<-YAML
section: AgentAttestation
schema: v1
spec:
policies:
- name: tpm_devid_policy
requiredAttestors:
- type: tpm_devid
config:
devIDCACerts: |
-----BEGIN CERTIFICATE-----
MIIBxTCCAW...
-----END CERTIFICATE-----
endorsementCACerts: |
-----BEGIN CERTIFICATE-----
MIIBxTCCAW...
-----END CERTIFICATE-----
YAML
}
}
Once a configuration document passes validation and is stored, the Defakto control plane syncs it to your Trust Domain Servers automatically. No server or agent restart is required.
Hash allow-list (trust only specific, known chips):
section: AgentAttestation
schema: v1
spec:
policies:
- name: tpm_devid_policy
requiredAttestors:
- type: tpm_devid
config:
devIDCACerts: |
-----BEGIN CERTIFICATE-----
MIIBxTCCAW...
-----END CERTIFICATE-----
allowedEKHashes:
- "0e09c2d1b430e324..."
Combined (EK passes if it satisfies either check):
section: AgentAttestation
schema: v1
spec:
policies:
- name: tpm_devid_policy
requiredAttestors:
- type: tpm_devid
config:
devIDCACerts: |
-----BEGIN CERTIFICATE-----
MIIBxTCCAW...
-----END CERTIFICATE-----
endorsementCACerts: |
-----BEGIN CERTIFICATE-----
MIIBxTCCAW...
-----END CERTIFICATE-----
allowedEKHashes:
- "0e09c2d1b430e324..."
Server Configuration Reference
| Field | Required | Description |
|---|---|---|
devIDCACerts | Required | PEM-encoded CA certificates that anchor the DevID certificate chain. |
endorsementCACerts | *Required | PEM-encoded manufacturer CA certificates. Any TPM whose EK cert chains to one of these CAs is trusted. |
allowedEKHashes | *Required | List of hex-encoded SHA-256 fingerprints of trusted EK public keys. |
* The EK can be trusted via CA-based validation, an explicit hash allow-list, or both. At least one of endorsementCACerts or allowedEKHashes must be present.
Step 2 — Configure the Agent
The agent loads the DevID certificate and the DevID key blobs from the local filesystem. Provisioning these files onto the host is handled by the customer's enterprise PKI tooling and is outside the scope of this document.
The certificate is a standard PEM file. The DevID key is stored on disk as a pair of TPM key blobs (typically the .pub and .priv files produced by tpm2_create):
- Public area (
.pub) — the DevID public key and its TPM attributes. - Private area (
.priv) — the DevID private key wrapped (encrypted) by a TPM-resident parent key.
The DevID private key never leaves the TPM. When the agent needs a signature, it loads both blobs into the chip; the TPM unwraps the private area internally using its parent key, and the signing operation runs inside the chip. The parent key is hardware-bound, so the private-area blob can only be unwrapped on the TPM that produced it.
The agent process needs read access to the TPM resource manager device (typically /dev/tpmrm0) and to each file referenced below.
- Helm Installation
- Linux Installation
agent:
auth:
clusterId: c-xxxxxx
attestors:
- type: tpm_devid
config:
devIDCertPath: /etc/spirl/agent/devid/devid.crt
devIDPubPath: /etc/spirl/agent/devid/devid.pub
devIDPrivPath: /etc/spirl/agent/devid/devid.priv
# devIDKeyPassword: "" # optional
# ownerHierarchyPassword: "" # optional
# endorsementHierarchyPassword: "" # optional
The agent pod requires access to the host TPM device and to the DevID files. Add a hostPath volume mount for /dev/tpmrm0 and mount the directory containing the DevID cert and key blobs into the agent pod.
cluster-id: c-xxxxxx
disable-kubernetes-attestation: true
agent-attestors:
- type: tpm_devid
config:
devIDCertPath: /etc/spirl/agent/devid/devid.crt
devIDPubPath: /etc/spirl/agent/devid/devid.pub
devIDPrivPath: /etc/spirl/agent/devid/devid.priv
# devIDKeyPassword: "" # optional
# ownerHierarchyPassword: "" # optional
# endorsementHierarchyPassword: "" # optional
Agent Configuration Reference
| Field | Required | Description |
|---|---|---|
devIDCertPath | Yes | Path to a file containing the PEM-encoded DevID certificate chain, leaf first. Multiple certificates may be concatenated. |
devIDPubPath | Yes | Path to a file containing the public part of the DevID key (e.g., the .pub output of tpm2_create). The agent reads it as-is — no encoding expected. |
devIDPrivPath | Yes | Path to a file containing the private part of the DevID key (e.g., the .priv output of tpm2_create). |
devIDKeyPassword | No | Password for the DevID key, if the key was created with one. Default: "". |
ownerHierarchyPassword | No | Owner hierarchy password for the TPM. Default: "". |
endorsementHierarchyPassword | No | Endorsement hierarchy password for the TPM. Default: "". |
Step 3 — Verify
Server logs — look for these in order:
"Login started with multi-attestation support"— confirms the agent offeredprovidedMethods: ["tpm_devid"]."Authorization received and verified"— includesagentAttestationAttributeswith the DevID and EK identity:When the agent's TPM has no EK certificate, only{"msg": "Authorization received and verified","agentAttestationAttributes": ["tpm_devid:tpm_devid.certificate.fingerprint=\"a3f1c82bd4e9f07c...\"","tpm_devid:tpm_devid.certificate.subject_cn=\"host-42.example.com\"","tpm_devid:tpm_devid.ek.public_hash=\"0e09c2d1b430e324...\"","tpm_devid:tpm_devid.ek.manufacturer=\"id:4E544300\""]}tpm_devid.ek.public_hashis emitted from the EK group; thecertificate.*attributes are still present."Connected to agent"— session is fully established.
Agent logs — enable debug logging to see "Sending Login" with attestors: ["tpm_devid"]. At the default log level, "Connected to server" confirms the session is live.
Metrics — confirm proofs are succeeding:
spirl_attestation_signer.proof{attestor_type="tpm_devid",outcome="success"}
spirl_attestation_agent.proof{attestor_type="tpm_devid",outcome="success"}
Alert on outcome="failed" to detect DevID or EK validation failures.
Common errors:
| Error | Likely cause |
|---|---|
no cluster policy authorizes the provided attestors | Agent's tpm_devid method does not match any policy in the cluster's AgentAttestation config |
EK validation failed | Neither allowedEKHashes nor endorsementCACerts accepted the presented EK |
read devIDCertPath ...: no such file or directory | The file at devIDCertPath does not exist or is not readable by the agent |
Security Considerations
TPM DevID attestation provides hardware-based proof that the agent controls a specific DevID key bound to a trusted TPM.
What the challenge proves: In a single session, the agent must sign a fresh nonce with the DevID private key, return the secret recovered from an encrypted credential bound to its EK and a fresh AK, and present an AK certification confirming the DevID key resides in the same TPM as the AK. Copying the DevID certificate to another machine fails the co-residency check; copying the EK certificate to another machine fails the encrypted credential challenge. Software TPM emulators are only accepted if their EK fingerprint appears in allowedEKHashes or their EK certificate is signed by a CA in endorsementCACerts.
Timing attack protection: The Trust Domain Server compares the credential activation secret returned by the agent in constant time, preventing information leakage from timing differences.
Session expiry: Each attestation attempt is tracked with a random identifier. If the agent does not complete the challenge within 5 minutes, the session is discarded. Once successfully answered, the session is removed immediately to prevent reuse.
EK Certificate requirements: When the agent supplies an EK certificate, the Trust Domain Server enforces strict requirements aligned with the TCG EK Credential Profile v2.6:
- The certificate must not be a CA certificate.
- Key usage must allow the TPM challenge operation.
- The certificate must include a valid issuer chain and TPM identity fields.
DevID certificate binding: The Trust Domain Server verifies that the DevID certificate's public key matches the DevID key the agent loaded into the TPM, preventing a DevID certificate from being paired with a key from a different TPM.
DevID key support: Both RSA and ECDSA TPM-resident signing keys are supported; the Trust Domain Server selects the verification algorithm automatically from the DevID certificate. The hash algorithm is fixed at SHA-256 — DevID keys configured with a different hash algorithm are rejected by the agent at startup and by the Trust Domain Server at attestation time.
Troubleshooting
| Error in Trust Domain Server logs | Likely cause |
|---|---|
devIDCACerts is required | The devIDCACerts field is missing from Managed Config |
at least one of endorsementCACerts or allowedEKHashes must be set | Managed Config has no EK trust configured |
devIDCACerts: could not parse any PEM certificates | The devIDCACerts value is not valid PEM |
endorsementCACerts: could not parse any PEM certificates | The endorsementCACerts value is not valid PEM |
allowedEKHashes[N]: expected 64-char hex SHA-256 hash | An entry in allowedEKHashes is not a 64-character hex string |
attestation policy not found or no matching policy | Managed Config has not been applied (Step 1 incomplete) |
verify DevID certificate chain | DevID certificate is not signed by a CA in devIDCACerts |
EK validation failed | Neither allowedEKHashes nor endorsementCACerts accepted the presented EK |
missing EK certificate: signer is not configured with an EK hash allow-list | Agent sent a proof without an EK cert, but the Trust Domain Server has no allowedEKHashes configured |
EK public key mismatch | The EK template blob does not match the public key in the EK certificate |
DevID certification verification failed | DevID key co-residency proof is invalid — possible tampering or mismatched blobs |
DevID signature verification failed | Agent failed to sign the DevID nonce — DevID private key mismatch |
DevID certificate public key does not match TPM-resident DevID key | The DevID certificate's public key does not match the file at devIDPubPath — possible cert/key mix-up across machines |
DevID key has unsupported hash algorithm ...: only SHA-256 is supported | Agent: the DevID key's signing scheme uses a hash other than SHA-256 |
DevID public: unsupported hash algorithm ...: only SHA-256 is supported | Trust Domain Server: the DevID public key declares a hash other than SHA-256 |
credential activation secret does not match | TPM returned the wrong secret — possible hardware mismatch or replay attempt |
devIDCertPath is required | Agent config is missing devIDCertPath |
devIDPubPath is required | Agent config is missing devIDPubPath |
devIDPrivPath is required | Agent config is missing devIDPrivPath |
read devIDCertPath ...: no such file or directory | The file at devIDCertPath does not exist or is not readable by the agent |
read devIDPubPath ...: no such file or directory | The file at devIDPubPath does not exist or is not readable by the agent |
read devIDPrivPath ...: no such file or directory | The file at devIDPrivPath does not exist or is not readable by the agent |
parse DevID certificate from ... | The file at devIDCertPath does not contain a valid PEM-encoded certificate |
unknown session ID | Internal error — agent sent a challenge response without a prior proof |