Vulnerability: swtpm is a libtpms-based TPM emulator with socket, character device, and Linux CUSE interface. Versions prior to 0.5.3, 0.6.2, and 0.7.1 are vulnerable to out-of-bounds read. A specially crafted header of swtpm's state, where the blobheader's hdrsize indicator has an invalid value, may cause an out-of-bounds access when the byte array representing the state of the TPM is accessed. This will likely crash swtpm or prevent it from starting since the state cannot be understood. Users should upgrade to swtpm v0.5.3, v0.6.2, or v0.7.1 to receive a patch. There are currently no known workarounds.
Vulnerability ID: CVE-2022-23645
CWE: CWE-125
Severity score: 2.9
Project: https://github.com/stefanberger/swtpm
Published: 2022-02-18
File: src/swtpm/swtpm_nvstore.c
Commit message: swtpm: Check header size indicator against expected size (CID 375869)

This fix addresses Coverity issue CID 375869.

Check the header size indicated in the header of the state against the
expected size and return an error code in case the header size indicator
is different. There was only one header size so far since blobheader was
introduced, so we don't need to deal with different sizes.

Without this fix a specially craft header could have cause out-of-bounds
accesses on the byte array containing the swtpm's state.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Commit author: Stefan Berger

Vulnerable version (before fix):
 SWTPM_NVRAM_CheckHeader(unsigned char *data, uint32_t length,                         uint8_t *hdrversion, bool quiet) {     blobheader *bh = (blobheader *)data;      if (length < sizeof(bh)) {         if (!quiet) SWTPM_NVRAM_CheckHeader(unsigned char *data, uint32_t length,         return TPM_BAD_VERSION;     }      *hdrversion = bh->version;     *dataoffset = ntohs(bh->hdrsize);     *hdrflags = ntohs(bh->flags);      return TPM_SUCCESS;

Fixed version (after fix):
 SWTPM_NVRAM_CheckHeader(unsigned char *data, uint32_t length,                         uint8_t *hdrversion, bool quiet) {     blobheader *bh = (blobheader *)data;     uint16_t hdrsize;      if (length < sizeof(bh)) {         if (!quiet) SWTPM_NVRAM_CheckHeader(unsigned char *data, uint32_t length,         return TPM_BAD_VERSION;     }      hdrsize = ntohs(bh->hdrsize);     if (hdrsize != sizeof(blobheader)) {         logprintf(STDERR_FILENO,                   "bad header size: %u != %zu\n",                   hdrsize, sizeof(blobheader));         return TPM_BAD_DATASIZE;     }      *hdrversion = bh->version;     *dataoffset = hdrsize;     *hdrflags = ntohs(bh->flags);      return TPM_SUCCESS;

Patch:
patch: @@ -1075,6 +1075,7 @@ SWTPM_NVRAM_CheckHeader(unsigned char *data, uint32_t length,
                         uint8_t *hdrversion, bool quiet)
 {
     blobheader *bh = (blobheader *)data;
+    uint16_t hdrsize;
 
     if (length < sizeof(bh)) {
         if (!quiet)
@@ -1100,8 +1101,16 @@ SWTPM_NVRAM_CheckHeader(unsigned char *data, uint32_t length,
         return TPM_BAD_VERSION;
     }
 
+    hdrsize = ntohs(bh->hdrsize);
+    if (hdrsize != sizeof(blobheader)) {
+        logprintf(STDERR_FILENO,
+                  "bad header size: %u != %zu\n",
+                  hdrsize, sizeof(blobheader));
+        return TPM_BAD_DATASIZE;
+    }
+
     *hdrversion = bh->version;
-    *dataoffset = ntohs(bh->hdrsize);
+    *dataoffset = hdrsize;
     *hdrflags = ntohs(bh->flags);
 
     return TPM_SUCCESS;
path: src/swtpm/swtpm_nvstore.c