diff --git a/libtpms.spec b/libtpms.spec index d5949da6820cf96dc998abe15c89110a1ccb422e..a7cdcf048c55355a5cc8c4bbd14eebff5934a361 100644 --- a/libtpms.spec +++ b/libtpms.spec @@ -6,7 +6,7 @@ %define name libtpms %define versionx 0.7.3 -%define release 4 +%define release 5 # Valid crypto subsystems are 'freebl' and 'openssl' %if "%{?crypto_subsystem}" == "" @@ -19,7 +19,7 @@ Summary: Library providing Trusted Platform Module (TPM) functionality Name: %{name} Version: %{versionx} -Release: 4 +Release: 5 License: BSD Group: Development/Libraries Url: http://github.com/stefanberger/libtpms @@ -34,6 +34,9 @@ Patch4: tpm2-rev155-Add-new-RsaAdjustPrimeCandidate-code.patch Patch5: tpm2-Introduce-SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FI.patch Patch6: tpm2-Pass-SEED_COMPAT_LEVEL-to-CryptAdjustPrimeCandi.patch Patch7: tpm2-Activate-SEED_COMPAT_LEVEL_RSA_PRIME_ADJUST_FIX.patch +Patch8: tpm2-Initialize-a-whole-OBJECT-before-using-it.patch +Patch9: tpm2-Fix-issue-with-misaligned-address-when-marshall.patch +Patch10: tpm2-NVMarshal-Handle-index-orderly-RAM-without-0-si.patch %if "%{crypto_subsystem}" == "openssl" BuildRequires: openssl-devel @@ -126,6 +129,12 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/libtpms.la %postun -p /sbin/ldconfig %changelog +* Wed Nov 10 2021 jiangfangjie - 0.7.3-5 +-TYPE: CVE +-ID:NA +-ID:NA +_DESC: fix CVE-2021-3746 + * Tue May 11 2021 jiangfangjie - 0.7.3-4 -TYPE: CVE -ID:NA diff --git a/tpm2-Fix-issue-with-misaligned-address-when-marshall.patch b/tpm2-Fix-issue-with-misaligned-address-when-marshall.patch new file mode 100644 index 0000000000000000000000000000000000000000..18b073a7b6afff7b1a945034df2e3a05021ca975 --- /dev/null +++ b/tpm2-Fix-issue-with-misaligned-address-when-marshall.patch @@ -0,0 +1,155 @@ +From 3aac390ce146b40117ad213c24504bb678f4daeb Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Mon, 23 Nov 2020 13:15:53 -0500 +Subject: [PATCH] tpm2: Fix issue with misaligned address when marshalling + NVRAM (UBSAN) + +UBSAN detects possibly misaligned address when reading out of the +TPM 2's NVRAM and when writing back into it. The NV_RAM_HEADER may +be unaligned like this: + +tests/test_tpm2_save_load_state_3.log:tpm2/Marshal.c:117:29: \ + runtime error: load of misaligned address 0x7ffcb53b3bca for type 'UINT32', which requires 4 byte alignment + +Signed-off-by: Stefan Berger +--- + src/tpm2/NVMarshal.c | 59 +++++++++++++++++++++++++++----------------- + 1 file changed, 36 insertions(+), 23 deletions(-) + +diff --git a/src/tpm2/NVMarshal.c b/src/tpm2/NVMarshal.c +index ec94ebf..74ea17f 100644 +--- a/src/tpm2/NVMarshal.c ++++ b/src/tpm2/NVMarshal.c +@@ -3991,7 +3991,7 @@ INDEX_ORDERLY_RAM_Marshal(void *array, size_t array_size, + BYTE **buffer, INT32 *size) + { + UINT16 written; +- NV_RAM_HEADER *nrh; ++ NV_RAM_HEADER nrh, *nrhp; + UINT16 offset = 0; + UINT16 datasize; + UINT32 sourceside_size = array_size; +@@ -4005,36 +4005,42 @@ INDEX_ORDERLY_RAM_Marshal(void *array, size_t array_size, + written += UINT32_Marshal(&sourceside_size, buffer, size); + + while (TRUE) { +- nrh = array + offset; ++ nrhp = array + offset; ++ /* nrhp may point to misaligned address (ubsan), so use 'nrh'; first access only 'size' */ ++ memcpy(&nrh, nrhp, sizeof(nrh.size)); ++ + /* write the NVRAM header; + nrh->size holds the complete size including data; + nrh->size = 0 indicates the end */ +- written += UINT32_Marshal(&nrh->size, buffer, size); +- if (nrh->size == 0) ++ written += UINT32_Marshal(&nrh.size, buffer, size); ++ if (nrh.size == 0) + break; +- written += TPM_HANDLE_Marshal(&nrh->handle, buffer, size); +- written += TPMA_NV_Marshal(&nrh->attributes, buffer, size); ++ /* copy the entire structure now; ubsan does not allow 'nrh = *nrhp' */ ++ memcpy(&nrh, nrhp, sizeof(nrh)); ++ ++ written += TPM_HANDLE_Marshal(&nrh.handle, buffer, size); ++ written += TPMA_NV_Marshal(&nrh.attributes, buffer, size); + +- if (offset + nrh->size > array_size) { ++ if (offset + nrh.size > array_size) { + TPMLIB_LogTPM2Error("NV_ORDERLY_RAM: nrh->size corrupted: %d\n", +- nrh->size); ++ nrh.size); + break; + } + /* write data size before array */ +- if (nrh->size < sizeof(NV_RAM_HEADER)) { ++ if (nrh.size < sizeof(NV_RAM_HEADER)) { + TPMLIB_LogTPM2Error( + "NV_ORDERLY_RAM: nrh->size < sizeof(NV_RAM_HEADER): %d < %zu\n", +- (int)nrh->size, sizeof(NV_RAM_HEADER)); ++ (int)nrh.size, sizeof(NV_RAM_HEADER)); + break; + } +- datasize = nrh->size - sizeof(NV_RAM_HEADER); ++ datasize = nrh.size - sizeof(NV_RAM_HEADER); + written += UINT16_Marshal(&datasize, buffer, size); + if (datasize > 0) { + /* append the data */ + written += Array_Marshal(array + offset + sizeof(NV_RAM_HEADER), + datasize, buffer, size); + } +- offset += nrh->size; ++ offset += nrh.size; + } + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); +@@ -4053,7 +4059,7 @@ INDEX_ORDERLY_RAM_Unmarshal(void *array, size_t array_size, + { + TPM_RC rc = TPM_RC_SUCCESS; + NV_HEADER hdr; +- NV_RAM_HEADER *nrh; ++ NV_RAM_HEADER nrh, *nrhp; + UINT16 offset = 0; + UINT16 datasize = 0; + UINT32 sourceside_size; +@@ -4071,31 +4077,36 @@ INDEX_ORDERLY_RAM_Unmarshal(void *array, size_t array_size, + } + + while (rc == TPM_RC_SUCCESS) { +- nrh = array + offset; ++ /* nrhp may point to misaligned address (ubsan) ++ * we read 'into' nrh and copy to nrhp at end ++ */ ++ nrhp = array + offset; ++ + /* write the NVRAM header; + nrh->size holds the complete size including data; + nrh->size = 0 indicates the end */ +- if (offset + sizeof(nrh->size) > array_size) { +- offset += sizeof(nrh->size); ++ if (offset + sizeof(nrh.size) > array_size) { ++ offset += sizeof(nrh.size); + goto exit_size; + } + + if (rc == TPM_RC_SUCCESS) { +- rc = UINT32_Unmarshal(&nrh->size, buffer, size); +- if (nrh->size == 0) ++ rc = UINT32_Unmarshal(&nrh.size, buffer, size); ++ if (nrh.size == 0) { ++ memcpy(nrhp, &nrh, sizeof(nrh.size)); + break; ++ } + } + if (offset + sizeof(NV_RAM_HEADER) > array_size) { + offset += sizeof(NV_RAM_HEADER); + goto exit_size; + } + if (rc == TPM_RC_SUCCESS) { +- rc = TPM_HANDLE_Unmarshal(&nrh->handle, buffer, size); ++ rc = TPM_HANDLE_Unmarshal(&nrh.handle, buffer, size); + } + if (rc == TPM_RC_SUCCESS) { +- rc = TPMA_NV_Unmarshal(&nrh->attributes, buffer, size); ++ rc = TPMA_NV_Unmarshal(&nrh.attributes, buffer, size); + } +- + if (rc == TPM_RC_SUCCESS) { + rc = UINT16_Unmarshal(&datasize, buffer, size); + } +@@ -4110,8 +4121,10 @@ INDEX_ORDERLY_RAM_Unmarshal(void *array, size_t array_size, + } + if (rc == TPM_RC_SUCCESS) { + /* fix up size in case it is architecture-dependent */ +- nrh->size = sizeof(*nrh) + datasize; +- offset += nrh->size; ++ nrh.size = sizeof(nrh) + datasize; ++ offset += nrh.size; ++ /* copy header into possibly misaligned address in NVRAM */ ++ *nrhp = nrh; + } + } + +-- +2.21.0.windows.1 + diff --git a/tpm2-Initialize-a-whole-OBJECT-before-using-it.patch b/tpm2-Initialize-a-whole-OBJECT-before-using-it.patch new file mode 100644 index 0000000000000000000000000000000000000000..a012ceacb52969d41e93e217f89f171a237bb52a --- /dev/null +++ b/tpm2-Initialize-a-whole-OBJECT-before-using-it.patch @@ -0,0 +1,34 @@ +From ea62fd9679f8c6fc5e79471b33cfbd8227bfed72 Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Thu, 22 Jul 2021 21:23:58 -0400 +Subject: [PATCH] tpm2: Initialize a whole OBJECT before using it + +Initialize a whole OBJECT before using it. This is necessary since +an OBJECT may also be used as a HASH_OBJECT via the ANY_OBJECT +union and that HASH_OBJECT can leave bad size inidicators in TPM2B +buffer in the OBJECT. To get rid of this problem we reset the whole +OBJECT to 0 before using it. This is as if the memory for the +OBJECT was just initialized. + +Signed-off-by: Stefan Berger +--- + src/tpm2/Object.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/tpm2/Object.c b/src/tpm2/Object.c +index ab50348..967105f 100644 +--- a/src/tpm2/Object.c ++++ b/src/tpm2/Object.c +@@ -284,7 +284,8 @@ FindEmptyObjectSlot( + if(handle) + *handle = i + TRANSIENT_FIRST; + // Initialize the object attributes +- MemorySet(&object->attributes, 0, sizeof(OBJECT_ATTRIBUTES)); ++ // MemorySet(&object->attributes, 0, sizeof(OBJECT_ATTRIBUTES)); ++ MemorySet(object, 0, sizeof(*object)); // libtpms added: Initialize the whole object + return object; + } + } +-- +2.21.0.windows.1 + diff --git a/tpm2-NVMarshal-Handle-index-orderly-RAM-without-0-si.patch b/tpm2-NVMarshal-Handle-index-orderly-RAM-without-0-si.patch new file mode 100644 index 0000000000000000000000000000000000000000..6bf8f4fab7495ea6c74a8ce2f2c2a49f87f9b656 --- /dev/null +++ b/tpm2-NVMarshal-Handle-index-orderly-RAM-without-0-si.patch @@ -0,0 +1,56 @@ +From 1fb6cd9b8df05b5d6e381b31215193d6ada969df Mon Sep 17 00:00:00 2001 +From: Stefan Berger +Date: Fri, 23 Jul 2021 13:29:00 -0400 +Subject: [PATCH] tpm2: NVMarshal: Handle index orderly RAM without 0-sized + terminating node + +The NVRAM entries in s_indexOrderlyRam array do not need to contain a +0-sized terminating node. Instead, the entries may fill up this 512 +byte array so that no NV_RAM_HEADER structure fits anymore. The fact +that no more NV_RAM_HEADER structure fits is also an indicator for the +last entry. We need to account for this in the code marshalling and +unmarshalling the entries so that we stop marshalling the entries +then and similarly stop unmarshalling. + +Signed-off-by: Stefan Berger +--- + src/tpm2/NVMarshal.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/src/tpm2/NVMarshal.c b/src/tpm2/NVMarshal.c +index 2b2d84a..430f481 100644 +--- a/src/tpm2/NVMarshal.c ++++ b/src/tpm2/NVMarshal.c +@@ -4103,6 +4103,12 @@ INDEX_ORDERLY_RAM_Marshal(void *array, size_t array_size, + datasize, buffer, size); + } + offset += nrh.size; ++ if (offset + sizeof(NV_RAM_HEADER) > array_size) { ++ /* nothing will fit anymore and there won't be a 0-sized ++ * terminating node (@1). ++ */ ++ break; ++ } + } + + written += BLOCK_SKIP_WRITE_PUSH(TRUE, buffer, size); +@@ -4144,6 +4150,16 @@ INDEX_ORDERLY_RAM_Unmarshal(void *array, size_t array_size, + */ + nrhp = array + offset; + ++ if (offset + sizeof(NV_RAM_HEADER) > sourceside_size) { ++ /* this case can occur with the previous entry filling up the ++ * space; in this case there will not be a 0-sized terminating ++ * node (see @1 above). We clear the rest of our space. ++ */ ++ if (array_size > offset) ++ memset(nrhp, 0, array_size - offset); ++ break; ++ } ++ + /* write the NVRAM header; + nrh->size holds the complete size including data; + nrh->size = 0 indicates the end */ +-- +2.21.0.windows.1 +