Safeguard
Supply Chain Security•

SPDM Device Attestation: How Hardware Proves Identity and Firmware

SPDM lets a host or BMC ask a NIC, GPU, SSD or CXL device for its certificate chain and a signed list of firmware measurements, then check both.

Safeguard Security Team
46 min read

SPDM, the DMTF Security Protocol and Data Model (DSP0274), is how a component such as a network card, GPU, SSD or CXL memory device proves who it is and what firmware it is running. The host or BMC asks for the device's X.509 certificate chain, challenges it to sign a fresh nonce with the matching private key, and asks for a signed list of firmware and configuration measurements to compare against known good values.

The same protocol then sets up encrypted sessions that PCIe and CXL use to key link encryption. This guide goes one level deeper than our hardware and firmware supply chain inventory guide and our HBOM vs SBOM explainer. It walks through every SPDM message that matters, how the certificate models chain to a manufacturer root, what a measurement block actually contains byte by byte, how secure sessions work, how a BMC exposes all of it through Redfish, where Caliptra and the Open Compute Project attestation requirements fit, how the evidence can feed a hardware bill of materials, and where the gaps still are. Every field name, version and date below comes from the specification or project document linked under Sources.

Key takeaways

  • SPDM is a DMTF standard. Version 1.0.0 was published on 16 October 2019; the current releases are 1.3.3 (24 October 2025) and 1.4.1 (26 June 2026). Version 1.4.0 (15 May 2025) added post quantum algorithms (ML-DSA and SLH-DSA signatures, ML-KEM key encapsulation).
  • Only three requests are mandatory for every responder: GET_VERSION (0x84), GET_CAPABILITIES (0xE1) and NEGOTIATE_ALGORITHMS (0xE3), plus RESPOND_IF_READY (0xFF) for slow replies. Identity and attestation use GET_DIGESTS (0x81), GET_CERTIFICATE (0x82), CHALLENGE (0x83) and GET_MEASUREMENTS (0xE0), all optional in the specification and required by most platform profiles.
  • A device holds up to eight certificate slots (0 to 7). Slot 0 must use either the device certificate model or the alias certificate model, and the chain should include a certificate carrying the Hardware identity OID, whose key pair stays the same across firmware versions.
  • A measurement block can report a ROM digest, a mutable firmware digest, hardware straps, firmware configuration, a firmware version string, an 8 byte security version number, a hash extended running value, a debug and device mode structure, or a manifest describing the other indices. The firmware version format is not standardised, which matters for inventory.
  • KEY_EXCHANGE and FINISH (or PSK_EXCHANGE and PSK_FINISH) create an authenticated, encrypted session using an HKDF key schedule. DSP0277 defines the secured record format. PCIe IDE key management and CXL's TEE Security Protocol run their messages through these sessions.
  • On servers, the BMC is usually the SPDM requester. Redfish models the result as a ComponentIntegrity resource with an SPDMGetSignedMeasurements action that takes your 32 byte nonce, a slot ID and measurement indices.
  • Attestation evidence is strong input for a hardware bill of materials, but it is not one: you still need reference values, a revocation story and a mapping from opaque digests and vendor version strings to the components you track.

What is the DMTF Security Protocol and Data Model?

SPDM is a message protocol defined by DMTF, a not for profit standards body best known for Redfish and the platform management specifications that BMCs use. The SPDM specification (DSP0274) describes two roles. A Requester sends requests. A Responder answers them. In a server the requester is usually the BMC, the host firmware or the operating system; the responder is a device with its own firmware: a network adapter, an accelerator, a storage controller, a memory expander, a power supply or the root of trust on a CPU package.

DMTF's own summary of the protocol's goals, from the SPDM 1.3 overview deck (May 2023), is two things: device attestation and authentication ("the ability to attest various aspects of a device such as firmware integrity and device identity") and secure communication over any transport. Each version built on that:

VersionWhat it added, per DMTF's overview and the change log in DSP0274
1.0 (2019)Measurements, device authentication (certificates and CHALLENGE)
1.1 (2020)Secure sessions with public key exchange or pre shared key, mutual authentication
1.2 (2021)Certificate installation (GET_CSR, SET_CERTIFICATE), alias certificates derived from device certificates, large message chunking, SM2, SM3 and SM4 algorithms
1.3 (2023)Event notifications inside sessions, multiple key pairs per algorithm, the generic certificate model, pending measurements after an update, the Measurement Extension Log and hash extended measurements, a structured measurement manifest, GET_ENDPOINT_INFO
1.4 (2025)Post quantum signatures and key encapsulation, extended capability flags, certificate slot management, opaque data in the session finish messages

SPDM itself says nothing about wires. It is carried by binding specifications. DMTF publishes DSP0275 (SPDM over MCTP, version 1.0.2 dated 8 October 2023), DSP0276 (secured messages over MCTP, version 1.3.0 dated 31 October 2025), DSP0286 (storage binding) and DSP0287 (TCP binding). MCTP, the Management Component Transport Protocol in DSP0236 (version 1.3.3, 25 March 2024), is the management bus fabric that BMCs use; its own physical bindings include SMBus and I2C (DSP0237) and PCIe vendor defined messages (DSP0238). PCI-SIG defines its own transport, the Data Object Exchange (DOE) mailbox in PCIe configuration space, and the Component Measurement and Authentication (CMA) rules that say how PCIe devices use SPDM through it.

Which devices speak SPDM?

SPDM responders show up in four device classes, going by the specifications and open source projects that implement them:

  • Network adapters and other management endpoints. Anything that already sits on the MCTP management bus next to the BMC can carry SPDM over DSP0275. The OpenBMC attestation design lists MCTP, PCIe DOE and TCP as the transports its SPDM daemon handles.
  • GPUs and accelerators. DMTF's reference library, libspdm, lists an open source GPU kernel module driver among its integrations, and CXL's confidential computing protocol (below) requires SPDM 1.2 or newer.
  • SSDs and storage. DSP0286 binds SPDM to storage security commands, and the Linux kernel's proposed SPDM requester names ATA, SCSI and NVMe as transports alongside PCIe, MCTP over SMBus or I3C, and TCP.
  • CXL devices. The CXL Consortium's Trusted Execution Environment Security Protocol (TSP) change notice states its scope includes "SPDM 1.2 or newer for authentication and attestation".

