REDHAT-BUG-2528538: Medium severity libtpms vulnerability
libtpms implements the software TPM 2.0 engine used by swtpm/QEMU. Its NV/volatile state (de)serializer in src/tpm2/NVMarshal.c uses blockskipread() (src/tpm2/NVMarshal.c:158-188) to skip an optional versioned sub-block when the running code does not need it. The function reads an attacker-controlled 16-bit blocksize field from the stream and then does 'buffer += blocksize; size -= blocksize;' with NO check that blocksize <= size. Because size is a signed INT32, a forged blocksize larger than the remaining bytes drives size negative. Every scalar unmarshal primitive in src/tpm2/Unmarshal.c (UINT8/16/32/64Unmarshal, ArrayUnmarshal) guards its bounds check as '(UINT32)size < sizeof(...)', which implicitly casts the now-negative size to UINT32, wrapping it to a huge unsigned value that passes the check. The next field read then dereferences buffer past the end of the heap allocation backing the state blob (CWE-125).
Reachable from TPMLIBSetState(TPMLIBSTATEVOLATILE/PERMANENT, ...) via VolatileStateUnmarshal()/PERSISTENTALLUnmarshal(), i.e. the power-on/restore and state-import paths. blockskipread() only performs pointer arithmetic and never copies skipped bytes, so the realistic impact is denial of service (process crash / TPM failure mode), not information disclosure.
Reported by Isuka Sanuj (CyberCrew Inc.) on 2026-09-01; independently reported publicly by Leyao (ICT CAS) as github.com/stefanberger/libtpms/issues/614 on 2026-09-04. PSIRTSUPT-23184.
Affected: all released libtpms versions carrying TPM 2.0 state deserialization code, including v0.10.2 (commit 03ff2481e133540be3b3ffe3daa1483d2a73d967). Upstream fix on master in commit b1462888180d896af03cae0487e8d45009cc445e ('tpm2: Add checks for size < 0 before casting it to UINT32'), adding 'size < 0 ||' guards to UINT8/16/32/64Unmarshal and ArrayUnmarshal. Not yet present in any tagged release as of 2026-09-04.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
libtpmsto a version that resolves this vulnerability.Patch PSIRTSUPT-23184 - Compensating control
If using the libtpms software TPM engine (e.g., via swtpm/QEMU), restrict/validate any TPM state-import/state-restore inputs reaching TPMLIB_SetState(TPMLIB_STATE_VOLATILE/PERMANENT, ...) / VolatileState_Unmarshal()/PERSISTENT_ALL_Unmarshal() so untrusted parties cannot supply attacker-controlled state blobs.
Event History
Frequently Asked Questions
Which environments are exposed to this issue?
Deployments using libtpms as the software TPM 2.0 engine, including swtpm/QEMU use cases, are exposed when they process volatile or permanent TPM state through the affected state-setting paths.
What does an attacker need to control to trigger the flaw?
The attacker needs to provide a crafted TPM state stream containing a forged 16-bit optional-block size larger than the bytes remaining in the state blob. The malformed size can cause subsequent unmarshalling to read beyond the heap allocation backing that blob.
Which operations reach the vulnerable code?
The affected code is reachable through TPMLIB_SetState for TPMLIB_STATE_VOLATILE and TPMLIB_STATE_PERMANENT. These correspond to power-on or restore processing and state-import paths via VolatileState_Unmarshal or PERSISTENT_ALL_Unmarshal.