Support for a specific device, version and message set is up to its manufacturer; the CAPABILITIES response tells you.

What do GET_VERSION, GET_CAPABILITIES, GET_CERTIFICATE, CHALLENGE and GET_MEASUREMENTS do?

Every SPDM conversation starts with the same three exchanges, which the specification and libspdm call VCA (version, capabilities, algorithms). After that the requester picks the messages it needs. Request codes below are from Table 4 of DSP0274 1.3.3.

RequestCodeRequired?What it does
GET_VERSION0x84RequiredAsks which SPDM versions the responder supports. Resets the connection state.
GET_CAPABILITIES0xE1RequiredExchanges capability flags (CERT_CAP, CHAL_CAP, MEAS_CAP, KEY_EX_CAP, PSK_CAP, ENCRYPT_CAP, MAC_CAP, MUT_AUTH_CAP, ALIAS_CERT_CAP and more) and timing parameters.
NEGOTIATE_ALGORITHMS0xE3RequiredAgrees on the hash, signature, measurement hash, key exchange and AEAD algorithms for the rest of the connection.
GET_DIGESTS0x81OptionalReturns a digest of the certificate chain in each populated slot, so a requester can skip downloading chains it has cached.
GET_CERTIFICATE0x82OptionalDownloads a certificate chain from one slot, in pieces if needed.
CHALLENGE0x83OptionalSends a nonce; the responder signs a transcript of the conversation with the slot's private key, proving it holds that key right now.
GET_MEASUREMENTS0xE0OptionalReturns one or all measurement blocks, optionally signed over a requester nonce.
RESPOND_IF_READY0xFFRequiredPolls for a response the device said would take time.

GET_VERSION and GET_CAPABILITIES

The VERSION response lists version entries; both sides use the highest common one, and every later message carries it in its first byte.

CAPABILITIES is where you learn what a device can actually do. The flags that matter for attestation are CERT_CAP (it has certificates), CHAL_CAP (it answers CHALLENGE), MEAS_CAP (it reports measurements; the value 10b means it can sign them) and ALIAS_CERT_CAP (it uses the alias certificate model). Session support is KEY_EX_CAP, PSK_CAP, ENCRYPT_CAP and MAC_CAP. CAPABILITIES also carries a timing exponent that the requester uses to decide how long to wait.

NEGOTIATE_ALGORITHMS

The requester lists what it supports and the responder picks one of each. The Open Compute Project's Attestation of System Components v1.0 (published 4 November 2020) sets a floor for attester devices that support SPDM: SHA-384 as the minimum measurement hash, RSASSA-3072 as the minimum signature algorithm and SHA-256 as the minimum base hash, with SHA-512 recommended for measurements. DMTF's reference emulator defaults to ECDSA P-384 or P-256 for signatures and SHA-384 or SHA-256 for hashes. From 1.4, ML-DSA and SLH-DSA signatures and ML-KEM key encapsulation can be negotiated as well.

GET_DIGESTS and GET_CERTIFICATE

A device can hold up to eight certificate chains, one per slot, numbered 0 to 7. GET_DIGESTS returns a hash of each populated chain and a slot mask. If the requester already has a chain with a matching digest, it can skip GET_CERTIFICATE entirely. Otherwise GET_CERTIFICATE pulls the chain for one slot, in portions sized by offset and length because many devices have small transport buffers.

CHALLENGE

CHALLENGE carries a slot number, a 32 byte nonce chosen by the requester ("The Requester should choose a random value", in the specification's words) and a request for a measurement summary hash: none, TCB measurements only, or all measurements. The CHALLENGE_AUTH response contains a hash of the certificate chain in that slot, a 32 byte responder nonce, the optional measurement summary hash, opaque data and a signature. The signature covers a transcript of the whole conversation so far: the VCA messages, the digests and certificate exchange, the challenge and the response itself. Replaying an old CHALLENGE_AUTH fails because the requester's nonce is new each time.

GET_MEASUREMENTS

GET_MEASUREMENTS asks for one measurement index, or for all of them with index 0xFF, or for the count with index 0. If the request asks for a signature, it carries a 32 byte nonce and a slot ID, and the MEASUREMENTS response (response code 0x60) ends with a signature over the transcript of the measurement exchange. SPDM 1.3 added a NewMeasurementRequested attribute: if an update has been staged but not yet applied, the device can report what it will measure after the reset instead of what is running now. If nothing is pending, current values come back either way.

If the device needs time to compute a reply, it returns an ERROR with code ResponseNotReady (0x42) and an RDT exponent. The wait time is 2 to the power of that exponent in microseconds. The specification's own example is a raw value of 8, which means 256 microseconds. A value of 12 would mean 4,096 microseconds, roughly 4.1 milliseconds, after which the requester sends RESPOND_IF_READY with the token the device gave it. Another error code worth knowing is RequestResynch (0x43), which the specification gives as the device's way to ask for a fresh GET_VERSION, for example following a firmware update.

How do device certificates chain to a manufacturer root?

Every SPDM certificate chain runs from a root certificate (RootCert) to a leaf, optionally through intermediates. The root belongs to a certificate authority the requester trusts, usually the device manufacturer's. The chain format in a slot is simple:

Byte offsetFieldSizeContent
0Length2 bytes, little endianTotal length of the chain structure, including these header fields
2Reserved2 bytesReserved
4RootHashH bytesDigest of the DER encoded root certificate, using the negotiated hash
4 + HCertificatesLength minus (4 + H)One or more DER encoded X.509 v3 certificates, root first

Worked example 1: sizing a certificate chain

Say the negotiated base hash is SHA-384, so H is 48 bytes. The chain holds a manufacturer root of 612 bytes, an intermediate of 703 bytes and a device leaf of 845 bytes, which together are 2,160 bytes. The Length field is then 2 + 2 + 48 + 2,160 = 2,212 bytes. If the device's transport only moves 1,024 bytes of certificate data per GET_CERTIFICATE response, the requester needs three requests: offsets 0, 1,024 and 2,048, with the last one returning 164 bytes. That is why requesters cache chains by the digest from GET_DIGESTS.

The three certificate models

DSP0274 defines three models, and slot 0 must use one of the first two.

Device certificate model (DeviceCert). The leaf is the Device Certificate. It holds the public key matching the device private key, and the root endorses it through the chain. The specification says the Device Certificate should contain the Hardware identity OID.

Alias certificate model (AliasCert). The Device Certificate becomes a "Device Certificate CA". The device private key signs one or more Alias Certificates below it, and the leaf alias key signs SPDM responses. The specification notes that a device using this model "might factor some mutable information, such as the measurement of a firmware image" into the alias key derivation, so alias keys should be treated as mutable. Alias certificates can carry firmware identity information, with the format left to other standards bodies. The certificates above the device certificate are immutable from the device's point of view; only SET_CERTIFICATE or an equivalent can change them.

Generic certificate model (GenericCert). Added in 1.3 for multiple key pairs. It has no requirements on content and applies only to slots above 0.

The hardware identity rule is the important one for inventory. DSP0274 says a chain using the device or alias model "should contain at least one certificate that includes hardware identity information", that the Hardware identity OID should mark which certificate that is, and that the key pair behind it "is constant on the instance of the device, regardless of the version of firmware running on the device."

What does checking the chain actually prove?

Verifying the chain proves that the manufacturer's CA endorsed this public key. A successful CHALLENGE then proves the device holds the matching private key right now. Together they answer "is this a genuine part from that manufacturer?" They do not, on their own, tell you the firmware is the version you approved. With the alias model, a new firmware image leads to a new alias key and certificate, so the chain itself starts to carry firmware identity. With the device model, you need measurements for that.

What does a measurement contain?

A MEASUREMENTS response carries one or more measurement blocks. Each block has an index (1 to 0xEF for device defined measurements), a measurement specification byte, a size, and the measurement itself. When the measurement follows the DMTF format, which is the common case, it is a small structure of its own:

Byte offsetFieldSizeMeaning
0DMTFSpecMeasurementValueType1Bit 7: 0 means a digest, 1 means a raw bit stream. Bits 6 to 0: what is measured (table below).
1DMTFSpecMeasurementValueSize2Size of the value. For a digest, set by the negotiated measurement hash.
3DMTFSpecMeasurementValuesizeThe digest or raw bytes

And the types, from Table 55 of DSP0274 1.3.3:

Type (bits 6:0)What it measuresRepresentation
0x0Immutable ROMUsually a digest
0x1Mutable firmwareUsually a digest
0x2Hardware configuration, such as strapsDigest or raw
0x3Firmware configuration, such as configurable firmware policyDigest or raw
0x4Freeform measurement manifest, device specific formatDigest or raw
0x5Structured debug and device modeRaw (required)
0x6Mutable firmware version number; the specification "does not mandate a format"Raw (recommended)
0x7Mutable firmware security version number, recommended as an 8 byte unsigned integerRaw (recommended)
0x8Hash extended measurement (HEM)Digest (required)
0x9Informational, for example human readable boot progressRaw (required)
0xAStructured measurement manifest in the format the specification definesRaw (required), digest (recommended)

Indices 0xFD (measurement manifest) and 0xFE (device mode) are reserved. Everything in 1 to 0xEF is up to the manufacturer, so a requester that wants to know which index is the firmware reads the manifest or the vendor's documentation.

Worked example 2: a hash extended measurement

SPDM 1.3 added a running measurement that works like a TPM PCR. DMTF's overview gives the rule: start with HEM set to HashSize bytes of zeros, then for each piece of data do HEM = hash(HEM || DataToExtend). The Measurement Extension Log (MEL) is the list of every DataToExtend, so a verifier can replay it.

Take SHA-256 and two extend events: the digest of a boot loader stage, then the digest of a configuration blob.

HEM0 = 00 x 32 bytes
HEM1 = SHA-256( HEM0 || D_bootstage )      32 + 32 = 64 bytes hashed
HEM2 = SHA-256( HEM1 || D_config )         32 + 32 = 64 bytes hashed

The device reports HEM2 in a type 0x8 block, signed with the rest of the measurements. The verifier fetches the MEL with GET_MEASUREMENT_EXTENSION_LOG, starts from 32 zero bytes, performs the same two hashes and must get the same HEM2. If an attacker removed the config entry from the log, the replay would stop at HEM1 and fail to match. If they reordered the two entries, the result would also differ, because SHA-256(SHA-256(0 || A) || B) is not SHA-256(SHA-256(0 || B) || A). Our TPM PCR explainer walks through the same arithmetic for PCRs with real byte values; the logic carries over exactly.

Measurement summary hash and TCB

CHALLENGE, KEY_EXCHANGE and PSK_EXCHANGE can each ask for a measurement summary hash, either over all measurements or over the "TCB" measurements only (those components whose change would alter the device's trusted computing base). That gives a requester a single digest to compare at connection time, and the full GET_MEASUREMENTS exchange when it needs detail.

How does SPDM set up secure sessions used by PCIe IDE and CXL?

SPDM 1.1 added sessions. Once established, they carry any application data, including further SPDM messages, inside an authenticated and encrypted record.

Session handshake with a certificate

  1. KEY_EXCHANGE. The requester sends its ephemeral Diffie Hellman public value (finite field or elliptic curve, as negotiated), a session ID half, a slot ID and an optional request for a measurement summary hash.
  2. KEY_EXCHANGE_RSP. The responder sends its own ephemeral value, its session ID half, the optional summary hash, a signature over the transcript using the slot's key, and an HMAC that proves it derived the handshake secret.
  3. FINISH. The requester proves it derived the same secret with its own HMAC. If mutual authentication was negotiated, it also signs with its own certificate.
  4. FINISH_RSP. The handshake completes and both sides switch to data keys.

From there, HEARTBEAT keeps the session alive, KEY_UPDATE rotates keys without a full handshake, and END_SESSION closes it. The pre shared key variant (PSK_EXCHANGE, PSK_FINISH) does the same job without certificates, for constrained devices that were provisioned with a shared secret.

The key schedule

DSP0274 defines the default key schedule in terms of HKDF-Extract and HKDF-Expand (RFC 5869) using the negotiated hash. The shared Diffie Hellman secret becomes a handshake secret. From that the schedule derives separate request direction and response direction handshake secrets, then a master secret and separate data secrets for each direction, then the AEAD encryption key and IV for each. SPDM also defines an export master secret that other protocols can use to derive their own keys.

The secured message format (DSP0277)

DSP0277 ("Secured Messages using SPDM", version 1.3.0 dated 27 October 2025) defines one record format for all application data. Each record carries a 4 byte session ID, a sequence number whose size depends on the transport binding, a length, then the encrypted application data length, the application data, optional random padding and the AEAD MAC. All fields except the MAC, application data and random data are little endian. The AEAD algorithm is the one negotiated in SPDM: AES-GCM, ChaCha20-Poly1305 or SM4-GCM in the libspdm implementation. DSP0277 also sets limits on how much data can go through one key before KEY_UPDATE is needed.

How PCIe uses it

PCIe defines Integrity and Data Encryption (IDE), which encrypts and integrity protects transaction layer packets on a link or along a selective stream between two ports. IDE needs keys, and those keys are programmed with IDE key management messages carried inside an SPDM secure session between the host and the device, over the DOE mailbox. You can see the moving parts in lspci output: the pciutils source prints "Data Object Exchange" for the DOE capability and "Integrity & Data Encryption" for the IDE capability, including an IDE_KM support flag and per stream selective IDE control registers. The Linux kernel's PCI TSM documentation describes the kernel side: a Trusted Execution Environment Security Manager core with helpers that allocate, set up, enable and tear down Selective IDE streams between partner ports. TDISP, PCI-SIG's TEE Device Interface Security Protocol, builds on CMA, SPDM and IDE so that a confidential virtual machine can accept a device function as part of its trusted boundary. The authoritative text for CMA, IDE and TDISP is in the PCIe Base Specification, which PCI-SIG distributes to members; the open sources above show how implementations wire it up. Our PCIe 6 explainer covers IDE on the link itself.

How CXL uses it

CXL runs three protocols over the PCIe physical layer: CXL.io (PCIe semantics), and CXL.cache and CXL.mem. CXL.io inherits PCIe's mechanisms. For the cache and memory protocols, the CXL Consortium announced on 20 February 2024 that CXL 3.1 adds the Trusted Execution Environment Security Protocol (TSP). A TSP change notice posted on the consortium's site scopes in "SPDM 1.2 or newer for authentication and attestation" and describes CMA and SPDM out of band messages to change a target's TEE state. In other words, a CXL memory expander that wants to host confidential workloads has to answer SPDM, prove its identity and measurements, and take its security state changes over SPDM.

How do BMCs and Redfish expose attestation results?

On most servers you never talk to a device's SPDM responder yourself. The BMC does, over MCTP or PCIe DOE, and publishes the result through Redfish, DMTF's REST API for platform management.

The ComponentIntegrity resource

The Redfish ComponentIntegrity schema (version 1.3.1, in Redfish release 2024.3) represents "critical and pertinent security information about a specific device". The fields that matter:

PropertyWhat it holds
ComponentIntegrityTypeSPDM, TPM, TCM, TPCM or OEM
ComponentIntegrityTypeVersionThe protocol version, for example the SPDM version in use
TargetComponentURILink to the device this record is about
SPDM.RequesterLink to the component doing the asking, usually the BMC
SPDM.IdentityAuthentication.ResponderAuthenticationComponentCertificate (a link to the leaf certificate) and VerificationStatus (Success or Failed)
SPDM.MeasurementSet.Measurements[]Per index: MeasurementIndex, MeasurementType, Measurement, MeasurementHashAlgorithm, SecurityVersionNumber, PartofSummaryHash, LastUpdated
SPDM.ComponentCommunication.Sessions[]Active sessions, each Plain, AuthenticatedOnly or EncryptedAuthenticated
Links.ComponentsProtectedComponents this one protects, for a root of trust

The measurement type enumeration in this schema version is ImmutableROM, MutableFirmware, HardwareConfiguration, FirmwareConfiguration, MutableFirmwareVersion, MutableFirmwareSecurityVersionNumber and MeasurementManifest. It does not list the device mode, hash extended or informational types that SPDM 1.3 added, so check the schema version your BMC implements if you rely on those.

The SPDMGetSignedMeasurements action

Cached values in a BMC are only as fresh as the last time it asked. For a verifier that wants proof now, the schema defines the action #ComponentIntegrity.SPDMGetSignedMeasurements. Its parameters:

  • Nonce: a 32 byte value as 64 hex characters, which the requester passes into GET_MEASUREMENTS. If you leave it out, the BMC generates one, which means you are trusting the BMC's randomness and honesty.
  • SlotId: which certificate slot's key signs the result. Defaults to 0.
  • MeasurementIndices: indices between 0 and 254, or a single 255 for all. Defaults to 255.

The response returns SignedMeasurements (Base64 of the signed statement), the SigningAlgorithm, HashingAlgorithm, the SPDM Version, and either a link to the Certificate for the slot or a PEM PublicKey.

How OpenBMC wires it up

The OpenBMC design document "Redfish SPDM Attestation Support" (created June 2023, last updated October 2023) describes the plumbing in the open source BMC stack: new D-Bus interfaces for ComponentIntegrity and TrustedComponent, an SPDM attestation daemon that does the protocol work using libspdm, and routes in the bmcweb web server that read the results from D-Bus. The daemon talks to devices over standard MCTP, PCIe DOE or TCP. The document calls bmcweb's SPDM support experimental and libspdm's README calls OpenBMC support planned, so verify your BMC's coverage rather than assume it. Our post on what a firewall cannot see covers why the BMC itself needs the same scrutiny.

How do Caliptra and OCP device attestation fit?

The OCP attestation requirements

The Open Compute Project's "Attestation of System Components v1.0 Requirements and Recommendations" (4 November 2020) set out the problem plainly: servers "had no standardized, open, and automated mechanism" to verify that, for example, a network adapter still contains the firmware its manufacturer installed. For attester devices that support SPDM it requires SPDM 1.0 or higher (and recommends the current version), requires the CERT_CAP, CHAL_CAP and MEAS_CAP capabilities, says devices should support signed measurements (MEAS_CAP = 10b), and sets the algorithm floor described above. It also requires certificate based identity for the endorsement of attestation quotes, which is where Caliptra comes in.

What Caliptra is

Caliptra is, in its project's words, "IP and firmware for an integrated Root of Trust block" for data center class chips such as CPUs, GPUs and other accelerators. It is the specification, silicon logic, ROM and firmware for a Root of Trust for Measurement inside the chip, providing identity, measured boot and attestation. The project began at the Open Compute Project, which publishes the major specification revisions; the source code lives in CHIPS Alliance, a Linux Foundation project. Caliptra components (RTL, ROM, first mutable code and runtime firmware) are versioned separately as major.minor.patch, and the mutable firmware stages also carry security version numbers that increase when a security critical issue is fixed.

Caliptra's DICE chain, and how it maps to SPDM

Caliptra follows the TCG DICE architecture. Its 1.x specification describes the chain:

  1. UDS. A unique device secret, stored obfuscated in fuses, used at cold boot and then cleared by hardware.
  2. IDevID. A hardware identity key derived from the UDS during manufacturing. Caliptra generates a certificate signing request; the vendor's provisioning CA, running on a hardware security module in the high volume manufacturing flow, signs the IDevID certificate. The private key never leaves Caliptra ROM.
  3. LDevID. A locally significant identity that mixes in field programmable entropy: two 16 byte fuse slots an owner can program at onboarding. IDevID endorses LDevID. This lets an owner get an identity that an attacker who stole the UDS earlier in the supply chain cannot derive.
  4. FMC alias. The LDevID CDI is mixed with a hash of the first mutable code and the device's security state (including whether debug unlock is enabled). The resulting alias certificate, signed by LDevID, includes those measurements.
  5. Runtime alias and DPE. The runtime firmware gets its own alias, and Caliptra exposes the DICE Protection Environment (DPE) API, so it can derive and use DICE identities for other parts of the chip.

Put next to SPDM, this is the alias certificate model with firmware identity built into the chain: IDevID is the Device Certificate CA carrying hardware identity, and the alias certificates change when firmware or security state changes. The Caliptra specification names the link to SPDM directly: one use of the DPE API is "serving as a signing oracle for a Security Protocol and Data Model (SPDM) responder that is executing in the SoC application processor". The SPDM protocol code runs on the chip's own processor; the keys and the measurements stay inside Caliptra.

Caliptra on revocation and ownership

The Caliptra specification is unusually direct about limits. It recommends that vendors add an Authority Information Access extension to IDevID certificates and run an OCSP responder. It states that the LDevID certificate "does not support revocation because there is no generic Caliptra OCSP service", and that owners should keep an allowlist of LDevID certificates or revoke upstream CAs. It also notes that field entropy does not protect against an attacker who obtains fuse data after the owner programmed it, for example during a return and repair flow. Those are honest descriptions of the gaps discussed at the end of this guide.

A dated timeline

DateEventSource
May 2018NIST SP 800-193, Platform Firmware Resiliency Guidelines: protect, detect, recover for platform firmwareNIST CSRC
16 Oct 2019SPDM 1.0.0 publishedDSP0274 change log
15 Jul 2020SPDM 1.1.0: sessions, mutual authenticationDSP0274 change log
18 Sep 2020DSP0277 1.0.0, secured messagesDSP0277 change log
4 Nov 2020OCP Attestation of System Components v1.0OCP
1 Nov 2021SPDM 1.2.0: certificate provisioning, alias certificates, chunkingDSP0274 change log
5 Apr 2023SPDM 1.3.0: events, multi key, generic certificates, MEL and HEMDSP0274 change log
25 Sep 2023CISA publishes the HBOM Framework for Supply Chain Risk ManagementCISA
20 Feb 2024CXL 3.1 introduces the TEE Security ProtocolCXL Consortium
25 Mar 2024MCTP base specification DSP0236 1.3.3DSP0236
30 Jun 2024Version 2 of the Linux "PCI device authentication" patch series (CMA-SPDM, results in sysfs) postedLWN
1 Jul and 19 Aug 2024SPDM 1.3.1 and 1.3.2DSP0274 change log
15 May 2025SPDM 1.4.0: post quantum algorithms, slot managementDSP0274 1.4.1 change log
24 Oct 2025SPDM 1.3.3 errata releaseDSP0274 1.3.3
23 Jun 2026Version 2 of a Rust SPDM requester series for the Linux kernel, positioned as a PCI CMA TSM driverLWN
26 Jun 2026SPDM 1.4.1DSP0274 1.4.1
29 Sep 2026libspdm 3.8.3 releasedGitHub releases
19 Oct 2026libspdm 4.0.0-rc3 taggedGitHub releases

Step by step: see SPDM on your own machines

None of the steps below change device state. GET_CSR, SET_CERTIFICATE and SET_KEY_PAIR_INFO do change it, and you should not run them against production hardware outside a planned provisioning process.

Step 1: check whether a PCIe device exposes DOE and IDE

On Linux, lspci decodes both capabilities. Find the device address first, then look at its extended capabilities.

# List devices and pick the address of the card you care about
lspci -nn | grep -Ei 'ethernet|non-volatile|3d|processing accelerators'

# Show its extended capabilities (needs root to read config space)
sudo lspci -vvv -s 0000:41:00.0 | grep -E -A4 'Data Object Exchange|Integrity & Data Encryption'

A "Data Object Exchange" block means the device has a DOE mailbox, the transport PCIe uses for CMA and SPDM. An "Integrity & Data Encryption" block, with IDE_KM+ in the IDECap line, means it supports link encryption keyed through SPDM. The absence of DOE does not mean the device lacks SPDM; it may speak SPDM over MCTP to the BMC instead.

Step 2: watch a full SPDM exchange with the reference emulator

DMTF's spdm-emu builds a requester and a responder on top of libspdm, so you can watch every message without hardware.

git clone --recursive https://github.com/DMTF/spdm-emu.git
cd spdm-emu
mkdir build && cd build
cmake -DARCH=x64 -DTOOLCHAIN=GCC -DTARGET=Release -DCRYPTO=openssl -DBUILD_VALIDATOR_SAMPLES=OFF ..
make copy_sample_key
make
cd bin

Then, in two terminals in build/bin:

# Terminal 1: a responder that pretends to be a PCIe device behind DOE
./spdm_responder_emu --trans PCI_DOE --pcap responder.pcap

# Terminal 2: version, capabilities, algorithms, certificate, challenge and signed measurements
./spdm_requester_emu --trans PCI_DOE --ver 1.3 \
  --exe_conn DIGEST,CERT,CHAL,MEAS --meas_op ALL --meas_att SIG \
  --exe_session KEY_EX,MEAS --pcap requester.pcap -v

Per the emulator's documentation, --trans selects MCTP, PCI_DOE, TCP or NONE, --exe_conn and --exe_session choose which steps run, --meas_att SIG asks for signed measurements and --pcap writes a capture for offline analysis. The sample keys are test keys, so never trust a real device that presents them.

Step 3: ask the BMC what it has verified

On a server whose BMC implements Redfish ComponentIntegrity, start at the service root and follow links. Replace the address and credentials with your own and keep them out of shell history.

BMC=https://bmc.example.internal

# Discover the collection
curl -sk -u "$BMC_USER:$BMC_PASS" "$BMC/redfish/v1/ComponentIntegrity" | jq '.Members'

# Read one record: type, version, verification status, measurements
curl -sk -u "$BMC_USER:$BMC_PASS" "$BMC/redfish/v1/ComponentIntegrity/<Id>" \
  | jq '{type: .ComponentIntegrityType, ver: .ComponentIntegrityTypeVersion,
         target: .TargetComponentURI,
         auth: .SPDM.IdentityAuthentication.ResponderAuthentication.VerificationStatus,
         meas: [.SPDM.MeasurementSet.Measurements[]? | {MeasurementIndex, MeasurementType, Measurement, SecurityVersionNumber}]}'

Use -k only on a lab BMC with a self signed certificate; in production, pin the BMC's CA with --cacert.

Step 4: request fresh signed measurements with your own nonce

NONCE=$(openssl rand -hex 32)   # 64 hex characters = 32 bytes

curl -sk -u "$BMC_USER:$BMC_PASS" -H 'Content-Type: application/json' \
  -X POST "$BMC/redfish/v1/ComponentIntegrity/<Id>/Actions/ComponentIntegrity.SPDMGetSignedMeasurements" \
  -d "{\"Nonce\": \"$NONCE\", \"SlotId\": 0, \"MeasurementIndices\": [255]}" \
  | tee signed-measurements.json | jq '{Version, SigningAlgorithm, HashingAlgorithm, Certificate}'

Supplying the nonce yourself matters. If the BMC chose it, a compromised BMC could replay an old signed response. With your nonce inside the signed data, an old response cannot match.

Step 5: verify the chain, then the signature, then the values

# Fetch the leaf certificate the response links to (follow the Certificate link)
curl -sk -u "$BMC_USER:$BMC_PASS" "$BMC<CertificateLink>" | jq -r '.CertificateString' > leaf.pem

# Check it chains to the manufacturer root you obtained out of band
openssl verify -CAfile vendor-root.pem -untrusted vendor-intermediates.pem leaf.pem
openssl x509 -in leaf.pem -noout -subject -issuer -dates -ext subjectAltName

Checking the signature over SignedMeasurements is the hard part to do by hand, because the signature covers an SPDM transcript, not a plain file. Use a verifier built on a maintained SPDM library rather than writing your own parser. Then compare each measurement against reference values from the device vendor for the firmware version you approved, and fail closed when an index you expect is missing.

Step 6: record what you learned

Write the result somewhere durable, with the device identity, the time, the nonce, the measurements and the verdict. The next section shows a shape for that record.

How could attestation evidence populate or verify an HBOM entry?

A hardware bill of materials lists the physical components in a product and their attributes. CISA's HBOM Framework (25 September 2023) gives a consistent way to describe them; our CISA HBOM framework explainer covers its fields. SPDM evidence can fill or check several of those fields for any component that answers it:

HBOM or SBOM attributeSPDM sourceCaveat
ManufacturerSubject or issuer of the hardware identity certificate; root CA identityNaming varies; map CA subjects to your supplier list
Model and partCertificate subject or subject alternative name, if the vendor encodes itNot standardised in SPDM
Unique instance (serial)Public key of the hardware identity certificate, which DSP0274 says is constant across firmware versionsThe certificate's serial number field is the CA's, not the device's
Firmware digestMeasurement type 0x1 (mutable firmware)Needs a vendor reference value to mean anything
ROM digestMeasurement type 0x0Same
Firmware versionMeasurement type 0x6, rawFormat not mandated; parse per vendor
Security version numberMeasurement type 0x7, 8 byte integer recommendedLets you enforce a minimum without parsing versions
ConfigurationTypes 0x2 and 0x3Opaque per vendor
Debug stateType 0x5 and index 0xFETreat debug enabled as a failed attestation in production
Evidence of freshnessYour nonce and the signatureStore both with the record

CycloneDX, one of the two common bill of materials formats, already has component types for device, firmware and device-driver, and every component can carry hashes, manufacturer, supplier and version. A record that ties a physical card to its attested firmware could look like this:

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.6",
  "components": [
    {
      "type": "device",
      "bom-ref": "nic-slot3",
      "name": "dual-port-25g-adapter",
      "manufacturer": { "name": "Example Silicon Ltd" },
      "properties": [
        { "name": "spdm:version", "value": "1.3" },
        { "name": "spdm:hwIdentityKeySha256", "value": "<sha256 of the identity public key>" },
        { "name": "spdm:attestedAt", "value": "2026-10-24T09:12:00Z" },
        { "name": "spdm:nonce", "value": "<the 64 hex character nonce>" }
      ],
      "components": [
        {
          "type": "firmware",
          "bom-ref": "nic-slot3-fw",
          "name": "adapter-mutable-firmware",
          "version": "<raw value of measurement type 0x6>",
          "hashes": [ { "alg": "SHA-384", "content": "<measurement type 0x1 digest>" } ],
          "properties": [
            { "name": "spdm:measurementIndex", "value": "2" },
            { "name": "spdm:securityVersionNumber", "value": "7" }
          ]
        }
      ]
    }
  ]
}

The spdm: property names are a local convention, not part of any standard. The useful pattern is the direction of checking. A vendor supplied HBOM says "this product ships firmware X with digest D". An attestation says "this unit, right now, runs firmware with digest D'". If D equals D', the HBOM entry is confirmed for that unit; if not, you have either an unrecorded update or a problem. Attestation can verify an HBOM entry, but it cannot write a complete one: it says nothing about passive components, parts without a responder or the open source code compiled into the firmware.

What are the gaps?

SPDM is mature as a protocol. The gaps are in what surrounds it.

GapWhy it mattersWhat to do
Adoption is unevenMany installed devices predate SPDM or implement only VCA, certificates and challengeInventory which devices answer which messages; plan refresh cycles around it
Firmware version semanticsType 0x6 has no mandated format; indices 1 to 0xEF are vendor definedUse the security version number for policy; get reference values and index maps from vendors in writing
Reference valuesA digest is meaningless without a trusted list of expected digests per versionRequire vendors to publish signed reference values with each firmware release
RevocationSPDM carries chains but defines no revocation transport; Caliptra notes LDevID certificates have no revocation serviceCheck CRLs or OCSP where vendors run them; keep allowlists for identities you onboard
Operating system supportThe Linux in-kernel requester for PCI CMA is still under review (a Rust series reached version 2 in June 2026); PCI TSM and IDE helpers are documentedRely on BMC and firmware requesters for now; track upstream
BMC trustIf the BMC is the requester, a compromised BMC can lie about resultsSupply your own nonce, verify signatures off the BMC, attest the BMC itself
Redfish coverageThe 1.3.1 schema enum omits SPDM 1.3's newer measurement types; OpenBMC support is described as experimental or plannedCheck your BMC's schema version and test against a known device
Measurement is not behaviourSigned measurements show what loaded at boot, not what the firmware does at runtimePair attestation with update hygiene and runtime monitoring
Ownership transferSecond hand and repaired parts carry the previous owner's identities and stateUse owner provisioned identities (LDevID style) and re-onboard after repair

NIST SP 800-193 frames the goal as protect, detect and recover for platform firmware. SPDM is a detection tool for components outside the CPU's boot chain: it gives you evidence, and deciding what it means is still your job.

Common mistakes

  • Treating a successful CHALLENGE as firmware verification. It proves identity and key possession. Unless the alias chain or measurements are checked against reference values, it says nothing about which firmware is running.
  • Letting the BMC pick the nonce when the BMC is not trusted. Pass your own 32 byte nonce to SPDMGetSignedMeasurements and check it is in the signed data.
  • Comparing firmware version strings across vendors. Type 0x6 has no mandated format. Use the 8 byte security version number for minimum version policy.
  • Trusting cached Redfish values as current. LastUpdated tells you when the BMC last asked. For decisions, request fresh signed measurements.
  • Assuming no DOE means no SPDM. Many devices answer only over MCTP to the BMC.
  • Ignoring the device mode block. A part in debug mode can produce plausible measurements. Fail attestation when the mode says debug is enabled.
  • Shipping test keys. The emulator and many evaluation boards ship sample keys. Make sure production trust anchors are the manufacturer's roots, not sample roots.
  • Writing your own SPDM parser for production. The responses are untrusted input from a complex specification. Use a maintained library and keep it patched.

FAQ

What is SPDM device attestation?

It is the process where a requester such as a BMC or host asks a device, using the DMTF SPDM protocol, for its certificate chain and a signed set of firmware and configuration measurements, then checks the chain against the manufacturer's root and compares the measurements with expected values.

Which SPDM messages are required?

GET_VERSION, GET_CAPABILITIES and NEGOTIATE_ALGORITHMS are required for every responder, along with RESPOND_IF_READY. Certificates, CHALLENGE and GET_MEASUREMENTS are optional in DSP0274 but required by platform profiles such as the OCP attestation requirements.

Does SPDM support post quantum cryptography?

Yes, from version 1.4.0 (15 May 2025). It added ML-DSA and SLH-DSA signatures and ML-KEM key encapsulation. DMTF's libspdm reference library lists ML-DSA, SLH-DSA and ML-KEM among its supported algorithms.

What is the difference between SPDM and PCIe CMA?

SPDM is DMTF's generic protocol. CMA, Component Measurement and Authentication, is PCI-SIG's specification for how PCIe devices use SPDM, carried over the DOE mailbox in configuration space.

How does SPDM relate to PCIe IDE?

IDE encrypts PCIe traffic between ports. The keys for IDE are set up with key management messages that run inside an SPDM secure session, so a host can authenticate a device before keying its link.

What is the difference between the device certificate and alias certificate models?

In the device model, the leaf certificate holds the device's long term key. In the alias model, the device key acts as a CA and signs alias certificates whose keys can depend on the firmware measured at boot, so a firmware change changes the leaf.

How do I see SPDM attestation results on a server?

Look for the Redfish ComponentIntegrity collection on the BMC. Each record shows the SPDM version, verification status, leaf certificate and measurements, and the SPDMGetSignedMeasurements action returns a fresh signed result for a nonce you supply.

Is Caliptra the same as SPDM?

No. Caliptra is an open source root of trust block inside a chip that provides DICE identity and measurements. SPDM is the protocol another component uses to ask for that identity and those measurements. Caliptra's DPE API can sign on behalf of an SPDM responder running on the same chip.

Can SPDM attestation replace a hardware bill of materials?

No. It can verify HBOM entries for components that speak SPDM, at the moment you ask. It does not list components without responders, and it does not describe the open source software compiled into the firmware.

Where Safeguard fits, honestly

Safeguard does not speak SPDM, verify device certificates, read measurements, scan firmware binaries, manage BMCs or generate a hardware bill of materials. Those jobs belong to the BMC, the device firmware and your platform tooling. Where Safeguard is useful is the software around attestation that your teams build and ship: BMC firmware builds, attestation verifier services, provisioning tools and their container images. Libraries such as libspdm, the cryptographic backends they link and the web servers that expose Redfish are open source components with their own release cadence. Safeguard scans repositories, container images and SBOM files you supply (safeguard scan --dir ., --image <name>, --sbom <file>), matches components against vulnerability databases, and shows which of your projects contain a given component and version, so when a fix lands in a library your verifier depends on, you can find every place it needs to go.

Attestation only tells you the truth if the code that asks and the code that answers are current, and both are built from open source components that need patching like any other dependency. A verifier service, a BMC image or a provisioning tool pulls those components again on every rebuild, so keeping them on fixed versions is ordinary supply chain hygiene, even though the devices themselves sit outside what Safeguard scans.

Fix it without waiting for upstream

Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.

1. Autonomous remediation: pull requests, not tickets

When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation covers eight categories, including dependencies, licenses, security posture and findings. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.

2. Gold Open Source: the safe version in seconds, free

gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds. The safeguard-sh/gold-scan-action GitHub Action can fail a build on a known exploited vulnerability, on any known vulnerability, or never, so a version you have just removed cannot quietly come back in next week's merge.

3. Gold Registry: start from components that are already fixed

registry.safeguard.sh provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs, zero malware and a completed license check, with SLSA L3 or higher provenance, a Sigstore signature and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.

When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. This fork and patch flow is in early access today, so ask which packages it covers before you plan around it.

Your situationWhat to use
A fixed version existsAutonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version
You need to know today whether you are affectedGold Open Source lookup and "Am I affected?" checker, free and without login
You want vulnerable versions to stop shippingThe Gold scan GitHub Action in CI, plus Safeguard policies and gates
Upstream has no fix yet, or will not ship oneA custom Gold request; fork and patch (early access)
You want to start clean on new projectsPull hardened components and images from Gold Registry

One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.

See how Safeguard would help

To be plain about scope again: none of these demos touch a device, a BMC or an SPDM exchange. They show how Safeguard works on the software your team builds, which for this topic means verifier services, BMC firmware build trees and provisioning tools.

This first demo is a real CLI session. You install the CLI, run safeguard to open the interactive terminal and ask it to fix a lodash CVE; it reads the finding and advisory, asks before each command, edits package.json to lodash 4.17.21, runs npm install and npm test with your approval, prints a summary and pushes nothing. The same ask before every command flow applies when you point it at the repository for an attestation dashboard or a Redfish client tool.

Click through it at your own pace, or open it full screen.

The second demo sets up the local runner on your own machine: you approve it with its device code, then scan from the terminal. That suits the build hosts where firmware images and verifier containers are assembled, so the scan runs where the files already are instead of shipping them elsewhere.

Click through it at your own pace, or open it full screen.

The third demo connects Claude to the Safeguard MCP server with OAuth and lets you choose which tools Claude can use. If your platform team already uses Claude while working through attestation tooling, this is how to let it ask Safeguard which of your projects carry a given package version, limited to the tools you approve.

Click through it at your own pace, or open it full screen.

You can download Safeguard or read the CLI documentation to try it on your own build.

Quick check

A device passes CHALLENGE with a valid chain to its manufacturer's root. Do you know which firmware it is running?

Not necessarily. CHALLENGE proves the device holds the private key for a certificate the manufacturer endorsed. You learn the firmware only if the alias certificates encode it, or if you fetch signed measurements and compare the mutable firmware digest (type 0x1) or security version number (type 0x7) with reference values for the version you approved.

Why should you pass your own nonce to the Redfish SPDMGetSignedMeasurements action?

Because the nonce goes into the signed data. If the BMC chooses it, a compromised or buggy BMC could hand you an old signed response. With your own fresh 32 byte nonce inside the signature, an old response cannot verify, so you know the measurements were signed after you asked.

Sources

Last reviewed: 24 October 2026. SPDM, Redfish and the PCIe and CXL security specifications are revised often; check the linked documents for the versions your devices implement.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.